Skip to content

Commit bc5fa26

Browse files
committed
Improve preview for terrain line placement
1 parent dd374b5 commit bc5fa26

File tree

4 files changed

+147
-55
lines changed

4 files changed

+147
-55
lines changed

src/TSMapEditor/Mutations/Classes/PlaceTerrainLineMutation.cs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,12 @@ int GetSouthernmostSubTileOffset()
3535

3636
for (int i = 0; i < tile.TMPImages.Length; i++)
3737
{
38-
var image = tile.TMPImages[i];
38+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
3939

40-
if (image == null)
40+
if (subTileOffset == null)
4141
continue;
4242

43-
int cx = i % tile.Width;
44-
int cy = i / tile.Height;
45-
46-
int southOffset = (cx + cy) / 2;
43+
int southOffset = (subTileOffset.Value.X + subTileOffset.Value.Y) / 2;
4744
if (southOffset > maxY)
4845
maxY = southOffset;
4946
}
@@ -57,15 +54,12 @@ int GetEasternmostSubTileOffset()
5754

5855
for (int i = 0; i < tile.TMPImages.Length; i++)
5956
{
60-
var image = tile.TMPImages[i];
57+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
6158

62-
if (image == null)
59+
if (subTileOffset == null)
6360
continue;
6461

65-
int cx = i % tile.Width;
66-
int cy = i / tile.Height;
67-
68-
int eastOffset = cx - cy;
62+
int eastOffset = subTileOffset.Value.X - subTileOffset.Value.Y;
6963

7064
if (eastOffset > maxEast)
7165
maxEast = eastOffset;
@@ -80,15 +74,12 @@ int GetWesternmostSubTileOffset()
8074

8175
for (int i = 0; i < tile.TMPImages.Length; i++)
8276
{
83-
var image = tile.TMPImages[i];
77+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
8478

85-
if (image == null)
79+
if (subTileOffset == null)
8680
continue;
8781

88-
int cx = i % tile.Width;
89-
int cy = i / tile.Height;
90-
91-
int westOffset = cy - cx;
82+
int westOffset = subTileOffset.Value.Y - subTileOffset.Value.X;
9283

9384
if (westOffset > maxWest)
9485
maxWest = westOffset;
@@ -139,21 +130,22 @@ private void PlaceTile(Point2D coords)
139130
// Process cells within tile foundation
140131
for (int i = 0; i < tile.TMPImages.Length; i++)
141132
{
142-
MGTMPImage image = tile.TMPImages[i];
133+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
143134

144-
if (image == null)
135+
if (subTileOffset == null)
145136
continue;
146137

147-
int cx = coords.X + i % tile.Width;
148-
int cy = coords.Y + i / tile.Width;
149-
150-
Point2D cellCoords = new Point2D(cx, cy);
138+
Point2D cellCoords = coords + subTileOffset.Value;
151139
var cell = Map.GetTile(cellCoords);
152140
if (cell == null)
153141
continue;
154142

143+
if (undoData.Exists(d => d.CellCoords == cellCoords))
144+
continue;
145+
155146
undoData.Add(new OriginalCellTerrainData(cellCoords, cell.TileIndex, cell.SubTileIndex, cell.Level));
156147
cell.ChangeTileIndex(tile.TileID, (byte)i);
148+
cell.Level = (byte)Math.Min(cell.Level + tile.GetSubTile(i).TmpImage.Height, Constants.MaxMapHeightLevel);
157149
}
158150
}
159151

src/TSMapEditor/Mutations/Classes/PlaceTerrainTileMutation.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,12 @@ public override void Perform()
7676
// so users can use larger brush sizes to "paint height"
7777
for (int i = 0; i < tile.TMPImages.Length; i++)
7878
{
79-
MGTMPImage image = tile.TMPImages[i];
79+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
8080

81-
if (image == null)
81+
if (subTileOffset == null)
8282
continue;
8383

84-
int cx = targetCellCoords.X + i % tile.Width;
85-
int cy = targetCellCoords.Y + i / tile.Width;
86-
87-
var mapTile = MutationTarget.Map.GetTile(cx, cy);
84+
var mapTile = MutationTarget.Map.GetTile(targetCellCoords + subTileOffset.Value);
8885

8986
if (mapTile != null)
9087
{
@@ -93,7 +90,7 @@ public override void Perform()
9390
int cellLevel = mapTile.Level;
9491

9592
// Allow replacing back cliffs
96-
if (existingTile.TmpImage.Height == image.TmpImage.Height)
93+
if (existingTile.TmpImage.Height == tile.GetSubTile(i).TmpImage.Height)
9794
cellLevel -= existingTile.TmpImage.Height;
9895

9996
if (originLevel < 0 || cellLevel < originLevel)
@@ -110,19 +107,19 @@ public override void Perform()
110107
{
111108
for (int i = 0; i < tile.TMPImages.Length; i++)
112109
{
113-
MGTMPImage image = tile.TMPImages[i];
110+
Point2D? subTileOffset = tile.GetSubTileCoordOffset(i);
114111

115-
if (image == null)
112+
if (subTileOffset == null)
116113
continue;
117114

118115
int cx = targetCellCoords.X + (offset.X * tile.Width) + i % tile.Width;
119116
int cy = targetCellCoords.Y + (offset.Y * tile.Height) + i / tile.Width;
120117

121-
var mapTile = MutationTarget.Map.GetTile(cx, cy);
118+
var mapTile = MutationTarget.Map.GetTile(targetCellCoords + new Point2D(offset.X * tile.Width, offset.Y * tile.Height) + subTileOffset.Value);
122119
if (mapTile != null && (!MutationTarget.OnlyPaintOnClearGround || mapTile.IsClearGround()))
123120
{
124121
mapTile.ChangeTileIndex(tile.TileID, (byte)i);
125-
mapTile.Level = (byte)Math.Min(originLevel + image.TmpImage.Height, Constants.MaxMapHeightLevel);
122+
mapTile.Level = (byte)Math.Min(originLevel + tile.GetSubTile(i).TmpImage.Height, Constants.MaxMapHeightLevel);
126123
RefreshCellLighting(mapTile);
127124
}
128125
}

src/TSMapEditor/Rendering/TileImage.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System;
1+
using SharpDX.Direct2D1.Effects;
2+
using System;
23
using TSMapEditor.GameMath;
4+
using TSMapEditor.UI;
35

46
namespace TSMapEditor.Rendering
57
{
@@ -96,6 +98,26 @@ public TileImage(int width, int height, int tileSetId, int tileIndex, int tileId
9698

9799
public MGTMPImage[] TMPImages { get; set; }
98100

101+
/// <summary>
102+
/// Performs an action for all valid sub-tiles of the TMP image.
103+
/// </summary>
104+
/// <param name="action">The action to perform. First parameter is the sub-tile, second parameter its offset within the tile, and the third parameter is the sub-tile's index.</param>
105+
public void DoForValidSubTiles(Action<MGTMPImage, Point2D, int> action)
106+
{
107+
for (int i = 0; i < TMPImages.Length; i++)
108+
{
109+
MGTMPImage image = TMPImages[i];
110+
111+
if (image == null)
112+
continue;
113+
114+
int cx = i % Width;
115+
int cy = i / Width;
116+
117+
action(image, new Point2D(cx, cy), i);
118+
}
119+
}
120+
99121
/// <summary>
100122
/// Calculates and returns the width of this full tile image.
101123
/// </summary>

src/TSMapEditor/UI/CursorActions/PlaceTerrainCursorAction.cs

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.Xna.Framework;
22
using Rampastring.XNAUI;
33
using Rampastring.XNAUI.Input;
4+
using SharpDX.Direct2D1.Effects;
5+
using SharpDX.MediaFoundation;
46
using System;
57
using System.Collections.Generic;
68
using 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

Comments
 (0)