Compare commits

..

No commits in common. 'aff3c22d220c0e2d3d1086e1b36fd29ad00554a0' and 'be477542b8c3fbe5d97ccf355093066bc8ca4db7' have entirely different histories.

  1. 1
      addons/terrain-editing/terrain_editing_plugin.gd
  2. 0
      assets/textures/terrain/editing/height_down.png
  3. 6
      assets/textures/terrain/editing/height_down.png.import
  4. 0
      assets/textures/terrain/editing/height_up.png
  5. 6
      assets/textures/terrain/editing/height_up.png.import
  6. 3
      terrain/Tile.cs
  7. 98
      terrain/editing/TerrainEditingControls+Editing.cs
  8. 6
      terrain/editing/TerrainEditingControls.cs
  9. 6
      terrain/editing/TerrainEditingControls.tscn

@ -20,7 +20,6 @@ func _make_visible(visible: bool) -> void:
if not controls: if not controls:
var controls_scene = load("res://terrain/editing/TerrainEditingControls.tscn") var controls_scene = load("res://terrain/editing/TerrainEditingControls.tscn")
controls = controls_scene.instantiate() controls = controls_scene.instantiate()
controls.EditorUndoRedo = get_undo_redo()
add_control_to_container(CONTAINER, controls) add_control_to_container(CONTAINER, controls)
elif controls and controls.get_parent(): elif controls and controls.get_parent():
remove_control_from_container(CONTAINER, controls) remove_control_from_container(CONTAINER, controls)

Before

Width:  |  Height:  |  Size: 135 B

After

Width:  |  Height:  |  Size: 135 B

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://covyafauwthij" uid="uid://covyafauwthij"
path="res://.godot/imported/height_lower.png-d00d3c7062c0a355f5c8381ee7e664da.ctex" path="res://.godot/imported/height_down.png-47ae6eeb5feb0ddf7bd952befb4351fe.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://assets/textures/terrain/editing/height_lower.png" source_file="res://assets/textures/terrain/editing/height_down.png"
dest_files=["res://.godot/imported/height_lower.png-d00d3c7062c0a355f5c8381ee7e664da.ctex"] dest_files=["res://.godot/imported/height_down.png-47ae6eeb5feb0ddf7bd952befb4351fe.ctex"]
[params] [params]

Before

Width:  |  Height:  |  Size: 149 B

After

Width:  |  Height:  |  Size: 149 B

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://dxbfohim13ti1" uid="uid://dxbfohim13ti1"
path="res://.godot/imported/height_raise.png-a5718ceb2e90ce17597f6300a0a9a715.ctex" path="res://.godot/imported/height_up.png-d84180c0cff17a8285e5e5cb8f54e819.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://assets/textures/terrain/editing/height_raise.png" source_file="res://assets/textures/terrain/editing/height_up.png"
dest_files=["res://.godot/imported/height_raise.png-a5718ceb2e90ce17597f6300a0a9a715.ctex"] dest_files=["res://.godot/imported/height_up.png-d84180c0cff17a8285e5e5cb8f54e819.ctex"]
[params] [params]

@ -90,9 +90,6 @@ public struct Corners<T>(T topLeft, T topRight, T bottomRight, T bottomLeft)
public T BottomRight = bottomRight; public T BottomRight = bottomRight;
public T BottomLeft = bottomLeft; public T BottomLeft = bottomLeft;
public Corners(T value)
: this(value, value, value, value) { }
public T this[Corner corner] { public T this[Corner corner] {
readonly get => corner switch { readonly get => corner switch {
Corner.TopLeft => TopLeft, Corner.TopLeft => TopLeft,

@ -1,10 +1,5 @@
using System.IO;
public partial class TerrainEditingControls public partial class TerrainEditingControls
{ {
// Set by the terrain editing plugin.
public EditorUndoRedoManager EditorUndoRedo { get; set; }
Terrain _currentTerrain = null; Terrain _currentTerrain = null;
Material _editToolMaterial; Material _editToolMaterial;
@ -81,6 +76,7 @@ public partial class TerrainEditingControls
// TODO: Handle different tool modes, such as flatten and painting. // TODO: Handle different tool modes, such as flatten and painting.
// TODO: Allow click-dragging which doesn't affect already changed tiles / corners. // TODO: Allow click-dragging which doesn't affect already changed tiles / corners.
// TODO: Support undo and redo.
// TODO: Make mesh generation generate vertical walls between disconnected corners. // TODO: Make mesh generation generate vertical walls between disconnected corners.
// TODO: Use ArrayMesh instead of ImmediateMesh. // TODO: Use ArrayMesh instead of ImmediateMesh.
@ -88,16 +84,13 @@ public partial class TerrainEditingControls
if (mouse is InputEventMouseButton { ButtonIndex: MouseButton.Left, Pressed: true }) { if (mouse is InputEventMouseButton { ButtonIndex: MouseButton.Left, Pressed: true }) {
GetViewport().SetInputAsHandled(); GetViewport().SetInputAsHandled();
var cornersToChange = new HashSet<(TilePos Position, Corner Corner)>(); const float AdjustHeight = 0.5f;
var amount = UpDownToggle.ButtonPressed ? AdjustHeight : -AdjustHeight;
// Raise selected tiles themselves.
foreach (var pos in tiles)
foreach (var corner2 in Enum.GetValues<Corner>())
cornersToChange.Add((pos, corner2));
// If the Connected toggle button is active, move "connected" corners. // If the Connected toggle button is active, move "connected" corners.
// Connected corners are the ones that are at the same height as ones already being moved. // Connected corners are the ones that are at the same height as ones already being moved.
if (ConnectedToggle.ButtonPressed) { if (ConnectedToggle.ButtonPressed) {
var corners = new HashSet<(TilePos Position, Corner Corner)>();
foreach (var pos in tiles) { foreach (var pos in tiles) {
var tile2 = terrain.GetTile(pos); var tile2 = terrain.GetTile(pos);
foreach (var corner2 in Enum.GetValues<Corner>()) { foreach (var corner2 in Enum.GetValues<Corner>()) {
@ -105,48 +98,30 @@ public partial class TerrainEditingControls
foreach (var (neighborPos, neighborCorner) in GetNeighbors(pos, corner2)) { foreach (var (neighborPos, neighborCorner) in GetNeighbors(pos, corner2)) {
if (tiles.Contains(neighborPos)) continue; if (tiles.Contains(neighborPos)) continue;
var neighborHeight = terrain.GetTile(neighborPos).Height[neighborCorner]; var neighborHeight = terrain.GetTile(neighborPos).Height[neighborCorner];
if (neighborHeight == height) cornersToChange.Add((neighborPos, neighborCorner)); if (neighborHeight == height) corners.Add((neighborPos, neighborCorner));
}
} }
} }
} }
var isFlatten = ToolMode == ToolMode.Flatten; // Raise connected corners.
var isRaise = RaiseLowerToggle.ButtonPressed; foreach (var group in corners.GroupBy(e => e.Position, e => e.Corner)) {
const float AdjustHeight = 0.5f;
var amount = isFlatten ? terrain.GetTile(tile).Height[corner]
: isRaise ? AdjustHeight : -AdjustHeight;
var tilesPrevious = new List<(TilePos, Corners<float>)>();
var tilesChanged = new List<(TilePos, Corners<float>)>();
foreach (var group in cornersToChange.GroupBy(c => c.Position, c => c.Corner)) {
var pos = group.Key; var pos = group.Key;
var tile2 = terrain.GetTile(pos); var tile2 = terrain.GetTile(pos);
tilesPrevious.Add((pos, tile2.Height)); foreach (var corner2 in group)
tile2.Height[corner2] += amount;
var newHeight = tile2.Height; terrain.SetTile(pos, tile2);
foreach (var corner2 in group) {
if (isFlatten) newHeight[corner2] = amount;
else newHeight[corner2] += amount;
} }
tilesChanged.Add((pos, newHeight));
} }
if (EditorUndoRedo is EditorUndoRedoManager undo) { // Raise selected tiles themselves.
var name = "Modify terrain"; // TODO: Change name depending on tool mode. foreach (var pos in tiles) {
undo.CreateAction(name, customContext: terrain, backwardUndoOps: false); var tile2 = terrain.GetTile(pos);
tile2.Height.Adjust(amount);
undo.AddDoMethod(this, nameof(TerrainModifyHeight), terrain, Pack(tilesChanged)); terrain.SetTile(pos, tile2);
undo.AddDoMethod(terrain, GodotObject.MethodName.NotifyPropertyListChanged);
undo.AddDoMethod(terrain, nameof(Terrain.UpdateMeshAndShape));
undo.AddUndoMethod(this, nameof(TerrainModifyHeight), terrain, Pack(tilesPrevious));
undo.AddUndoMethod(terrain, GodotObject.MethodName.NotifyPropertyListChanged);
undo.AddUndoMethod(terrain, nameof(Terrain.UpdateMeshAndShape));
undo.CommitAction(true);
} }
terrain.UpdateMeshAndShape();
terrain.NotifyPropertyListChanged();
} }
UpdateEditToolMesh(terrain, tiles); UpdateEditToolMesh(terrain, tiles);
@ -156,43 +131,6 @@ public partial class TerrainEditingControls
} }
} }
public void TerrainModifyHeight(Terrain terrain, byte[] data)
{
foreach (var (pos, corners) in Unpack(data)) {
var tile = terrain.GetTile(pos);
tile.Height = corners;
terrain.SetTile(pos, tile);
}
}
static byte[] Pack(IEnumerable<(TilePos Position, Corners<float> Corners)> data) {
using var stream = new MemoryStream();
using var writer = new BinaryWriter(stream);
foreach (var (pos, corners) in data) {
writer.Write(pos.X);
writer.Write(pos.Y);
writer.Write(corners.TopLeft);
writer.Write(corners.TopRight);
writer.Write(corners.BottomRight);
writer.Write(corners.BottomLeft);
}
return stream.ToArray();
}
static IEnumerable<(TilePos Position, Corners<float> Corners)> Unpack(byte[] data)
{
using var stream = new MemoryStream(data);
using var reader = new BinaryReader(stream);
while (stream.Position < stream.Length) {
var x = reader.ReadInt32();
var y = reader.ReadInt32();
var corners = new Corners<float>(
reader.ReadSingle(), reader.ReadSingle(),
reader.ReadSingle(), reader.ReadSingle());
yield return (new(x, y), corners);
}
}
void UpdateEditToolMesh(Terrain terrain, IEnumerable<TilePos> tiles) void UpdateEditToolMesh(Terrain terrain, IEnumerable<TilePos> tiles)
{ {
if (terrain != _currentTerrain) ClearEditToolMesh(); if (terrain != _currentTerrain) ClearEditToolMesh();

@ -7,7 +7,7 @@ public partial class TerrainEditingControls
public Slider DrawSizeSlider { get; private set; } public Slider DrawSizeSlider { get; private set; }
public Button[] PaintTextureButtons { get; private set; } public Button[] PaintTextureButtons { get; private set; }
public Button RaiseLowerToggle { get; private set; } public Button UpDownToggle { get; private set; }
public Button ConnectedToggle { get; private set; } public Button ConnectedToggle { get; private set; }
public ToolMode ToolMode { get => GetToolMode (); set => SetToolMode (value); } public ToolMode ToolMode { get => GetToolMode (); set => SetToolMode (value); }
@ -48,7 +48,7 @@ public partial class TerrainEditingControls
DrawSizeSlider = GetNode<Slider>("SizeSlider"); DrawSizeSlider = GetNode<Slider>("SizeSlider");
DrawSizeSlider.ValueChanged += (_) => drawSizeLabel.Text = $"{DrawSize}"; DrawSizeSlider.ValueChanged += (_) => drawSizeLabel.Text = $"{DrawSize}";
RaiseLowerToggle = GetNode<Button>("RaiseLower"); UpDownToggle = GetNode<Button>("UpDown");
ConnectedToggle = GetNode<Button>("Connected"); ConnectedToggle = GetNode<Button>("Connected");
} }
@ -67,7 +67,7 @@ public partial class TerrainEditingControls
ToolShapeButtons[0].Item2.Icon = (value != ToolMode.Paint) ToolShapeButtons[0].Item2.Icon = (value != ToolMode.Paint)
? CornerTextureNormal : CornerTexturePaint; ? CornerTextureNormal : CornerTexturePaint;
RaiseLowerToggle.Disabled = value is ToolMode.Flatten or ToolMode.Paint; UpDownToggle.Disabled = value is ToolMode.Flatten or ToolMode.Paint;
ConnectedToggle.Disabled = value is ToolMode.Paint; ConnectedToggle.Disabled = value is ToolMode.Paint;
} }

@ -9,8 +9,8 @@
[ext_resource type="Texture2D" uid="uid://dc0q2xn2cgcjw" path="res://assets/textures/terrain/editing/corner_paint.png" id="3_e00xo"] [ext_resource type="Texture2D" uid="uid://dc0q2xn2cgcjw" path="res://assets/textures/terrain/editing/corner_paint.png" id="3_e00xo"]
[ext_resource type="Texture2D" uid="uid://2u1ldmh0osbx" path="res://assets/textures/terrain/editing/circle.png" id="2_yvc34"] [ext_resource type="Texture2D" uid="uid://2u1ldmh0osbx" path="res://assets/textures/terrain/editing/circle.png" id="2_yvc34"]
[ext_resource type="Texture2D" uid="uid://btjd1704xtdjv" path="res://assets/textures/terrain/editing/square.png" id="3_aaaoe"] [ext_resource type="Texture2D" uid="uid://btjd1704xtdjv" path="res://assets/textures/terrain/editing/square.png" id="3_aaaoe"]
[ext_resource type="Texture2D" uid="uid://dxbfohim13ti1" path="res://assets/textures/terrain/editing/height_raise.png" id="9_u4loi"] [ext_resource type="Texture2D" uid="uid://dxbfohim13ti1" path="res://assets/textures/terrain/editing/height_up.png" id="9_u4loi"]
[ext_resource type="Texture2D" uid="uid://covyafauwthij" path="res://assets/textures/terrain/editing/height_lower.png" id="10_owj33"] [ext_resource type="Texture2D" uid="uid://covyafauwthij" path="res://assets/textures/terrain/editing/height_down.png" id="10_owj33"]
[ext_resource type="Texture2D" uid="uid://dsbovbbrtuv8f" path="res://assets/textures/terrain/editing/connected_on.png" id="8_4qifu"] [ext_resource type="Texture2D" uid="uid://dsbovbbrtuv8f" path="res://assets/textures/terrain/editing/connected_on.png" id="8_4qifu"]
[ext_resource type="Texture2D" uid="uid://c5j5v62f7p6qt" path="res://assets/textures/terrain/editing/connected_off.png" id="12_5hs2d"] [ext_resource type="Texture2D" uid="uid://c5j5v62f7p6qt" path="res://assets/textures/terrain/editing/connected_off.png" id="12_5hs2d"]
[ext_resource type="Image" uid="uid://b0jp1dyxugbr7" path="res://assets/textures/terrain/grass.png" id="Image_d41co"] [ext_resource type="Image" uid="uid://b0jp1dyxugbr7" path="res://assets/textures/terrain/grass.png" id="Image_d41co"]
@ -91,7 +91,7 @@ value = -1.0
[node name="HSeparator2" type="HSeparator" parent="."] [node name="HSeparator2" type="HSeparator" parent="."]
layout_mode = 2 layout_mode = 2
[node name="RaiseLower" type="Button" parent="."] [node name="UpDown" type="Button" parent="."]
layout_mode = 2 layout_mode = 2
toggle_mode = true toggle_mode = true
button_pressed = true button_pressed = true

Loading…
Cancel
Save