summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/input/input.cpp5
-rw-r--r--core/math/triangle_mesh.cpp12
-rw-r--r--doc/classes/EditorNode3DGizmo.xml127
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml93
-rw-r--r--doc/classes/Node3D.xml39
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp (renamed from editor/node_3d_editor_gizmos.cpp)914
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h (renamed from editor/node_3d_editor_gizmos.h)257
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp1288
-rw-r--r--editor/plugins/node_3d_editor_plugin.h177
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp56
-rw-r--r--editor/plugins/path_3d_editor_plugin.h10
-rw-r--r--editor/scene_tree_editor.cpp36
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--modules/csg/csg_gizmos.cpp44
-rw-r--r--modules/csg/csg_gizmos.h22
-rw-r--r--modules/csg/csg_shape.cpp52
-rw-r--r--modules/navigation/navigation_mesh_editor_plugin.cpp4
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp12
-rw-r--r--modules/visual_script/visual_script_func_nodes.h3
-rw-r--r--scene/3d/audio_stream_player_3d.cpp4
-rw-r--r--scene/3d/camera_3d.cpp8
-rw-r--r--scene/3d/collision_polygon_3d.cpp6
-rw-r--r--scene/3d/collision_shape_3d.cpp6
-rw-r--r--scene/3d/decal.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp20
-rw-r--r--scene/3d/light_3d.cpp4
-rw-r--r--scene/3d/lightmap_gi.cpp2
-rw-r--r--scene/3d/mesh_instance_3d.cpp4
-rw-r--r--scene/3d/navigation_region_3d.cpp6
-rw-r--r--scene/3d/node_3d.cpp141
-rw-r--r--scene/3d/node_3d.h20
-rw-r--r--scene/3d/occluder_instance_3d.cpp4
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp12
-rw-r--r--scene/3d/physics_joint_3d.cpp20
-rw-r--r--scene/3d/ray_cast_3d.cpp6
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/skeleton_3d.cpp2
-rw-r--r--scene/3d/spring_arm_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp2
-rw-r--r--scene/3d/vehicle_body_3d.cpp4
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp2
-rw-r--r--scene/3d/voxel_gi.cpp4
-rw-r--r--scene/gui/popup_menu.cpp12
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
47 files changed, 2044 insertions, 1413 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp
index f57985831a..6bcf2b4777 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -101,7 +101,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action", "exact_match"), &Input::is_action_just_pressed, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_action_just_released", "action", "exact_match"), &Input::is_action_just_released, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact_match"), &Input::get_action_raw_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis);
ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
@@ -169,7 +169,8 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
String pf = p_function;
if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" ||
pf == "is_action_just_pressed" || pf == "is_action_just_released" ||
- pf == "get_action_strength" || pf == "get_axis" || pf == "get_vector")) {
+ pf == "get_action_strength" || pf == "get_action_raw_strength" ||
+ pf == "get_axis" || pf == "get_vector")) {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 903d5951a8..bf06c848c5 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -32,9 +32,9 @@
#include "core/templates/sort_array.h"
-int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) {
- if (p_depth > max_depth) {
- max_depth = p_depth;
+int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) {
+ if (p_depth > r_max_depth) {
+ r_max_depth = p_depth;
}
if (p_size == 1) {
@@ -70,10 +70,10 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in
} break;
}
- int left = _create_bvh(p_bvh, p_bb, p_from, p_size / 2, p_depth + 1, max_depth, max_alloc);
- int right = _create_bvh(p_bvh, p_bb, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, max_depth, max_alloc);
+ int left = _create_bvh(p_bvh, p_bb, p_from, p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
+ int right = _create_bvh(p_bvh, p_bb, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
- int index = max_alloc++;
+ int index = r_max_alloc++;
BVH *_new = &p_bvh[index];
_new->aabb = aabb;
_new->center = aabb.position + aabb.size * 0.5;
diff --git a/doc/classes/EditorNode3DGizmo.xml b/doc/classes/EditorNode3DGizmo.xml
index 221b5e44d6..d4d1e4a652 100644
--- a/doc/classes/EditorNode3DGizmo.xml
+++ b/doc/classes/EditorNode3DGizmo.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorNode3DGizmo" inherits="Node3DGizmo" version="4.0">
<brief_description>
- Custom gizmo for editing Node3D objects.
+ Gizmo for editing Node3D objects.
</brief_description>
<description>
- Custom gizmo that is used for providing custom visualization and editing (handles) for Node3D objects. See [EditorNode3DGizmoPlugin] for more information.
+ Gizmo that is used for providing custom visualization and editing (handles and subgizmos) for Node3D objects. Can be overridden to create custom gizmos, but for simple gizmos creating a [EditorNode3DGizmoPlugin] is usually recommended.
</description>
<tutorials>
</tutorials>
@@ -12,64 +12,119 @@
<method name="_commit_handle" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<argument index="1" name="restore" type="Variant">
</argument>
<argument index="2" name="cancel" type="bool" default="false">
</argument>
<description>
- 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.
+ </description>
+ </method>
+ <method name="_commit_subgizmos" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="ids" type="PackedInt32Array">
+ </argument>
+ <argument index="1" name="restore" type="Array">
+ </argument>
+ <argument index="2" name="cancel" type="bool" default="false">
+ </argument>
+ <description>
+ 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.
</description>
</method>
<method name="_get_handle_name" qualifiers="virtual">
<return type="String">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- 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.
</description>
</method>
<method name="_get_handle_value" qualifiers="virtual">
<return type="Variant">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- 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].
+ </description>
+ </method>
+ <method name="_get_subgizmo_transform" qualifiers="virtual">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ 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].
</description>
</method>
<method name="_is_handle_highlighted" qualifiers="virtual">
<return type="bool">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- 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.
</description>
</method>
<method name="_redraw" qualifiers="virtual">
<return type="void">
</return>
<description>
- This function is called when the [Node3D] this gizmo refers to changes (the [method Node3D.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.
</description>
</method>
<method name="_set_handle" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<argument index="1" name="camera" type="Camera3D">
</argument>
<argument index="2" name="point" type="Vector2">
</argument>
<description>
- This function is used when the user drags a gizmo handle (previously added with [method add_handles]) in screen coordinates.
- The [Camera3D] 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.
+ </description>
+ </method>
+ <method name="_set_subgizmo_transform" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="transform" type="Transform3D">
+ </argument>
+ <description>
+ 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 Node3D's local coordinate system.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_frustum" qualifiers="virtual">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="camera" type="Camera3D">
+ </argument>
+ <argument index="1" name="frustum" type="Array">
+ </argument>
+ <description>
+ 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].
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_ray" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="camera" type="Camera3D">
+ </argument>
+ <argument index="1" name="point" type="Vector2">
+ </argument>
+ <description>
+ 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].
</description>
</method>
<method name="add_collision_segments">
@@ -78,7 +133,7 @@
<argument index="0" name="segments" type="PackedVector3Array">
</argument>
<description>
- 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].
</description>
</method>
<method name="add_collision_triangles">
@@ -87,7 +142,7 @@
<argument index="0" name="triangles" type="TriangleMesh">
</argument>
<description>
- 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].
</description>
</method>
<method name="add_handles">
@@ -97,13 +152,15 @@
</argument>
<argument index="1" name="material" type="Material">
</argument>
- <argument index="2" name="billboard" type="bool" default="false">
+ <argument index="2" name="ids" type="PackedInt32Array">
</argument>
- <argument index="3" name="secondary" type="bool" default="false">
+ <argument index="3" name="billboard" type="bool" default="false">
+ </argument>
+ <argument index="4" name="secondary" type="bool" default="false">
</argument>
<description>
- 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 Node3D. 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].
</description>
</method>
<method name="add_lines">
@@ -118,7 +175,7 @@
<argument index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
</argument>
<description>
- 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].
</description>
</method>
<method name="add_mesh">
@@ -126,14 +183,14 @@
</return>
<argument index="0" name="mesh" type="ArrayMesh">
</argument>
- <argument index="1" name="billboard" type="bool" default="false">
+ <argument index="1" name="material" type="Material" default="null">
</argument>
- <argument index="2" name="skeleton" type="SkinReference" default="null">
+ <argument index="2" name="transform" type="Transform3D" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
</argument>
- <argument index="3" name="material" type="Material" default="null">
+ <argument index="3" name="skeleton" type="SkinReference" default="null">
</argument>
<description>
- 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].
</description>
</method>
<method name="add_unscaled_billboard">
@@ -146,7 +203,7 @@
<argument index="2" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
</argument>
<description>
- 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].
</description>
</method>
<method name="clear">
@@ -170,6 +227,22 @@
Returns the Node3D node associated with this gizmo.
</description>
</method>
+ <method name="get_subgizmo_selection" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <description>
+ Returns a list of the currently selected subgizmos. Can be used to highlight selected elements during [method _redraw].
+ </description>
+ </method>
+ <method name="is_subgizmo_selected" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <description>
+ Returns [code]true[/code] if the given subgizmo is currently selected. Can be used to highlight selected elements during [method _redraw].
+ </description>
+ </method>
<method name="set_hidden">
<return type="void">
</return>
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 41c94cbbc6..10d6bd8bc8 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -14,7 +14,7 @@
<return type="bool">
</return>
<description>
- 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.
</description>
</method>
<method name="_commit_handle" qualifiers="virtual">
@@ -22,14 +22,31 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<argument index="2" name="restore" type="Variant">
</argument>
<argument index="3" name="cancel" type="bool" default="false">
</argument>
<description>
- 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 EditorNode3DGizmo.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.
+ </description>
+ </method>
+ <method name="_commit_subgizmos" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="ids" type="PackedInt32Array">
+ </argument>
+ <argument index="2" name="restore" type="Array">
+ </argument>
+ <argument index="3" name="cancel" type="bool" default="false">
+ </argument>
+ <description>
+ 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.
</description>
</method>
<method name="_create_gizmo" qualifiers="virtual">
@@ -53,7 +70,7 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
Override this method to provide gizmo's handle names. Called for this plugin's active gizmos.
@@ -64,18 +81,29 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
- 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.
</description>
</method>
<method name="_get_priority" qualifiers="virtual">
<return type="int">
</return>
<description>
- 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.
+ </description>
+ </method>
+ <method name="_get_subgizmo_transform" qualifiers="virtual">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="id" type="int">
+ </argument>
+ <description>
+ 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.
</description>
</method>
<method name="_has_gizmo" qualifiers="virtual">
@@ -92,10 +120,10 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
- 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.
</description>
</method>
<method name="_is_selectable_when_hidden" qualifiers="virtual">
@@ -111,7 +139,7 @@
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
<description>
- 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 EditorNode3DGizmo.clear] at the beginning of this method and then add visual elements depending on the node's properties.
</description>
</method>
<method name="_set_handle" qualifiers="virtual">
@@ -119,14 +147,53 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<argument index="2" name="camera" type="Camera3D">
</argument>
<argument index="3" name="point" type="Vector2">
</argument>
<description>
- 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 EditorNode3DGizmo.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.
+ </description>
+ </method>
+ <method name="_set_subgizmo_transform" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="id" type="int">
+ </argument>
+ <argument index="2" name="transform" type="Transform3D">
+ </argument>
+ <description>
+ 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 Node3D's local coordinate system. Called for this plugin's active gizmos.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_frustum" qualifiers="virtual">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="camera" type="Camera3D">
+ </argument>
+ <argument index="2" name="frustum" type="Array">
+ </argument>
+ <description>
+ 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.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_ray" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="camera" type="Camera3D">
+ </argument>
+ <argument index="2" name="point" type="Vector2">
+ </argument>
+ <description>
+ 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.
</description>
</method>
<method name="add_material">
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 14e03a2186..9c05ed1ef6 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -13,6 +13,29 @@
<link title="All 3D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/3d</link>
</tutorials>
<methods>
+ <method name="add_gizmo">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="Node3DGizmo">
+ </argument>
+ <description>
+ Attach a gizmo to this [code]Node3D[/code].
+ </description>
+ </method>
+ <method name="clear_gizmos">
+ <return type="void">
+ </return>
+ <description>
+ Clear all gizmos attached to this [code]Node3D[/code].
+ </description>
+ </method>
+ <method name="clear_subgizmo_selection">
+ <return type="void">
+ </return>
+ <description>
+ Clears subgizmo selection for this node in the editor. Useful when subgizmo IDs become invalid after a property change.
+ </description>
+ </method>
<method name="force_update_transform">
<return type="void">
</return>
@@ -20,6 +43,13 @@
Forces the transform to update. Transform changes in physics are not instant for performance reasons. Transforms are accumulated and then set. Use this if you need an up-to-date transform when doing physics operations.
</description>
</method>
+ <method name="get_gizmos" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Returns all the gizmos attached to this [code]Node3D[/code].
+ </description>
+ </method>
<method name="get_parent_node_3d" qualifiers="const">
<return type="Node3D">
</return>
@@ -276,18 +306,15 @@
Changes the node's position by the given offset [Vector3] in local space.
</description>
</method>
- <method name="update_gizmo">
+ <method name="update_gizmos">
<return type="void">
</return>
<description>
- Updates the [Node3DGizmo] of this node.
+ Updates all the [Node3DGizmo]s attached to this node.
</description>
</method>
</methods>
<members>
- <member name="gizmo" type="Node3DGizmo" setter="set_gizmo" getter="get_gizmo">
- The [Node3DGizmo] for this node. Used for example in [EditorNode3DGizmo] as custom visualization and editing handles in Editor.
- </member>
<member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
@@ -324,7 +351,7 @@
<constants>
<constant name="NOTIFICATION_TRANSFORM_CHANGED" value="2000">
Node3D 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.
</constant>
<constant name="NOTIFICATION_ENTER_WORLD" value="41">
Node3D nodes receives this notification when they are registered to new [World3D] resource.
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 74fb38b66b..492ba51b8a 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -33,7 +33,9 @@
#include "core/math/convex_hull.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/audio_stream_player_3d.h"
+#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/cpu_particles_3d.h"
@@ -106,58 +108,122 @@ void EditorNode3DGizmo::clear() {
void EditorNode3DGizmo::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 (Node3DEditor::get_singleton()->is_current_selected_gizmo(this)) {
+ Node3DEditor::get_singleton()->update_transform_gizmo();
+ }
}
-String EditorNode3DGizmo::get_handle_name(int p_idx) const {
+String EditorNode3DGizmo::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 EditorNode3DGizmo::is_handle_highlighted(int p_idx) const {
+bool EditorNode3DGizmo::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 EditorNode3DGizmo::get_handle_value(int p_idx) {
+Variant EditorNode3DGizmo::get_handle_value(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_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 EditorNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void EditorNode3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const {
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 EditorNode3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
+void EditorNode3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) const {
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_id, p_restore, p_cancel);
+}
+
+int EditorNode3DGizmo::subgizmos_intersect_ray(Camera3D *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<int> EditorNode3DGizmo::subgizmos_intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &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<int>());
+ return gizmo_plugin->subgizmos_intersect_frustum(this, p_camera, p_frustum);
+}
+
+Transform3D EditorNode3DGizmo::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, Transform3D());
+ return gizmo_plugin->get_subgizmo_transform(this, p_id);
+}
+
+void EditorNode3DGizmo::set_subgizmo_transform(int p_id, Transform3D 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->commit_handle(this, p_idx, p_restore, p_cancel);
+ gizmo_plugin->set_subgizmo_transform(this, p_id, p_transform);
+}
+
+void EditorNode3DGizmo::commit_subgizmos(const Vector<int> &p_ids, const Vector<Transform3D> &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 EditorNode3DGizmo::set_spatial_node(Node3D *p_node) {
@@ -180,17 +246,17 @@ void EditorNode3DGizmo::Instance::create_instance(Node3D *p_base, bool p_hidden)
RS::get_singleton()->instance_geometry_set_flag(instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
}
-void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const Ref<SkinReference> &p_skin_reference, const Ref<Material> &p_material) {
+void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, const Ref<Material> &p_material, const Transform3D &p_xform, const Ref<SkinReference> &p_skin_reference) {
ERR_FAIL_COND(!spatial_node);
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);
- RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
+ RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform() * ins.xform);
if (ins.material.is_valid()) {
RS::get_singleton()->instance_geometry_set_material_override(ins.instance, p_material->get_rid());
}
@@ -245,7 +311,6 @@ void EditorNode3DGizmo::add_vertices(const Vector<Vector3> &p_vertices, const Re
}
}
- ins.billboard = p_billboard;
ins.mesh = mesh;
if (valid) {
ins.create_instance(spatial_node, hidden);
@@ -307,8 +372,6 @@ void EditorNode3DGizmo::add_unscaled_billboard(const Ref<Material> &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);
RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
@@ -331,7 +394,7 @@ void EditorNode3DGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
}
}
-void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard, bool p_secondary) {
+void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, const Vector<int> &p_ids, bool p_billboard, bool p_secondary) {
billboard_handle = p_billboard;
if (!is_selected() || !is_editable()) {
@@ -340,8 +403,16 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
ERR_FAIL_COND(!spatial_node);
- Instance ins;
+ if (p_ids.is_empty()) {
+ ERR_FAIL_COND_MSG((!handles.is_empty() && !handle_ids.is_empty()) || (!secondary_handles.is_empty() && !secondary_handle_ids.is_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 = Node3DEditor::get_singleton()->get_current_hover_gizmo() == this;
+ int current_hover_handle = Node3DEditor::get_singleton()->get_current_hover_gizmo_handle();
+
+ Instance ins;
Ref<ArrayMesh> mesh = memnew(ArrayMesh);
Array a;
@@ -357,7 +428,8 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
col = Color(0, 0, 1, 0.9);
}
- if (Node3DEditor::get_singleton()->get_over_gizmo_handle() != i) {
+ int id = p_ids.is_empty() ? i : p_ids[i];
+ if (!is_current_hover_gizmo || current_hover_handle != id) {
col.a = 0.8;
}
@@ -379,29 +451,31 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
}
ins.mesh = mesh;
- ins.billboard = p_billboard;
ins.extra_margin = true;
if (valid) {
ins.create_instance(spatial_node, hidden);
RS::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<Vector3> &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.is_empty()) {
+ Vector<int> &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 EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position) {
+void EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position, const Transform3D &p_xform) {
ERR_FAIL_COND(!spatial_node);
BoxMesh box_mesh;
@@ -419,8 +493,7 @@ void EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size,
Ref<ArrayMesh> m = memnew(ArrayMesh);
m->add_surface_from_arrays(box_mesh.surface_get_primitive_type(0), arrays);
- m->surface_set_material(0, p_material);
- add_mesh(m);
+ add_mesh(m, p_material, p_xform);
}
bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) {
@@ -485,13 +558,15 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
Transform3D it = t.affine_inverse();
Vector<Plane> 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<Vector3> convex_points = Geometry3D::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<Vector3> convex_points = Geometry3D::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;
}
}
@@ -499,64 +574,71 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
return false;
}
-bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) {
- ERR_FAIL_COND_V(!spatial_node, false);
- ERR_FAIL_COND_V(!valid, false);
+void EditorNode3DGizmo::handles_intersect_ray(Camera3D *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id) {
+ r_id = -1;
- if (hidden && !gizmo_plugin->is_selectable_when_hidden()) {
- return false;
+ ERR_FAIL_COND(!spatial_node);
+ ERR_FAIL_COND(!valid);
+
+ if (hidden) {
+ return;
}
- if (r_gizmo_handle && !hidden) {
- Transform3D 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));
- }
+ Transform3D camera_xform = p_camera->get_global_transform();
+ Transform3D 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;
- int idx = -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);
+ 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.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.is_empty()) {
+ r_id = i;
+ } else {
+ r_id = secondary_handle_ids[i];
}
}
}
+ }
- if (p_sec_first && idx != -1) {
- *r_gizmo_handle = idx;
- return true;
- }
+ if (r_id != -1 && p_shift_pressed) {
+ return;
+ }
- min_d = 1e20;
+ min_d = 1e20;
- for (int i = 0; i < handles.size(); i++) {
- Vector3 hpos = t.xform(handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
+ 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 (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.is_empty()) {
+ r_id = i;
+ } else {
+ r_id = handle_ids[i];
}
}
}
+ }
+}
- if (idx >= 0) {
- *r_gizmo_handle = idx;
- return true;
- }
+bool EditorNode3DGizmo::intersect_ray(Camera3D *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);
+
+ if (hidden && !gizmo_plugin->is_selectable_when_hidden()) {
+ return false;
}
if (selectable_icon_size > 0.0f) {
@@ -674,6 +756,25 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
return false;
}
+bool EditorNode3DGizmo::is_subgizmo_selected(int p_id) const {
+ Node3DEditor *ed = Node3DEditor::get_singleton();
+ ERR_FAIL_COND_V(!ed, false);
+ return ed->is_current_selected_gizmo(this) && ed->is_subgizmo_selected(p_id);
+}
+
+Vector<int> EditorNode3DGizmo::get_subgizmo_selection() const {
+ Vector<int> ret;
+
+ Node3DEditor *ed = Node3DEditor::get_singleton();
+ ERR_FAIL_COND_V(!ed, ret);
+
+ if (ed->is_current_selected_gizmo(this)) {
+ ret = ed->get_subgizmo_selection();
+ }
+
+ return ret;
+}
+
void EditorNode3DGizmo::create() {
ERR_FAIL_COND(!spatial_node);
ERR_FAIL_COND(valid);
@@ -690,7 +791,7 @@ void EditorNode3DGizmo::transform() {
ERR_FAIL_COND(!spatial_node);
ERR_FAIL_COND(!valid);
for (int i = 0; i < instances.size(); i++) {
- RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform());
+ RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform() * instances[i].xform);
}
}
@@ -724,38 +825,46 @@ void EditorNode3DGizmo::set_plugin(EditorNode3DGizmoPlugin *p_plugin) {
void EditorNode3DGizmo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard", "modulate"), &EditorNode3DGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorNode3DGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref<SkinReference>()), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "material", "transform", "skeleton"), &EditorNode3DGizmo::add_mesh, DEFVAL(Variant()), DEFVAL(Transform3D()), DEFVAL(Ref<SkinReference>()));
ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorNode3DGizmo::add_collision_segments);
ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorNode3DGizmo::add_collision_triangles);
ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale", "modulate"), &EditorNode3DGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorNode3DGizmo::add_handles, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "ids", "billboard", "secondary"), &EditorNode3DGizmo::add_handles, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorNode3DGizmo::_set_spatial_node);
ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorNode3DGizmo::get_spatial_node);
ClassDB::bind_method(D_METHOD("get_plugin"), &EditorNode3DGizmo::get_plugin);
ClassDB::bind_method(D_METHOD("clear"), &EditorNode3DGizmo::clear);
ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorNode3DGizmo::set_hidden);
+ ClassDB::bind_method(D_METHOD("is_subgizmo_selected"), &EditorNode3DGizmo::is_subgizmo_selected);
+ ClassDB::bind_method(D_METHOD("get_subgizmo_selection"), &EditorNode3DGizmo::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, "Camera3D"), 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, "Camera3D"), 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, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum")));
+ BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform")));
+ MethodInfo cs = MethodInfo("_commit_subgizmos", PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ cs.default_arguments.push_back(false);
+ BIND_VMETHOD(cs);
}
EditorNode3DGizmo::EditorNode3DGizmo() {
valid = false;
billboard_handle = false;
hidden = false;
- base = nullptr;
selected = false;
- instantiated = false;
spatial_node = nullptr;
gizmo_plugin = nullptr;
selectable_icon_size = -1.0f;
@@ -768,10 +877,362 @@ EditorNode3DGizmo::~EditorNode3DGizmo() {
clear();
}
-Vector3 EditorNode3DGizmo::get_handle_pos(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, handles.size(), Vector3());
+/////
+
+void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) {
+ Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+
+ Vector<Ref<StandardMaterial3D>> mats;
+
+ for (int i = 0; i < 4; i++) {
+ bool selected = i % 2 == 1;
+ bool instantiated = i < 2;
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+
+ Color color = instantiated ? instantiated_color : p_color;
+
+ if (!selected) {
+ color.a *= 0.3;
+ }
+
+ material->set_albedo(color);
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
+ material->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
+
+ if (p_use_vertex_color) {
+ material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ }
+
+ if (p_billboard) {
+ material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ }
+
+ if (p_on_top && selected) {
+ material->set_on_top_of_alpha();
+ }
+
+ mats.push_back(material);
+ }
+
+ materials[p_name] = mats;
+}
+
+void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top, const Color &p_albedo) {
+ Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+
+ Vector<Ref<StandardMaterial3D>> icons;
+
+ for (int i = 0; i < 4; i++) {
+ bool selected = i % 2 == 1;
+ bool instantiated = i < 2;
+
+ Ref<StandardMaterial3D> icon = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+
+ Color color = instantiated ? instantiated_color : p_albedo;
+
+ if (!selected) {
+ color.a *= 0.85;
+ }
+
+ icon->set_albedo(color);
+
+ icon->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ icon->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ icon->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ icon->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
+ icon->set_depth_draw_mode(StandardMaterial3D::DEPTH_DRAW_DISABLED);
+ icon->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ icon->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, p_texture);
+ icon->set_flag(StandardMaterial3D::FLAG_FIXED_SIZE, true);
+ icon->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ icon->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN);
+
+ if (p_on_top && selected) {
+ icon->set_on_top_of_alpha();
+ }
+
+ icons.push_back(icon);
+ }
+
+ materials[p_name] = icons;
+}
+
+void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref<Texture2D> &p_icon) {
+ Ref<StandardMaterial3D> handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+
+ handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
+ Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
+ handle_material->set_point_size(handle_t->get_width());
+ handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
+ handle_material->set_albedo(Color(1, 1, 1));
+ handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ handle_material->set_on_top_of_alpha();
+ if (p_billboard) {
+ handle_material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ handle_material->set_on_top_of_alpha();
+ }
+ handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+
+ materials[p_name] = Vector<Ref<StandardMaterial3D>>();
+ materials[p_name].push_back(handle_material);
+}
+
+void EditorNode3DGizmoPlugin::add_material(const String &p_name, Ref<StandardMaterial3D> p_material) {
+ materials[p_name] = Vector<Ref<StandardMaterial3D>>();
+ materials[p_name].push_back(p_material);
+}
+
+Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo) {
+ ERR_FAIL_COND_V(!materials.has(p_name), Ref<StandardMaterial3D>());
+ ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref<StandardMaterial3D>());
+
+ 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<StandardMaterial3D> mat = materials[p_name][index];
+
+ if (current_state == ON_TOP && p_gizmo->is_selected()) {
+ mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ } else {
+ mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, false);
+ }
+
+ return mat;
+}
+
+String EditorNode3DGizmoPlugin::get_gizmo_name() const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
+ return get_script_instance()->call("_get_gizmo_name");
+ }
+ return TTR("Nameless gizmo");
+}
+
+int EditorNode3DGizmoPlugin::get_priority() const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
+ return get_script_instance()->call("_get_priority");
+ }
+ return 0;
+}
+
+Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
+ if (get_script_instance() && get_script_instance()->has_method("_get_gizmo")) {
+ return get_script_instance()->call("_get_gizmo", p_spatial);
+ }
+
+ Ref<EditorNode3DGizmo> 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);
- return handles[p_idx];
+ current_gizmos.push_back(ref.ptr());
+ return ref;
+}
+
+void EditorNode3DGizmoPlugin::_bind_methods() {
+#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
+
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+ BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+
+ ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material);
+
+ ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
+
+ 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, "id"));
+ 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, "Camera3D"), 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, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum")));
+ BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform")));
+ MethodInfo cs = MethodInfo("_commit_subgizmos", GIZMO_REF, PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ cs.default_arguments.push_back(false);
+ BIND_VMETHOD(cs);
+
+#undef GIZMO_REF
+}
+
+bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *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<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
+ if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) {
+ return get_script_instance()->call("_create_gizmo", p_spatial);
+ }
+
+ Ref<EditorNode3DGizmo> ref;
+ if (has_gizmo(p_spatial)) {
+ ref.instantiate();
+ }
+ return ref;
+}
+
+bool EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
+ Ref<EditorNode3DGizmo> ref(p_gizmo);
+ get_script_instance()->call("_redraw", ref);
+ }
+}
+
+bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
+ 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 EditorNode3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
+ 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 EditorNode3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *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<int> EditorNode3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &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<int>();
+}
+
+Transform3D EditorNode3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *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 Transform3D();
+}
+
+void EditorNode3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D 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 EditorNode3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &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 EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::get_state() const {
+ return current_state;
+}
+
+void EditorNode3DGizmoPlugin::unregister_gizmo(EditorNode3DGizmo *p_gizmo) {
+ current_gizmos.erase(p_gizmo);
+}
+
+EditorNode3DGizmoPlugin::EditorNode3DGizmoPlugin() {
+ current_state = VISIBLE;
+}
+
+EditorNode3DGizmoPlugin::~EditorNode3DGizmoPlugin() {
+ 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 (Node3DEditor::get_singleton()) {
+ Node3DEditor::get_singleton()->update_all_gizmos();
+ }
}
//// light gizmo
@@ -802,20 +1263,20 @@ int Light3DGizmoPlugin::get_priority() const {
return -1;
}
-String Light3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (p_idx == 0) {
+String Light3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (p_id == 0) {
return "Radius";
} else {
return "Aperture";
}
}
-Variant Light3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant Light3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
- if (p_idx == 0) {
+ if (p_id == 0) {
return light->get_param(Light3D::PARAM_RANGE);
}
- if (p_idx == 1) {
+ if (p_id == 1) {
return light->get_param(Light3D::PARAM_SPOT_ANGLE);
}
@@ -849,7 +1310,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec
return Math::rad2deg(a);
}
-void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Light3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
Transform3D gt = light->get_global_transform();
Transform3D gi = gt.affine_inverse();
@@ -858,7 +1319,7 @@ void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
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<SpotLight3D>(light)) {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
@@ -887,24 +1348,24 @@ void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
}
}
- } 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(Light3D::PARAM_RANGE), gt);
light->set_param(Light3D::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99));
}
}
-void Light3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void Light3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
- light->set_param(p_idx == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore);
+ light->set_param(p_id == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore);
- } else if (p_idx == 0) {
+ } else if (p_id == 0) {
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_RANGE, light->get_param(Light3D::PARAM_RANGE));
ur->add_undo_method(light, "set_param", Light3D::PARAM_RANGE, p_restore);
ur->commit_action();
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, light->get_param(Light3D::PARAM_SPOT_ANGLE));
@@ -996,7 +1457,7 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector<Vector3> 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<int>(), true);
}
if (Object::cast_to<SpotLight3D>(light)) {
@@ -1068,16 +1529,16 @@ int AudioStreamPlayer3DGizmoPlugin::get_priority() const {
return -1;
}
-String AudioStreamPlayer3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String AudioStreamPlayer3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "Emission Radius";
}
-Variant AudioStreamPlayer3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant AudioStreamPlayer3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
return player->get_emission_angle();
}
-void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void AudioStreamPlayer3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
Transform3D gt = player->get_global_transform();
@@ -1114,7 +1575,7 @@ void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int
}
}
-void AudioStreamPlayer3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void AudioStreamPlayer3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -1203,7 +1664,7 @@ int Camera3DGizmoPlugin::get_priority() const {
return -1;
}
-String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1213,7 +1674,7 @@ String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, in
}
}
-Variant Camera3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant Camera3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1223,7 +1684,7 @@ Variant Camera3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_
}
}
-void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Camera3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
Transform3D gt = camera->get_global_transform();
@@ -1252,7 +1713,7 @@ void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Came
}
}
-void Camera3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void Camera3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1761,7 +2222,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
Ref<ArrayMesh> m = surface_tool->commit();
- p_gizmo->add_mesh(m, false, skel->register_skin(Ref<Skin>()));
+ p_gizmo->add_mesh(m, Ref<Material>(), Transform3D(), skel->register_skin(Ref<Skin>()));
}
////
@@ -2102,23 +2563,23 @@ void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->add_collision_triangles(tm);
}
-String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "SoftBody3D pin point";
}
-Variant SoftBody3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant SoftBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- return Variant(soft_body->is_point_pinned(p_idx));
+ return Variant(soft_body->is_point_pinned(p_id));
}
-void SoftBody3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void SoftBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- soft_body->pin_point_toggle(p_idx);
+ soft_body->pin_point_toggle(p_id);
}
-bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const {
+bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- return soft_body->is_point_pinned(idx);
+ return soft_body->is_point_pinned(p_id);
}
///////////
@@ -2143,8 +2604,8 @@ int VisibleOnScreenNotifier3DGizmoPlugin::get_priority() const {
return -1;
}
-String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Size X";
case 1:
@@ -2162,20 +2623,20 @@ String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DG
return "";
}
-Variant VisibleOnScreenNotifier3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant VisibleOnScreenNotifier3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
return notifier->get_aabb();
}
-void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
Transform3D gt = notifier->get_global_transform();
Transform3D 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);
@@ -2186,25 +2647,25 @@ void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2213,13 +2674,13 @@ void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo
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 VisibleOnScreenNotifier3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void VisibleOnScreenNotifier3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -2335,8 +2796,8 @@ bool GPUParticles3DGizmoPlugin::is_selectable_when_hidden() const {
return true;
}
-String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Size X";
case 1:
@@ -2354,19 +2815,19 @@ String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_giz
return "";
}
-Variant GPUParticles3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant GPUParticles3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
return particles->get_visibility_aabb();
}
-void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void GPUParticles3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
Transform3D gt = particles->get_global_transform();
Transform3D 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 = particles->get_visibility_aabb();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
@@ -2377,25 +2838,25 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::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;
particles->set_visibility_aabb(aabb);
} else {
Vector3 ra, rb;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2404,13 +2865,13 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
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;
particles->set_visibility_aabb(aabb);
}
}
-void GPUParticles3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void GPUParticles3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -2475,8 +2936,6 @@ void GPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
-////
-
GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_collision", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
@@ -2498,7 +2957,7 @@ int GPUParticlesCollision3DGizmoPlugin::get_priority() const {
return -1;
}
-String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const Node3D *cs = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(cs) || Object::cast_to<GPUParticlesAttractorSphere>(cs)) {
@@ -2512,7 +2971,7 @@ String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGiz
return "";
}
-Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const Node3D *cs = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(cs) || Object::cast_to<GPUParticlesAttractorSphere>(cs)) {
@@ -2526,7 +2985,7 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *
return Variant();
}
-void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Node3D *sn = p_gizmo->get_spatial_node();
Transform3D gt = sn->get_global_transform();
@@ -2554,10 +3013,10 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo,
if (Object::cast_to<GPUParticlesCollisionBox>(sn) || Object::cast_to<GPUParticlesAttractorBox>(sn) || Object::cast_to<GPUParticlesAttractorVectorField>(sn) || Object::cast_to<GPUParticlesCollisionSDF>(sn) || Object::cast_to<GPUParticlesCollisionHeightField>(sn)) {
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2567,12 +3026,12 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo,
}
Vector3 he = sn->call("get_extents");
- he[p_idx] = d;
+ he[p_id] = d;
sn->call("set_extents", he);
}
}
-void GPUParticlesCollision3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Node3D *sn = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(sn) || Object::cast_to<GPUParticlesAttractorSphere>(sn)) {
@@ -2762,8 +3221,8 @@ int ReflectionProbeGizmoPlugin::get_priority() const {
return -1;
}
-String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -2781,18 +3240,18 @@ String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gi
return "";
}
-Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant ReflectionProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
return AABB(probe->get_extents(), probe->get_origin_offset());
}
-void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
Transform3D gt = probe->get_global_transform();
Transform3D 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);
@@ -2801,11 +3260,11 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2814,13 +3273,13 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
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);
@@ -2828,22 +3287,22 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
- origin[p_idx] = d;
+ origin[p_id] = d;
probe->set_origin_offset(origin);
}
}
-void ReflectionProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
AABB restore = p_restore;
@@ -2947,8 +3406,8 @@ int DecalGizmoPlugin::get_priority() const {
return -1;
}
-String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -2960,12 +3419,12 @@ String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p
return "";
}
-Variant DecalGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
return decal->get_extents();
}
-void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
Transform3D gt = decal->get_global_transform();
@@ -2979,11 +3438,11 @@ void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2992,11 +3451,11 @@ void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3
d = 0.001;
}
- extents[p_idx] = d;
+ extents[p_id] = d;
decal->set_extents(extents);
}
-void DecalGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
Vector3 restore = p_restore;
@@ -3055,7 +3514,6 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<Material> material = get_material("decal_material", p_gizmo);
p_gizmo->add_lines(lines, material);
-
p_gizmo->add_handles(handles, get_material("handles"));
}
@@ -3088,8 +3546,8 @@ int VoxelGIGizmoPlugin::get_priority() const {
return -1;
}
-String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -3101,12 +3559,12 @@ String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int
return "";
}
-Variant VoxelGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
return probe->get_extents();
}
-void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
Transform3D gt = probe->get_global_transform();
@@ -3120,11 +3578,11 @@ void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
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;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -3133,11 +3591,11 @@ void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
d = 0.001;
}
- extents[p_idx] = d;
+ extents[p_id] = d;
probe->set_extents(extents);
}
-void VoxelGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
Vector3 restore = p_restore;
@@ -3257,18 +3715,18 @@ LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoLightmapGI"), SNAME("EditorIcons")));
}
-String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "";
}
-Variant LightmapGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant LightmapGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return Variant();
}
-void LightmapGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void LightmapGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
}
-void LightmapGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void LightmapGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
}
bool LightmapGIGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -3439,18 +3897,18 @@ LightmapProbeGizmoPlugin::LightmapProbeGizmoPlugin() {
create_material("lightprobe_lines", gizmo_color);
}
-String LightmapProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String LightmapProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "";
}
-Variant LightmapProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant LightmapProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return Variant();
}
-void LightmapProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void LightmapProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
}
-void LightmapProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void LightmapProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
}
bool LightmapProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -3570,7 +4028,7 @@ void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
SurfaceTool st;
st.append_from(s->get_debug_mesh(), 0, xform);
- p_gizmo->add_mesh(st.commit(), false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(st.commit(), material);
p_gizmo->add_collision_segments(s->get_debug_mesh_lines());
}
}
@@ -3600,7 +4058,7 @@ int CollisionShape3DGizmoPlugin::get_priority() const {
return -1;
}
-String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3617,11 +4075,11 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
}
if (Object::cast_to<CapsuleShape3D>(*s)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<CylinderShape3D>(*s)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<RayShape3D>(*s)) {
@@ -3631,7 +4089,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
return "";
}
-Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3651,12 +4109,12 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> 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<CylinderShape3D>(*s)) {
Ref<CylinderShape3D> 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<RayShape3D>(*s)) {
@@ -3667,7 +4125,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo
return Variant();
}
-void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3717,11 +4175,11 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
if (Object::cast_to<BoxShape3D>(*s)) {
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Ref<BoxShape3D> bs = s;
Vector3 ra, rb;
Geometry3D::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 (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -3731,18 +4189,18 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
}
Vector3 he = bs->get_size();
- he[p_idx] = d * 2;
+ he[p_id] = d * 2;
bs->set_size(he);
}
if (Object::cast_to<CapsuleShape3D>(*s)) {
Vector3 axis;
- axis[p_idx == 0 ? 0 : 2] = 1.0;
+ axis[p_id == 0 ? 0 : 2] = 1.0;
Ref<CapsuleShape3D> cs2 = s;
Vector3 ra, rb;
Geometry3D::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();
}
@@ -3754,16 +4212,16 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_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<CylinderShape3D>(*s)) {
Vector3 axis;
- axis[p_idx == 0 ? 0 : 1] = 1.0;
+ axis[p_id == 0 ? 0 : 1] = 1.0;
Ref<CylinderShape3D> cs2 = s;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
@@ -3776,15 +4234,15 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_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 CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3823,7 +4281,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> ss = s;
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
ss->set_radius(p_restore);
} else {
ss->set_height(p_restore);
@@ -3832,7 +4290,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
}
UndoRedo *ur = Node3DEditor::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);
@@ -3848,7 +4306,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CylinderShape3D>(*s)) {
Ref<CylinderShape3D> ss = s;
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
ss->set_radius(p_restore);
} else {
ss->set_height(p_restore);
@@ -3857,7 +4315,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
}
UndoRedo *ur = Node3DEditor::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);
@@ -4153,7 +4611,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
if (Object::cast_to<ConcavePolygonShape3D>(*s)) {
Ref<ConcavePolygonShape3D> cs2 = s;
Ref<ArrayMesh> mesh = cs2->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(mesh, material);
p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines());
}
@@ -4174,7 +4632,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<HeightMapShape3D> hms = s;
Ref<ArrayMesh> mesh = hms->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(mesh, material);
}
}
diff --git a/editor/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 6f071859ec..61ee3a95a9 100644
--- a/editor/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -28,13 +28,156 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPATIAL_EDITOR_GIZMOS_H
-#define SPATIAL_EDITOR_GIZMOS_H
+#ifndef NODE_3D_EDITOR_GIZMOS_H
+#define NODE_3D_EDITOR_GIZMOS_H
-#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/camera_3d.h"
+#include "core/templates/ordered_hash_map.h"
+#include "scene/3d/node_3d.h"
+#include "scene/3d/skeleton_3d.h"
class Camera3D;
+class Timer;
+class EditorNode3DGizmoPlugin;
+
+class EditorNode3DGizmo : public Node3DGizmo {
+ GDCLASS(EditorNode3DGizmo, Node3DGizmo);
+
+ struct Instance {
+ RID instance;
+ Ref<ArrayMesh> mesh;
+ Ref<Material> material;
+ Ref<SkinReference> skin_reference;
+ bool extra_margin = false;
+ Transform3D xform;
+
+ void create_instance(Node3D *p_base, bool p_hidden = false);
+ };
+
+ bool selected;
+
+ Vector<Vector3> collision_segments;
+ Ref<TriangleMesh> collision_mesh;
+
+ Vector<Vector3> handles;
+ Vector<int> handle_ids;
+ Vector<Vector3> secondary_handles;
+ Vector<int> secondary_handle_ids;
+
+ float selectable_icon_size;
+ bool billboard_handle;
+
+ bool valid;
+ bool hidden;
+ Vector<Instance> instances;
+ Node3D *spatial_node;
+
+ void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }
+
+protected:
+ static void _bind_methods();
+
+ EditorNode3DGizmoPlugin *gizmo_plugin;
+
+public:
+ void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
+ void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
+ void add_mesh(const Ref<ArrayMesh> &p_mesh, const Ref<Material> &p_material = Ref<Material>(), const Transform3D &p_xform = Transform3D(), const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>());
+ void add_collision_segments(const Vector<Vector3> &p_lines);
+ void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
+ void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
+ void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, const Vector<int> &p_ids = Vector<int>(), bool p_billboard = false, bool p_secondary = false);
+ void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3(), const Transform3D &p_xform = Transform3D());
+
+ 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) const;
+ virtual void set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const;
+ virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false) const;
+
+ virtual int subgizmos_intersect_ray(Camera3D *p_camera, const Vector2 &p_point) const;
+ virtual Vector<int> subgizmos_intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) const;
+ virtual Transform3D get_subgizmo_transform(int p_id) const;
+ virtual void set_subgizmo_transform(int p_id, Transform3D p_transform) const;
+ virtual void commit_subgizmos(const Vector<int> &p_ids, const Vector<Transform3D> &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(Node3D *p_node);
+ Node3D *get_spatial_node() const { return spatial_node; }
+ Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
+ bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
+ void handles_intersect_ray(Camera3D *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id);
+ bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal);
+ bool is_subgizmo_selected(int p_id) const;
+ Vector<int> get_subgizmo_selection() const;
+
+ virtual void clear() override;
+ virtual void create() override;
+ virtual void transform() override;
+ virtual void redraw() override;
+ virtual void free() override;
+
+ virtual bool is_editable() const;
+
+ void set_hidden(bool p_hidden);
+ void set_plugin(EditorNode3DGizmoPlugin *p_plugin);
+
+ EditorNode3DGizmo();
+ ~EditorNode3DGizmo();
+};
+
+class EditorNode3DGizmoPlugin : public Resource {
+ GDCLASS(EditorNode3DGizmoPlugin, Resource);
+
+public:
+ static const int VISIBLE = 0;
+ static const int HIDDEN = 1;
+ static const int ON_TOP = 2;
+
+protected:
+ int current_state;
+ List<EditorNode3DGizmo *> current_gizmos;
+ HashMap<String, Vector<Ref<StandardMaterial3D>>> materials;
+
+ static void _bind_methods();
+ virtual bool has_gizmo(Node3D *p_spatial);
+ virtual Ref<EditorNode3DGizmo> create_gizmo(Node3D *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<Texture2D> &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<Texture2D> &p_texture = nullptr);
+ void add_material(const String &p_name, Ref<StandardMaterial3D> p_material);
+
+ Ref<StandardMaterial3D> get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo = Ref<EditorNode3DGizmo>());
+
+ 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(EditorNode3DGizmo *p_gizmo);
+ virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const;
+ virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const;
+
+ virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const;
+ virtual Vector<int> subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const;
+ virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) const;
+ virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) const;
+
+ Ref<EditorNode3DGizmo> get_gizmo(Node3D *p_spatial);
+ void set_state(int p_state);
+ int get_state() const;
+ void unregister_gizmo(EditorNode3DGizmo *p_gizmo);
+
+ EditorNode3DGizmoPlugin();
+ virtual ~EditorNode3DGizmoPlugin();
+};
class Light3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Light3DGizmoPlugin, EditorNode3DGizmoPlugin);
@@ -44,10 +187,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
Light3DGizmoPlugin();
@@ -61,10 +204,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
AudioStreamPlayer3DGizmoPlugin();
@@ -78,10 +221,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
Camera3DGizmoPlugin();
@@ -210,10 +353,10 @@ public:
bool is_selectable_when_hidden() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) override;
- bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
+ bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
SoftBody3DGizmoPlugin();
};
@@ -227,10 +370,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
VisibleOnScreenNotifier3DGizmoPlugin();
};
@@ -257,10 +400,10 @@ public:
bool is_selectable_when_hidden() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
GPUParticles3DGizmoPlugin();
};
@@ -274,10 +417,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
GPUParticlesCollision3DGizmoPlugin();
};
@@ -291,10 +434,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
ReflectionProbeGizmoPlugin();
};
@@ -308,10 +451,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
DecalGizmoPlugin();
};
@@ -325,10 +468,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
VoxelGIGizmoPlugin();
};
@@ -342,10 +485,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
LightmapGIGizmoPlugin();
};
@@ -359,10 +502,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
LightmapProbeGizmoPlugin();
};
@@ -388,10 +531,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
CollisionShape3DGizmoPlugin();
};
@@ -489,4 +632,4 @@ public:
Joint3DGizmoPlugin();
};
-#endif // SPATIAL_EDITOR_GIZMOS_H
+#endif // NODE_3D_EDITOR_GIZMOS_H
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 7290a39463..ebf593e556 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -35,20 +35,20 @@
#include "core/math/camera_matrix.h"
#include "core/math/math_funcs.h"
#include "core/os/keyboard.h"
-#include "core/string/print_string.h"
#include "core/templates/sort_array.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
-#include "editor/node_3d_editor_gizmos.h"
#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
#include "editor/plugins/script_editor_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/3d/world_environment.h"
#include "scene/gui/center_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
@@ -58,7 +58,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
@@ -436,16 +435,29 @@ Vector3 Node3DEditorViewport::_get_ray(const Vector2 &p_pos) const {
}
void Node3DEditorViewport::_clear_selected() {
- editor_selection->clear();
-}
-
-void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) {
- if (clicked.is_null()) {
- return;
+ _edit.gizmo = Ref<EditorNode3DGizmo>();
+ _edit.gizmo_handle = -1;
+ _edit.gizmo_initial_value = Variant();
+
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(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();
+ Node3DEditor::get_singleton()->edit(nullptr);
}
+}
- Node *node = Object::cast_to<Node>(ObjectDB::get_instance(clicked));
+void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
+ Node *node = Object::cast_to<Node3D>(ObjectDB::get_instance(clicked));
Node3D *selected = Object::cast_to<Node3D>(node);
+ clicked = ObjectID();
+
if (!selected) {
return;
}
@@ -462,43 +474,27 @@ void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_
}
if (p_allow_locked || !_is_node_locked(selected)) {
- _select(selected, clicked_wants_append, true);
- }
-}
-
-void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) {
- // Add or remove a single node from the selection
- if (p_append && p_single) {
- if (editor_selection->is_selected(p_node)) {
- // Already in the selection, remove it from the selected nodes
- editor_selection->remove_node(p_node);
+ if (clicked_wants_append) {
+ if (editor_selection->is_selected(selected)) {
+ editor_selection->remove_node(selected);
+ } else {
+ editor_selection->add_node(selected);
+ }
} else {
- // Add the item to the selection
- editor_selection->add_node(p_node);
- }
- } else if (p_append && !p_single) {
- // Add the item to the selection
- editor_selection->add_node(p_node);
- } else {
- // No append; single select
- editor_selection->clear();
- editor_selection->add_node(p_node);
- // Reselect
- if (Engine::get_singleton()->is_editor_hint()) {
- editor->call("edit_node", p_node);
+ if (!editor_selection->is_selected(selected)) {
+ editor_selection->clear();
+ editor_selection->add_node(selected);
+ editor->edit_node(selected);
+ }
}
- }
- if (editor_selection->get_selected_node_list().size() == 1) {
- editor->push_item(editor_selection->get_selected_node_list()[0]);
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->edit_node(editor_selection->get_selected_node_list()[0]);
+ }
}
}
-ObjectID Node3DEditorViewport::_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 Node3DEditorViewport::_select_ray(const Point2 &p_pos) {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
@@ -514,7 +510,6 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
ObjectID closest;
Node *item = nullptr;
float closest_dist = 1e20;
- int selected_handle = -1;
for (int i = 0; i < instances.size(); i++) {
Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
@@ -523,38 +518,40 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
continue;
}
- Ref<EditorNode3DGizmo> seg = spat->get_gizmo();
+ Vector<Ref<Node3DGizmo>> gizmos = spat->get_gizmos();
- if ((!seg.is_valid()) || found_gizmos.has(seg)) {
- continue;
- }
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
- found_gizmos.insert(seg);
- Vector3 point;
- Vector3 normal;
+ if ((!seg.is_valid()) || found_gizmos.has(seg)) {
+ continue;
+ }
- int handle = -1;
- bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal, &handle, p_alt_select);
+ found_gizmos.insert(seg);
+ Vector3 point;
+ Vector3 normal;
- if (!inters) {
- continue;
- }
+ bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal);
- float dist = pos.distance_to(point);
+ if (!inters) {
+ continue;
+ }
- if (dist < 0) {
- continue;
- }
+ float dist = pos.distance_to(point);
- if (dist < closest_dist) {
- item = Object::cast_to<Node>(spat);
- if (item != edited_scene) {
- item = edited_scene->get_deepest_editable_node(item);
+ if (dist < 0) {
+ continue;
}
- closest = item->get_instance_id();
- closest_dist = dist;
- selected_handle = handle;
+ if (dist < closest_dist) {
+ item = Object::cast_to<Node>(spat);
+ if (item != edited_scene) {
+ item = edited_scene->get_deepest_editable_node(item);
+ }
+
+ closest = item->get_instance_id();
+ closest_dist = dist;
+ }
}
}
@@ -562,23 +559,15 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
return ObjectID();
}
- if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle >= 0)) {
- if (r_gizmo_handle) {
- *r_gizmo_handle = selected_handle;
- }
- }
-
return closest;
}
-void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select, bool p_include_locked_nodes) {
+void Node3DEditorViewport::_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<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario());
- Set<Ref<EditorNode3DGizmo>> found_gizmos;
-
- r_includes_current = false;
+ Set<Node3D *> found_nodes;
for (int i = 0; i < instances.size(); i++) {
Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
@@ -587,53 +576,48 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_inclu
continue;
}
- Ref<EditorNode3DGizmo> 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<Ref<Node3DGizmo>> gizmos = spat->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> 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;
- float dist = pos.distance_to(point);
+ bool inters = seg->intersect_ray(camera, p_pos, point, normal);
- if (dist < 0) {
- continue;
- }
+ if (!inters) {
+ continue;
+ }
- if (!p_include_locked_nodes && _is_node_locked(spat)) {
- continue;
- }
+ float dist = pos.distance_to(point);
- if (editor_selection->is_selected(spat)) {
- r_includes_current = true;
- }
+ if (dist < 0) {
+ continue;
+ }
- _RayResult res;
- res.item = spat;
- res.depth = dist;
- res.handle = handle;
- results.push_back(res);
- }
+ found_nodes.insert(spat);
- if (results.is_empty()) {
- return;
+ _RayResult res;
+ res.item = spat;
+ res.depth = dist;
+ r_results.push_back(res);
+ break;
+ }
}
- results.sort();
+ r_results.sort();
}
Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
@@ -656,6 +640,9 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
void Node3DEditorViewport::_select_region() {
if (cursor.region_begin == cursor.region_end) {
+ if (!clicked_wants_append) {
+ _clear_selected();
+ }
return; //nothing really
}
@@ -702,7 +689,66 @@ void Node3DEditorViewport::_select_region() {
far.d += get_zfar();
frustum.push_back(far);
+ if (spatial_editor->get_single_selected_node()) {
+ Node3D *single_selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(single_selected);
+
+ Ref<EditorNode3DGizmo> old_gizmo;
+ if (!clicked_wants_append) {
+ se->subgizmos.clear();
+ old_gizmo = se->gizmo;
+ se->gizmo.unref();
+ }
+
+ bool found_subgizmos = false;
+ Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
+ if (!seg.is_valid()) {
+ continue;
+ }
+
+ if (se->gizmo.is_valid() && se->gizmo != seg) {
+ continue;
+ }
+
+ Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum);
+ if (!subgizmos.is_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<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world_3d()->get_scenario());
+ Set<Node3D *> found_nodes;
Vector<Node *> selected;
Node *edited_scene = get_tree()->get_edited_scene_root();
@@ -713,6 +759,12 @@ void Node3DEditorViewport::_select_region() {
continue;
}
+ if (found_nodes.has(sp)) {
+ continue;
+ }
+
+ found_nodes.insert(sp);
+
Node *item = Object::cast_to<Node>(sp);
if (item != edited_scene) {
item = edited_scene->get_deepest_editable_node(item);
@@ -731,28 +783,31 @@ void Node3DEditorViewport::_select_region() {
item = sel;
}
- if (selected.find(item) != -1) {
- continue;
- }
-
if (_is_node_locked(item)) {
continue;
}
- Ref<EditorNode3DGizmo> seg = sp->get_gizmo();
+ Vector<Ref<Node3DGizmo>> gizmos = sp->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> 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);
+ for (int i = 0; i < selected.size(); i++) {
+ if (!editor_selection->is_selected(selected[i])) {
+ editor_selection->add_node(selected[i]);
}
}
- bool single = selected.size() == 1;
- for (int i = 0; i < selected.size(); i++) {
- _select(selected[i], true, single);
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->edit_node(editor_selection->get_selected_node_list()[0]);
}
}
@@ -779,21 +834,34 @@ void Node3DEditorViewport::_compute_edit(const Point2 &p_point) {
spatial_editor->update_transform_gizmo();
_edit.center = spatial_editor->get_gizmo_transform().origin;
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
+ if (se && se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::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<Node *> &selection = editor_selection->get_selected_node_list();
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
- if (!se) {
- continue;
- }
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
+
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+
+ if (!sel_item) {
+ continue;
+ }
- se->original = se->sp->get_global_gizmo_transform();
- se->original_local = se->sp->get_local_gizmo_transform();
+ sel_item->original_local = sel_item->sp->get_local_gizmo_transform();
+ sel_item->original = sel_item->sp->get_global_gizmo_transform();
+ }
}
}
@@ -829,7 +897,7 @@ static int _get_key_modifier(Ref<InputEventWithModifiers> e) {
return 0;
}
-bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) {
+bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) {
if (!spatial_editor->is_gizmo_visible()) {
return false;
}
@@ -1015,6 +1083,88 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high
return false;
}
+void Node3DEditorViewport::_transform_gizmo_apply(Node3D *p_node, const Transform3D &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);
+ }
+}
+
+Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &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));
+ Transform3D local_t = p_original_local;
+ local_t.basis.set_euler_scale(p_original_local.basis.get_rotation_euler(), local_scale);
+ return local_t;
+ } else {
+ Transform3D base = Transform3D(Basis(), _edit.center);
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
+
+ Transform3D 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
+ Transform3D 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();
+ Transform3D t;
+ t.basis.set_euler_scale(euler, scale);
+ t.origin = p_original_local.origin;
+ return t;
+ } else {
+ Transform3D r;
+ r.basis.rotate(p_motion, p_extra);
+ Transform3D base = Transform3D(Basis(), _edit.center);
+ return base * r * base.inverse() * p_original;
+ }
+ }
+ default: {
+ ERR_FAIL_V_MSG(Transform3D(), "Invalid mode in '_compute_transform'");
+ }
+ }
+}
+
void Node3DEditorViewport::_surface_mouse_enter() {
if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
surface->grab_focus();
@@ -1038,7 +1188,7 @@ bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) {
}
void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
- _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed(), spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
+ _find_items_at_pos(b->get_position(), selection_results, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
Node *scene = editor->get_edited_scene();
@@ -1058,10 +1208,8 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
selection_results.clear();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
- clicked = ObjectID();
+ _select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
}
-
} else if (!selection_results.is_empty()) {
NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
@@ -1190,7 +1338,20 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- sp->set_global_transform(se->original);
+ if (se->gizmo.is_valid()) {
+ Vector<int> ids;
+ Vector<Transform3D> restore;
+
+ for (Map<int, Transform3D>::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);
@@ -1271,28 +1432,65 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
can_select_gizmos = view_menu->get_popup()->is_item_checked(idx);
}
- if (can_select_gizmos && spatial_editor->get_selected()) {
- Ref<EditorNode3DGizmo> 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->is_shift_pressed());
- if (inters && handle != -1) {
+ if (can_select_gizmos && spatial_editor->get_single_selected_node()) {
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(spatial_editor->get_single_selected_node());
+ Vector<Ref<Node3DGizmo>> gizmos = spatial_editor->get_single_selected_node()->get_gizmos();
+
+ bool intersected_handle = false;
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> 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->is_shift_pressed()) {
+ 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.is_empty()) {
+ se->gizmo = Ref<EditorNode3DGizmo>();
+ } 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->is_shift_pressed(), 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 = ObjectID();
- clicked_includes_current = false;
if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
/* HANDLE ROTATION */
@@ -1325,40 +1523,19 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
}
- // todo scale
-
- int gizmo_handle = -1;
-
- clicked = _select_ray(b->get_position(), b->is_shift_pressed(), clicked_includes_current, &gizmo_handle, b->is_shift_pressed());
+ clicked = _select_ray(b->get_position());
//clicking is always deferred to either move or release
clicked_wants_append = b->is_shift_pressed();
if (clicked.is_null()) {
- 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.is_valid() && gizmo_handle >= 0) {
- Node3D *spa = Object::cast_to<Node3D>(ObjectDB::get_instance(clicked));
- if (spa) {
- Ref<EditorNode3DGizmo> 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()) {
@@ -1366,47 +1543,57 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.gizmo = Ref<EditorNode3DGizmo>();
break;
}
+
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true);
- // Processing was deferred.
- clicked = ObjectID();
+ _select_clicked(false);
}
if (cursor.region_select) {
- if (!clicked_wants_append) {
- _clear_selected();
- }
-
_select_region();
cursor.region_select = false;
surface->update();
}
if (_edit.mode != TRANSFORM_NONE) {
- static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" };
- undo_redo->create_action(_transform_name[_edit.mode]);
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ if (se && se->gizmo.is_valid()) {
+ Vector<int> ids;
+ Vector<Transform3D> restore;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ ids.push_back(GE->key());
+ restore.push_back(GE->value());
}
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(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]);
+
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
+
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(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", se->original);
+ 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("");
}
-
surface->update();
}
@@ -1421,31 +1608,39 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (m.is_valid()) {
_edit.mouse_pos = m->get_position();
- if (spatial_editor->get_selected()) {
- Ref<EditorNode3DGizmo> seg = spatial_editor->get_selected()->get_gizmo();
- if (seg.is_valid()) {
- int selected_handle = -1;
-
- 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;
+ if (spatial_editor->get_single_selected_node()) {
+ Vector<Ref<Node3DGizmo>> gizmos = spatial_editor->get_single_selected_node()->get_gizmos();
+
+ Ref<EditorNode3DGizmo> found_gizmo;
+ int found_handle = -1;
+
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> 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();
@@ -1469,11 +1664,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} else {
const bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 8 * EDSCALE;
if (clicked.is_valid() && movement_threshold_passed) {
- if (!clicked_includes_current) {
- _select_clicked(clicked_wants_append, true);
- // Processing was deferred.
- }
-
_compute_edit(_edit.mouse_pos);
clicked = ObjectID();
@@ -1568,8 +1758,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
motion = Vector3(scale, scale, scale);
}
- List<Node *> &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);
@@ -1582,6 +1770,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &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<Node *> &selection = editor_selection->get_selected_node_list();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Node3D *sp = Object::cast_to<Node3D>(E->get());
if (!sp) {
@@ -1597,44 +1786,22 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D original = se->original;
- Transform3D original_local = se->original_local;
- Transform3D base = Transform3D(Basis(), _edit.center);
- Transform3D 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));
- }
-
- 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);
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D 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);
}
-
} else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- motion.snap(Vector3(snap, snap, snap));
- }
-
- Transform3D r;
- r.basis.scale(motion + Vector3(1, 1, 1));
- t = base * (r * (base.inverse() * original));
-
- // Apply scale
- sp->set_global_transform(t);
+ Transform3D 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;
@@ -1691,8 +1858,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
- List<Node *> &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);
@@ -1704,6 +1869,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &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<Node *> &selection = editor_selection->get_selected_node_list();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Node3D *sp = Object::cast_to<Node3D>(E->get());
if (!sp) {
@@ -1719,30 +1885,20 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D original = se->original;
- Transform3D 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<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D 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));
- }
+ Transform3D 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;
@@ -1796,10 +1952,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals)));
angle = Math::deg2rad(angle);
- List<Node *> &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<Node *> &selection = editor_selection->get_selected_node_list();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Node3D *sp = Object::cast_to<Node3D>(E->get());
if (!sp) {
@@ -1815,32 +1970,24 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D t;
-
- if (local_coords) {
- Transform3D 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<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D 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 {
- Transform3D original = se->original;
- Transform3D r;
- Transform3D base = Transform3D(Basis(), _edit.center);
-
- r.basis.rotate(plane.normal, angle);
- t = base * r * base.inverse() * original;
-
- // Apply rotation
- sp->set_global_transform(t);
+ Transform3D 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;
@@ -3310,8 +3457,7 @@ void Node3DEditorViewport::_selection_result_pressed(int p_result) {
clicked = selection_results[p_result].item->get_instance_id();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
- clicked = ObjectID();
+ _select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
}
}
@@ -3606,6 +3752,13 @@ void Node3DEditorViewport::focus_selection() {
continue;
}
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::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++;
}
@@ -3644,34 +3797,39 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const
continue;
}
- Ref<EditorNode3DGizmo> seg = mesh_instance->get_gizmo();
+ Vector<Ref<Node3DGizmo>> gizmos = mesh_instance->get_gizmos();
- if ((!seg.is_valid()) || found_gizmos.has(seg)) {
- continue;
- }
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
- found_gizmos.insert(seg);
+ if ((!seg.is_valid()) || found_gizmos.has(seg)) {
+ continue;
+ }
- Vector3 hit_point;
- Vector3 hit_normal;
- bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal, nullptr, false);
+ found_gizmos.insert(seg);
- if (!inters) {
- continue;
- }
+ Vector3 hit_point;
+ Vector3 hit_normal;
+ bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal);
- float dist = world_pos.distance_to(hit_point);
+ if (!inters) {
+ continue;
+ }
- if (dist < 0) {
- continue;
- }
+ float dist = world_pos.distance_to(hit_point);
- if (dist < closest_dist) {
- closest_dist = dist;
- point = hit_point;
- normal = hit_normal;
+ 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) {
@@ -3972,9 +4130,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
_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;
@@ -3982,7 +4139,6 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
editor_selection = editor->get_editor_selection();
undo_redo = editor->get_undo_redo();
- clicked_includes_current = false;
orthogonal = false;
auto_orthogonal = false;
lock_rotation = false;
@@ -4005,7 +4161,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
surface->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
surface->set_clip_contents(true);
camera = memnew(Camera3D);
- 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();
@@ -4574,43 +4730,54 @@ void Node3DEditor::select_gizmo_highlight_axis(int p_axis) {
}
void Node3DEditor::update_transform_gizmo() {
- List<Node *> &selection = editor_selection->get_selected_node_list();
- AABB center;
- bool first = true;
+ int count = 0;
+ bool local_gizmo_coords = are_local_coords_enabled();
+ Vector3 gizmo_center;
Basis gizmo_basis;
- bool local_gizmo_coords = are_local_coords_enabled();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
- }
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
- if (!se) {
- continue;
+ if (se && se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) {
+ Transform3D 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<Node *> &selection = editor_selection->get_selected_node_list();
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
- Transform3D xf = se->sp->get_global_gizmo_transform();
+ if (sp->has_meta("_edit_lock_")) {
+ continue;
+ }
+
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+ if (!sel_item) {
+ continue;
+ }
- if (first) {
- center.position = xf.origin;
- first = false;
- if (local_gizmo_coords) {
+ Transform3D xf = sel_item->sp->get_global_transform();
+ gizmo_center += xf.origin;
+ if (count == 0 && local_gizmo_coords) {
gizmo_basis = xf.basis;
gizmo_basis.orthonormalize();
}
- } else {
- center.expand_to(xf.origin);
- gizmo_basis = Basis();
+ count++;
}
}
- Vector3 pcenter = center.position + center.size * 0.5;
- gizmo.visible = !first;
- gizmo.transform.origin = pcenter;
- gizmo.transform.basis = gizmo_basis;
+ 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();
@@ -4621,7 +4788,7 @@ void _update_all_gizmos(Node *p_node) {
for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
Node3D *spatial_node = Object::cast_to<Node3D>(p_node->get_child(i));
if (spatial_node) {
- spatial_node->update_gizmo();
+ spatial_node->update_gizmos();
}
_update_all_gizmos(p_node->get_child(i));
@@ -4940,22 +5107,38 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
void Node3DEditor::edit(Node3D *p_spatial) {
if (p_spatial != selected) {
if (selected) {
- Ref<EditorNode3DGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
seg->set_selected(false);
- selected->update_gizmo();
}
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
+ }
+
+ selected->update_gizmos();
}
selected = p_spatial;
- over_gizmo_handle = -1;
+ current_hover_gizmo = Ref<EditorNode3DGizmo>();
+ current_hover_gizmo_handle = -1;
if (selected) {
- Ref<EditorNode3DGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
seg->set_selected(true);
- selected->update_gizmo();
}
+ selected->update_gizmos();
}
}
}
@@ -6027,13 +6210,27 @@ void Node3DEditor::update_grid() {
_init_grid();
}
-bool Node3DEditor::is_any_freelook_active() const {
- for (unsigned int i = 0; i < VIEWPORTS_COUNT; ++i) {
- if (viewports[i]->is_freelook_active()) {
- return true;
+void Node3DEditor::_selection_changed() {
+ _refresh_menu_icons();
+ if (selected && editor_selection->get_selected_node_list().size() != 1) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
+ seg->set_selected(false);
+ }
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
}
+ selected->update_gizmos();
+ selected = nullptr;
}
- return false;
+ update_transform_gizmo();
}
void Node3DEditor::_refresh_menu_icons() {
@@ -6325,7 +6522,7 @@ void Node3DEditor::_notification(int p_what) {
get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed));
get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added));
EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
- editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
+ editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed));
editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
@@ -6384,6 +6581,34 @@ void Node3DEditor::_notification(int p_what) {
}
}
+bool Node3DEditor::is_subgizmo_selected(int p_id) {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+ if (se) {
+ return se->subgizmos.has(p_id);
+ }
+ return false;
+}
+
+bool Node3DEditor::is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo) {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+ if (se) {
+ return se->gizmo == p_gizmo;
+ }
+ return false;
+}
+
+Vector<int> Node3DEditor::get_subgizmo_selection() {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+
+ Vector<int> ret;
+ if (se) {
+ for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) {
+ ret.push_back(E->key());
+ }
+ }
+ return ret;
+}
+
void Node3DEditor::add_control_to_menu_panel(Control *p_control) {
hbc_menu->add_child(p_control);
}
@@ -6411,23 +6636,43 @@ void Node3DEditor::_request_gizmo(Object *p_obj) {
if (!sp) {
return;
}
- if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_ancestor_of(sp)))) {
- Ref<EditorNode3DGizmo> seg;
+ bool is_selected = (sp == selected);
+
+ if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_ancestor_of(sp)))) {
for (int i = 0; i < gizmo_plugins_by_priority.size(); ++i) {
- seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp);
+ Ref<EditorNode3DGizmo> 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 Node3DEditor::_clear_subgizmo_selection(Object *p_obj) {
+ Node3D *sp = nullptr;
+ if (p_obj) {
+ sp = Object::cast_to<Node3D>(p_obj);
+ } else {
+ sp = selected;
+ }
+
+ if (!sp) {
+ return;
+ }
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+ if (se) {
+ se->subgizmos.clear();
+ se->gizmo.unref();
+ sp->update_gizmos();
+ update_transform_gizmo();
}
}
@@ -6516,7 +6761,13 @@ void Node3DEditor::_node_removed(Node *p_node) {
}
if (p_node == selected) {
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
+ }
selected = nullptr;
+ update_transform_gizmo();
}
}
@@ -6554,6 +6805,7 @@ void Node3DEditor::_bind_methods() {
ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input);
ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data);
ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo);
+ ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection);
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
ADD_SIGNAL(MethodInfo("transform_key_request"));
@@ -7130,7 +7382,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "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;
{
//sun popup
@@ -7444,303 +7696,3 @@ Node3DEditorPlugin::Node3DEditorPlugin(EditorNode *p_node) {
Node3DEditorPlugin::~Node3DEditorPlugin() {
}
-
-void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
-
- Vector<Ref<StandardMaterial3D>> mats;
-
- for (int i = 0; i < 4; i++) {
- bool selected = i % 2 == 1;
- bool instantiated = i < 2;
-
- Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- Color color = instantiated ? instantiated_color : p_color;
-
- if (!selected) {
- color.a *= 0.3;
- }
-
- material->set_albedo(color);
- material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
- material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
- material->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
-
- if (p_use_vertex_color) {
- material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- }
-
- if (p_billboard) {
- material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- }
-
- if (p_on_top && selected) {
- material->set_on_top_of_alpha();
- }
-
- mats.push_back(material);
- }
-
- materials[p_name] = mats;
-}
-
-void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top, const Color &p_albedo) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
-
- Vector<Ref<StandardMaterial3D>> icons;
-
- for (int i = 0; i < 4; i++) {
- bool selected = i % 2 == 1;
- bool instantiated = i < 2;
-
- Ref<StandardMaterial3D> icon = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- Color color = instantiated ? instantiated_color : p_albedo;
-
- if (!selected) {
- color.a *= 0.85;
- }
-
- icon->set_albedo(color);
-
- icon->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- icon->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- icon->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- icon->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
- icon->set_depth_draw_mode(StandardMaterial3D::DEPTH_DRAW_DISABLED);
- icon->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
- icon->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, p_texture);
- icon->set_flag(StandardMaterial3D::FLAG_FIXED_SIZE, true);
- icon->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- icon->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN);
-
- if (p_on_top && selected) {
- icon->set_on_top_of_alpha();
- }
-
- icons.push_back(icon);
- }
-
- materials[p_name] = icons;
-}
-
-void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref<Texture2D> &p_icon) {
- Ref<StandardMaterial3D> handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
- Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
- handle_material->set_point_size(handle_t->get_width());
- handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
- handle_material->set_albedo(Color(1, 1, 1));
- handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- handle_material->set_on_top_of_alpha();
- if (p_billboard) {
- handle_material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- handle_material->set_on_top_of_alpha();
- }
- handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
-
- materials[p_name] = Vector<Ref<StandardMaterial3D>>();
- materials[p_name].push_back(handle_material);
-}
-
-void EditorNode3DGizmoPlugin::add_material(const String &p_name, Ref<StandardMaterial3D> p_material) {
- materials[p_name] = Vector<Ref<StandardMaterial3D>>();
- materials[p_name].push_back(p_material);
-}
-
-Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo) {
- ERR_FAIL_COND_V(!materials.has(p_name), Ref<StandardMaterial3D>());
- ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref<StandardMaterial3D>());
-
- 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<StandardMaterial3D> mat = materials[p_name][index];
-
- if (current_state == ON_TOP && p_gizmo->is_selected()) {
- mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
- } else {
- mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, false);
- }
-
- return mat;
-}
-
-String EditorNode3DGizmoPlugin::get_gizmo_name() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
- return get_script_instance()->call("_get_gizmo_name");
- }
- return TTR("Nameless gizmo");
-}
-
-int EditorNode3DGizmoPlugin::get_priority() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
- return get_script_instance()->call("_get_priority");
- }
- return 0;
-}
-
-Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("get_gizmo")) {
- return get_script_instance()->call("get_gizmo", p_spatial);
- }
-
- Ref<EditorNode3DGizmo> 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 EditorNode3DGizmoPlugin::_bind_methods() {
-#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
-
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
- BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
-
- ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1)));
- ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material);
-
- ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
-
- 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, "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, "Camera3D"), 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 EditorNode3DGizmoPlugin::has_gizmo(Node3D *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<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) {
- return get_script_instance()->call("_create_gizmo", p_spatial);
- }
-
- Ref<EditorNode3DGizmo> ref;
- if (has_gizmo(p_spatial)) {
- ref.instantiate();
- }
- return ref;
-}
-
-bool EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
- if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
- Ref<EditorNode3DGizmo> ref(p_gizmo);
- get_script_instance()->call("_redraw", ref);
- }
-}
-
-String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *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 EditorNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *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 EditorNode3DGizmoPlugin::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 EditorNode3DGizmoPlugin::get_state() const {
- return current_state;
-}
-
-void EditorNode3DGizmoPlugin::unregister_gizmo(EditorNode3DGizmo *p_gizmo) {
- current_gizmos.erase(p_gizmo);
-}
-
-EditorNode3DGizmoPlugin::EditorNode3DGizmoPlugin() {
- current_state = VISIBLE;
-}
-
-EditorNode3DGizmoPlugin::~EditorNode3DGizmoPlugin() {
- 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 (Node3DEditor::get_singleton()) {
- Node3DEditor::get_singleton()->update_all_gizmos();
- }
-}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index cc65cb53ca..576e4c93d3 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
@@ -43,96 +44,10 @@
class Camera3D;
class Node3DEditor;
-class EditorNode3DGizmoPlugin;
class Node3DEditorViewport;
class SubViewportContainer;
-
-class EditorNode3DGizmo : public Node3DGizmo {
- GDCLASS(EditorNode3DGizmo, Node3DGizmo);
-
- bool selected;
- bool instantiated;
-
-public:
- void set_selected(bool p_selected) { selected = p_selected; }
- bool is_selected() const { return selected; }
-
- struct Instance {
- RID instance;
- Ref<ArrayMesh> mesh;
- Ref<Material> material;
- Ref<SkinReference> skin_reference;
- RID skeleton;
- bool billboard = false;
- bool unscaled = false;
- bool can_intersect = false;
- bool extra_margin = false;
-
- void create_instance(Node3D *p_base, bool p_hidden = false);
- };
-
- Vector<Vector3> collision_segments;
- Ref<TriangleMesh> collision_mesh;
-
- struct Handle {
- Vector3 pos;
- bool billboard = false;
- };
-
- Vector<Vector3> handles;
- Vector<Vector3> secondary_handles;
- float selectable_icon_size;
- bool billboard_handle;
-
- bool valid;
- bool hidden;
- Node3D *base;
- Vector<Instance> instances;
- Node3D *spatial_node;
- EditorNode3DGizmoPlugin *gizmo_plugin;
-
- void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }
-
-protected:
- static void _bind_methods();
-
-public:
- void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
- void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
- void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
- void add_collision_segments(const Vector<Vector3> &p_lines);
- void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
- void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
- void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard = false, bool p_secondary = false);
- void add_solid_box(Ref<Material> &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, Camera3D *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(Node3D *p_node);
- Node3D *get_spatial_node() const { return spatial_node; }
- Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
- Vector3 get_handle_pos(int p_idx) const;
- bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
- bool intersect_ray(Camera3D *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() override;
- virtual void create() override;
- virtual void transform() override;
- virtual void redraw() override;
- virtual void free() override;
-
- virtual bool is_editable() const;
-
- void set_hidden(bool p_hidden);
- void set_plugin(EditorNode3DGizmoPlugin *p_plugin);
-
- EditorNode3DGizmo();
- ~EditorNode3DGizmo();
-};
+class DirectionalLight3D;
+class WorldEnvironment;
class ViewportRotationControl : public Control {
GDCLASS(ViewportRotationControl, Control);
@@ -307,17 +222,15 @@ private:
struct _RayResult {
Node3D *item = nullptr;
float depth = 0;
- int handle = 0;
_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, bool p_include_locked_nodes = 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);
@@ -329,7 +242,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(Node3D *p_node, const Transform3D &p_transform, bool p_local);
void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
@@ -342,7 +256,6 @@ private:
ObjectID clicked;
Vector<_RayResult> selection_results;
- bool clicked_includes_current;
bool clicked_wants_append;
PopupMenu *selection_menu;
@@ -383,15 +296,12 @@ private:
Vector3 click_ray;
Vector3 click_ray_pos;
Vector3 center;
- Vector3 orig_gizmo_pos;
- int edited_gizmo = 0;
Point2 mouse_pos;
Point2 original_mouse_pos;
bool snap = false;
Ref<EditorNode3DGizmo> gizmo;
int gizmo_handle = 0;
Variant gizmo_initial_value;
- Vector3 gizmo_initial_pos;
} _edit;
struct Cursor {
@@ -472,6 +382,8 @@ private:
void _project_settings_changed();
+ Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -512,6 +424,8 @@ public:
Node3D *sp;
RID sbox_instance;
RID sbox_instance_xray;
+ Ref<EditorNode3DGizmo> gizmo;
+ Map<int, Transform3D> subgizmos; // map ID -> initial transform
Node3DEditorSelectedItem() {
sp = nullptr;
@@ -617,7 +531,9 @@ private:
Ref<StandardMaterial3D> plane_gizmo_color_hl[3];
Ref<ShaderMaterial> rotate_gizmo_color_hl[3];
- int over_gizmo_handle;
+ Ref<Node3DGizmo> current_hover_gizmo;
+ int current_hover_gizmo_handle;
+
float snap_translate_value;
float snap_rotate_value;
float snap_scale_value;
@@ -688,7 +604,6 @@ private:
LineEdit *snap_translate;
LineEdit *snap_rotate;
LineEdit *snap_scale;
- PanelContainer *menu_panel;
LineEdit *xform_translate[3];
LineEdit *xform_rotate[3];
@@ -734,6 +649,7 @@ private:
Node3D *selected;
void _request_gizmo(Object *p_obj);
+ void _clear_subgizmo_selection(Object *p_obj = nullptr);
static Node3DEditor *singleton;
@@ -746,8 +662,7 @@ private:
Node3DEditor();
- bool is_any_freelook_active() const;
-
+ void _selection_changed();
void _refresh_menu_icons();
// Preview Sun and Environment
@@ -861,10 +776,16 @@ public:
VSplitContainer *get_shader_split();
HSplitContainer *get_palette_split();
- Node3D *get_selected() { return selected; }
+ Node3D *get_single_selected_node() { return selected; }
+ bool is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo);
+ bool is_subgizmo_selected(int p_id);
+ Vector<int> get_subgizmo_selection();
+
+ Ref<EditorNode3DGizmo> get_current_hover_gizmo() const { return current_hover_gizmo; }
+ void set_current_hover_gizmo(Ref<EditorNode3DGizmo> p_gizmo) { current_hover_gizmo = p_gizmo; }
- int get_over_gizmo_handle() const { return over_gizmo_handle; }
- void set_over_gizmo_handle(int idx) { over_gizmo_handle = idx; }
+ 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(Camera3D *p_preview);
@@ -907,50 +828,4 @@ public:
~Node3DEditorPlugin();
};
-class EditorNode3DGizmoPlugin : public Resource {
- GDCLASS(EditorNode3DGizmoPlugin, Resource);
-
-public:
- static const int VISIBLE = 0;
- static const int HIDDEN = 1;
- static const int ON_TOP = 2;
-
-protected:
- int current_state;
- List<EditorNode3DGizmo *> current_gizmos;
- HashMap<String, Vector<Ref<StandardMaterial3D>>> materials;
-
- static void _bind_methods();
- virtual bool has_gizmo(Node3D *p_spatial);
- virtual Ref<EditorNode3DGizmo> create_gizmo(Node3D *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<Texture2D> &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<Texture2D> &p_texture = nullptr);
- void add_material(const String &p_name, Ref<StandardMaterial3D> p_material);
-
- Ref<StandardMaterial3D> get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo = Ref<EditorNode3DGizmo>());
-
- 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(EditorNode3DGizmo *p_gizmo);
- virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const;
- virtual Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const;
- virtual void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point);
- virtual void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false);
- virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const;
-
- Ref<EditorNode3DGizmo> get_gizmo(Node3D *p_spatial);
- void set_state(int p_state);
- int get_state() const;
- void unregister_gizmo(EditorNode3DGizmo *p_gizmo);
-
- EditorNode3DGizmoPlugin();
- virtual ~EditorNode3DGizmoPlugin();
-};
-
#endif // NODE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 0a95986fe2..63b89aea35 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -36,20 +36,20 @@
#include "node_3d_editor_plugin.h"
#include "scene/resources/curve.h"
-String Path3DGizmo::get_handle_name(int p_idx) const {
+String Path3DGizmo::get_handle_name(int p_id) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return "";
}
- if (p_idx < c->get_point_count()) {
- return TTR("Curve Point #") + itos(p_idx);
+ if (p_id < c->get_point_count()) {
+ return TTR("Curve Point #") + itos(p_id);
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
String n = TTR("Curve Point #") + itos(idx);
if (t == 0) {
n += " In";
@@ -60,21 +60,21 @@ String Path3DGizmo::get_handle_name(int p_idx) const {
return n;
}
-Variant Path3DGizmo::get_handle_value(int p_idx) {
+Variant Path3DGizmo::get_handle_value(int p_id) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return Variant();
}
- if (p_idx < c->get_point_count()) {
- original = c->get_point_position(p_idx);
+ if (p_id < c->get_point_count()) {
+ original = c->get_point_position(p_id);
return original;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
Vector3 ofs;
if (t == 0) {
@@ -88,7 +88,7 @@ Variant Path3DGizmo::get_handle_value(int p_idx) {
return ofs;
}
-void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Path3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return;
@@ -100,7 +100,7 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
// Setting curve point positions
- if (p_idx < c->get_point_count()) {
+ if (p_id < c->get_point_count()) {
Plane p(gt.xform(original), p_camera->get_transform().basis.get_axis(2));
Vector3 inters;
@@ -112,16 +112,16 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
}
Vector3 local = gi.xform(inters);
- c->set_point_position(p_idx, local);
+ c->set_point_position(p_id, local);
}
return;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
Vector3 base = c->get_point_position(idx);
@@ -157,7 +157,7 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
}
}
-void Path3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
+void Path3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return;
@@ -165,27 +165,27 @@ void Path3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_canc
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx < c->get_point_count()) {
+ if (p_id < c->get_point_count()) {
if (p_cancel) {
- c->set_point_position(p_idx, p_restore);
+ c->set_point_position(p_id, p_restore);
return;
}
ur->create_action(TTR("Set Curve Point Position"));
- ur->add_do_method(c.ptr(), "set_point_position", p_idx, c->get_point_position(p_idx));
- ur->add_undo_method(c.ptr(), "set_point_position", p_idx, p_restore);
+ ur->add_do_method(c.ptr(), "set_point_position", p_id, c->get_point_position(p_id));
+ ur->add_undo_method(c.ptr(), "set_point_position", p_id, p_restore);
ur->commit_action();
return;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
if (t == 0) {
if (p_cancel) {
- c->set_point_in(p_idx, p_restore);
+ c->set_point_in(p_id, p_restore);
return;
}
@@ -282,7 +282,7 @@ void Path3DGizmo::redraw() {
add_handles(handles, handles_material);
}
if (sec_handles.size()) {
- add_handles(sec_handles, sec_handles_material, false, true);
+ add_handles(sec_handles, sec_handles_material, Vector<int>(), false, true);
}
}
}
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index 13870d7591..5902500526 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -31,7 +31,9 @@
#ifndef PATH_EDITOR_PLUGIN_H
#define PATH_EDITOR_PLUGIN_H
-#include "editor/node_3d_editor_gizmos.h"
+#include "editor/editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
+#include "scene/3d/camera_3d.h"
#include "scene/3d/path_3d.h"
class Path3DGizmo : public EditorNode3DGizmo {
@@ -44,9 +46,9 @@ class Path3DGizmo : public EditorNode3DGizmo {
public:
virtual String get_handle_name(int p_idx) const override;
- virtual Variant get_handle_value(int p_idx) override;
- virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ virtual Variant get_handle_value(int p_id) const override;
+ virtual void set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false) const override;
virtual void redraw() override;
Path3DGizmo(Path3D *p_path = nullptr);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index c6f2c9253e..0468fe4ee0 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -521,7 +521,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) {
if (p_node == selected) {
selected = nullptr;
- _emit_node_selected();
+ emit_signal("node_selected");
}
}
@@ -615,6 +615,24 @@ void SceneTreeEditor::_tree_changed() {
pending_test_update = true;
}
+void SceneTreeEditor::_selected_changed() {
+ TreeItem *s = tree->get_selected();
+ ERR_FAIL_COND(!s);
+ NodePath np = s->get_metadata(0);
+
+ Node *n = get_node(np);
+
+ if (n == selected) {
+ return;
+ }
+
+ selected = get_node(np);
+
+ blocked++;
+ emit_signal("node_selected");
+ blocked--;
+}
+
void SceneTreeEditor::_deselect_items() {
// Clear currently selected items in scene tree dock.
if (editor_selection) {
@@ -623,12 +641,6 @@ void SceneTreeEditor::_deselect_items() {
}
}
-void SceneTreeEditor::_emit_node_selected() {
- blocked++;
- emit_signal(SNAME("node_selected"));
- blocked--;
-}
-
void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_selected) {
TreeItem *item = Object::cast_to<TreeItem>(p_object);
ERR_FAIL_COND(!item);
@@ -652,11 +664,8 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_
editor_selection->remove_node(n);
}
- // Selection changed to be single node, so emit "selected" (for single node) rather than "changed" (for multiple nodes)
- if (editor_selection->get_selected_nodes().size() == 1) {
- selected = editor_selection->get_selected_node_list()[0];
- _emit_node_selected();
- } else {
+ // Emitted "selected" in _selected_changed() when select single node, so select multiple node emit "changed"
+ if (editor_selection->get_selected_nodes().size() > 1) {
emit_signal(SNAME("node_changed"));
}
}
@@ -747,7 +756,7 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) {
}
if (p_emit_selected) {
- _emit_node_selected();
+ emit_signal("node_selected");
}
}
@@ -1197,6 +1206,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
tree->connect("empty_tree_rmb_selected", callable_mp(this, &SceneTreeEditor::_rmb_select));
}
+ tree->connect("cell_selected", callable_mp(this, &SceneTreeEditor::_selected_changed));
tree->connect("item_edited", callable_mp(this, &SceneTreeEditor::_renamed), varray(), CONNECT_DEFERRED);
tree->connect("multi_selected", callable_mp(this, &SceneTreeEditor::_cell_multi_selected));
tree->connect("button_pressed", callable_mp(this, &SceneTreeEditor::_cell_button_pressed));
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index e833bf93e0..acd49e8d92 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -81,6 +81,7 @@ class SceneTreeEditor : public Control {
TreeItem *_find(TreeItem *p_node, const NodePath &p_path);
void _notification(int p_what);
+ void _selected_changed();
void _deselect_items();
void _rename_node(ObjectID p_node, const String &p_name);
@@ -132,8 +133,6 @@ class SceneTreeEditor : public Control {
Vector<StringName> valid_types;
- void _emit_node_selected();
-
public:
void set_filter(const String &p_filter);
String get_filter() const;
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index 37a7d96de5..fc84c029ec 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "csg_gizmos.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
+#include "scene/3d/camera_3d.h"
///////////
@@ -48,7 +50,7 @@ CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() {
create_handle_material("handles");
}
-String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -60,17 +62,17 @@ String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo,
}
if (Object::cast_to<CSGCylinder3D>(cs)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<CSGTorus3D>(cs)) {
- return p_idx == 0 ? "InnerRadius" : "OuterRadius";
+ return p_id == 0 ? "InnerRadius" : "OuterRadius";
}
return "";
}
-Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant CSGShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -85,18 +87,18 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CSGCylinder3D>(cs)) {
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
- return p_idx == 0 ? s->get_radius() : s->get_height();
+ return p_id == 0 ? s->get_radius() : s->get_height();
}
if (Object::cast_to<CSGTorus3D>(cs)) {
CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs);
- return p_idx == 0 ? s->get_inner_radius() : s->get_outer_radius();
+ return p_id == 0 ? s->get_inner_radius() : s->get_outer_radius();
}
return Variant();
}
-void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
Transform3D gt = cs->get_global_transform();
@@ -129,10 +131,10 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
CSGBox3D *s = Object::cast_to<CSGBox3D>(cs);
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -142,7 +144,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
}
Vector3 h = s->get_size();
- h[p_idx] = d * 2;
+ h[p_id] = d * 2;
s->set_size(h);
}
@@ -150,7 +152,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
Vector3 axis;
- axis[p_idx == 0 ? 0 : 1] = 1.0;
+ axis[p_id == 0 ? 0 : 1] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
float d = axis.dot(ra);
@@ -162,9 +164,9 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
s->set_height(d * 2.0);
}
}
@@ -185,15 +187,15 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_inner_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
s->set_outer_radius(d);
}
}
}
-void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -227,7 +229,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
if (Object::cast_to<CSGCylinder3D>(cs)) {
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_radius(p_restore);
} else {
s->set_height(p_restore);
@@ -236,7 +238,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Cylinder Radius"));
ur->add_do_method(s, "set_radius", s->get_radius());
ur->add_undo_method(s, "set_radius", p_restore);
@@ -252,7 +254,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
if (Object::cast_to<CSGTorus3D>(cs)) {
CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs);
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_inner_radius(p_restore);
} else {
s->set_outer_radius(p_restore);
@@ -261,7 +263,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Torus Inner Radius"));
ur->add_do_method(s, "set_inner_radius", s->get_inner_radius());
ur->add_undo_method(s, "set_inner_radius", p_restore);
@@ -356,7 +358,7 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
break;
}
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material);
+ p_gizmo->add_mesh(mesh, solid_material);
}
if (Object::cast_to<CSGSphere3D>(cs)) {
diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h
index 8f7da35de3..847313c0b4 100644
--- a/modules/csg/csg_gizmos.h
+++ b/modules/csg/csg_gizmos.h
@@ -33,22 +33,22 @@
#include "csg_shape.h"
#include "editor/editor_plugin.h"
-#include "editor/node_3d_editor_gizmos.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
public:
- bool has_gizmo(Node3D *p_spatial) override;
- String get_gizmo_name() const override;
- int get_priority() const override;
- bool is_selectable_when_hidden() const override;
- void redraw(EditorNode3DGizmo *p_gizmo) override;
-
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) override;
+ virtual bool has_gizmo(Node3D *p_spatial) override;
+ virtual String get_gizmo_name() const override;
+ virtual int get_priority() const override;
+ virtual bool is_selectable_when_hidden() const override;
+ virtual void redraw(EditorNode3DGizmo *p_gizmo) override;
+
+ virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const override;
CSGShape3DGizmoPlugin();
};
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 729dc2f8fc..73c1ba554c 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -548,7 +548,7 @@ void CSGShape3D::_notification(int p_what) {
void CSGShape3D::set_operation(Operation p_operation) {
operation = p_operation;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
CSGShape3D::Operation CSGShape3D::get_operation() const {
@@ -845,7 +845,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
void CSGMesh3D::_mesh_changed() {
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
void CSGMesh3D::set_material(const Ref<Material> &p_material) {
@@ -1034,7 +1034,7 @@ void CSGSphere3D::set_radius(const float p_radius) {
ERR_FAIL_COND(p_radius <= 0);
radius = p_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGSphere3D::get_radius() const {
@@ -1044,7 +1044,7 @@ float CSGSphere3D::get_radius() const {
void CSGSphere3D::set_radial_segments(const int p_radial_segments) {
radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGSphere3D::get_radial_segments() const {
@@ -1054,7 +1054,7 @@ int CSGSphere3D::get_radial_segments() const {
void CSGSphere3D::set_rings(const int p_rings) {
rings = p_rings > 1 ? p_rings : 1;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGSphere3D::get_rings() const {
@@ -1203,7 +1203,7 @@ void CSGBox3D::_bind_methods() {
void CSGBox3D::set_size(const Vector3 &p_size) {
size = p_size;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Vector3 CSGBox3D::get_size() const {
@@ -1213,7 +1213,7 @@ Vector3 CSGBox3D::get_size() const {
void CSGBox3D::set_material(const Ref<Material> &p_material) {
material = p_material;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Ref<Material> CSGBox3D::get_material() const {
@@ -1384,7 +1384,7 @@ void CSGCylinder3D::_bind_methods() {
void CSGCylinder3D::set_radius(const float p_radius) {
radius = p_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGCylinder3D::get_radius() const {
@@ -1394,7 +1394,7 @@ float CSGCylinder3D::get_radius() const {
void CSGCylinder3D::set_height(const float p_height) {
height = p_height;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGCylinder3D::get_height() const {
@@ -1405,7 +1405,7 @@ void CSGCylinder3D::set_sides(const int p_sides) {
ERR_FAIL_COND(p_sides < 3);
sides = p_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGCylinder3D::get_sides() const {
@@ -1415,7 +1415,7 @@ int CSGCylinder3D::get_sides() const {
void CSGCylinder3D::set_cone(const bool p_cone) {
cone = p_cone;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGCylinder3D::is_cone() const {
@@ -1603,7 +1603,7 @@ void CSGTorus3D::_bind_methods() {
void CSGTorus3D::set_inner_radius(const float p_inner_radius) {
inner_radius = p_inner_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGTorus3D::get_inner_radius() const {
@@ -1613,7 +1613,7 @@ float CSGTorus3D::get_inner_radius() const {
void CSGTorus3D::set_outer_radius(const float p_outer_radius) {
outer_radius = p_outer_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGTorus3D::get_outer_radius() const {
@@ -1624,7 +1624,7 @@ void CSGTorus3D::set_sides(const int p_sides) {
ERR_FAIL_COND(p_sides < 3);
sides = p_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGTorus3D::get_sides() const {
@@ -1635,7 +1635,7 @@ void CSGTorus3D::set_ring_sides(const int p_ring_sides) {
ERR_FAIL_COND(p_ring_sides < 3);
ring_sides = p_ring_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGTorus3D::get_ring_sides() const {
@@ -2172,7 +2172,7 @@ void CSGPolygon3D::_validate_property(PropertyInfo &property) const {
void CSGPolygon3D::_path_changed() {
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
void CSGPolygon3D::_path_exited() {
@@ -2248,7 +2248,7 @@ void CSGPolygon3D::_bind_methods() {
void CSGPolygon3D::set_polygon(const Vector<Vector2> &p_polygon) {
polygon = p_polygon;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Vector<Vector2> CSGPolygon3D::get_polygon() const {
@@ -2258,7 +2258,7 @@ Vector<Vector2> CSGPolygon3D::get_polygon() const {
void CSGPolygon3D::set_mode(Mode p_mode) {
mode = p_mode;
_make_dirty();
- update_gizmo();
+ update_gizmos();
notify_property_list_changed();
}
@@ -2270,7 +2270,7 @@ void CSGPolygon3D::set_depth(const float p_depth) {
ERR_FAIL_COND(p_depth < 0.001);
depth = p_depth;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_depth() const {
@@ -2290,7 +2290,7 @@ void CSGPolygon3D::set_spin_degrees(const float p_spin_degrees) {
ERR_FAIL_COND(p_spin_degrees < 0.01 || p_spin_degrees > 360);
spin_degrees = p_spin_degrees;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_spin_degrees() const {
@@ -2301,7 +2301,7 @@ void CSGPolygon3D::set_spin_sides(const int p_spin_sides) {
ERR_FAIL_COND(p_spin_sides < 3);
spin_sides = p_spin_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGPolygon3D::get_spin_sides() const {
@@ -2311,7 +2311,7 @@ int CSGPolygon3D::get_spin_sides() const {
void CSGPolygon3D::set_path_node(const NodePath &p_path) {
path_node = p_path;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
NodePath CSGPolygon3D::get_path_node() const {
@@ -2322,7 +2322,7 @@ void CSGPolygon3D::set_path_interval(float p_interval) {
ERR_FAIL_COND_MSG(p_interval < 0.001, "Path interval cannot be smaller than 0.001.");
path_interval = p_interval;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_path_interval() const {
@@ -2332,7 +2332,7 @@ float CSGPolygon3D::get_path_interval() const {
void CSGPolygon3D::set_path_rotation(PathRotation p_rotation) {
path_rotation = p_rotation;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const {
@@ -2342,7 +2342,7 @@ CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const {
void CSGPolygon3D::set_path_local(bool p_enable) {
path_local = p_enable;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGPolygon3D::is_path_local() const {
@@ -2352,7 +2352,7 @@ bool CSGPolygon3D::is_path_local() const {
void CSGPolygon3D::set_path_joined(bool p_enable) {
path_joined = p_enable;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGPolygon3D::is_path_joined() const {
diff --git a/modules/navigation/navigation_mesh_editor_plugin.cpp b/modules/navigation/navigation_mesh_editor_plugin.cpp
index 8f4203e260..587e56f593 100644
--- a/modules/navigation/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/navigation_mesh_editor_plugin.cpp
@@ -65,7 +65,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() {
@@ -77,7 +77,7 @@ void NavigationMeshEditor::_clear_pressed() {
bake_info->set_text("");
if (node) {
- node->update_gizmo();
+ node->update_gizmos();
}
}
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 7b5ca56dcc..a6c52a0f8c 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -2268,7 +2268,7 @@ int VisualScriptEmitSignal::get_input_value_port_count() const {
}
int VisualScriptEmitSignal::get_output_value_port_count() const {
- return 1;
+ return 0;
}
String VisualScriptEmitSignal::get_output_sequence_port_text(int p_port) const {
@@ -2311,16 +2311,6 @@ StringName VisualScriptEmitSignal::get_signal() const {
return name;
}
-void VisualScriptEmitSignal::_adjust_input_index(PropertyInfo &pinfo) const {
- if (index != StringName()) {
- Variant v;
- Callable::CallError ce;
- Variant::construct(pinfo.type, v, nullptr, 0, ce);
- Variant i = v.get(index);
- pinfo.type = i.get_type();
- }
-}
-
void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const {
if (property.name == "signal") {
property.hint = PROPERTY_HINT_ENUM;
diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h
index 37a707d108..cca08455f9 100644
--- a/modules/visual_script/visual_script_func_nodes.h
+++ b/modules/visual_script/visual_script_func_nodes.h
@@ -328,9 +328,6 @@ class VisualScriptEmitSignal : public VisualScriptNode {
private:
StringName name;
- StringName index;
-
- void _adjust_input_index(PropertyInfo &pinfo) const;
protected:
virtual void _validate_property(PropertyInfo &property) const override;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index dd8cb1f20d..bb8f9f8ccb 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -794,7 +794,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 {
@@ -804,7 +804,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();
}
float AudioStreamPlayer3D::get_emission_angle() const {
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 0c38d85a6b..2e962b96c3 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -164,7 +164,7 @@ void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_f
mode = PROJECTION_PERSPECTIVE;
RenderingServer::get_singleton()->camera_set_perspective(camera, fov, near, far);
- update_gizmo();
+ update_gizmos();
force_change = false;
}
@@ -181,7 +181,7 @@ void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
force_change = false;
RenderingServer::get_singleton()->camera_set_orthogonal(camera, size, near, far);
- update_gizmo();
+ update_gizmos();
}
void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
@@ -198,7 +198,7 @@ void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float
force_change = false;
RenderingServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far);
- update_gizmo();
+ update_gizmos();
}
void Camera3D::set_projection(Camera3D::Projection p_mode) {
@@ -755,7 +755,7 @@ void ClippedCamera3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- update_gizmo();
+ update_gizmos();
}
}
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index 8a4f8b639b..42645f47d4 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -122,7 +122,7 @@ void CollisionPolygon3D::set_polygon(const Vector<Point2> &p_polygon) {
_build_polygon();
}
update_configuration_warnings();
- update_gizmo();
+ update_gizmos();
}
Vector<Point2> CollisionPolygon3D::get_polygon() const {
@@ -136,7 +136,7 @@ AABB CollisionPolygon3D::get_item_rect() const {
void CollisionPolygon3D::set_depth(real_t p_depth) {
depth = p_depth;
_build_polygon();
- update_gizmo();
+ update_gizmos();
}
real_t CollisionPolygon3D::get_depth() const {
@@ -145,7 +145,7 @@ real_t CollisionPolygon3D::get_depth() const {
void CollisionPolygon3D::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_3d.cpp b/scene/3d/collision_shape_3d.cpp
index be3fde8013..9643d33c86 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -117,7 +117,7 @@ void CollisionShape3D::_notification(int p_what) {
}
void CollisionShape3D::resource_changed(RES res) {
- update_gizmo();
+ update_gizmos();
}
TypedArray<String> CollisionShape3D::get_configuration_warnings() const {
@@ -166,7 +166,7 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &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()) {
@@ -187,7 +187,7 @@ Ref<Shape3D> CollisionShape3D::get_shape() const {
void CollisionShape3D::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/decal.cpp b/scene/3d/decal.cpp
index 5af7b8ca07..05f023721b 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -33,7 +33,7 @@
void Decal::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->decal_set_extents(decal, p_extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 Decal::get_extents() const {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index f78027e6c7..44cd7c10d8 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -99,7 +99,7 @@ void GPUParticles3D::set_randomness_ratio(float p_ratio) {
void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) {
visibility_aabb = p_aabb;
RS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
- update_gizmo();
+ update_gizmos();
}
void GPUParticles3D::set_use_local_coordinates(bool p_enable) {
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index 5b88a6ec9f..df7d7be1fd 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -73,7 +73,7 @@ void GPUParticlesCollisionSphere::_bind_methods() {
void GPUParticlesCollisionSphere::set_radius(float p_radius) {
radius = p_radius;
RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesCollisionSphere::get_radius() const {
@@ -103,7 +103,7 @@ void GPUParticlesCollisionBox::_bind_methods() {
void GPUParticlesCollisionBox::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesCollisionBox::get_extents() const {
@@ -545,7 +545,7 @@ float GPUParticlesCollisionSDF::get_thickness() const {
void GPUParticlesCollisionSDF::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesCollisionSDF::get_extents() const {
@@ -554,7 +554,7 @@ Vector3 GPUParticlesCollisionSDF::get_extents() const {
void GPUParticlesCollisionSDF::set_resolution(Resolution p_resolution) {
resolution = p_resolution;
- update_gizmo();
+ update_gizmos();
}
GPUParticlesCollisionSDF::Resolution GPUParticlesCollisionSDF::get_resolution() const {
@@ -680,7 +680,7 @@ float GPUParticlesCollisionHeightField::get_follow_camera_push_ratio() const {
void GPUParticlesCollisionHeightField::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
RS::get_singleton()->particles_collision_height_field_update(_get_collision());
}
@@ -691,7 +691,7 @@ Vector3 GPUParticlesCollisionHeightField::get_extents() const {
void GPUParticlesCollisionHeightField::set_resolution(Resolution p_resolution) {
resolution = p_resolution;
RS::get_singleton()->particles_collision_set_height_field_resolution(_get_collision(), RS::ParticlesCollisionHeightfieldResolution(resolution));
- update_gizmo();
+ update_gizmos();
RS::get_singleton()->particles_collision_height_field_update(_get_collision());
}
@@ -761,7 +761,7 @@ float GPUParticlesAttractor3D::get_attenuation() const {
void GPUParticlesAttractor3D::set_directionality(float p_directionality) {
directionality = p_directionality;
RS::get_singleton()->particles_collision_set_attractor_directionality(collision, p_directionality);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesAttractor3D::get_directionality() const {
@@ -808,7 +808,7 @@ void GPUParticlesAttractorSphere::_bind_methods() {
void GPUParticlesAttractorSphere::set_radius(float p_radius) {
radius = p_radius;
RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesAttractorSphere::get_radius() const {
@@ -838,7 +838,7 @@ void GPUParticlesAttractorBox::_bind_methods() {
void GPUParticlesAttractorBox::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesAttractorBox::get_extents() const {
@@ -872,7 +872,7 @@ void GPUParticlesAttractorVectorField::_bind_methods() {
void GPUParticlesAttractorVectorField::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesAttractorVectorField::get_extents() const {
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 8478821ba1..c2943a9606 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -45,7 +45,7 @@ void Light3D::set_param(Param p_param, float p_value) {
RS::get_singleton()->light_set_param(light, RS::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) {
update_configuration_warnings();
@@ -95,7 +95,7 @@ void Light3D::set_color(const Color &p_color) {
color = p_color;
RS::get_singleton()->light_set_color(light, p_color);
// The gizmo color depends on the light color, so update it.
- update_gizmo();
+ update_gizmos();
}
Color Light3D::get_color() const {
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 3ffb3c0393..0085c8933d 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1250,7 +1250,7 @@ void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
}
}
- update_gizmo();
+ update_gizmos();
}
Ref<LightmapGIData> LightmapGI::get_light_data() const {
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 28ccbd3e68..5bb598227c 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -133,7 +133,7 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
set_base(RID());
}
- update_gizmo();
+ update_gizmos();
notify_property_list_changed();
}
@@ -356,7 +356,7 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
void MeshInstance3D::_mesh_changed() {
ERR_FAIL_COND(mesh.is_null());
surface_override_materials.resize(mesh->get_surface_count());
- update_gizmo();
+ update_gizmos();
}
void MeshInstance3D::create_debug_tangents() {
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 19abb3f33a..2976dad39d 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -59,7 +59,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
}
}
- update_gizmo();
+ update_gizmos();
}
bool NavigationRegion3D::is_enabled() const {
@@ -134,7 +134,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
emit_signal(SNAME("navigation_mesh_changed"));
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
@@ -211,7 +211,7 @@ void NavigationRegion3D::_bind_methods() {
}
void NavigationRegion3D::_navigation_changed() {
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index d6c6ec75b4..d1f96230e0 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -76,7 +76,7 @@ Node3DGizmo::Node3DGizmo() {
void Node3D::_notify_dirty() {
#ifdef TOOLS_ENABLED
- if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
+ if ((!data.gizmos.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) {
@@ -110,7 +110,7 @@ void Node3D::_propagate_transform_changed(Node3D *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.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) {
#endif
@@ -181,15 +181,14 @@ void Node3D::_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();
}
}
}
@@ -198,10 +197,7 @@ void Node3D::_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()) {
@@ -215,8 +211,8 @@ void Node3D::_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;
@@ -368,80 +364,119 @@ Vector3 Node3D::get_scale() const {
return data.scale;
}
-void Node3D::update_gizmo() {
+void Node3D::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.gizmos.is_empty()) {
+ return;
}
- if (!data.gizmo.is_valid()) {
+ data.gizmos_dirty = true;
+ MessageQueue::get_singleton()->push_callable(callable_mp(this, &Node3D::_update_gizmos));
+#endif
+}
+
+void Node3D::clear_subgizmo_selection() {
+#ifdef TOOLS_ENABLED
+ if (!is_inside_world()) {
return;
}
- if (data.gizmo_dirty) {
+
+ if (data.gizmos.is_empty()) {
return;
}
- data.gizmo_dirty = true;
- MessageQueue::get_singleton()->push_call(this, "_update_gizmo");
+
+ 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 Node3D::set_gizmo(const Ref<Node3DGizmo> &p_gizmo) {
+void Node3D::add_gizmo(Ref<Node3DGizmo> p_gizmo) {
#ifdef TOOLS_ENABLED
- if (data.gizmo_disabled) {
+ if (data.gizmos_disabled || p_gizmo.is_null()) {
return;
}
- if (data.gizmo.is_valid() && is_inside_world()) {
- data.gizmo->free();
- }
- data.gizmo = p_gizmo;
- if (data.gizmo.is_valid() && is_inside_world()) {
- data.gizmo->create();
+ 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
+}
+
+void Node3D::remove_gizmo(Ref<Node3DGizmo> p_gizmo) {
+#ifdef TOOLS_ENABLED
+ int idx = data.gizmos.find(p_gizmo);
+ if (idx != -1) {
+ p_gizmo->free();
+ data.gizmos.remove(idx);
+ }
+#endif
+}
+
+void Node3D::clear_gizmos() {
+#ifdef TOOLS_ENABLED
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ data.gizmos.write[i]->free();
+ }
+ data.gizmos.clear();
+#endif
+}
+
+Array Node3D::get_gizmos_bind() const {
+ Array ret;
+
+#ifdef TOOLS_ENABLED
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ ret.push_back(Variant(data.gizmos[i].ptr()));
+ }
#endif
+
+ return ret;
}
-Ref<Node3DGizmo> Node3D::get_gizmo() const {
+Vector<Ref<Node3DGizmo>> Node3D::get_gizmos() const {
#ifdef TOOLS_ENABLED
- return data.gizmo;
+ return data.gizmos;
#else
- return Ref<Node3DGizmo>();
+ return Vector<Ref<Node3DGizmo>>();
#endif
}
-void Node3D::_update_gizmo() {
+void Node3D::_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
}
#ifdef TOOLS_ENABLED
-void Node3D::set_disable_gizmo(bool p_enabled) {
- data.gizmo_disabled = p_enabled;
- if (!p_enabled && data.gizmo.is_valid()) {
- data.gizmo = Ref<Node3DGizmo>();
+void Node3D::set_disable_gizmos(bool p_enabled) {
+ data.gizmos_disabled = p_enabled;
+ if (!p_enabled) {
+ clear_gizmos();
}
}
-
#endif
void Node3D::set_disable_scale(bool p_enabled) {
@@ -486,8 +521,9 @@ void Node3D::_propagate_visibility_changed() {
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
#ifdef TOOLS_ENABLED
- if (data.gizmo.is_valid()) {
- _update_gizmo();
+ if (!data.gizmos.is_empty()) {
+ data.gizmos_dirty = true;
+ _update_gizmos();
}
#endif
@@ -758,11 +794,11 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visibility_parent", "path"), &Node3D::set_visibility_parent);
ClassDB::bind_method(D_METHOD("get_visibility_parent"), &Node3D::get_visibility_parent);
- ClassDB::bind_method(D_METHOD("_update_gizmo"), &Node3D::_update_gizmo);
-
- ClassDB::bind_method(D_METHOD("update_gizmo"), &Node3D::update_gizmo);
- ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Node3D::set_gizmo);
- ClassDB::bind_method(D_METHOD("get_gizmo"), &Node3D::get_gizmo);
+ ClassDB::bind_method(D_METHOD("update_gizmos"), &Node3D::update_gizmos);
+ ClassDB::bind_method(D_METHOD("add_gizmo", "gizmo"), &Node3D::add_gizmo);
+ ClassDB::bind_method(D_METHOD("get_gizmos"), &Node3D::get_gizmos_bind);
+ ClassDB::bind_method(D_METHOD("clear_gizmos"), &Node3D::clear_gizmos);
+ ClassDB::bind_method(D_METHOD("clear_subgizmo_selection"), &Node3D::clear_subgizmo_selection);
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Node3D::set_visible);
ClassDB::bind_method(D_METHOD("is_visible"), &Node3D::is_visible);
@@ -813,7 +849,6 @@ void Node3D::_bind_methods() {
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "Node3DGizmo", PROPERTY_USAGE_NONE), "set_gizmo", "get_gizmo");
ADD_SIGNAL(MethodInfo("visibility_changed"));
}
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index fe6324c796..282f4805cc 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -90,16 +90,16 @@ class Node3D : public Node {
bool disable_scale = false;
#ifdef TOOLS_ENABLED
- Ref<Node3DGizmo> gizmo;
- bool gizmo_disabled = false;
- bool gizmo_dirty = false;
+ Vector<Ref<Node3DGizmo>> gizmos;
+ bool gizmos_disabled = false;
+ bool gizmos_dirty = false;
#endif
} data;
NodePath visibility_parent_path;
- void _update_gizmo();
+ void _update_gizmos();
void _notify_dirty();
void _propagate_transform_changed(Node3D *p_origin);
@@ -154,10 +154,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<Node3DGizmo> &p_gizmo);
- Ref<Node3DGizmo> get_gizmo() const;
+ void set_disable_gizmos(bool p_enabled);
+ void update_gizmos();
+ void clear_subgizmo_selection();
+ Vector<Ref<Node3DGizmo>> get_gizmos() const;
+ Array get_gizmos_bind() const;
+ void add_gizmo(Ref<Node3DGizmo> p_gizmo);
+ void remove_gizmo(Ref<Node3DGizmo> p_gizmo);
+ void clear_gizmos();
_FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; }
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index 7b736e689c..3d1a27911b 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -173,12 +173,12 @@ void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
set_base(RID());
}
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
void OccluderInstance3D::_occluder_changed() {
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 54ae2cef75..6af2e7f879 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -38,7 +38,7 @@ void Path3D::_notification(int p_what) {
void Path3D::_curve_changed() {
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
- update_gizmo();
+ update_gizmos();
}
if (is_inside_tree()) {
emit_signal(SNAME("curve_changed"));
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 760dbdadca..0e3180bcdf 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -2181,9 +2181,7 @@ bool PhysicalBone3D::_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;
}
@@ -2371,9 +2369,7 @@ void PhysicalBone3D::_update_joint_offset() {
set_ignore_transform_notification(false);
#ifdef TOOLS_ENABLED
- if (get_gizmo().is_valid()) {
- get_gizmo()->redraw();
- }
+ update_gizmos();
#endif
}
@@ -2540,9 +2536,7 @@ void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
#ifdef TOOLS_ENABLED
notify_property_list_changed();
- if (get_gizmo().is_valid()) {
- get_gizmo()->redraw();
- }
+ update_gizmos();
#endif
}
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index 01f10c171f..59440bd1a8 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -348,7 +348,7 @@ void HingeJoint3D::set_param(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t HingeJoint3D::get_param(Param p_param) const {
@@ -363,7 +363,7 @@ void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
}
- update_gizmo();
+ update_gizmos();
}
bool HingeJoint3D::get_flag(Flag p_flag) const {
@@ -497,7 +497,7 @@ void SliderJoint3D::set_param(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t SliderJoint3D::get_param(Param p_param) const {
@@ -602,7 +602,7 @@ void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t ConeTwistJoint3D::get_param(Param p_param) const {
@@ -857,7 +857,7 @@ void Generic6DOFJoint3D::set_param_x(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_x(Param p_param) const {
@@ -871,7 +871,7 @@ void Generic6DOFJoint3D::set_param_y(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_y(Param p_param) const {
@@ -885,7 +885,7 @@ void Generic6DOFJoint3D::set_param_z(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_z(Param p_param) const {
@@ -899,7 +899,7 @@ void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
@@ -913,7 +913,7 @@ void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
@@ -927,7 +927,7 @@ void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index dfab3d4a17..7356ce478b 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -37,7 +37,7 @@
void RayCast3D::set_target_position(const Vector3 &p_point) {
target_position = p_point;
- update_gizmo();
+ update_gizmos();
if (Engine::get_singleton()->is_editor_hint()) {
if (is_inside_tree()) {
@@ -102,7 +102,7 @@ Vector3 RayCast3D::get_collision_normal() const {
void RayCast3D::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);
@@ -366,7 +366,7 @@ void RayCast3D::_update_debug_shape_vertices() {
void RayCast3D::set_debug_shape_thickness(const float 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 c289fc4fd7..719dbedd94 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -101,7 +101,7 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) {
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- update_gizmo();
+ update_gizmos();
}
Vector3 ReflectionProbe::get_extents() const {
@@ -119,7 +119,7 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- update_gizmo();
+ update_gizmos();
}
Vector3 ReflectionProbe::get_origin_offset() const {
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index fa3b16935c..ba70a6eb41 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -404,7 +404,7 @@ void Skeleton3D::add_bone(const String &p_name) {
process_order_dirty = true;
version++;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int Skeleton3D::find_bone(const String &p_name) const {
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index 1911e14d54..5e9265b4c3 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -84,7 +84,7 @@ real_t SpringArm3D::get_length() const {
void SpringArm3D::set_length(real_t 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 2a53dd6aca..fd3bf99e0a 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -174,7 +174,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_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index b0e37b81a5..92c0e09947 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -149,7 +149,7 @@ void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) {
void VehicleWheel3D::set_radius(real_t p_radius) {
m_wheelRadius = p_radius;
- update_gizmo();
+ update_gizmos();
}
real_t VehicleWheel3D::get_radius() const {
@@ -158,7 +158,7 @@ real_t VehicleWheel3D::get_radius() const {
void VehicleWheel3D::set_suspension_rest_length(real_t p_length) {
m_suspensionRestLength = p_length;
- update_gizmo();
+ update_gizmos();
}
real_t VehicleWheel3D::get_suspension_rest_length() const {
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 682bcec449..6a80aa3f45 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -63,7 +63,7 @@ void VisibleOnScreenNotifier3D::set_aabb(const AABB &p_aabb) {
RS::get_singleton()->visibility_notifier_set_aabb(get_base(), aabb);
- update_gizmo();
+ update_gizmos();
}
AABB VisibleOnScreenNotifier3D::get_aabb() const {
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index 3da59ac4c0..bc52db5387 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -265,7 +265,7 @@ Ref<VoxelGIData> VoxelGI::get_probe_data() const {
void VoxelGI::set_subdiv(Subdiv p_subdiv) {
ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
subdiv = p_subdiv;
- update_gizmo();
+ update_gizmos();
}
VoxelGI::Subdiv VoxelGI::get_subdiv() const {
@@ -274,7 +274,7 @@ VoxelGI::Subdiv VoxelGI::get_subdiv() const {
void VoxelGI::set_extents(const Vector3 &p_extents) {
extents = p_extents;
- update_gizmo();
+ update_gizmos();
}
Vector3 VoxelGI::get_extents() const {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index ee9e0e8ab8..14c86c0d27 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -397,10 +397,6 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
- if (!item_clickable_area.has_point(m->get_position())) {
- return;
- }
-
for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
_close_pressed();
@@ -408,6 +404,10 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
}
}
+ if (!item_clickable_area.has_point(m->get_position())) {
+ return;
+ }
+
int over = _get_mouse_over(m->get_position());
int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].id >= 0 ? items[over].id : over);
@@ -747,7 +747,7 @@ void PopupMenu::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
//only used when using operating system windows
- if (get_window_id() != DisplayServer::INVALID_WINDOW_ID && autohide_areas.size()) {
+ if (!is_embedded() && autohide_areas.size()) {
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
mouse_pos -= get_position();
@@ -786,7 +786,7 @@ void PopupMenu::_notification(int p_what) {
set_process_internal(false);
} else {
- if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (!is_embedded()) {
set_process_internal(true);
}
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d53d155cce..b8173c9623 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -136,6 +136,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 a141c2b3aa..eddb0c33eb 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -156,6 +156,7 @@ public:
StringName _spatial_editor_group;
StringName _request_gizmo;
+ StringName _clear_subgizmo_selection;
StringName offset;
StringName unit_offset;