2121using Microsoft . Xna . Framework . Graphics ;
2222using ORTS . Common ;
2323using System ;
24+ using System . Collections . Concurrent ;
2425using System . Collections . Generic ;
26+ using System . Collections . ObjectModel ;
27+ using System . Linq ;
2528
2629namespace Orts . Viewer3D
2730{
@@ -30,51 +33,89 @@ public class EditorShapes : StaticShape, IDisposable
3033 public readonly MouseCrosshair MouseCrosshair ;
3134 public bool MouseCrosshairEnabled { get ; set ; }
3235 public bool CrosshairPositionUpdateEnabled { get ; set ; } = true ;
33- public StaticShape SelectedObject { get ; set ; }
36+
37+ public readonly HandleX HandleX ;
38+ public readonly HandleY HandleY ;
39+ public readonly HandleZ HandleZ ;
40+ public bool HandleEnabled { get ; set ; } = true ;
41+ public WorldPosition HandleLocation ;
42+
3443 StaticShape _selectedObject ;
35- readonly List < BoundingBoxPrimitive > SelectedObjectBoundingBoxPrimitives = new List < BoundingBoxPrimitive > ( ) ;
36- readonly List < EditorPrimitive > UnusedPrimitives = new List < EditorPrimitive > ( ) ;
44+ public StaticShape SelectedObject { get ; set ; }
45+
46+ public ConcurrentBag < StaticShape > BoundingBoxShapes = new ConcurrentBag < StaticShape > ( ) ;
47+ readonly ConcurrentDictionary < ( int tileX , int tileZ , int uid , Matrix matrix , int number ) , BoundingBoxPrimitive > BoundingBoxPrimitives = new ConcurrentDictionary < ( int , int , int , Matrix , int ) , BoundingBoxPrimitive > ( ) ;
48+ readonly ConcurrentBag < EditorPrimitive > UnusedPrimitives = new ConcurrentBag < EditorPrimitive > ( ) ;
3749 Vector3 CrosshairPosition ;
3850
3951 public EditorShapes ( Viewer viewer ) : base ( viewer , "" , null , ShapeFlags . None , null , - 1 )
4052 {
4153 MouseCrosshair = new MouseCrosshair ( Viewer , Color . GreenYellow ) ;
54+ HandleX = new HandleX ( Viewer , Color . Red ) ;
55+ HandleY = new HandleY ( Viewer , Color . Blue ) ;
56+ HandleZ = new HandleZ ( Viewer , Color . Green ) ;
4257 }
4358
4459 public override void PrepareFrame ( RenderFrame frame , ElapsedTime elapsedTime )
4560 {
4661 if ( _selectedObject != SelectedObject )
4762 {
63+ if ( _selectedObject != null )
64+ for ( var i = 0 ; i < 5 ; i ++ )
65+ BoundingBoxPrimitives . TryRemove ( ( _selectedObject . Location . TileX , _selectedObject . Location . TileZ , _selectedObject . Uid , _selectedObject . Location . XNAMatrix , i ) , out _ ) ;
66+
4867 _selectedObject = SelectedObject ;
49- if ( UnusedPrimitives . Count > 0 )
68+
69+ if ( _selectedObject ? . BoundingBox ? . Length > 0 )
5070 {
51- foreach ( var primitive in UnusedPrimitives )
71+ for ( var i = 0 ; i < _selectedObject . BoundingBox . Length ; i ++ )
5272 {
53- //primitive.Dispose();
73+ BoundingBoxPrimitives . TryAdd ( ( _selectedObject . Location . TileX , _selectedObject . Location . TileZ , _selectedObject . Uid , _selectedObject . Location . XNAMatrix , i ) ,
74+ new BoundingBoxPrimitive ( Viewer , _selectedObject . BoundingBox [ i ] , Color . CornflowerBlue ) ) ;
5475 }
55- //UnusedPrimitives.Clear();
5676 }
57- UnusedPrimitives . AddRange ( SelectedObjectBoundingBoxPrimitives ) ;
58- SelectedObjectBoundingBoxPrimitives . Clear ( ) ;
59- if ( _selectedObject ? . BoundingBox ? . Length > 0 )
77+ }
78+ for ( var i = 0 ; i < BoundingBoxPrimitives . Count ; i ++ )
79+ {
80+ var bb = BoundingBoxPrimitives . Keys . ElementAtOrDefault ( i ) ;
81+ if ( bb != default ( ( int , int , int , Matrix , int ) )
82+ && ! BoundingBoxShapes . Any ( s => s ? . Location . TileX == bb . tileX && s ? . Location . TileZ == bb . tileZ && s ? . Uid == bb . uid ) )
6083 {
61- foreach ( var boundingBox in _selectedObject . BoundingBox )
84+ if ( bb . tileX != _selectedObject ? . Location . TileX && bb . tileZ != _selectedObject ? . Location . TileZ && bb . uid != _selectedObject ? . Uid )
6285 {
63- SelectedObjectBoundingBoxPrimitives . Add ( new BoundingBoxPrimitive ( Viewer , boundingBox , Color . CornflowerBlue ) ) ;
86+ if ( BoundingBoxPrimitives . TryRemove ( bb , out var primitive ) )
87+ UnusedPrimitives . Add ( primitive ) ;
6488 }
6589 }
6690 }
67- if ( SelectedObjectBoundingBoxPrimitives ? . Count > 0 )
91+
92+ for ( var j = 0 ; j < BoundingBoxShapes . Count ; j ++ )
6893 {
69- foreach ( var boundingBox in SelectedObjectBoundingBoxPrimitives )
94+ var s = BoundingBoxShapes . ElementAtOrDefault ( j ) ;
95+ if ( s ? . BoundingBox == null || s . BoundingBox . Length == 0 )
96+ continue ;
97+
98+ if ( ! BoundingBoxPrimitives . Keys . Any ( bb => s . Location . TileX == bb . tileX && s . Location . TileZ == bb . tileZ && s . Uid == bb . uid ) )
7099 {
71- var dTileX = _selectedObject . Location . TileX - Viewer . Camera . TileX ;
72- var dTileZ = _selectedObject . Location . TileZ - Viewer . Camera . TileZ ;
73- var xnaDTileTranslation = _selectedObject . Location . XNAMatrix ;
100+ for ( var i = 0 ; i < s . BoundingBox . Length ; i ++ )
101+ {
102+ BoundingBoxPrimitives . TryAdd ( ( s . Location . TileX , s . Location . TileZ , s . Uid , s . Location . XNAMatrix , i ) ,
103+ new BoundingBoxPrimitive ( Viewer , s . BoundingBox [ i ] , Color . MediumVioletRed ) ) ;
104+ }
105+ }
106+ }
107+
108+ if ( BoundingBoxPrimitives ? . Count > 0 )
109+ {
110+ foreach ( var boundingBox in BoundingBoxPrimitives . Keys )
111+ {
112+ var dTileX = boundingBox . tileX - Viewer . Camera . TileX ;
113+ var dTileZ = boundingBox . tileZ - Viewer . Camera . TileZ ;
114+ var xnaDTileTranslation = boundingBox . matrix ;
74115 xnaDTileTranslation . M41 += dTileX * 2048 ;
75116 xnaDTileTranslation . M43 -= dTileZ * 2048 ;
76- xnaDTileTranslation = boundingBox . ComplexTransform * xnaDTileTranslation ;
77- frame . AddPrimitive ( boundingBox . Material , boundingBox , RenderPrimitiveGroup . Labels , ref xnaDTileTranslation ) ;
117+ xnaDTileTranslation = BoundingBoxPrimitives [ boundingBox ] . ComplexTransform * xnaDTileTranslation ;
118+ frame . AddPrimitive ( BoundingBoxPrimitives [ boundingBox ] . Material , BoundingBoxPrimitives [ boundingBox ] , RenderPrimitiveGroup . Labels , ref xnaDTileTranslation ) ;
78119 }
79120 }
80121 if ( MouseCrosshairEnabled )
@@ -86,28 +127,43 @@ public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
86127 var mouseCrosshairMatrix = Matrix . CreateTranslation ( CrosshairPosition ) ;
87128 frame . AddPrimitive ( MouseCrosshair . Material , MouseCrosshair , RenderPrimitiveGroup . World , ref mouseCrosshairMatrix ) ;
88129 }
130+ if ( HandleEnabled )
131+ {
132+ var handleLocation = HandleLocation ?? _selectedObject ? . Location ;
133+ if ( handleLocation != null )
134+ {
135+ var dTileX = handleLocation . TileX - Viewer . Camera . TileX ;
136+ var dTileZ = handleLocation . TileZ - Viewer . Camera . TileZ ;
137+ var xnaDTileTranslation = handleLocation . XNAMatrix ;
138+ xnaDTileTranslation . M41 += dTileX * 2048 ;
139+ xnaDTileTranslation . M43 -= dTileZ * 2048 ;
140+ frame . AddPrimitive ( HandleX . Material , HandleX , RenderPrimitiveGroup . Overlay , ref xnaDTileTranslation ) ;
141+ frame . AddPrimitive ( HandleY . Material , HandleY , RenderPrimitiveGroup . Overlay , ref xnaDTileTranslation ) ;
142+ frame . AddPrimitive ( HandleZ . Material , HandleZ , RenderPrimitiveGroup . Overlay , ref xnaDTileTranslation ) ;
143+ }
144+ }
89145 }
90146
91147 internal override void Mark ( )
92148 {
93149 MouseCrosshair . Mark ( ) ;
94- if ( SelectedObjectBoundingBoxPrimitives ? . Count > 0 )
150+ if ( BoundingBoxPrimitives ? . Count > 0 )
95151 {
96- foreach ( var selectedObject in SelectedObjectBoundingBoxPrimitives )
152+ foreach ( var selectedObject in BoundingBoxPrimitives )
97153 {
98- selectedObject . Mark ( ) ;
154+ selectedObject . Value . Mark ( ) ;
99155 }
100156 }
101157 }
102158
103159 public void Dispose ( )
104160 {
105161 MouseCrosshair ? . Dispose ( ) ;
106- if ( SelectedObjectBoundingBoxPrimitives ? . Count > 0 )
162+ if ( BoundingBoxPrimitives ? . Count > 0 )
107163 {
108- foreach ( var selectedObject in SelectedObjectBoundingBoxPrimitives )
164+ foreach ( var selectedObject in BoundingBoxPrimitives )
109165 {
110- selectedObject . Dispose ( ) ;
166+ selectedObject . Value . Dispose ( ) ;
111167 }
112168 }
113169 }
@@ -162,7 +218,7 @@ public BoundingBoxPrimitive(Viewer viewer, BoundingBox boundingBox, Color color)
162218 IndexBuffer = BoundingBoxIndexBuffer ;
163219 PrimitiveCount = IndexBuffer . IndexCount / 2 ;
164220 PrimitiveType = PrimitiveType . LineList ;
165- Material = viewer . MaterialManager . Load ( "DebugNormals " ) ;
221+ Material = viewer . MaterialManager . Load ( "EditorPrimitive " ) ;
166222 ComplexTransform = boundingBox . ComplexTransform ;
167223 }
168224 }
@@ -188,4 +244,84 @@ public MouseCrosshair(Viewer viewer, Color color)
188244 Material = viewer . MaterialManager . Load ( "DebugNormals" ) ;
189245 }
190246 }
247+
248+ [ CallOnThread ( "Loader" ) ]
249+ public class HandleX : EditorPrimitive
250+ {
251+ public HandleX ( Viewer viewer , Color color )
252+ {
253+ var vertexData = GetVertexData ( color ) ;
254+ VertexBuffer = new VertexBuffer ( viewer . GraphicsDevice , typeof ( VertexPositionColor ) , vertexData . Length , BufferUsage . WriteOnly ) ;
255+ VertexBuffer . SetData ( vertexData ) ;
256+ PrimitiveCount = VertexBuffer . VertexCount / 2 ;
257+ PrimitiveType = PrimitiveType . TriangleList ;
258+ Material = viewer . MaterialManager . Load ( "EditorPrimitive" ) ;
259+ }
260+
261+ protected virtual VertexPositionColor [ ] GetVertexData ( Color color ) => GetVertexData ( 0 , 1 , 2 , color ) ;
262+ protected VertexPositionColor [ ] GetVertexData ( int x , int y , int z , Color color )
263+ {
264+ var l = 5f ;
265+ var d = 0.1f ;
266+ var a = l / 5 ;
267+ var b = a / 4 ;
268+ var c = l - a ;
269+ var data = new float [ ] [ ]
270+ {
271+ new [ ] { 0 , + d , 0 } ,
272+ new [ ] { c , + d , 0 } ,
273+ new [ ] { 0 , - d , 0 } ,
274+ new [ ] { 0 , - d , 0 } ,
275+ new [ ] { c , + d , 0 } ,
276+ new [ ] { c , - d , 0 } ,
277+
278+ new [ ] { 0 , 0 , + d } ,
279+ new [ ] { c , 0 , + d } ,
280+ new [ ] { 0 , 0 , - d } ,
281+ new [ ] { 0 , 0 , - d } ,
282+ new [ ] { c , 0 , + d } ,
283+ new [ ] { c , 0 , - d } ,
284+
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 } ,
304+ } ;
305+ var vertexData = new VertexPositionColor [ data . Length ] ;
306+ for ( var i = 0 ; i < data . Length ; i ++ )
307+ {
308+ vertexData [ i ] = new VertexPositionColor ( new Vector3 ( data [ i ] [ x ] , data [ i ] [ y ] , data [ i ] [ z ] ) , color ) ;
309+ }
310+ return vertexData ;
311+ }
312+ }
313+
314+ [ CallOnThread ( "Loader" ) ]
315+ public class HandleY : HandleX
316+ {
317+ public HandleY ( Viewer viewer , Color color ) : base ( viewer , color ) { }
318+ protected override VertexPositionColor [ ] GetVertexData ( Color color ) => GetVertexData ( 2 , 0 , 1 , color ) ;
319+ }
320+
321+ [ CallOnThread ( "Loader" ) ]
322+ public class HandleZ : HandleX
323+ {
324+ public HandleZ ( Viewer viewer , Color color ) : base ( viewer , color ) { }
325+ protected override VertexPositionColor [ ] GetVertexData ( Color color ) => GetVertexData ( 1 , 2 , 0 , color ) ;
326+ }
191327}
0 commit comments