From 58539a22b6d078a45713a28d0f964f928902a9c0 Mon Sep 17 00:00:00 2001 From: Relintai Date: Thu, 11 Aug 2022 01:24:29 +0200 Subject: [PATCH] Backported from Godot4: Node3D gizmo improvements * Clean-up of node_3d_editor_plugin.{h,cpp}: removed unused code, fixed some bugs. * Moved node_3d_editor_gizmos.{h,cpp} to editor/plugins. * Added support for multiple gizmos per node. This means custom gizmos will no longer override the built-in ones and that multiple gizmos can be used in more complex nodes. * Added support for handle IDs. When adding handles to a gizmo, an ID can be specified for each one, making it easier to work with gizmos that have a variable number of handles. * Added support for subgizmos, selectable elements that can be transformed without needing a node of their own. By overriding _subgizmo_intersect_frustum() and/or _subgizmo_intersect_ray() gizmos can define which subgizmos should be selected on a region or click selection. Subgizmo transformations are applied using get/set/commit virtual methods, similar to how handles work. - JFonS https://github.com/godotengine/godot/commit/cfb555a08175c811ea06a43ea320b81a2c90554a - Note: MeshDataResourceEditor is now kind of painful to use, it will be fixed a bit later. --- doc/classes/EditorSpatialGizmo.xml | 126 +- doc/classes/EditorSpatialGizmoPlugin.xml | 93 +- doc/classes/Spatial.xml | 39 +- editor/plugins/path_editor_plugin.cpp | 2 +- editor/plugins/room_manager_editor_plugin.cpp | 2 +- editor/plugins/spatial_editor_plugin.cpp | 1324 +++++++++-------- editor/plugins/spatial_editor_plugin.h | 187 +-- editor/spatial_editor_gizmos.cpp | 1047 +++++++++---- editor/spatial_editor_gizmos.h | 277 +++- .../editor/mdi_ed_plugin.cpp | 104 +- .../mesh_data_resource/editor/mdi_ed_plugin.h | 2 + modules/mesh_data_resource/editor/mdi_gizmo.h | 2 +- .../editor/mdi_gizmo_plugin.cpp | 2 +- .../editor/mdi_gizmo_plugin.h | 4 +- .../navigation_mesh_editor_plugin.cpp | 4 +- .../skeleton_editor_plugin.cpp | 2 +- .../skeleton_editor/skeleton_editor_plugin.h | 2 +- .../skeleton_editor/spatial_editor_gizmos.cpp | 4 +- .../skeleton_editor/spatial_editor_gizmos.h | 4 +- scene/3d/audio_stream_player_3d.cpp | 4 +- scene/3d/camera.cpp | 8 +- scene/3d/collision_polygon.cpp | 6 +- scene/3d/collision_shape.cpp | 6 +- scene/3d/label_3d.cpp | 2 +- scene/3d/light.cpp | 4 +- scene/3d/mesh_instance.cpp | 2 +- scene/3d/navigation_mesh_instance.cpp | 6 +- scene/3d/occluder.cpp | 6 +- scene/3d/path.cpp | 2 +- scene/3d/physics_body.cpp | 16 +- scene/3d/physics_joint.cpp | 20 +- scene/3d/portal.cpp | 14 +- scene/3d/ray_cast.cpp | 6 +- scene/3d/reflection_probe.cpp | 4 +- scene/3d/room_manager.cpp | 12 +- scene/3d/skeleton.cpp | 6 +- scene/3d/spatial.cpp | 159 +- scene/3d/spatial.h | 20 +- scene/3d/spring_arm.cpp | 2 +- scene/3d/sprite_3d.cpp | 2 +- scene/3d/vehicle_body.cpp | 4 +- scene/3d/visibility_notifier.cpp | 2 +- scene/scene_string_names.cpp | 1 + scene/scene_string_names.h | 1 + 44 files changed, 2166 insertions(+), 1376 deletions(-) diff --git a/doc/classes/EditorSpatialGizmo.xml b/doc/classes/EditorSpatialGizmo.xml index 24514f491..338ef1ae4 100644 --- a/doc/classes/EditorSpatialGizmo.xml +++ b/doc/classes/EditorSpatialGizmo.xml @@ -1,10 +1,10 @@ - Custom gizmo for editing Spatial objects. + Gizmo for editing Spatial objects. - Custom gizmo that is used for providing custom visualization and editing (handles) for 3D Spatial objects. See [EditorSpatialGizmoPlugin] for more information. + Gizmo that is used for providing custom visualization and editing (handles and subgizmos) for Spatial objects. Can be overridden to create custom gizmos, but for simple gizmos creating a [EditorSpatialGizmoPlugin] is usually recommended. @@ -13,25 +13,26 @@ - Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this function during [method redraw]. + Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this method during [method redraw]. - Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method redraw]. + Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this method during [method redraw]. - - + + + - Adds a list of handles (points) which can be used to deform the object being edited. - There are virtual functions which will be called upon editing of these handles. Call this function during [method redraw]. + Adds a list of handles (points) which can be used to edit the properties of the gizmo's Spatial. The [code]ids[/code] argument can be used to specify a custom identifier for each handle, if an empty [code]Array[/code] is passed, the ids will be assigned automatically from the [code]handles[/code] argument order. + There are virtual methods which will be called upon editing of these handles. Call this method during [method _redraw]. @@ -41,17 +42,17 @@ - Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this function during [method redraw]. + Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this method during [method redraw]. - - - + + + - Adds a mesh to the gizmo with the specified [code]billboard[/code] state, [code]skeleton[/code] and [code]material[/code]. If [code]billboard[/code] is [code]true[/code], the mesh will rotate to always face the camera. Call this function during [method redraw]. + Adds a mesh to the gizmo with the specified [code]material[/code], local [code]transform[/code] and [code]skeleton[/code]. Call this method during [method _redraw]. @@ -60,7 +61,7 @@ - Adds an unscaled billboard for visualization. Call this function during [method redraw]. + Adds an unscaled billboard for visualization and selection. Call this method during [method _redraw]. @@ -71,27 +72,50 @@ - + - Commit a handle being edited (handles must have been previously added by [method add_handles]). - If the [code]cancel[/code] parameter is [code]true[/code], an option to restore the edited value to the original is provided. + Override this method to commit a handle being edited (handles must have been previously added by [method add_handles]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo". + If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action. + + + + + + + + + + + + + Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo". + If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action. - + - Gets the name of an edited handle (handles must have been previously added by [method add_handles]). + Override this method to return the name of an edited handle (handles must have been previously added by [method add_handles]). Handles can be named for reference to the user when editing. - + - Gets actual value of a handle. This value can be anything and used for eventually undoing the motion when calling [method commit_handle]. + Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle]. + + + + + + + + + Override this method to return the current transform of a subgizmo. This transform will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_subgizmos]. @@ -108,25 +132,73 @@ - + - Returns [code]true[/code] if the handle at index [code]index[/code] is highlighted by being hovered with the mouse. + Override this method to return [code]true[/code] whenever the given handle should be highlighted in the editor. - This function is called when the [Spatial] this gizmo refers to changes (the [method Spatial.update_gizmo] is called). + Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method clear] at the beginning of this method and then add visual elements depending on the node's properties. - + - This function is used when the user drags a gizmo handle (previously added with [method add_handles]) in screen coordinates. - The [Camera] is also provided so screen coordinates can be converted to raycasts. + Override this method to update the node properties when the user drags a gizmo handle (previously added with [method add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts. + + + + + + + + + + + Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [code]transform[/code] is given in the Spatial's local coordinate system. + + + + + + + + + + + Override this method to allow selecting subgizmos using mouse drag box selection. Given a [code]camera[/code] and a [code]frustum[/code], this method should return which subgizmos are contained within the frustum. The [code]frustum[/code] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. + + + + + + + + + + + Override this method to allow selecting subgizmos using mouse clicks. Given a [code]camera[/code] and a [code]point[/code] in screen coordinates, this method should return which subgizmo should be selected. The returned value should be a unique subgizmo identifier, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. + + + + + + + Returns a list of the currently selected subgizmos. Can be used to highlight selected elements during [method _redraw]. + + + + + + + + + Returns [code]true[/code] if the given subgizmo is currently selected. Can be used to highlight selected elements during [method _redraw]. diff --git a/doc/classes/EditorSpatialGizmoPlugin.xml b/doc/classes/EditorSpatialGizmoPlugin.xml index 1ef9c15b2..26665f899 100644 --- a/doc/classes/EditorSpatialGizmoPlugin.xml +++ b/doc/classes/EditorSpatialGizmoPlugin.xml @@ -22,17 +22,34 @@ - Override this method to define whether the gizmo can be hidden or not. Returns [code]true[/code] if not overridden. + Override this method to define whether the gizmos handled by this plugin can be hidden or not. Returns [code]true[/code] if not overridden. - + - Override this method to commit gizmo handles. Called for this plugin's active gizmos. + Override this method to commit a handle being edited (handles must have been previously added by [method EditorSpatialGizmo.add_handles] during [method _redraw]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo". + If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action. Called for this plugin's active gizmos. + + + + + + + + + + + + + + + Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo". + If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action. Called for this plugin's active gizmos. @@ -76,7 +93,7 @@ - + Override this method to provide gizmo's handle names. Called for this plugin's active gizmos. @@ -84,9 +101,9 @@ - + - Gets actual value of a handle from gizmo. Called for this plugin's active gizmos. + Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle]. Called for this plugin's active gizmos. @@ -106,8 +123,19 @@ - Override this method to set the gizmo's priority. Higher values correspond to higher priority. If a gizmo with higher priority conflicts with another gizmo, only the gizmo with higher priority will be used. - All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically override built-in gizmos. + Override this method to set the gizmo's priority. Gizmos with higher priority will have precedence when processing inputs like handles or subgizmos selection. + All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically get higher priority than built-in gizmos. + + + + + + + + + + + Override this method to return the current transform of a subgizmo. This transform will be requested at the start of an edit and used in the [code]restore[/code] argument in [method _commit_subgizmos]. Called for this plugin's active gizmos. @@ -120,9 +148,9 @@ - + - Gets whether a handle is highlighted or not. Called for this plugin's active gizmos. + Override this method to return [code]true[/code] whenever to given handle should be highlighted in the editor. Called for this plugin's active gizmos. @@ -135,17 +163,56 @@ - Callback to redraw the provided gizmo. Called for this plugin's active gizmos. + Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method EditorSpatialGizmo.clear] at the beginning of this method and then add visual elements depending on the node's properties. - + - Update the value of a handle after it has been updated. Called for this plugin's active gizmos. + Override this method to update the node's properties when the user drags a gizmo handle (previously added with [method EditorSpatialGizmo.add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts. Called for this plugin's active gizmos. + + + + + + + + + + + + + Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [code]transform[/code] is given in the Spatial's local coordinate system. Called for this plugin's active gizmos. + + + + + + + + + + + + + Override this method to allow selecting subgizmos using mouse drag box selection. Given a [code]camera[/code] and a [code]frustum[/code], this method should return which subgizmos are contained within the frustum. The [code]frustum[/code] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, these identifiers can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos. + + + + + + + + + + + + + Override this method to allow selecting subgizmos using mouse clicks. Given a [code]camera[/code] and a [code]point[/code] in screen coordinates, this method should return which subgizmo should be selected. The returned value should be a unique subgizmo identifier, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos. diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml index dc9485244..092edfd6c 100644 --- a/doc/classes/Spatial.xml +++ b/doc/classes/Spatial.xml @@ -13,6 +13,29 @@ https://github.com/godotengine/godot-demo-projects/tree/master/3d + + + + + + + Attach a gizmo to this [code]Spatial[/code]. + + + + + + + Clear all gizmos attached to this [code]Spatial[/code]. + + + + + + + Clears subgizmo selection for this node in the editor. Useful when subgizmo IDs become invalid after a property change. + + @@ -26,6 +49,13 @@ This is particularly important for frame-based operations that take place in [method Node._process], rather than [method Node._physics_process]. Examples include [Camera]s focusing on a node, or finding where to fire lasers from on a frame rather than physics tick. + + + + + Returns all the gizmos attached to this [code]Spatial[/code]. + + @@ -242,17 +272,14 @@ Changes the node's position by the given offset [Vector3] in local space. - + - Updates the [SpatialGizmo] of this node. + Updates all the [SpatialGizmo]s attached to this node. - - The [SpatialGizmo] for this node. Used for example in [EditorSpatialGizmo] as custom visualization and editing handles in Editor. - Rotation part of the global transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle). [b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful. @@ -304,7 +331,7 @@ Spatial nodes receives this notification when their global transform changes. This means that either the current or a parent node changed its transform. - In order for [constant NOTIFICATION_TRANSFORM_CHANGED] to work, users first need to ask for it, with [method set_notify_transform]. The notification is also sent if the node is in the editor context and it has a valid gizmo. + In order for [constant NOTIFICATION_TRANSFORM_CHANGED] to work, users first need to ask for it, with [method set_notify_transform]. The notification is also sent if the node is in the editor context and it has at least one valid gizmo. Spatial nodes receives this notification when they are registered to new [World] resource. diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index c666125cf..e3d3cedeb 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -301,7 +301,7 @@ void PathSpatialGizmo::redraw() { add_handles(handles, handles_material); } if (sec_handles.size()) { - add_handles(sec_handles, handles_material, false, true); + add_handles(sec_handles, handles_material, Vector(), false, true); } } } diff --git a/editor/plugins/room_manager_editor_plugin.cpp b/editor/plugins/room_manager_editor_plugin.cpp index 9b605e925..f4920ae83 100644 --- a/editor/plugins/room_manager_editor_plugin.cpp +++ b/editor/plugins/room_manager_editor_plugin.cpp @@ -258,7 +258,7 @@ void OccluderEditorPlugin::_center() { undo_redo->add_undo_method(_occluder, "set_transform", old_local_xform); undo_redo->commit_action(); - _occluder->update_gizmo(); + _occluder->update_gizmos(); } } } diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index a2da615c6..f54fb4471 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -103,7 +103,6 @@ #define GIZMO_ARROW_SIZE 0.35 #define GIZMO_RING_HALF_WIDTH 0.1 -#define GIZMO_SCALE_DEFAULT 0.15 #define GIZMO_PLANE_SIZE 0.2 #define GIZMO_PLANE_DST 0.3 #define GIZMO_CIRCLE_SIZE 1.1 @@ -473,22 +472,35 @@ Vector3 SpatialEditorViewport::_get_ray(const Vector2 &p_pos) const { } void SpatialEditorViewport::_clear_selected() { - editor_selection->clear(); + _edit.gizmo = Ref(); + _edit.gizmo_handle = -1; + _edit.gizmo_initial_value = Variant(); + + Spatial *selected = spatial_editor->get_single_selected_node(); + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; + + if (se && se->gizmo.is_valid()) { + se->subgizmos.clear(); + se->gizmo->redraw(); + se->gizmo.unref(); + spatial_editor->update_transform_gizmo(); + } else { + editor_selection->clear(); + SpatialEditor::get_singleton()->edit(nullptr); + } } -void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) { - if (!clicked) { - return; - } - - Node *node = Object::cast_to(ObjectDB::get_instance(clicked)); +void SpatialEditorViewport::_select_clicked(bool p_allow_locked) { + Node *node = Object::cast_to(ObjectDB::get_instance(clicked)); Spatial *selected = Object::cast_to(node); + clicked = ObjectID(); + if (!selected) { return; } if (!p_allow_locked) { - // Replace the node by the group if grouped. + // Replace the node by the group if grouped while (node && node != editor->get_edited_scene()->get_parent()) { Spatial *selected_tmp = Object::cast_to(node); if (selected_tmp && node->has_meta("_edit_group_")) { @@ -499,34 +511,28 @@ void SpatialEditorViewport::_select_clicked(bool p_append, bool p_single, bool p } if (p_allow_locked || !_is_node_locked(selected)) { - _select(selected, clicked_wants_append, true); - } -} + if (clicked_wants_append) { + if (editor_selection->is_selected(selected)) { + editor_selection->remove_node(selected); + } else { + editor_selection->add_node(selected); + } + } else { + if (!editor_selection->is_selected(selected)) { + editor_selection->clear(); + editor_selection->add_node(selected); + editor->edit_node(selected); + } + } -void SpatialEditorViewport::_select(Node *p_node, bool p_append, bool p_single) { - if (!p_append) { - editor_selection->clear(); - } - - if (editor_selection->is_selected(p_node)) { - //erase - editor_selection->remove_node(p_node); - } else { - editor_selection->add_node(p_node); - } - - if (p_single) { - if (Engine::get_singleton()->is_editor_hint()) { - editor->call("edit_node", p_node); + if (editor_selection->get_selected_node_list().size() == 1) { + editor->edit_node(editor_selection->get_selected_node_list()[0]); + //editor->call("edit_node", p_node); } } } -ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) { - if (r_gizmo_handle) { - *r_gizmo_handle = -1; - } - +ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos) { Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / viewport_container->get_stretch_shrink(); @@ -535,10 +541,9 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, Set> found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); - ObjectID closest = 0; + ObjectID closest; Node *item = nullptr; float closest_dist = 1e20; - int selected_handle = -1; for (int i = 0; i < instances.size(); i++) { Spatial *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); @@ -547,38 +552,40 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, continue; } - Ref seg = spat->get_gizmo(); + Vector> gizmos = spat->get_gizmos(); - if ((!seg.is_valid()) || found_gizmos.has(seg)) { - continue; - } + for (int j = 0; j < gizmos.size(); j++) { + Ref seg = gizmos[j]; - found_gizmos.insert(seg); - Vector3 point; - Vector3 normal; - - int handle = -1; - bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal, &handle, p_alt_select); - - if (!inters) { - continue; - } - - float dist = pos.distance_to(point); - - if (dist < 0) { - continue; - } - - if (dist < closest_dist) { - item = Object::cast_to(spat); - if (item != edited_scene) { - item = edited_scene->get_deepest_editable_node(item); + if ((!seg.is_valid()) || found_gizmos.has(seg)) { + continue; } - closest = item->get_instance_id(); - closest_dist = dist; - selected_handle = handle; + found_gizmos.insert(seg); + Vector3 point; + Vector3 normal; + + bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal); + + if (!inters) { + continue; + } + + float dist = pos.distance_to(point); + + if (dist < 0) { + continue; + } + + if (dist < closest_dist) { + item = Object::cast_to(spat); + if (item != edited_scene) { + item = edited_scene->get_deepest_editable_node(item); + } + + closest = item->get_instance_id(); + closest_dist = dist; + } } } @@ -586,23 +593,15 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, return 0; } - if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle >= 0)) { - if (r_gizmo_handle) { - *r_gizmo_handle = selected_handle; - } - } - return closest; } -void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select) { +void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked_nodes) { Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); Vector instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); - Set> found_gizmos; - - r_includes_current = false; + Set found_nodes; for (int i = 0; i < instances.size(); i++) { Spatial *spat = Object::cast_to(ObjectDB::get_instance(instances[i])); @@ -611,49 +610,48 @@ void SpatialEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_incl continue; } - Ref seg = spat->get_gizmo(); - - if (!seg.is_valid()) { + if (found_nodes.has(spat)) { continue; } - if (found_gizmos.has(seg)) { + if (!p_include_locked_nodes && _is_node_locked(spat)) { continue; } - found_gizmos.insert(seg); - Vector3 point; - Vector3 normal; + Vector> gizmos = spat->get_gizmos(); + for (int j = 0; j < gizmos.size(); j++) { + Ref seg = gizmos[j]; - int handle = -1; - bool inters = seg->intersect_ray(camera, p_pos, point, normal, nullptr, p_alt_select); + if (!seg.is_valid()) { + continue; + } - if (!inters) { - continue; + Vector3 point; + Vector3 normal; + + bool inters = seg->intersect_ray(camera, p_pos, point, normal); + + if (!inters) { + continue; + } + + float dist = pos.distance_to(point); + + if (dist < 0) { + continue; + } + + found_nodes.insert(spat); + + _RayResult res; + res.item = spat; + res.depth = dist; + r_results.push_back(res); + break; } - - float dist = pos.distance_to(point); - - if (dist < 0) { - continue; - } - - if (editor_selection->is_selected(spat)) { - r_includes_current = true; - } - - _RayResult res; - res.item = spat; - res.depth = dist; - res.handle = handle; - results.push_back(res); } - if (results.empty()) { - return; - } - - results.sort(); + r_results.sort(); } Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { @@ -676,6 +674,9 @@ Vector3 SpatialEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) { void SpatialEditorViewport::_select_region() { if (cursor.region_begin == cursor.region_end) { + if (!clicked_wants_append) { + _clear_selected(); + } return; //nothing really } @@ -722,7 +723,66 @@ void SpatialEditorViewport::_select_region() { far.d += get_zfar(); frustum.push_back(far); + if (spatial_editor->get_single_selected_node()) { + Spatial *single_selected = spatial_editor->get_single_selected_node(); + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(single_selected); + + Ref old_gizmo; + if (!clicked_wants_append) { + se->subgizmos.clear(); + old_gizmo = se->gizmo; + se->gizmo.unref(); + } + + bool found_subgizmos = false; + Vector> gizmos = single_selected->get_gizmos(); + for (int j = 0; j < gizmos.size(); j++) { + Ref seg = gizmos[j]; + if (!seg.is_valid()) { + continue; + } + + if (se->gizmo.is_valid() && se->gizmo != seg) { + continue; + } + + Vector subgizmos = seg->subgizmos_intersect_frustum(camera, frustum); + if (!subgizmos.empty()) { + se->gizmo = seg; + for (int i = 0; i < subgizmos.size(); i++) { + int subgizmo_id = subgizmos[i]; + if (!se->subgizmos.has(subgizmo_id)) { + se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id)); + } + } + found_subgizmos = true; + break; + } + } + + if (!clicked_wants_append || found_subgizmos) { + if (se->gizmo.is_valid()) { + se->gizmo->redraw(); + } + + if (old_gizmo != se->gizmo && old_gizmo.is_valid()) { + old_gizmo->redraw(); + } + + spatial_editor->update_transform_gizmo(); + } + + if (found_subgizmos) { + return; + } + } + + if (!clicked_wants_append) { + _clear_selected(); + } + Vector instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario()); + Set found_nodes; Vector selected; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -733,6 +793,12 @@ void SpatialEditorViewport::_select_region() { continue; } + if (found_nodes.has(sp)) { + continue; + } + + found_nodes.insert(sp); + Node *item = Object::cast_to(sp); if (item != edited_scene) { item = edited_scene->get_deepest_editable_node(item); @@ -751,28 +817,31 @@ void SpatialEditorViewport::_select_region() { item = sel; } - if (selected.find(item) != -1) { - continue; - } - if (_is_node_locked(item)) { continue; } - Ref seg = sp->get_gizmo(); + Vector> gizmos = sp->get_gizmos(); + for (int j = 0; j < gizmos.size(); j++) { + Ref seg = gizmos[j]; + if (!seg.is_valid()) { + continue; + } - if (!seg.is_valid()) { - continue; - } - - if (seg->intersect_frustum(camera, frustum)) { - selected.push_back(item); + if (seg->intersect_frustum(camera, frustum)) { + selected.push_back(item); + } } } - bool single = selected.size() == 1; for (int i = 0; i < selected.size(); i++) { - _select(selected[i], true, single); + if (!editor_selection->is_selected(selected[i])) { + editor_selection->add_node(selected[i]); + } + } + + if (editor_selection->get_selected_node_list().size() == 1) { + editor->edit_node(editor_selection->get_selected_node_list()[0]); } } @@ -852,21 +921,34 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) { spatial_editor->update_transform_gizmo(); _edit.center = spatial_editor->get_gizmo_transform().origin; - List &selection = editor_selection->get_selected_node_list(); + Spatial *selected = spatial_editor->get_single_selected_node(); + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; - for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); - if (!sp) { - continue; + if (se && se->gizmo.is_valid()) { + for (Map::Element *E = se->subgizmos.front(); E; E = E->next()) { + int subgizmo_id = E->key(); + se->subgizmos[subgizmo_id] = se->gizmo->get_subgizmo_transform(subgizmo_id); } + se->original_local = selected->get_transform(); + se->original = selected->get_global_transform(); + } else { + List &selection = editor_selection->get_selected_node_list(); - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); - if (!se) { - continue; + for (List::Element *E = selection.front(); E; E = E->next()) { + Spatial *sp = Object::cast_to(E->get()); + if (!sp) { + continue; + } + + SpatialEditorSelectedItem *sel_item = editor_selection->get_node_editor_data(sp); + + if (!sel_item) { + continue; + } + + sel_item->original_local = sel_item->sp->get_local_gizmo_transform(); + sel_item->original = sel_item->sp->get_global_gizmo_transform(); } - - se->original = se->sp->get_global_gizmo_transform(); - se->original_local = se->sp->get_local_gizmo_transform(); } } @@ -902,10 +984,11 @@ static int _get_key_modifier(Ref e) { return 0; } -bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) { +bool SpatialEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) { if (!spatial_editor->is_gizmo_visible()) { return false; } + if (get_selected_count() == 0) { if (p_highlight_only && spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_EXTERNAL) { spatial_editor->select_gizmo_highlight_axis(-1); @@ -1096,6 +1179,88 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig return false; } +void SpatialEditorViewport::_transform_gizmo_apply(Spatial *p_node, const Transform &p_transform, bool p_local) { + if (p_transform.basis.determinant() == 0) { + return; + } + + if (p_local) { + p_node->set_transform(p_transform); + } else { + p_node->set_global_transform(p_transform); + } +} + +Transform SpatialEditorViewport::_compute_transform(TransformMode p_mode, const Transform &p_original, const Transform &p_original_local, Vector3 p_motion, double p_extra, bool p_local) { + switch (p_mode) { + case TRANSFORM_SCALE: { + if (p_local) { + Basis g = p_original.basis.orthonormalized(); + Vector3 local_motion = g.inverse().xform(p_motion); + + if (_edit.snap || spatial_editor->is_snap_enabled()) { + local_motion.snap(Vector3(p_extra, p_extra, p_extra)); + } + + Vector3 local_scale = p_original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1)); + Transform local_t = p_original_local; + local_t.basis.set_euler_scale(p_original_local.basis.get_rotation_euler(), local_scale); + return local_t; + } else { + Transform base = Transform(Basis(), _edit.center); + if (_edit.snap || spatial_editor->is_snap_enabled()) { + p_motion.snap(Vector3(p_extra, p_extra, p_extra)); + } + + Transform r; + r.basis.scale(p_motion + Vector3(1, 1, 1)); + return base * (r * (base.inverse() * p_original)); + } + } + case TRANSFORM_TRANSLATE: { + if (p_local) { + if (_edit.snap || spatial_editor->is_snap_enabled()) { + Basis g = p_original.basis.orthonormalized(); + Vector3 local_motion = g.inverse().xform(p_motion); + local_motion.snap(Vector3(p_extra, p_extra, p_extra)); + + p_motion = g.xform(local_motion); + } + + } else { + if (_edit.snap || spatial_editor->is_snap_enabled()) { + p_motion.snap(Vector3(p_extra, p_extra, p_extra)); + } + } + + // Apply translation + Transform t = p_original; + t.origin += p_motion; + return t; + } + case TRANSFORM_ROTATE: { + if (p_local) { + Basis rot = Basis(p_motion, p_extra); + + Vector3 scale = p_original_local.basis.get_scale(); + Vector3 euler = (p_original_local.get_basis().orthonormalized() * rot).get_euler(); + Transform t; + t.basis.set_euler_scale(euler, scale); + t.origin = p_original_local.origin; + return t; + } else { + Transform r; + r.basis.rotate(p_motion, p_extra); + Transform base = Transform(Basis(), _edit.center); + return base * r * base.inverse() * p_original; + } + } + default: { + ERR_FAIL_V_MSG(Transform(), "Invalid mode in '_compute_transform'"); + } + } +} + void SpatialEditorViewport::_surface_mouse_enter() { if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { surface->grab_focus(); @@ -1117,7 +1282,7 @@ bool SpatialEditorViewport ::_is_node_locked(const Node *p_node) { return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); } void SpatialEditorViewport::_list_select(Ref b) { - _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift()); + _find_items_at_pos(b->get_position(), selection_results, spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT); Node *scene = editor->get_edited_scene(); @@ -1138,8 +1303,7 @@ void SpatialEditorViewport::_list_select(Ref b) { selection_results.clear(); if (clicked) { - _select_clicked(clicked_wants_append, true, allow_locked); - clicked = 0; + _select_clicked(spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT); } } else if (!selection_results.empty()) { @@ -1286,7 +1450,20 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { continue; } - sp->set_global_transform(se->original); + if (se->gizmo.is_valid()) { + Vector ids; + Vector restore; + + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + ids.push_back(GE->key()); + restore.push_back(GE->value()); + } + + se->gizmo->commit_subgizmos(ids, restore, true); + spatial_editor->update_transform_gizmo(); + } else { + sp->set_global_transform(se->original); + } } surface->update(); set_message(TTR("Transform Aborted."), 3); @@ -1367,28 +1544,65 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { can_select_gizmos = view_menu->get_popup()->is_item_checked(idx); } - if (can_select_gizmos && spatial_editor->get_selected()) { - Ref seg = spatial_editor->get_selected()->get_gizmo(); - if (seg.is_valid()) { - int handle = -1; - Vector3 point; - Vector3 normal; - bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->get_shift()); - if (inters && handle != -1) { + if (can_select_gizmos && spatial_editor->get_single_selected_node()) { + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(spatial_editor->get_single_selected_node()); + Vector> gizmos = spatial_editor->get_single_selected_node()->get_gizmos(); + + bool intersected_handle = false; + for (int i = 0; i < gizmos.size(); i++) { + Ref seg = gizmos[i]; + + if ((!seg.is_valid())) { + continue; + } + + int subgizmo_id = seg->subgizmos_intersect_ray(camera, _edit.mouse_pos); + if (subgizmo_id != -1) { + ERR_CONTINUE(!se); + if (b->get_shift()) { + if (se->subgizmos.has(subgizmo_id)) { + se->subgizmos.erase(subgizmo_id); + } else { + se->subgizmos.insert(subgizmo_id, seg->get_subgizmo_transform(subgizmo_id)); + } + } else { + se->subgizmos.clear(); + se->subgizmos.insert(subgizmo_id, seg->get_subgizmo_transform(subgizmo_id)); + } + + if (se->subgizmos.empty()) { + se->gizmo = Ref(); + } else { + se->gizmo = seg; + } + + seg->redraw(); + spatial_editor->update_transform_gizmo(); + intersected_handle = true; + break; + } + + int gizmo_handle = -1; + seg->handles_intersect_ray(camera, _edit.mouse_pos, b->get_shift(), gizmo_handle); + if (gizmo_handle != -1) { _edit.gizmo = seg; - _edit.gizmo_handle = handle; - _edit.gizmo_initial_value = seg->get_handle_value(handle); + _edit.gizmo_handle = gizmo_handle; + _edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle); + intersected_handle = true; break; } } + + if (intersected_handle) { + break; + } } - if (_gizmo_select(_edit.mouse_pos)) { + if (_transform_gizmo_select(_edit.mouse_pos)) { break; } clicked = 0; - clicked_includes_current = false; if ((spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT && b->get_command()) || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_ROTATE) { /* HANDLE ROTATION */ @@ -1421,11 +1635,9 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { break; } - // todo scale + clicked = _select_ray(b->get_position()); - int gizmo_handle = -1; - - clicked = _select_ray(b->get_position(), b->get_shift(), clicked_includes_current, &gizmo_handle, b->get_shift()); + //TODO is this needed? selection_in_progress = true; //clicking is always deferred to either move or release @@ -1433,29 +1645,12 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { clicked_wants_append = b->get_shift(); if (!clicked) { - if (!clicked_wants_append) { - _clear_selected(); - } - //default to regionselect cursor.region_select = true; cursor.region_begin = b->get_position(); cursor.region_end = b->get_position(); } - if (clicked && gizmo_handle >= 0) { - Spatial *spa = Object::cast_to(ObjectDB::get_instance(clicked)); - if (spa) { - Ref seg = spa->get_gizmo(); - if (seg.is_valid()) { - _edit.gizmo = seg; - _edit.gizmo_handle = gizmo_handle; - _edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle); - break; - } - } - } - surface->update(); } else { if (_edit.gizmo.is_valid()) { @@ -1463,17 +1658,12 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { _edit.gizmo = Ref(); break; } + if (clicked) { - _select_clicked(clicked_wants_append, true); - // Processing was deferred. - clicked = 0; + _select_clicked(false); } if (cursor.region_select) { - if (!clicked_wants_append) { - _clear_selected(); - } - _select_region(); cursor.region_select = false; surface->update(); @@ -1481,32 +1671,43 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { selection_in_progress = false; if (_edit.mode != TRANSFORM_NONE) { - static const char *_transform_name[4] = { - TTRC("None"), - TTRC("Rotate"), - // TRANSLATORS: This refers to the movement that changes the position of an object. - TTRC("Translate"), - TTRC("Scale"), - }; - undo_redo->create_action(TTRGET(_transform_name[_edit.mode])); + Spatial *selected = spatial_editor->get_single_selected_node(); + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; - List &selection = editor_selection->get_selected_node_list(); + if (se && se->gizmo.is_valid()) { + Vector ids; + Vector restore; - for (List::Element *E = selection.front(); E; E = E->next()) { - Spatial *sp = Object::cast_to(E->get()); - if (!sp) { - continue; + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + ids.push_back(GE->key()); + restore.push_back(GE->value()); } - SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); - if (!se) { - continue; - } + se->gizmo->commit_subgizmos(ids, restore, false); + spatial_editor->update_transform_gizmo(); + } else { + static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" }; + undo_redo->create_action(_transform_name[_edit.mode]); - undo_redo->add_do_method(sp, "set_global_transform", sp->get_global_gizmo_transform()); - undo_redo->add_undo_method(sp, "set_global_transform", se->original); + List &selection = editor_selection->get_selected_node_list(); + + for (List::Element *E = selection.front(); E; E = E->next()) { + Spatial *sp = Object::cast_to(E->get()); + if (!sp) { + continue; + } + + SpatialEditorSelectedItem *sel_item = editor_selection->get_node_editor_data(sp); + if (!sel_item) { + continue; + } + + undo_redo->add_do_method(sp, "set_global_transform", sp->get_global_gizmo_transform()); + undo_redo->add_undo_method(sp, "set_global_transform", sel_item->original); + } + undo_redo->commit_action(); } - undo_redo->commit_action(); + _edit.mode = TRANSFORM_NONE; set_message(""); } @@ -1523,31 +1724,39 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { if (m.is_valid()) { _edit.mouse_pos = m->get_position(); - if (spatial_editor->get_selected()) { - Ref seg = spatial_editor->get_selected()->get_gizmo(); - if (seg.is_valid()) { - int selected_handle = -1; + if (spatial_editor->get_single_selected_node()) { + Vector> gizmos = spatial_editor->get_single_selected_node()->get_gizmos(); - int handle = -1; - Vector3 point; - Vector3 normal; - bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, false); - if (inters && handle != -1) { - selected_handle = handle; + Ref found_gizmo; + int found_handle = -1; + + for (int i = 0; i < gizmos.size(); i++) { + Ref seg = gizmos[i]; + if (!seg.is_valid()) { + continue; } - if (selected_handle != spatial_editor->get_over_gizmo_handle()) { - spatial_editor->set_over_gizmo_handle(selected_handle); - spatial_editor->get_selected()->update_gizmo(); - if (selected_handle != -1) { - spatial_editor->select_gizmo_highlight_axis(-1); - } + seg->handles_intersect_ray(camera, _edit.mouse_pos, false, found_handle); + + if (found_handle != -1) { + found_gizmo = seg; + break; } } + + if (found_gizmo.is_valid()) { + spatial_editor->select_gizmo_highlight_axis(-1); + } + + if (found_gizmo != spatial_editor->get_current_hover_gizmo() || found_handle != spatial_editor->get_current_hover_gizmo_handle()) { + spatial_editor->set_current_hover_gizmo(found_gizmo); + spatial_editor->set_current_hover_gizmo_handle(found_handle); + spatial_editor->get_single_selected_node()->update_gizmos(); + } } - if (spatial_editor->get_over_gizmo_handle() == -1 && !(m->get_button_mask() & 1) && !_edit.gizmo.is_valid()) { - _gizmo_select(_edit.mouse_pos, true); + if (spatial_editor->get_current_hover_gizmo().is_null() && !(m->get_button_mask() & 1) && !_edit.gizmo.is_valid()) { + _transform_gizmo_select(_edit.mouse_pos, true); } NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int(); @@ -1674,8 +1883,6 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { motion /= click.distance_to(_edit.center); - List &selection = editor_selection->get_selected_node_list(); - // Disable local transformation for TRANSFORM_VIEW bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); @@ -1688,6 +1895,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { set_message(TTR("Scaling: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " + String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")"); + List &selection = editor_selection->get_selected_node_list(); for (List::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to(E->get()); if (!sp) { @@ -1703,44 +1911,22 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { continue; } - Transform original = se->original; - Transform original_local = se->original_local; - Transform base = Transform(Basis(), _edit.center); - Transform t; - Vector3 local_scale; - - if (local_coords) { - Basis g = original.basis.orthonormalized(); - Vector3 local_motion = g.inverse().xform(motion); - - if (_edit.snap || spatial_editor->is_snap_enabled()) { - local_motion.snap(Vector3(snap, snap, snap)); + if (se->gizmo.is_valid()) { + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + Transform xform = GE->get(); + Transform new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords); + if (!local_coords) { + new_xform = se->original.inverse() * new_xform; + } + se->gizmo->set_subgizmo_transform(GE->key(), new_xform); } - - local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1)); - - // Prevent scaling to 0 it would break the gizmo - Basis check = original_local.basis; - check.scale(local_scale); - if (check.determinant() != 0) { - // Apply scale - sp->set_scale(local_scale); - } - } else { - if (_edit.snap || spatial_editor->is_snap_enabled()) { - motion.snap(Vector3(snap, snap, snap)); - } - - Transform r; - r.basis.scale(motion + Vector3(1, 1, 1)); - t = base * (r * (base.inverse() * original)); - - // Apply scale - sp->set_global_transform(t); + Transform new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords); + _transform_gizmo_apply(se->sp, new_xform, local_coords); } } + spatial_editor->update_transform_gizmo(); surface->update(); } break; @@ -1797,8 +1983,6 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { } } - List &selection = editor_selection->get_selected_node_list(); - // Disable local transformation for TRANSFORM_VIEW bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); @@ -1810,6 +1994,7 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { set_message(TTR("Translating: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " + String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")"); + List &selection = editor_selection->get_selected_node_list(); for (List::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to(E->get()); if (!sp) { @@ -1825,30 +2010,21 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { continue; } - Transform original = se->original; - Transform t; - - if (local_coords) { - if (_edit.snap || spatial_editor->is_snap_enabled()) { - Basis g = original.basis.orthonormalized(); - Vector3 local_motion = g.inverse().xform(motion); - local_motion.snap(Vector3(snap, snap, snap)); - - motion = g.xform(local_motion); + if (se->gizmo.is_valid()) { + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + Transform xform = GE->get(); + Transform new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords); + new_xform = se->original.inverse() * new_xform; + se->gizmo->set_subgizmo_transform(GE->key(), new_xform); } } else { - if (_edit.snap || spatial_editor->is_snap_enabled()) { - motion.snap(Vector3(snap, snap, snap)); - } + Transform new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords); + _transform_gizmo_apply(se->sp, new_xform, false); } - - // Apply translation - t = original; - t.origin += motion; - sp->set_global_transform(t); } + spatial_editor->update_transform_gizmo(); surface->update(); } break; @@ -1902,10 +2078,9 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals))); angle = Math::deg2rad(angle); - List &selection = editor_selection->get_selected_node_list(); - bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW + List &selection = editor_selection->get_selected_node_list(); for (List::Element *E = selection.front(); E; E = E->next()) { Spatial *sp = Object::cast_to(E->get()); if (!sp) { @@ -1921,32 +2096,24 @@ void SpatialEditorViewport::_sinput(const Ref &p_event) { continue; } - Transform t; - - if (local_coords) { - Transform original_local = se->original_local; - Basis rot = Basis(axis, angle); - - t.basis = original_local.get_basis().orthonormalized() * rot; - t.origin = original_local.origin; - - // Apply rotation - sp->set_transform(t); - sp->set_scale(original_local.basis.get_scale()); // re-apply original scale + Vector3 compute_axis = local_coords ? axis : plane.normal; + if (se->gizmo.is_valid()) { + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + Transform xform = GE->get(); + Transform new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords); + if (!local_coords) { + new_xform = se->original.inverse() * new_xform; + } + se->gizmo->set_subgizmo_transform(GE->key(), new_xform); + } } else { - Transform original = se->original; - Transform r; - Transform base = Transform(Basis(), _edit.center); - - r.basis.rotate(plane.normal, angle); - t = base * r * base.inverse() * original; - - // Apply rotation - sp->set_global_transform(t); + Transform new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords); + _transform_gizmo_apply(se->sp, new_xform, local_coords); } } + spatial_editor->update_transform_gizmo(); surface->update(); } break; @@ -3418,8 +3585,7 @@ void SpatialEditorViewport::_selection_result_pressed(int p_result) { clicked = selection_results[p_result].item->get_instance_id(); if (clicked) { - _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() != SpatialEditor::TOOL_MODE_LIST_SELECT); - clicked = 0; + _select_clicked(spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT); } } @@ -3730,6 +3896,13 @@ void SpatialEditorViewport::focus_selection() { continue; } + if (se->gizmo.is_valid()) { + for (Map::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) { + center += se->gizmo->get_subgizmo_transform(GE->key()).origin; + count++; + } + } + center += sp->get_global_gizmo_transform().origin; count++; } @@ -3747,6 +3920,9 @@ void SpatialEditorViewport::assign_pending_data_pointers(Spatial *p_preview_node accept = p_accept; } +/* +TODO how did I not have a commit from 5 years ago? +https://github.com/godotengine/godot/commit/d3cb8d12ff666477ecb1e3a935727b970de1f8e5 Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const { const float MAX_DISTANCE = 50.0; @@ -3764,6 +3940,72 @@ Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const return point; } +*/ + +Vector3 SpatialEditorViewport::_get_instance_position(const Point2 &p_pos) const { + const float MAX_DISTANCE = 10; + + Vector3 world_ray = _get_ray(p_pos); + Vector3 world_pos = _get_ray_pos(p_pos); + + Vector instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario()); + Set> found_gizmos; + + float closest_dist = MAX_DISTANCE; + + Vector3 point = world_pos + world_ray * MAX_DISTANCE; + Vector3 normal = Vector3(0.0, 0.0, 0.0); + + for (int i = 0; i < instances.size(); i++) { + MeshInstance *mesh_instance = Object::cast_to(ObjectDB::get_instance(instances[i])); + + if (!mesh_instance) { + continue; + } + + Vector> gizmos = mesh_instance->get_gizmos(); + + for (int j = 0; j < gizmos.size(); j++) { + Ref seg = gizmos[j]; + + if ((!seg.is_valid()) || found_gizmos.has(seg)) { + continue; + } + + found_gizmos.insert(seg); + + Vector3 hit_point; + Vector3 hit_normal; + bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal); + + if (!inters) { + continue; + } + + float dist = world_pos.distance_to(hit_point); + + if (dist < 0) { + continue; + } + + if (dist < closest_dist) { + closest_dist = dist; + point = hit_point; + normal = hit_normal; + } + } + } + + Vector3 offset = Vector3(); + for (int i = 0; i < 3; i++) { + if (normal[i] > 0.0) { + offset[i] = (preview_bounds->get_size()[i] - (preview_bounds->get_size()[i] + preview_bounds->get_position()[i])); + } else if (normal[i] < 0.0) { + offset[i] = -(preview_bounds->get_size()[i] + preview_bounds->get_position()[i]); + } + } + return point + offset; +} AABB SpatialEditorViewport::_calculate_spatial_bounds(const Spatial *p_parent, bool p_exclude_toplevel_transform) { AABB bounds; @@ -4085,9 +4327,8 @@ void SpatialEditorViewport::drop_data_fw(const Point2 &p_point, const Variant &p SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, EditorNode *p_editor, int p_index) { _edit.mode = TRANSFORM_NONE; _edit.plane = TRANSFORM_VIEW; - _edit.edited_gizmo = 0; _edit.snap = true; - _edit.gizmo_handle = 0; + _edit.gizmo_handle = -1; index = p_index; editor = p_editor; @@ -4095,7 +4336,6 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed editor_selection = editor->get_editor_selection(); undo_redo = editor->get_undo_redo(); clicked = 0; - clicked_includes_current = false; orthogonal = false; auto_orthogonal = false; lock_rotation = false; @@ -4118,7 +4358,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed surface->set_anchors_and_margins_preset(Control::PRESET_WIDE); surface->set_clip_contents(true); camera = memnew(Camera); - camera->set_disable_gizmo(true); + camera->set_disable_gizmos(true); camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER) | (1 << MISC_TOOL_LAYER)); viewport->add_child(camera); camera->make_current(); @@ -4701,6 +4941,7 @@ void SpatialEditor::update_portal_tools() { } } +/* void SpatialEditor::update_transform_gizmo() { AABB center; bool first = true; @@ -4762,12 +5003,68 @@ void SpatialEditor::update_transform_gizmo() { viewports[i]->update_transform_gizmo_view(); } } +*/ + +void SpatialEditor::update_transform_gizmo() { + int count = 0; + bool local_gizmo_coords = are_local_coords_enabled(); + + Vector3 gizmo_center; + Basis gizmo_basis; + + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; + + if (se && se->gizmo.is_valid()) { + for (Map::Element *E = se->subgizmos.front(); E; E = E->next()) { + Transform xf = se->sp->get_global_transform() * se->gizmo->get_subgizmo_transform(E->key()); + gizmo_center += xf.origin; + if (count == 0 && local_gizmo_coords) { + gizmo_basis = xf.basis; + gizmo_basis.orthonormalize(); + } + count++; + } + } else { + List &selection = editor_selection->get_selected_node_list(); + for (List::Element *E = selection.front(); E; E = E->next()) { + Spatial *sp = Object::cast_to(E->get()); + if (!sp) { + continue; + } + + if (sp->has_meta("_edit_lock_")) { + continue; + } + + SpatialEditorSelectedItem *sel_item = editor_selection->get_node_editor_data(sp); + if (!sel_item) { + continue; + } + + Transform xf = sel_item->sp->get_global_transform(); + gizmo_center += xf.origin; + if (count == 0 && local_gizmo_coords) { + gizmo_basis = xf.basis; + gizmo_basis.orthonormalize(); + } + count++; + } + } + + gizmo.visible = count > 0; + gizmo.transform.origin = (count > 0) ? gizmo_center / count : Vector3(); + gizmo.transform.basis = (count == 1) ? gizmo_basis : Basis(); + + for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { + viewports[i]->update_transform_gizmo_view(); + } +} void _update_all_gizmos(Node *p_node) { for (int i = p_node->get_child_count() - 1; 0 <= i; --i) { Spatial *spatial_node = Object::cast_to(p_node->get_child(i)); if (spatial_node) { - spatial_node->update_gizmo(); + spatial_node->update_gizmos(); } _update_all_gizmos(p_node->get_child(i)); @@ -5034,22 +5331,39 @@ Ref SpatialEditor::get_viewport_environment() { void SpatialEditor::edit(Spatial *p_spatial) { if (p_spatial != selected) { if (selected) { - Ref seg = selected->get_gizmo(); - if (seg.is_valid()) { + Vector> gizmos = selected->get_gizmos(); + for (int i = 0; i < gizmos.size(); i++) { + Ref seg = gizmos[i]; + if (!seg.is_valid()) { + continue; + } seg->set_selected(false); - selected->update_gizmo(); } + + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(selected); + if (se) { + se->gizmo.unref(); + se->subgizmos.clear(); + } + + selected->update_gizmos(); } selected = p_spatial; - over_gizmo_handle = -1; + current_hover_gizmo = Ref(); + current_hover_gizmo_handle = -1; if (selected) { - Ref seg = selected->get_gizmo(); - if (seg.is_valid()) { + Vector> gizmos = selected->get_gizmos(); + for (int i = 0; i < gizmos.size(); i++) { + Ref seg = gizmos[i]; + if (!seg.is_valid()) { + continue; + } seg->set_selected(true); - selected->update_gizmo(); } + + selected->update_gizmos(); } } } @@ -6152,13 +6466,28 @@ void SpatialEditor::update_grid() { _init_grid(); } -bool SpatialEditor::is_any_freelook_active() const { - for (unsigned int i = 0; i < VIEWPORTS_COUNT; ++i) { - if (viewports[i]->is_freelook_active()) { - return true; +void SpatialEditor::_selection_changed() { + _refresh_menu_icons(); + if (selected && editor_selection->get_selected_node_list().size() != 1) { + Vector> gizmos = selected->get_gizmos(); + for (int i = 0; i < gizmos.size(); i++) { + Ref seg = gizmos[i]; + if (!seg.is_valid()) { + continue; + } + seg->set_selected(false); } + + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(selected); + + if (se) { + se->gizmo.unref(); + se->subgizmos.clear(); + } + selected->update_gizmos(); + selected = nullptr; } - return false; + update_transform_gizmo(); } void SpatialEditor::_refresh_menu_icons() { @@ -6385,7 +6714,7 @@ void SpatialEditor::_notification(int p_what) { get_tree()->connect("node_removed", this, "_node_removed"); EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", this, "_refresh_menu_icons"); - editor_selection->connect("selection_changed", this, "_refresh_menu_icons"); + editor_selection->connect("selection_changed", this, "_selection_changed"); editor->connect("stop_pressed", this, "_update_camera_override_button", make_binds(false)); editor->connect("play_pressed", this, "_update_camera_override_button", make_binds(true)); @@ -6432,6 +6761,34 @@ void SpatialEditor::_notification(int p_what) { } } +bool SpatialEditor::is_subgizmo_selected(int p_id) { + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; + if (se) { + return se->subgizmos.has(p_id); + } + return false; +} + +bool SpatialEditor::is_current_selected_gizmo(const EditorSpatialGizmo *p_gizmo) { + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; + if (se) { + return se->gizmo == p_gizmo; + } + return false; +} + +Vector SpatialEditor::get_subgizmo_selection() { + SpatialEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data(selected) : nullptr; + + Vector ret; + if (se) { + for (Map::Element *E = se->subgizmos.front(); E; E = E->next()) { + ret.push_back(E->key()); + } + } + return ret; +} + void SpatialEditor::add_control_to_menu_panel(Control *p_control) { hbc_context_menu->add_child(p_control); } @@ -6506,23 +6863,45 @@ void SpatialEditor::_request_gizmo(Object *p_obj) { if (!sp) { return; } + + bool is_selected = (sp == selected); + if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_a_parent_of(sp)))) { Ref seg; for (int i = 0; i < gizmo_plugins_by_priority.size(); ++i) { - seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp); + Ref seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp); if (seg.is_valid()) { - sp->set_gizmo(seg); + sp->add_gizmo(seg); - if (sp == selected) { - seg->set_selected(true); - selected->update_gizmo(); + if (is_selected != seg->is_selected()) { + seg->set_selected(is_selected); } - - break; } } + sp->update_gizmos(); + } +} + +void SpatialEditor::_clear_subgizmo_selection(Object *p_obj) { + Spatial *sp = nullptr; + if (p_obj) { + sp = Object::cast_to(p_obj); + } else { + sp = selected; + } + + if (!sp) { + return; + } + + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + if (se) { + se->subgizmos.clear(); + se->gizmo.unref(); + sp->update_gizmos(); + update_transform_gizmo(); } } @@ -6581,7 +6960,15 @@ void SpatialEditor::_toggle_maximize_view(Object *p_viewport) { void SpatialEditor::_node_removed(Node *p_node) { if (p_node == selected) { + SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data(selected); + + if (se) { + se->gizmo.unref(); + se->subgizmos.clear(); + } + selected = nullptr; + update_transform_gizmo(); } } @@ -6618,12 +7005,14 @@ void SpatialEditor::_bind_methods() { ClassDB::bind_method("_xform_dialog_action", &SpatialEditor::_xform_dialog_action); ClassDB::bind_method("_get_editor_data", &SpatialEditor::_get_editor_data); ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo); + ClassDB::bind_method("_clear_subgizmo_selection", &SpatialEditor::_clear_subgizmo_selection); ClassDB::bind_method("_toggle_maximize_view", &SpatialEditor::_toggle_maximize_view); ClassDB::bind_method("_refresh_menu_icons", &SpatialEditor::_refresh_menu_icons); ClassDB::bind_method("_update_camera_override_button", &SpatialEditor::_update_camera_override_button); ClassDB::bind_method("_update_camera_override_viewport", &SpatialEditor::_update_camera_override_viewport); ClassDB::bind_method("_snap_changed", &SpatialEditor::_snap_changed); ClassDB::bind_method("_snap_update", &SpatialEditor::_snap_update); + ClassDB::bind_method("_selection_changed", &SpatialEditor::_selection_changed); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); @@ -7049,7 +7438,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::REAL, "editors/3d/manipulator_gizmo_opacity", PROPERTY_HINT_RANGE, "0,1,0.01")); EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true); - over_gizmo_handle = -1; + current_hover_gizmo_handle = -1; // make sure the portal tools are off by default // (when no RoomManager is present) @@ -7207,304 +7596,3 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) { SpatialEditorPlugin::~SpatialEditorPlugin() { } - -void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { - Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); - - Vector> mats; - - for (int i = 0; i < 4; i++) { - bool selected = i % 2 == 1; - bool instanced = i < 2; - - Ref material = Ref(memnew(SpatialMaterial)); - - Color color = instanced ? instanced_color : p_color; - - if (!selected) { - color.a *= 0.3; - } - - material->set_albedo(color); - material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - material->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN + 1); - - if (p_use_vertex_color) { - material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - } - - if (p_billboard) { - material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - } - - if (p_on_top && selected) { - material->set_on_top_of_alpha(); - } - - mats.push_back(material); - } - - materials[p_name] = mats; -} - -void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top, const Color &p_albedo) { - Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); - - Vector> icons; - - for (int i = 0; i < 4; i++) { - bool selected = i % 2 == 1; - bool instanced = i < 2; - - Ref icon = Ref(memnew(SpatialMaterial)); - - Color color = instanced ? instanced_color : p_albedo; - - if (!selected) { - color.a *= 0.85; - } - - icon->set_albedo(color); - - icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - icon->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - icon->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); - icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); - icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, p_texture); - icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); - icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - icon->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN); - - if (p_on_top && selected) { - icon->set_on_top_of_alpha(); - } - - icons.push_back(icon); - } - - materials[p_name] = icons; -} - -void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref &p_icon) { - Ref handle_material = Ref(memnew(SpatialMaterial)); - - handle_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); - handle_material->set_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); - - Ref handle_t = p_icon != nullptr ? p_icon : SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); - handle_material->set_point_size(handle_t->get_width()); - handle_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, handle_t); - handle_material->set_albedo(Color(1, 1, 1)); - handle_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); - handle_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - handle_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - handle_material->set_on_top_of_alpha(); - if (p_billboard) { - handle_material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - handle_material->set_on_top_of_alpha(); - } - - materials[p_name] = Vector>(); - materials[p_name].push_back(handle_material); -} - -void EditorSpatialGizmoPlugin::add_material(const String &p_name, Ref p_material) { - materials[p_name] = Vector>(); - materials[p_name].push_back(p_material); -} - -Ref EditorSpatialGizmoPlugin::get_material(const String &p_name, const Ref &p_gizmo) { - ERR_FAIL_COND_V(!materials.has(p_name), Ref()); - ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref()); - - if (p_gizmo.is_null() || materials[p_name].size() == 1) { - return materials[p_name][0]; - } - - int index = (p_gizmo->is_selected() ? 1 : 0) + (p_gizmo->is_editable() ? 2 : 0); - - Ref mat = materials[p_name][index]; - - if (current_state == ON_TOP && p_gizmo->is_selected()) { - mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true); - } else { - mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, false); - } - - return mat; -} - -String EditorSpatialGizmoPlugin::get_name() const { - if (get_script_instance() && get_script_instance()->has_method("get_name")) { - return get_script_instance()->call("get_name"); - } - WARN_PRINT_ONCE("A 3D editor gizmo has no name defined (it will appear as \"Unnamed Gizmo\" in the \"View > Gizmos\" menu). To resolve this, override the `get_name()` function to return a String in the script that extends EditorSpatialGizmoPlugin."); - return TTR("Unnamed Gizmo"); -} - -int EditorSpatialGizmoPlugin::get_priority() const { - if (get_script_instance() && get_script_instance()->has_method("get_priority")) { - return get_script_instance()->call("get_priority"); - } - return 0; -} - -Ref EditorSpatialGizmoPlugin::get_gizmo(Spatial *p_spatial) { - if (get_script_instance() && get_script_instance()->has_method("get_gizmo")) { - return get_script_instance()->call("get_gizmo", p_spatial); - } - - Ref ref = create_gizmo(p_spatial); - - if (ref.is_null()) { - return ref; - } - - ref->set_plugin(this); - ref->set_spatial_node(p_spatial); - ref->set_hidden(current_state == HIDDEN); - - current_gizmos.push_back(ref.ptr()); - return ref; -} - -void EditorSpatialGizmoPlugin::_bind_methods() { -#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorSpatialGizmo") - - BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); - BIND_VMETHOD(MethodInfo(GIZMO_REF, "create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); - - ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorSpatialGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorSpatialGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1))); - ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorSpatialGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant())); - ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorSpatialGizmoPlugin::add_material); - - ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorSpatialGizmoPlugin::get_material, DEFVAL(Ref())); - - BIND_VMETHOD(MethodInfo(Variant::STRING, "get_name")); - BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority")); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden")); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden")); - - BIND_VMETHOD(MethodInfo("redraw", GIZMO_REF)); - BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "index"))); - - MethodInfo hvget(Variant::NIL, "get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "index")); - hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - BIND_VMETHOD(hvget); - - BIND_VMETHOD(MethodInfo("set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); - MethodInfo cm = MethodInfo("commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); - cm.default_arguments.push_back(false); - BIND_VMETHOD(cm); - - BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "index"))); - -#undef GIZMO_REF -} - -bool EditorSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { - if (get_script_instance() && get_script_instance()->has_method("has_gizmo")) { - return get_script_instance()->call("has_gizmo", p_spatial); - } - return false; -} - -Ref EditorSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { - if (get_script_instance() && get_script_instance()->has_method("create_gizmo")) { - return get_script_instance()->call("create_gizmo", p_spatial); - } - - Ref ref; - if (has_gizmo(p_spatial)) { - ref.instance(); - } - return ref; -} - -bool EditorSpatialGizmoPlugin::can_be_hidden() const { - if (get_script_instance() && get_script_instance()->has_method("can_be_hidden")) { - return get_script_instance()->call("can_be_hidden"); - } - return true; -} - -bool EditorSpatialGizmoPlugin::is_selectable_when_hidden() const { - if (get_script_instance() && get_script_instance()->has_method("is_selectable_when_hidden")) { - return get_script_instance()->call("is_selectable_when_hidden"); - } - return false; -} - -void EditorSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { - if (get_script_instance() && get_script_instance()->has_method("redraw")) { - Ref ref(p_gizmo); - get_script_instance()->call("redraw", ref); - } -} - -String EditorSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) { - return get_script_instance()->call("get_handle_name", p_gizmo, p_idx); - } - return ""; -} - -Variant EditorSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { - if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) { - return get_script_instance()->call("get_handle_value", p_gizmo, p_idx); - } - return Variant(); -} - -void EditorSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { - if (get_script_instance() && get_script_instance()->has_method("set_handle")) { - get_script_instance()->call("set_handle", p_gizmo, p_idx, p_camera, p_point); - } -} - -void EditorSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { - if (get_script_instance() && get_script_instance()->has_method("commit_handle")) { - get_script_instance()->call("commit_handle", p_gizmo, p_idx, p_restore, p_cancel); - } -} - -bool EditorSpatialGizmoPlugin::is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) { - return get_script_instance()->call("is_handle_highlighted", p_gizmo, p_idx); - } - return false; -} - -void EditorSpatialGizmoPlugin::set_state(int p_state) { - current_state = p_state; - for (int i = 0; i < current_gizmos.size(); ++i) { - current_gizmos[i]->set_hidden(current_state == HIDDEN); - } -} - -int EditorSpatialGizmoPlugin::get_state() const { - return current_state; -} - -void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) { - current_gizmos.erase(p_gizmo); -} - -EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() { - current_state = VISIBLE; -} - -EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() { - for (int i = 0; i < current_gizmos.size(); ++i) { - current_gizmos[i]->set_plugin(nullptr); - current_gizmos[i]->get_spatial_node()->set_gizmo(nullptr); - } - if (SpatialEditor::get_singleton()) { - SpatialEditor::get_singleton()->update_all_gizmos(); - } -} diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index 7a1399c93..7f13a5c71 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -30,16 +30,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene/gui/control.h" +#include "editor/editor_plugin.h" +#include "scene/3d/spatial.h" #include "scene/gui/box_container.h" #include "scene/gui/container.h" -#include "scene/3d/spatial.h" -#include "editor/editor_plugin.h" +#include "scene/gui/control.h" #include "scene/3d/skeleton.h" #include "scene/gui/spin_box.h" -#include "core/reference.h" #include "core/color.h" #include "core/dictionary.h" #include "core/error_macros.h" @@ -52,6 +51,7 @@ #include "core/math/vector3.h" #include "core/object.h" #include "core/object_id.h" +#include "core/reference.h" #include "core/resource.h" #include "core/rid.h" #include "core/typedefs.h" @@ -60,6 +60,8 @@ #include "core/vector.h" #include "editor/editor_scale.h" +#include "editor/spatial_editor_gizmos.h" + #include "scene/resources/material.h" #include "scene/resources/mesh.h" #include "scene/resources/texture.h" @@ -67,6 +69,7 @@ class Camera; class SpatialEditor; class EditorSpatialGizmoPlugin; +class EditorSpatialGizmo; class ViewportContainer; class SpatialEditorViewport; class Environment; @@ -96,96 +99,6 @@ class VSplitContainer; class Viewport; class SpinBox; -class EditorSpatialGizmo : public SpatialGizmo { - GDCLASS(EditorSpatialGizmo, SpatialGizmo); - - bool selected; - bool instanced; - -public: - void set_selected(bool p_selected) { selected = p_selected; } - bool is_selected() const { return selected; } - - struct Instance { - RID instance; - Ref mesh; - Ref material; - Ref skin_reference; - RID skeleton; - bool billboard; - bool unscaled; - bool can_intersect; - bool extra_margin; - - Instance(); - ~Instance(); - - void create_instance(Spatial *p_base, bool p_hidden = false); - }; - - Vector collision_segments; - Ref collision_mesh; - - struct Handle { - Vector3 pos; - bool billboard; - }; - - Vector handles; - Vector secondary_handles; - float selectable_icon_size; - bool billboard_handle; - - bool valid; - bool hidden; - Spatial *base; - Vector instances; - Spatial *spatial_node; - EditorSpatialGizmoPlugin *gizmo_plugin; - - void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to(p_node)); } - -protected: - static void _bind_methods(); - -public: - void add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); - void add_vertices(const Vector &p_vertices, const Ref &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); - void add_mesh(const Ref &p_mesh, bool p_billboard = false, const Ref &p_skin_reference = Ref(), const Ref &p_material = Ref()); - void add_collision_segments(const Vector &p_lines); - void add_collision_triangles(const Ref &p_tmesh); - void add_unscaled_billboard(const Ref &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1)); - void add_handles(const Vector &p_handles, const Ref &p_material, bool p_billboard = false, bool p_secondary = false); - void add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position = Vector3()); - - virtual bool is_handle_highlighted(int p_idx) const; - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); - - void set_spatial_node(Spatial *p_node); - Spatial *get_spatial_node() const { return spatial_node; } - Ref get_plugin() const { return gizmo_plugin; } - Vector3 get_handle_pos(int p_idx) const; - bool intersect_frustum(const Camera *p_camera, const Vector &p_frustum); - bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = nullptr, bool p_sec_first = false); - - virtual void clear(); - virtual void create(); - virtual void transform(); - virtual void redraw(); - virtual void free(); - - virtual bool is_editable() const; - - void set_hidden(bool p_hidden); - void set_plugin(EditorSpatialGizmoPlugin *p_plugin); - - EditorSpatialGizmo(); - ~EditorSpatialGizmo(); -}; - class ViewportRotationControl : public Control { GDCLASS(ViewportRotationControl, Control); @@ -339,17 +252,15 @@ private: struct _RayResult { Spatial *item; float depth; - int handle; _FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; } }; void _update_name(); void _compute_edit(const Point2 &p_point); void _clear_selected(); - void _select_clicked(bool p_append, bool p_single, bool p_allow_locked = false); - void _select(Node *p_node, bool p_append, bool p_single); - ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = nullptr, bool p_alt_select = false); - void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false); + void _select_clicked(bool p_allow_locked); + ObjectID _select_ray(const Point2 &p_pos); + void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked); Vector3 _get_ray_pos(const Vector2 &p_pos) const; Vector3 _get_ray(const Vector2 &p_pos) const; Point2 _point_to_screen(const Vector3 &p_point); @@ -361,7 +272,8 @@ private: Vector3 _get_screen_to_space(const Vector3 &p_vector3); void _select_region(); - bool _gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false); + bool _transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false); + void _transform_gizmo_apply(Spatial *p_node, const Transform &p_transform, bool p_local); void _nav_pan(Ref p_event, const Vector2 &p_relative); void _nav_zoom(Ref p_event, const Vector2 &p_relative); @@ -374,7 +286,6 @@ private: ObjectID clicked; Vector<_RayResult> selection_results; - bool clicked_includes_current; bool clicked_wants_append; bool selection_in_progress = false; @@ -418,15 +329,12 @@ public: Vector3 click_ray; Vector3 click_ray_pos; Vector3 center; - Vector3 orig_gizmo_pos; - int edited_gizmo; Point2 mouse_pos; Point2 original_mouse_pos; bool snap; Ref gizmo; int gizmo_handle; Variant gizmo_initial_value; - Vector3 gizmo_initial_pos; } _edit; private: @@ -514,6 +422,8 @@ private: void _project_settings_changed(); + Transform _compute_transform(TransformMode p_mode, const Transform &p_original, const Transform &p_original_local, Vector3 p_motion, double p_extra, bool p_local); + protected: void _notification(int p_what); static void _bind_methods(); @@ -564,6 +474,8 @@ public: RID sbox_instance_offset; RID sbox_instance_xray; RID sbox_instance_xray_offset; + Ref gizmo; + Map subgizmos; // map ID -> initial transform SpatialEditorSelectedItem() { sp = nullptr; @@ -687,7 +599,9 @@ private: Ref plane_gizmo_color_hl[3]; Ref rotate_gizmo_color_hl[3]; - int over_gizmo_handle; + Ref current_hover_gizmo; + int current_hover_gizmo_handle; + float snap_translate_value; float snap_rotate_value; float snap_scale_value; @@ -763,7 +677,6 @@ private: LineEdit *snap_translate; LineEdit *snap_rotate; LineEdit *snap_scale; - PanelContainer *menu_panel; LineEdit *xform_translate[3]; LineEdit *xform_rotate[3]; @@ -814,6 +727,7 @@ private: Spatial *selected; void _request_gizmo(Object *p_obj); + void _clear_subgizmo_selection(Object *p_obj = nullptr); static SpatialEditor *singleton; @@ -823,8 +737,7 @@ private: void _register_all_gizmos(); - bool is_any_freelook_active() const; - + void _selection_changed(); void _refresh_menu_icons(); protected: @@ -891,10 +804,16 @@ public: VSplitContainer *get_shader_split(); - Spatial *get_selected() { return selected; } + Spatial *get_single_selected_node() { return selected; } + bool is_current_selected_gizmo(const EditorSpatialGizmo *p_gizmo); + bool is_subgizmo_selected(int p_id); + Vector get_subgizmo_selection(); - int get_over_gizmo_handle() const { return over_gizmo_handle; } - void set_over_gizmo_handle(int idx) { over_gizmo_handle = idx; } + Ref get_current_hover_gizmo() const { return current_hover_gizmo; } + void set_current_hover_gizmo(Ref p_gizmo) { current_hover_gizmo = p_gizmo; } + + void set_current_hover_gizmo_handle(int p_id) { current_hover_gizmo_handle = p_id; } + int get_current_hover_gizmo_handle() const { return current_hover_gizmo_handle; } void set_can_preview(Camera *p_preview); void set_message(String p_message, float p_time = 5); @@ -962,50 +881,4 @@ public: ~SpatialEditorPlugin(); }; -class EditorSpatialGizmoPlugin : public Resource { - GDCLASS(EditorSpatialGizmoPlugin, Resource); - -public: - static const int VISIBLE = 0; - static const int HIDDEN = 1; - static const int ON_TOP = 2; - -protected: - int current_state; - List current_gizmos; - HashMap>> materials; - - static void _bind_methods(); - virtual bool has_gizmo(Spatial *p_spatial); - virtual Ref create_gizmo(Spatial *p_spatial); - -public: - void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); - void create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1)); - void create_handle_material(const String &p_name, bool p_billboard = false, const Ref &p_icon = nullptr); - void add_material(const String &p_name, Ref p_material); - - Ref get_material(const String &p_name, const Ref &p_gizmo = Ref()); - - virtual String get_name() const; - virtual int get_priority() const; - virtual bool can_be_hidden() const; - virtual bool is_selectable_when_hidden() const; - - virtual void redraw(EditorSpatialGizmo *p_gizmo); - virtual String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - virtual Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - virtual void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); - virtual bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - - Ref get_gizmo(Spatial *p_spatial); - void set_state(int p_state); - int get_state() const; - void unregister_gizmo(EditorSpatialGizmo *p_gizmo); - - EditorSpatialGizmoPlugin(); - virtual ~EditorSpatialGizmoPlugin(); -}; - #endif diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index f7e443adb..f57268674 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -143,58 +143,122 @@ void EditorSpatialGizmo::clear() { void EditorSpatialGizmo::redraw() { if (get_script_instance() && get_script_instance()->has_method("redraw")) { get_script_instance()->call("redraw"); - return; + } else { + ERR_FAIL_COND(!gizmo_plugin); + gizmo_plugin->redraw(this); } - ERR_FAIL_COND(!gizmo_plugin); - gizmo_plugin->redraw(this); + if (SpatialEditor::get_singleton()->is_current_selected_gizmo(this)) { + SpatialEditor::get_singleton()->update_transform_gizmo(); + } } -String EditorSpatialGizmo::get_handle_name(int p_idx) const { +String EditorSpatialGizmo::get_handle_name(int p_id) const { if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) { - return get_script_instance()->call("get_handle_name", p_idx); + return get_script_instance()->call("get_handle_name", p_id); } ERR_FAIL_COND_V(!gizmo_plugin, ""); - return gizmo_plugin->get_handle_name(this, p_idx); + return gizmo_plugin->get_handle_name(this, p_id); } -bool EditorSpatialGizmo::is_handle_highlighted(int p_idx) const { +bool EditorSpatialGizmo::is_handle_highlighted(int p_id) const { if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) { - return get_script_instance()->call("is_handle_highlighted", p_idx); + return get_script_instance()->call("is_handle_highlighted", p_id); } ERR_FAIL_COND_V(!gizmo_plugin, false); - return gizmo_plugin->is_handle_highlighted(this, p_idx); + return gizmo_plugin->is_handle_highlighted(this, p_id); } -Variant EditorSpatialGizmo::get_handle_value(int p_idx) { +Variant EditorSpatialGizmo::get_handle_value(int p_id) { if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) { - return get_script_instance()->call("get_handle_value", p_idx); + return get_script_instance()->call("get_handle_value", p_id); } ERR_FAIL_COND_V(!gizmo_plugin, Variant()); - return gizmo_plugin->get_handle_value(this, p_idx); + return gizmo_plugin->get_handle_value(this, p_id); } -void EditorSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void EditorSpatialGizmo::set_handle(int p_id, Camera *p_camera, const Point2 &p_point) { if (get_script_instance() && get_script_instance()->has_method("set_handle")) { - get_script_instance()->call("set_handle", p_idx, p_camera, p_point); + get_script_instance()->call("set_handle", p_id, p_camera, p_point); return; } ERR_FAIL_COND(!gizmo_plugin); - gizmo_plugin->set_handle(this, p_idx, p_camera, p_point); + gizmo_plugin->set_handle(this, p_id, p_camera, p_point); } -void EditorSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void EditorSpatialGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) { if (get_script_instance() && get_script_instance()->has_method("commit_handle")) { - get_script_instance()->call("commit_handle", p_idx, p_restore, p_cancel); + get_script_instance()->call("commit_handle", p_id, p_restore, p_cancel); return; } ERR_FAIL_COND(!gizmo_plugin); - gizmo_plugin->commit_handle(this, p_idx, p_restore, p_cancel); + gizmo_plugin->commit_handle(this, p_id, p_restore, p_cancel); +} + +int EditorSpatialGizmo::subgizmos_intersect_ray(Camera *p_camera, const Vector2 &p_point) const { + if (get_script_instance() && get_script_instance()->has_method("subgizmos_intersect_ray")) { + return get_script_instance()->call("subgizmos_intersect_ray", p_camera, p_point); + } + + ERR_FAIL_COND_V(!gizmo_plugin, -1); + return gizmo_plugin->subgizmos_intersect_ray(this, p_camera, p_point); +} + +Vector EditorSpatialGizmo::subgizmos_intersect_frustum(const Camera *p_camera, const Vector &p_frustum) const { + if (get_script_instance() && get_script_instance()->has_method("subgizmos_intersect_frustum")) { + Array frustum; + for (int i = 0; i < p_frustum.size(); i++) { + frustum[i] = p_frustum[i]; + } + return get_script_instance()->call("subgizmos_intersect_frustum", p_camera, frustum); + } + + ERR_FAIL_COND_V(!gizmo_plugin, Vector()); + return gizmo_plugin->subgizmos_intersect_frustum(this, p_camera, p_frustum); +} + +Transform EditorSpatialGizmo::get_subgizmo_transform(int p_id) const { + if (get_script_instance() && get_script_instance()->has_method("get_subgizmo_transform")) { + return get_script_instance()->call("get_subgizmo_transform", p_id); + } + + ERR_FAIL_COND_V(!gizmo_plugin, Transform()); + return gizmo_plugin->get_subgizmo_transform(this, p_id); +} + +void EditorSpatialGizmo::set_subgizmo_transform(int p_id, Transform p_transform) const { + if (get_script_instance() && get_script_instance()->has_method("set_subgizmo_transform")) { + get_script_instance()->call("set_subgizmo_transform", p_id, p_transform); + return; + } + + ERR_FAIL_COND(!gizmo_plugin); + gizmo_plugin->set_subgizmo_transform(this, p_id, p_transform); +} + +void EditorSpatialGizmo::commit_subgizmos(const Vector &p_ids, const Vector &p_restore, bool p_cancel) const { + if (get_script_instance() && get_script_instance()->has_method("_commit_subgizmos")) { + Array ids; + for (int i = 0; i < p_ids.size(); i++) { + ids[i] = p_ids[i]; + } + + Array restore; + for (int i = 0; i < p_restore.size(); i++) { + restore[i] = p_restore[i]; + } + + get_script_instance()->call("_commit_subgizmos", ids, restore, p_cancel); + return; + } + + ERR_FAIL_COND(!gizmo_plugin); + gizmo_plugin->commit_subgizmos(this, p_ids, p_restore, p_cancel); } void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { @@ -203,9 +267,6 @@ void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { } EditorSpatialGizmo::Instance::Instance() { - billboard = false; - unscaled = false; - can_intersect = false; extra_margin = false; } @@ -227,19 +288,20 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base, bool p_hidde VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 } -void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const Ref &p_skin_reference, const Ref &p_material) { +void EditorSpatialGizmo::add_mesh(const Ref &p_mesh, const Ref &p_material, const Transform &p_xform, const Ref &p_skin_reference) { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND_MSG(!p_mesh.is_valid(), "EditorSpatialGizmo.add_mesh() requires a valid Mesh resource."); Instance ins; - ins.billboard = p_billboard; ins.mesh = p_mesh; ins.skin_reference = p_skin_reference; ins.material = p_material; + ins.xform = p_xform; + if (valid) { ins.create_instance(spatial_node, hidden); - VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); + VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform() * ins.xform); if (ins.material.is_valid()) { VS::get_singleton()->instance_geometry_set_material_override(ins.instance, p_material->get_rid()); } @@ -290,7 +352,6 @@ void EditorSpatialGizmo::add_lines(const Vector &p_lines, const Ref &p_vertices, const R } } - ins.billboard = p_billboard; ins.mesh = mesh; if (valid) { ins.create_instance(spatial_node, hidden); @@ -396,8 +456,6 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref &p_material, mesh->set_custom_aabb(AABB(Vector3(-selectable_icon_size, -selectable_icon_size, -selectable_icon_size) * 100.0f, Vector3(selectable_icon_size, selectable_icon_size, selectable_icon_size) * 200.0f)); ins.mesh = mesh; - ins.unscaled = true; - ins.billboard = true; if (valid) { ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); @@ -420,7 +478,7 @@ void EditorSpatialGizmo::add_collision_segments(const Vector &p_lines) } } -void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref &p_material, bool p_billboard, bool p_secondary) { +void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref &p_material, const Vector &p_ids, bool p_billboard, bool p_secondary) { billboard_handle = p_billboard; if (!is_selected() || !is_editable()) { @@ -429,6 +487,15 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref ERR_FAIL_COND(!spatial_node); + if (p_ids.empty()) { + ERR_FAIL_COND_MSG((!handles.empty() && !handle_ids.empty()) || (!secondary_handles.empty() && !secondary_handle_ids.empty()), "Fail"); + } else { + ERR_FAIL_COND_MSG(handles.size() != handle_ids.size() || secondary_handles.size() != secondary_handle_ids.size(), "Fail"); + } + + bool is_current_hover_gizmo = SpatialEditor::get_singleton()->get_current_hover_gizmo() == this; + int current_hover_handle = SpatialEditor::get_singleton()->get_current_hover_gizmo_handle(); + Instance ins; Ref mesh = memnew(ArrayMesh); @@ -446,7 +513,8 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref col = Color(0, 0, 1, 0.9); } - if (SpatialEditor::get_singleton()->get_over_gizmo_handle() != i) { + int id = p_ids.empty() ? i : p_ids[i]; + if (!is_current_hover_gizmo || current_hover_handle != id) { col.a = 0.8; } @@ -468,29 +536,30 @@ void EditorSpatialGizmo::add_handles(const Vector &p_handles, const Ref } ins.mesh = mesh; - ins.billboard = p_billboard; ins.extra_margin = true; if (valid) { ins.create_instance(spatial_node, hidden); VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } instances.push_back(ins); - if (!p_secondary) { - int chs = handles.size(); - handles.resize(chs + p_handles.size()); - for (int i = 0; i < p_handles.size(); i++) { - handles.write[i + chs] = p_handles[i]; - } - } else { - int chs = secondary_handles.size(); - secondary_handles.resize(chs + p_handles.size()); - for (int i = 0; i < p_handles.size(); i++) { - secondary_handles.write[i + chs] = p_handles[i]; + Vector &h = p_secondary ? secondary_handles : handles; + int current_size = h.size(); + h.resize(current_size + p_handles.size()); + for (int i = 0; i < p_handles.size(); i++) { + h.write[current_size + i] = p_handles[i]; + } + + if (!p_ids.empty()) { + Vector &ids = p_secondary ? secondary_handle_ids : handle_ids; + current_size = ids.size(); + ids.resize(current_size + p_ids.size()); + for (int i = 0; i < p_ids.size(); i++) { + ids.write[current_size + i] = p_ids[i]; } } } -void EditorSpatialGizmo::add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position) { +void EditorSpatialGizmo::add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position, const Transform &p_xform) { ERR_FAIL_COND(!spatial_node); CubeMesh cubem; @@ -508,8 +577,7 @@ void EditorSpatialGizmo::add_solid_box(Ref &p_material, Vector3 p_size Ref m = memnew(ArrayMesh); m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), arrays); - m->surface_set_material(0, p_material); - add_mesh(m); + add_mesh(m, p_material, p_xform); } bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector &p_frustum) { @@ -574,14 +642,15 @@ bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector< Transform it = t.affine_inverse(); Vector transformed_frustum; + int plane_count = p_frustum.size(); + transformed_frustum.resize(plane_count); - for (int i = 0; i < p_frustum.size(); i++) { - transformed_frustum.push_back(it.xform(p_frustum[i])); + for (int i = 0; i < plane_count; i++) { + transformed_frustum.write[i] = it.xform(p_frustum[i]); } - Vector convex_points = Geometry::compute_convex_mesh_points(p_frustum.ptr(), p_frustum.size()); - - if (collision_mesh->inside_convex_shape(transformed_frustum.ptr(), transformed_frustum.size(), convex_points.ptr(), convex_points.size(), mesh_scale)) { + Vector convex_points = Geometry::compute_convex_mesh_points(transformed_frustum.ptr(), plane_count); + if (collision_mesh->inside_convex_shape(transformed_frustum.ptr(), plane_count, convex_points.ptr(), convex_points.size(), mesh_scale)) { return true; } } @@ -589,7 +658,66 @@ bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector< return false; } -bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) { +void EditorSpatialGizmo::handles_intersect_ray(Camera *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id) { + r_id = -1; + + ERR_FAIL_COND(!spatial_node); + ERR_FAIL_COND(!valid); + + if (hidden) { + return; + } + + Transform camera_xform = p_camera->get_global_transform(); + Transform t = spatial_node->get_global_transform(); + if (billboard_handle) { + t.set_look_at(t.origin, t.origin - camera_xform.basis.get_axis(2), camera_xform.basis.get_axis(1)); + } + + float min_d = 1e20; + + for (int i = 0; i < secondary_handles.size(); i++) { + Vector3 hpos = t.xform(secondary_handles[i]); + Vector2 p = p_camera->unproject_position(hpos); + + if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { + real_t dp = p_camera->get_transform().origin.distance_to(hpos); + if (dp < min_d) { + min_d = dp; + if (secondary_handle_ids.empty()) { + r_id = i; + } else { + r_id = secondary_handle_ids[i]; + } + } + } + } + + if (r_id != -1 && p_shift_pressed) { + return; + } + + min_d = 1e20; + + for (int i = 0; i < handles.size(); i++) { + Vector3 hpos = t.xform(handles[i]); + Vector2 p = p_camera->unproject_position(hpos); + + if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { + real_t dp = p_camera->get_transform().origin.distance_to(hpos); + if (dp < min_d) { + min_d = dp; + if (handle_ids.empty()) { + r_id = i; + } else { + r_id = handle_ids[i]; + } + } + } + } +} + +bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal) { ERR_FAIL_COND_V(!spatial_node, false); ERR_FAIL_COND_V(!valid, false); @@ -597,58 +725,6 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, return false; } - if (r_gizmo_handle && !hidden) { - Transform t = spatial_node->get_global_transform(); - if (billboard_handle) { - t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); - } - - float min_d = 1e20; - int idx = -1; - - for (int i = 0; i < secondary_handles.size(); i++) { - Vector3 hpos = t.xform(secondary_handles[i]); - Vector2 p = p_camera->unproject_position(hpos); - - if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { - real_t dp = p_camera->get_transform().origin.distance_to(hpos); - if (dp < min_d) { - r_pos = t.xform(hpos); - r_normal = p_camera->get_transform().basis.get_axis(2); - min_d = dp; - idx = i + handles.size(); - } - } - } - - if (p_sec_first && idx != -1) { - *r_gizmo_handle = idx; - return true; - } - - min_d = 1e20; - - for (int i = 0; i < handles.size(); i++) { - Vector3 hpos = t.xform(handles[i]); - Vector2 p = p_camera->unproject_position(hpos); - - if (p.distance_to(p_point) < HANDLE_HALF_SIZE) { - real_t dp = p_camera->get_transform().origin.distance_to(hpos); - if (dp < min_d) { - r_pos = t.xform(hpos); - r_normal = p_camera->get_transform().basis.get_axis(2); - min_d = dp; - idx = i; - } - } - } - - if (idx >= 0) { - *r_gizmo_handle = idx; - return true; - } - } - if (selectable_icon_size > 0.0f) { Transform t = spatial_node->get_global_transform(); Vector3 camera_position = p_camera->get_camera_transform().origin; @@ -764,6 +840,25 @@ bool EditorSpatialGizmo::intersect_ray(Camera *p_camera, const Point2 &p_point, return false; } +bool EditorSpatialGizmo::is_subgizmo_selected(int p_id) const { + SpatialEditor *ed = SpatialEditor::get_singleton(); + ERR_FAIL_COND_V(!ed, false); + return ed->is_current_selected_gizmo(this) && ed->is_subgizmo_selected(p_id); +} + +Vector EditorSpatialGizmo::get_subgizmo_selection() const { + Vector ret; + + SpatialEditor *ed = SpatialEditor::get_singleton(); + ERR_FAIL_COND_V(!ed, ret); + + if (ed->is_current_selected_gizmo(this)) { + ret = ed->get_subgizmo_selection(); + } + + return ret; +} + void EditorSpatialGizmo::create() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(valid); @@ -780,7 +875,7 @@ void EditorSpatialGizmo::transform() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(!valid); for (int i = 0; i < instances.size(); i++) { - VS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform()); + VS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform() * instances[i].xform); } } @@ -814,38 +909,46 @@ void EditorSpatialGizmo::set_plugin(EditorSpatialGizmoPlugin *p_plugin) { void EditorSpatialGizmo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard", "modulate"), &EditorSpatialGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1))); - ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorSpatialGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref()), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "material", "transform", "skeleton"), &EditorSpatialGizmo::add_mesh, DEFVAL(Variant()), DEFVAL(Transform()), DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorSpatialGizmo::add_collision_segments); ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorSpatialGizmo::add_collision_triangles); ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale", "modulate"), &EditorSpatialGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1))); - ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "ids", "billboard", "secondary"), &EditorSpatialGizmo::add_handles, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorSpatialGizmo::_set_spatial_node); ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorSpatialGizmo::get_spatial_node); ClassDB::bind_method(D_METHOD("get_plugin"), &EditorSpatialGizmo::get_plugin); ClassDB::bind_method(D_METHOD("clear"), &EditorSpatialGizmo::clear); ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorSpatialGizmo::set_hidden); + ClassDB::bind_method(D_METHOD("is_subgizmo_selected"), &EditorSpatialGizmo::is_subgizmo_selected); + ClassDB::bind_method(D_METHOD("get_subgizmo_selection"), &EditorSpatialGizmo::get_subgizmo_selection); BIND_VMETHOD(MethodInfo("redraw")); - BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "index"))); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", PropertyInfo(Variant::INT, "index"))); + BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", PropertyInfo(Variant::INT, "id"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", PropertyInfo(Variant::INT, "id"))); - MethodInfo hvget(Variant::NIL, "get_handle_value", PropertyInfo(Variant::INT, "index")); + MethodInfo hvget(Variant::NIL, "get_handle_value", PropertyInfo(Variant::INT, "id")); hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; BIND_VMETHOD(hvget); - BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); - MethodInfo cm = MethodInfo("commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); + BIND_VMETHOD(MethodInfo("set_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + MethodInfo cm = MethodInfo("commit_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); cm.default_arguments.push_back(false); BIND_VMETHOD(cm); + + BIND_VMETHOD(MethodInfo(Variant::INT, "subgizmos_intersect_ray", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + BIND_VMETHOD(MethodInfo(Variant::POOL_INT_ARRAY, "subgizmos_intersect_frustum", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::ARRAY, "frustum"))); + BIND_VMETHOD(MethodInfo(Variant::TRANSFORM, "get_subgizmo_transform", PropertyInfo(Variant::INT, "id"))); + BIND_VMETHOD(MethodInfo("set_subgizmo_transform", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM, "transform"))); + MethodInfo cs = MethodInfo("commit_subgizmos", PropertyInfo(Variant::POOL_INT_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel")); + cs.default_arguments.push_back(false); + BIND_VMETHOD(cs); } EditorSpatialGizmo::EditorSpatialGizmo() { valid = false; billboard_handle = false; hidden = false; - base = nullptr; selected = false; - instanced = false; spatial_node = nullptr; gizmo_plugin = nullptr; selectable_icon_size = -1.0f; @@ -858,10 +961,364 @@ EditorSpatialGizmo::~EditorSpatialGizmo() { clear(); } -Vector3 EditorSpatialGizmo::get_handle_pos(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, handles.size(), Vector3()); +//// GizmoPlugin - return handles[p_idx]; +void EditorSpatialGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) { + Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); + + Vector> mats; + + for (int i = 0; i < 4; i++) { + bool selected = i % 2 == 1; + bool instanced = i < 2; + + Ref material = Ref(memnew(SpatialMaterial)); + + Color color = instanced ? instanced_color : p_color; + + if (!selected) { + color.a *= 0.3; + } + + material->set_albedo(color); + material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + material->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN + 1); + material->set_cull_mode(SpatialMaterial::CULL_DISABLED); + + if (p_use_vertex_color) { + material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + } + + if (p_billboard) { + material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + } + + if (p_on_top && selected) { + material->set_on_top_of_alpha(); + } + + mats.push_back(material); + } + + materials[p_name] = mats; +} + +void EditorSpatialGizmoPlugin::create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top, const Color &p_albedo) { + Color instanced_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instanced", Color(0.7, 0.7, 0.7, 0.6)); + + Vector> icons; + + for (int i = 0; i < 4; i++) { + bool selected = i % 2 == 1; + bool instanced = i < 2; + + Ref icon = Ref(memnew(SpatialMaterial)); + + Color color = instanced ? instanced_color : p_albedo; + + if (!selected) { + color.a *= 0.85; + } + + icon->set_albedo(color); + + icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + icon->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + icon->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, p_texture); + icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); + icon->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + icon->set_render_priority(SpatialMaterial::RENDER_PRIORITY_MIN); + + if (p_on_top && selected) { + icon->set_on_top_of_alpha(); + } + + icons.push_back(icon); + } + + materials[p_name] = icons; +} + +void EditorSpatialGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref &p_icon) { + Ref handle_material = Ref(memnew(SpatialMaterial)); + + handle_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + handle_material->set_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); + + Ref handle_t = p_icon != nullptr ? p_icon : SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); + handle_material->set_point_size(handle_t->get_width()); + handle_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, handle_t); + handle_material->set_albedo(Color(1, 1, 1)); + handle_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + handle_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + handle_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + handle_material->set_on_top_of_alpha(); + if (p_billboard) { + handle_material->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + handle_material->set_on_top_of_alpha(); + } + + materials[p_name] = Vector>(); + materials[p_name].push_back(handle_material); +} + +void EditorSpatialGizmoPlugin::add_material(const String &p_name, Ref p_material) { + materials[p_name] = Vector>(); + materials[p_name].push_back(p_material); +} + +Ref EditorSpatialGizmoPlugin::get_material(const String &p_name, const Ref &p_gizmo) { + ERR_FAIL_COND_V(!materials.has(p_name), Ref()); + ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref()); + + if (p_gizmo.is_null() || materials[p_name].size() == 1) { + return materials[p_name][0]; + } + + int index = (p_gizmo->is_selected() ? 1 : 0) + (p_gizmo->is_editable() ? 2 : 0); + + Ref mat = materials[p_name][index]; + + if (current_state == ON_TOP && p_gizmo->is_selected()) { + mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, true); + } else { + mat->set_flag(SpatialMaterial::FLAG_DISABLE_DEPTH_TEST, false); + } + + return mat; +} + +String EditorSpatialGizmoPlugin::get_gizmo_name() const { + if (get_script_instance() && get_script_instance()->has_method("get_gizmo_name")) { + return get_script_instance()->call("get_gizmo_name"); + } + WARN_PRINT_ONCE("A 3D editor gizmo has no name defined (it will appear as \"Unnamed Gizmo\" in the \"View > Gizmos\" menu). To resolve this, override the `get_gizmo_name()` function to return a String in the script that extends EditorSpatialGizmoPlugin."); + return TTR("Unnamed Gizmo"); +} + +int EditorSpatialGizmoPlugin::get_priority() const { + if (get_script_instance() && get_script_instance()->has_method("get_priority")) { + return get_script_instance()->call("get_priority"); + } + return 0; +} + +Ref EditorSpatialGizmoPlugin::get_gizmo(Spatial *p_spatial) { + if (get_script_instance() && get_script_instance()->has_method("get_gizmo")) { + return get_script_instance()->call("get_gizmo", p_spatial); + } + + Ref ref = create_gizmo(p_spatial); + + if (ref.is_null()) { + return ref; + } + + ref->set_plugin(this); + ref->set_spatial_node(p_spatial); + ref->set_hidden(current_state == HIDDEN); + + current_gizmos.push_back(ref.ptr()); + return ref; +} + +void EditorSpatialGizmoPlugin::_bind_methods() { +#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorSpatialGizmo") + + BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); + BIND_VMETHOD(MethodInfo(GIZMO_REF, "create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Spatial"))); + + ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorSpatialGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorSpatialGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1))); + ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorSpatialGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorSpatialGizmoPlugin::add_material); + + ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorSpatialGizmoPlugin::get_material, DEFVAL(Ref())); + + BIND_VMETHOD(MethodInfo(Variant::STRING, "get_gizmo_name")); + BIND_VMETHOD(MethodInfo(Variant::INT, "get_priority")); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_be_hidden")); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_selectable_when_hidden")); + + BIND_VMETHOD(MethodInfo("redraw", GIZMO_REF)); + BIND_VMETHOD(MethodInfo(Variant::STRING, "get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); + + MethodInfo hvget(Variant::NIL, "get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "index")); + hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + BIND_VMETHOD(hvget); + + BIND_VMETHOD(MethodInfo("set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + MethodInfo cm = MethodInfo("commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); + cm.default_arguments.push_back(false); + BIND_VMETHOD(cm); + + BIND_VMETHOD(MethodInfo(Variant::INT, "subgizmos_intersect_ray", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::VECTOR2, "point"))); + BIND_VMETHOD(MethodInfo(Variant::POOL_INT_ARRAY, "subgizmos_intersect_frustum", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera"), PropertyInfo(Variant::ARRAY, "frustum"))); + BIND_VMETHOD(MethodInfo(Variant::TRANSFORM, "get_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); + BIND_VMETHOD(MethodInfo("set_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM, "transform"))); + MethodInfo cs = MethodInfo("commit_subgizmos", GIZMO_REF, PropertyInfo(Variant::POOL_INT_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel")); + cs.default_arguments.push_back(false); + BIND_VMETHOD(cs); + +#undef GIZMO_REF +} + +bool EditorSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { + if (get_script_instance() && get_script_instance()->has_method("has_gizmo")) { + return get_script_instance()->call("has_gizmo", p_spatial); + } + return false; +} + +Ref EditorSpatialGizmoPlugin::create_gizmo(Spatial *p_spatial) { + if (get_script_instance() && get_script_instance()->has_method("create_gizmo")) { + return get_script_instance()->call("create_gizmo", p_spatial); + } + + Ref ref; + if (has_gizmo(p_spatial)) { + ref.instance(); + } + return ref; +} + +bool EditorSpatialGizmoPlugin::can_be_hidden() const { + if (get_script_instance() && get_script_instance()->has_method("can_be_hidden")) { + return get_script_instance()->call("can_be_hidden"); + } + return true; +} + +bool EditorSpatialGizmoPlugin::is_selectable_when_hidden() const { + if (get_script_instance() && get_script_instance()->has_method("is_selectable_when_hidden")) { + return get_script_instance()->call("is_selectable_when_hidden"); + } + return false; +} + +void EditorSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { + if (get_script_instance() && get_script_instance()->has_method("redraw")) { + Ref ref(p_gizmo); + get_script_instance()->call("redraw", ref); + } +} + +bool EditorSpatialGizmoPlugin::is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_id) const { + if (get_script_instance() && get_script_instance()->has_method("is_handle_highlighted")) { + return get_script_instance()->call("is_handle_highlighted", p_gizmo, p_id); + } + return false; +} + +String EditorSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { + if (get_script_instance() && get_script_instance()->has_method("get_handle_name")) { + return get_script_instance()->call("get_handle_name", p_gizmo, p_id); + } + return ""; +} + +Variant EditorSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { + if (get_script_instance() && get_script_instance()->has_method("get_handle_value")) { + return get_script_instance()->call("get_handle_value", p_gizmo, p_id); + } + return Variant(); +} + +void EditorSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { + if (get_script_instance() && get_script_instance()->has_method("set_handle")) { + get_script_instance()->call("set_handle", p_gizmo, p_id, p_camera, p_point); + } +} + +void EditorSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { + if (get_script_instance() && get_script_instance()->has_method("commit_handle")) { + get_script_instance()->call("commit_handle", p_gizmo, p_id, p_restore, p_cancel); + } +} + +int EditorSpatialGizmoPlugin::subgizmos_intersect_ray(const EditorSpatialGizmo *p_gizmo, Camera *p_camera, const Vector2 &p_point) const { + if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_ray")) { + return get_script_instance()->call("subgizmos_intersect_ray", p_camera, p_point); + } + return -1; +} + +Vector EditorSpatialGizmoPlugin::subgizmos_intersect_frustum(const EditorSpatialGizmo *p_gizmo, const Camera *p_camera, const Vector &p_frustum) const { + if (get_script_instance() && get_script_instance()->has_method("subgizmos_intersect_frustum")) { + Array frustum; + for (int i = 0; i < p_frustum.size(); i++) { + frustum[i] = p_frustum[i]; + } + return get_script_instance()->call("subgizmos_intersect_frustum", p_camera, frustum); + } + + return Vector(); +} + +Transform EditorSpatialGizmoPlugin::get_subgizmo_transform(const EditorSpatialGizmo *p_gizmo, int p_id) const { + if (get_script_instance() && get_script_instance()->has_method("get_subgizmo_transform")) { + return get_script_instance()->call("get_subgizmo_transform", p_id); + } + + return Transform(); +} + +void EditorSpatialGizmoPlugin::set_subgizmo_transform(const EditorSpatialGizmo *p_gizmo, int p_id, Transform p_transform) const { + if (get_script_instance() && get_script_instance()->has_method("set_subgizmo_transform")) { + get_script_instance()->call("set_subgizmo_transform", p_id, p_transform); + } +} + +void EditorSpatialGizmoPlugin::commit_subgizmos(const EditorSpatialGizmo *p_gizmo, const Vector &p_ids, const Vector &p_restore, bool p_cancel) const { + if (get_script_instance() && get_script_instance()->has_method("commit_subgizmos")) { + Array ids; + for (int i = 0; i < p_ids.size(); i++) { + ids[i] = p_ids[i]; + } + + Array restore; + for (int i = 0; i < p_restore.size(); i++) { + restore[i] = p_restore[i]; + } + + get_script_instance()->call("commit_subgizmos", ids, restore, p_cancel); + } +} + +void EditorSpatialGizmoPlugin::set_state(int p_state) { + current_state = p_state; + for (int i = 0; i < current_gizmos.size(); ++i) { + current_gizmos[i]->set_hidden(current_state == HIDDEN); + } +} + +int EditorSpatialGizmoPlugin::get_state() const { + return current_state; +} + +void EditorSpatialGizmoPlugin::unregister_gizmo(EditorSpatialGizmo *p_gizmo) { + current_gizmos.erase(p_gizmo); +} + +EditorSpatialGizmoPlugin::EditorSpatialGizmoPlugin() { + current_state = VISIBLE; +} + +EditorSpatialGizmoPlugin::~EditorSpatialGizmoPlugin() { + for (int i = 0; i < current_gizmos.size(); ++i) { + current_gizmos[i]->set_plugin(nullptr); + current_gizmos[i]->get_spatial_node()->remove_gizmo(current_gizmos[i]); + } + if (SpatialEditor::get_singleton()) { + SpatialEditor::get_singleton()->update_all_gizmos(); + } } //// light gizmo @@ -884,7 +1341,7 @@ bool LightSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String LightSpatialGizmoPlugin::get_name() const { +String LightSpatialGizmoPlugin::get_gizmo_name() const { return "Lights"; } @@ -892,20 +1349,20 @@ int LightSpatialGizmoPlugin::get_priority() const { return -1; } -String LightSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - if (p_idx == 0) { +String LightSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { + if (p_id == 0) { return "Radius"; } else { return "Aperture"; } } -Variant LightSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant LightSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { Light *light = Object::cast_to(p_gizmo->get_spatial_node()); - if (p_idx == 0) { + if (p_id == 0) { return light->get_param(Light::PARAM_RANGE); } - if (p_idx == 1) { + if (p_id == 1) { return light->get_param(Light::PARAM_SPOT_ANGLE); } @@ -939,7 +1396,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec return a * 180.0 / Math_PI; } -void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { Light *light = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = light->get_global_transform(); Transform gi = gt.affine_inverse(); @@ -948,7 +1405,7 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Vector3 ray_dir = p_camera->project_ray_normal(p_point); Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) }; - if (p_idx == 0) { + if (p_id == 0) { if (Object::cast_to(light)) { Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb); @@ -977,24 +1434,24 @@ void LightSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, } } - } else if (p_idx == 1) { + } else if (p_id == 1) { float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], light->get_param(Light::PARAM_RANGE), gt); light->set_param(Light::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99)); } } -void LightSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void LightSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { Light *light = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { - light->set_param(p_idx == 0 ? Light::PARAM_RANGE : Light::PARAM_SPOT_ANGLE, p_restore); + light->set_param(p_id == 0 ? Light::PARAM_RANGE : Light::PARAM_SPOT_ANGLE, p_restore); - } else if (p_idx == 0) { + } else if (p_id == 0) { UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); ur->add_do_method(light, "set_param", Light::PARAM_RANGE, light->get_param(Light::PARAM_RANGE)); ur->add_undo_method(light, "set_param", Light::PARAM_RANGE, p_restore); ur->commit_action(); - } else if (p_idx == 1) { + } else if (p_id == 1) { UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Light Radius")); ur->add_do_method(light, "set_param", Light::PARAM_SPOT_ANGLE, light->get_param(Light::PARAM_SPOT_ANGLE)); @@ -1086,7 +1543,7 @@ void LightSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Vector handles; handles.push_back(Vector3(r, 0, 0)); - p_gizmo->add_handles(handles, get_material("handles_billboard"), true); + p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector(), true); } if (Object::cast_to(light)) { @@ -1153,7 +1610,7 @@ bool AudioStreamPlayer3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String AudioStreamPlayer3DSpatialGizmoPlugin::get_name() const { +String AudioStreamPlayer3DSpatialGizmoPlugin::get_gizmo_name() const { return "AudioStreamPlayer3D"; } @@ -1161,16 +1618,16 @@ int AudioStreamPlayer3DSpatialGizmoPlugin::get_priority() const { return -1; } -String AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { return "Emission Radius"; } -Variant AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant AudioStreamPlayer3DSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); return player->get_emission_angle(); } -void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = player->get_global_transform(); @@ -1207,7 +1664,7 @@ void AudioStreamPlayer3DSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_giz } } -void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void AudioStreamPlayer3DSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { AudioStreamPlayer3D *player = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { @@ -1284,7 +1741,7 @@ bool ListenerSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String ListenerSpatialGizmoPlugin::get_name() const { +String ListenerSpatialGizmoPlugin::get_gizmo_name() const { return "Listener"; } @@ -1310,7 +1767,7 @@ bool CameraSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String CameraSpatialGizmoPlugin::get_name() const { +String CameraSpatialGizmoPlugin::get_gizmo_name() const { return "Camera"; } @@ -1318,7 +1775,7 @@ int CameraSpatialGizmoPlugin::get_priority() const { return -1; } -String CameraSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String CameraSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { @@ -1328,7 +1785,7 @@ String CameraSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_giz } } -Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { @@ -1338,7 +1795,7 @@ Variant CameraSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, } } -void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = camera->get_global_transform(); @@ -1367,7 +1824,7 @@ void CameraSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx } } -void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CameraSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { Camera *camera = Object::cast_to(p_gizmo->get_spatial_node()); if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { @@ -1547,7 +2004,7 @@ bool MeshInstanceSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr && Object::cast_to(p_spatial) == nullptr; } -String MeshInstanceSpatialGizmoPlugin::get_name() const { +String MeshInstanceSpatialGizmoPlugin::get_gizmo_name() const { return "MeshInstance"; } @@ -1584,7 +2041,7 @@ bool Sprite3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String Sprite3DSpatialGizmoPlugin::get_name() const { +String Sprite3DSpatialGizmoPlugin::get_gizmo_name() const { return "Sprite3D"; } @@ -1616,7 +2073,7 @@ bool Label3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String Label3DSpatialGizmoPlugin::get_name() const { +String Label3DSpatialGizmoPlugin::get_gizmo_name() const { return "Label3D"; } @@ -1705,7 +2162,7 @@ bool Position3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String Position3DSpatialGizmoPlugin::get_name() const { +String Position3DSpatialGizmoPlugin::get_gizmo_name() const { return "Position3D"; } @@ -1729,7 +2186,7 @@ bool PhysicalBoneSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String PhysicalBoneSpatialGizmoPlugin::get_name() const { +String PhysicalBoneSpatialGizmoPlugin::get_gizmo_name() const { return "PhysicalBones"; } @@ -1866,7 +2323,7 @@ bool RayCastSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String RayCastSpatialGizmoPlugin::get_name() const { +String RayCastSpatialGizmoPlugin::get_gizmo_name() const { return "RayCast"; } @@ -1917,7 +2374,7 @@ bool SpringArmSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String SpringArmSpatialGizmoPlugin::get_name() const { +String SpringArmSpatialGizmoPlugin::get_gizmo_name() const { return "SpringArm"; } @@ -1936,7 +2393,7 @@ bool VehicleWheelSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String VehicleWheelSpatialGizmoPlugin::get_name() const { +String VehicleWheelSpatialGizmoPlugin::get_gizmo_name() const { return "VehicleWheel"; } @@ -2008,7 +2465,7 @@ bool SoftBodySpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String SoftBodySpatialGizmoPlugin::get_name() const { +String SoftBodySpatialGizmoPlugin::get_gizmo_name() const { return "SoftBody"; } @@ -2061,18 +2518,18 @@ void SoftBodySpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { p_gizmo->add_collision_triangles(tm); } -String SoftBodySpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String SoftBodySpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { return "SoftBody pin point"; } -Variant SoftBodySpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant SoftBodySpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); - return Variant(soft_body->is_point_pinned(p_idx)); + return Variant(soft_body->is_point_pinned(p_id)); } -void SoftBodySpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void SoftBodySpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { SoftBody *soft_body = Object::cast_to(p_gizmo->get_spatial_node()); - soft_body->pin_point_toggle(p_idx); + soft_body->pin_point_toggle(p_id); } bool SoftBodySpatialGizmoPlugin::is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const { @@ -2094,7 +2551,7 @@ bool VisibilityNotifierGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String VisibilityNotifierGizmoPlugin::get_name() const { +String VisibilityNotifierGizmoPlugin::get_gizmo_name() const { return "VisibilityNotifier"; } @@ -2102,8 +2559,8 @@ int VisibilityNotifierGizmoPlugin::get_priority() const { return -1; } -String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - switch (p_idx) { +String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { + switch (p_id) { case 0: return "Size X"; case 1: @@ -2121,19 +2578,19 @@ String VisibilityNotifierGizmoPlugin::get_handle_name(const EditorSpatialGizmo * return ""; } -Variant VisibilityNotifierGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant VisibilityNotifierGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); return notifier->get_aabb(); } -void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = notifier->get_global_transform(); Transform gi = gt.affine_inverse(); - bool move = p_idx >= 3; - p_idx = p_idx % 3; + bool move = p_id >= 3; + p_id = p_id % 3; AABB aabb = notifier->get_aabb(); Vector3 ray_from = p_camera->project_ray_origin(p_point); @@ -2144,25 +2601,25 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int Vector3 ofs = aabb.position + aabb.size * 0.5; Vector3 axis; - axis[p_idx] = 1.0; + axis[p_id] = 1.0; if (move) { Vector3 ra, rb; Geometry::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; + float d = ra[p_id]; if (SpatialEditor::get_singleton()->is_snap_enabled()) { d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); } - aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5; + aabb.position[p_id] = d - 1.0 - aabb.size[p_id] * 0.5; notifier->set_aabb(aabb); } else { Vector3 ra, rb; Geometry::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_idx] - ofs[p_idx]; + float d = ra[p_id] - ofs[p_id]; if (SpatialEditor::get_singleton()->is_snap_enabled()) { d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); } @@ -2171,13 +2628,13 @@ void VisibilityNotifierGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int d = 0.001; } //resize - aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d; - aabb.size[p_idx] = d * 2; + aabb.position[p_id] = (aabb.position[p_id] + aabb.size[p_id] * 0.5) - d; + aabb.size[p_id] = d * 2; notifier->set_aabb(aabb); } } -void VisibilityNotifierGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void VisibilityNotifierGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { VisibilityNotifier *notifier = Object::cast_to(p_gizmo->get_spatial_node()); if (p_cancel) { @@ -2249,7 +2706,7 @@ bool CPUParticlesGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String CPUParticlesGizmoPlugin::get_name() const { +String CPUParticlesGizmoPlugin::get_gizmo_name() const { return "CPUParticles"; } @@ -2287,7 +2744,7 @@ bool ReflectionProbeGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String ReflectionProbeGizmoPlugin::get_name() const { +String ReflectionProbeGizmoPlugin::get_gizmo_name() const { return "ReflectionProbe"; } @@ -2295,8 +2752,8 @@ int ReflectionProbeGizmoPlugin::get_priority() const { return -1; } -String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { - switch (p_idx) { +String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { + switch (p_id) { case 0: return "Extents X"; case 1: @@ -2313,17 +2770,17 @@ String ReflectionProbeGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_g return ""; } -Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); return AABB(probe->get_extents(), probe->get_origin_offset()); } -void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); Transform gt = probe->get_global_transform(); Transform gi = gt.affine_inverse(); - if (p_idx < 3) { + if (p_id < 3) { Vector3 extents = probe->get_extents(); Vector3 ray_from = p_camera->project_ray_origin(p_point); @@ -2332,11 +2789,11 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; Vector3 axis; - axis[p_idx] = 1.0; + axis[p_id] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; + float d = ra[p_id]; if (SpatialEditor::get_singleton()->is_snap_enabled()) { d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); } @@ -2345,13 +2802,13 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i d = 0.001; } - extents[p_idx] = d; + extents[p_id] = d; probe->set_extents(extents); } else { - p_idx -= 3; + p_id -= 3; Vector3 origin = probe->get_origin_offset(); - origin[p_idx] = 0; + origin[p_id] = 0; Vector3 ray_from = p_camera->project_ray_origin(p_point); Vector3 ray_dir = p_camera->project_ray_normal(p_point); @@ -2359,22 +2816,22 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_i Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) }; Vector3 axis; - axis[p_idx] = 1.0; + axis[p_id] = 1.0; Vector3 ra, rb; Geometry::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb); // Adjust the actual position to account for the gizmo handle position - float d = ra[p_idx] + 0.25; + float d = ra[p_id] + 0.25; if (SpatialEditor::get_singleton()->is_snap_enabled()) { d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); } - origin[p_idx] = d; + origin[p_id] = d; probe->set_origin_offset(origin); } } -void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void ReflectionProbeGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { ReflectionProbe *probe = Object::cast_to(p_gizmo->get_spatial_node()); AABB restore = p_restore; @@ -2468,7 +2925,7 @@ bool CollisionObjectGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String CollisionObjectGizmoPlugin::get_name() const { +String CollisionObjectGizmoPlugin::get_gizmo_name() const { return "CollisionObject"; } @@ -2498,7 +2955,7 @@ void CollisionObjectGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { SurfaceTool st; st.append_from(s->get_debug_mesh(), 0, xform); - p_gizmo->add_mesh(st.commit(), false, Ref(), material); + p_gizmo->add_mesh(st.commit(), material); p_gizmo->add_collision_segments(s->get_debug_mesh_lines()); } } @@ -2520,7 +2977,7 @@ bool CollisionShapeSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String CollisionShapeSpatialGizmoPlugin::get_name() const { +String CollisionShapeSpatialGizmoPlugin::get_gizmo_name() const { return "CollisionShape"; } @@ -2528,7 +2985,7 @@ int CollisionShapeSpatialGizmoPlugin::get_priority() const { return -1; } -String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const { +String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const { const CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); Ref s = cs->get_shape(); @@ -2545,11 +3002,11 @@ String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizm } if (Object::cast_to(*s)) { - return p_idx == 0 ? "Radius" : "Height"; + return p_id == 0 ? "Radius" : "Height"; } if (Object::cast_to(*s)) { - return p_idx == 0 ? "Radius" : "Height"; + return p_id == 0 ? "Radius" : "Height"; } if (Object::cast_to(*s)) { @@ -2559,7 +3016,7 @@ String CollisionShapeSpatialGizmoPlugin::get_handle_name(const EditorSpatialGizm return ""; } -Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const { +Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const { CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); Ref s = cs->get_shape(); @@ -2579,12 +3036,12 @@ Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p if (Object::cast_to(*s)) { Ref cs2 = s; - return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); + return p_id == 0 ? cs2->get_radius() : cs2->get_height(); } if (Object::cast_to(*s)) { Ref cs2 = s; - return p_idx == 0 ? cs2->get_radius() : cs2->get_height(); + return p_id == 0 ? cs2->get_radius() : cs2->get_height(); } if (Object::cast_to(*s)) { @@ -2594,7 +3051,7 @@ Variant CollisionShapeSpatialGizmoPlugin::get_handle_value(EditorSpatialGizmo *p return Variant(); } -void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point) { +void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point) { CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); Ref s = cs->get_shape(); @@ -2644,11 +3101,11 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i if (Object::cast_to(*s)) { Vector3 axis; - axis[p_idx] = 1.0; + axis[p_id] = 1.0; Ref bs = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); - float d = ra[p_idx]; + float d = ra[p_id]; if (SpatialEditor::get_singleton()->is_snap_enabled()) { d = Math::stepify(d, SpatialEditor::get_singleton()->get_translate_snap()); } @@ -2658,18 +3115,18 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i } Vector3 he = bs->get_extents(); - he[p_idx] = d; + he[p_id] = d; bs->set_extents(he); } if (Object::cast_to(*s)) { Vector3 axis; - axis[p_idx == 0 ? 0 : 2] = 1.0; + axis[p_id == 0 ? 0 : 2] = 1.0; Ref cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (p_idx == 1) { + if (p_id == 1) { d -= cs2->get_radius(); } @@ -2681,16 +3138,16 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i d = 0.001; } - if (p_idx == 0) { + if (p_id == 0) { cs2->set_radius(d); - } else if (p_idx == 1) { + } else if (p_id == 1) { cs2->set_height(d * 2.0); } } if (Object::cast_to(*s)) { Vector3 axis; - axis[p_idx == 0 ? 0 : 1] = 1.0; + axis[p_id == 0 ? 0 : 1] = 1.0; Ref cs2 = s; Vector3 ra, rb; Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); @@ -2703,14 +3160,14 @@ void CollisionShapeSpatialGizmoPlugin::set_handle(EditorSpatialGizmo *p_gizmo, i d = 0.001; } - if (p_idx == 0) { + if (p_id == 0) { cs2->set_radius(d); - } else if (p_idx == 1) { + } else if (p_id == 1) { cs2->set_height(d * 2.0); } } } -void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { +void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { CollisionShape *cs = Object::cast_to(p_gizmo->get_spatial_node()); Ref s = cs->get_shape(); @@ -2749,7 +3206,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo if (Object::cast_to(*s)) { Ref ss = s; if (p_cancel) { - if (p_idx == 0) { + if (p_id == 0) { ss->set_radius(p_restore); } else { ss->set_height(p_restore); @@ -2758,7 +3215,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - if (p_idx == 0) { + if (p_id == 0) { ur->create_action(TTR("Change Capsule Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); ur->add_undo_method(ss.ptr(), "set_radius", p_restore); @@ -2774,7 +3231,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo if (Object::cast_to(*s)) { Ref ss = s; if (p_cancel) { - if (p_idx == 0) { + if (p_id == 0) { ss->set_radius(p_restore); } else { ss->set_height(p_restore); @@ -2783,7 +3240,7 @@ void CollisionShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); - if (p_idx == 0) { + if (p_id == 0) { ur->create_action(TTR("Change Cylinder Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); ur->add_undo_method(ss.ptr(), "set_radius", p_restore); @@ -3078,7 +3535,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { if (Object::cast_to(*s)) { Ref cs2 = s; Ref mesh = cs2->get_debug_mesh(); - p_gizmo->add_mesh(mesh, false, Ref(), material); + p_gizmo->add_mesh(mesh, material); p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines()); } @@ -3099,7 +3556,7 @@ void CollisionShapeSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { Ref hms = s; Ref mesh = hms->get_debug_mesh(); - p_gizmo->add_mesh(mesh, false, Ref(), material); + p_gizmo->add_mesh(mesh, material); } } @@ -3117,7 +3574,7 @@ bool CollisionPolygonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String CollisionPolygonSpatialGizmoPlugin::get_name() const { +String CollisionPolygonSpatialGizmoPlugin::get_gizmo_name() const { return "CollisionPolygon"; } @@ -3164,7 +3621,7 @@ bool NavigationMeshSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String NavigationMeshSpatialGizmoPlugin::get_name() const { +String NavigationMeshSpatialGizmoPlugin::get_gizmo_name() const { return "NavigationMeshInstance"; } @@ -3533,7 +3990,7 @@ bool JointSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != nullptr; } -String JointSpatialGizmoPlugin::get_name() const { +String JointSpatialGizmoPlugin::get_gizmo_name() const { return "Joints"; } @@ -3978,7 +4435,7 @@ bool RoomGizmoPlugin::has_gizmo(Spatial *p_spatial) { return false; } -String RoomGizmoPlugin::get_name() const { +String RoomGizmoPlugin::get_gizmo_name() const { return "Room"; } @@ -3988,32 +4445,32 @@ int RoomGizmoPlugin::get_priority() const { ////////////////////// -String RoomSpatialGizmo::get_handle_name(int p_idx) const { - return "Point " + itos(p_idx); +String RoomSpatialGizmo::get_handle_name(int p_id) const { + return "Point " + itos(p_id); } -Variant RoomSpatialGizmo::get_handle_value(int p_idx) { +Variant RoomSpatialGizmo::get_handle_value(int p_id) { if (!_room) { return Vector3(0, 0, 0); } int num_points = _room->_bound_pts.size(); - if (p_idx >= num_points) { + if (p_id >= num_points) { return Vector3(0, 0, 0); } - return _room->_bound_pts[p_idx]; + return _room->_bound_pts[p_id]; } -void RoomSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - if (!_room || (p_idx >= _room->_bound_pts.size())) { +void RoomSpatialGizmo::set_handle(int p_id, Camera *p_camera, const Point2 &p_point) { + if (!_room || (p_id >= _room->_bound_pts.size())) { return; } Transform tr = _room->get_global_transform(); Transform tr_inv = tr.affine_inverse(); - Vector3 pt_world = _room->_bound_pts[p_idx]; + Vector3 pt_world = _room->_bound_pts[p_id]; pt_world = tr.xform(pt_world); Vector3 ray_from = p_camera->project_ray_origin(p_point); @@ -4051,23 +4508,23 @@ void RoomSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p } Vector3 pt_local = tr_inv.xform(pt_world); - _room->set_point(p_idx, pt_local); + _room->set_point(p_id, pt_local); } return; } } -void RoomSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - if (!_room || (p_idx >= _room->_bound_pts.size())) { +void RoomSpatialGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) { + if (!_room || (p_id >= _room->_bound_pts.size())) { return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Room Point Position")); - ur->add_do_method(_room, "set_point", p_idx, _room->_bound_pts[p_idx]); - ur->add_undo_method(_room, "set_point", p_idx, p_restore); + ur->add_do_method(_room, "set_point", p_id, _room->_bound_pts[p_id]); + ur->add_undo_method(_room, "set_point", p_id, p_restore); ur->commit_action(); _room->property_list_changed_notify(); @@ -4128,7 +4585,7 @@ void RoomSpatialGizmo::redraw() { array.resize(Mesh::ARRAY_MAX); array[Mesh::ARRAY_VERTEX] = pts; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); - add_mesh(mesh, false, Ref(), material_overlap); + add_mesh(mesh, material_overlap); } Vector handles; @@ -4185,7 +4642,7 @@ bool PortalGizmoPlugin::has_gizmo(Spatial *p_spatial) { return false; } -String PortalGizmoPlugin::get_name() const { +String PortalGizmoPlugin::get_gizmo_name() const { return "Portal"; } @@ -4195,32 +4652,32 @@ int PortalGizmoPlugin::get_priority() const { ////////////////////// -String PortalSpatialGizmo::get_handle_name(int p_idx) const { - return "Point " + itos(p_idx); +String PortalSpatialGizmo::get_handle_name(int p_id) const { + return "Point " + itos(p_id); } -Variant PortalSpatialGizmo::get_handle_value(int p_idx) { +Variant PortalSpatialGizmo::get_handle_value(int p_id) { if (!_portal) { return Vector2(0, 0); } int num_points = _portal->_pts_local_raw.size(); - if (p_idx >= num_points) { + if (p_id >= num_points) { return Vector2(0, 0); } - return _portal->_pts_local_raw[p_idx]; + return _portal->_pts_local_raw[p_id]; } -void PortalSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { - if (!_portal || (p_idx >= _portal->_pts_local_raw.size())) { +void PortalSpatialGizmo::set_handle(int p_id, Camera *p_camera, const Point2 &p_point) { + if (!_portal || (p_id >= _portal->_pts_local_raw.size())) { return; } Transform tr = _portal->get_global_transform(); Transform tr_inv = tr.affine_inverse(); - Vector3 pt_local = Portal::_vec2to3(_portal->_pts_local_raw[p_idx]); + Vector3 pt_local = Portal::_vec2to3(_portal->_pts_local_raw[p_id]); Vector3 pt_world = tr.xform(pt_local); Vector3 ray_from = p_camera->project_ray_origin(p_point); @@ -4246,22 +4703,22 @@ void PortalSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p inters.snap(Vector3(snap, snap, snap)); } - _portal->set_point(p_idx, Vector2(inters.x, inters.y)); + _portal->set_point(p_id, Vector2(inters.x, inters.y)); return; } } -void PortalSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { - if (!_portal || (p_idx >= _portal->_pts_local_raw.size())) { +void PortalSpatialGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) { + if (!_portal || (p_id >= _portal->_pts_local_raw.size())) { return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Set Portal Point Position")); - ur->add_do_method(_portal, "set_point", p_idx, _portal->_pts_local_raw[p_idx]); - ur->add_undo_method(_portal, "set_point", p_idx, p_restore); + ur->add_do_method(_portal, "set_point", p_id, _portal->_pts_local_raw[p_id]); + ur->add_undo_method(_portal, "set_point", p_id, p_restore); ur->commit_action(); _portal->property_list_changed_notify(); @@ -4389,7 +4846,7 @@ void PortalSpatialGizmo::redraw() { array[Mesh::ARRAY_VERTEX] = pts_portal; array[Mesh::ARRAY_COLOR] = cols_portal; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); - add_mesh(mesh, false, Ref(), material_portal); + add_mesh(mesh, material_portal); // handles Ref material_handle = gizmo_plugin->get_material("portal_handle", this); @@ -4402,7 +4859,7 @@ void PortalSpatialGizmo::redraw() { array.resize(Mesh::ARRAY_MAX); array[Mesh::ARRAY_VERTEX] = pts_margin; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); - add_mesh(mesh, false, Ref(), material_margin); + add_mesh(mesh, material_margin); // lines around the outside of mesh add_lines(edge_pts, material_edge, false, color); @@ -4484,7 +4941,7 @@ bool OccluderGizmoPlugin::has_gizmo(Spatial *p_spatial) { return false; } -String OccluderGizmoPlugin::get_name() const { +String OccluderGizmoPlugin::get_gizmo_name() const { return "Occluder"; } @@ -4494,53 +4951,53 @@ int OccluderGizmoPlugin::get_priority() const { ////////////////////// -String OccluderSpatialGizmo::get_handle_name(int p_idx) const { +String OccluderSpatialGizmo::get_handle_name(int p_id) const { const OccluderShapeSphere *occ_sphere = get_occluder_shape_sphere(); if (occ_sphere) { int num_spheres = occ_sphere->get_spheres().size(); - if (p_idx >= num_spheres) { - p_idx -= num_spheres; - return "Radius " + itos(p_idx); + if (p_id >= num_spheres) { + p_id -= num_spheres; + return "Radius " + itos(p_id); } else { - return "Sphere " + itos(p_idx); + return "Sphere " + itos(p_id); } } const OccluderShapePolygon *occ_poly = get_occluder_shape_poly(); if (occ_poly) { - if (p_idx < occ_poly->_poly_pts_local_raw.size()) { - return "Poly Point " + itos(p_idx); + if (p_id < occ_poly->_poly_pts_local_raw.size()) { + return "Poly Point " + itos(p_id); } else { - return "Hole Point " + itos(p_idx - occ_poly->_poly_pts_local_raw.size()); + return "Hole Point " + itos(p_id - occ_poly->_poly_pts_local_raw.size()); } } return "Unknown"; } -Variant OccluderSpatialGizmo::get_handle_value(int p_idx) { +Variant OccluderSpatialGizmo::get_handle_value(int p_id) { const OccluderShapeSphere *occ_sphere = get_occluder_shape_sphere(); if (occ_sphere) { Vector spheres = occ_sphere->get_spheres(); int num_spheres = spheres.size(); - if (p_idx >= num_spheres) { - p_idx -= num_spheres; - return spheres[p_idx].d; + if (p_id >= num_spheres) { + p_id -= num_spheres; + return spheres[p_id].d; } else { - return spheres[p_idx].normal; + return spheres[p_id].normal; } } const OccluderShapePolygon *occ_poly = get_occluder_shape_poly(); if (occ_poly) { - if (p_idx < occ_poly->_poly_pts_local_raw.size()) { - return occ_poly->_poly_pts_local_raw[p_idx]; + if (p_id < occ_poly->_poly_pts_local_raw.size()) { + return occ_poly->_poly_pts_local_raw[p_id]; } else { - p_idx -= occ_poly->_poly_pts_local_raw.size(); - if (p_idx < occ_poly->_hole_pts_local_raw.size()) { - return occ_poly->_hole_pts_local_raw[p_idx]; + p_id -= occ_poly->_poly_pts_local_raw.size(); + if (p_id < occ_poly->_hole_pts_local_raw.size()) { + return occ_poly->_hole_pts_local_raw[p_id]; } return Vector2(0, 0); } @@ -4549,7 +5006,7 @@ Variant OccluderSpatialGizmo::get_handle_value(int p_idx) { return 0; } -void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_point) { +void OccluderSpatialGizmo::set_handle(int p_id, Camera *p_camera, const Point2 &p_point) { if (!_occluder) { return; } @@ -4584,12 +5041,12 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 // radius? bool is_radius = false; - if (p_idx >= num_spheres) { - p_idx -= num_spheres; + if (p_id >= num_spheres) { + p_id -= num_spheres; is_radius = true; } - Vector3 pt_world = spheres[p_idx].normal; + Vector3 pt_world = spheres[p_id].normal; pt_world = tr.xform(pt_world); Vector3 pt_world_center = pt_world; @@ -4613,7 +5070,7 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 // new radius is simply the dist between this point and the centre of the sphere real_t radius = (pt_world - pt_world_center).length(); - occ_sphere->set_sphere_radius(p_idx, radius); + occ_sphere->set_sphere_radius(p_id, radius); } else { for (int n = 0; n < 3; n++) { if (n != biggest_axis) { @@ -4622,7 +5079,7 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 } Vector3 pt_local = tr_inv.xform(pt_world); - occ_sphere->set_sphere_position(p_idx, pt_local); + occ_sphere->set_sphere_position(p_id, pt_local); } return; @@ -4633,15 +5090,15 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 if (occ_poly) { Vector3 pt_local; - bool hole = p_idx >= occ_poly->_poly_pts_local_raw.size(); + bool hole = p_id >= occ_poly->_poly_pts_local_raw.size(); if (hole) { - p_idx -= occ_poly->_poly_pts_local_raw.size(); - if (p_idx >= occ_poly->_hole_pts_local_raw.size()) { + p_id -= occ_poly->_poly_pts_local_raw.size(); + if (p_id >= occ_poly->_hole_pts_local_raw.size()) { return; } - pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_hole_pts_local_raw[p_idx]); + pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_hole_pts_local_raw[p_id]); } else { - pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_poly_pts_local_raw[p_idx]); + pt_local = OccluderShapePolygon::_vec2to3(occ_poly->_poly_pts_local_raw[p_id]); } Vector3 pt_world = tr.xform(pt_local); @@ -4667,9 +5124,9 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 } if (hole) { - occ_poly->set_hole_point(p_idx, Vector2(inters.x, inters.y)); + occ_poly->set_hole_point(p_id, Vector2(inters.x, inters.y)); } else { - occ_poly->set_polygon_point(p_idx, Vector2(inters.x, inters.y)); + occ_poly->set_polygon_point(p_id, Vector2(inters.x, inters.y)); } return; @@ -4677,7 +5134,7 @@ void OccluderSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 } } -void OccluderSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { +void OccluderSpatialGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) { UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); OccluderShapeSphere *occ_sphere = get_occluder_shape_sphere(); @@ -4685,16 +5142,16 @@ void OccluderSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bo Vector spheres = occ_sphere->get_spheres(); int num_spheres = spheres.size(); - if (p_idx >= num_spheres) { - p_idx -= num_spheres; + if (p_id >= num_spheres) { + p_id -= num_spheres; ur->create_action(TTR("Set Occluder Sphere Radius")); - ur->add_do_method(occ_sphere, "set_sphere_radius", p_idx, spheres[p_idx].d); - ur->add_undo_method(occ_sphere, "set_sphere_radius", p_idx, p_restore); + ur->add_do_method(occ_sphere, "set_sphere_radius", p_id, spheres[p_id].d); + ur->add_undo_method(occ_sphere, "set_sphere_radius", p_id, p_restore); } else { ur->create_action(TTR("Set Occluder Sphere Position")); - ur->add_do_method(occ_sphere, "set_sphere_position", p_idx, spheres[p_idx].normal); - ur->add_undo_method(occ_sphere, "set_sphere_position", p_idx, p_restore); + ur->add_do_method(occ_sphere, "set_sphere_position", p_id, spheres[p_id].normal); + ur->add_undo_method(occ_sphere, "set_sphere_position", p_id, p_restore); } ur->commit_action(); @@ -4703,18 +5160,18 @@ void OccluderSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bo OccluderShapePolygon *occ_poly = get_occluder_shape_poly(); if (occ_poly) { - if (p_idx < occ_poly->_poly_pts_local_raw.size()) { + if (p_id < occ_poly->_poly_pts_local_raw.size()) { ur->create_action(TTR("Set Occluder Polygon Point Position")); - ur->add_do_method(occ_poly, "set_polygon_point", p_idx, occ_poly->_poly_pts_local_raw[p_idx]); - ur->add_undo_method(occ_poly, "set_polygon_point", p_idx, p_restore); + ur->add_do_method(occ_poly, "set_polygon_point", p_id, occ_poly->_poly_pts_local_raw[p_id]); + ur->add_undo_method(occ_poly, "set_polygon_point", p_id, p_restore); ur->commit_action(); _occluder->property_list_changed_notify(); } else { - p_idx -= occ_poly->_poly_pts_local_raw.size(); - if (p_idx < occ_poly->_hole_pts_local_raw.size()) { + p_id -= occ_poly->_poly_pts_local_raw.size(); + if (p_id < occ_poly->_hole_pts_local_raw.size()) { ur->create_action(TTR("Set Occluder Hole Point Position")); - ur->add_do_method(occ_poly, "set_hole_point", p_idx, occ_poly->_hole_pts_local_raw[p_idx]); - ur->add_undo_method(occ_poly, "set_hole_point", p_idx, p_restore); + ur->add_do_method(occ_poly, "set_hole_point", p_id, occ_poly->_hole_pts_local_raw[p_id]); + ur->add_undo_method(occ_poly, "set_hole_point", p_id, p_restore); ur->commit_action(); _occluder->property_list_changed_notify(); } @@ -4822,7 +5279,7 @@ void OccluderSpatialGizmo::redraw() { Ref material_handle = gizmo_plugin->get_material("occluder_handle", this); Ref material_extra_handle = gizmo_plugin->get_material("extra_handle", this); add_handles(handles, material_handle); - add_handles(radius_handles, material_extra_handle, false, true); + add_handles(radius_handles, material_extra_handle, Vector(), false, true); } const OccluderShapePolygon *occ_poly = get_occluder_shape_poly(); @@ -4893,7 +5350,7 @@ void OccluderSpatialGizmo::_redraw_poly(bool p_hole, const Vector &p_pt mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); Ref material_poly = gizmo_plugin->get_material("occluder_poly", this); - add_mesh(mesh, false, Ref(), material_poly); + add_mesh(mesh, material_poly); } // handles @@ -4902,7 +5359,7 @@ void OccluderSpatialGizmo::_redraw_poly(bool p_hole, const Vector &p_pt add_handles(handles, material_handle); } else { Ref material_extra_handle = gizmo_plugin->get_material("extra_handle", this); - add_handles(handles, material_extra_handle, false, true); + add_handles(handles, material_extra_handle, Vector(), false, true); } } } diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 687e6ff80..8d9cd076a 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -38,6 +38,8 @@ #include "core/math/vector2.h" #include "core/math/vector3.h" #include "core/object.h" +#include "core/ordered_hash_map.h" +#include "core/pool_vector.h" #include "core/reference.h" #include "core/ustring.h" #include "core/variant.h" @@ -49,21 +51,166 @@ class Camera; class Spatial; class Timer; class Transform; -template -class PoolVector; +class Timer; + +class EditorSpatialGizmo : public SpatialGizmo { + GDCLASS(EditorSpatialGizmo, SpatialGizmo); + +public: + struct Instance { + RID instance; + Ref mesh; + Ref material; + Ref skin_reference; + bool extra_margin; + Transform xform; + + Instance(); + ~Instance(); + + void create_instance(Spatial *p_base, bool p_hidden = false); + }; + + bool selected; + + Vector collision_segments; + Ref collision_mesh; + + Vector handles; + Vector handle_ids; + Vector secondary_handles; + Vector secondary_handle_ids; + + float selectable_icon_size; + bool billboard_handle; + + bool valid; + bool hidden; + + Vector instances; + Spatial *spatial_node; + + void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to(p_node)); } + +protected: + static void _bind_methods(); + + EditorSpatialGizmoPlugin *gizmo_plugin; + +public: + void add_lines(const Vector &p_lines, const Ref &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); + void add_vertices(const Vector &p_vertices, const Ref &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); + void add_mesh(const Ref &p_mesh, const Ref &p_material = Ref(), const Transform &p_xform = Transform(), const Ref &p_skin_reference = Ref()); + void add_collision_segments(const Vector &p_lines); + void add_collision_triangles(const Ref &p_tmesh); + void add_unscaled_billboard(const Ref &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1)); + void add_handles(const Vector &p_handles, const Ref &p_material, const Vector &p_ids = Vector(), bool p_billboard = false, bool p_secondary = false); + void add_solid_box(Ref &p_material, Vector3 p_size, Vector3 p_position = Vector3(), const Transform &p_xform = Transform()); + + virtual bool is_handle_highlighted(int p_id) const; + virtual String get_handle_name(int p_id) const; + virtual Variant get_handle_value(int p_id); + virtual void set_handle(int p_id, Camera *p_camera, const Point2 &p_point); + virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false); + + virtual int subgizmos_intersect_ray(Camera *p_camera, const Vector2 &p_point) const; + virtual Vector subgizmos_intersect_frustum(const Camera *p_camera, const Vector &p_frustum) const; + virtual Transform get_subgizmo_transform(int p_id) const; + virtual void set_subgizmo_transform(int p_id, Transform p_transform) const; + virtual void commit_subgizmos(const Vector &p_ids, const Vector &p_restore, bool p_cancel = false) const; + + void set_selected(bool p_selected) { selected = p_selected; } + bool is_selected() const { return selected; } + + void set_spatial_node(Spatial *p_node); + Spatial *get_spatial_node() const { return spatial_node; } + Ref get_plugin() const { return gizmo_plugin; } + bool intersect_frustum(const Camera *p_camera, const Vector &p_frustum); + void handles_intersect_ray(Camera *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id); + bool intersect_ray(Camera *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal); + bool is_subgizmo_selected(int p_id) const; + Vector get_subgizmo_selection() const; + + virtual void clear(); + virtual void create(); + virtual void transform(); + virtual void redraw(); + virtual void free(); + + virtual bool is_editable() const; + + void set_hidden(bool p_hidden); + void set_plugin(EditorSpatialGizmoPlugin *p_plugin); + + EditorSpatialGizmo(); + ~EditorSpatialGizmo(); +}; + +class EditorSpatialGizmoPlugin : public Resource { + GDCLASS(EditorSpatialGizmoPlugin, Resource); + +public: + static const int VISIBLE = 0; + static const int HIDDEN = 1; + static const int ON_TOP = 2; + +protected: + int current_state; + List current_gizmos; + HashMap>> materials; + + static void _bind_methods(); + virtual bool has_gizmo(Spatial *p_spatial); + virtual Ref create_gizmo(Spatial *p_spatial); + +public: + void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); + void create_icon_material(const String &p_name, const Ref &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1)); + void create_handle_material(const String &p_name, bool p_billboard = false, const Ref &p_icon = nullptr); + void add_material(const String &p_name, Ref p_material); + + Ref get_material(const String &p_name, const Ref &p_gizmo = Ref()); + + virtual String get_gizmo_name() const; + virtual int get_priority() const; + virtual bool can_be_hidden() const; + virtual bool is_selectable_when_hidden() const; + + virtual void redraw(EditorSpatialGizmo *p_gizmo); + virtual bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_id) const; + virtual String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + virtual Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + virtual void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + virtual void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); + + virtual int subgizmos_intersect_ray(const EditorSpatialGizmo *p_gizmo, Camera *p_camera, const Vector2 &p_point) const; + virtual Vector subgizmos_intersect_frustum(const EditorSpatialGizmo *p_gizmo, const Camera *p_camera, const Vector &p_frustum) const; + virtual Transform get_subgizmo_transform(const EditorSpatialGizmo *p_gizmo, int p_id) const; + virtual void set_subgizmo_transform(const EditorSpatialGizmo *p_gizmo, int p_id, Transform p_transform) const; + virtual void commit_subgizmos(const EditorSpatialGizmo *p_gizmo, const Vector &p_ids, const Vector &p_restore, bool p_cancel = false) const; + + + Ref get_gizmo(Spatial *p_spatial); + void set_state(int p_state); + int get_state() const; + void unregister_gizmo(EditorSpatialGizmo *p_gizmo); + + EditorSpatialGizmoPlugin(); + virtual ~EditorSpatialGizmoPlugin(); +}; class LightSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { GDCLASS(LightSpatialGizmoPlugin, EditorSpatialGizmoPlugin); public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); void redraw(EditorSpatialGizmo *p_gizmo); LightSpatialGizmoPlugin(); @@ -74,13 +221,13 @@ class AudioStreamPlayer3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); void redraw(EditorSpatialGizmo *p_gizmo); AudioStreamPlayer3DSpatialGizmoPlugin(); @@ -91,7 +238,7 @@ class ListenerSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -104,13 +251,13 @@ class CameraSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); void redraw(EditorSpatialGizmo *p_gizmo); CameraSpatialGizmoPlugin(); @@ -121,7 +268,7 @@ class MeshInstanceSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool can_be_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -134,7 +281,7 @@ class Sprite3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool can_be_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -147,7 +294,7 @@ class Label3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool can_be_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -163,7 +310,7 @@ class Position3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -175,7 +322,7 @@ class PhysicalBoneSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -187,7 +334,7 @@ class RayCastSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -199,7 +346,7 @@ class SpringArmSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -211,7 +358,7 @@ class VehicleWheelSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -223,14 +370,14 @@ class SoftBodySpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool is_selectable_when_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel); bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int idx) const; SoftBodySpatialGizmoPlugin(); @@ -241,14 +388,14 @@ class VisibilityNotifierGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); VisibilityNotifierGizmoPlugin(); }; @@ -258,7 +405,7 @@ class CPUParticlesGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool is_selectable_when_hidden() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -270,14 +417,14 @@ class ReflectionProbeGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); ReflectionProbeGizmoPlugin(); }; @@ -287,7 +434,7 @@ class CollisionObjectGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -299,14 +446,14 @@ class CollisionShapeSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); - String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_idx) const; - Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_idx) const; - void set_handle(EditorSpatialGizmo *p_gizmo, int p_idx, Camera *p_camera, const Point2 &p_point); - void commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false); + String get_handle_name(const EditorSpatialGizmo *p_gizmo, int p_id) const; + Variant get_handle_value(EditorSpatialGizmo *p_gizmo, int p_id) const; + void set_handle(EditorSpatialGizmo *p_gizmo, int p_id, Camera *p_camera, const Point2 &p_point); + void commit_handle(EditorSpatialGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false); CollisionShapeSpatialGizmoPlugin(); }; @@ -316,7 +463,7 @@ class CollisionPolygonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); CollisionPolygonSpatialGizmoPlugin(); @@ -334,7 +481,7 @@ class NavigationMeshSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -369,7 +516,7 @@ protected: public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); @@ -415,10 +562,10 @@ class RoomSpatialGizmo : public EditorSpatialGizmo { Room *_room = nullptr; public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + virtual String get_handle_name(int p_id) const; + virtual Variant get_handle_value(int p_id); + virtual void set_handle(int p_id, Camera *p_camera, const Point2 &p_point); + virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false); virtual void redraw(); RoomSpatialGizmo(Room *p_room = nullptr); @@ -429,7 +576,7 @@ class RoomGizmoPlugin : public EditorSpatialGizmoPlugin { protected: virtual bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; Ref create_gizmo(Spatial *p_spatial); @@ -447,10 +594,10 @@ class PortalSpatialGizmo : public EditorSpatialGizmo { Color _color_portal_back; public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + virtual String get_handle_name(int p_id) const; + virtual Variant get_handle_value(int p_id); + virtual void set_handle(int p_id, Camera *p_camera, const Point2 &p_point); + virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false); virtual void redraw(); PortalSpatialGizmo(Portal *p_portal = nullptr); @@ -461,7 +608,7 @@ class PortalGizmoPlugin : public EditorSpatialGizmoPlugin { protected: virtual bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; Ref create_gizmo(Spatial *p_spatial); @@ -493,10 +640,10 @@ class OccluderSpatialGizmo : public EditorSpatialGizmo { void _redraw_poly(bool p_hole, const Vector &p_pts, const PoolVector &p_pts_raw); public: - virtual String get_handle_name(int p_idx) const; - virtual Variant get_handle_value(int p_idx); - virtual void set_handle(int p_idx, Camera *p_camera, const Point2 &p_point); - virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false); + virtual String get_handle_name(int p_id) const; + virtual Variant get_handle_value(int p_id); + virtual void set_handle(int p_id, Camera *p_camera, const Point2 &p_point); + virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false); virtual void redraw(); OccluderSpatialGizmo(Occluder *p_occluder = nullptr); @@ -507,7 +654,7 @@ class OccluderGizmoPlugin : public EditorSpatialGizmoPlugin { protected: virtual bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; Ref create_gizmo(Spatial *p_spatial); diff --git a/modules/mesh_data_resource/editor/mdi_ed_plugin.cpp b/modules/mesh_data_resource/editor/mdi_ed_plugin.cpp index 464a5c382..6f729620f 100644 --- a/modules/mesh_data_resource/editor/mdi_ed_plugin.cpp +++ b/modules/mesh_data_resource/editor/mdi_ed_plugin.cpp @@ -39,8 +39,8 @@ void MDIEdPlugin::edit(Object *object) { if (mdi) { if (current_mesh_data_instance) { - Ref g = mdi->get_gizmo(); - Ref c = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(mdi); + Ref c = get_gizmo_from(current_mesh_data_instance); if (g.is_valid() && c.is_valid()) { g->transfer_state_from(c); @@ -68,57 +68,57 @@ String MDIEdPlugin::get_name() const { void MDIEdPlugin::set_translate() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_translate(); } } void MDIEdPlugin::set_scale() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_scale(); } } void MDIEdPlugin::set_rotate() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_rotate(); } } void MDIEdPlugin::set_axis_x(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_axis_x(on); } } void MDIEdPlugin::set_axis_y(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_axis_y(on); } } void MDIEdPlugin::set_axis_z(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_axis_z(on); } } void MDIEdPlugin::set_selection_mode_vertex() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_selection_mode_vertex(); } } void MDIEdPlugin::set_selection_mode_edge() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_selection_mode_edge(); } } void MDIEdPlugin::set_selection_mode_face() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_selection_mode_face(); } } @@ -137,7 +137,7 @@ bool MDIEdPlugin::forward_spatial_gui_input(int index, Camera *camera, const Ref } if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); if (g.is_valid() && g->forward_spatial_gui_input(index, camera, p_event)) { return true; } @@ -148,217 +148,231 @@ bool MDIEdPlugin::forward_spatial_gui_input(int index, Camera *camera, const Ref void MDIEdPlugin::add_box() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->add_box(); } } void MDIEdPlugin::add_triangle() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->add_triangle(); } } void MDIEdPlugin::add_quad() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->add_quad(); } } void MDIEdPlugin::add_triangle_at() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->add_triangle_at(); } } void MDIEdPlugin::add_quad_at() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->add_quad_at(); } } void MDIEdPlugin::split() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->split(); } } void MDIEdPlugin::disconnect_action() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->disconnect_action(); } } void MDIEdPlugin::create_face() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->create_face(); } } void MDIEdPlugin::delete_selected() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->delete_selected(); } } void MDIEdPlugin::generate_normals() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->generate_normals(); } } void MDIEdPlugin::remove_doubles() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->remove_doubles(); } } void MDIEdPlugin::merge_optimize() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->merge_optimize(); } } void MDIEdPlugin::generate_tangents() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->generate_tangents(); } } void MDIEdPlugin::connect_to_first_selected() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->connect_to_first_selected(); } } void MDIEdPlugin::connect_to_avg() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->connect_to_avg(); } } void MDIEdPlugin::connect_to_last_selected() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->connect_to_last_selected(); } } void MDIEdPlugin::mark_seam() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->mark_seam(); } } void MDIEdPlugin::unmark_seam() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->unmark_seam(); } } void MDIEdPlugin::apply_seam() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->apply_seam(); } } void MDIEdPlugin::uv_unwrap() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->uv_unwrap(); } } void MDIEdPlugin::set_pivot_averaged() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_pivot_averaged(); } } void MDIEdPlugin::set_pivot_mdi_origin() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_translate(); } } void MDIEdPlugin::set_pivot_world_origin() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->set_pivot_world_origin(); } } void MDIEdPlugin::visual_indicator_outline_set(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->visual_indicator_outline_set(on); } } void MDIEdPlugin::visual_indicator_seam_set(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->visual_indicator_seam_set(on); } } void MDIEdPlugin::visual_indicator_handle_set(bool on) { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->visual_indicator_handle_set(on); } } void MDIEdPlugin::select_all() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->select_all(); } } void MDIEdPlugin::handle_selection_type_front() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->handle_selection_type_front(); } } void MDIEdPlugin::handle_selection_type_back() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->handle_selection_type_back(); } } void MDIEdPlugin::handle_selection_type_all() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->handle_selection_type_all(); } } void MDIEdPlugin::extrude() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->extrude(); } } void MDIEdPlugin::clean_mesh() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->clean_mesh(); } } void MDIEdPlugin::flip_selected_faces() { if (current_mesh_data_instance) { - Ref g = current_mesh_data_instance->get_gizmo(); + Ref g = get_gizmo_from(current_mesh_data_instance); g->flip_selected_faces(); } } +Ref MDIEdPlugin::get_gizmo_from(MeshDataInstance *mdi) { + Vector> gizmos = mdi->get_gizmos(); + + for (int i = 0; i < gizmos.size(); ++i) { + Ref g = gizmos[i]; + + if (g.is_valid()) { + return g; + } + } + + return Ref(); +} + MDIEdPlugin::MDIEdPlugin(EditorNode *p_node) { editor = p_node; diff --git a/modules/mesh_data_resource/editor/mdi_ed_plugin.h b/modules/mesh_data_resource/editor/mdi_ed_plugin.h index ae7ebdc9f..ad6b87d09 100644 --- a/modules/mesh_data_resource/editor/mdi_ed_plugin.h +++ b/modules/mesh_data_resource/editor/mdi_ed_plugin.h @@ -111,6 +111,8 @@ public: void flip_selected_faces(); + Ref get_gizmo_from(MeshDataInstance *mdi); + MDIEdPlugin(EditorNode *p_node); ~MDIEdPlugin(); diff --git a/modules/mesh_data_resource/editor/mdi_gizmo.h b/modules/mesh_data_resource/editor/mdi_gizmo.h index a2c67cf2b..d266e4a89 100644 --- a/modules/mesh_data_resource/editor/mdi_gizmo.h +++ b/modules/mesh_data_resource/editor/mdi_gizmo.h @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "editor/plugins/spatial_editor_plugin.h" +#include "editor/spatial_editor_gizmos.h" #include "core/math/basis.h" #include "core/math/transform.h" diff --git a/modules/mesh_data_resource/editor/mdi_gizmo_plugin.cpp b/modules/mesh_data_resource/editor/mdi_gizmo_plugin.cpp index e6204c763..afc963ec7 100644 --- a/modules/mesh_data_resource/editor/mdi_gizmo_plugin.cpp +++ b/modules/mesh_data_resource/editor/mdi_gizmo_plugin.cpp @@ -26,7 +26,7 @@ SOFTWARE. #include "mdi_ed_plugin.h" #include "mdi_gizmo.h" -String MDIGizmoPlugin::get_name() const { +String MDIGizmoPlugin::get_gizmo_name() const { return "MDIGizmo"; } int MDIGizmoPlugin::get_priority() const { diff --git a/modules/mesh_data_resource/editor/mdi_gizmo_plugin.h b/modules/mesh_data_resource/editor/mdi_gizmo_plugin.h index cd49e44d2..1e9c31f99 100644 --- a/modules/mesh_data_resource/editor/mdi_gizmo_plugin.h +++ b/modules/mesh_data_resource/editor/mdi_gizmo_plugin.h @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "editor/plugins/spatial_editor_plugin.h" +#include "editor/spatial_editor_gizmos.h" class MDIEdPlugin; @@ -32,7 +32,7 @@ class MDIGizmoPlugin : public EditorSpatialGizmoPlugin { public: void _init(); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; bool is_handle_highlighted(const EditorSpatialGizmo *p_gizmo, int p_idx) const; diff --git a/modules/navigation/navigation_mesh_editor_plugin.cpp b/modules/navigation/navigation_mesh_editor_plugin.cpp index 8fe34a669..8023d15ad 100644 --- a/modules/navigation/navigation_mesh_editor_plugin.cpp +++ b/modules/navigation/navigation_mesh_editor_plugin.cpp @@ -68,7 +68,7 @@ void NavigationMeshEditor::_bake_pressed() { NavigationMeshGenerator::get_singleton()->clear(node->get_navigation_mesh()); NavigationMeshGenerator::get_singleton()->bake(node->get_navigation_mesh(), node); - node->update_gizmo(); + node->update_gizmos(); } void NavigationMeshEditor::_clear_pressed() { @@ -80,7 +80,7 @@ void NavigationMeshEditor::_clear_pressed() { bake_info->set_text(""); if (node) { - node->update_gizmo(); + node->update_gizmos(); } } diff --git a/modules/skeleton_editor/skeleton_editor_plugin.cpp b/modules/skeleton_editor/skeleton_editor_plugin.cpp index e732e1019..28695d540 100644 --- a/modules/skeleton_editor/skeleton_editor_plugin.cpp +++ b/modules/skeleton_editor/skeleton_editor_plugin.cpp @@ -1607,7 +1607,7 @@ void ModuleEditorInspectorPluginSkeleton::parse_begin(Object *p_object) { } void ModuleEditorInspectorPluginSkeleton::set_rest_mode_toggled(const bool p_pressed) { - if (SpatialEditor::get_singleton()->get_selected()->get_class() == "Skeleton" && skel_editor) { + if (SpatialEditor::get_singleton()->get_single_selected_node()->get_class() == "Skeleton" && skel_editor) { skel_editor->set_rest_mode_toggled(p_pressed); } } diff --git a/modules/skeleton_editor/skeleton_editor_plugin.h b/modules/skeleton_editor/skeleton_editor_plugin.h index 4ff120eba..0729c974a 100644 --- a/modules/skeleton_editor/skeleton_editor_plugin.h +++ b/modules/skeleton_editor/skeleton_editor_plugin.h @@ -34,7 +34,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "editor/plugins/spatial_editor_plugin.h" +#include "editor/spatial_editor_gizmos.h" #include "scene/3d/camera.h" #include "scene/3d/mesh_instance.h" #include "scene/3d/skeleton.h" diff --git a/modules/skeleton_editor/spatial_editor_gizmos.cpp b/modules/skeleton_editor/spatial_editor_gizmos.cpp index 6c4dc3fbc..93c544cbc 100644 --- a/modules/skeleton_editor/spatial_editor_gizmos.cpp +++ b/modules/skeleton_editor/spatial_editor_gizmos.cpp @@ -71,7 +71,7 @@ bool ModuleSkeletonSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) { return Object::cast_to(p_spatial) != NULL; } -String ModuleSkeletonSpatialGizmoPlugin::get_name() const { +String ModuleSkeletonSpatialGizmoPlugin::get_gizmo_name() const { return "Skeleton"; } @@ -265,5 +265,5 @@ void ModuleSkeletonSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) { } Ref m = surface_tool->commit(); - p_gizmo->add_mesh(m, false, skel->register_skin(Ref())); + p_gizmo->add_mesh(m, Ref(), Transform(), skel->register_skin(Ref())); } diff --git a/modules/skeleton_editor/spatial_editor_gizmos.h b/modules/skeleton_editor/spatial_editor_gizmos.h index 474b9027c..dcfce3767 100644 --- a/modules/skeleton_editor/spatial_editor_gizmos.h +++ b/modules/skeleton_editor/spatial_editor_gizmos.h @@ -30,7 +30,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "editor/plugins/spatial_editor_plugin.h" +#include "editor/spatial_editor_gizmos.h" #include "scene/3d/camera.h" #include "core/local_vector.h" @@ -46,7 +46,7 @@ class ModuleSkeletonSpatialGizmoPlugin : public EditorSpatialGizmoPlugin { public: bool has_gizmo(Spatial *p_spatial); - String get_name() const; + String get_gizmo_name() const; int get_priority() const; void redraw(EditorSpatialGizmo *p_gizmo); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index d012387a0..025548061 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -807,7 +807,7 @@ uint32_t AudioStreamPlayer3D::get_area_mask() const { void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) { emission_angle_enabled = p_enable; - update_gizmo(); + update_gizmos(); } bool AudioStreamPlayer3D::is_emission_angle_enabled() const { @@ -817,7 +817,7 @@ bool AudioStreamPlayer3D::is_emission_angle_enabled() const { void AudioStreamPlayer3D::set_emission_angle(float p_angle) { ERR_FAIL_COND(p_angle < 0 || p_angle > 90); emission_angle = p_angle; - update_gizmo(); + update_gizmos(); _change_notify("emission_angle"); } diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index ad2e1c64d..28c8b6d78 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -186,7 +186,7 @@ void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far mode = PROJECTION_PERSPECTIVE; VisualServer::get_singleton()->camera_set_perspective(camera, fov, near, far); - update_gizmo(); + update_gizmos(); force_change = false; } void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) { @@ -202,7 +202,7 @@ void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) { force_change = false; VisualServer::get_singleton()->camera_set_orthogonal(camera, size, near, far); - update_gizmo(); + update_gizmos(); } void Camera::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { @@ -219,7 +219,7 @@ void Camera::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p force_change = false; VisualServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far); - update_gizmo(); + update_gizmos(); } void Camera::set_projection(Camera::Projection p_mode) { @@ -773,7 +773,7 @@ void ClippedCamera::_notification(int p_what) { } if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { - update_gizmo(); + update_gizmos(); } } diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp index 6c73c18ad..cc41cbbac 100644 --- a/scene/3d/collision_polygon.cpp +++ b/scene/3d/collision_polygon.cpp @@ -123,7 +123,7 @@ void CollisionPolygon::set_polygon(const Vector &p_polygon) { _build_polygon(); } update_configuration_warning(); - update_gizmo(); + update_gizmos(); } Vector CollisionPolygon::get_polygon() const { @@ -137,7 +137,7 @@ AABB CollisionPolygon::get_item_rect() const { void CollisionPolygon::set_depth(float p_depth) { depth = p_depth; _build_polygon(); - update_gizmo(); + update_gizmos(); } float CollisionPolygon::get_depth() const { @@ -146,7 +146,7 @@ float CollisionPolygon::get_depth() const { void CollisionPolygon::set_disabled(bool p_disabled) { disabled = p_disabled; - update_gizmo(); + update_gizmos(); if (parent) { parent->shape_owner_set_disabled(owner_id, p_disabled); diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp index d25a6d982..6b99143b0 100644 --- a/scene/3d/collision_shape.cpp +++ b/scene/3d/collision_shape.cpp @@ -104,7 +104,7 @@ void CollisionShape::_notification(int p_what) { } void CollisionShape::resource_changed(RES res) { - update_gizmo(); + update_gizmos(); } String CollisionShape::get_configuration_warning() const { @@ -168,7 +168,7 @@ void CollisionShape::set_shape(const Ref &p_shape) { if (!shape.is_null()) { shape->register_owner(this); } - update_gizmo(); + update_gizmos(); if (parent) { parent->shape_owner_clear_shapes(owner_id); if (shape.is_valid()) { @@ -189,7 +189,7 @@ Ref CollisionShape::get_shape() const { void CollisionShape::set_disabled(bool p_disabled) { disabled = p_disabled; - update_gizmo(); + update_gizmos(); if (parent) { parent->shape_owner_set_disabled(owner_id, p_disabled); } diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 0eec09fcc..0b87f0302 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -379,7 +379,7 @@ void Label3D::_im_update() { _shape(); triangle_mesh.unref(); - update_gizmo(); + update_gizmos(); pending_update = false; } diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index aeae110b9..827396d3d 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -41,7 +41,7 @@ void Light::set_param(Param p_param, float p_value) { VS::get_singleton()->light_set_param(light, VS::LightParam(p_param), p_value); if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) { - update_gizmo(); + update_gizmos(); if (p_param == PARAM_SPOT_ANGLE) { _change_notify("spot_angle"); @@ -90,7 +90,7 @@ void Light::set_color(const Color &p_color) { color = p_color; VS::get_singleton()->light_set_color(light, p_color); // The gizmo color depends on the light color, so update it. - update_gizmo(); + update_gizmos(); } Color Light::get_color() const { return color; diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index a7c21d099..874390d47 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -149,7 +149,7 @@ void MeshInstance::set_mesh(const Ref &p_mesh) { set_base(RID()); } - update_gizmo(); + update_gizmos(); _change_notify(); } diff --git a/scene/3d/navigation_mesh_instance.cpp b/scene/3d/navigation_mesh_instance.cpp index 5d66b8272..0cc9e782a 100644 --- a/scene/3d/navigation_mesh_instance.cpp +++ b/scene/3d/navigation_mesh_instance.cpp @@ -67,7 +67,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) { } } - update_gizmo(); + update_gizmos(); } bool NavigationMeshInstance::is_enabled() const { @@ -194,7 +194,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref &p_na emit_signal("navigation_mesh_changed"); - update_gizmo(); + update_gizmos(); update_configuration_warning(); } @@ -294,7 +294,7 @@ void NavigationMeshInstance::_bind_methods() { } void NavigationMeshInstance::_changed_callback(Object *p_changed, const char *p_prop) { - update_gizmo(); + update_gizmos(); update_configuration_warning(); } diff --git a/scene/3d/occluder.cpp b/scene/3d/occluder.cpp index 9e865f89f..48ba3304b 100644 --- a/scene/3d/occluder.cpp +++ b/scene/3d/occluder.cpp @@ -37,7 +37,7 @@ #include "servers/visual_server.h" void Occluder::resource_changed(RES res) { - update_gizmo(); + update_gizmos(); } void Occluder::set_shape(const Ref &p_shape) { @@ -58,7 +58,7 @@ void Occluder::set_shape(const Ref &p_shape) { } } - update_gizmo(); + update_gizmos(); update_configuration_warning(); } Ref Occluder::get_shape() const { @@ -151,7 +151,7 @@ void Occluder::_notification(int p_what) { case NOTIFICATION_INTERNAL_PROCESS: { if (PortalOcclusionCuller::_redraw_gizmo) { PortalOcclusionCuller::_redraw_gizmo = false; - update_gizmo(); + update_gizmos(); } } break; } diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index ced3171f3..6a1c18ff7 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -39,7 +39,7 @@ void Path::_notification(int p_what) { void Path::_curve_changed() { if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) { - update_gizmo(); + update_gizmos(); } if (is_inside_tree()) { emit_signal("curve_changed"); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 9fd34ec3d..c5f64c037 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -2267,9 +2267,7 @@ bool PhysicalBone::_set(const StringName &p_name, const Variant &p_value) { if (joint_data) { if (joint_data->_set(p_name, p_value, joint)) { #ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) { - get_gizmo()->redraw(); - } + update_gizmos(); #endif return true; } @@ -2600,9 +2598,7 @@ void PhysicalBone::set_joint_type(JointType p_joint_type) { #ifdef TOOLS_ENABLED _change_notify(); - if (get_gizmo().is_valid()) { - get_gizmo()->redraw(); - } + update_gizmos(); #endif } @@ -2620,9 +2616,7 @@ void PhysicalBone::set_joint_offset(const Transform &p_offset) { set_ignore_transform_notification(false); #ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) { - get_gizmo()->redraw(); - } + update_gizmos(); #endif } @@ -2641,9 +2635,7 @@ void PhysicalBone::set_body_offset(const Transform &p_offset) { set_ignore_transform_notification(false); #ifdef TOOLS_ENABLED - if (get_gizmo().is_valid()) { - get_gizmo()->redraw(); - } + update_gizmos(); #endif } diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 5db9ce3e9..70320d534 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -371,7 +371,7 @@ void HingeJoint::set_param(Param p_param, float p_value) { PhysicsServer::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer::HingeJointParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float HingeJoint::get_param(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -385,7 +385,7 @@ void HingeJoint::set_flag(Flag p_flag, bool p_value) { PhysicsServer::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer::HingeJointFlag(p_flag), p_value); } - update_gizmo(); + update_gizmos(); } bool HingeJoint::get_flag(Flag p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); @@ -519,7 +519,7 @@ void SliderJoint::set_param(Param p_param, float p_value) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer::SliderJointParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float SliderJoint::get_param(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -625,7 +625,7 @@ void ConeTwistJoint::set_param(Param p_param, float p_value) { PhysicsServer::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer::ConeTwistJointParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float ConeTwistJoint::get_param(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -881,7 +881,7 @@ void Generic6DOFJoint::set_param_x(Param p_param, float p_value) { PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float Generic6DOFJoint::get_param_x(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -894,7 +894,7 @@ void Generic6DOFJoint::set_param_y(Param p_param, float p_value) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float Generic6DOFJoint::get_param_y(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -907,7 +907,7 @@ void Generic6DOFJoint::set_param_z(Param p_param, float p_value) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); } - update_gizmo(); + update_gizmos(); } float Generic6DOFJoint::get_param_z(Param p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); @@ -920,7 +920,7 @@ void Generic6DOFJoint::set_flag_x(Flag p_flag, bool p_enabled) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); } - update_gizmo(); + update_gizmos(); } bool Generic6DOFJoint::get_flag_x(Flag p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); @@ -933,7 +933,7 @@ void Generic6DOFJoint::set_flag_y(Flag p_flag, bool p_enabled) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); } - update_gizmo(); + update_gizmos(); } bool Generic6DOFJoint::get_flag_y(Flag p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); @@ -946,7 +946,7 @@ void Generic6DOFJoint::set_flag_z(Flag p_flag, bool p_enabled) { if (get_joint().is_valid()) { PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); } - update_gizmo(); + update_gizmos(); } bool Generic6DOFJoint::get_flag_z(Flag p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); diff --git a/scene/3d/portal.cpp b/scene/3d/portal.cpp index 491a57f94..58c0644b0 100644 --- a/scene/3d/portal.cpp +++ b/scene/3d/portal.cpp @@ -123,7 +123,7 @@ void Portal::set_point(int p_idx, const Vector2 &p_point) { _pts_local_raw.set(p_idx, p_point); _sanitize_points(); - update_gizmo(); + update_gizmos(); } void Portal::set_points(const PoolVector &p_points) { @@ -132,7 +132,7 @@ void Portal::set_points(const PoolVector &p_points) { if (is_inside_tree()) { portal_update(); - update_gizmo(); + update_gizmos(); } } @@ -170,7 +170,7 @@ void Portal::_notification(int p_what) { // we can't calculate world points until we have entered the tree portal_update(); - update_gizmo(); + update_gizmos(); } break; case NOTIFICATION_EXIT_WORLD: { @@ -188,7 +188,7 @@ void Portal::_notification(int p_what) { // and needs 'resyncing' to the global scale of the portal node. // We really only need to do this when Z scale is changed, but it is easier codewise // to always change it, unless we have evidence this is a performance problem. - update_gizmo(); + update_gizmos(); } break; } } @@ -204,7 +204,7 @@ bool Portal::get_portal_active() const { void Portal::set_use_default_margin(bool p_use) { _use_default_margin = p_use; - update_gizmo(); + update_gizmos(); } bool Portal::get_use_default_margin() const { @@ -216,7 +216,7 @@ void Portal::set_portal_margin(real_t p_margin) { if (!_use_default_margin) { // give visual feedback in the editor for the portal margin zone - update_gizmo(); + update_gizmos(); } } @@ -343,7 +343,7 @@ void Portal::flip() { _sanitize_points(); portal_update(); - update_gizmo(); + update_gizmos(); } bool Portal::create_from_mesh_instance(const MeshInstance *p_mi) { diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index abe2ae2e2..51d15521b 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -40,7 +40,7 @@ void RayCast::set_cast_to(const Vector3 &p_point) { cast_to = p_point; - update_gizmo(); + update_gizmos(); if (Engine::get_singleton()->is_editor_hint()) { if (is_inside_tree()) { @@ -102,7 +102,7 @@ Vector3 RayCast::get_collision_normal() const { void RayCast::set_enabled(bool p_enabled) { enabled = p_enabled; - update_gizmo(); + update_gizmos(); if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { set_physics_process_internal(p_enabled); @@ -373,7 +373,7 @@ void RayCast::_update_debug_shape_vertices() { void RayCast::set_debug_shape_thickness(const int p_debug_shape_thickness) { debug_shape_thickness = p_debug_shape_thickness; - update_gizmo(); + update_gizmos(); if (Engine::get_singleton()->is_editor_hint()) { if (is_inside_tree()) { diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 53fd440be..8b808574f 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -94,7 +94,7 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) { VS::get_singleton()->reflection_probe_set_extents(probe, extents); VS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); _change_notify("extents"); - update_gizmo(); + update_gizmos(); } Vector3 ReflectionProbe::get_extents() const { return extents; @@ -112,7 +112,7 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) { VS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); _change_notify("origin_offset"); - update_gizmo(); + update_gizmos(); } Vector3 ReflectionProbe::get_origin_offset() const { return origin_offset; diff --git a/scene/3d/room_manager.cpp b/scene/3d/room_manager.cpp index b27c163d4..7b1fe23fa 100644 --- a/scene/3d/room_manager.cpp +++ b/scene/3d/room_manager.cpp @@ -412,7 +412,7 @@ void RoomManager::_update_portal_gizmos(Spatial *p_node) { Portal *portal = Object::cast_to(p_node); if (portal) { - portal->update_gizmo(); + portal->update_gizmos(); } // recurse @@ -856,7 +856,7 @@ void RoomManager::_third_pass_rooms(const LocalVector &p_portals) { if (!_convert_room_hull_final(room, p_portals)) { found_errors = true; } - room->update_gizmo(); + room->update_gizmos(); room->update_configuration_warning(); } @@ -1028,7 +1028,7 @@ void RoomManager::_autolink_portals(Spatial *p_roomlist, LocalVector & #ifdef TOOLS_ENABLED portal->_warning_autolink_failed = true; - portal->update_gizmo(); + portal->update_gizmos(); #endif } } // for portal @@ -1190,7 +1190,7 @@ void RoomManager::_check_portal_for_warnings(Portal *p_portal, const AABB &p_roo p_portal->_warning_autolink_failed = false; if (changed) { - p_portal->update_gizmo(); + p_portal->update_gizmos(); } #endif } @@ -1620,7 +1620,7 @@ bool RoomManager::_room_regenerate_bound(Room *p_room) { } p_room->_bound_mesh_data = md; - p_room->update_gizmo(); + p_room->update_gizmos(); return true; } @@ -1963,7 +1963,7 @@ void RoomManager::_update_gizmos_recursive(Node *p_node) { Portal *portal = Object::cast_to(p_node); if (portal) { - portal->update_gizmo(); + portal->update_gizmos(); } for (int n = 0; n < p_node->get_child_count(); n++) { diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 362d9d1f2..089cfb3a4 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -490,7 +490,7 @@ void Skeleton::add_bone(const String &p_name) { process_order_dirty = true; version++; _make_dirty(); - update_gizmo(); + update_gizmos(); } int Skeleton::find_bone(const String &p_name) const { for (int i = 0; i < bones.size(); i++) { @@ -1373,7 +1373,7 @@ Skeleton::~Skeleton() { void Skeleton::set_selected_bone(int p_bone) { selected_bone = p_bone; - update_gizmo(); + update_gizmos(); return; } @@ -1445,5 +1445,5 @@ void Skeleton::remove_bone(const int p_bone_idx) { property_list_changed_notify(); _make_dirty(); - update_gizmo(); + update_gizmos(); } diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 4e384e18b..61f93a685 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -78,7 +78,7 @@ SpatialGizmo::SpatialGizmo() { void Spatial::_notify_dirty() { #ifdef TOOLS_ENABLED - if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { + if ((!data.gizmos.empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { #else if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { @@ -111,7 +111,7 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) { E->get()->_propagate_transform_changed(p_origin); } #ifdef TOOLS_ENABLED - if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { + if ((!data.gizmos.empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) { #else if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) { #endif @@ -200,15 +200,16 @@ void Spatial::_notification(int p_what) { } #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { - //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this); get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); - if (!data.gizmo_disabled) { - if (data.gizmo.is_valid()) { - data.gizmo->create(); + + if (!data.gizmos_disabled) { + for (int i = 0; i < data.gizmos.size(); i++) { + data.gizmos.write[i]->create(); + if (is_visible_in_tree()) { - data.gizmo->redraw(); + data.gizmos.write[i]->redraw(); } - data.gizmo->transform(); + data.gizmos.write[i]->transform(); } } } @@ -217,10 +218,7 @@ void Spatial::_notification(int p_what) { } break; case NOTIFICATION_EXIT_WORLD: { #ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) { - data.gizmo->free(); - data.gizmo.unref(); - } + clear_gizmos(); #endif if (get_script_instance()) { @@ -234,8 +232,8 @@ void Spatial::_notification(int p_what) { case NOTIFICATION_TRANSFORM_CHANGED: { #ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) { - data.gizmo->transform(); + for (int i = 0; i < data.gizmos.size(); i++) { + data.gizmos.write[i]->transform(); } #endif } break; @@ -539,77 +537,121 @@ Vector3 Spatial::get_scale() const { return data.scale; } -void Spatial::update_gizmo() { +void Spatial::update_gizmos() { #ifdef TOOLS_ENABLED if (!is_inside_world()) { return; } - if (!data.gizmo.is_valid()) { - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this); - } - if (!data.gizmo.is_valid()) { + + if (data.gizmos.empty()) { return; } - if (data.gizmo_dirty) { - return; - } - data.gizmo_dirty = true; - MessageQueue::get_singleton()->push_call(this, "_update_gizmo"); + + data.gizmos_dirty = true; + MessageQueue::get_singleton()->push_call(this, "_update_gizmos"); #endif } -void Spatial::set_gizmo(const Ref &p_gizmo) { +void Spatial::clear_subgizmo_selection() { #ifdef TOOLS_ENABLED - - if (data.gizmo_disabled) { + if (!is_inside_world()) { return; } - if (data.gizmo.is_valid() && is_inside_world()) { - data.gizmo->free(); + + if (data.gizmos.empty()) { + return; } - data.gizmo = p_gizmo; - if (data.gizmo.is_valid() && is_inside_world()) { - data.gizmo->create(); + + if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) { + get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_clear_subgizmo_selection, this); + } +#endif +} + +void Spatial::add_gizmo(Ref p_gizmo) { +#ifdef TOOLS_ENABLED + if (data.gizmos_disabled || p_gizmo.is_null()) { + return; + } + + data.gizmos.push_back(p_gizmo); + + if (p_gizmo.is_valid() && is_inside_world()) { + p_gizmo->create(); if (is_visible_in_tree()) { - data.gizmo->redraw(); + p_gizmo->redraw(); } - data.gizmo->transform(); + p_gizmo->transform(); } - #endif } -Ref Spatial::get_gizmo() const { +void Spatial::remove_gizmo(Ref p_gizmo) { #ifdef TOOLS_ENABLED - return data.gizmo; + int idx = data.gizmos.find(p_gizmo); + if (idx != -1) { + p_gizmo->free(); + data.gizmos.remove(idx); + } +#endif +} + +void Spatial::clear_gizmos() { +#ifdef TOOLS_ENABLED + for (int i = 0; i < data.gizmos.size(); i++) { + data.gizmos.write[i]->free(); + } + + data.gizmos.clear(); +#endif +} + +Vector Spatial::get_gizmos_bind() const { + Vector ret; + +#ifdef TOOLS_ENABLED + for (int i = 0; i < data.gizmos.size(); i++) { + ret.push_back(data.gizmos[i].get_ref_ptr()); + } +#endif + + return ret; +} + +Vector> Spatial::get_gizmos() const { +#ifdef TOOLS_ENABLED + + return data.gizmos; #else - return Ref(); + return Vector>(); #endif } -void Spatial::_update_gizmo() { +void Spatial::_update_gizmos() { #ifdef TOOLS_ENABLED - if (!is_inside_world()) { + if (data.gizmos_disabled || !is_inside_world() || !data.gizmos_dirty) { return; } - data.gizmo_dirty = false; - if (data.gizmo.is_valid()) { + + data.gizmos_dirty = false; + for (int i = 0; i < data.gizmos.size(); i++) { if (is_visible_in_tree()) { - data.gizmo->redraw(); + data.gizmos.write[i]->redraw(); } else { - data.gizmo->clear(); + data.gizmos.write[i]->clear(); } } #endif } -void Spatial::set_disable_gizmo(bool p_enabled) { +void Spatial::set_disable_gizmos(bool p_enabled) { #ifdef TOOLS_ENABLED - data.gizmo_disabled = p_enabled; - if (!p_enabled && data.gizmo.is_valid()) { - data.gizmo = Ref(); + data.gizmos_disabled = p_enabled; + + if (!p_enabled) { + clear_gizmos(); } #endif } @@ -656,9 +698,11 @@ void Spatial::_propagate_visibility_changed() { notification(NOTIFICATION_VISIBILITY_CHANGED); emit_signal(SceneStringNames::get_singleton()->visibility_changed); _change_notify("visible"); + #ifdef TOOLS_ENABLED - if (data.gizmo.is_valid()) { - _update_gizmo(); + if (!data.gizmos.empty()) { + data.gizmos_dirty = true; + _update_gizmos(); } #endif @@ -890,11 +934,13 @@ void Spatial::_bind_methods() { ClassDB::bind_method(D_METHOD("force_update_transform"), &Spatial::force_update_transform); - ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); + ClassDB::bind_method(D_METHOD("_update_gizmos"), &Spatial::_update_gizmos); - ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo); - ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Spatial::set_gizmo); - ClassDB::bind_method(D_METHOD("get_gizmo"), &Spatial::get_gizmo); + ClassDB::bind_method(D_METHOD("update_gizmos"), &Spatial::update_gizmos); + ClassDB::bind_method(D_METHOD("add_gizmo", "gizmo"), &Spatial::add_gizmo); + ClassDB::bind_method(D_METHOD("get_gizmos"), &Spatial::get_gizmos_bind); + ClassDB::bind_method(D_METHOD("clear_gizmos"), &Spatial::clear_gizmos); + ClassDB::bind_method(D_METHOD("clear_subgizmo_selection"), &Spatial::clear_subgizmo_selection); ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Spatial::set_visible); ClassDB::bind_method(D_METHOD("is_visible"), &Spatial::is_visible); @@ -948,7 +994,6 @@ void Spatial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); ADD_GROUP("Visibility", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "SpatialGizmo", 0), "set_gizmo", "get_gizmo"); ADD_SIGNAL(MethodInfo("visibility_changed")); ADD_SIGNAL(MethodInfo("gameplay_entered")); @@ -973,8 +1018,8 @@ Spatial::Spatial() : data.client_physics_interpolation_data = nullptr; #ifdef TOOLS_ENABLED - data.gizmo_disabled = false; - data.gizmo_dirty = false; + data.gizmos_disabled = false; + data.gizmos_dirty = false; #endif data.notify_local_transform = false; data.notify_transform = false; diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 5c6b53248..701b1b9b6 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -107,14 +107,14 @@ class Spatial : public Node { ClientPhysicsInterpolationData *client_physics_interpolation_data; #ifdef TOOLS_ENABLED - Ref gizmo; - bool gizmo_disabled : 1; - bool gizmo_dirty : 1; + Vector> gizmos; + bool gizmos_disabled : 1; + bool gizmos_dirty : 1; #endif } data; - void _update_gizmo(); + void _update_gizmos(); void _notify_dirty(); void _propagate_transform_changed(Spatial *p_origin); @@ -189,10 +189,14 @@ public: void set_disable_scale(bool p_enabled); bool is_scale_disabled() const; - void set_disable_gizmo(bool p_enabled); - void update_gizmo(); - void set_gizmo(const Ref &p_gizmo); - Ref get_gizmo() const; + void set_disable_gizmos(bool p_enabled); + void update_gizmos(); + void clear_subgizmo_selection(); + Vector> get_gizmos() const; + Vector get_gizmos_bind() const; + void add_gizmo(Ref p_gizmo); + void remove_gizmo(Ref p_gizmo); + void clear_gizmos(); _FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; diff --git a/scene/3d/spring_arm.cpp b/scene/3d/spring_arm.cpp index fd4bb7711..25b2764ce 100644 --- a/scene/3d/spring_arm.cpp +++ b/scene/3d/spring_arm.cpp @@ -92,7 +92,7 @@ float SpringArm::get_length() const { void SpringArm::set_length(float p_length) { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) { - update_gizmo(); + update_gizmos(); } spring_length = p_length; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index ff45659c6..9e22c52d7 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -183,7 +183,7 @@ void SpriteBase3D::_queue_update() { } triangle_mesh.unref(); - update_gizmo(); + update_gizmos(); pending_update = true; call_deferred(SceneStringNames::get_singleton()->_im_update); diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index afdef672c..c79d59141 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -150,7 +150,7 @@ void VehicleWheel::_update(PhysicsDirectBodyState *s) { void VehicleWheel::set_radius(float p_radius) { m_wheelRadius = p_radius; - update_gizmo(); + update_gizmos(); } float VehicleWheel::get_radius() const { @@ -159,7 +159,7 @@ float VehicleWheel::get_radius() const { void VehicleWheel::set_suspension_rest_length(float p_length) { m_suspensionRestLength = p_length; - update_gizmo(); + update_gizmos(); } float VehicleWheel::get_suspension_rest_length() const { return m_suspensionRestLength; diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index dca6248fb..da80a14c2 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -105,7 +105,7 @@ void VisibilityNotifier::set_aabb(const AABB &p_aabb) { } _change_notify("aabb"); - update_gizmo(); + update_gizmos(); } AABB VisibilityNotifier::get_aabb() const { diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 4d615f72e..01b53ed8f 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -142,6 +142,7 @@ SceneStringNames::SceneStringNames() { _spatial_editor_group = StaticCString::create("_spatial_editor_group"); _request_gizmo = StaticCString::create("_request_gizmo"); + _clear_subgizmo_selection = StaticCString::create("_clear_subgizmo_selection"); offset = StaticCString::create("offset"); unit_offset = StaticCString::create("unit_offset"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 16b46910c..92cd83bae 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -160,6 +160,7 @@ public: StringName _spatial_editor_group; StringName _request_gizmo; + StringName _clear_subgizmo_selection; StringName offset; StringName unit_offset;