Edit Selection Mode: Fix Ceiling/Floor transforms when pinned (#943)

This commit is contained in:
samwiddowson 2023-08-11 17:25:49 +01:00 committed by GitHub
parent 8f1d645e81
commit 19b8bd1e6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -87,9 +87,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
public readonly SurfaceTextureInfo Floor;
public readonly SurfaceTextureInfo Ceiling;
public readonly Vertex FirstVertex;
public readonly Vector2D PreviousFirstVertexPosition;
public SectorTextureInfo(Sector s)
{
FirstVertex = s.Sidedefs.First<Sidedef>().Line.Start;
PreviousFirstVertexPosition = FirstVertex.Position;
// Get transform properties
Floor.Offset = new Vector2D(UniFields.GetFloat(s.Fields, "xpanningfloor", 0.0), UniFields.GetFloat(s.Fields, "ypanningfloor", 0.0));
Ceiling.Offset = new Vector2D(UniFields.GetFloat(s.Fields, "xpanningceiling", 0.0), UniFields.GetFloat(s.Fields, "ypanningceiling", 0.0));
@ -105,6 +109,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Surface name
Floor.Part = "floor";
Ceiling.Part = "ceiling";
}
private static Size GetTextureSize(long hash)
@ -879,15 +884,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
foreach(KeyValuePair<Sector, SectorTextureInfo> group in selectedsectors)
{
group.Key.Fields.BeforeFieldsChange();
Sector eachSector = group.Key;
SectorTextureInfo eachSectorTexInfo = group.Value;
Vector2D newFirstVertexPosition = new Vector2D( Math.Round(eachSectorTexInfo.FirstVertex.Position.x, General.Map.FormatInterface.VertexDecimals),
Math.Round(eachSectorTexInfo.FirstVertex.Position.y, General.Map.FormatInterface.VertexDecimals) );
eachSector.Fields.BeforeFieldsChange();
// Apply transforms
UpdateTextureTransform(group.Key.Fields, group.Value.Ceiling /*, transformceiloffsets, rotateceiloffsets, scaleceiloffsets */);
UpdateTextureTransform(group.Key.Fields, group.Value.Floor /*, transformflooroffsets, rotateflooroffsets, scaleflooroffsets */);
UpdateTextureTransform(eachSector.Fields, eachSectorTexInfo.Ceiling, newFirstVertexPosition, eachSectorTexInfo.PreviousFirstVertexPosition);
UpdateTextureTransform(eachSector.Fields, eachSectorTexInfo.Floor, newFirstVertexPosition, eachSectorTexInfo.PreviousFirstVertexPosition);
// Update cache
group.Key.UpdateNeeded = true;
group.Key.UpdateCache();
eachSector.UpdateNeeded = true;
eachSector.UpdateCache();
}
// Map was changed
@ -895,18 +905,40 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
//mxd. This updates texture transforms in given UniFields
private void UpdateTextureTransform(UniFields fields, SurfaceTextureInfo si /*, bool transformoffsets, bool rotateoffsets, bool scaleoffsets */)
private void UpdateTextureTransform(UniFields fields, SurfaceTextureInfo si, Vector2D newReferencePosition, Vector2D previousReferencePosition)
{
if ((si.Part == "floor" && pinfloortextures) || (si.Part == "ceiling" && pinceilingtextures))
{
double texrotation = Angle2D.PI2 - rotation;
if (si.Scale.x != 0 && si.Scale.y != 0)
{
double selectionRotationRad = Angle2D.PI2 - rotation;
double newSurfaceRotationRad = selectionRotationRad + si.Rotation;
double trotation = texrotation + si.Rotation;
Vector2D o = ((referencepoint - selectionbasecenter).GetRotated(-trotation) + selectionbasecenter + this.offset - this.baseoffset).GetRotated(trotation);
Vector2D textureSize = new Vector2D ((double)si.TextureSize.Width / si.Scale.x,
(double)si.TextureSize.Height / -si.Scale.y);
fields["xpanning" + si.Part] = new UniValue(UniversalType.Float, Math.Round(-o.x + si.Offset.x, General.Map.FormatInterface.VertexDecimals));
fields["ypanning" + si.Part] = new UniValue(UniversalType.Float, Math.Round(o.y + si.Offset.y, General.Map.FormatInterface.VertexDecimals));
fields["rotation" + si.Part] = new UniValue(UniversalType.Float, General.ClampAngle(Math.Round(Angle2D.RadToDeg(trotation), General.Map.FormatInterface.VertexDecimals)));
double previousSurfaceRotationRad = Angle2D.PI2 - si.Rotation;
//Set the new surface texture rotation
double newSurfaceRotationDegrees = General.ClampAngle(Math.Round(Angle2D.RadToDeg(newSurfaceRotationRad), General.Map.FormatInterface.VertexDecimals));
fields["rotation" + si.Part] = new UniValue(UniversalType.Float, newSurfaceRotationDegrees);
//Find the offset required to place the texture origin point at the reference vector
Vector2D globalOffsetForNewReferencePoint = ConvertToOffsetCoordinates(newReferencePosition);
Vector2D surfaceOffsetForNewReferencePoint = GetClampedOffsetVector(globalOffsetForNewReferencePoint.GetRotated(-newSurfaceRotationRad), textureSize);
//find an "origin point offset" using the previous texture offset, relative to our reference vertex
Vector2D rotatedPreviousReferencePosition = GetClampedOffsetVector(previousReferencePosition.GetRotated(-previousSurfaceRotationRad), textureSize);
Vector2D previousSurfaceOffset = ConvertToOffsetCoordinates(GetClampedOffsetVector(si.Offset, textureSize));
Vector2D localSurfaceAdjustment = rotatedPreviousReferencePosition - previousSurfaceOffset;
//Adjust our offset by applying using the "origin point offset" to the offset for our reference vertex
Vector2D adjustedSurfaceOffset = GetClampedOffsetVector(surfaceOffsetForNewReferencePoint - ConvertToOffsetCoordinates(localSurfaceAdjustment), textureSize);
//Set the new texture offset
fields["xpanning" + si.Part] = new UniValue(UniversalType.Float, adjustedSurfaceOffset.x);
fields["ypanning" + si.Part] = new UniValue(UniversalType.Float, adjustedSurfaceOffset.y);
}
}
else
{
@ -919,6 +951,25 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
private Vector2D ConvertToOffsetCoordinates(Vector2D v)
{
return new Vector2D(-v.x, v.y);
}
private Vector2D GetClampedOffsetVector(Vector2D v, Vector2D textureSize)
{
Vector2D roundedV = new Vector2D(
Math.Round(v.x, General.Map.FormatInterface.VertexDecimals),
Math.Round(v.y, General.Map.FormatInterface.VertexDecimals));
Vector2D roundedTextureSize = new Vector2D(
Math.Round(textureSize.x, General.Map.FormatInterface.VertexDecimals),
Math.Round(textureSize.y, General.Map.FormatInterface.VertexDecimals));
return new Vector2D(roundedV.x % roundedTextureSize.x,
roundedV.y % roundedTextureSize.y);
}
//mxd. This restores texture transforms for all sectors
private void RestoreTextureTransform()
{
@ -1300,8 +1351,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
if (General.Map.UDMF)
{
foreach (Sector s in General.Map.Map.GetSectorsFromLinedefs(selectedlines))
{
if (!s.Fields.ContainsKey(MapSet.VIRTUAL_SECTOR_FIELD)) // Ignore sectors that have the VIRTUAL_SECTOR_FIELD UDMF field created when cloning the MapSet when copying
{
selectedsectors.Add(s, new SectorTextureInfo(s));
}
}
}
// Array to keep original coordinates