diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp index 3becc9c9fd2..2695253b780 100644 --- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.cpp @@ -34,6 +34,7 @@ #include "core/math/geometry_3d.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/collision_shape_3d.h" #include "scene/resources/box_shape_3d.h" @@ -47,6 +48,7 @@ #include "scene/resources/world_boundary_shape_3d.h" CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() { + helper.instantiate(); const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); create_material("shape_material", gizmo_color); const float gizmo_value = gizmo_color.get_v(); @@ -55,6 +57,9 @@ CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() { create_handle_material("handles"); } +CollisionShape3DGizmoPlugin::~CollisionShape3DGizmoPlugin() { +} + bool CollisionShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -80,7 +85,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g } if (Object::cast_to(*s)) { - return "Size"; + return helper->box_get_handle_name(p_id); } if (Object::cast_to(*s)) { @@ -135,8 +140,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p } void CollisionShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { - initial_transform = p_gizmo->get_node_3d()->get_global_transform(); - initial_value = get_handle_value(p_gizmo, p_id, p_secondary); + helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform()); } void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -147,13 +151,8 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i return; } - Transform3D gt = initial_transform; - Transform3D gi = gt.affine_inverse(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); if (Object::cast_to(*s)) { Ref ss = s; @@ -188,38 +187,12 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i } if (Object::cast_to(*s)) { - Vector3 axis; - axis[p_id / 2] = 1.0; Ref bs = s; - Vector3 ra, rb; - int sign = p_id % 2 * -2 + 1; - Vector3 initial_size = initial_value; - - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * sign, sg[0], sg[1], ra, rb); - if (ra[p_id / 2] == 0) { - // Point before half of the shape. Needs to be calculated in opposite direction. - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * -sign, sg[0], sg[1], ra, rb); - } - - float d = ra[p_id / 2] * sign; - - Vector3 he = bs->get_size(); - he[p_id / 2] = d * 2; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - he[p_id / 2] = Math::snapped(he[p_id / 2], Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (Input::get_singleton()->is_key_pressed(Key::ALT)) { - he[p_id / 2] = MAX(he[p_id / 2], 0.001); - bs->set_size(he); - cs->set_global_position(initial_transform.get_origin()); - } else { - he[p_id / 2] = MAX(he[p_id / 2], -initial_size[p_id / 2] + 0.002); - bs->set_size((initial_size + (he - initial_size) * 0.5).abs()); - Vector3 pos = initial_transform.affine_inverse().xform(initial_transform.get_origin()); - pos += (bs->get_size() - initial_size) * 0.5 * sign; - cs->set_global_position(initial_transform.xform(pos)); - } + Vector3 size = bs->get_size(); + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); + bs->set_size(size); + cs->set_global_position(position); } if (Object::cast_to(*s)) { @@ -291,20 +264,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo } if (Object::cast_to(*s)) { - Ref ss = s; - if (p_cancel) { - cs->set_global_position(initial_transform.get_origin()); - ss->set_size(p_restore); - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Box Shape Size")); - ur->add_do_method(ss.ptr(), "set_size", ss->get_size()); - ur->add_do_method(cs, "set_global_position", cs->get_global_position()); - ur->add_undo_method(ss.ptr(), "set_size", p_restore); - ur->add_undo_method(cs, "set_global_position", initial_transform.get_origin()); - ur->commit_action(); + helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs, s.ptr()); } if (Object::cast_to(*s)) { @@ -446,14 +406,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { lines.push_back(b); } - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = bs->get_size()[i] / 2; - handles.push_back(ax); - handles.push_back(-ax); - } + const Vector handles = helper->box_get_handles(bs->get_size()); p_gizmo->add_lines(lines, material); p_gizmo->add_collision_segments(lines); diff --git a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h index 6b7740de2f5..464012acf97 100644 --- a/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h +++ b/editor/plugins/gizmos/collision_shape_3d_gizmo_plugin.h @@ -33,11 +33,12 @@ #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class CollisionShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(CollisionShape3DGizmoPlugin, EditorNode3DGizmoPlugin); - Transform3D initial_transform; - Variant initial_value; + Ref helper; public: bool has_gizmo(Node3D *p_spatial) override; @@ -52,6 +53,7 @@ public: void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; CollisionShape3DGizmoPlugin(); + ~CollisionShape3DGizmoPlugin(); }; #endif // COLLISION_SHAPE_3D_GIZMO_PLUGIN_H diff --git a/editor/plugins/gizmos/decal_gizmo_plugin.cpp b/editor/plugins/gizmos/decal_gizmo_plugin.cpp index b439598ef4a..68206a7ee54 100644 --- a/editor/plugins/gizmos/decal_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/decal_gizmo_plugin.cpp @@ -32,10 +32,12 @@ #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/decal.h" DecalGizmoPlugin::DecalGizmoPlugin() { + helper.instantiate(); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/decal", Color(0.6, 0.5, 1.0)); create_material("decal_material", gizmo_color); @@ -43,6 +45,9 @@ DecalGizmoPlugin::DecalGizmoPlugin() { create_handle_material("handles"); } +DecalGizmoPlugin::~DecalGizmoPlugin() { +} + bool DecalGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -56,16 +61,7 @@ int DecalGizmoPlugin::get_priority() const { } String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - switch (p_id) { - case 0: - return "Size X"; - case 1: - return "Size Y"; - case 2: - return "Size Z"; - } - - return ""; + return helper->box_get_handle_name(p_id); } Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { @@ -73,52 +69,25 @@ Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int return decal->get_size(); } +void DecalGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { + helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform()); +} + void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { Decal *decal = Object::cast_to(p_gizmo->get_node_3d()); - Transform3D gt = decal->get_global_transform(); - - Transform3D gi = gt.affine_inverse(); - Vector3 size = decal->get_size(); - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_id] = 1.0; - - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id] * 2; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - size[p_id] = d; + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); decal->set_size(size); + decal->set_global_position(position); } void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { - Decal *decal = Object::cast_to(p_gizmo->get_node_3d()); - - Vector3 restore = p_restore; - - if (p_cancel) { - decal->set_size(restore); - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Decal Size")); - ur->add_do_method(decal, "set_size", decal->get_size()); - ur->add_undo_method(decal, "set_size", restore); - ur->commit_action(); + helper->box_commit_handle(TTR("Change Decal Size"), p_cancel, p_gizmo->get_node_3d()); } void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { @@ -153,14 +122,7 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { lines.push_back(Vector3(0, half_size_y, 0)); lines.push_back(Vector3(0, half_size_y * 1.2, 0)); - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } - + Vector handles = helper->box_get_handles(decal->get_size()); Ref material = get_material("decal_material", p_gizmo); p_gizmo->add_lines(lines, material); diff --git a/editor/plugins/gizmos/decal_gizmo_plugin.h b/editor/plugins/gizmos/decal_gizmo_plugin.h index 800a14b2d51..c7809dc556a 100644 --- a/editor/plugins/gizmos/decal_gizmo_plugin.h +++ b/editor/plugins/gizmos/decal_gizmo_plugin.h @@ -33,9 +33,13 @@ #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class DecalGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(DecalGizmoPlugin, EditorNode3DGizmoPlugin); + Ref helper; + public: bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; @@ -44,10 +48,12 @@ public: String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; + void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; DecalGizmoPlugin(); + ~DecalGizmoPlugin(); }; #endif // DECAL_GIZMO_PLUGIN_H diff --git a/editor/plugins/gizmos/gizmo_3d_helper.cpp b/editor/plugins/gizmos/gizmo_3d_helper.cpp new file mode 100644 index 00000000000..6c7acb67085 --- /dev/null +++ b/editor/plugins/gizmos/gizmo_3d_helper.cpp @@ -0,0 +1,131 @@ +/**************************************************************************/ +/* gizmo_3d_helper.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#include "gizmo_3d_helper.h" + +#include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/node_3d_editor_plugin.h" +#include "scene/3d/camera_3d.h" + +void Gizmo3DHelper::initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform) { + initial_value = p_initial_value; + initial_transform = p_initial_transform; +} + +void Gizmo3DHelper::get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment) { + Transform3D gt = initial_transform; + Transform3D gi = gt.affine_inverse(); + + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + r_segment[0] = gi.xform(ray_from); + r_segment[1] = gi.xform(ray_from + ray_dir * 4096); +} + +Vector Gizmo3DHelper::box_get_handles(const Vector3 &p_box_size) { + Vector handles; + for (int i = 0; i < 3; i++) { + Vector3 ax; + ax[i] = p_box_size[i] / 2; + handles.push_back(ax); + handles.push_back(-ax); + } + return handles; +} + +String Gizmo3DHelper::box_get_handle_name(int p_id) const { + switch (p_id) { + case 0: + case 1: + return "Size X"; + case 2: + case 3: + return "Size Y"; + case 4: + case 5: + return "Size Z"; + } + return ""; +} + +void Gizmo3DHelper::box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position) { + Vector3 axis; + axis[p_id / 2] = 1.0; + Vector3 ra, rb; + int sign = p_id % 2 * -2 + 1; + Vector3 initial_size = initial_value; + + Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * sign, p_segment[0], p_segment[1], ra, rb); + if (ra[p_id / 2] == 0) { + // Point before half of the shape. Needs to be calculated in opposite direction. + Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096 * -sign, p_segment[0], p_segment[1], ra, rb); + } + + float d = ra[p_id / 2] * sign; + + Vector3 he = r_box_size; + he[p_id / 2] = d * 2; + if (Node3DEditor::get_singleton()->is_snap_enabled()) { + he[p_id / 2] = Math::snapped(he[p_id / 2], Node3DEditor::get_singleton()->get_translate_snap()); + } + + if (Input::get_singleton()->is_key_pressed(Key::ALT)) { + he[p_id / 2] = MAX(he[p_id / 2], 0.001); + r_box_size = he; + r_box_position = initial_transform.get_origin(); + } else { + he[p_id / 2] = MAX(he[p_id / 2], -initial_size[p_id / 2] + 0.002); + r_box_size = (initial_size + (he - initial_size) * 0.5).abs(); + Vector3 pos = initial_transform.affine_inverse().xform(initial_transform.get_origin()); + pos += (r_box_size - initial_size) * 0.5 * sign; + r_box_position = initial_transform.xform(pos); + } +} + +void Gizmo3DHelper::box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object, const StringName &p_position_property, const StringName &p_size_property) { + if (!p_size_object) { + p_size_object = p_position_object; + } + + if (p_cancel) { + p_size_object->set(p_size_property, initial_value); + p_position_object->set(p_position_property, initial_transform.get_origin()); + return; + } + + EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); + ur->create_action(p_action_name); + ur->add_do_property(p_size_object, p_size_property, p_size_object->get(p_size_property)); + ur->add_do_property(p_position_object, p_position_property, p_position_object->get(p_position_property)); + ur->add_undo_property(p_size_object, p_size_property, initial_value); + ur->add_undo_property(p_position_object, p_position_property, initial_transform.get_origin()); + ur->commit_action(); +} diff --git a/editor/plugins/gizmos/gizmo_3d_helper.h b/editor/plugins/gizmos/gizmo_3d_helper.h new file mode 100644 index 00000000000..387ea020b8c --- /dev/null +++ b/editor/plugins/gizmos/gizmo_3d_helper.h @@ -0,0 +1,55 @@ +/**************************************************************************/ +/* gizmo_3d_helper.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GIZMO_3D_HELPER_H +#define GIZMO_3D_HELPER_H + +#include "core/object/ref_counted.h" + +class Camera3D; + +class Gizmo3DHelper : public RefCounted { + GDCLASS(Gizmo3DHelper, RefCounted); + + int current_handle_id; + Variant initial_value; + Transform3D initial_transform; + +public: + void initialize_handle_action(const Variant &p_initial_value, const Transform3D &p_initial_transform); + void get_segment(Camera3D *p_camera, const Point2 &p_point, Vector3 *r_segment); + + Vector box_get_handles(const Vector3 &p_box_size); + String box_get_handle_name(int p_id) const; + void box_set_handle(const Vector3 p_segment[2], int p_id, Vector3 &r_box_size, Vector3 &r_box_position); + void box_commit_handle(const String &p_action_name, bool p_cancel, Object *p_position_object, Object *p_size_object = nullptr, const StringName &p_position_property = "global_position", const StringName &p_size_property = "size"); +}; + +#endif // GIZMO_3D_HELPER_H diff --git a/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.cpp b/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.cpp index 248e15c2c14..2cbfccc05e0 100644 --- a/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.cpp @@ -32,10 +32,13 @@ #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/gpu_particles_collision_3d.h" GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() { + helper.instantiate(); + Color gizmo_color_attractor = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_attractor", Color(1, 0.7, 0.5)); create_material("shape_material_attractor", gizmo_color_attractor); gizmo_color_attractor.a = 0.15; @@ -49,6 +52,9 @@ GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() { create_handle_material("handles"); } +GPUParticlesCollision3DGizmoPlugin::~GPUParticlesCollision3DGizmoPlugin() { +} + bool GPUParticlesCollision3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { return (Object::cast_to(p_spatial) != nullptr) || (Object::cast_to(p_spatial) != nullptr); } @@ -69,7 +75,7 @@ String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGiz } if (Object::cast_to(cs) || Object::cast_to(cs) || Object::cast_to(cs) || Object::cast_to(cs) || Object::cast_to(cs)) { - return "Size"; + return helper->box_get_handle_name(p_id); } return ""; @@ -89,16 +95,15 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(const EditorNode3DG return Variant(); } +void GPUParticlesCollision3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { + helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform()); +} + void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { Node3D *sn = p_gizmo->get_node_3d(); - Transform3D gt = sn->get_global_transform(); - Transform3D gi = gt.affine_inverse(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); if (Object::cast_to(sn) || Object::cast_to(sn)) { Vector3 ra, rb; @@ -116,22 +121,11 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_g } if (Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn)) { - Vector3 axis; - axis[p_id] = 1.0; - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id] * 2; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - Vector3 he = sn->call("get_size"); - he[p_id] = d; - sn->call("set_size", he); + Vector3 size = sn->call("get_size"); + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); + sn->call("set_size", size); + sn->set_global_position(position); } } @@ -152,16 +146,7 @@ void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo * } if (Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn) || Object::cast_to(sn)) { - if (p_cancel) { - sn->call("set_size", p_restore); - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Box Shape Size")); - ur->add_do_method(sn, "set_size", sn->call("get_size")); - ur->add_undo_method(sn, "set_size", p_restore); - ur->commit_action(); + helper->box_commit_handle("Change Box Shape Size", p_cancel, sn); } } @@ -237,13 +222,7 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { lines.push_back(b); } - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = cs->call("get_size").operator Vector3()[i] / 2; - handles.push_back(ax); - } + Vector handles = helper->box_get_handles(aabb.size); p_gizmo->add_lines(lines, material); p_gizmo->add_collision_segments(lines); diff --git a/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.h b/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.h index 6045f6e4403..98572ff837f 100644 --- a/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.h +++ b/editor/plugins/gizmos/gpu_particles_collision_3d_gizmo_plugin.h @@ -33,9 +33,13 @@ #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class GPUParticlesCollision3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(GPUParticlesCollision3DGizmoPlugin, EditorNode3DGizmoPlugin); + Ref helper; + public: bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; @@ -44,10 +48,12 @@ public: String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; + void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; GPUParticlesCollision3DGizmoPlugin(); + ~GPUParticlesCollision3DGizmoPlugin(); }; #endif // GPU_PARTICLES_COLLISION_3D_GIZMO_PLUGIN_H diff --git a/editor/plugins/gizmos/reflection_probe_gizmo_plugin.cpp b/editor/plugins/gizmos/reflection_probe_gizmo_plugin.cpp index d9c2316ce0a..f4d524e39c4 100644 --- a/editor/plugins/gizmos/reflection_probe_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/reflection_probe_gizmo_plugin.cpp @@ -32,10 +32,12 @@ #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/reflection_probe.h" ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { + helper.instantiate(); Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/reflection_probe", Color(0.6, 1, 0.5)); create_material("reflection_probe_material", gizmo_color); @@ -50,6 +52,9 @@ ReflectionProbeGizmoPlugin::ReflectionProbeGizmoPlugin() { create_handle_material("handles"); } +ReflectionProbeGizmoPlugin::~ReflectionProbeGizmoPlugin() { +} + bool ReflectionProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -63,21 +68,17 @@ int ReflectionProbeGizmoPlugin::get_priority() const { } String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + if (p_id < 6) { + return helper->box_get_handle_name(p_id); + } switch (p_id) { - case 0: - return "Size X"; - case 1: - return "Size Y"; - case 2: - return "Size Z"; - case 3: + case 6: return "Origin X"; - case 4: + case 7: return "Origin Y"; - case 5: + case 8: return "Origin Z"; } - return ""; } @@ -86,47 +87,30 @@ Variant ReflectionProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_ return AABB(probe->get_origin_offset(), probe->get_size()); } +void ReflectionProbeGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { + // The initial value is only used for resizing the box, so we only need AABB size. + AABB aabb = get_handle_value(p_gizmo, p_id, p_secondary); + helper->initialize_handle_action(aabb.size, p_gizmo->get_node_3d()->get_global_transform()); +} + void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_node_3d()); - Transform3D gt = probe->get_global_transform(); - Transform3D gi = gt.affine_inverse(); + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); - if (p_id < 3) { + if (p_id < 6) { Vector3 size = probe->get_size(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_id] = 1.0; - - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id] * 2; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - size[p_id] = d; + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); probe->set_size(size); + probe->set_global_position(position); } else { - p_id -= 3; + p_id -= 6; Vector3 origin = probe->get_origin_offset(); origin[p_id] = 0; - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - Vector3 axis; axis[p_id] = 1.0; @@ -146,6 +130,11 @@ void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, in void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_node_3d()); + if (p_id < 6) { + helper->box_commit_handle(TTR("Change Probe Size"), p_cancel, probe); + return; + } + AABB restore = p_restore; if (p_cancel) { @@ -155,10 +144,8 @@ void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, } EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Probe Size")); - ur->add_do_method(probe, "set_size", probe->get_size()); + ur->create_action(TTR("Change Probe Origin Offset")); ur->add_do_method(probe, "set_origin_offset", probe->get_origin_offset()); - ur->add_undo_method(probe, "set_size", restore.size); ur->add_undo_method(probe, "set_origin_offset", restore.position); ur->commit_action(); } @@ -189,13 +176,7 @@ void ReflectionProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { internal_lines.push_back(ep); } - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } + Vector handles = helper->box_get_handles(probe->get_size()); for (int i = 0; i < 3; i++) { Vector3 orig_handle = probe->get_origin_offset(); diff --git a/editor/plugins/gizmos/reflection_probe_gizmo_plugin.h b/editor/plugins/gizmos/reflection_probe_gizmo_plugin.h index bc9840b27cd..b980f5a9448 100644 --- a/editor/plugins/gizmos/reflection_probe_gizmo_plugin.h +++ b/editor/plugins/gizmos/reflection_probe_gizmo_plugin.h @@ -33,9 +33,13 @@ #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class ReflectionProbeGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(ReflectionProbeGizmoPlugin, EditorNode3DGizmoPlugin); + Ref helper; + public: bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; @@ -44,10 +48,12 @@ public: String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; + void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; ReflectionProbeGizmoPlugin(); + ~ReflectionProbeGizmoPlugin(); }; #endif // REFLECTION_PROBE_GIZMO_PLUGIN_H diff --git a/editor/plugins/gizmos/voxel_gi_gizmo_plugin.cpp b/editor/plugins/gizmos/voxel_gi_gizmo_plugin.cpp index 08dbe76d87a..22792e48fe5 100644 --- a/editor/plugins/gizmos/voxel_gi_gizmo_plugin.cpp +++ b/editor/plugins/gizmos/voxel_gi_gizmo_plugin.cpp @@ -32,10 +32,13 @@ #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/voxel_gi.h" VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() { + helper.instantiate(); + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/voxel_gi", Color(0.5, 1, 0.6)); create_material("voxel_gi_material", gizmo_color); @@ -51,6 +54,9 @@ VoxelGIGizmoPlugin::VoxelGIGizmoPlugin() { create_handle_material("handles"); } +VoxelGIGizmoPlugin::~VoxelGIGizmoPlugin() { +} + bool VoxelGIGizmoPlugin::has_gizmo(Node3D *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } @@ -64,16 +70,7 @@ int VoxelGIGizmoPlugin::get_priority() const { } String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - switch (p_id) { - case 0: - return "Size X"; - case 1: - return "Size Y"; - case 2: - return "Size Z"; - } - - return ""; + return helper->box_get_handle_name(p_id); } Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { @@ -81,52 +78,25 @@ Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, i return probe->get_size(); } +void VoxelGIGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { + helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform()); +} + void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { VoxelGI *probe = Object::cast_to(p_gizmo->get_node_3d()); - Transform3D gt = probe->get_global_transform(); - Transform3D gi = gt.affine_inverse(); + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); Vector3 size = probe->get_size(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; - - Vector3 axis; - axis[p_id] = 1.0; - - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_id] * 2; - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - size[p_id] = d; + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); probe->set_size(size); + probe->set_global_position(position); } void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { - VoxelGI *probe = Object::cast_to(p_gizmo->get_node_3d()); - - Vector3 restore = p_restore; - - if (p_cancel) { - probe->set_size(restore); - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Probe Size")); - ur->add_do_method(probe, "set_size", probe->get_size()); - ur->add_undo_method(probe, "set_size", restore); - ur->commit_action(); + helper->box_commit_handle(TTR("Change Probe Size"), p_cancel, p_gizmo->get_node_3d()); } void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { @@ -191,13 +161,7 @@ void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_lines(lines, material_internal); - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 ax; - ax[i] = aabb.position[i] + aabb.size[i]; - handles.push_back(ax); - } + Vector handles = helper->box_get_handles(probe->get_size()); if (p_gizmo->is_selected()) { Ref solid_material = get_material("voxel_gi_solid_material", p_gizmo); diff --git a/editor/plugins/gizmos/voxel_gi_gizmo_plugin.h b/editor/plugins/gizmos/voxel_gi_gizmo_plugin.h index 4d1f282bd60..a5447c8b5ce 100644 --- a/editor/plugins/gizmos/voxel_gi_gizmo_plugin.h +++ b/editor/plugins/gizmos/voxel_gi_gizmo_plugin.h @@ -33,9 +33,13 @@ #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class VoxelGIGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(VoxelGIGizmoPlugin, EditorNode3DGizmoPlugin); + Ref helper; + public: bool has_gizmo(Node3D *p_spatial) override; String get_gizmo_name() const override; @@ -44,10 +48,12 @@ public: String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; + void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override; void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; VoxelGIGizmoPlugin(); + ~VoxelGIGizmoPlugin(); }; #endif // VOXEL_GI_GIZMO_PLUGIN_H diff --git a/modules/csg/editor/csg_gizmos.cpp b/modules/csg/editor/csg_gizmos.cpp index 2c533cb36d4..ebf0f5a91fa 100644 --- a/modules/csg/editor/csg_gizmos.cpp +++ b/modules/csg/editor/csg_gizmos.cpp @@ -35,12 +35,15 @@ #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/plugins/gizmos/gizmo_3d_helper.h" #include "editor/plugins/node_3d_editor_plugin.h" #include "scene/3d/camera_3d.h" /////////// CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { + helper.instantiate(); + Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15)); create_material("shape_union_material", gizmo_color); create_material("shape_union_solid_material", gizmo_color); @@ -56,6 +59,9 @@ CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() { create_handle_material("handles"); } +CSGShape3DGizmoPlugin::~CSGShape3DGizmoPlugin() { +} + String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { CSGShape3D *cs = Object::cast_to(p_gizmo->get_node_3d()); @@ -64,7 +70,7 @@ String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, } if (Object::cast_to(cs)) { - return "Size"; + return helper->box_get_handle_name(p_id); } if (Object::cast_to(cs)) { @@ -104,17 +110,15 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo return Variant(); } +void CSGShape3DGizmoPlugin::begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) { + helper->initialize_handle_action(get_handle_value(p_gizmo, p_id, p_secondary), p_gizmo->get_node_3d()->get_global_transform()); +} + void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { CSGShape3D *cs = Object::cast_to(p_gizmo->get_node_3d()); - Transform3D gt = cs->get_global_transform(); - //gt.orthonormalize(); - Transform3D gi = gt.affine_inverse(); - - Vector3 ray_from = p_camera->project_ray_origin(p_point); - Vector3 ray_dir = p_camera->project_ray_normal(p_point); - - Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; + Vector3 sg[2]; + helper->get_segment(p_camera, p_point, sg); if (Object::cast_to(cs)) { CSGSphere3D *s = Object::cast_to(cs); @@ -135,29 +139,11 @@ void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_i if (Object::cast_to(cs)) { CSGBox3D *s = Object::cast_to(cs); - - Vector3 axis; - axis[p_id] = 1.0; - Vector3 ra, rb; - Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_id]; - - if (Math::is_nan(d)) { - // The handle is perpendicular to the camera. - return; - } - - if (Node3DEditor::get_singleton()->is_snap_enabled()) { - d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); - } - - if (d < 0.001) { - d = 0.001; - } - - Vector3 h = s->get_size(); - h[p_id] = d * 2; - s->set_size(h); + Vector3 size = s->get_size(); + Vector3 position; + helper->box_set_handle(sg, p_id, size, position); + s->set_size(size); + s->set_global_position(position); } if (Object::cast_to(cs)) { @@ -225,17 +211,7 @@ void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int } if (Object::cast_to(cs)) { - CSGBox3D *s = Object::cast_to(cs); - if (p_cancel) { - s->set_size(p_restore); - return; - } - - EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton(); - ur->create_action(TTR("Change Box Shape Size")); - ur->add_do_method(s, "set_size", s->get_size()); - ur->add_undo_method(s, "set_size", p_restore); - ur->commit_action(); + helper->box_commit_handle(TTR("Change Box Shape Size"), p_cancel, cs); } if (Object::cast_to(cs)) { @@ -394,15 +370,7 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (Object::cast_to(cs)) { CSGBox3D *s = Object::cast_to(cs); - - Vector handles; - - for (int i = 0; i < 3; i++) { - Vector3 h; - h[i] = s->get_size()[i] / 2; - handles.push_back(h); - } - + Vector handles = helper->box_get_handles(s->get_size()); p_gizmo->add_handles(handles, handles_material); } diff --git a/modules/csg/editor/csg_gizmos.h b/modules/csg/editor/csg_gizmos.h index deac1d428d0..6281db0a215 100644 --- a/modules/csg/editor/csg_gizmos.h +++ b/modules/csg/editor/csg_gizmos.h @@ -38,9 +38,13 @@ #include "editor/editor_plugin.h" #include "editor/plugins/node_3d_editor_gizmos.h" +class Gizmo3DHelper; + class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin { GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin); + Ref helper; + public: virtual bool has_gizmo(Node3D *p_spatial) override; virtual String get_gizmo_name() const override; @@ -50,10 +54,12 @@ public: virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; + void begin_handle_action(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) override; virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) override; virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) override; CSGShape3DGizmoPlugin(); + ~CSGShape3DGizmoPlugin(); }; class EditorPluginCSG : public EditorPlugin {