From 81a4f2c83ccfcf1db1b761e07356c6e8889d122a Mon Sep 17 00:00:00 2001 From: Sara Date: Sun, 7 Dec 2025 21:21:17 +0100 Subject: [PATCH] feat: implemented basic primitive tree display --- .../terrain_editor/primitive_layer_list.cpp | 86 +++++++++++++++++++ modules/terrain_editor/primitive_layer_list.h | 26 ++++++ modules/terrain_editor/register_types.cpp | 2 + project/scenes/editor.tscn | 57 +++--------- 4 files changed, 127 insertions(+), 44 deletions(-) create mode 100644 modules/terrain_editor/primitive_layer_list.cpp create mode 100644 modules/terrain_editor/primitive_layer_list.h diff --git a/modules/terrain_editor/primitive_layer_list.cpp b/modules/terrain_editor/primitive_layer_list.cpp new file mode 100644 index 00000000..ee4613fe --- /dev/null +++ b/modules/terrain_editor/primitive_layer_list.cpp @@ -0,0 +1,86 @@ +#include "primitive_layer_list.h" +#include "core/object/object.h" +#include "scene/gui/tree.h" +#include "terrain_editor/macros.h" +#include "terrain_editor/terrain_primitive.h" + +void PrimitiveLayerList::_bind_methods() { + BIND_HPROPERTY(Variant::OBJECT, terrain, PROPERTY_HINT_NODE_TYPE, "TerrainMeshGenerator"); +} + +void PrimitiveLayerList::generate_subtree(size_t idx, Ref prim, TreeItem *parent) { + TreeItem *base{ create_item(get_root()) }; + base->set_text(0, vformat("%d", idx)); + base->set_expand_right(0, false); + base->set_editable(0, true); + base->set_text(1, prim->get_name().is_empty() ? prim->get_class() : prim->get_name()); + base->set_editable(1, true); + base->set_expand_right(1, true); + this->subtrees.insert(prim, base); +} + +void PrimitiveLayerList::regenerate_tree(Array array) { + get_root()->clear_children(); + this->subtrees.clear(); + size_t i{ 0 }; + for (Variant var : array) { + Ref prim{ var }; + if (prim.is_valid()) { + generate_subtree(i, prim, get_root()); + ++i; + } + } +} + +void PrimitiveLayerList::switch_index(size_t from, size_t to) { + Array primitives = this->terrain->get_primitives(); + Ref primitive{ primitives.get(from) }; + primitives.remove_at(from); + if (primitives.size() <= to) { + primitives.push_back(primitive); + } else { + primitives.insert(to, primitive); + } + + this->terrain->set_primitives(primitives); +} + +void PrimitiveLayerList::item_edited() { + TreeItem *edited{ get_edited() }; + switch (get_edited_column()) { + default: + return; + case 0: // index + switch_index(edited->get_index(), edited->get_text(0).to_int()); + return; + case 1: // name + return; + } +} + +void PrimitiveLayerList::_notification(int what) { + if (Engine::get_singleton()->is_editor_hint()) { + return; + } + switch (what) { + default: + return; + case NOTIFICATION_READY: + connect("item_edited", callable_mp(this, &self_type::item_edited)); + create_item(); + set_hide_root(true); + if (this->terrain) { + this->terrain->connect(TerrainMeshGenerator::sig_primitive_list_changed, callable_mp(this, &self_type::regenerate_tree)); + regenerate_tree(this->terrain->get_primitives()); + } + return; + } +} + +void PrimitiveLayerList::set_terrain(TerrainMeshGenerator *terrain) { + this->terrain = terrain; +} + +TerrainMeshGenerator *PrimitiveLayerList::get_terrain() const { + return this->terrain; +} diff --git a/modules/terrain_editor/primitive_layer_list.h b/modules/terrain_editor/primitive_layer_list.h new file mode 100644 index 00000000..d9f4f1d4 --- /dev/null +++ b/modules/terrain_editor/primitive_layer_list.h @@ -0,0 +1,26 @@ +#pragma once + +#include "core/templates/hash_map.h" +#include "scene/gui/tree.h" +#include "terrain_editor/terrain_mesh_generator.h" +#include "terrain_editor/terrain_primitive.h" + +class PrimitiveLayerList : public Tree { + GDCLASS(PrimitiveLayerList, Tree); + static void _bind_methods(); + void generate_subtree(size_t idx, Ref prim, TreeItem *parent); + void regenerate_tree(Array array); + void switch_index(size_t from, size_t to); + void item_edited(); + +protected: + void _notification(int what); + +public: + void set_terrain(TerrainMeshGenerator *generator); + TerrainMeshGenerator *get_terrain() const; + +private: + TerrainMeshGenerator *terrain{}; + HashMap, TreeItem *> subtrees{}; +}; diff --git a/modules/terrain_editor/register_types.cpp b/modules/terrain_editor/register_types.cpp index b9d1604f..712975b5 100644 --- a/modules/terrain_editor/register_types.cpp +++ b/modules/terrain_editor/register_types.cpp @@ -5,6 +5,7 @@ #include "scene/main/scene_tree.h" #include "terrain_editor/edit_history.h" #include "terrain_editor/point_primitive_node.h" +#include "terrain_editor/primitive_layer_list.h" #include "terrain_editor/terrain_chunk.h" #include "terrain_editor/terrain_mesh_editor.h" #include "terrain_editor/terrain_mesh_generator.h" @@ -26,6 +27,7 @@ void initialize_terrain_editor_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); Engine::get_singleton()->add_singleton(Engine::Singleton("EditHistory", (EditHistory::singleton_instance = memnew(EditHistory)), "EditHistory")); + ClassDB::register_class(); } void uninitialize_terrain_editor_module(ModuleInitializationLevel p_level) { diff --git a/project/scenes/editor.tscn b/project/scenes/editor.tscn index 13877512..1cfc8810 100644 --- a/project/scenes/editor.tscn +++ b/project/scenes/editor.tscn @@ -9,7 +9,7 @@ slope = -0.7 height = 0.0 [sub_resource type="PointPrimitive" id="PointPrimitive_ba0ut"] -blend_range = 20.0 +blend_range = 10.0 center = Vector2(50, 0) slope = -0.7 @@ -42,8 +42,8 @@ fractal_weighted_strength = 0.58 blend_mode = 1 noise = SubResource("FastNoiseLite_ba0ut") -[sub_resource type="PlanePrimitive" id="PlanePrimitive_pxqd5"] -blend_range = 10.0 +[sub_resource type="PlanePrimitive" id="PlanePrimitive_ba0ut"] +blend_range = 20.0 baseline = -1.0 [sub_resource type="Gradient" id="Gradient_b1cmn"] @@ -120,20 +120,12 @@ func _unhandled_input(event: InputEvent) -> void: global_position = (global_position - pivot).normalized() * distance + pivot " -[sub_resource type="CylinderMesh" id="CylinderMesh_pxqd5"] - -[sub_resource type="Gradient" id="Gradient_pxqd5"] - -[sub_resource type="GradientTexture2D" id="GradientTexture2D_ba0ut"] -gradient = SubResource("Gradient_pxqd5") - [node name="Editor" type="Node3D" unique_id=1027707839] [node name="TerrainMeshEditor" type="TerrainMeshEditor" parent="." unique_id=1382595562] -primitives = [SubResource("PointPrimitive_pxqd5"), SubResource("PointPrimitive_ba0ut"), SubResource("NoisePrimitive_ba0ut"), SubResource("NoisePrimitive_pxqd5"), SubResource("NoisePrimitive_q68jb"), SubResource("PlanePrimitive_pxqd5")] +primitives = [SubResource("PointPrimitive_pxqd5"), SubResource("PointPrimitive_ba0ut"), SubResource("NoisePrimitive_ba0ut"), SubResource("NoisePrimitive_pxqd5"), SubResource("NoisePrimitive_q68jb"), SubResource("PlanePrimitive_ba0ut")] vertex_color_gradient = SubResource("Gradient_b1cmn") color_gradient_end_height = 100.0 -chunk_count = 15 chunk_scene = ExtResource("1_pxqd5") point_primitive_object = ExtResource("1_b1cmn") @@ -153,14 +145,10 @@ fov = 57.3 far = 2000.0 script = SubResource("GDScript_b1cmn") -[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=613969950] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 7, 0) -mesh = SubResource("CylinderMesh_pxqd5") - [node name="LeftPanel" type="Panel" parent="." unique_id=1768834661] anchors_preset = 9 anchor_bottom = 1.0 -offset_right = 193.0 +offset_right = 258.0 grow_vertical = 2 theme = ExtResource("3_ba0ut") @@ -173,36 +161,17 @@ grow_horizontal = 2 grow_vertical = 2 current_tab = 0 -[node name="ScrollContainer" type="ScrollContainer" parent="LeftPanel/TabContainer" unique_id=1323188283] +[node name="MarginContainer" type="MarginContainer" parent="LeftPanel/TabContainer" unique_id=1533578826] layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 metadata/_tab_index = 0 -[node name="MarginContainer" type="MarginContainer" parent="LeftPanel/TabContainer/ScrollContainer" unique_id=1533578826] +[node name="Tree" type="PrimitiveLayerList" parent="LeftPanel/TabContainer/MarginContainer" unique_id=797700186 node_paths=PackedStringArray("terrain")] layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="VBoxContainer" type="VBoxContainer" parent="LeftPanel/TabContainer/ScrollContainer/MarginContainer" unique_id=326791130] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - -[node name="HBoxContainer" type="HBoxContainer" parent="LeftPanel/TabContainer/ScrollContainer/MarginContainer/VBoxContainer" unique_id=247007395] -layout_mode = 2 -size_flags_vertical = 2 - -[node name="TextureRect" type="TextureRect" parent="LeftPanel/TabContainer/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer" unique_id=313030843] -layout_mode = 2 -size_flags_horizontal = 0 -texture = SubResource("GradientTexture2D_ba0ut") -expand_mode = 2 -stretch_mode = 4 - -[node name="RichTextLabel" type="RichTextLabel" parent="LeftPanel/TabContainer/ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer" unique_id=1765888481] -layout_mode = 2 -size_flags_horizontal = 3 -bbcode_enabled = true -text = "Layer 1" -fit_content = true +columns = 4 +drop_mode_flags = 2 +select_mode = 1 +terrain = NodePath("../../../../TerrainMeshEditor") [connection signal="primitives_changed" from="TerrainMeshEditor" to="TerrainMeshEditor" method="_on_primitives_changed"]