Skip to content

Commit cfb7111

Browse files
committed
Add support for brush sizes to smudge placement cursor action
1 parent 5600865 commit cfb7111

File tree

3 files changed

+155
-55
lines changed

3 files changed

+155
-55
lines changed
Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,99 @@
1-
using TSMapEditor.GameMath;
1+
using System;
2+
using System.Collections.Generic;
3+
using TSMapEditor.GameMath;
24
using TSMapEditor.Models;
35
using TSMapEditor.UI;
46

57
namespace TSMapEditor.Mutations.Classes
68
{
9+
public struct CachedSmudge
10+
{
11+
public Point2D CellCoords;
12+
public SmudgeType SmudgeType;
13+
14+
public CachedSmudge(Point2D cellCoords, SmudgeType smudgeType)
15+
{
16+
CellCoords = cellCoords;
17+
SmudgeType = smudgeType;
18+
}
19+
}
20+
721
/// <summary>
822
/// A mutation that places a smudge on the map.
923
/// </summary>
1024
public class PlaceSmudgeMutation : Mutation
1125
{
12-
public PlaceSmudgeMutation(IMutationTarget mutationTarget, SmudgeType smudgeType, Point2D cellCoords) : base(mutationTarget)
26+
public PlaceSmudgeMutation(IMutationTarget mutationTarget, SmudgeType smudgeType, Point2D cellCoords, BrushSize brushSize) : base(mutationTarget)
1327
{
1428
this.smudgeType = smudgeType;
1529
this.cellCoords = cellCoords;
30+
this.brushSize = brushSize ?? throw new ArgumentNullException(nameof(brushSize));
1631
}
1732

18-
private Smudge oldSmudge;
33+
private List<CachedSmudge> oldSmudges = new List<CachedSmudge>(1);
1934
private SmudgeType smudgeType;
2035
private Point2D cellCoords;
36+
private BrushSize brushSize;
2137

2238
public override string GetDisplayString()
2339
{
24-
return string.Format(Translate(this, "DisplayString",
25-
"Place smudge '{0}' at {1}"),
26-
smudgeType.GetEditorDisplayName(), cellCoords);
40+
if (smudgeType == null)
41+
{
42+
return string.Format(Translate(this, "DisplayStringErase",
43+
"Erase smudges at {0} with brush size of {1}"),
44+
cellCoords, brushSize);
45+
}
46+
else
47+
{
48+
return string.Format(Translate(this, "DisplayString",
49+
"Place smudge '{0}' at {1} with brush size of {2}"),
50+
smudgeType.GetEditorDisplayName(), cellCoords, brushSize);
51+
}
2752
}
2853

2954
public override void Perform()
3055
{
31-
var cell = MutationTarget.Map.GetTile(cellCoords);
32-
if (cell.Smudge != null)
33-
oldSmudge = cell.Smudge;
56+
oldSmudges.Clear();
3457

35-
if (smudgeType != null)
36-
cell.Smudge = new Smudge() { SmudgeType = smudgeType, Position = cellCoords };
37-
else
38-
cell.Smudge = null; // delete an existing smudge if smudge type is null
58+
brushSize.DoForBrushSize(offset =>
59+
{
60+
var cell = MutationTarget.Map.GetTile(cellCoords + offset);
61+
62+
if (cell == null)
63+
return;
3964

40-
MutationTarget.AddRefreshPoint(cellCoords, 1);
65+
if ((smudgeType == null && cell.Smudge != null) ||
66+
(smudgeType != null && (cell.Smudge == null || cell.Smudge.SmudgeType != smudgeType)))
67+
{
68+
oldSmudges.Add(new CachedSmudge(cell.CoordsToPoint(), cell.Smudge == null ? null : cell.Smudge.SmudgeType));
69+
}
70+
else
71+
{
72+
return;
73+
}
74+
75+
if (smudgeType != null)
76+
cell.Smudge = new Smudge() { SmudgeType = smudgeType, Position = cell.CoordsToPoint() };
77+
else
78+
cell.Smudge = null; // delete an existing smudge if smudge type is null
79+
});
80+
81+
MutationTarget.AddRefreshPoint(cellCoords, brushSize.Max);
4182
}
4283

4384
public override void Undo()
4485
{
45-
var cell = MutationTarget.Map.GetTile(cellCoords);
86+
foreach (var oldSmudge in oldSmudges)
87+
{
88+
var cell = Map.GetTile(oldSmudge.CellCoords);
89+
90+
if (oldSmudge.SmudgeType == null)
91+
cell.Smudge = null;
92+
else
93+
cell.Smudge = new Smudge() { SmudgeType = oldSmudge.SmudgeType, Position = oldSmudge.CellCoords };
94+
}
4695

47-
// if oldSmudge is null, then this has the same effect as cell.Smudge = null
48-
// otherwise the smudge is replaced with the old smudge
49-
// iow. we don't need to handle the null case separately
50-
cell.Smudge = oldSmudge;
51-
MutationTarget.AddRefreshPoint(cellCoords, 1);
96+
MutationTarget.AddRefreshPoint(cellCoords, brushSize.Max);
5297
}
5398
}
5499
}

src/TSMapEditor/UI/BrushSize.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,20 @@ public BrushSize(int width, int height)
1313

1414
public int Width { get; }
1515
public int Height { get; }
16+
public int Max => Math.Max(Width, Height);
17+
18+
public Point2D CenterWithinBrush(Point2D point) => new Point2D(point.X - (Width / 2), point.Y - (Height / 2));
1619

1720
public void DoForBrushSize(Action<Point2D> action)
1821
{
1922
DoForArea(0, 0, Height, Width, action);
2023
}
2124

25+
public bool CheckForBrushSize(Func<Point2D, bool> checker)
26+
{
27+
return CheckForAnyInArea(0, 0, Height, Width, checker);
28+
}
29+
2230
public void DoForBrushSizeAndSurroundings(Action<Point2D> action)
2331
{
2432
DoForArea(-1, -1, Height + 1, Width + 1, action);
@@ -35,6 +43,20 @@ private void DoForArea(int initY, int initX, int height, int width, Action<Point
3543
}
3644
}
3745

46+
private bool CheckForAnyInArea(int initY, int initX, int height, int width, Func<Point2D, bool> checker)
47+
{
48+
for (int y = initY; y < height; y++)
49+
{
50+
for (int x = initX; x < width; x++)
51+
{
52+
if (checker(new Point2D(x, y)))
53+
return true;
54+
}
55+
}
56+
57+
return false;
58+
}
59+
3860
public override string ToString()
3961
{
4062
return Width + "x" + Height;

src/TSMapEditor/UI/CursorActions/PlaceSmudgeCursorAction.cs

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using TSMapEditor.GameMath;
1+
using System.Collections.Generic;
2+
using TSMapEditor.GameMath;
23
using TSMapEditor.Models;
34
using TSMapEditor.Mutations.Classes;
45

@@ -8,7 +9,6 @@ public class PlaceSmudgeCursorAction : CursorAction
89
{
910
public PlaceSmudgeCursorAction(ICursorActionTarget cursorActionTarget) : base(cursorActionTarget)
1011
{
11-
previewSmudge = new Smudge();
1212
}
1313

1414
public override string GetName() => Translate("Name", "Place Smudge");
@@ -22,60 +22,93 @@ public SmudgeType SmudgeType
2222
if (value != _smudgeType)
2323
{
2424
_smudgeType = value;
25-
previewSmudge.SmudgeType = value;
26-
}
25+
}
2726
}
2827
}
2928

30-
private Smudge cachedSmudge;
31-
private Smudge previewSmudge;
29+
private List<Smudge> previewSmudges = new List<Smudge>();
30+
private List<Smudge> existingSmudges = new List<Smudge>();
3231

3332
public override void PreMapDraw(Point2D cellCoords)
3433
{
3534
base.PreMapDraw(cellCoords);
36-
37-
var cell = CursorActionTarget.Map.GetTile(cellCoords);
38-
if (cell == null)
39-
return;
40-
41-
previewSmudge.Position = cellCoords;
42-
cachedSmudge = cell.Smudge;
43-
if (SmudgeType != null)
44-
cell.Smudge = previewSmudge;
45-
else
46-
cell.Smudge = null;
47-
48-
CursorActionTarget.AddRefreshPoint(cellCoords, 1);
35+
36+
Point2D centeredBrushSizeCellCoords = CursorActionTarget.BrushSize.CenterWithinBrush(cellCoords);
37+
existingSmudges.Clear();
38+
39+
int i = 0;
40+
CursorActionTarget.BrushSize.DoForBrushSize(offset =>
41+
{
42+
var cell = CursorActionTarget.Map.GetTile(centeredBrushSizeCellCoords + offset);
43+
if (cell == null)
44+
return;
45+
46+
if (previewSmudges.Count <= i)
47+
{
48+
previewSmudges.Add(new Smudge());
49+
}
50+
51+
previewSmudges[i].Position = centeredBrushSizeCellCoords + offset;
52+
previewSmudges[i].SmudgeType = SmudgeType;
53+
existingSmudges.Add(cell.Smudge);
54+
55+
if (SmudgeType != null)
56+
cell.Smudge = previewSmudges[i];
57+
else
58+
cell.Smudge = null;
59+
60+
i++;
61+
});
62+
63+
CursorActionTarget.AddRefreshPoint(centeredBrushSizeCellCoords, CursorActionTarget.BrushSize.Max);
4964
}
5065

5166
public override void PostMapDraw(Point2D cellCoords)
5267
{
5368
base.PostMapDraw(cellCoords);
54-
55-
var cell = CursorActionTarget.Map.GetTile(cellCoords);
56-
if (cell == null)
57-
return;
58-
59-
cell.Smudge = cachedSmudge;
60-
CursorActionTarget.AddRefreshPoint(cellCoords, 1);
69+
70+
Point2D centeredBrushSizeCellCoords = CursorActionTarget.BrushSize.CenterWithinBrush(cellCoords);
71+
72+
int i = 0;
73+
CursorActionTarget.BrushSize.DoForBrushSize(offset =>
74+
{
75+
var cell = CursorActionTarget.Map.GetTile(centeredBrushSizeCellCoords + offset);
76+
if (cell == null)
77+
return;
78+
79+
cell.Smudge = existingSmudges[i];
80+
i++;
81+
});
82+
83+
CursorActionTarget.AddRefreshPoint(centeredBrushSizeCellCoords, CursorActionTarget.BrushSize.Max);
6184
}
6285

6386
public override void LeftClick(Point2D cellCoords)
6487
{
65-
var cell = CursorActionTarget.Map.GetTile(cellCoords);
66-
if (cell == null)
67-
return;
88+
Point2D centeredBrushSizeCellCoords = CursorActionTarget.BrushSize.CenterWithinBrush(cellCoords);
6889

69-
if (cell.Smudge != null && cell.Smudge.SmudgeType == SmudgeType)
90+
if (!CursorActionTarget.BrushSize.CheckForBrushSize(offset =>
91+
{
92+
var cell = CursorActionTarget.Map.GetTile(centeredBrushSizeCellCoords + offset);
93+
if (cell == null)
94+
return false;
95+
96+
if (cell.Smudge != null && cell.Smudge.SmudgeType == SmudgeType)
97+
{
98+
// it's pointless to replace a smudge with another smudge of the same type
99+
return false;
100+
}
101+
102+
if (cell.Smudge == null && SmudgeType == null)
103+
return false; // we're in deletion mode when SmudgeType == null, skip if there's nothing to delete
104+
105+
return true;
106+
}))
70107
{
71-
// it's pointless to replace a smudge with another smudge of the same type
72108
return;
73109
}
74110

75-
if (cell.Smudge == null && SmudgeType == null)
76-
return; // we're in deletion mode when SmudgeType == null, skip if there's nothing to delete
77-
78-
CursorActionTarget.MutationManager.PerformMutation(new PlaceSmudgeMutation(CursorActionTarget.MutationTarget, SmudgeType, cellCoords));
111+
CursorActionTarget.MutationManager.PerformMutation(new PlaceSmudgeMutation(CursorActionTarget.MutationTarget, SmudgeType, centeredBrushSizeCellCoords, CursorActionTarget.BrushSize));
79112
}
80113

81114
public override void LeftDown(Point2D cellCoords) => LeftClick(cellCoords);

0 commit comments

Comments
 (0)