3636using Orts . Viewer3D ;
3737using Orts . Viewer3D . Processes ;
3838using ORTS . Common . Input ;
39+ using System . Windows . Media . Imaging ;
3940
4041namespace ORTS . TrackViewer
4142{
@@ -58,7 +59,9 @@ public class SceneViewer
5859 StaticShape MovedObject ;
5960 WorldPosition MovedObjectOriginalPosition ;
6061 WorldPosition HandlePosition ;
61- int MoveAxis ; // 0 - x, 1 - y, 2 - z
62+ WorldPosition HandleOriginalPosition ;
63+ float DeltaX , DeltaY , DeltaZ ;
64+ UndoDataSet DeltaContext ;
6265 WorldLocation CursorLocation ;
6366
6467 public SceneViewer ( TrackViewer trackViewer , string [ ] args )
@@ -120,10 +123,10 @@ public void Update(GameTime gameTime)
120123
121124 Viewer . EditorShapes . MouseCrosshairEnabled = true ;
122125
126+ UpdateViewUndoState ( ) ;
127+
123128 if ( EditorState == EditorState . Default || EditorState == EditorState . ObjectSelected )
124129 {
125- UpdateViewUndoState ( ) ;
126-
127130 if ( UserInput . IsMouseLeftButtonPressed && UserInput . ModifiersMaskShiftCtrlAlt ( false , false , false ) )
128131 {
129132 if ( Camera . PickByMouse ( out var selectedObject ) )
@@ -156,7 +159,7 @@ public void Update(GameTime gameTime)
156159 }
157160 if ( UserInput . IsPressed ( UserCommand . EditorMoveHandle ) )
158161 {
159- EditorState = EditorState . HandleMoving ;
162+ StartHandleMove ( ) ;
160163 }
161164 }
162165 if ( EditorState == EditorState . HandleMoving )
@@ -170,7 +173,7 @@ public void Update(GameTime gameTime)
170173 {
171174 CancelHandleMove ( ) ;
172175 }
173- if ( UserInput . IsMouseLeftButtonPressed && UserInput . ModifiersMaskShiftCtrlAlt ( false , false , false ) )
176+ if ( UserInput . IsMouseLeftButtonPressed )
174177 {
175178 ApplyHandleMove ( ) ;
176179 }
@@ -186,29 +189,39 @@ public void Update(GameTime gameTime)
186189 {
187190 CancelObjectMove ( ) ;
188191 }
189- if ( UserInput . IsMouseLeftButtonPressed && UserInput . ModifiersMaskShiftCtrlAlt ( false , false , false ) )
192+ if ( UserInput . IsMouseLeftButtonPressed )
190193 {
191194 ApplyObjectMove ( ) ;
192195 }
193196 }
194197
195198 CursorLocation = Camera ? . CameraWorldLocation ?? new WorldLocation ( ) ;
196199 CursorLocation . Location = Viewer ? . TerrainPoint ?? new Vector3 ( ) ;
200+ CursorLocation . Location . Z *= - 1 ;
197201 CursorLocation . Normalize ( ) ;
198202 FillCursorPositionStatus ( CursorLocation ) ;
199203 SetCameraLocationStatus ( Camera ? . CameraWorldLocation ?? new WorldLocation ( ) ) ;
200204
201205 // A second pass after user input handled, do the effective work
202206 if ( EditorState == EditorState . ObjectMoving )
203207 {
204- var distance = WorldLocation . GetDistance ( SelectedObject . Location . WorldLocation , CursorLocation ) ;
205- var tileLocation = MovedObject . Location . XNAMatrix . Translation ;
206- tileLocation . X += distance . X ;
207- MovedObject . Location . XNAMatrix . Translation = tileLocation ;
208-
208+ MovedObject . Location . XNAMatrix = GetMovingMatrix ( MovedObjectOriginalPosition , HandleOriginalPosition , HandlePosition ) ;
209209 Viewer . EditorShapes . MovedObject = MovedObject ;
210210 Viewer . EditorShapes . MovedObjectLocation = MovedObject . Location ;
211211 }
212+ else
213+ {
214+ Viewer . EditorShapes . MovedObject = null ;
215+ Viewer . EditorShapes . MovedObjectLocation = null ;
216+ }
217+
218+ if ( EditorState == EditorState . HandleMoving )
219+ {
220+ HandlePosition . XNAMatrix = GetMovingMatrix ( HandleOriginalPosition ) ;
221+ Viewer . EditorShapes . HandleLocation = HandlePosition ;
222+ }
223+
224+ FillDeltaStatus ( ) ;
212225 }
213226
214227 /// <summary>
@@ -226,22 +239,35 @@ public void SetKeyboardInput(bool enable)
226239 /// Put the mouse location in the statusbar
227240 /// </summary>
228241 /// <param name="mouseLocation"></param>
229- private void SetCameraLocationStatus ( WorldLocation location )
242+ void SetCameraLocationStatus ( WorldLocation location )
230243 {
231244 SceneWindow . tileXZ . Text = string . Format ( CultureInfo . InvariantCulture , "{0,-7} {1,-7}" , location . TileX , location . TileZ ) ;
232245 SceneWindow . LocationX . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . X ) ;
233246 SceneWindow . LocationY . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . Y ) ;
234247 SceneWindow . LocationZ . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . Z ) ;
235248 }
236249
237- private void FillCursorPositionStatus ( WorldLocation location )
250+ void FillCursorPositionStatus ( WorldLocation location )
238251 {
239252 SceneWindow . tileXZcursor . Text = string . Format ( CultureInfo . InvariantCulture , "{0,-7} {1,-7}" , location . TileX , location . TileZ ) ;
240253 SceneWindow . LocationXcursor . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . X ) ;
241254 SceneWindow . LocationYcursor . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . Y ) ;
242255 SceneWindow . LocationZcursor . Text = string . Format ( CultureInfo . InvariantCulture , "{0,3:F3} " , location . Location . Z ) ;
243256 }
244257
258+ void FillDeltaStatus ( )
259+ {
260+ //if (DeltaContext == null)
261+ {
262+ if ( EditorState == EditorState . ObjectMoving )
263+ {
264+ SceneWindow . DeltaX . Text = DeltaX . ToString ( "N3" , CultureInfo . InvariantCulture ) ;
265+ SceneWindow . DeltaY . Text = DeltaY . ToString ( "N3" , CultureInfo . InvariantCulture ) ;
266+ SceneWindow . DeltaZ . Text = DeltaZ . ToString ( "N3" , CultureInfo . InvariantCulture ) ;
267+ }
268+ }
269+ }
270+
245271 public async Task SetCameraLocation ( WorldLocation worldLocation )
246272 {
247273 var elevatedLocation = 0f ;
@@ -260,7 +286,7 @@ public async Task SetCameraLocation(WorldLocation worldLocation)
260286 worldLocation . TileX , worldLocation . TileZ , worldLocation . Location . X , worldLocation . Location . Z , true ) ?? 0 ;
261287 break ;
262288 }
263- worldLocation . Location . Y = elevatedLocation + 15 ;
289+ worldLocation . Location . Y = elevatedLocation + 50 ;
264290 Camera . SetLocation ( worldLocation ) ;
265291
266292 var lastView = UndoStack . Count > 0 ?
@@ -284,6 +310,80 @@ public async Task SetCameraLocation(WorldLocation worldLocation)
284310 } ) ;
285311 }
286312
313+ Matrix GetMovingMatrix ( in WorldPosition originalPosition , in WorldPosition handleOriginalPosition = null , WorldPosition handlePosition = null )
314+ {
315+ var handle = handleOriginalPosition ?? originalPosition ;
316+ var xnaMatrix = originalPosition . XNAMatrix ;
317+
318+ if ( UserInput . IsDown ( UserCommand . EditorLockRotation ) )
319+ {
320+ var distance = WorldLocation . GetDistance ( handle . WorldLocation , CursorLocation ) ;
321+ distance . Z *= - 1 ;
322+
323+ var angle = MathHelper . WrapAngle ( ( float ) ( Math . Atan2 ( originalPosition . XNAMatrix . M13 , originalPosition . XNAMatrix . M33 ) - Math . Atan2 ( distance . Z , distance . X ) ) ) ;
324+ var rotation = Matrix . CreateFromYawPitchRoll ( angle , 0 , 0 ) ;
325+ var translation = handle . XNAMatrix . Translation ;
326+ xnaMatrix . Translation -= translation ;
327+ xnaMatrix *= rotation ;
328+ xnaMatrix . Translation += translation ;
329+
330+ if ( handlePosition != null && handleOriginalPosition != null )
331+ {
332+ angle = MathHelper . WrapAngle ( ( float ) ( Math . Atan2 ( handleOriginalPosition . XNAMatrix . M13 , handleOriginalPosition . XNAMatrix . M33 ) - Math . Atan2 ( distance . Z , distance . X ) ) ) ;
333+ rotation = Matrix . CreateFromYawPitchRoll ( angle , 0 , 0 ) ;
334+ var handleMatrix = handleOriginalPosition . XNAMatrix ;
335+ handleMatrix . Translation -= translation ;
336+ handleMatrix *= rotation ;
337+ handleMatrix . Translation += translation ;
338+ handlePosition . XNAMatrix = handleMatrix ;
339+ }
340+ }
341+ else
342+ {
343+ var distance = WorldLocation . GetDistance ( originalPosition . WorldLocation , CursorLocation ) ;
344+ distance . Z *= - 1 ;
345+
346+ var axisX = Vector3 . Normalize ( handle . XNAMatrix . Right ) ;
347+ var axisY = Vector3 . Normalize ( handle . XNAMatrix . Up ) ;
348+ var axisZ = Vector3 . Normalize ( handle . XNAMatrix . Backward ) ;
349+
350+ var tileLocation = xnaMatrix . Translation ;
351+
352+ if ( UserInput . IsDown ( UserCommand . EditorLockOrthogonal ) )
353+ {
354+ var distanceX = Vector3 . Dot ( axisX , distance ) ;
355+ var distanceZ = Vector3 . Dot ( axisZ , distance ) ;
356+
357+ tileLocation += Math . Abs ( distanceX ) > Math . Abs ( distanceZ ) ? distanceX * axisX : distanceZ * axisZ ;
358+ }
359+ else
360+ {
361+ tileLocation . X += distance . X ;
362+ tileLocation . Z += distance . Z ;
363+ }
364+
365+ if ( ! UserInput . IsDown ( UserCommand . EditorLockElevation ) )
366+ {
367+ tileLocation . Y = Viewer . Tiles . GetElevation ( handle . TileX , handle . TileZ , tileLocation . X , - tileLocation . Z ) ;
368+ }
369+ xnaMatrix . Translation = tileLocation ;
370+
371+ distance = xnaMatrix . Translation - originalPosition . XNAMatrix . Translation ;
372+
373+ if ( handlePosition != null && handleOriginalPosition != null )
374+ {
375+ var handleMatrix = handleOriginalPosition . XNAMatrix ;
376+ handleMatrix . Translation += distance ;
377+ handlePosition . XNAMatrix = handleMatrix ;
378+ }
379+
380+ DeltaX = Vector3 . Dot ( axisX , distance ) ;
381+ DeltaY = Vector3 . Dot ( axisY , distance ) ;
382+ DeltaZ = Vector3 . Dot ( axisZ , distance ) ;
383+ }
384+ return xnaMatrix ;
385+ }
386+
287387 void UpdateViewUndoState ( )
288388 {
289389 if ( UndoStack . Count == 0 )
@@ -359,12 +459,28 @@ void UndoRedo(UndoDataSet undoDataSet, bool undo)
359459 undo ? undoDataSet . OldCameraRotationXRadians : undoDataSet . NewCameraRotationXRadians ,
360460 undo ? undoDataSet . OldCameraRotationYRadians : undoDataSet . NewCameraRotationYRadians ) ;
361461 }
462+ else if ( undoDataSet . UndoEvent == UndoEvent . WorldObjectChanged )
463+ {
464+ if ( undo )
465+ {
466+ var newPosition = new WorldPosition ( undoDataSet . ChangedStaticShape . Location ) ;
467+ undoDataSet . ChangedStaticShape . Location . CopyFrom ( undoDataSet . OldPosition ) ;
468+ undoDataSet . OldPosition . CopyFrom ( newPosition ) ;
469+ }
470+ else
471+ {
472+
473+ }
474+ }
362475 }
363476
364477 void StartObjectMove ( )
365478 {
366479 MovedObject = SelectedObject ;
367480 MovedObjectOriginalPosition = new WorldPosition ( MovedObject . Location ) ;
481+ if ( HandlePosition != null )
482+ HandleOriginalPosition = new WorldPosition ( HandlePosition ) ;
483+ DeltaContext = null ;
368484 EditorState = EditorState . ObjectMoving ;
369485 }
370486
@@ -377,30 +493,51 @@ void CancelObjectMove()
377493
378494 void ApplyObjectMove ( )
379495 {
496+ UndoStack . Push ( new UndoDataSet ( )
497+ {
498+ UndoEvent = UndoEvent . WorldObjectChanged ,
499+ TileX = MovedObject . Location . TileX ,
500+ TileZ = MovedObject . Location . TileZ ,
501+ Uid = MovedObject . Uid ,
502+ ChangedStaticShape = MovedObject ,
503+ OldPosition = MovedObjectOriginalPosition ,
504+ MovedWithRespectTo = HandlePosition ?? MovedObject . Location ,
505+ } ) ;
506+ RedoStack . Clear ( ) ;
507+
508+ DeltaContext = UndoStack . Peek ( ) ;
380509 MovedObject = null ;
381510 EditorState = EditorState . ObjectSelected ;
382511 }
383512
384513 void StartHandleMove ( )
385514 {
386515 HandlePosition = new WorldPosition ( SelectedObject . Location ) ;
516+ HandleOriginalPosition = new WorldPosition ( HandlePosition ) ;
517+ DeltaContext = null ;
387518 EditorState = EditorState . HandleMoving ;
388519 }
389520
390521 void CancelHandleMove ( )
391522 {
392523 HandlePosition = null ;
524+ HandleOriginalPosition = null ;
393525 EditorState = EditorState . ObjectSelected ;
394526 }
395527
396528 void ApplyHandleMove ( )
397529 {
530+ HandleOriginalPosition = new WorldPosition ( HandlePosition ) ;
398531 EditorState = EditorState . ObjectSelected ;
399532 }
400533
401534 void SelectedObjectChanged ( )
402535 {
403536 Viewer . EditorShapes . SelectedObject = SelectedObject ;
537+ Viewer . EditorShapes . MovedObject = null ;
538+ Viewer . EditorShapes . HandleLocation = null ;
539+ HandlePosition = null ;
540+ HandleOriginalPosition = null ;
404541
405542 SelectedWorldFile = Viewer . World . Scenery . WorldFiles . SingleOrDefault ( w => w . TileX == SelectedObject ? . Location . TileX && w . TileZ == SelectedObject ? . Location . TileZ ) ;
406543 SelectedWorldObject = SelectedWorldFile ? . MstsWFile ? . Tr_Worldfile ? . SingleOrDefault ( o => o . UID == SelectedObject ? . Uid ) ;
@@ -454,6 +591,9 @@ public class UndoDataSet
454591 public int TileX ;
455592 public int TileZ ;
456593 public int Uid ;
594+ public StaticShape ChangedStaticShape ;
595+ public WorldPosition OldPosition ;
596+ public WorldPosition MovedWithRespectTo ;
457597 public Orts . Formats . Msts . WorldObject OldWorldObject ;
458598 public Orts . Formats . Msts . WorldObject NewWorldObject ;
459599
0 commit comments