Skip to content

Commit 1c21582

Browse files
committed
Allow placing terrain objects in a line by holding Shift
1 parent a127fda commit 1c21582

File tree

5 files changed

+199
-5
lines changed

5 files changed

+199
-5
lines changed

src/TSMapEditor/Config/Translations/en/Translation_en.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,7 @@ PlaceSmudgeMutation.DisplayString=Place smudge '{0}' at {1} with brush size of {
14771477
PlaceSmudgeMutation.DisplayStringErase=Erase smudges at {0} with brush size of {1}
14781478
PlaceTerrainLineMutation.DisplayString=Place Terrain Line from {0} towards {1} with distance of {2}
14791479
PlaceTerrainObjectCollectionMutation.DisplayString=Place terrain object collection '{0}' at {1}
1480+
PlaceTerrainObjectLineMutation.DisplayString=Place terrain object '{0}' in a line from {1} towards {2} with length {3}
14801481
PlaceTerrainObjectMutation.DisplayString=Place terrain object '{0}' at {1}
14811482
PlaceTerrainTileMutation.DisplayString=Place terrain tile of TileSet {0} at {1} with a brush size of {2}
14821483
PlaceTubeMutation.DisplayString=Place tunnel tube of length {0} at {1}

src/TSMapEditor/Constants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace TSMapEditor
44
{
55
public static class Constants
66
{
7-
public const string ReleaseVersion = "1.7.12";
7+
public const string ReleaseVersion = "1.8.0";
88

99
public static int CellSizeX = 48;
1010
public static int CellSizeY = 24;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System.Collections.Generic;
2+
using TSMapEditor.GameMath;
3+
using TSMapEditor.Models;
4+
using TSMapEditor.UI;
5+
6+
namespace TSMapEditor.Mutations.Classes
7+
{
8+
/// <summary>
9+
/// A mutation that allows placing terrain objects in a line on the map.
10+
/// </summary>
11+
public class PlaceTerrainObjectLineMutation : Mutation
12+
{
13+
public PlaceTerrainObjectLineMutation(IMutationTarget mutationTarget, TerrainType terrainType, Point2D sourceCoords, Direction direction, int length) : base(mutationTarget)
14+
{
15+
this.terrainType = terrainType;
16+
this.sourceCoords = sourceCoords;
17+
this.direction = direction;
18+
this.length = length;
19+
}
20+
21+
private readonly TerrainType terrainType;
22+
private readonly Point2D sourceCoords;
23+
private readonly Direction direction;
24+
private readonly int length;
25+
26+
private List<Point2D> placedCells;
27+
28+
public override string GetDisplayString()
29+
{
30+
string directionString = Translate("Direction." + direction, Helpers.DirectionToName(direction));
31+
return string.Format(Translate(this, "DisplayString",
32+
"Place terrain object '{0}' in a line from {1} towards {2} with length {3}"),
33+
terrainType.GetEditorDisplayName(), sourceCoords, directionString, length);
34+
}
35+
36+
public override void Perform()
37+
{
38+
placedCells = new List<Point2D>();
39+
Point2D step = Helpers.VisualDirectionToPoint(direction);
40+
41+
for (int i = 0; i <= length; i++)
42+
{
43+
Point2D coords = sourceCoords + step.ScaleBy(i);
44+
var tile = MutationTarget.Map.GetTile(coords);
45+
if (tile == null)
46+
continue;
47+
48+
if (tile.TerrainObject != null)
49+
continue;
50+
51+
var terrainObject = new TerrainObject(terrainType, coords);
52+
MutationTarget.Map.AddTerrainObject(terrainObject);
53+
placedCells.Add(coords);
54+
}
55+
56+
MutationTarget.InvalidateMap();
57+
}
58+
59+
public override void Undo()
60+
{
61+
foreach (Point2D coords in placedCells)
62+
{
63+
MutationTarget.Map.RemoveTerrainObject(coords);
64+
}
65+
66+
MutationTarget.InvalidateMap();
67+
}
68+
}
69+
}

src/TSMapEditor/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
[assembly: AssemblyConfiguration("")]
1111
[assembly: AssemblyCompany("Rampastring")]
1212
[assembly: AssemblyProduct("World-Altering Editor (WAE)")]
13-
[assembly: AssemblyCopyright("Copyright © Rami 'Rampastring' Pasanen 2021-2025")]
13+
[assembly: AssemblyCopyright("Copyright © Rami 'Rampastring' Pasanen 2021-2026")]
1414
[assembly: AssemblyTrademark("")]
1515
[assembly: AssemblyCulture("")]
1616

@@ -34,4 +34,4 @@
3434
// You can specify all the values or you can default the Build and Revision Numbers
3535
// by using the '*' as shown below:
3636
// [assembly: AssemblyVersion("1.0.*")]
37-
[assembly: AssemblyVersion("1.7.*")]
37+
[assembly: AssemblyVersion("1.8.*")]

src/TSMapEditor/UI/CursorActions/TerrainObjectPlacementAction.cs

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System;
1+
using Microsoft.Xna.Framework;
2+
using Rampastring.XNAUI;
3+
using System;
24
using TSMapEditor.GameMath;
35
using TSMapEditor.Models;
46
using TSMapEditor.Mutations.Classes;
@@ -41,8 +43,33 @@ public TerrainType TerrainType
4143
}
4244
}
4345

46+
private Point2D? lineSourceCell;
47+
private PlaceTerrainObjectLineMutation linePreviewMutation;
48+
private bool blocked;
49+
50+
public override void OnActionExit()
51+
{
52+
ClearLinePreview();
53+
base.OnActionExit();
54+
}
55+
56+
private (Direction direction, int length) GetLineInformation(Point2D cellCoords)
57+
{
58+
Direction direction = Helpers.DirectionFromPoints(lineSourceCell.Value, cellCoords);
59+
Point2D vector = cellCoords - lineSourceCell.Value;
60+
int length = Math.Max(Math.Abs(vector.X), Math.Abs(vector.Y));
61+
62+
return (direction, length);
63+
}
64+
4465
public override void PreMapDraw(Point2D cellCoords)
4566
{
67+
if (lineSourceCell.HasValue)
68+
{
69+
ApplyLinePreview(cellCoords);
70+
return;
71+
}
72+
4673
var cell = CursorActionTarget.Map.GetTile(cellCoords);
4774
if (cell.TerrainObject == null)
4875
{
@@ -55,6 +82,12 @@ public override void PreMapDraw(Point2D cellCoords)
5582

5683
public override void PostMapDraw(Point2D cellCoords)
5784
{
85+
if (lineSourceCell.HasValue)
86+
{
87+
ClearLinePreview();
88+
return;
89+
}
90+
5891
var cell = CursorActionTarget.Map.GetTile(cellCoords);
5992
if (cell.TerrainObject == terrainObject)
6093
{
@@ -64,11 +97,65 @@ public override void PostMapDraw(Point2D cellCoords)
6497
CursorActionTarget.AddRefreshPoint(cellCoords);
6598
}
6699

100+
private void ApplyLinePreview(Point2D cellCoords)
101+
{
102+
if (!lineSourceCell.HasValue || lineSourceCell.Value == cellCoords)
103+
return;
104+
105+
(Direction direction, int length) = GetLineInformation(cellCoords);
106+
107+
if (length < 1)
108+
return;
109+
110+
linePreviewMutation = new PlaceTerrainObjectLineMutation(CursorActionTarget.MutationTarget, TerrainType, lineSourceCell.Value, direction, length);
111+
linePreviewMutation.Perform();
112+
}
113+
114+
private void ClearLinePreview()
115+
{
116+
if (linePreviewMutation != null)
117+
{
118+
linePreviewMutation.Undo();
119+
linePreviewMutation = null;
120+
}
121+
122+
CursorActionTarget.InvalidateMap();
123+
}
124+
125+
public override void DrawPreview(Point2D cellCoords, Point2D cameraTopLeftPoint)
126+
{
127+
if (!lineSourceCell.HasValue)
128+
return;
129+
130+
if (cellCoords == lineSourceCell.Value)
131+
return;
132+
133+
(Direction direction, int length) = GetLineInformation(cellCoords);
134+
135+
Point2D cameraPoint1 = (CellMath.CellCenterPointFromCellCoords_3D(lineSourceCell.Value, Map) - cameraTopLeftPoint).ScaleBy(CursorActionTarget.Camera.ZoomLevel);
136+
Point2D cameraPoint2 = (CellMath.CellCenterPointFromCellCoords_3D(lineSourceCell.Value + Helpers.VisualDirectionToPoint(direction).ScaleBy(length), Map) - cameraTopLeftPoint).ScaleBy(CursorActionTarget.Camera.ZoomLevel);
137+
138+
Renderer.DrawLine(cameraPoint1.ToXNAVector(), cameraPoint2.ToXNAVector(), Color.Orange, 2);
139+
}
140+
67141
public override void LeftDown(Point2D cellCoords)
68142
{
69143
if (_terrainType == null)
70144
throw new InvalidOperationException(nameof(TerrainType) + " cannot be null");
71145

146+
if (blocked)
147+
return;
148+
149+
if (KeyboardCommands.Instance.PlaceTerrainLine.AreKeysOrModifiersDown(Keyboard))
150+
{
151+
if (lineSourceCell == null && CursorActionTarget.Map.GetTile(cellCoords) != null)
152+
{
153+
lineSourceCell = cellCoords;
154+
}
155+
156+
return;
157+
}
158+
72159
var cell = CursorActionTarget.Map.GetTile(cellCoords);
73160
if (cell.TerrainObject != null)
74161
return;
@@ -77,6 +164,43 @@ public override void LeftDown(Point2D cellCoords)
77164
CursorActionTarget.MutationManager.PerformMutation(mutation);
78165
}
79166

80-
public override void LeftClick(Point2D cellCoords) => LeftDown(cellCoords);
167+
private void ApplyLine(Point2D cellCoords)
168+
{
169+
(Direction direction, int length) = GetLineInformation(cellCoords);
170+
var mutation = new PlaceTerrainObjectLineMutation(CursorActionTarget.MutationTarget, TerrainType, lineSourceCell.Value, direction, length);
171+
PerformMutation(mutation);
172+
lineSourceCell = null;
173+
}
174+
175+
public override void LeftClick(Point2D cellCoords)
176+
{
177+
if (KeyboardCommands.Instance.PlaceTerrainLine.AreKeysOrModifiersDown(Keyboard))
178+
{
179+
if (lineSourceCell != null && cellCoords != lineSourceCell.Value)
180+
{
181+
ApplyLine(cellCoords);
182+
}
183+
184+
return;
185+
}
186+
187+
LeftDown(cellCoords);
188+
blocked = false;
189+
}
190+
191+
public override void Update(Point2D? cellCoords)
192+
{
193+
if (lineSourceCell != null && cellCoords != null && lineSourceCell != cellCoords)
194+
{
195+
if (!KeyboardCommands.Instance.PlaceTerrainLine.AreKeysOrModifiersDown(Keyboard))
196+
{
197+
ApplyLine(cellCoords.Value);
198+
blocked = true;
199+
}
200+
}
201+
202+
if (!CursorActionTarget.WindowManager.Cursor.LeftDown && !CursorActionTarget.WindowManager.Cursor.LeftClicked)
203+
blocked = false;
204+
}
81205
}
82206
}

0 commit comments

Comments
 (0)