diff --git a/Fushigi/ui/SceneObjects/bgunit/BGUnitRailSceneObj.cs b/Fushigi/ui/SceneObjects/bgunit/BGUnitRailSceneObj.cs
index e63c8efc..18df4ecb 100644
--- a/Fushigi/ui/SceneObjects/bgunit/BGUnitRailSceneObj.cs
+++ b/Fushigi/ui/SceneObjects/bgunit/BGUnitRailSceneObj.cs
@@ -214,18 +214,11 @@ public void OnSelecting(CourseAreaEditContext ctx, LevelViewport viewport)
Vector3 posVec = viewport.ScreenToWorld(ImGui.GetMousePos());
Vector3 diff = posVec - mouseDownPos;
+
if (diff.X != 0 && diff.Y != 0 && !transformStart)
{
transformStart = true;
- //Store each selected point for undoing
mTransformUndos.Clear();
- foreach (var point in GetSelected(ctx))
- {
- if (!ChildPoints.TryGetValue(point, out RailPoint? childPoint))
- continue;
-
- mTransformUndos.Add(new TransformUndo(childPoint.Transform));
- }
}
bool anyTransformed = false;
@@ -240,7 +233,19 @@ public void OnSelecting(CourseAreaEditContext ctx, LevelViewport viewport)
diff.X = MathF.Round(diff.X, MidpointRounding.AwayFromZero);
diff.Y = MathF.Round(diff.Y, MidpointRounding.AwayFromZero);
posVec.Z = rail.Points[i].Position.Z;
- rail.Points[i].Position = childPoint.PreviousPosition + diff;
+
+ var newPos = childPoint.PreviousPosition + diff;
+
+ if (!ImGui.GetIO().KeyCtrl || IsValidPosition(newPos, i))
+ {
+ mTransformUndos.Add(new TransformUndo(
+ childPoint.Transform,
+ childPoint.PreviousPosition,
+ newPos));
+
+ rail.Points[i].Position = newPos;
+ }
+
anyTransformed = true;
}
}
@@ -349,6 +354,35 @@ private bool IsValidAngle(Vector2 point1, Vector2 point2)
return validAngles.Contains(MathF.Round(angle));
}
+ ///
+ /// Check if the proposed position is valid within the rail
+ ///
+ /// new proposed position
+ /// index of the point to set to the new position
+ /// true if the point is valid there, false otherwise
+ private bool IsValidPosition(Vector3 pos, int index)
+ {
+ Vector2 newPos = new(pos.X, pos.Y);
+
+ // Check if the point has valid angles with the points coming before and after it
+ int[] offsets = [-1, 1];
+ foreach (var offset in offsets)
+ {
+ var neighborIndex = (index + offset) % rail.Points.Count;
+
+ if (neighborIndex < 0)
+ neighborIndex += rail.Points.Count;
+
+ Vector2 neighborPos = new(rail.Points[neighborIndex].Position.X,
+ rail.Points[neighborIndex].Position.Y);
+
+ if (!IsValidAngle(newPos, neighborPos))
+ return false;
+ }
+
+ return true;
+ }
+
void IViewportSelectable.OnSelect(CourseAreaEditContext editContext)
{
IViewportSelectable.DefaultSelect(editContext, rail);
diff --git a/Fushigi/ui/undo/TransformUndo.cs b/Fushigi/ui/undo/TransformUndo.cs
index aaf87313..29b800f7 100644
--- a/Fushigi/ui/undo/TransformUndo.cs
+++ b/Fushigi/ui/undo/TransformUndo.cs
@@ -1,6 +1,7 @@
using Fushigi.util;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
@@ -13,32 +14,25 @@ public class TransformUndo : IRevertable
{
public string Name { get; set; }
- public Transform Transform;
+ Transform Transform;
+ Vector3 OldPos;
+ Vector3 NewPos;
- public Vector3 PreviousPosition;
- public Vector3 PreviousRotation;
- public Vector3 PreviousScale;
-
- public TransformUndo(Transform transform, string name = $"{IconUtil.ICON_ARROWS_ALT} Transform")
+ public TransformUndo(Transform transform, Vector3 oldPos, Vector3 newPos, string name = $"{IconUtil.ICON_ARROWS_ALT} Transform")
{
//Undo display name
Name = name;
- //The transform to update
Transform = transform;
- //The state to revert to
- PreviousPosition = transform.Position;
- PreviousRotation = transform.RotationEuler;
- PreviousScale = transform.Scale;
+ OldPos = oldPos;
+ NewPos = newPos;
}
public IRevertable Revert()
{
//Revert transform instance
- var redo = new TransformUndo(Transform);
+ var redo = new TransformUndo(Transform, NewPos, OldPos);
- Transform.Position = this.PreviousPosition;
- Transform.RotationEuler = this.PreviousRotation;
- Transform.Scale = this.PreviousScale;
+ Transform.Position = OldPos;
Transform.OnUpdate();
//Create revert stack