3939using Orts . Viewer3D . Processes ;
4040using System . Threading ;
4141using System . Threading . Tasks ;
42+ using System . IO ;
43+ using System . Globalization ;
4244
4345namespace ORTS . TrackViewer
4446{
@@ -48,8 +50,9 @@ public class SceneViewer
4850
4951 public SceneWindow SceneWindow ;
5052 public GameWindow SwapChainWindow ;
51- TrackViewer TrackViewer ;
53+ public readonly TrackViewer TrackViewer ;
5254 SwapChainRenderTarget SwapChain ;
55+ internal StaticShape SelectedObject ;
5356
5457 /// <summary>The command-line arguments</summary>
5558 private string [ ] CommandLineArgs ;
@@ -107,8 +110,7 @@ public SceneViewer(TrackViewer trackViewer, string[] args)
107110 /// <summary>
108111 /// Allows the game to perform any initialization it needs to before starting to run.
109112 /// This is where it can query for any required services and load any non-graphic
110- /// relation ontent. Calling base.Initialize will enumerate through any components
111- /// and initialize them as well.
113+ /// relation ontent.
112114 /// </summary>
113115 public void Initialize ( )
114116 {
@@ -130,17 +132,17 @@ public void LoadContent()
130132 /// <param name="gameTime">Provides a snapshot of timing values.</param>
131133 public void Update ( GameTime gameTime )
132134 {
135+ if ( UserInput . IsMouseLeftButtonPressed && UserInput . ModifiersMaskShiftCtrlAlt ( false , false , false ) )
136+ {
137+ if ( PickByMouse ( out SelectedObject ) )
138+ {
139+ TrackViewer . RenderProcess . Viewer . EditorShapes . SelectedObject = SelectedObject ;
140+ FillSelectedObjectData ( ) ;
141+ }
142+ }
133143 SetCameraLocationStatus ( TrackViewer . RenderProcess ? . Viewer ? . Camera ? . CameraWorldLocation ?? new WorldLocation ( ) ) ;
134144 }
135145
136- /// <summary>
137- /// This is called when the game should draw itself.
138- /// </summary>
139- /// <param name="gameTime">Provides a snapshot of timing values.</param>
140- public void Draw ( GameTime gameTime )
141- {
142- }
143-
144146 public void EndDraw ( )
145147 {
146148 SwapChain . Present ( ) ;
@@ -195,6 +197,87 @@ public async Task SetCameraLocation()
195197 mouseLocation . Location . Y = elevatedLocation + 15 ;
196198 TrackViewer . RenderProcess . Viewer . ViewerCamera . SetLocation ( mouseLocation ) ;
197199 }
200+
201+ protected bool PickByMouse ( out StaticShape pickedObject )
202+ {
203+ var viewer = TrackViewer . RenderProcess . Viewer ;
204+
205+ if ( viewer == null )
206+ {
207+ pickedObject = null ;
208+ return false ;
209+ }
210+
211+ var camera = viewer . Camera ;
212+
213+ var direction = Vector3 . Normalize ( viewer . FarPoint - viewer . NearPoint ) ;
214+ var pickRay = new Ray ( viewer . NearPoint , direction ) ;
215+
216+ pickedObject = null ;
217+ var pickedDistance = float . MaxValue ;
218+ foreach ( var worldFile in viewer . World . Scenery . WorldFiles )
219+ {
220+ foreach ( var sceneryObject in worldFile . sceneryObjects )
221+ {
222+ float ? distance = null ;
223+
224+ if ( sceneryObject . BoundingBox is Orts . Viewer3D . BoundingBox boundingBox )
225+ {
226+ // Locate relative to the camera
227+ var dTileX = sceneryObject . Location . TileX - camera . TileX ;
228+ var dTileZ = sceneryObject . Location . TileZ - camera . TileZ ;
229+ var xnaDTileTranslation = sceneryObject . Location . XNAMatrix ;
230+ xnaDTileTranslation . M41 += dTileX * 2048 ;
231+ xnaDTileTranslation . M43 -= dTileZ * 2048 ;
232+
233+ var min = Vector3 . Transform ( boundingBox . Min , xnaDTileTranslation ) ;
234+ var max = Vector3 . Transform ( boundingBox . Max , xnaDTileTranslation ) ;
235+
236+ var xnabb = new Microsoft . Xna . Framework . BoundingBox ( min , max ) ;
237+ distance = pickRay . Intersects ( xnabb ) ;
238+ }
239+ else
240+ {
241+ var radius = 10f ;
242+ var boundingSphere = new BoundingSphere ( camera . XnaLocation ( sceneryObject . Location . WorldLocation ) , radius ) ;
243+ distance = pickRay . Intersects ( boundingSphere ) ;
244+ }
245+
246+ if ( distance != null )
247+ {
248+ if ( distance < pickedDistance )
249+ {
250+ pickedDistance = distance . Value ;
251+ pickedObject = sceneryObject ;
252+ }
253+ }
254+ }
255+ }
256+ return pickedObject != null ;
257+ }
258+
259+ void FillSelectedObjectData ( )
260+ {
261+ SceneWindow . Filename . Text = SelectedObject != null ? System . IO . Path . GetFileName ( SelectedObject . SharedShape . FilePath ) : "" ;
262+ SceneWindow . TileX . Text = SelectedObject ? . Location . TileX . ToString ( CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
263+ SceneWindow . TileZ . Text = SelectedObject ? . Location . TileZ . ToString ( CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
264+ SceneWindow . PosX . Text = SelectedObject ? . Location . Location . X . ToString ( "N3" , CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
265+ SceneWindow . PosY . Text = SelectedObject ? . Location . Location . Y . ToString ( "N3" , CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
266+ SceneWindow . PosZ . Text = SelectedObject ? . Location . Location . Z . ToString ( "N3" , CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
267+ if ( SelectedObject ? . Location . XNAMatrix . Decompose ( out var _ , out var q , out var _ ) ?? false )
268+ {
269+ var mag = Math . Sqrt ( q . W * q . W + q . Y * q . Y ) ;
270+ var w = q . W / mag ;
271+ var ang = 2.0 * Math . Acos ( w ) / Math . PI * 180 ;
272+ SceneWindow . RotY . Text = ang . ToString ( "N3" , CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
273+ }
274+ else
275+ {
276+ SceneWindow . RotY . Text = "" ;
277+ }
278+ SceneWindow . Uid . Text = SelectedObject . Uid . ToString ( CultureInfo . InvariantCulture ) . Replace ( "," , "" ) ;
279+ }
280+
198281 }
199282
200283 public class SceneViewerHwndHost : HwndHost
@@ -225,24 +308,6 @@ protected override HandleRef BuildWindowCore(HandleRef hwndParent)
225308
226309 protected override void DestroyWindowCore ( HandleRef hwnd )
227310 {
228-
229- }
230- }
231-
232- public class SceneViewerVisualHost : UIElement
233- {
234- System . Windows . Media . Visual Visual ;
235-
236- public SceneViewerVisualHost ( GameWindow gameWindow )
237- {
238- Visual = HwndSource . FromHwnd ( gameWindow . Handle ) . RootVisual ;
239- }
240-
241- protected override int VisualChildrenCount { get { return Visual != null ? 1 : 0 ; } }
242-
243- protected override System . Windows . Media . Visual GetVisualChild ( int index )
244- {
245- return Visual ;
246311 }
247312 }
248313}
0 commit comments