11using Microsoft . Xna . Framework ;
22using Rampastring . XNAUI ;
33using Rampastring . XNAUI . Input ;
4+ using SharpDX . Direct2D1 . Effects ;
5+ using SharpDX . MediaFoundation ;
46using System ;
57using System . Collections . Generic ;
68using TSMapEditor . GameMath ;
@@ -37,6 +39,9 @@ public TileImage Tile
3739 private HashSet < MapTile > previewTiles = new HashSet < MapTile > ( ) ;
3840
3941 private Point2D ? lineSourceCell ;
42+ private PlaceTerrainLineMutation placeTerrainLineMutation ;
43+
44+ private bool blocked ;
4045
4146 public override void OnActionEnter ( )
4247 {
@@ -106,10 +111,25 @@ private void ClearPreview()
106111 cell . PreviewLevel = - 1 ;
107112 }
108113
114+ if ( placeTerrainLineMutation != null )
115+ {
116+ placeTerrainLineMutation . Undo ( ) ;
117+ placeTerrainLineMutation = null ;
118+ }
119+
109120 previewTiles . Clear ( ) ;
110121 CursorActionTarget . InvalidateMap ( ) ;
111122 }
112123
124+ private ( Direction direction , Point2D vector , int length ) GetLineInformation ( Point2D cellCoords )
125+ {
126+ Direction direction = Helpers . DirectionFromPoints ( lineSourceCell . Value , cellCoords ) ;
127+ Point2D vector = cellCoords - lineSourceCell . Value ;
128+ int length = Math . Max ( Math . Abs ( vector . X ) , Math . Abs ( vector . Y ) ) ;
129+
130+ return ( direction , vector , length ) ;
131+ }
132+
113133 /// <summary>
114134 /// Draws a preview for the line-based terrain placement feature.
115135 /// </summary>
@@ -121,21 +141,68 @@ public override void DrawPreview(Point2D cellCoords, Point2D cameraTopLeftPoint)
121141 if ( cellCoords == lineSourceCell . Value )
122142 return ;
123143
124- Direction direction = Helpers . DirectionFromPoints ( lineSourceCell . Value , cellCoords ) ;
125- Point2D vector = cellCoords - lineSourceCell . Value ;
126- int length = Math . Max ( Math . Abs ( vector . X ) , Math . Abs ( vector . Y ) ) ;
144+ ( Direction direction , Point2D vector , int length ) = GetLineInformation ( cellCoords ) ;
127145
128146 Point2D cameraPoint1 = CellMath . CellCenterPointFromCellCoords_3D ( lineSourceCell . Value , Map ) - cameraTopLeftPoint ;
129147 Point2D cameraPoint2 = CellMath . CellCenterPointFromCellCoords_3D ( lineSourceCell . Value + Helpers . VisualDirectionToPoint ( direction ) . ScaleBy ( length ) , Map ) - cameraTopLeftPoint ;
130148
131149 Renderer . DrawLine ( cameraPoint1 . ToXNAVector ( ) , cameraPoint2 . ToXNAVector ( ) , Color . Orange , 2 ) ;
132150 }
133151
152+ private void ApplyLinePreview ( Point2D cellCoords )
153+ {
154+ Point2D adjustedCellCoords = GetAdjustedCellCoords ( cellCoords ) ;
155+
156+ MapTile originTile = CursorActionTarget . Map . GetTile ( cellCoords ) ;
157+
158+ Direction direction ;
159+ Point2D vector ;
160+ int length ;
161+
162+ if ( lineSourceCell . Value == adjustedCellCoords )
163+ {
164+ direction = default ;
165+ vector = default ;
166+ length = 1 ;
167+ }
168+ else
169+ {
170+ ( direction , vector , length ) = GetLineInformation ( adjustedCellCoords ) ;
171+ }
172+
173+ if ( length < 2 )
174+ {
175+ Tile . DoForValidSubTiles ( ( subTile , subTileOffset , subTileIndex ) =>
176+ {
177+ var mapTile = Map . GetTile ( adjustedCellCoords + subTileOffset ) ;
178+
179+ if ( mapTile != null && ( ! CursorActionTarget . OnlyPaintOnClearGround || mapTile . IsClearGround ( ) ) )
180+ {
181+ mapTile . PreviewSubTileIndex = subTileIndex ;
182+ mapTile . PreviewLevel = Math . Min ( mapTile . Level + subTile . TmpImage . Height , Constants . MaxMapHeightLevel ) ;
183+ mapTile . PreviewTileImage = Tile ;
184+ previewTiles . Add ( mapTile ) ;
185+ }
186+ } ) ;
187+ }
188+ else
189+ {
190+ placeTerrainLineMutation = new PlaceTerrainLineMutation ( MutationTarget , Map . GetTile ( lineSourceCell . Value ) , direction , length , Tile ) ;
191+ placeTerrainLineMutation . Perform ( ) ;
192+ }
193+ }
194+
134195 private void ApplyPreviewForCells ( Point2D cellCoords )
135196 {
136197 if ( Tile == null )
137198 return ;
138199
200+ if ( lineSourceCell . HasValue )
201+ {
202+ ApplyLinePreview ( cellCoords ) ;
203+ return ;
204+ }
205+
139206 Point2D adjustedCellCoords = GetAdjustedCellCoords ( cellCoords ) ;
140207
141208 MapTile originTile = CursorActionTarget . Map . GetTile ( adjustedCellCoords ) ;
@@ -146,17 +213,15 @@ private void ApplyPreviewForCells(Point2D cellCoords)
146213 // First, look up the lowest point within the tile area for origin level
147214 // Only use a 1x1 brush size for this (meaning no brush at all)
148215 // so users can use larger brush sizes to "paint height"
216+
149217 for ( int i = 0 ; i < Tile . TMPImages . Length ; i ++ )
150218 {
151- MGTMPImage image = Tile . TMPImages [ i ] ;
219+ Point2D ? subTileOffset = Tile . GetSubTileCoordOffset ( i ) ;
152220
153- if ( image == null )
221+ if ( subTileOffset == null )
154222 continue ;
155223
156- int cx = adjustedCellCoords . X + i % Tile . Width ;
157- int cy = adjustedCellCoords . Y + i / Tile . Width ;
158-
159- var mapTile = MutationTarget . Map . GetTile ( cx , cy ) ;
224+ var mapTile = MutationTarget . Map . GetTile ( adjustedCellCoords + subTileOffset . Value ) ;
160225
161226 if ( mapTile != null )
162227 {
@@ -165,7 +230,7 @@ private void ApplyPreviewForCells(Point2D cellCoords)
165230 int cellLevel = mapTile . Level ;
166231
167232 // Allow replacing back cliffs
168- if ( existingTile . TmpImage . Height == image . TmpImage . Height )
233+ if ( existingTile . TmpImage . Height == Tile . GetSubTile ( i ) . TmpImage . Height )
169234 cellLevel -= existingTile . TmpImage . Height ;
170235
171236 if ( originLevel < 0 || cellLevel < originLevel )
@@ -182,19 +247,17 @@ private void ApplyPreviewForCells(Point2D cellCoords)
182247 {
183248 for ( int i = 0 ; i < Tile . TMPImages . Length ; i ++ )
184249 {
185- MGTMPImage image = Tile . TMPImages [ i ] ;
250+ Point2D ? subTileOffset = Tile . GetSubTileCoordOffset ( i ) ;
186251
187- if ( image == null )
252+ if ( subTileOffset == null )
188253 continue ;
189254
190- int cx = adjustedCellCoords . X + ( offset . X * Tile . Width ) + i % Tile . Width ;
191- int cy = adjustedCellCoords . Y + ( offset . Y * Tile . Height ) + i / Tile . Width ;
255+ var mapTile = Map . GetTile ( adjustedCellCoords + new Point2D ( offset . X * Tile . Width , offset . Y * Tile . Height ) + subTileOffset . Value ) ;
192256
193- var mapTile = CursorActionTarget . Map . GetTile ( cx , cy ) ;
194257 if ( mapTile != null && ( ! CursorActionTarget . OnlyPaintOnClearGround || mapTile . IsClearGround ( ) ) )
195258 {
196259 mapTile . PreviewSubTileIndex = i ;
197- mapTile . PreviewLevel = Math . Min ( originLevel + image . TmpImage . Height , Constants . MaxMapHeightLevel ) ;
260+ mapTile . PreviewLevel = Math . Min ( originLevel + Tile . GetSubTile ( i ) . TmpImage . Height , Constants . MaxMapHeightLevel ) ;
198261 mapTile . PreviewTileImage = Tile ;
199262 previewTiles . Add ( mapTile ) ;
200263 }
@@ -249,6 +312,9 @@ public override void LeftDown(Point2D cellCoords)
249312 if ( Tile == null )
250313 return ;
251314
315+ if ( blocked )
316+ return ;
317+
252318 Point2D adjustedCellCoords = GetAdjustedCellCoords ( cellCoords ) ;
253319
254320 Mutation mutation = null ;
@@ -265,11 +331,25 @@ public override void LeftDown(Point2D cellCoords)
265331 }
266332 else if ( KeyboardCommands . Instance . PlaceTerrainLine . AreKeysOrModifiersDown ( Keyboard ) )
267333 {
268- if ( lineSourceCell == null )
334+ var targetCell = CursorActionTarget . Map . GetTile ( adjustedCellCoords ) ;
335+
336+ if ( lineSourceCell == null && targetCell != null )
337+ {
338+ lineSourceCell = adjustedCellCoords ;
339+ }
340+
341+ return ;
342+ }
343+ else if ( lineSourceCell != null )
344+ {
345+ // Place a line if Shift is released. Block the user from accidentally placing a tile at the end of the line.
346+ if ( adjustedCellCoords != lineSourceCell )
269347 {
270- lineSourceCell = cellCoords ;
348+ ApplyTerrainLine ( adjustedCellCoords ) ;
349+ blocked = true ;
271350 }
272351
352+ lineSourceCell = null ;
273353 return ;
274354 }
275355 else
@@ -296,13 +376,14 @@ public override void LeftClick(Point2D cellCoords)
296376 {
297377 if ( lineSourceCell != null && cellCoords != lineSourceCell . Value )
298378 {
299- ApplyTerrainLine ( cellCoords ) ;
379+ ApplyTerrainLine ( GetAdjustedCellCoords ( cellCoords ) ) ;
300380 }
301381
302382 return ;
303383 }
304384
305385 LeftDown ( cellCoords ) ;
386+ blocked = false ;
306387 }
307388 }
308389}
0 commit comments