diff --git a/assets/icons/kenney_icons.svg b/assets/icons/kenney_icons.svg
index af02f854..96f5dd92 100644
--- a/assets/icons/kenney_icons.svg
+++ b/assets/icons/kenney_icons.svg
@@ -7,7 +7,7 @@
viewBox="0 0 16.933332 16.933332"
version="1.1"
id="svg1"
- inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
+ inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
sodipodi:docname="kenney_icons.svg"
inkscape:export-batch-path="../../project/assets/icons"
inkscape:export-batch-name=""
@@ -25,9 +25,9 @@
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#2b2b2b"
inkscape:document-units="mm"
- inkscape:zoom="3.9054994"
- inkscape:cx="227.37169"
- inkscape:cy="45.320708"
+ inkscape:zoom="2.7110516"
+ inkscape:cx="344.14689"
+ inkscape:cy="49.058453"
inkscape:current-layer="layer1">
+
@@ -90,5 +99,15 @@
d="m 83.533512,4.9852096 -0.465721,0.864913 -0.02218,0.044357 c -0.931446,1.8481071 -0.850129,3.7331753 0.24395,5.6552054 1.094081,2.010739 2.727806,3.053071 4.901178,3.126996 0.177418,0.01477 0.340054,-0.03695 0.487901,-0.15524 0.133055,-0.118281 0.206989,-0.273521 0.221772,-0.465723 0.162642,-1.064509 0.229166,-1.848108 0.199594,-2.350792 -0.01475,-0.177418 -0.07393,-0.332659 -0.177418,-0.465722 -0.118286,-0.133064 -0.273522,-0.199595 -0.465723,-0.199595 -0.901874,-0.07393 -1.58198,-0.495294 -2.040309,-1.2641061 l 0.02218,0.02218 C 85.995193,9.0584358 85.936054,8.3191961 86.26132,7.5799521 86.690081,6.5745809 87.414537,6.0423263 88.434693,5.9831883 h 0.02218 c 0.724456,-0.014769 1.34542,0.2365561 1.86289,0.7540273 C 89.595307,7.15119 89.08523,7.491243 88.789532,7.7573704 88.671246,7.8608625 88.597331,7.9865371 88.567759,8.134384 l 0.02218,0.4435455 0.310482,0.3326592 6.165284,3.5705423 0.487899,0.06653 c 0.162629,-0.01477 0.303091,-0.08871 0.421372,-0.221774 l 0.155235,-0.443545 -0.02218,-7.2297943 -0.08872,-0.377014 -0.266128,-0.2661273 -0.02218,-0.022179 -0.33266,-0.088715 -0.332658,0.088715 -1.55241,0.8870915 C 92.951448,4.120291 92.323096,3.5436824 91.628207,3.1444914 V 3.1223124 C 90.223644,2.2795748 88.759945,2.0504086 87.237106,2.4348171 85.773406,2.7896524 84.561049,3.617606 83.600033,4.918671 l -0.06654,0.066536"
style="fill:#ffffff;stroke:none;stroke-width:0.264582"
id="path1-9-7" />
+
+
diff --git a/project/assets/icons/delete.png b/project/assets/icons/delete.png
new file mode 100644
index 00000000..2d511233
Binary files /dev/null and b/project/assets/icons/delete.png differ
diff --git a/project/assets/icons/delete.png.import b/project/assets/icons/delete.png.import
new file mode 100644
index 00000000..dfbc423c
--- /dev/null
+++ b/project/assets/icons/delete.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d4gdegb25s1yc"
+path="res://.godot/imported/delete.png-1a1c27a227e9b4f0c6cd8be5e5c0ab16.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/delete.png"
+dest_files=["res://.godot/imported/delete.png-1a1c27a227e9b4f0c6cd8be5e5c0ab16.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/project/assets/icons/duplicate.png b/project/assets/icons/duplicate.png
new file mode 100644
index 00000000..8aa6f4b4
Binary files /dev/null and b/project/assets/icons/duplicate.png differ
diff --git a/project/assets/icons/duplicate.png.import b/project/assets/icons/duplicate.png.import
new file mode 100644
index 00000000..9450b20c
--- /dev/null
+++ b/project/assets/icons/duplicate.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dnkv4js7q0lsd"
+path="res://.godot/imported/duplicate.png-3b4a1d4e14daeab44ffffbdce5245ae9.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/duplicate.png"
+dest_files=["res://.godot/imported/duplicate.png-3b4a1d4e14daeab44ffffbdce5245ae9.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/project/assets/icons/redo.png b/project/assets/icons/redo.png
new file mode 100644
index 00000000..32c65b58
Binary files /dev/null and b/project/assets/icons/redo.png differ
diff --git a/project/assets/icons/redo.png.import b/project/assets/icons/redo.png.import
new file mode 100644
index 00000000..c888a51e
--- /dev/null
+++ b/project/assets/icons/redo.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://po5tk6p4tf2e"
+path="res://.godot/imported/redo.png-f1b4b62c7b0e9b2d396dde66297fc72c.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/redo.png"
+dest_files=["res://.godot/imported/redo.png-f1b4b62c7b0e9b2d396dde66297fc72c.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/project/assets/icons/save.png b/project/assets/icons/save.png
new file mode 100644
index 00000000..2d2759b3
Binary files /dev/null and b/project/assets/icons/save.png differ
diff --git a/project/assets/icons/save.png.import b/project/assets/icons/save.png.import
new file mode 100644
index 00000000..5ea764c3
--- /dev/null
+++ b/project/assets/icons/save.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://duys3jsbt4bwi"
+path="res://.godot/imported/save.png-dcc2a5e33a407ba0416163ad46af5821.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/save.png"
+dest_files=["res://.godot/imported/save.png-dcc2a5e33a407ba0416163ad46af5821.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/project/assets/icons/undo.png b/project/assets/icons/undo.png
new file mode 100644
index 00000000..2db34321
Binary files /dev/null and b/project/assets/icons/undo.png differ
diff --git a/project/assets/icons/undo.png.import b/project/assets/icons/undo.png.import
new file mode 100644
index 00000000..7faed4ec
--- /dev/null
+++ b/project/assets/icons/undo.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://chtokhc0c1t52"
+path="res://.godot/imported/undo.png-be9e5b255e3e404615bebba331e4171e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/undo.png"
+dest_files=["res://.godot/imported/undo.png-be9e5b255e3e404615bebba331e4171e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+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/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+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
diff --git a/project/scenes/editor.tscn b/project/scenes/editor.tscn
index 9e7dc0fd..f57c56bf 100644
--- a/project/scenes/editor.tscn
+++ b/project/scenes/editor.tscn
@@ -5,7 +5,6 @@
[ext_resource type="SaveData" uid="uid://djlwnfbjmjb6a" path="res://default_file.tres" id="3_78fwb"]
[ext_resource type="Theme" uid="uid://dh5hqcu3vyhrh" path="res://editor_theme.tres" id="3_ba0ut"]
[ext_resource type="Texture2D" uid="uid://b8hetdn3d3ysr" path="res://assets/icons/point.svg" id="4_5lcyj"]
-[ext_resource type="Texture2D" uid="uid://bb0mnjwx58nt3" path="res://assets/icons/plus.svg" id="4_q68jb"]
[ext_resource type="Texture2D" uid="uid://bl3gn6qruuy8w" path="res://assets/icons/plane.svg" id="4_xg7d5"]
[ext_resource type="Texture2D" uid="uid://cwl3no6dbtjrf" path="res://assets/icons/save.svg" id="5_74j0u"]
[ext_resource type="Texture2D" uid="uid://d1te42w7wpkrx" path="res://assets/icons/noise.svg" id="5_eqbpn"]
@@ -192,6 +191,7 @@ drag_area_highlight_in_editor = true
layout_mode = 2
size_flags_vertical = 3
current_tab = 0
+tabs_visible = false
[node name="File" type="VBoxContainer" parent="LeftPanel/VBoxContainer/Layers" unique_id=138865385]
layout_mode = 2
@@ -201,13 +201,6 @@ metadata/_tab_index = 0
layout_mode = 2
size_flags_vertical = 8
-[node name="TextureRect" type="TextureRect" parent="LeftPanel/VBoxContainer/Layers/File/HBoxContainer" unique_id=1669840346]
-custom_minimum_size = Vector2(32, 32)
-layout_mode = 2
-texture = ExtResource("4_q68jb")
-expand_mode = 2
-stretch_mode = 4
-
[node name="AddPointPrimitive" type="AddPrimitiveButton" parent="LeftPanel/VBoxContainer/Layers/File/HBoxContainer" unique_id=255935272 node_paths=PackedStringArray("terrain")]
custom_minimum_size = Vector2(32, 32)
layout_mode = 2
diff --git a/project/ui/primitive_inspectors/base_primitive_inspector.tscn b/project/ui/primitive_inspectors/base_primitive_inspector.tscn
index 6cb4246f..d670fc28 100644
--- a/project/ui/primitive_inspectors/base_primitive_inspector.tscn
+++ b/project/ui/primitive_inspectors/base_primitive_inspector.tscn
@@ -2,6 +2,7 @@
[ext_resource type="PackedScene" uid="uid://cwby0in0f2wi2" path="res://ui/editor_elements/float_editor.tscn" id="1_dildi"]
[ext_resource type="Texture2D" uid="uid://bt72qid068u8u" path="res://assets/icons/delete.svg" id="1_h3glg"]
+[ext_resource type="Texture2D" uid="uid://dnkv4js7q0lsd" path="res://assets/icons/duplicate.png" id="3_ivj30"]
[sub_resource type="GDScript" id="GDScript_h3glg"]
resource_name = "BlendModeSelector"
@@ -45,11 +46,15 @@ func _primitive_changed():
$\"../ExpressionError\".text = primitive.get_expression_error()
func _text_changed():
- if not pushing_change:
+ if not pushing_change and has_focus():
+ $ExpressionTimerBuffer.stop()
$ExpressionTimerBuffer.start(0.5)
func _timeout():
- primitive.expression = text
+ if not pushing_change:
+ pushing_change = true
+ primitive.expression = text
+ pushing_change = false
"
[sub_resource type="GDScript" id="GDScript_ivj30"]
@@ -65,6 +70,17 @@ func _pressed() -> void:
terrain.current_selected = null
"
+[sub_resource type="GDScript" id="GDScript_osefh"]
+resource_name = "DuplicatePrimitive"
+script/source = "extends Button
+
+@onready var terrain : TerrainMeshEditor = ($\"../../../..\" as LayerEditor).terrain
+@onready var primitive : TerrainPrimitive = terrain.current_selected
+
+func _pressed() -> void:
+ terrain.add_primitive(primitive.duplicate_deep())
+"
+
[node name="Primitive" type="MarginContainer" unique_id=905749607]
offset_right = 302.0
offset_bottom = 230.0
@@ -112,7 +128,7 @@ script = SubResource("GDScript_h3glg")
[node name="Expression" type="TextEdit" parent="VBoxContainer" unique_id=1154146381]
layout_mode = 2
size_flags_vertical = 3
-placeholder_text = "previous_height * previous_height"
+placeholder_text = "Heightmap Override (float)"
backspace_deletes_composite_character_enabled = true
caret_blink = true
caret_move_on_right_click = false
@@ -121,7 +137,7 @@ draw_spaces = true
script = SubResource("GDScript_2i6ni")
[node name="ExpressionTimerBuffer" type="Timer" parent="VBoxContainer/Expression" unique_id=1376932514]
-wait_time = 2.0
+wait_time = 0.5
[node name="ExpressionError" type="Label" parent="VBoxContainer" unique_id=1840569033]
layout_mode = 2
@@ -131,7 +147,7 @@ text = "Error Text"
layout_mode = 2
alignment = 2
-[node name="Button" type="Button" parent="VBoxContainer/HBoxContainer" unique_id=1514690251]
+[node name="DeleteButton" type="Button" parent="VBoxContainer/HBoxContainer" unique_id=1514690251]
custom_minimum_size = Vector2(32, 32)
layout_mode = 2
icon = ExtResource("1_h3glg")
@@ -139,6 +155,14 @@ icon_alignment = 1
expand_icon = true
script = SubResource("GDScript_ivj30")
+[node name="DuplicateButton" type="Button" parent="VBoxContainer/HBoxContainer" unique_id=1329310966]
+custom_minimum_size = Vector2(32, 32)
+layout_mode = 2
+icon = ExtResource("3_ivj30")
+icon_alignment = 1
+expand_icon = true
+script = SubResource("GDScript_osefh")
+
[connection signal="item_selected" from="VBoxContainer/BlendModeSelector" to="VBoxContainer/BlendModeSelector" method="_on_item_selected"]
[editable path="VBoxContainer/FloatEditor3"]
diff --git a/test-terrains/hills.terrain.res b/test-terrains/hills.terrain.res
index 3a728c7a..e450c91e 100644
Binary files a/test-terrains/hills.terrain.res and b/test-terrains/hills.terrain.res differ