Skip to content

Commit 21ef7b9

Browse files
committed
updated terrain painting controls.
1 parent 2580cc7 commit 21ef7b9

File tree

12 files changed

+259
-132
lines changed

12 files changed

+259
-132
lines changed

src/main/java/com/ss/editor/control/painting/PaintingControl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ default void finishPainting(@NotNull final Vector3f contactPoint) {
5959
* @param contactPoint the contact point.
6060
*/
6161
@JmeThread
62-
default void updateEditing(@NotNull final Vector3f contactPoint) {
62+
default void updatePainting(@NotNull final Vector3f contactPoint) {
6363
}
6464

6565
/**

src/main/java/com/ss/editor/control/painting/terrain/ChangeHeightTerrainToolControl.java

Lines changed: 123 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@
66
import com.jme3.scene.Node;
77
import com.jme3.scene.Spatial;
88
import com.jme3.terrain.Terrain;
9+
import com.ss.editor.annotation.FromAnyThread;
910
import com.ss.editor.annotation.JmeThread;
1011
import com.ss.editor.model.undo.editor.ChangeConsumer;
1112
import com.ss.editor.model.undo.editor.ModelChangeConsumer;
1213
import com.ss.editor.ui.component.painting.terrain.TerrainPaintingComponent;
1314
import com.ss.editor.ui.control.property.operation.PropertyOperation;
15+
import com.ss.editor.util.NodeUtils;
16+
import com.ss.rlib.util.array.Array;
17+
import com.ss.rlib.util.array.ArrayFactory;
18+
import com.ss.rlib.util.dictionary.Dictionary;
1419
import com.ss.rlib.util.dictionary.DictionaryFactory;
1520
import com.ss.rlib.util.dictionary.ObjectDictionary;
1621
import org.jetbrains.annotations.NotNull;
17-
import org.jetbrains.annotations.Nullable;
1822

1923
import java.util.ArrayList;
2024
import java.util.List;
25+
import java.util.function.Supplier;
2126

2227
/**
2328
* The base implementation of tool control to change height of terrain.
@@ -26,6 +31,10 @@
2631
*/
2732
public class ChangeHeightTerrainToolControl extends TerrainToolControl {
2833

34+
@NotNull
35+
private static final Supplier<ObjectDictionary<HeightPoint, Float>> DICTIONARY_FACTORY = () ->
36+
DictionaryFactory.newObjectDictionary(0.2F, 10000);
37+
2938
private static class HeightPoint {
3039

3140
private final float x;
@@ -63,17 +72,25 @@ public int hashCode() {
6372
* The table of original heights.
6473
*/
6574
@NotNull
66-
private final ObjectDictionary<HeightPoint, Float> originalHeight;
75+
private final ObjectDictionary<Terrain, ObjectDictionary<HeightPoint, Float>> originalHeight;
76+
77+
/**
78+
* The table with copied of original terrains.
79+
*/
80+
@NotNull
81+
private final ObjectDictionary<Terrain, Spatial> copiedTerrains;
6782

6883
/**
69-
* The copy of an original terrain.
84+
* The current terrains.
7085
*/
71-
@Nullable
72-
private Spatial copiedTerrain;
86+
@NotNull
87+
private final Array<Terrain> terrains;
7388

7489
public ChangeHeightTerrainToolControl(@NotNull final TerrainPaintingComponent component) {
7590
super(component);
76-
this.originalHeight = DictionaryFactory.newObjectDictionary(0.2F, 1000);
91+
this.originalHeight = DictionaryFactory.newObjectDictionary();
92+
this.copiedTerrains = DictionaryFactory.newObjectDictionary();
93+
this.terrains = ArrayFactory.newArray(Terrain.class);
7794
}
7895

7996
/**
@@ -82,32 +99,74 @@ public ChangeHeightTerrainToolControl(@NotNull final TerrainPaintingComponent co
8299
* @return the table of original heights.
83100
*/
84101
@JmeThread
85-
private @NotNull ObjectDictionary<HeightPoint, Float> getOriginalHeight() {
102+
private @NotNull ObjectDictionary<Terrain, ObjectDictionary<HeightPoint, Float>> getOriginalHeight() {
86103
return originalHeight;
87104
}
88105

106+
/**
107+
* Get the table with copied of original terrains.
108+
*
109+
* @return the table with copied of original terrains.
110+
*/
111+
@JmeThread
112+
private @NotNull ObjectDictionary<Terrain, Spatial> getCopiedTerrains() {
113+
return copiedTerrains;
114+
}
115+
116+
/**
117+
* Get the current terrains.
118+
*
119+
* @return the current terrains.
120+
*/
121+
@JmeThread
122+
protected @NotNull Array<Terrain> getTerrains() {
123+
return terrains;
124+
}
125+
89126
/**
90127
* Start making changes.
91128
*/
92129
@JmeThread
93130
protected void startChange() {
94131

95-
final ObjectDictionary<HeightPoint, Float> originalHeight = getOriginalHeight();
132+
final ObjectDictionary<Terrain, ObjectDictionary<HeightPoint, Float>> originalHeight = getOriginalHeight();
133+
originalHeight.forEach(Dictionary::clear);
96134
originalHeight.clear();
97135

98-
copiedTerrain = notNull(getPaintedModel()).clone();
136+
final Array<Terrain> terrains = getTerrains();
137+
terrains.clear();
138+
139+
NodeUtils.visitSpatial(notNull(getPaintedModel()), spatial -> {
140+
if (spatial instanceof Terrain) {
141+
terrains.add((Terrain) spatial);
142+
return false;
143+
}
144+
return true;
145+
});
146+
147+
final ObjectDictionary<Terrain, Spatial> copiedTerrains = getCopiedTerrains();
148+
copiedTerrains.clear();
149+
150+
terrains.forEach(copiedTerrains, (terrain, toStore) ->
151+
toStore.put(terrain, ((Spatial) terrain).clone()));
152+
}
153+
154+
@JmeThread
155+
@Deprecated
156+
protected void change(@NotNull final Vector2f point) {
157+
change(null, point);
99158
}
100159

101160
/**
102-
* Notify about wanting to change height of a point.
161+
* Notify about changing height by the point in the terrain.
103162
*
104-
* @param point the point.
163+
* @param terrain the terrain.
164+
* @param point the point.
105165
*/
106166
@JmeThread
107-
protected void change(@NotNull final Vector2f point) {
167+
protected void change(@NotNull final Terrain terrain, @NotNull final Vector2f point) {
108168

109-
final Terrain terrain = (Terrain) notNull(copiedTerrain);
110-
final Node terrainNode = (Node) notNull(getPaintedModel());
169+
final Node terrainNode = (Node) terrain;
111170
final Vector3f scale = terrainNode.getWorldScale();
112171

113172
final int halfSize = terrain.getTerrainSize() / 2;
@@ -116,54 +175,80 @@ protected void change(@NotNull final Vector2f point) {
116175

117176
final HeightPoint heightPoint = new HeightPoint(point.getX(), point.getY(), x, z);
118177

119-
final ObjectDictionary<HeightPoint, Float> originalHeight = getOriginalHeight();
120-
if(originalHeight.containsKey(heightPoint)) {
178+
final ObjectDictionary<Terrain, ObjectDictionary<HeightPoint, Float>> originalHeight = getOriginalHeight();
179+
final ObjectDictionary<HeightPoint, Float> terrainHeights = originalHeight.get(terrain, DICTIONARY_FACTORY);
180+
if (terrainHeights.containsKey(heightPoint)) {
121181
return;
122182
}
123183

124184
final float height = terrain.getHeightmapHeight(point);
125-
126-
originalHeight.put(heightPoint, height);
185+
terrainHeights.put(heightPoint, height);
127186
}
128187

129188
/**
130189
* Commit all changes.
131190
*/
132191
protected void commitChanges() {
133192

134-
final Terrain terrain = (Terrain) notNull(getPaintedModel());
135-
final ObjectDictionary<Vector2f, Float> oldValues = DictionaryFactory.newObjectDictionary();
136-
final ObjectDictionary<Vector2f, Float> newValues = DictionaryFactory.newObjectDictionary();
193+
final Spatial paintedModel = getPaintedModel();
194+
final ObjectDictionary<Terrain, ObjectDictionary<Vector2f, Float>> oldValues = DictionaryFactory.newObjectDictionary();
195+
final ObjectDictionary<Terrain, ObjectDictionary<Vector2f, Float>> newValues = DictionaryFactory.newObjectDictionary();
137196

138-
final ObjectDictionary<HeightPoint, Float> originalHeight = getOriginalHeight();
139-
originalHeight.forEach((heightPoint, height) -> oldValues.put(new Vector2f(heightPoint.x, heightPoint.y), height));
140-
originalHeight.forEach((heightPoint, value) -> {
141-
final Vector2f point = new Vector2f(heightPoint.x, heightPoint.y);
142-
newValues.put(point, terrain.getHeightmapHeight(point));
197+
final ObjectDictionary<Terrain, ObjectDictionary<HeightPoint, Float>> originalHeight = getOriginalHeight();
198+
originalHeight.forEach((terrain, floats) -> {
199+
final ObjectDictionary<Vector2f, Float> values = oldValues.get(terrain, () -> createValuesDictionary(floats));
200+
floats.forEach((heightPoint, height) -> values.put(new Vector2f(heightPoint.x, heightPoint.y), height));
143201
});
144202

145-
final PropertyOperation<ChangeConsumer, Terrain, ObjectDictionary<Vector2f, Float>> operation =
146-
new PropertyOperation<>(terrain, "Heightmap", newValues, oldValues);
203+
originalHeight.forEach((terrain, floats) -> {
204+
final ObjectDictionary<Vector2f, Float> values = oldValues.get(terrain, () -> createValuesDictionary(floats));
205+
floats.forEach((heightPoint, height) -> {
206+
final Vector2f point = new Vector2f(heightPoint.x, heightPoint.y);
207+
values.put(point, terrain.getHeightmapHeight(point));
208+
});
209+
});
147210

148-
operation.setApplyHandler((toChange, heightMap) -> {
211+
final Array<Terrain> toApply = ArrayFactory.newArray(Terrain.class);
212+
toApply.addAll(getTerrains());
149213

150-
final List<Vector2f> points = new ArrayList<>(heightMap.size());
151-
final List<Float> heights = new ArrayList<>(heightMap.size());
214+
final PropertyOperation<ChangeConsumer, Spatial, ObjectDictionary<Terrain, ObjectDictionary<Vector2f, Float>>> operation =
215+
new PropertyOperation<>(paintedModel, "Heightmap", newValues, oldValues);
152216

153-
heightMap.forEach((point, height) -> {
154-
points.add(point);
155-
heights.add(height);
156-
});
217+
operation.setApplyHandler((node, heightMaps) -> {
218+
219+
for (final Terrain terrain : toApply) {
220+
221+
final ObjectDictionary<Vector2f, Float> heightData = heightMaps.get(terrain);
222+
if (heightData == null || heightData.isEmpty()) {
223+
continue;
224+
}
225+
226+
final List<Vector2f> points = new ArrayList<>(heightMaps.size());
227+
final List<Float> heights = new ArrayList<>(heightMaps.size());
157228

158-
toChange.setHeight(points, heights);
159-
((Node) toChange).updateModelBound();
229+
heightData.forEach((point, height) -> {
230+
points.add(point);
231+
heights.add(height);
232+
});
233+
234+
terrain.setHeight(points, heights);
235+
}
236+
237+
node.updateModelBound();
160238
});
161239

240+
originalHeight.forEach(Dictionary::clear);
162241
originalHeight.clear();
163242

164243
final ModelChangeConsumer changeConsumer = getChangeConsumer();
165244
changeConsumer.execute(operation);
166245

167-
copiedTerrain = null;
246+
getTerrains().clear();
247+
getCopiedTerrains().clear();
248+
}
249+
250+
@FromAnyThread
251+
private @NotNull ObjectDictionary<Vector2f, Float> createValuesDictionary(@NotNull final ObjectDictionary<HeightPoint, Float> floats) {
252+
return DictionaryFactory.newObjectDictionary(0.2F, floats.size());
168253
}
169254
}

src/main/java/com/ss/editor/control/painting/terrain/LevelTerrainToolControl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.ss.editor.control.painting.terrain;
22

3-
import static com.ss.editor.util.EditingUtils.*;
3+
import static com.ss.editor.util.PaintingUtils.*;
44
import static com.ss.rlib.util.ObjectUtils.notNull;
55
import com.jme3.math.ColorRGBA;
66
import com.jme3.math.Vector2f;
@@ -115,7 +115,7 @@ public void startPainting(@NotNull final PaintingInput paintingInput, @NotNull f
115115
}
116116

117117
@Override
118-
public void updateEditing(@NotNull final Vector3f contactPoint) {
118+
public void updatePainting(@NotNull final Vector3f contactPoint) {
119119

120120
final PaintingInput paintingInput = notNull(getCurrentInput());
121121

src/main/java/com/ss/editor/control/painting/terrain/PaintTerrainToolControl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public void startPainting(@NotNull final PaintingInput paintingInput, @NotNull f
157157
}
158158

159159
@Override
160-
public void updateEditing(@NotNull final Vector3f contactPoint) {
160+
public void updatePainting(@NotNull final Vector3f contactPoint) {
161161

162162
final PaintingInput currentInput = notNull(getCurrentInput());
163163

0 commit comments

Comments
 (0)