2015-10-08 20:00:40 +02:00
/**************************************************************************/
2020-03-27 08:44:44 +01:00
/* node_3d_editor_gizmos.cpp */
2015-10-08 20:00:40 +02:00
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2020-03-27 08:44:44 +01:00
# include "node_3d_editor_gizmos.h"
2017-01-16 08:04:19 +01:00
2020-05-25 19:20:45 +02:00
# include "core/math/geometry_2d.h"
# include "core/math/geometry_3d.h"
2022-02-12 02:46:22 +01:00
# include "editor/editor_node.h"
# include "editor/editor_settings.h"
2023-09-13 13:14:07 +02:00
# include "editor/editor_string_names.h"
2021-06-23 16:49:50 +02:00
# include "editor/plugins/node_3d_editor_plugin.h"
2021-08-13 18:42:45 +02:00
# include "scene/resources/3d/primitive_meshes.h"
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
# define HANDLE_HALF_SIZE 9.5
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmo : : is_editable ( ) const {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( spatial_node , false ) ;
2017-08-26 05:40:45 +02:00
Node * edited_root = spatial_node - > get_tree ( ) - > get_edited_scene_root ( ) ;
2020-05-14 16:41:43 +02:00
if ( spatial_node = = edited_root ) {
2017-08-26 05:40:45 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
if ( spatial_node - > get_owner ( ) = = edited_root ) {
2017-08-26 05:40:45 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-08-26 05:40:45 +02:00
2020-05-14 16:41:43 +02:00
if ( edited_root - > is_editable_instance ( spatial_node - > get_owner ( ) ) ) {
2017-08-26 05:40:45 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-08-26 05:40:45 +02:00
return false ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : clear ( ) {
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
2015-10-08 20:00:40 +02:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( instances [ i ] . instance . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( instances [ i ] . instance ) ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
}
billboard_handle = false ;
collision_segments . clear ( ) ;
collision_mesh = Ref < TriangleMesh > ( ) ;
instances . clear ( ) ;
handles . clear ( ) ;
2022-11-01 09:25:13 +01:00
handle_ids . clear ( ) ;
2015-10-08 20:00:40 +02:00
secondary_handles . clear ( ) ;
2022-11-01 09:25:13 +01:00
secondary_handle_ids . clear ( ) ;
2015-10-08 20:00:40 +02:00
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : redraw ( ) {
2021-08-22 03:52:44 +02:00
if ( ! GDVIRTUAL_CALL ( _redraw ) ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2021-06-23 16:49:50 +02:00
gizmo_plugin - > redraw ( this ) ;
2019-01-25 12:57:32 +01:00
}
2024-07-20 01:30:33 +02:00
_update_bvh ( ) ;
2021-06-23 16:49:50 +02:00
if ( Node3DEditor : : get_singleton ( ) - > is_current_selected_gizmo ( this ) ) {
Node3DEditor : : get_singleton ( ) - > update_transform_gizmo ( ) ;
}
2018-07-25 00:08:49 +02:00
}
2022-01-11 12:33:37 +01:00
String EditorNode3DGizmo : : get_handle_name ( int p_id , bool p_secondary ) const {
2021-08-22 03:52:44 +02:00
String ret ;
2022-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _get_handle_name , p_id , p_secondary , ret ) ) {
2021-08-22 03:52:44 +02:00
return ret ;
2019-01-25 12:57:32 +01:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , " " ) ;
2022-01-11 12:33:37 +01:00
return gizmo_plugin - > get_handle_name ( this , p_id , p_secondary ) ;
2018-07-25 00:08:49 +02:00
}
2022-01-11 12:33:37 +01:00
bool EditorNode3DGizmo : : is_handle_highlighted ( int p_id , bool p_secondary ) const {
2021-08-22 03:52:44 +02:00
bool success ;
2022-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _is_handle_highlighted , p_id , p_secondary , success ) ) {
2021-08-22 03:52:44 +02:00
return success ;
2019-01-25 12:57:32 +01:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , false ) ;
2022-01-11 12:33:37 +01:00
return gizmo_plugin - > is_handle_highlighted ( this , p_id , p_secondary ) ;
2019-01-25 12:57:32 +01:00
}
2022-01-11 12:33:37 +01:00
Variant EditorNode3DGizmo : : get_handle_value ( int p_id , bool p_secondary ) const {
2021-08-22 03:52:44 +02:00
Variant value ;
2022-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _get_handle_value , p_id , p_secondary , value ) ) {
2021-08-22 03:52:44 +02:00
return value ;
2019-01-25 12:57:32 +01:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , Variant ( ) ) ;
2022-01-11 12:33:37 +01:00
return gizmo_plugin - > get_handle_value ( this , p_id , p_secondary ) ;
2018-07-25 00:08:49 +02:00
}
2023-01-09 02:35:27 +01:00
void EditorNode3DGizmo : : begin_handle_action ( int p_id , bool p_secondary ) {
if ( GDVIRTUAL_CALL ( _begin_handle_action , p_id , p_secondary ) ) {
return ;
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2023-01-09 02:35:27 +01:00
gizmo_plugin - > begin_handle_action ( this , p_id , p_secondary ) ;
}
2022-01-11 12:33:37 +01:00
void EditorNode3DGizmo : : set_handle ( int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
if ( GDVIRTUAL_CALL ( _set_handle , p_id , p_secondary , p_camera , p_point ) ) {
2019-01-25 12:57:32 +01:00
return ;
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2022-01-11 12:33:37 +01:00
gizmo_plugin - > set_handle ( this , p_id , p_secondary , p_camera , p_point ) ;
2018-07-25 00:08:49 +02:00
}
2022-01-11 12:33:37 +01:00
void EditorNode3DGizmo : : commit_handle ( int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
if ( GDVIRTUAL_CALL ( _commit_handle , p_id , p_secondary , p_restore , p_cancel ) ) {
2021-06-23 16:49:50 +02:00
return ;
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2022-01-11 12:33:37 +01:00
gizmo_plugin - > commit_handle ( this , p_id , p_secondary , p_restore , p_cancel ) ;
2021-06-23 16:49:50 +02:00
}
int EditorNode3DGizmo : : subgizmos_intersect_ray ( Camera3D * p_camera , const Vector2 & p_point ) const {
2021-08-22 03:52:44 +02:00
int id ;
if ( GDVIRTUAL_CALL ( _subgizmos_intersect_ray , p_camera , p_point , id ) ) {
return id ;
2021-06-23 16:49:50 +02:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , - 1 ) ;
2021-06-23 16:49:50 +02:00
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 {
2021-08-22 03:52:44 +02:00
TypedArray < Plane > frustum ;
frustum . resize ( p_frustum . size ( ) ) ;
for ( int i = 0 ; i < p_frustum . size ( ) ; i + + ) {
frustum [ i ] = p_frustum [ i ] ;
}
Vector < int > ret ;
if ( GDVIRTUAL_CALL ( _subgizmos_intersect_frustum , p_camera , frustum , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , Vector < int > ( ) ) ;
2021-06-23 16:49:50 +02:00
return gizmo_plugin - > subgizmos_intersect_frustum ( this , p_camera , p_frustum ) ;
}
Transform3D EditorNode3DGizmo : : get_subgizmo_transform ( int p_id ) const {
2021-08-22 03:52:44 +02:00
Transform3D ret ;
if ( GDVIRTUAL_CALL ( _get_subgizmo_transform , p_id , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( gizmo_plugin , Transform3D ( ) ) ;
2021-06-23 16:49:50 +02:00
return gizmo_plugin - > get_subgizmo_transform ( this , p_id ) ;
}
2021-08-07 09:15:57 +02:00
void EditorNode3DGizmo : : set_subgizmo_transform ( int p_id , Transform3D p_transform ) {
2021-08-22 03:52:44 +02:00
if ( GDVIRTUAL_CALL ( _set_subgizmo_transform , p_id , p_transform ) ) {
2019-01-25 12:57:32 +01:00
return ;
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2021-06-23 16:49:50 +02:00
gizmo_plugin - > set_subgizmo_transform ( this , p_id , p_transform ) ;
}
2021-08-07 09:15:57 +02:00
void EditorNode3DGizmo : : commit_subgizmos ( const Vector < int > & p_ids , const Vector < Transform3D > & p_restore , bool p_cancel ) {
2021-08-22 03:52:44 +02:00
TypedArray < Transform3D > restore ;
restore . resize ( p_restore . size ( ) ) ;
for ( int i = 0 ; i < p_restore . size ( ) ; i + + ) {
restore [ i ] = p_restore [ i ] ;
}
2021-06-23 16:49:50 +02:00
2021-08-22 03:52:44 +02:00
if ( GDVIRTUAL_CALL ( _commit_subgizmos , p_ids , restore , p_cancel ) ) {
2021-06-23 16:49:50 +02:00
return ;
}
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( gizmo_plugin ) ;
2021-06-23 16:49:50 +02:00
gizmo_plugin - > commit_subgizmos ( this , p_ids , p_restore , p_cancel ) ;
2018-07-25 00:08:49 +02:00
}
2022-09-08 18:38:33 +02:00
void EditorNode3DGizmo : : set_node_3d ( Node3D * p_node ) {
2018-07-25 00:08:49 +02:00
ERR_FAIL_NULL ( p_node ) ;
spatial_node = p_node ;
2016-02-28 03:10:44 +01:00
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : Instance : : create_instance ( Node3D * p_base , bool p_hidden ) {
2020-04-18 11:00:51 +02:00
instance = RS : : get_singleton ( ) - > instance_create2 ( mesh - > get_rid ( ) , p_base - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_attach_object_instance_id ( instance , p_base - > get_instance_id ( ) ) ;
2019-09-25 21:44:44 +02:00
if ( skin_reference . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_attach_skeleton ( instance , skin_reference - > get_skeleton ( ) ) ;
2019-09-25 21:44:44 +02:00
}
2020-05-14 16:41:43 +02:00
if ( extra_margin ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_extra_visibility_margin ( instance , 1 ) ;
2020-05-14 16:41:43 +02:00
}
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( instance , RS : : SHADOW_CASTING_SETTING_OFF ) ;
2020-03-26 22:49:16 +01:00
int layer = p_hidden ? 0 : 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( instance , layer ) ; //gizmos are 26
2021-04-20 18:40:24 +02:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( instance , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 22:58:44 +02:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( instance , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2015-10-08 20:00:40 +02:00
}
2021-12-03 09:34:08 +01:00
void EditorNode3DGizmo : : add_mesh ( const Ref < Mesh > & p_mesh , const Ref < Material > & p_material , const Transform3D & p_xform , const Ref < SkinReference > & p_skin_reference ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2021-12-03 09:34:08 +01:00
ERR_FAIL_COND_MSG ( ! p_mesh . is_valid ( ) , " EditorNode3DGizmo.add_mesh() requires a valid Mesh resource. " ) ;
2015-10-08 20:00:40 +02:00
Instance ins ;
ins . mesh = p_mesh ;
2019-09-19 00:46:32 +02:00
ins . skin_reference = p_skin_reference ;
2019-02-24 00:20:54 +01:00
ins . material = p_material ;
2021-06-23 16:49:50 +02:00
ins . xform = p_xform ;
2015-10-08 20:00:40 +02:00
if ( valid ) {
2018-07-25 00:08:49 +02:00
ins . create_instance ( spatial_node , hidden ) ;
2021-06-23 16:49:50 +02:00
RS : : get_singleton ( ) - > instance_set_transform ( ins . instance , spatial_node - > get_global_transform ( ) * ins . xform ) ;
2019-02-24 00:20:54 +01:00
if ( ins . material . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_geometry_set_material_override ( ins . instance , p_material - > get_rid ( ) ) ;
2019-02-24 00:20:54 +01:00
}
2015-10-08 20:00:40 +02:00
}
instances . push_back ( ins ) ;
}
2024-07-20 01:30:33 +02:00
void EditorNode3DGizmo : : _update_bvh ( ) {
ERR_FAIL_NULL ( spatial_node ) ;
Transform3D transform = spatial_node - > get_global_transform ( ) ;
float effective_icon_size = selectable_icon_size > 0.0f ? selectable_icon_size : 0.0f ;
Vector3 icon_size_vector3 = Vector3 ( effective_icon_size , effective_icon_size , effective_icon_size ) ;
AABB aabb ( spatial_node - > get_position ( ) - icon_size_vector3 * 100.0f , icon_size_vector3 * 200.0f ) ;
for ( const Vector3 & segment_end : collision_segments ) {
aabb . expand_to ( transform . xform ( segment_end ) ) ;
}
if ( collision_mesh . is_valid ( ) ) {
for ( const Face3 & face : collision_mesh - > get_faces ( ) ) {
aabb . expand_to ( transform . xform ( face . vertex [ 0 ] ) ) ;
aabb . expand_to ( transform . xform ( face . vertex [ 1 ] ) ) ;
aabb . expand_to ( transform . xform ( face . vertex [ 2 ] ) ) ;
}
}
Node3DEditor : : get_singleton ( ) - > update_gizmo_bvh_node (
bvh_node_id ,
aabb ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : add_lines ( const Vector < Vector3 > & p_lines , const Ref < Material > & p_material , bool p_billboard , const Color & p_modulate ) {
2021-02-28 22:15:52 +01:00
add_vertices ( p_lines , p_material , Mesh : : PRIMITIVE_LINES , p_billboard , p_modulate ) ;
}
void EditorNode3DGizmo : : add_vertices ( const Vector < Vector3 > & p_vertices , const Ref < Material > & p_material , Mesh : : PrimitiveType p_primitive_type , bool p_billboard , const Color & p_modulate ) {
if ( p_vertices . is_empty ( ) ) {
2019-12-05 19:27:57 +01:00
return ;
}
2015-10-08 20:00:40 +02:00
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2015-10-08 20:00:40 +02:00
Instance ins ;
2017-06-07 23:18:55 +02:00
Ref < ArrayMesh > mesh = memnew ( ArrayMesh ) ;
2015-10-08 20:00:40 +02:00
Array a ;
a . resize ( Mesh : : ARRAY_MAX ) ;
2021-02-28 22:15:52 +01:00
a [ Mesh : : ARRAY_VERTEX ] = p_vertices ;
2015-10-08 20:00:40 +02:00
2020-02-17 22:06:54 +01:00
Vector < Color > color ;
2021-02-28 22:15:52 +01:00
color . resize ( p_vertices . size ( ) ) ;
2015-10-08 20:00:40 +02:00
{
2020-02-17 22:06:54 +01:00
Color * w = color . ptrw ( ) ;
2021-02-28 22:15:52 +01:00
for ( int i = 0 ; i < p_vertices . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( is_selected ( ) ) {
2020-01-01 00:52:20 +01:00
w [ i ] = Color ( 1 , 1 , 1 , 0.8 ) * p_modulate ;
2020-05-14 16:41:43 +02:00
} else {
2020-01-01 00:52:20 +01:00
w [ i ] = Color ( 1 , 1 , 1 , 0.2 ) * p_modulate ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
}
}
a [ Mesh : : ARRAY_COLOR ] = color ;
2021-02-28 22:15:52 +01:00
mesh - > add_surface_from_arrays ( p_primitive_type , a ) ;
2015-10-08 20:00:40 +02:00
mesh - > surface_set_material ( 0 , p_material ) ;
if ( p_billboard ) {
float md = 0 ;
2021-02-28 22:15:52 +01:00
for ( int i = 0 ; i < p_vertices . size ( ) ; i + + ) {
md = MAX ( 0 , p_vertices [ i ] . length ( ) ) ;
2015-10-08 20:00:40 +02:00
}
if ( md ) {
2017-11-17 03:09:00 +01:00
mesh - > set_custom_aabb ( AABB ( Vector3 ( - md , - md , - md ) , Vector3 ( md , md , md ) * 2.0 ) ) ;
2015-10-08 20:00:40 +02:00
}
}
ins . mesh = mesh ;
if ( valid ) {
2018-07-25 00:08:49 +02:00
ins . create_instance ( spatial_node , hidden ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_transform ( ins . instance , spatial_node - > get_global_transform ( ) ) ;
2015-10-08 20:00:40 +02:00
}
instances . push_back ( ins ) ;
}
2021-06-21 05:30:19 +02:00
void EditorNode3DGizmo : : add_unscaled_billboard ( const Ref < Material > & p_material , real_t p_scale , const Color & p_modulate ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2015-10-08 20:00:40 +02:00
Instance ins ;
2022-01-11 16:27:39 +01:00
Vector < Vector3 > vs = {
Vector3 ( - p_scale , p_scale , 0 ) ,
Vector3 ( p_scale , p_scale , 0 ) ,
Vector3 ( p_scale , - p_scale , 0 ) ,
Vector3 ( - p_scale , - p_scale , 0 )
} ;
Vector < Vector2 > uv = {
Vector2 ( 0 , 0 ) ,
Vector2 ( 1 , 0 ) ,
Vector2 ( 1 , 1 ) ,
Vector2 ( 0 , 1 )
} ;
Vector < Color > colors = {
p_modulate ,
p_modulate ,
p_modulate ,
p_modulate
} ;
Vector < int > indices = { 0 , 1 , 2 , 0 , 2 , 3 } ;
2020-01-01 00:52:20 +01:00
2017-06-07 23:18:55 +02:00
Ref < ArrayMesh > mesh = memnew ( ArrayMesh ) ;
2015-10-08 20:00:40 +02:00
Array a ;
a . resize ( Mesh : : ARRAY_MAX ) ;
a [ Mesh : : ARRAY_VERTEX ] = vs ;
a [ Mesh : : ARRAY_TEX_UV ] = uv ;
2019-06-16 04:45:24 +02:00
a [ Mesh : : ARRAY_INDEX ] = indices ;
2020-01-01 00:52:20 +01:00
a [ Mesh : : ARRAY_COLOR ] = colors ;
2019-06-16 04:45:24 +02:00
mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , a ) ;
2015-10-08 20:00:40 +02:00
mesh - > surface_set_material ( 0 , p_material ) ;
2019-06-26 15:08:25 +02:00
float md = 0 ;
for ( int i = 0 ; i < vs . size ( ) ; i + + ) {
md = MAX ( 0 , vs [ i ] . length ( ) ) ;
}
if ( md ) {
mesh - > set_custom_aabb ( AABB ( Vector3 ( - md , - md , - md ) , Vector3 ( md , md , md ) * 2.0 ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-05-06 20:49:22 +02:00
selectable_icon_size = p_scale ;
2018-06-27 16:59:45 +02:00
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 ) ) ;
2018-05-06 20:49:22 +02:00
2015-10-08 20:00:40 +02:00
ins . mesh = mesh ;
if ( valid ) {
2018-07-25 00:08:49 +02:00
ins . create_instance ( spatial_node , hidden ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_transform ( ins . instance , spatial_node - > get_global_transform ( ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-06-27 16:59:45 +02:00
selectable_icon_size = p_scale ;
2018-05-06 20:49:22 +02:00
2015-10-08 20:00:40 +02:00
instances . push_back ( ins ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : add_collision_triangles ( const Ref < TriangleMesh > & p_tmesh ) {
2015-10-08 20:00:40 +02:00
collision_mesh = p_tmesh ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : add_collision_segments ( const Vector < Vector3 > & p_lines ) {
2015-10-08 20:00:40 +02:00
int from = collision_segments . size ( ) ;
collision_segments . resize ( from + p_lines . size ( ) ) ;
for ( int i = 0 ; i < p_lines . size ( ) ; i + + ) {
2018-07-25 03:11:03 +02:00
collision_segments . write [ from + i ] = p_lines [ i ] ;
2015-10-08 20:00:40 +02:00
}
}
2021-06-23 16:49:50 +02:00
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 ) {
2015-10-08 20:00:40 +02:00
billboard_handle = p_billboard ;
2020-05-14 16:41:43 +02:00
if ( ! is_selected ( ) | | ! is_editable ( ) ) {
2015-10-08 20:00:40 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
2022-11-01 09:25:13 +01:00
ERR_FAIL_NULL ( spatial_node ) ;
Vector < Vector3 > & handle_list = p_secondary ? secondary_handles : handles ;
Vector < int > & id_list = p_secondary ? secondary_handle_ids : handle_ids ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
if ( p_ids . is_empty ( ) ) {
2022-11-01 09:25:13 +01:00
ERR_FAIL_COND_MSG ( ! id_list . is_empty ( ) , " IDs must be provided for all handles, as handles with IDs already exist. " ) ;
2021-06-23 16:49:50 +02:00
} else {
2022-11-01 09:25:13 +01:00
ERR_FAIL_COND_MSG ( p_handles . size ( ) ! = p_ids . size ( ) , " The number of IDs should be the same as the number of handles. " ) ;
2021-06-23 16:49:50 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
bool is_current_hover_gizmo = Node3DEditor : : get_singleton ( ) - > get_current_hover_gizmo ( ) = = this ;
2022-01-11 12:33:37 +01:00
bool current_hover_handle_secondary ;
int current_hover_handle = Node3DEditor : : get_singleton ( ) - > get_current_hover_gizmo_handle ( current_hover_handle_secondary ) ;
2021-06-23 16:49:50 +02:00
Instance ins ;
2017-06-07 23:18:55 +02:00
Ref < ArrayMesh > mesh = memnew ( ArrayMesh ) ;
2015-10-08 20:00:40 +02:00
Array a ;
2020-03-27 19:21:27 +01:00
a . resize ( RS : : ARRAY_MAX ) ;
a [ RS : : ARRAY_VERTEX ] = p_handles ;
2020-02-17 22:06:54 +01:00
Vector < Color > colors ;
2015-10-08 20:00:40 +02:00
{
colors . resize ( p_handles . size ( ) ) ;
2020-02-17 22:06:54 +01:00
Color * w = colors . ptrw ( ) ;
2015-10-08 20:00:40 +02:00
for ( int i = 0 ; i < p_handles . size ( ) ; i + + ) {
2024-03-17 14:15:59 +01:00
int id = p_ids . is_empty ( ) ? i : p_ids [ i ] ;
2015-10-08 20:00:40 +02:00
Color col ( 1 , 1 , 1 , 1 ) ;
2024-03-17 14:15:59 +01:00
if ( is_handle_highlighted ( id , p_secondary ) ) {
2017-11-21 01:36:32 +01:00
col = Color ( 0 , 0 , 1 , 0.9 ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-21 01:36:32 +01:00
2022-01-11 12:33:37 +01:00
if ( ! is_current_hover_gizmo | | current_hover_handle ! = id | | p_secondary ! = current_hover_handle_secondary ) {
2017-11-21 01:36:32 +01:00
col . a = 0.8 ;
2020-05-14 16:41:43 +02:00
}
2017-11-21 01:36:32 +01:00
2015-10-08 20:00:40 +02:00
w [ i ] = col ;
}
}
2020-03-27 19:21:27 +01:00
a [ RS : : ARRAY_COLOR ] = colors ;
2016-11-10 03:55:06 +01:00
mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_POINTS , a ) ;
2018-07-25 00:08:49 +02:00
mesh - > surface_set_material ( 0 , p_material ) ;
2015-10-08 20:00:40 +02:00
if ( p_billboard ) {
float md = 0 ;
for ( int i = 0 ; i < p_handles . size ( ) ; i + + ) {
md = MAX ( 0 , p_handles [ i ] . length ( ) ) ;
}
if ( md ) {
2017-11-17 03:09:00 +01:00
mesh - > set_custom_aabb ( AABB ( Vector3 ( - md , - md , - md ) , Vector3 ( md , md , md ) * 2.0 ) ) ;
2015-10-08 20:00:40 +02:00
}
}
ins . mesh = mesh ;
ins . extra_margin = true ;
if ( valid ) {
2018-07-25 00:08:49 +02:00
ins . create_instance ( spatial_node , hidden ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_transform ( ins . instance , spatial_node - > get_global_transform ( ) ) ;
2015-10-08 20:00:40 +02:00
}
instances . push_back ( ins ) ;
2021-06-23 16:49:50 +02:00
2022-11-01 09:25:13 +01:00
int current_size = handle_list . size ( ) ;
handle_list . resize ( current_size + p_handles . size ( ) ) ;
2021-06-23 16:49:50 +02:00
for ( int i = 0 ; i < p_handles . size ( ) ; i + + ) {
2022-11-01 09:25:13 +01:00
handle_list . write [ current_size + i ] = p_handles [ i ] ;
2021-06-23 16:49:50 +02:00
}
if ( ! p_ids . is_empty ( ) ) {
2022-11-01 09:25:13 +01:00
current_size = id_list . size ( ) ;
id_list . resize ( current_size + p_ids . size ( ) ) ;
2021-06-23 16:49:50 +02:00
for ( int i = 0 ; i < p_ids . size ( ) ; i + + ) {
2022-11-01 09:25:13 +01:00
id_list . write [ current_size + i ] = p_ids [ i ] ;
2015-10-08 20:00:40 +02:00
}
}
}
2022-04-28 11:35:39 +02:00
void EditorNode3DGizmo : : add_solid_box ( const Ref < Material > & p_material , Vector3 p_size , Vector3 p_position , const Transform3D & p_xform ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2017-08-30 00:50:45 +02:00
2020-12-04 16:39:45 +01:00
BoxMesh box_mesh ;
box_mesh . set_size ( p_size ) ;
2018-02-03 18:17:57 +01:00
2020-12-04 16:39:45 +01:00
Array arrays = box_mesh . surface_get_arrays ( 0 ) ;
2020-03-27 19:21:27 +01:00
PackedVector3Array vertex = arrays [ RS : : ARRAY_VERTEX ] ;
2020-02-17 22:06:54 +01:00
Vector3 * w = vertex . ptrw ( ) ;
2018-02-03 18:17:57 +01:00
for ( int i = 0 ; i < vertex . size ( ) ; + + i ) {
w [ i ] + = p_position ;
}
2020-03-27 19:21:27 +01:00
arrays [ RS : : ARRAY_VERTEX ] = vertex ;
2018-02-03 18:17:57 +01:00
2017-08-28 08:21:54 +02:00
Ref < ArrayMesh > m = memnew ( ArrayMesh ) ;
2020-12-04 16:39:45 +01:00
m - > add_surface_from_arrays ( box_mesh . surface_get_primitive_type ( 0 ) , arrays ) ;
2021-06-23 16:49:50 +02:00
add_mesh ( m , p_material , p_xform ) ;
2017-08-28 08:21:54 +02:00
}
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmo : : intersect_frustum ( const Camera3D * p_camera , const Vector < Plane > & p_frustum ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( spatial_node , false ) ;
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND_V ( ! valid , false ) ;
2020-05-14 16:41:43 +02:00
if ( hidden & & ! gizmo_plugin - > is_selectable_when_hidden ( ) ) {
2018-07-25 00:08:49 +02:00
return false ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
2018-05-06 20:49:22 +02:00
if ( selectable_icon_size > 0.0f ) {
Vector3 origin = spatial_node - > get_global_transform ( ) . get_origin ( ) ;
2015-10-08 20:00:40 +02:00
const Plane * p = p_frustum . ptr ( ) ;
int fc = p_frustum . size ( ) ;
2018-05-06 20:49:22 +02:00
bool any_out = false ;
2015-10-08 20:00:40 +02:00
2018-05-06 20:49:22 +02:00
for ( int j = 0 ; j < fc ; j + + ) {
if ( p [ j ] . is_point_over ( origin ) ) {
any_out = true ;
break ;
}
}
2019-06-26 15:08:25 +02:00
return ! any_out ;
2018-05-06 20:49:22 +02:00
}
2015-10-08 20:00:40 +02:00
2018-05-06 20:49:22 +02:00
if ( collision_segments . size ( ) ) {
const Plane * p = p_frustum . ptr ( ) ;
int fc = p_frustum . size ( ) ;
2015-10-08 20:00:40 +02:00
2018-05-06 20:49:22 +02:00
int vc = collision_segments . size ( ) ;
const Vector3 * vptr = collision_segments . ptr ( ) ;
2020-10-17 07:08:21 +02:00
Transform3D t = spatial_node - > get_global_transform ( ) ;
2018-05-06 20:49:22 +02:00
bool any_out = false ;
for ( int j = 0 ; j < fc ; j + + ) {
for ( int i = 0 ; i < vc ; i + + ) {
Vector3 v = t . xform ( vptr [ i ] ) ;
if ( p [ j ] . is_point_over ( v ) ) {
2015-10-08 20:00:40 +02:00
any_out = true ;
break ;
}
}
2020-05-14 16:41:43 +02:00
if ( any_out ) {
2018-05-06 20:49:22 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
}
2020-05-14 16:41:43 +02:00
if ( ! any_out ) {
2018-05-06 20:49:22 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
}
2018-05-06 20:49:22 +02:00
if ( collision_mesh . is_valid ( ) ) {
2020-10-17 07:08:21 +02:00
Transform3D t = spatial_node - > get_global_transform ( ) ;
2017-09-12 15:06:13 +02:00
2018-05-06 20:49:22 +02:00
Vector3 mesh_scale = t . get_basis ( ) . get_scale ( ) ;
t . orthonormalize ( ) ;
2017-09-12 15:06:13 +02:00
2020-10-17 07:08:21 +02:00
Transform3D it = t . affine_inverse ( ) ;
2017-09-12 15:06:13 +02:00
2018-05-06 20:49:22 +02:00
Vector < Plane > transformed_frustum ;
2021-06-23 16:49:50 +02:00
int plane_count = p_frustum . size ( ) ;
transformed_frustum . resize ( plane_count ) ;
2017-09-12 15:06:13 +02:00
2021-06-23 16:49:50 +02:00
for ( int i = 0 ; i < plane_count ; i + + ) {
transformed_frustum . write [ i ] = it . xform ( p_frustum [ i ] ) ;
2017-09-12 15:06:13 +02:00
}
2021-06-23 16:49:50 +02:00
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 ) ) {
2017-09-12 15:06:13 +02:00
return true ;
2018-05-06 20:49:22 +02:00
}
2017-09-12 15:06:13 +02:00
}
2015-10-08 20:00:40 +02:00
return false ;
}
2022-01-11 12:33:37 +01:00
void EditorNode3DGizmo : : handles_intersect_ray ( Camera3D * p_camera , const Vector2 & p_point , bool p_shift_pressed , int & r_id , bool & r_secondary ) {
2021-06-23 16:49:50 +02:00
r_id = - 1 ;
2022-01-11 12:33:37 +01:00
r_secondary = false ;
2015-10-08 20:00:40 +02:00
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2021-06-23 16:49:50 +02:00
ERR_FAIL_COND ( ! valid ) ;
if ( hidden ) {
return ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
Transform3D camera_xform = p_camera - > get_global_transform ( ) ;
Transform3D t = spatial_node - > get_global_transform ( ) ;
if ( billboard_handle ) {
2022-05-03 14:50:35 +02:00
t . set_look_at ( t . origin , t . origin - camera_xform . basis . get_column ( 2 ) , camera_xform . basis . get_column ( 1 ) ) ;
2021-06-23 16:49:50 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
float min_d = 1e20 ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
for ( int i = 0 ; i < secondary_handles . size ( ) ; i + + ) {
Vector3 hpos = t . xform ( secondary_handles [ i ] ) ;
Vector2 p = p_camera - > unproject_position ( hpos ) ;
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
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 ] ;
2015-10-08 20:00:40 +02:00
}
2022-01-11 12:33:37 +01:00
r_secondary = true ;
2015-10-08 20:00:40 +02:00
}
}
2021-06-23 16:49:50 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
if ( r_id ! = - 1 & & p_shift_pressed ) {
return ;
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
min_d = 1e20 ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
for ( int i = 0 ; i < handles . size ( ) ; i + + ) {
Vector3 hpos = t . xform ( handles [ i ] ) ;
Vector2 p = p_camera - > unproject_position ( hpos ) ;
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
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 ] ;
2015-10-08 20:00:40 +02:00
}
2022-01-11 12:33:37 +01:00
r_secondary = false ;
2015-10-08 20:00:40 +02:00
}
}
2021-06-23 16:49:50 +02:00
}
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
bool EditorNode3DGizmo : : intersect_ray ( Camera3D * p_camera , const Point2 & p_point , Vector3 & r_pos , Vector3 & r_normal ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( spatial_node , false ) ;
2021-06-23 16:49:50 +02:00
ERR_FAIL_COND_V ( ! valid , false ) ;
if ( hidden & & ! gizmo_plugin - > is_selectable_when_hidden ( ) ) {
return false ;
2015-10-08 20:00:40 +02:00
}
2018-05-06 20:49:22 +02:00
if ( selectable_icon_size > 0.0f ) {
2020-10-17 07:08:21 +02:00
Transform3D t = spatial_node - > get_global_transform ( ) ;
2019-01-25 00:52:28 +01:00
Vector3 camera_position = p_camera - > get_camera_transform ( ) . origin ;
2021-07-16 19:19:55 +02:00
if ( ! camera_position . is_equal_approx ( t . origin ) ) {
2021-01-30 10:22:20 +01:00
t . set_look_at ( t . origin , camera_position ) ;
2019-01-25 00:52:28 +01:00
}
2018-05-06 20:49:22 +02:00
float scale = t . origin . distance_to ( p_camera - > get_camera_transform ( ) . origin ) ;
2020-03-26 22:49:16 +01:00
if ( p_camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ) {
2018-06-27 16:59:45 +02:00
float aspect = p_camera - > get_viewport ( ) - > get_visible_rect ( ) . size . aspect ( ) ;
float size = p_camera - > get_size ( ) ;
scale = size / aspect ;
2018-05-06 20:49:22 +02:00
}
Point2 center = p_camera - > unproject_position ( t . origin ) ;
2020-10-17 07:08:21 +02:00
Transform3D orig_camera_transform = p_camera - > get_camera_transform ( ) ;
2018-05-06 20:49:22 +02:00
2021-07-16 19:19:55 +02:00
if ( ! orig_camera_transform . origin . is_equal_approx ( t . origin ) & &
2022-05-03 14:50:35 +02:00
ABS ( orig_camera_transform . basis . get_column ( Vector3 : : AXIS_Z ) . dot ( Vector3 ( 0 , 1 , 0 ) ) ) < 0.99 ) {
2021-01-30 10:22:20 +01:00
p_camera - > look_at ( t . origin ) ;
2019-01-25 00:52:28 +01:00
}
2019-05-07 17:36:35 +02:00
2018-05-06 20:49:22 +02:00
Vector3 c0 = t . xform ( Vector3 ( selectable_icon_size , selectable_icon_size , 0 ) * scale ) ;
Vector3 c1 = t . xform ( Vector3 ( - selectable_icon_size , - selectable_icon_size , 0 ) * scale ) ;
Point2 p0 = p_camera - > unproject_position ( c0 ) ;
Point2 p1 = p_camera - > unproject_position ( c1 ) ;
2019-01-25 00:52:28 +01:00
p_camera - > set_global_transform ( orig_camera_transform ) ;
2018-05-06 20:49:22 +02:00
2019-05-07 17:36:35 +02:00
Rect2 rect ( p0 , ( p1 - p0 ) . abs ( ) ) ;
2018-05-06 20:49:22 +02:00
rect . set_position ( center - rect . get_size ( ) / 2.0 ) ;
if ( rect . has_point ( p_point ) ) {
2018-08-11 23:07:00 +02:00
r_pos = t . origin ;
r_normal = - p_camera - > project_ray_normal ( p_point ) ;
2018-05-06 20:49:22 +02:00
return true ;
}
}
2015-10-08 20:00:40 +02:00
if ( collision_segments . size ( ) ) {
2022-05-03 14:50:35 +02:00
Plane camp ( - p_camera - > get_transform ( ) . basis . get_column ( 2 ) . normalized ( ) , p_camera - > get_transform ( ) . origin ) ;
2015-10-08 20:00:40 +02:00
int vc = collision_segments . size ( ) ;
const Vector3 * vptr = collision_segments . ptr ( ) ;
2020-10-17 07:08:21 +02:00
Transform3D t = spatial_node - > get_global_transform ( ) ;
2015-10-08 20:00:40 +02:00
if ( billboard_handle ) {
2022-05-03 14:50:35 +02:00
t . set_look_at ( t . origin , t . origin - p_camera - > get_transform ( ) . basis . get_column ( 2 ) , p_camera - > get_transform ( ) . basis . get_column ( 1 ) ) ;
2015-10-08 20:00:40 +02:00
}
Vector3 cp ;
float cpd = 1e20 ;
for ( int i = 0 ; i < vc / 2 ; i + + ) {
Vector3 a = t . xform ( vptr [ i * 2 + 0 ] ) ;
Vector3 b = t . xform ( vptr [ i * 2 + 1 ] ) ;
Vector2 s [ 2 ] ;
s [ 0 ] = p_camera - > unproject_position ( a ) ;
s [ 1 ] = p_camera - > unproject_position ( b ) ;
2020-05-25 19:20:45 +02:00
Vector2 p = Geometry2D : : get_closest_point_to_segment ( p_point , s ) ;
2015-10-08 20:00:40 +02:00
float pd = p . distance_to ( p_point ) ;
if ( pd < cpd ) {
float d = s [ 0 ] . distance_to ( s [ 1 ] ) ;
Vector3 tcp ;
if ( d > 0 ) {
float d2 = s [ 0 ] . distance_to ( p ) / d ;
tcp = a + ( b - a ) * d2 ;
} else {
tcp = a ;
}
2020-12-16 13:40:42 +01:00
if ( camp . distance_to ( tcp ) < p_camera - > get_near ( ) ) {
2015-10-08 20:00:40 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
cp = tcp ;
cpd = pd ;
}
}
if ( cpd < 8 ) {
r_pos = cp ;
r_normal = - p_camera - > project_ray_normal ( p_point ) ;
return true ;
}
}
if ( collision_mesh . is_valid ( ) ) {
2020-10-17 07:08:21 +02:00
Transform3D gt = spatial_node - > get_global_transform ( ) ;
2015-10-08 20:00:40 +02:00
if ( billboard_handle ) {
2022-05-03 14:50:35 +02:00
gt . set_look_at ( gt . origin , gt . origin - p_camera - > get_transform ( ) . basis . get_column ( 2 ) , p_camera - > get_transform ( ) . basis . get_column ( 1 ) ) ;
2015-10-08 20:00:40 +02:00
}
2020-10-17 07:08:21 +02:00
Transform3D ai = gt . affine_inverse ( ) ;
2015-10-08 20:00:40 +02:00
Vector3 ray_from = ai . xform ( p_camera - > project_ray_origin ( p_point ) ) ;
Vector3 ray_dir = ai . basis . xform ( p_camera - > project_ray_normal ( p_point ) ) . normalized ( ) ;
Vector3 rpos , rnorm ;
if ( collision_mesh - > intersect_ray ( ray_from , ray_dir , rpos , rnorm ) ) {
r_pos = gt . xform ( rpos ) ;
r_normal = gt . basis . xform ( rnorm ) . normalized ( ) ;
return true ;
}
}
return false ;
}
2021-06-23 16:49:50 +02:00
bool EditorNode3DGizmo : : is_subgizmo_selected ( int p_id ) const {
Node3DEditor * ed = Node3DEditor : : get_singleton ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( ed , false ) ;
2021-06-23 16:49:50 +02:00
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 ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL_V ( ed , ret ) ;
2021-06-23 16:49:50 +02:00
if ( ed - > is_current_selected_gizmo ( this ) ) {
ret = ed - > get_subgizmo_selection ( ) ;
}
return ret ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : create ( ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( valid ) ;
valid = true ;
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2018-07-25 00:08:49 +02:00
instances . write [ i ] . create_instance ( spatial_node , hidden ) ;
2015-10-08 20:00:40 +02:00
}
2024-07-20 01:30:33 +02:00
bvh_node_id = Node3DEditor : : get_singleton ( ) - > insert_gizmo_bvh_node (
spatial_node ,
AABB ( spatial_node - > get_position ( ) , Vector3 ( 0 , 0 , 0 ) ) ) ;
2015-10-08 20:00:40 +02:00
transform ( ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : transform ( ) {
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! valid ) ;
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2021-06-23 16:49:50 +02:00
RS : : get_singleton ( ) - > instance_set_transform ( instances [ i ] . instance , spatial_node - > get_global_transform ( ) * instances [ i ] . xform ) ;
2015-10-08 20:00:40 +02:00
}
2024-07-20 01:30:33 +02:00
_update_bvh ( ) ;
2015-10-08 20:00:40 +02:00
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : free ( ) {
2022-12-12 18:42:37 +01:00
ERR_FAIL_NULL ( RenderingServer : : get_singleton ( ) ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( spatial_node ) ;
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! valid ) ;
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( instances [ i ] . instance . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( instances [ i ] . instance ) ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 03:11:03 +02:00
instances . write [ i ] . instance = RID ( ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
clear ( ) ;
2024-07-20 01:30:33 +02:00
Node3DEditor : : get_singleton ( ) - > remove_gizmo_bvh_node ( bvh_node_id ) ;
bvh_node_id = DynamicBVH : : ID ( ) ;
2015-10-08 20:00:40 +02:00
valid = false ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : set_hidden ( bool p_hidden ) {
2018-07-25 00:08:49 +02:00
hidden = p_hidden ;
2020-03-26 22:49:16 +01:00
int layer = hidden ? 0 : 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < instances . size ( ) ; + + i ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( instances [ i ] . instance , layer ) ;
2017-08-26 05:40:45 +02:00
}
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : set_plugin ( EditorNode3DGizmoPlugin * p_plugin ) {
2018-07-25 00:08:49 +02:00
gizmo_plugin = p_plugin ;
2017-08-26 05:40:45 +02:00
}
2020-03-26 22:49:16 +01:00
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 ) ) ) ;
2021-06-23 16:49:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_mesh " , " mesh " , " material " , " transform " , " skeleton " ) , & EditorNode3DGizmo : : add_mesh , DEFVAL ( Variant ( ) ) , DEFVAL ( Transform3D ( ) ) , DEFVAL ( Ref < SkinReference > ( ) ) ) ;
2020-03-26 22:49:16 +01:00
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 ) ) ) ;
2021-06-23 16:49:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_handles " , " handles " , " material " , " ids " , " billboard " , " secondary " ) , & EditorNode3DGizmo : : add_handles , DEFVAL ( false ) , DEFVAL ( false ) ) ;
2022-09-08 18:38:33 +02:00
ClassDB : : bind_method ( D_METHOD ( " set_node_3d " , " node " ) , & EditorNode3DGizmo : : _set_node_3d ) ;
ClassDB : : bind_method ( D_METHOD ( " get_node_3d " ) , & EditorNode3DGizmo : : get_node_3d ) ;
2020-03-26 22:49:16 +01:00
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 ) ;
2021-10-08 23:26:13 +02:00
ClassDB : : bind_method ( D_METHOD ( " is_subgizmo_selected " , " id " ) , & EditorNode3DGizmo : : is_subgizmo_selected ) ;
2021-06-23 16:49:50 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_subgizmo_selection " ) , & EditorNode3DGizmo : : get_subgizmo_selection ) ;
2017-03-05 16:44:50 +01:00
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _redraw ) ;
2022-01-11 12:33:37 +01:00
GDVIRTUAL_BIND ( _get_handle_name , " id " , " secondary " ) ;
GDVIRTUAL_BIND ( _is_handle_highlighted , " id " , " secondary " ) ;
2017-08-29 07:15:46 +02:00
2022-01-11 12:33:37 +01:00
GDVIRTUAL_BIND ( _get_handle_value , " id " , " secondary " ) ;
2024-01-06 15:41:50 +01:00
GDVIRTUAL_BIND ( _begin_handle_action , " id " , " secondary " ) ;
2022-01-11 12:33:37 +01:00
GDVIRTUAL_BIND ( _set_handle , " id " , " secondary " , " camera " , " point " ) ;
GDVIRTUAL_BIND ( _commit_handle , " id " , " secondary " , " restore " , " cancel " ) ;
2021-06-23 16:49:50 +02:00
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _subgizmos_intersect_ray , " camera " , " point " ) ;
GDVIRTUAL_BIND ( _subgizmos_intersect_frustum , " camera " , " frustum " ) ;
GDVIRTUAL_BIND ( _set_subgizmo_transform , " id " , " transform " ) ;
GDVIRTUAL_BIND ( _get_subgizmo_transform , " id " ) ;
GDVIRTUAL_BIND ( _commit_subgizmos , " ids " , " restores " , " cancel " ) ;
2016-02-28 03:10:44 +01:00
}
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
EditorNode3DGizmo : : EditorNode3DGizmo ( ) {
2015-10-08 20:00:40 +02:00
valid = false ;
billboard_handle = false ;
2018-07-25 00:08:49 +02:00
hidden = false ;
selected = false ;
2020-04-02 01:20:12 +02:00
spatial_node = nullptr ;
gizmo_plugin = nullptr ;
2018-09-26 11:22:59 +02:00
selectable_icon_size = - 1.0f ;
2015-10-08 20:00:40 +02:00
}
2020-03-26 22:49:16 +01:00
EditorNode3DGizmo : : ~ EditorNode3DGizmo ( ) {
2020-05-14 16:41:43 +02:00
if ( gizmo_plugin ! = nullptr ) {
2020-04-02 01:20:12 +02:00
gizmo_plugin - > unregister_gizmo ( this ) ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
clear ( ) ;
}
2021-06-23 16:49:50 +02:00
/////
void EditorNode3DGizmoPlugin : : create_material ( const String & p_name , const Color & p_color , bool p_billboard , bool p_on_top , bool p_use_vertex_color ) {
2022-03-06 21:39:19 +01:00
Color instantiated_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/instantiated " ) ;
2021-06-23 16:49:50 +02:00
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 ) ;
2023-09-27 00:45:57 +02:00
material - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_FOG , true ) ;
2021-06-23 16:49:50 +02:00
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 ) {
2022-03-06 21:39:19 +01:00
Color instantiated_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/instantiated " ) ;
2021-06-23 16:49:50 +02:00
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 ) {
2024-04-25 20:26:32 +02:00
color . r * = 0.6 ;
color . g * = 0.6 ;
color . b * = 0.6 ;
2021-06-23 16:49:50 +02:00
}
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 ) ;
2023-09-27 00:45:57 +02:00
icon - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_FOG , true ) ;
2024-04-25 20:26:32 +02:00
icon - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA_SCISSOR ) ;
icon - > set_alpha_scissor_threshold ( 0.1 ) ;
2021-06-23 16:49:50 +02:00
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 ) ;
2024-07-26 11:52:26 +02:00
Ref < Texture2D > handle_t = p_icon . is_valid ( ) ? p_icon : EditorNode : : get_singleton ( ) - > get_editor_theme ( ) - > get_icon ( SNAME ( " Editor3DHandle " ) , EditorStringName ( EditorIcons ) ) ;
2021-06-23 16:49:50 +02:00
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 ) ;
2023-09-27 00:45:57 +02:00
handle_material - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_FOG , true ) ;
2021-06-23 16:49:50 +02:00
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 > ( ) ) ;
2024-01-19 13:21:39 +01:00
ERR_FAIL_COND_V ( materials [ p_name ] . is_empty ( ) , Ref < StandardMaterial3D > ( ) ) ;
2021-06-23 16:49:50 +02:00
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 ] ;
2024-04-03 21:05:17 +02:00
bool on_top_mat = mat - > get_flag ( StandardMaterial3D : : FLAG_DISABLE_DEPTH_TEST ) ;
if ( ! on_top_mat & & current_state = = ON_TOP & & p_gizmo - > is_selected ( ) ) {
mat = mat - > duplicate ( ) ;
2021-06-23 16:49:50 +02:00
mat - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_DEPTH_TEST , true ) ;
}
return mat ;
}
String EditorNode3DGizmoPlugin : : get_gizmo_name ( ) const {
2022-10-07 13:55:51 +02:00
String ret ;
if ( GDVIRTUAL_CALL ( _get_gizmo_name , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
2021-09-17 00:26:51 +02:00
WARN_PRINT_ONCE ( " A 3D editor gizmo has no name defined (it will appear as \" Unnamed Gizmo \" in the \" View > Gizmos \" menu). To resolve this, override the `_get_gizmo_name()` function to return a String in the script that extends EditorNode3DGizmoPlugin. " ) ;
return TTR ( " Unnamed Gizmo " ) ;
2021-06-23 16:49:50 +02:00
}
int EditorNode3DGizmoPlugin : : get_priority ( ) const {
2022-10-07 13:55:51 +02:00
int ret ;
if ( GDVIRTUAL_CALL ( _get_priority , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
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 ) ;
2022-09-08 18:38:33 +02:00
ref - > set_node_3d ( p_spatial ) ;
2021-06-23 16:49:50 +02:00
ref - > set_hidden ( current_state = = HIDDEN ) ;
2015-10-08 20:00:40 +02:00
2024-07-24 16:27:52 +02:00
current_gizmos . insert ( ref . ptr ( ) ) ;
2021-06-23 16:49:50 +02:00
return ref ;
}
void EditorNode3DGizmoPlugin : : _bind_methods ( ) {
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 > ( ) ) ) ;
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _has_gizmo , " for_node_3d " ) ;
GDVIRTUAL_BIND ( _create_gizmo , " for_node_3d " ) ;
2021-06-23 16:49:50 +02:00
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _get_gizmo_name ) ;
GDVIRTUAL_BIND ( _get_priority ) ;
GDVIRTUAL_BIND ( _can_be_hidden ) ;
GDVIRTUAL_BIND ( _is_selectable_when_hidden ) ;
2021-06-23 16:49:50 +02:00
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _redraw , " gizmo " ) ;
2022-01-11 12:33:37 +01:00
GDVIRTUAL_BIND ( _get_handle_name , " gizmo " , " handle_id " , " secondary " ) ;
GDVIRTUAL_BIND ( _is_handle_highlighted , " gizmo " , " handle_id " , " secondary " ) ;
GDVIRTUAL_BIND ( _get_handle_value , " gizmo " , " handle_id " , " secondary " ) ;
2021-06-23 16:49:50 +02:00
2024-01-06 15:41:50 +01:00
GDVIRTUAL_BIND ( _begin_handle_action , " gizmo " , " handle_id " , " secondary " ) ;
2022-01-11 12:33:37 +01:00
GDVIRTUAL_BIND ( _set_handle , " gizmo " , " handle_id " , " secondary " , " camera " , " screen_pos " ) ;
GDVIRTUAL_BIND ( _commit_handle , " gizmo " , " handle_id " , " secondary " , " restore " , " cancel " ) ;
2021-06-23 16:49:50 +02:00
2021-08-22 03:52:44 +02:00
GDVIRTUAL_BIND ( _subgizmos_intersect_ray , " gizmo " , " camera " , " screen_pos " ) ;
GDVIRTUAL_BIND ( _subgizmos_intersect_frustum , " gizmo " , " camera " , " frustum_planes " ) ;
GDVIRTUAL_BIND ( _get_subgizmo_transform , " gizmo " , " subgizmo_id " ) ;
GDVIRTUAL_BIND ( _set_subgizmo_transform , " gizmo " , " subgizmo_id " , " transform " ) ;
GDVIRTUAL_BIND ( _commit_subgizmos , " gizmo " , " ids " , " restores " , " cancel " ) ;
2021-06-23 16:49:50 +02:00
}
bool EditorNode3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2022-10-18 18:47:44 +02:00
bool success = false ;
GDVIRTUAL_CALL ( _has_gizmo , p_spatial , success ) ;
return success ;
2021-06-23 16:49:50 +02:00
}
Ref < EditorNode3DGizmo > EditorNode3DGizmoPlugin : : create_gizmo ( Node3D * p_spatial ) {
2021-08-22 03:52:44 +02:00
Ref < EditorNode3DGizmo > ret ;
if ( GDVIRTUAL_CALL ( _create_gizmo , p_spatial , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
Ref < EditorNode3DGizmo > ref ;
if ( has_gizmo ( p_spatial ) ) {
ref . instantiate ( ) ;
}
return ref ;
}
bool EditorNode3DGizmoPlugin : : can_be_hidden ( ) const {
2022-10-18 18:47:44 +02:00
bool ret = true ;
GDVIRTUAL_CALL ( _can_be_hidden , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
bool EditorNode3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2022-10-18 18:47:44 +02:00
bool ret = false ;
GDVIRTUAL_CALL ( _is_selectable_when_hidden , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
void EditorNode3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2021-08-22 03:52:44 +02:00
GDVIRTUAL_CALL ( _redraw , p_gizmo ) ;
2021-06-23 16:49:50 +02:00
}
2022-01-11 12:33:37 +01:00
bool EditorNode3DGizmoPlugin : : is_handle_highlighted ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-29 11:53:28 +02:00
bool ret = false ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _is_handle_highlighted , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
2022-01-11 12:33:37 +01:00
String EditorNode3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-08-22 03:52:44 +02:00
String ret ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _get_handle_name , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
2022-01-11 12:33:37 +01:00
Variant EditorNode3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-08-22 03:52:44 +02:00
Variant ret ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _get_handle_value , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
2023-01-09 02:35:27 +01:00
void EditorNode3DGizmoPlugin : : begin_handle_action ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) {
GDVIRTUAL_CALL ( _begin_handle_action , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary ) ;
}
2022-01-11 12:33:37 +01:00
void EditorNode3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
GDVIRTUAL_CALL ( _set_handle , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , p_camera , p_point ) ;
2021-06-23 16:49:50 +02:00
}
2022-01-11 12:33:37 +01:00
void EditorNode3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
GDVIRTUAL_CALL ( _commit_handle , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , p_restore , p_cancel ) ;
2021-06-23 16:49:50 +02:00
}
int EditorNode3DGizmoPlugin : : subgizmos_intersect_ray ( const EditorNode3DGizmo * p_gizmo , Camera3D * p_camera , const Vector2 & p_point ) const {
2022-09-29 11:53:28 +02:00
int ret = - 1 ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _subgizmos_intersect_ray , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_camera , p_point , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
Vector < int > EditorNode3DGizmoPlugin : : subgizmos_intersect_frustum ( const EditorNode3DGizmo * p_gizmo , const Camera3D * p_camera , const Vector < Plane > & p_frustum ) const {
2022-10-29 09:15:28 +02:00
TypedArray < Plane > frustum ;
2021-08-22 03:52:44 +02:00
frustum . resize ( p_frustum . size ( ) ) ;
for ( int i = 0 ; i < p_frustum . size ( ) ; i + + ) {
frustum [ i ] = p_frustum [ i ] ;
}
Vector < int > ret ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _subgizmos_intersect_frustum , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_camera , frustum , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
Transform3D EditorNode3DGizmoPlugin : : get_subgizmo_transform ( const EditorNode3DGizmo * p_gizmo , int p_id ) const {
2021-08-22 03:52:44 +02:00
Transform3D ret ;
2022-10-18 18:47:44 +02:00
GDVIRTUAL_CALL ( _get_subgizmo_transform , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , ret ) ;
return ret ;
2021-06-23 16:49:50 +02:00
}
2021-08-07 09:15:57 +02:00
void EditorNode3DGizmoPlugin : : set_subgizmo_transform ( const EditorNode3DGizmo * p_gizmo , int p_id , Transform3D p_transform ) {
2021-08-22 03:52:44 +02:00
GDVIRTUAL_CALL ( _set_subgizmo_transform , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_transform ) ;
2021-06-23 16:49:50 +02:00
}
2021-08-07 09:15:57 +02:00
void EditorNode3DGizmoPlugin : : commit_subgizmos ( const EditorNode3DGizmo * p_gizmo , const Vector < int > & p_ids , const Vector < Transform3D > & p_restore , bool p_cancel ) {
2021-08-22 03:52:44 +02:00
TypedArray < Transform3D > restore ;
restore . resize ( p_restore . size ( ) ) ;
for ( int i = 0 ; i < p_restore . size ( ) ; i + + ) {
restore [ i ] = p_restore [ i ] ;
2021-06-23 16:49:50 +02:00
}
2021-08-22 03:52:44 +02:00
GDVIRTUAL_CALL ( _commit_subgizmos , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_ids , restore , p_cancel ) ;
2021-06-23 16:49:50 +02:00
}
void EditorNode3DGizmoPlugin : : set_state ( int p_state ) {
current_state = p_state ;
2024-04-15 15:18:34 +02:00
for ( EditorNode3DGizmo * current : current_gizmos ) {
current - > set_hidden ( current_state = = HIDDEN ) ;
2021-06-23 16:49:50 +02:00
}
}
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 ( ) {
2024-04-15 15:18:34 +02:00
for ( EditorNode3DGizmo * current : current_gizmos ) {
current - > set_plugin ( nullptr ) ;
current - > get_node_3d ( ) - > remove_gizmo ( current ) ;
2021-06-23 16:49:50 +02:00
}
if ( Node3DEditor : : get_singleton ( ) ) {
Node3DEditor : : get_singleton ( ) - > update_all_gizmos ( ) ;
}
2015-10-08 20:00:40 +02:00
}
2018-08-21 21:28:06 +02:00
//////