Skip to content

Commit cd452ee

Browse files
committed
Fixed the undo system
1 parent 93a5fa9 commit cd452ee

File tree

2 files changed

+112
-77
lines changed

2 files changed

+112
-77
lines changed

Source/Contrib/TrackViewer/SceneViewer.cs

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public class SceneViewer
5858
OrbitingCamera Camera;
5959
Stack<UndoDataSet> UndoStack = new Stack<UndoDataSet>();
6060
Stack<UndoDataSet> RedoStack = new Stack<UndoDataSet>();
61+
EditorState EditorState;
6162

6263
/// <summary>The command-line arguments</summary>
6364
private string[] CommandLineArgs;
@@ -126,19 +127,27 @@ public void Update(GameTime gameTime)
126127
{
127128
SelectedObject = selectedObject;
128129
SelectedObjectChanged();
130+
EditorState = EditorState.ObjectSelected;
129131
}
130132
}
131133
if (UserInput.IsPressed(UserCommand.EditorUnselectAll))
132134
{
133-
SelectedObject = null;
134-
SelectedObjectChanged();
135+
if (EditorState == EditorState.ObjectSelected || EditorState == EditorState.Default)
136+
{
137+
SetDefaultMode();
138+
}
135139
}
136140
if (UserInput.IsPressed(UserCommand.EditorUndo))
137141
{
138-
UndoCommand();
142+
if (EditorState == EditorState.ObjectSelected || EditorState == EditorState.Default)
143+
{
144+
SetDefaultMode();
145+
UndoCommand();
146+
}
139147
}
140148
if (UserInput.IsPressed(UserCommand.EditorRedo))
141149
{
150+
SetDefaultMode();
142151
RedoCommand();
143152
}
144153

@@ -198,12 +207,12 @@ public async Task SetCameraLocation()
198207
mouseLocation.Location.Y = elevatedLocation + 15;
199208
Camera.SetLocation(mouseLocation);
200209

201-
var lastView = UndoStack.Count > 0 ? UndoStack.Last(s => s.UndoEvent == UndoEvent.ViewChanged) :
210+
var lastView = UndoStack.Count > 0 ? UndoStack.First(s => s.UndoEvent == UndoEvent.ViewChanged) :
202211
new UndoDataSet()
203212
{
204-
OldCameraLocation = Camera.CameraWorldLocation,
205-
OldCameraRotationXRadians = Camera.GetRotationX(),
206-
OldCameraRotationYRadians = Camera.GetRotationY(),
213+
NewCameraLocation = Camera.CameraWorldLocation,
214+
NewCameraRotationXRadians = Camera.GetRotationX(),
215+
NewCameraRotationYRadians = Camera.GetRotationY(),
207216
};
208217

209218
UndoStack.Push(new UndoDataSet()
@@ -222,12 +231,16 @@ void UpdateViewUndoState()
222231
{
223232
if (UndoStack.Count == 0)
224233
return;
234+
235+
var lastView = UndoStack.First(s => s.UndoEvent == UndoEvent.ViewChanged);
236+
237+
if (Camera.GetRotationX() == lastView.NewCameraRotationXRadians && Camera.GetRotationY() == lastView.NewCameraRotationYRadians && Camera.CameraWorldLocation == lastView.NewCameraLocation)
238+
return;
225239

226-
var lastView = UndoStack.Last(s => s.UndoEvent == UndoEvent.ViewChanged);
227-
if (lastView == UndoStack.Last())
240+
if (UndoStack.First().UndoEvent == UndoEvent.ViewChanged) // then updatable
228241
{
229-
if (lastView.NewCameraLocation == lastView.OldCameraLocation && (Camera.GetRotationX() != lastView.NewCameraRotationXRadians || Camera.GetRotationY() != lastView.NewCameraRotationYRadians)
230-
|| lastView.NewCameraLocation != lastView.OldCameraLocation && Camera.CameraWorldLocation == lastView.NewCameraLocation)
242+
if ((Camera.GetRotationX() == lastView.NewCameraRotationXRadians && Camera.GetRotationY() == lastView.NewCameraRotationYRadians) ^
243+
(lastView.NewCameraRotationXRadians != lastView.OldCameraRotationXRadians || lastView.NewCameraRotationYRadians != lastView.OldCameraRotationYRadians))
231244
{
232245
// Group rotations and pan-zooms by just updating the last action
233246
lastView.NewCameraRotationXRadians = Camera.GetRotationX();
@@ -237,7 +250,7 @@ void UpdateViewUndoState()
237250
return;
238251
}
239252
}
240-
if (Camera.GetRotationX() != lastView.NewCameraRotationXRadians || Camera.GetRotationY() != lastView.NewCameraRotationYRadians || Camera.CameraWorldLocation == lastView.NewCameraLocation)
253+
if (Camera.GetRotationX() != lastView.NewCameraRotationXRadians || Camera.GetRotationY() != lastView.NewCameraRotationYRadians || Camera.CameraWorldLocation != lastView.NewCameraLocation)
241254
{
242255
UndoStack.Push(new UndoDataSet()
243256
{
@@ -253,19 +266,21 @@ void UpdateViewUndoState()
253266
}
254267
}
255268

269+
void SetDefaultMode()
270+
{
271+
SelectedObject = null;
272+
SelectedObjectChanged();
273+
EditorState = EditorState.Default;
274+
}
275+
256276
void UndoCommand()
257277
{
258-
UndoDataSet undoDataSet;
259278
if (UndoStack.Count > 1)
260279
{
261-
undoDataSet = UndoStack.Pop();
280+
var undoDataSet = UndoStack.Pop();
262281
RedoStack.Push(undoDataSet);
282+
UndoRedo(undoDataSet, true);
263283
}
264-
else
265-
{
266-
undoDataSet = UndoStack.Peek();
267-
}
268-
UndoRedo(undoDataSet, true);
269284
}
270285

271286
void RedoCommand()
@@ -283,8 +298,9 @@ void UndoRedo(UndoDataSet undoDataSet, bool undo)
283298
if (undoDataSet.UndoEvent == UndoEvent.ViewChanged)
284299
{
285300
Camera.SetLocation(undo ? undoDataSet.OldCameraLocation : undoDataSet.NewCameraLocation);
286-
Camera.RotationXTargetRadians = undo ? undoDataSet.OldCameraRotationXRadians : undoDataSet.NewCameraRotationXRadians;
287-
Camera.RotationYTargetRadians = undo ? undoDataSet.OldCameraRotationYRadians : undoDataSet.NewCameraRotationYRadians;
301+
Camera.SetRotation(
302+
undo ? undoDataSet.OldCameraRotationXRadians : undoDataSet.NewCameraRotationXRadians,
303+
undo ? undoDataSet.OldCameraRotationYRadians : undoDataSet.NewCameraRotationYRadians);
288304
}
289305
}
290306

@@ -370,6 +386,15 @@ public enum UndoEvent
370386
WorldObjectChanged,
371387
}
372388

389+
public enum EditorState
390+
{
391+
Default = 0,
392+
ObjectSelected,
393+
ObjectMovingX,
394+
ObjectMovingY,
395+
ObjectMovingZ,
396+
}
397+
373398
public class SceneViewerHwndHost : HwndHost
374399
{
375400
readonly IntPtr HwndChildHandle;

Source/RunActivity/Viewer3D/EditorPrimitives.cs

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
using ORTS.Common;
2323
using System;
2424
using System.Collections.Concurrent;
25-
using System.Collections.Generic;
26-
using System.Collections.ObjectModel;
2725
using System.Linq;
2826

2927
namespace Orts.Viewer3D
@@ -50,10 +48,10 @@ public class EditorShapes : StaticShape, IDisposable
5048

5149
public EditorShapes(Viewer viewer) : base(viewer, "", null, ShapeFlags.None, null, -1)
5250
{
53-
MouseCrosshair = new MouseCrosshair(Viewer, Color.GreenYellow);
51+
MouseCrosshair = new MouseCrosshair(Viewer, Color.GreenYellow, Color.Red, Color.Cyan);
5452
HandleX = new HandleX(Viewer, Color.Red);
5553
HandleY = new HandleY(Viewer, Color.Blue);
56-
HandleZ = new HandleZ(Viewer, Color.Green);
54+
HandleZ = new HandleZ(Viewer, Color.LightGreen);
5755
}
5856

5957
public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
@@ -189,26 +187,54 @@ public override void Draw(GraphicsDevice graphicsDevice)
189187
}
190188

191189
[CallOnThread("Loader")]
192-
public class BoundingBoxPrimitive : EditorPrimitive
190+
public class BoxPrimitive : EditorPrimitive
193191
{
194-
static IndexBuffer BoundingBoxIndexBuffer;
195-
public readonly Matrix ComplexTransform;
192+
static IndexBuffer BoxIndexBuffer;
196193

197-
public BoundingBoxPrimitive(Viewer viewer, BoundingBox boundingBox, Color color)
194+
public BoxPrimitive(Viewer viewer, float size, Color color)
195+
: this(viewer, new Vector3(-size / 2), new Vector3(size / 2), color)
196+
{
197+
Material = viewer.MaterialManager.Load("EditorPrimitive");
198+
if (BoxIndexBuffer == null)
199+
{
200+
var indexData = new short[] { 2, 3, 6, 7, 5, 3, 1, 2, 0, 6, 4, 5, 0, 1 };
201+
BoxIndexBuffer = new IndexBuffer(viewer.GraphicsDevice, typeof(short), indexData.Length, BufferUsage.WriteOnly);
202+
BoxIndexBuffer.SetData(indexData);
203+
}
204+
IndexBuffer = BoxIndexBuffer;
205+
PrimitiveCount = IndexBuffer.IndexCount - 2;
206+
PrimitiveType = PrimitiveType.TriangleStrip;
207+
}
208+
209+
protected BoxPrimitive(Viewer viewer, Vector3 min, Vector3 max, Color color)
198210
{
199211
var vertexData = new VertexPositionColor[]
200212
{
201-
new VertexPositionColor(boundingBox.Min, color),
202-
new VertexPositionColor(new Vector3(boundingBox.Min.X, boundingBox.Min.Y, boundingBox.Max.Z), color),
203-
new VertexPositionColor(new Vector3(boundingBox.Min.X, boundingBox.Max.Y, boundingBox.Min.Z), color),
204-
new VertexPositionColor(new Vector3(boundingBox.Min.X, boundingBox.Max.Y, boundingBox.Max.Z), color),
205-
new VertexPositionColor(new Vector3(boundingBox.Max.X, boundingBox.Min.Y, boundingBox.Min.Z), color),
206-
new VertexPositionColor(new Vector3(boundingBox.Max.X, boundingBox.Min.Y, boundingBox.Max.Z), color),
207-
new VertexPositionColor(new Vector3(boundingBox.Max.X, boundingBox.Max.Y, boundingBox.Min.Z), color),
208-
new VertexPositionColor(boundingBox.Max, color)
213+
new VertexPositionColor(min, color),
214+
new VertexPositionColor(new Vector3(min.X, min.Y, max.Z), color),
215+
new VertexPositionColor(new Vector3(min.X, max.Y, min.Z), color),
216+
new VertexPositionColor(new Vector3(min.X, max.Y, max.Z), color),
217+
new VertexPositionColor(new Vector3(max.X, min.Y, min.Z), color),
218+
new VertexPositionColor(new Vector3(max.X, min.Y, max.Z), color),
219+
new VertexPositionColor(new Vector3(max.X, max.Y, min.Z), color),
220+
new VertexPositionColor(max, color)
209221
};
210222
VertexBuffer = new VertexBuffer(viewer.GraphicsDevice, typeof(VertexPositionColor), vertexData.Length, BufferUsage.WriteOnly);
211223
VertexBuffer.SetData(vertexData);
224+
}
225+
}
226+
227+
[CallOnThread("Loader")]
228+
public class BoundingBoxPrimitive : BoxPrimitive
229+
{
230+
static IndexBuffer BoundingBoxIndexBuffer;
231+
public readonly Matrix ComplexTransform;
232+
233+
public BoundingBoxPrimitive(Viewer viewer, BoundingBox boundingBox, Color color)
234+
: base(viewer, boundingBox.Min, boundingBox.Max, color)
235+
{
236+
Material = viewer.MaterialManager.Load("EditorPrimitive");
237+
ComplexTransform = boundingBox.ComplexTransform;
212238
if (BoundingBoxIndexBuffer == null)
213239
{
214240
var indexData = new short[] { 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7 };
@@ -218,23 +244,21 @@ public BoundingBoxPrimitive(Viewer viewer, BoundingBox boundingBox, Color color)
218244
IndexBuffer = BoundingBoxIndexBuffer;
219245
PrimitiveCount = IndexBuffer.IndexCount / 2;
220246
PrimitiveType = PrimitiveType.LineList;
221-
Material = viewer.MaterialManager.Load("EditorPrimitive");
222-
ComplexTransform = boundingBox.ComplexTransform;
223247
}
224248
}
225249

226250
[CallOnThread("Loader")]
227251
public class MouseCrosshair : EditorPrimitive
228252
{
229-
public MouseCrosshair(Viewer viewer, Color color)
253+
public MouseCrosshair(Viewer viewer, Color color, Color northColor, Color southColor)
230254
{
231255
var vertexData = new VertexPositionColor[]
232256
{
233257
new VertexPositionColor(new Vector3(-5, 0, 0), color),
234258
new VertexPositionColor(new Vector3(5, 0, 0), color),
235-
new VertexPositionColor(new Vector3(0, 0, -5), Color.Red),
236-
new VertexPositionColor(new Vector3(0, 0, 5), Color.Cyan),
237-
new VertexPositionColor(new Vector3(0, 0, 0), color),
259+
new VertexPositionColor(new Vector3(0, 0, -5), northColor),
260+
new VertexPositionColor(new Vector3(0, 0, 5), southColor),
261+
new VertexPositionColor(new Vector3(0, -5, 0), color),
238262
new VertexPositionColor(new Vector3(0, 20, 0), color)
239263
};
240264
VertexBuffer = new VertexBuffer(viewer.GraphicsDevice, typeof(VertexPositionColor), vertexData.Length, BufferUsage.WriteOnly);
@@ -253,54 +277,40 @@ public HandleX(Viewer viewer, Color color)
253277
var vertexData = GetVertexData(color);
254278
VertexBuffer = new VertexBuffer(viewer.GraphicsDevice, typeof(VertexPositionColor), vertexData.Length, BufferUsage.WriteOnly);
255279
VertexBuffer.SetData(vertexData);
256-
PrimitiveCount = VertexBuffer.VertexCount / 2;
257-
PrimitiveType = PrimitiveType.TriangleList;
280+
PrimitiveCount = VertexBuffer.VertexCount - 2;
281+
PrimitiveType = PrimitiveType.TriangleStrip;
258282
Material = viewer.MaterialManager.Load("EditorPrimitive");
259283
}
260284

261285
protected virtual VertexPositionColor[] GetVertexData(Color color) => GetVertexData(0, 1, 2, color);
262286
protected VertexPositionColor[] GetVertexData(int x, int y, int z, Color color)
263287
{
264-
var l = 5f;
265-
var d = 0.1f;
266-
var a = l / 5;
267-
var b = a / 4;
288+
var l = 5f; // total length, meter
289+
var d = 0.1f; // shaft half thickness
290+
var a = l / 5; // arrow head length
291+
var b = a / 4; // arrow head half thickness
268292
var c = l - a;
269293
var data = new float[][]
270294
{
271-
new[] { 0, +d, 0 },
272-
new[] { c, +d, 0 },
273-
new[] { 0, -d, 0 },
295+
// Arrow shaft
296+
new[] { 0, d, 0 },
297+
new[] { c, d, 0 },
298+
new[] { 0, 0, d },
299+
new[] { c, 0, d },
274300
new[] { 0, -d, 0 },
275-
new[] { c, +d, 0 },
276301
new[] { c, -d, 0 },
277-
278-
new[] { 0, 0, +d },
279-
new[] { c, 0, +d },
280-
new[] { 0, 0, -d },
281302
new[] { 0, 0, -d },
282-
new[] { c, 0, +d },
283303
new[] { c, 0, -d },
284304

285-
new[] { l, 0, 0 },
286-
new[] { l - a, +b, +b },
287-
new[] { l - a, -b, +b },
288-
new[] { l, 0, 0 },
289-
new[] { l - a, -b, +b },
290-
new[] { l - a, -b, -b },
291-
new[] { l, 0, 0 },
292-
new[] { l - a, -b, -b },
293-
new[] { l - a, +b, -b },
294-
new[] { l, 0, 0 },
295-
new[] { l - a, +b, -b },
296-
new[] { l - a, +b, +b },
297-
298-
new[] { l - a, +b, +b },
299-
new[] { l - a, +b, -b },
300-
new[] { l - a, -b, -b },
301-
new[] { l - a, -b, -b },
302-
new[] { l - a, +b, -b },
303-
new[] { l - a, -b, +b },
305+
// Arrow head
306+
new[] { l, 0, 0 },
307+
new[] { c, +b, +b },
308+
new[] { c, -b, +b },
309+
new[] { c, -b, -b },
310+
new[] { l, 0, 0 },
311+
new[] { c, +b, -b },
312+
new[] { c, +b, +b },
313+
new[] { c, -b, -b },
304314
};
305315
var vertexData = new VertexPositionColor[data.Length];
306316
for (var i = 0; i < data.Length; i++)

0 commit comments

Comments
 (0)