Changes to terrain editing controls

- Added new buttons:
  - Flatten tool mode (not implemented)
  - Up / down toggle modifier
    Switches between moving terrain up or down
  - Connected toggle modifier
    Used to cause corners to be disconnected
- Added ModifierToggleButton script
  Inversed by holding modifier button
- "Corner" tool shape button switches
  to single tile texture in paint mode
- Modify editing code to use modifier buttons
main
copygirl 3 months ago
parent 5541872d20
commit be477542b8
  1. BIN
      assets/textures/terrain/editing/connected_off.png
  2. 34
      assets/textures/terrain/editing/connected_off.png.import
  3. BIN
      assets/textures/terrain/editing/connected_on.png
  4. 34
      assets/textures/terrain/editing/connected_on.png.import
  5. 2
      assets/textures/terrain/editing/corner.png.import
  6. BIN
      assets/textures/terrain/editing/corner_paint.png
  7. 34
      assets/textures/terrain/editing/corner_paint.png.import
  8. BIN
      assets/textures/terrain/editing/flatten.png
  9. 34
      assets/textures/terrain/editing/flatten.png.import
  10. BIN
      assets/textures/terrain/editing/height_down.png
  11. 34
      assets/textures/terrain/editing/height_down.png.import
  12. BIN
      assets/textures/terrain/editing/height_up.png
  13. 34
      assets/textures/terrain/editing/height_up.png.import
  14. 17
      terrain/editing/ModifierToggleButton.cs
  15. 54
      terrain/editing/TerrainEditingControls+Editing.cs
  16. 25
      terrain/editing/TerrainEditingControls.cs
  17. 44
      terrain/editing/TerrainEditingControls.tscn

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c5j5v62f7p6qt"
path="res://.godot/imported/connected_off.png-9d4314286cb3dda8aeb51987f4722c68.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/connected_off.png"
dest_files=["res://.godot/imported/connected_off.png-9d4314286cb3dda8aeb51987f4722c68.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dsbovbbrtuv8f"
path="res://.godot/imported/connected_on.png-d142e6ffef231eda75d9207321617fb4.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/connected_on.png"
dest_files=["res://.godot/imported/connected_on.png-d142e6ffef231eda75d9207321617fb4.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

@ -31,4 +31,4 @@ process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
detect_3d/compress_to=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dc0q2xn2cgcjw"
path="res://.godot/imported/corner_paint.png-d3f97054fffda3dc2896d8416d2182b9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/corner_paint.png"
dest_files=["res://.godot/imported/corner_paint.png-d3f97054fffda3dc2896d8416d2182b9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bcb8w33ns56go"
path="res://.godot/imported/flatten.png-f2f312eef574983bc85e28cb99e262b2.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/flatten.png"
dest_files=["res://.godot/imported/flatten.png-f2f312eef574983bc85e28cb99e262b2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://covyafauwthij"
path="res://.godot/imported/height_down.png-47ae6eeb5feb0ddf7bd952befb4351fe.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/height_down.png"
dest_files=["res://.godot/imported/height_down.png-47ae6eeb5feb0ddf7bd952befb4351fe.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dxbfohim13ti1"
path="res://.godot/imported/height_up.png-d84180c0cff17a8285e5e5cb8f54e819.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/textures/terrain/editing/height_up.png"
dest_files=["res://.godot/imported/height_up.png-d84180c0cff17a8285e5e5cb8f54e819.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

@ -0,0 +1,17 @@
[Tool]
public partial class ModifierToggleButton : Button
{
[Export] public Texture2D OnTexture { get; set; }
[Export] public Texture2D OffTexture { get; set; }
[Export] public Key ModifierKey { get; set; }
public override void _Ready()
=> Toggled += (on) => Icon = on ? OnTexture : OffTexture;
public override void _Input(InputEvent ev)
{
if ((ev is InputEventKey { Keycode: var key }) && (key == ModifierKey))
ButtonPressed = !ButtonPressed;
}
}

@ -74,43 +74,43 @@ public partial class TerrainEditingControls
_ => throw new InvalidOperationException(),
}).ToHashSet();
// TODO: Handle different tool modes, such as painting.
// TODO: Add a flatten tool mode: Flattens everything selected to nearest corner height.
// TODO: Handle different tool modes, such as flatten and painting.
// TODO: Allow click-dragging which doesn't affect already changed tiles / corners.
// TODO: Support undo and redo.
// TODO: Support "disconnected" mode which can create vertical cliffs.
// TODO: Make mesh generation generate vertical walls between disconnected corners.
// TODO: Use ArrayMesh instead of ImmediateMesh.
// Raise / lower the terrain if left / right mouse button is pressed.
if ((mouse is InputEventMouseButton { ButtonIndex: var button, Pressed: true })
&& (button is MouseButton.Left or MouseButton.Right))
{
if (mouse is InputEventMouseButton { ButtonIndex: MouseButton.Left, Pressed: true }) {
GetViewport().SetInputAsHandled();
const float AdjustHeight = 0.5f;
var amount = (button == MouseButton.Left)
? AdjustHeight : -AdjustHeight;
// Find corners that are "connected" and should be raised.
var corners = new HashSet<(TilePos Position, Corner Corner)>();
foreach (var pos in tiles) {
var tile2 = terrain.GetTile(pos);
foreach (var corner2 in Enum.GetValues<Corner>()) {
var height = tile2.Height[corner2];
foreach (var (neighborPos, neighborCorner) in GetNeighbors(pos, corner2)) {
if (tiles.Contains(neighborPos)) continue;
var neighborHeight = terrain.GetTile(neighborPos).Height[neighborCorner];
if (neighborHeight == height) corners.Add((neighborPos, neighborCorner));
var amount = UpDownToggle.ButtonPressed ? AdjustHeight : -AdjustHeight;
// 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.
if (ConnectedToggle.ButtonPressed) {
var corners = new HashSet<(TilePos Position, Corner Corner)>();
foreach (var pos in tiles) {
var tile2 = terrain.GetTile(pos);
foreach (var corner2 in Enum.GetValues<Corner>()) {
var height = tile2.Height[corner2];
foreach (var (neighborPos, neighborCorner) in GetNeighbors(pos, corner2)) {
if (tiles.Contains(neighborPos)) continue;
var neighborHeight = terrain.GetTile(neighborPos).Height[neighborCorner];
if (neighborHeight == height) corners.Add((neighborPos, neighborCorner));
}
}
}
}
// Raise connected corners.
foreach (var group in corners.GroupBy(e => e.Position, e => e.Corner)) {
var pos = group.Key;
var tile2 = terrain.GetTile(pos);
foreach (var corner2 in group)
tile2.Height[corner2] += amount;
terrain.SetTile(pos, tile2);
// Raise connected corners.
foreach (var group in corners.GroupBy(e => e.Position, e => e.Corner)) {
var pos = group.Key;
var tile2 = terrain.GetTile(pos);
foreach (var corner2 in group)
tile2.Height[corner2] += amount;
terrain.SetTile(pos, tile2);
}
}
// Raise selected tiles themselves.

@ -4,19 +4,26 @@ public partial class TerrainEditingControls
{
public (ToolMode , Button)[] ToolModeButtons { get; private set; }
public (ToolShape, Button)[] ToolShapeButtons { get; private set; }
public Button[] PaintTextureButtons { get; private set; }
public Slider DrawSizeSlider { get; private set; }
public Button[] PaintTextureButtons { get; private set; }
public Button UpDownToggle { get; private set; }
public Button ConnectedToggle { get; private set; }
public ToolMode ToolMode { get => GetToolMode (); set => SetToolMode (value); }
public ToolShape ToolShape { get => GetToolShape(); set => SetToolShape(value); }
public int DrawSize { get => GetDrawSize (); set => SetDrawSize (value); }
public int Texture { get => GetTexture (); set => SetTexture (value); }
[Export] public Texture2D CornerTextureNormal { get; set; }
[Export] public Texture2D CornerTexturePaint { get; set; }
public override void _Ready()
{
ToolModeButtons = [
(ToolMode.Height, GetNode<Button>("Height")),
(ToolMode.Paint , GetNode<Button>("Paint" )),
(ToolMode.Height , GetNode<Button>("Height" )),
(ToolMode.Flatten, GetNode<Button>("Flatten")),
(ToolMode.Paint , GetNode<Button>("Paint" )),
];
ToolShapeButtons = [
(ToolShape.Corner, GetNode<Button>("Corner")),
@ -40,6 +47,9 @@ public partial class TerrainEditingControls
var drawSizeLabel = GetNode<Label>("SizeLabel");
DrawSizeSlider = GetNode<Slider>("SizeSlider");
DrawSizeSlider.ValueChanged += (_) => drawSizeLabel.Text = $"{DrawSize}";
UpDownToggle = GetNode<Button>("UpDown");
ConnectedToggle = GetNode<Button>("Connected");
}
ToolMode GetToolMode()
@ -51,6 +61,14 @@ public partial class TerrainEditingControls
button.Flat = !(button.ButtonPressed = value == mode);
foreach (var button in PaintTextureButtons)
button.Disabled = value != ToolMode.Paint;
// In paint mode, `ToolShape.Corner` affects a single tile regardless
// of `DrawSize`. This changes the button's icon to communicate that.
ToolShapeButtons[0].Item2.Icon = (value != ToolMode.Paint)
? CornerTextureNormal : CornerTexturePaint;
UpDownToggle.Disabled = value is ToolMode.Flatten or ToolMode.Paint;
ConnectedToggle.Disabled = value is ToolMode.Paint;
}
ToolShape GetToolShape()
@ -88,6 +106,7 @@ public partial class TerrainEditingControls
public enum ToolMode
{
Height,
Flatten,
Paint,
}

@ -1,11 +1,18 @@
[gd_scene load_steps=15 format=3 uid="uid://bmljchm3fj42"]
[gd_scene load_steps=18 format=3 uid="uid://bmljchm3fj42"]
[ext_resource type="Script" path="res://terrain/editing/TerrainEditingControls.cs" id="1_fklx3"]
[ext_resource type="Texture2D" uid="uid://btl3jsqeldix2" path="res://assets/textures/terrain/editing/corner.png" id="1_w5qr7"]
[ext_resource type="Script" path="res://terrain/editing/ModifierToggleButton.cs" id="9_7fwmx"]
[ext_resource type="Texture2D" uid="uid://dqbtbf8pe05qv" path="res://assets/textures/terrain/editing/height.png" id="2_hrmm4"]
[ext_resource type="Texture2D" uid="uid://2u1ldmh0osbx" path="res://assets/textures/terrain/editing/circle.png" id="2_yvc34"]
[ext_resource type="Texture2D" uid="uid://bcb8w33ns56go" path="res://assets/textures/terrain/editing/flatten.png" id="3_gvr2t"]
[ext_resource type="Texture2D" uid="uid://btdpyu4n3pgkx" path="res://assets/textures/terrain/editing/paint.png" id="3_5x55r"]
[ext_resource type="Texture2D" uid="uid://btl3jsqeldix2" path="res://assets/textures/terrain/editing/corner.png" id="1_w5qr7"]
[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://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_up.png" id="9_u4loi"]
[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://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://bpo7mkr6sctqr" path="res://assets/textures/terrain/dirt.png" id="Image_y3rra"]
[ext_resource type="Image" uid="uid://dqyqg6yt7yk3k" path="res://assets/textures/terrain/rock.png" id="Image_x8cdn"]
@ -25,6 +32,8 @@ image = ExtResource("Image_sb66e")
[node name="TerrainEditingControls" type="VBoxContainer"]
script = ExtResource("1_fklx3")
CornerTextureNormal = ExtResource("1_w5qr7")
CornerTexturePaint = ExtResource("3_e00xo")
[node name="Height" type="Button" parent="."]
layout_mode = 2
@ -32,6 +41,12 @@ toggle_mode = true
button_pressed = true
icon = ExtResource("2_hrmm4")
[node name="Flatten" type="Button" parent="."]
layout_mode = 2
toggle_mode = true
icon = ExtResource("3_gvr2t")
flat = true
[node name="Paint" type="Button" parent="."]
layout_mode = 2
toggle_mode = true
@ -76,6 +91,29 @@ value = -1.0
[node name="HSeparator2" type="HSeparator" parent="."]
layout_mode = 2
[node name="UpDown" type="Button" parent="."]
layout_mode = 2
toggle_mode = true
button_pressed = true
icon = ExtResource("9_u4loi")
script = ExtResource("9_7fwmx")
OnTexture = ExtResource("9_u4loi")
OffTexture = ExtResource("10_owj33")
ModifierKey = 4194325
[node name="Connected" type="Button" parent="."]
layout_mode = 2
toggle_mode = true
button_pressed = true
icon = ExtResource("8_4qifu")
script = ExtResource("9_7fwmx")
OnTexture = ExtResource("8_4qifu")
OffTexture = ExtResource("12_5hs2d")
ModifierKey = 4194326
[node name="HSeparator3" type="HSeparator" parent="."]
layout_mode = 2
[node name="Grass" type="Button" parent="."]
layout_mode = 2
theme_override_colors/icon_normal_color = Color(0.752941, 0.752941, 0.752941, 1)

Loading…
Cancel
Save