From b1e386fd735f46265854cefec514e99e82cb8f46 Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 5 Feb 2025 14:01:01 +0100 Subject: [PATCH] Implemented the TerrainWorldGizmo. --- .../terraman/editor/terrain_world_editor.cpp | 106 ++++++++++++++++++ .../terraman/editor/terrain_world_editor.h | 7 ++ .../terraman/editor/terrain_world_gizmo.cpp | 88 +++++++++++---- modules/terraman/editor/terrain_world_gizmo.h | 16 ++- .../editor/terrain_world_gizmo_plugin.cpp | 3 +- .../editor/terrain_world_gizmo_plugin.h | 1 - 6 files changed, 188 insertions(+), 33 deletions(-) diff --git a/modules/terraman/editor/terrain_world_editor.cpp b/modules/terraman/editor/terrain_world_editor.cpp index 525662930..19053ff99 100644 --- a/modules/terraman/editor/terrain_world_editor.cpp +++ b/modules/terraman/editor/terrain_world_editor.cpp @@ -38,6 +38,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "terrain_world_gizmo.h" #include "terrain_world_gizmo_plugin.h" #include "../world/terrain_world.h" @@ -79,6 +80,42 @@ EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Came if (mm.is_valid()) { if (!_mouse_down) { + switch (_tool_mode) { + case TOOL_MODE_ADD: + case TOOL_MODE_REMOVE: { + } break; + case TOOL_MODE_ISOLEVEL_BRUSH: { + Vector3 position; + Vector3 normal; + + if (get_draw_world_coordinate(p_camera, Point2(mm->get_position().x, mm->get_position().y), position, normal)) { + _gizmo->visible = true; + _gizmo->drawing = false; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + } else { + _gizmo->visible = false; + _gizmo->redraw(); + } + } break; + case TOOL_MODE_PAINT_BRUSH: { + Vector3 position; + Vector3 normal; + + if (get_draw_world_coordinate(p_camera, Point2(mm->get_position().x, mm->get_position().y), position, normal)) { + _gizmo->visible = true; + _gizmo->drawing = false; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + } else { + _gizmo->visible = false; + _gizmo->redraw(); + } + } break; + case TOOL_MODE_PAINT_PICKER: { + } break; + } + return EditorPlugin::AFTER_GUI_INPUT_PASS; } @@ -92,6 +129,14 @@ EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Came if (get_draw_world_coordinate(p_camera, Point2(mm->get_position().x, mm->get_position().y), position, normal)) { isolevel_brush_draw(position); + + _gizmo->visible = true; + _gizmo->drawing = true; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + } else { + _gizmo->visible = false; + _gizmo->redraw(); } } break; case TOOL_MODE_PAINT_BRUSH: { @@ -100,6 +145,14 @@ EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Came if (get_draw_world_coordinate(p_camera, Point2(mm->get_position().x, mm->get_position().y), position, normal)) { paint_brush_draw(position); + + _gizmo->visible = true; + _gizmo->drawing = true; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + } else { + _gizmo->visible = false; + _gizmo->redraw(); } } break; case TOOL_MODE_PAINT_PICKER: { @@ -127,8 +180,16 @@ EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Came isolevel_brush_draw(position); + _gizmo->visible = true; + _gizmo->drawing = true; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + return EditorPlugin::AFTER_GUI_INPUT_STOP; } else { + _gizmo->visible = false; + _gizmo->redraw(); + return EditorPlugin::AFTER_GUI_INPUT_PASS; } } break; @@ -141,8 +202,16 @@ EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Came paint_brush_draw(position); + _gizmo->visible = true; + _gizmo->drawing = true; + _gizmo->position = position; + _gizmo->refresh_lines(_world); + return EditorPlugin::AFTER_GUI_INPUT_STOP; } else { + _gizmo->visible = false; + _gizmo->redraw(); + return EditorPlugin::AFTER_GUI_INPUT_PASS; } @@ -379,12 +448,19 @@ void TerrainWorldEditor::edit(TerrainWorld *p_world) { return; } + if (_gizmo.is_valid()) { + _gizmo->visible = false; + _gizmo->redraw(); + } + _world = p_world; if (!_world) { return; } + _gizmo = get_gizmo_from(_world); + _channel_type = _world->get_channel_index_info(TerrainWorld::CHANNEL_TYPE_INFO_TYPE); _channel_isolevel = _world->get_channel_index_info(TerrainWorld::CHANNEL_TYPE_INFO_ISOLEVEL); @@ -794,9 +870,28 @@ void TerrainWorldEditor::_notification(int p_what) { void TerrainWorldEditor::_node_removed(Node *p_node) { if (p_node == _world) { _world = NULL; + _gizmo.unref(); } } +Ref TerrainWorldEditor::get_gizmo_from(TerrainWorld *w) { + if (!w) { + return Ref(); + } + + Vector> gizmos = w->get_gizmos(); + + for (int i = 0; i < gizmos.size(); ++i) { + Ref g = gizmos[i]; + + if (g.is_valid()) { + return g; + } + } + + return Ref(); +} + void TerrainWorldEditor::_on_surface_button_pressed() { BaseButton *button = _surfaces_button_group->get_pressed_button(); @@ -808,6 +903,9 @@ void TerrainWorldEditor::_on_surface_button_pressed() { void TerrainWorldEditor::_on_tool_button_pressed() { BaseButton *button = _tool_button_group->get_pressed_button(); + _gizmo->visible = false; + _gizmo->redraw(); + if (button) { _previous_tool_mode = _tool_mode; _tool_mode = static_cast(static_cast(button->get_meta("tool_mode"))); @@ -821,11 +919,13 @@ void TerrainWorldEditor::_on_tool_button_pressed() { _paint_brush_tool_container->hide(); break; case TOOL_MODE_PAINT_BRUSH: + _gizmo->size = _paint_brush_size; _add_remove_tool_container->hide(); _isolevel_brush_tool_container->hide(); _paint_brush_tool_container->show(); break; case TOOL_MODE_ISOLEVEL_BRUSH: + _gizmo->size = _isolevel_brush_size; _add_remove_tool_container->hide(); _isolevel_brush_tool_container->show(); _paint_brush_tool_container->hide(); @@ -956,6 +1056,12 @@ void TerrainWorldEditorPlugin::_notification(int p_what) { } void TerrainWorldEditorPlugin::edit(Object *p_object) { + TerrainWorld *ow = terrain_world_editor->get_edited_world(); + + if (p_object == ow) { + return; + } + terrain_world_editor->edit(Object::cast_to(p_object)); } diff --git a/modules/terraman/editor/terrain_world_editor.h b/modules/terraman/editor/terrain_world_editor.h index 5cd11b161..d06d6b77a 100644 --- a/modules/terraman/editor/terrain_world_editor.h +++ b/modules/terraman/editor/terrain_world_editor.h @@ -37,6 +37,7 @@ #include "scene/gui/panel_container.h" +class TerrainWorldGizmo; class TerrainWorld; class SpatialEditorPlugin; class HSlider; @@ -60,6 +61,8 @@ public: }; public: + TerrainWorld *get_edited_world() { return _world; } + EditorPlugin::AfterGUIInput forward_spatial_input_event(Camera *p_camera, const Ref &p_event); void edit(TerrainWorld *p_world); @@ -72,6 +75,9 @@ public: TerrainWorldEditor(EditorNode *p_editor); ~TerrainWorldEditor(); +protected: + Ref get_gizmo_from(TerrainWorld *w); + protected: static void _bind_methods(); void _notification(int p_what); @@ -128,6 +134,7 @@ private: private: TerrainWorld *_world; + Ref _gizmo; int _selected_type; diff --git a/modules/terraman/editor/terrain_world_gizmo.cpp b/modules/terraman/editor/terrain_world_gizmo.cpp index 1a3815d3d..7f8144cfe 100644 --- a/modules/terraman/editor/terrain_world_gizmo.cpp +++ b/modules/terraman/editor/terrain_world_gizmo.cpp @@ -31,13 +31,14 @@ #include "terrain_world_gizmo.h" +#include "core/math/math_defs.h" #include "editor/editor_node.h" #include "scene/3d/camera.h" +#include "scene/main/world.h" +#include "scene/resources/world_3d.h" +#include "servers/physics_server.h" -void TerrainWorldGizmo::set_visible(const bool visible) { - _visible = visible; - redraw(); -} +#include "../world/terrain_world.h" void TerrainWorldGizmo::set_editor_plugin(EditorPlugin *editor_plugin) { _editor_plugin = editor_plugin; @@ -51,46 +52,85 @@ void TerrainWorldGizmo::set_handle(int index, bool secondary, Camera *camera, co void TerrainWorldGizmo::redraw() { clear(); - if (!_visible) { + if (!visible) { return; } if (!get_plugin().is_valid()) { return; } - /* - Ref handles_material = get_plugin()->get_material("handles", Ref(this)); - Ref material = get_plugin()->get_material("main", Ref(this)); - Ref seam_material = get_plugin()->get_material("seam", Ref(this)); + if (_lines.size() == 0) { + return; + } - _mesh_outline_generator->setup(_mdr); + Ref material; - if (selection_mode == SELECTION_MODE_EDGE) { - _mesh_outline_generator->generate_mark_edges(visual_indicator_outline, visual_indicator_handle); - } else if (selection_mode == SELECTION_MODE_FACE) { - _mesh_outline_generator->generate_mark_faces(visual_indicator_outline, visual_indicator_handle); + if (drawing) { + material = get_plugin()->get_material("drawing", Ref(this)); } else { - _mesh_outline_generator->generate(visual_indicator_outline, visual_indicator_handle); + material = get_plugin()->get_material("main", Ref(this)); } - if (visual_indicator_outline || visual_indicator_handle) { - add_lines(_mesh_outline_generator->lines, material, false); - } - - if (visual_indicator_seam) { - add_lines(_mesh_outline_generator->seam_lines, seam_material, false); - } - */ + add_lines(_lines, material); } void TerrainWorldGizmo::apply() { } +void TerrainWorldGizmo::refresh_lines(TerrainWorld *world) { + //Transform local_xform = world->get_global_transform().affine_inverse(); + + PhysicsDirectSpaceState *ss = world->get_world_3d()->get_direct_space_state(); + + Vector3 from; + Vector3 to; + PhysicsDirectSpaceState::RayResult res; + + _lines.clear(); + _points.clear(); + + float voxel_scale = world->get_voxel_scale(); + Vector3 vsv = Vector3(voxel_scale, voxel_scale, voxel_scale); + + for (int i = 0; i < 10; ++i) { + from = Vector3(Math::sin((Math_PI * 2.0 / 10.0) * (float)i) * size, 1000, Math::cos((Math_PI * 2.0 / 10.0) * (float)i) * size) * vsv; + to = Vector3(from.x, -from.y, from.z); + + from += position; + to += position; + + //from = local_xform.xform(from); + //to = local_xform.xform(to); + + Vector3 p; + + if (ss->intersect_ray(from, to, res)) { + p = res.position + res.normal.limit_length(0.1); + } else { + p = Vector3(from.x, 0, from.z); + } + + _points.push_back(p); + } + + for (int i = 1; i < _points.size(); ++i) { + _lines.push_back(_points[i - 1]); + _lines.push_back(_points[i]); + } + + _lines.push_back(_points[_points.size() - 1]); + _lines.push_back(_points[0]); + + redraw(); +} + TerrainWorldGizmo::TerrainWorldGizmo() { _editor_plugin = nullptr; _undo_redo = nullptr; - _visible = false; + visible = false; + drawing = false; + size = 10; } TerrainWorldGizmo::~TerrainWorldGizmo() { diff --git a/modules/terraman/editor/terrain_world_gizmo.h b/modules/terraman/editor/terrain_world_gizmo.h index ad1ccb3de..48931ef0d 100644 --- a/modules/terraman/editor/terrain_world_gizmo.h +++ b/modules/terraman/editor/terrain_world_gizmo.h @@ -40,12 +40,16 @@ class MDREDMeshOutline; class InputEvent; class EditorPlugin; class UndoRedo; +class TerrainWorld; class TerrainWorldGizmo : public EditorSpatialGizmo { GDCLASS(TerrainWorldGizmo, EditorSpatialGizmo); public: - void set_visible(const bool visible); + bool visible; + bool drawing; + Vector3 position; + float size; void set_editor_plugin(EditorPlugin *editor_plugin); @@ -53,19 +57,19 @@ public: void redraw(); void apply(); + void refresh_lines(TerrainWorld *world); + TerrainWorldGizmo(); ~TerrainWorldGizmo(); - PoolVector3Array _vertices; - PoolIntArray _indices; - EditorPlugin *_editor_plugin; UndoRedo *_undo_redo; - bool _visible; - protected: static void _bind_methods(); + + Vector _points; + Vector _lines; }; #endif diff --git a/modules/terraman/editor/terrain_world_gizmo_plugin.cpp b/modules/terraman/editor/terrain_world_gizmo_plugin.cpp index 1adccd260..979fd247e 100644 --- a/modules/terraman/editor/terrain_world_gizmo_plugin.cpp +++ b/modules/terraman/editor/terrain_world_gizmo_plugin.cpp @@ -65,8 +65,7 @@ TerrainWorldGizmoPlugin::TerrainWorldGizmoPlugin() { plugin = nullptr; create_material("main", Color(0.7, 0.7, 0.7)); - create_material("seam", Color(1, 0, 0), false, true); - create_handle_material("handles"); + create_material("drawing", Color(1, 0, 0)); } TerrainWorldGizmoPlugin::~TerrainWorldGizmoPlugin() { diff --git a/modules/terraman/editor/terrain_world_gizmo_plugin.h b/modules/terraman/editor/terrain_world_gizmo_plugin.h index 51d08e9e4..cb48e1597 100644 --- a/modules/terraman/editor/terrain_world_gizmo_plugin.h +++ b/modules/terraman/editor/terrain_world_gizmo_plugin.h @@ -40,7 +40,6 @@ class TerrainWorldGizmoPlugin : public EditorSpatialGizmoPlugin { GDCLASS(TerrainWorldGizmoPlugin, EditorSpatialGizmoPlugin); public: - void _init(); String get_gizmo_name() const; int get_priority() const; bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx, bool p_secondary) const;