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 */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2015-10-08 20:00:40 +02:00
/*************************************************************************/
2022-01-03 21:27:34 +01:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2015-10-08 20:00:40 +02:00
/* */
/* 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
2021-05-21 09:58:01 +02:00
# include "core/math/convex_hull.h"
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"
2022-03-25 18:06:46 +01:00
# include "editor/editor_undo_redo_manager.h"
2021-06-23 16:49:50 +02:00
# include "editor/plugins/node_3d_editor_plugin.h"
2021-09-16 21:28:20 +02:00
# include "scene/3d/audio_listener_3d.h"
2018-09-04 11:30:04 +02:00
# include "scene/3d/audio_stream_player_3d.h"
2021-06-23 16:49:50 +02:00
# include "scene/3d/camera_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/collision_polygon_3d.h"
# include "scene/3d/collision_shape_3d.h"
# include "scene/3d/cpu_particles_3d.h"
2020-04-14 05:05:21 +02:00
# include "scene/3d/decal.h"
2021-10-03 13:28:55 +02:00
# include "scene/3d/fog_volume.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/gpu_particles_3d.h"
2020-10-08 02:29:49 +02:00
# include "scene/3d/gpu_particles_collision_3d.h"
2021-10-01 21:00:32 +02:00
# include "scene/3d/joint_3d.h"
2022-04-19 12:27:18 +02:00
# include "scene/3d/label_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/light_3d.h"
2021-06-05 00:47:26 +02:00
# include "scene/3d/lightmap_gi.h"
2020-05-01 14:34:23 +02:00
# include "scene/3d/lightmap_probe.h"
2022-08-13 19:09:58 +02:00
# include "scene/3d/marker_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/mesh_instance_3d.h"
2022-01-31 00:39:52 +01:00
# include "scene/3d/navigation_link_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/navigation_region_3d.h"
2021-04-20 18:40:24 +02:00
# include "scene/3d/occluder_instance_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/ray_cast_3d.h"
2018-09-04 11:30:04 +02:00
# include "scene/3d/reflection_probe.h"
2022-07-18 20:34:14 +02:00
# include "scene/3d/shape_cast_3d.h"
2022-08-25 19:35:52 +02:00
# include "scene/3d/soft_body_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/spring_arm_3d.h"
2018-09-04 11:30:04 +02:00
# include "scene/3d/sprite_3d.h"
2020-03-27 08:44:44 +01:00
# include "scene/3d/vehicle_body_3d.h"
2021-06-17 02:52:30 +02:00
# include "scene/3d/visible_on_screen_notifier_3d.h"
2021-06-05 00:47:26 +02:00
# include "scene/3d/voxel_gi.h"
2020-03-26 22:49:16 +01:00
# include "scene/resources/box_shape_3d.h"
# include "scene/resources/capsule_shape_3d.h"
# include "scene/resources/concave_polygon_shape_3d.h"
# include "scene/resources/convex_polygon_shape_3d.h"
# include "scene/resources/cylinder_shape_3d.h"
2020-03-27 08:44:44 +01:00
# include "scene/resources/height_map_shape_3d.h"
2017-08-28 08:21:54 +02:00
# include "scene/resources/primitive_meshes.h"
2021-08-19 20:21:56 +02:00
# include "scene/resources/separation_ray_shape_3d.h"
2020-03-26 22:49:16 +01:00
# include "scene/resources/sphere_shape_3d.h"
2015-10-08 20:00:40 +02:00
# include "scene/resources/surface_tool.h"
2021-09-14 19:52:35 +02:00
# include "scene/resources/world_boundary_shape_3d.h"
2022-07-01 18:58:03 +02:00
# include "servers/navigation_server_3d.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 {
2017-08-26 05:40:45 +02:00
ERR_FAIL_COND_V ( ! spatial_node , false ) ;
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 ( ) {
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 ( ) ;
secondary_handles . clear ( ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : redraw ( ) {
2021-08-22 03:52:44 +02:00
if ( ! GDVIRTUAL_CALL ( _redraw ) ) {
2021-06-23 16:49:50 +02:00
ERR_FAIL_COND ( ! gizmo_plugin ) ;
gizmo_plugin - > redraw ( this ) ;
2019-01-25 12:57:32 +01:00
}
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
}
2018-07-25 00:08:49 +02:00
ERR_FAIL_COND_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
}
ERR_FAIL_COND_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
}
2018-07-25 00:08:49 +02:00
ERR_FAIL_COND_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
}
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 ;
}
2018-07-25 00:08:49 +02:00
ERR_FAIL_COND ( ! 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 ;
}
ERR_FAIL_COND ( ! 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
}
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 {
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
}
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 {
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
}
ERR_FAIL_COND_V ( ! gizmo_plugin , Transform3D ( ) ) ;
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 ;
}
2018-07-25 00:08:49 +02:00
ERR_FAIL_COND ( ! 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 ;
}
ERR_FAIL_COND ( ! gizmo_plugin ) ;
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 ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! 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 ) ;
}
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
ERR_FAIL_COND ( ! spatial_node ) ;
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 ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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
ERR_FAIL_COND ( ! spatial_node ) ;
2021-06-23 16:49:50 +02:00
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 " ) ;
}
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 + + ) {
Color col ( 1 , 1 , 1 , 1 ) ;
2022-01-11 12:33:37 +01:00
if ( is_handle_highlighted ( i , 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
2021-06-23 16:49:50 +02:00
int id = p_ids . is_empty ( ) ? i : p_ids [ i ] ;
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
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 ] ;
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 ) {
2017-08-30 00:50:45 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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 ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND_V ( ! spatial_node , false ) ;
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
2021-06-23 16:49:50 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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 ) {
ERR_FAIL_COND_V ( ! spatial_node , false ) ;
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 ( ) ;
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 ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : create ( ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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
}
transform ( ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : transform ( ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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
}
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmo : : free ( ) {
2015-10-08 20:00:40 +02:00
ERR_FAIL_COND ( ! spatial_node ) ;
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 ( ) ;
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 " ) ;
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 ) ;
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 ) {
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 " ) ;
}
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 {
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 ) ;
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
2021-06-23 16:49:50 +02:00
current_gizmos . push_back ( ref . ptr ( ) ) ;
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
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 ) {
2021-08-22 03:52:44 +02:00
bool success ;
if ( GDVIRTUAL_CALL ( _has_gizmo , p_spatial , success ) ) {
return success ;
2021-06-23 16:49:50 +02:00
}
return false ;
}
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 {
2021-08-22 03:52:44 +02:00
bool ret ;
if ( GDVIRTUAL_CALL ( _can_be_hidden , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
return true ;
}
bool EditorNode3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2021-08-22 03:52:44 +02:00
bool ret ;
if ( GDVIRTUAL_CALL ( _is_selectable_when_hidden , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
return false ;
}
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-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _is_handle_highlighted , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ) {
2021-08-22 03:52:44 +02:00
return ret ;
2021-06-23 16:49:50 +02:00
}
return false ;
}
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-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _get_handle_name , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ) {
2021-08-22 03:52:44 +02:00
return ret ;
2021-06-23 16:49:50 +02:00
}
return " " ;
}
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-01-11 12:33:37 +01:00
if ( GDVIRTUAL_CALL ( _get_handle_value , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , p_secondary , ret ) ) {
2021-08-22 03:52:44 +02:00
return ret ;
2021-06-23 16:49:50 +02:00
}
return Variant ( ) ;
}
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 ;
2021-08-22 03:52:44 +02:00
if ( GDVIRTUAL_CALL ( _subgizmos_intersect_ray , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_camera , p_point , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
return - 1 ;
}
Vector < int > EditorNode3DGizmoPlugin : : subgizmos_intersect_frustum ( const EditorNode3DGizmo * p_gizmo , const Camera3D * p_camera , const Vector < Plane > & p_frustum ) const {
2021-08-22 03:52:44 +02:00
TypedArray < Transform3D > 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 , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_camera , frustum , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
return Vector < int > ( ) ;
}
Transform3D EditorNode3DGizmoPlugin : : get_subgizmo_transform ( const EditorNode3DGizmo * p_gizmo , int p_id ) const {
2021-08-22 03:52:44 +02:00
Transform3D ret ;
if ( GDVIRTUAL_CALL ( _get_subgizmo_transform , Ref < EditorNode3DGizmo > ( p_gizmo ) , p_id , ret ) ) {
return ret ;
2021-06-23 16:49:50 +02:00
}
return Transform3D ( ) ;
}
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 ;
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 ) ;
2022-09-08 18:38:33 +02:00
current_gizmos [ i ] - > get_node_3d ( ) - > remove_gizmo ( current_gizmos [ i ] ) ;
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
}
//// light gizmo
2020-04-06 12:40:52 +02:00
Light3DGizmoPlugin : : Light3DGizmoPlugin ( ) {
2020-01-01 00:52:20 +01:00
// Enable vertex colors for the materials below as the gizmo color depends on the light color.
create_material ( " lines_primary " , Color ( 1 , 1 , 1 ) , false , false , true ) ;
create_material ( " lines_secondary " , Color ( 1 , 1 , 1 , 0.35 ) , false , false , true ) ;
create_material ( " lines_billboard " , Color ( 1 , 1 , 1 ) , true , false , true ) ;
2018-07-25 00:08:49 +02:00
2021-07-17 23:22:52 +02:00
create_icon_material ( " light_directional_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoDirectionalLight " ) , SNAME ( " EditorIcons " ) ) ) ;
create_icon_material ( " light_omni_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoLight " ) , SNAME ( " EditorIcons " ) ) ) ;
create_icon_material ( " light_spot_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoSpotLight " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
create_handle_material ( " handles_billboard " , true ) ;
}
2020-04-06 12:40:52 +02:00
bool Light3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < Light3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2020-07-23 00:39:21 +02:00
String Light3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-04-06 12:40:52 +02:00
return " Light3D " ;
2018-07-25 00:08:49 +02:00
}
2020-04-06 12:40:52 +02:00
int Light3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String Light3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2016-05-21 01:18:35 +02:00
return " Radius " ;
2020-05-14 16:41:43 +02:00
} else {
2016-05-21 01:18:35 +02:00
return " Aperture " ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
}
2022-01-11 12:33:37 +01:00
Variant Light3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
Light3D * light = Object : : cast_to < Light3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2020-03-26 22:49:16 +01:00
return light - > get_param ( Light3D : : PARAM_RANGE ) ;
2020-05-14 16:41:43 +02:00
}
2021-06-23 16:49:50 +02:00
if ( p_id = = 1 ) {
2020-03-26 22:49:16 +01:00
return light - > get_param ( Light3D : : PARAM_SPOT_ANGLE ) ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
return Variant ( ) ;
}
2020-10-17 07:08:21 +02:00
static float _find_closest_angle_to_half_pi_arc ( const Vector3 & p_from , const Vector3 & p_to , float p_arc_radius , const Transform3D & p_arc_xform ) {
2015-10-08 20:00:40 +02:00
//bleh, discrete is simpler
static const int arc_test_points = 64 ;
float min_d = 1e20 ;
Vector3 min_p ;
for ( int i = 0 ; i < arc_test_points ; i + + ) {
float a = i * Math_PI * 0.5 / arc_test_points ;
float an = ( i + 1 ) * Math_PI * 0.5 / arc_test_points ;
Vector3 p = Vector3 ( Math : : cos ( a ) , 0 , - Math : : sin ( a ) ) * p_arc_radius ;
Vector3 n = Vector3 ( Math : : cos ( an ) , 0 , - Math : : sin ( an ) ) * p_arc_radius ;
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( p , n , p_from , p_to , ra , rb ) ;
2015-10-08 20:00:40 +02:00
float d = ra . distance_to ( rb ) ;
if ( d < min_d ) {
min_d = d ;
min_p = ra ;
}
}
//min_p = p_arc_xform.affine_inverse().xform(min_p);
2017-10-02 05:59:39 +02:00
float a = ( Math_PI * 0.5 ) - Vector2 ( min_p . x , - min_p . z ) . angle ( ) ;
2022-08-13 17:45:42 +02:00
return Math : : rad_to_deg ( a ) ;
2015-10-08 20:00:40 +02:00
}
2022-01-11 12:33:37 +01:00
void Light3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
Light3D * light = Object : : cast_to < Light3D > ( p_gizmo - > get_node_3d ( ) ) ;
2020-10-17 07:08:21 +02:00
Transform3D gt = light - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2015-10-08 20:00:40 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 s [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SpotLight3D > ( light ) ) {
2015-10-08 20:00:40 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , Vector3 ( 0 , 0 , - 4096 ) , s [ 0 ] , s [ 1 ] , ra , rb ) ;
2015-10-08 20:00:40 +02:00
float d = - ra . z ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < = 0 ) { // Equal is here for negative zero.
2015-10-08 20:00:40 +02:00
d = 0 ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
light - > set_param ( Light3D : : PARAM_RANGE , d ) ;
} else if ( Object : : cast_to < OmniLight3D > ( light ) ) {
2022-05-03 14:50:35 +02:00
Plane cp = Plane ( p_camera - > get_transform ( ) . basis . get_column ( 2 ) , gt . origin ) ;
2015-10-08 20:00:40 +02:00
Vector3 inters ;
if ( cp . intersects_ray ( ray_from , ray_dir , & inters ) ) {
float r = inters . distance_to ( gt . origin ) ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
r = Math : : snapped ( r , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-03-26 22:49:16 +01:00
light - > set_param ( Light3D : : PARAM_RANGE , r ) ;
2015-10-08 20:00:40 +02:00
}
}
2021-06-23 16:49:50 +02:00
} else if ( p_id = = 1 ) {
2020-03-26 22:49:16 +01:00
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 ) ) ;
2015-10-08 20:00:40 +02:00
}
}
2022-01-11 12:33:37 +01:00
void Light3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
Light3D * light = Object : : cast_to < Light3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
if ( p_cancel ) {
2021-06-23 16:49:50 +02:00
light - > set_param ( p_id = = 0 ? Light3D : : PARAM_RANGE : Light3D : : PARAM_SPOT_ANGLE , p_restore ) ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
} else if ( p_id = = 0 ) {
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2016-05-04 03:25:37 +02:00
ur - > create_action ( TTR ( " Change Light Radius " ) ) ;
2020-03-26 22:49:16 +01:00
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 ) ;
2015-10-08 20:00:40 +02:00
ur - > commit_action ( ) ;
2021-06-23 16:49:50 +02:00
} else if ( p_id = = 1 ) {
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2016-05-04 03:25:37 +02:00
ur - > create_action ( TTR ( " Change Light Radius " ) ) ;
2020-03-26 22:49:16 +01:00
ur - > add_do_method ( light , " set_param " , Light3D : : PARAM_SPOT_ANGLE , light - > get_param ( Light3D : : PARAM_SPOT_ANGLE ) ) ;
ur - > add_undo_method ( light , " set_param " , Light3D : : PARAM_SPOT_ANGLE , p_restore ) ;
2015-10-08 20:00:40 +02:00
ur - > commit_action ( ) ;
}
}
2020-04-06 12:40:52 +02:00
void Light3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Light3D * light = Object : : cast_to < Light3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
2022-08-01 01:20:24 +02:00
Color color = light - > get_color ( ) . srgb_to_linear ( ) * light - > get_correlated_color ( ) . srgb_to_linear ( ) ;
color = color . linear_to_srgb ( ) ;
2020-01-01 00:52:20 +01:00
// Make the gizmo color as bright as possible for better visibility
color . set_hsv ( color . get_h ( ) , color . get_s ( ) , 1 ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2017-08-26 05:40:45 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < DirectionalLight3D > ( light ) ) {
2019-09-16 23:07:24 +02:00
Ref < Material > material = get_material ( " lines_primary " , p_gizmo ) ;
2018-07-25 00:08:49 +02:00
Ref < Material > icon = get_material ( " light_directional_icon " , p_gizmo ) ;
2017-08-26 05:40:45 +02:00
2017-08-28 20:32:28 +02:00
const int arrow_points = 7 ;
const float arrow_length = 1.5 ;
2015-10-08 20:00:40 +02:00
Vector3 arrow [ arrow_points ] = {
2017-08-28 20:32:28 +02:00
Vector3 ( 0 , 0 , - 1 ) ,
Vector3 ( 0 , 0.8 , 0 ) ,
Vector3 ( 0 , 0.3 , 0 ) ,
Vector3 ( 0 , 0.3 , arrow_length ) ,
Vector3 ( 0 , - 0.3 , arrow_length ) ,
Vector3 ( 0 , - 0.3 , 0 ) ,
Vector3 ( 0 , - 0.8 , 0 )
2015-10-08 20:00:40 +02:00
} ;
2017-08-28 20:32:28 +02:00
int arrow_sides = 2 ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > lines ;
for ( int i = 0 ; i < arrow_sides ; i + + ) {
2017-08-28 20:32:28 +02:00
for ( int j = 0 ; j < arrow_points ; j + + ) {
Basis ma ( Vector3 ( 0 , 0 , 1 ) , Math_PI * i / arrow_sides ) ;
2015-10-08 20:00:40 +02:00
2017-08-28 20:32:28 +02:00
Vector3 v1 = arrow [ j ] - Vector3 ( 0 , 0 , arrow_length ) ;
Vector3 v2 = arrow [ ( j + 1 ) % arrow_points ] - Vector3 ( 0 , 0 , arrow_length ) ;
2015-10-08 20:00:40 +02:00
2017-08-28 20:32:28 +02:00
lines . push_back ( ma . xform ( v1 ) ) ;
lines . push_back ( ma . xform ( v2 ) ) ;
2015-10-08 20:00:40 +02:00
}
}
2020-01-01 00:52:20 +01:00
p_gizmo - > add_lines ( lines , material , false , color ) ;
p_gizmo - > add_unscaled_billboard ( icon , 0.05 , color ) ;
2015-10-08 20:00:40 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < OmniLight3D > ( light ) ) {
2019-09-16 23:07:24 +02:00
// Use both a billboard circle and 3 non-billboard circles for a better sphere-like representation
const Ref < Material > lines_material = get_material ( " lines_secondary " , p_gizmo ) ;
const Ref < Material > lines_billboard_material = get_material ( " lines_billboard " , p_gizmo ) ;
const Ref < Material > icon = get_material ( " light_omni_icon " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
OmniLight3D * on = Object : : cast_to < OmniLight3D > ( light ) ;
const float r = on - > get_param ( Light3D : : PARAM_RANGE ) ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > points ;
2019-09-16 23:07:24 +02:00
Vector < Vector3 > points_billboard ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
for ( int i = 0 ; i < 120 ; i + + ) {
// Create a circle
2022-08-13 17:45:42 +02:00
const float ra = Math : : deg_to_rad ( ( float ) ( i * 3 ) ) ;
const float rb = Math : : deg_to_rad ( ( float ) ( ( i + 1 ) * 3 ) ) ;
2019-09-16 23:07:24 +02:00
const Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
const Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
// Draw axis-aligned circles
points . push_back ( Vector3 ( a . x , 0 , a . y ) ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) ) ;
points . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
points . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
2015-10-08 20:00:40 +02:00
points . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
points . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
2019-09-16 23:07:24 +02:00
// Draw a billboarded circle
points_billboard . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
points_billboard . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
2015-10-08 20:00:40 +02:00
}
2020-01-01 00:52:20 +01:00
p_gizmo - > add_lines ( points , lines_material , true , color ) ;
p_gizmo - > add_lines ( points_billboard , lines_billboard_material , true , color ) ;
p_gizmo - > add_unscaled_billboard ( icon , 0.05 , color ) ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > handles ;
handles . push_back ( Vector3 ( r , 0 , 0 ) ) ;
2021-06-23 16:49:50 +02:00
p_gizmo - > add_handles ( handles , get_material ( " handles_billboard " ) , Vector < int > ( ) , true ) ;
2015-10-08 20:00:40 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SpotLight3D > ( light ) ) {
2019-09-16 23:07:24 +02:00
const Ref < Material > material_primary = get_material ( " lines_primary " , p_gizmo ) ;
const Ref < Material > material_secondary = get_material ( " lines_secondary " , p_gizmo ) ;
const Ref < Material > icon = get_material ( " light_spot_icon " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
Vector < Vector3 > points_primary ;
Vector < Vector3 > points_secondary ;
2020-03-26 22:49:16 +01:00
SpotLight3D * sl = Object : : cast_to < SpotLight3D > ( light ) ;
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
float r = sl - > get_param ( Light3D : : PARAM_RANGE ) ;
2022-08-13 17:45:42 +02:00
float w = r * Math : : sin ( Math : : deg_to_rad ( sl - > get_param ( Light3D : : PARAM_SPOT_ANGLE ) ) ) ;
float d = r * Math : : cos ( Math : : deg_to_rad ( sl - > get_param ( Light3D : : PARAM_SPOT_ANGLE ) ) ) ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
for ( int i = 0 ; i < 120 ; i + + ) {
// Draw a circle
2022-08-13 17:45:42 +02:00
const float ra = Math : : deg_to_rad ( ( float ) ( i * 3 ) ) ;
const float rb = Math : : deg_to_rad ( ( float ) ( ( i + 1 ) * 3 ) ) ;
2019-09-16 23:07:24 +02:00
const Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * w ;
const Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * w ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
points_primary . push_back ( Vector3 ( a . x , a . y , - d ) ) ;
points_primary . push_back ( Vector3 ( b . x , b . y , - d ) ) ;
2015-10-08 20:00:40 +02:00
2019-09-16 23:07:24 +02:00
if ( i % 15 = = 0 ) {
// Draw 8 lines from the cone origin to the sides of the circle
points_secondary . push_back ( Vector3 ( a . x , a . y , - d ) ) ;
points_secondary . push_back ( Vector3 ( ) ) ;
2015-10-08 20:00:40 +02:00
}
}
2019-09-16 23:07:24 +02:00
points_primary . push_back ( Vector3 ( 0 , 0 , - r ) ) ;
points_primary . push_back ( Vector3 ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-01-01 00:52:20 +01:00
p_gizmo - > add_lines ( points_primary , material_primary , false , color ) ;
p_gizmo - > add_lines ( points_secondary , material_secondary , false , color ) ;
2015-10-08 20:00:40 +02:00
2022-01-11 16:27:39 +01:00
Vector < Vector3 > handles = {
Vector3 ( 0 , 0 , - r ) ,
Vector3 ( w , 0 , - d )
} ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
2020-01-01 00:52:20 +01:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 , color ) ;
2015-10-08 20:00:40 +02:00
}
}
2018-07-25 00:08:49 +02:00
//// player gizmo
2020-04-06 12:40:52 +02:00
AudioStreamPlayer3DGizmoPlugin : : AudioStreamPlayer3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/stream_player_3d " , Color ( 0.4 , 0.8 , 1 ) ) ;
2015-10-08 20:00:40 +02:00
2021-07-17 23:22:52 +02:00
create_icon_material ( " stream_player_3d_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " Gizmo3DSamplePlayer " ) , SNAME ( " EditorIcons " ) ) ) ;
2019-09-24 22:39:54 +02:00
create_material ( " stream_player_3d_material_primary " , gizmo_color ) ;
create_material ( " stream_player_3d_material_secondary " , gizmo_color * Color ( 1 , 1 , 1 , 0.35 ) ) ;
2022-04-25 19:36:48 +02:00
// Enable vertex colors for the billboard material as the gizmo color depends on the
// AudioStreamPlayer3D attenuation type and source (Unit Size or Max Distance).
create_material ( " stream_player_3d_material_billboard " , Color ( 1 , 1 , 1 ) , true , false , true ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
2016-03-20 03:10:04 +01:00
}
2020-04-06 12:40:52 +02:00
bool AudioStreamPlayer3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < AudioStreamPlayer3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-07-23 00:39:21 +02:00
String AudioStreamPlayer3DGizmoPlugin : : get_gizmo_name ( ) const {
2018-07-25 00:08:49 +02:00
return " AudioStreamPlayer3D " ;
}
2017-07-15 06:23:10 +02:00
2020-04-06 12:40:52 +02:00
int AudioStreamPlayer3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String AudioStreamPlayer3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2017-07-15 06:23:10 +02:00
return " Emission Radius " ;
}
2022-01-11 12:33:37 +01:00
Variant AudioStreamPlayer3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
AudioStreamPlayer3D * player = Object : : cast_to < AudioStreamPlayer3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-07-15 06:23:10 +02:00
return player - > get_emission_angle ( ) ;
}
2022-01-11 12:33:37 +01:00
void AudioStreamPlayer3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
AudioStreamPlayer3D * player = Object : : cast_to < AudioStreamPlayer3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-07-15 06:23:10 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = player - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2017-07-15 06:23:10 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 ray_to = ray_from + ray_dir * 4096 ;
ray_from = gi . xform ( ray_from ) ;
ray_to = gi . xform ( ray_to ) ;
float closest_dist = 1e20 ;
float closest_angle = 1e20 ;
for ( int i = 0 ; i < 180 ; i + + ) {
2022-08-13 17:45:42 +02:00
float a = Math : : deg_to_rad ( ( float ) i ) ;
float an = Math : : deg_to_rad ( ( float ) ( i + 1 ) ) ;
2017-07-15 06:23:10 +02:00
Vector3 from ( Math : : sin ( a ) , 0 , - Math : : cos ( a ) ) ;
Vector3 to ( Math : : sin ( an ) , 0 , - Math : : cos ( an ) ) ;
Vector3 r1 , r2 ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( from , to , ray_from , ray_to , r1 , r2 ) ;
2017-07-15 06:23:10 +02:00
float d = r1 . distance_to ( r2 ) ;
if ( d < closest_dist ) {
closest_dist = d ;
closest_angle = i ;
}
}
if ( closest_angle < 91 ) {
player - > set_emission_angle ( closest_angle ) ;
}
}
2022-01-11 12:33:37 +01:00
void AudioStreamPlayer3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
AudioStreamPlayer3D * player = Object : : cast_to < AudioStreamPlayer3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-07-15 06:23:10 +02:00
if ( p_cancel ) {
player - > set_emission_angle ( p_restore ) ;
} else {
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2017-07-15 06:23:10 +02:00
ur - > create_action ( TTR ( " Change AudioStreamPlayer3D Emission Angle " ) ) ;
ur - > add_do_method ( player , " set_emission_angle " , player - > get_emission_angle ( ) ) ;
ur - > add_undo_method ( player , " set_emission_angle " , p_restore ) ;
ur - > commit_action ( ) ;
}
}
2020-04-06 12:40:52 +02:00
void AudioStreamPlayer3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
const AudioStreamPlayer3D * player = Object : : cast_to < AudioStreamPlayer3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
const Ref < Material > icon = get_material ( " stream_player_3d_icon " , p_gizmo ) ;
2017-08-26 05:40:45 +02:00
2022-04-25 19:36:48 +02:00
if ( player - > get_attenuation_model ( ) ! = AudioStreamPlayer3D : : ATTENUATION_DISABLED | | player - > get_max_distance ( ) > CMP_EPSILON ) {
// Draw a circle to represent sound volume attenuation.
// Use only a billboard circle to represent radius.
// This helps distinguish AudioStreamPlayer3D gizmos from OmniLight3D gizmos.
const Ref < Material > lines_billboard_material = get_material ( " stream_player_3d_material_billboard " , p_gizmo ) ;
// Soft distance cap varies depending on attenuation model, as some will fade out more aggressively than others.
// Multipliers were empirically determined through testing.
float soft_multiplier ;
switch ( player - > get_attenuation_model ( ) ) {
case AudioStreamPlayer3D : : ATTENUATION_INVERSE_DISTANCE :
soft_multiplier = 12.0 ;
break ;
case AudioStreamPlayer3D : : ATTENUATION_INVERSE_SQUARE_DISTANCE :
soft_multiplier = 4.0 ;
break ;
case AudioStreamPlayer3D : : ATTENUATION_LOGARITHMIC :
soft_multiplier = 3.25 ;
break ;
default :
// Ensures Max Distance's radius visualization is not capped by Unit Size
// (when the attenuation mode is Disabled).
soft_multiplier = 10000.0 ;
break ;
}
// Draw the distance at which the sound can be reasonably heard.
// This can be either a hard distance cap with the Max Distance property (if set above 0.0),
// or a soft distance cap with the Unit Size property (sound never reaches true zero).
// When Max Distance is 0.0, `r` represents the distance above which the
// sound can't be heard in *most* (but not all) scenarios.
float r ;
if ( player - > get_max_distance ( ) > CMP_EPSILON ) {
r = MIN ( player - > get_unit_size ( ) * soft_multiplier , player - > get_max_distance ( ) ) ;
} else {
r = player - > get_unit_size ( ) * soft_multiplier ;
}
Vector < Vector3 > points_billboard ;
for ( int i = 0 ; i < 120 ; i + + ) {
// Create a circle.
2022-08-13 17:45:42 +02:00
const float ra = Math : : deg_to_rad ( ( float ) ( i * 3 ) ) ;
const float rb = Math : : deg_to_rad ( ( float ) ( ( i + 1 ) * 3 ) ) ;
2022-04-25 19:36:48 +02:00
const Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
const Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
// Draw a billboarded circle.
points_billboard . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
points_billboard . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
}
Color color ;
switch ( player - > get_attenuation_model ( ) ) {
// Pick cold colors for all attenuation models (except Disabled),
// so that soft caps can be easily distinguished from hard caps
// (which use warm colors).
case AudioStreamPlayer3D : : ATTENUATION_INVERSE_DISTANCE :
color = Color ( 0.4 , 0.8 , 1 ) ;
break ;
case AudioStreamPlayer3D : : ATTENUATION_INVERSE_SQUARE_DISTANCE :
color = Color ( 0.4 , 0.5 , 1 ) ;
break ;
case AudioStreamPlayer3D : : ATTENUATION_LOGARITHMIC :
color = Color ( 0.4 , 0.2 , 1 ) ;
break ;
default :
// Disabled attenuation mode.
// This is never reached when Max Distance is 0, but the
// hue-inverted form of this color will be used if Max Distance is greater than 0.
color = Color ( 1 , 1 , 1 ) ;
break ;
}
if ( player - > get_max_distance ( ) > CMP_EPSILON ) {
// Sound is hard-capped by max distance. The attenuation model still matters,
// so invert the hue of the color that was chosen above.
color . set_h ( color . get_h ( ) + 0.5 ) ;
}
p_gizmo - > add_lines ( points_billboard , lines_billboard_material , true , color ) ;
}
2017-07-15 06:23:10 +02:00
if ( player - > is_emission_angle_enabled ( ) ) {
2019-09-24 22:39:54 +02:00
const float pc = player - > get_emission_angle ( ) ;
2022-08-13 17:45:42 +02:00
const float ofs = - Math : : cos ( Math : : deg_to_rad ( pc ) ) ;
const float radius = Math : : sin ( Math : : deg_to_rad ( pc ) ) ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
Vector < Vector3 > points_primary ;
points_primary . resize ( 200 ) ;
2017-07-15 06:23:10 +02:00
2020-04-03 11:50:40 +02:00
real_t step = Math_TAU / 100.0 ;
2017-07-15 06:23:10 +02:00
for ( int i = 0 ; i < 100 ; i + + ) {
2020-04-03 11:50:40 +02:00
const float a = i * step ;
const float an = ( i + 1 ) * step ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
const Vector3 from ( Math : : sin ( a ) * radius , Math : : cos ( a ) * radius , ofs ) ;
const Vector3 to ( Math : : sin ( an ) * radius , Math : : cos ( an ) * radius , ofs ) ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
points_primary . write [ i * 2 + 0 ] = from ;
points_primary . write [ i * 2 + 1 ] = to ;
2017-07-15 06:23:10 +02:00
}
2019-09-24 22:39:54 +02:00
const Ref < Material > material_primary = get_material ( " stream_player_3d_material_primary " , p_gizmo ) ;
p_gizmo - > add_lines ( points_primary , material_primary ) ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
Vector < Vector3 > points_secondary ;
points_secondary . resize ( 16 ) ;
2017-07-15 06:23:10 +02:00
2019-09-24 22:39:54 +02:00
for ( int i = 0 ; i < 8 ; i + + ) {
2020-04-03 11:50:40 +02:00
const float a = i * ( Math_TAU / 8.0 ) ;
2019-09-24 22:39:54 +02:00
const Vector3 from ( Math : : sin ( a ) * radius , Math : : cos ( a ) * radius , ofs ) ;
points_secondary . write [ i * 2 + 0 ] = from ;
points_secondary . write [ i * 2 + 1 ] = Vector3 ( ) ;
2017-07-15 06:23:10 +02:00
}
2019-09-24 22:39:54 +02:00
const Ref < Material > material_secondary = get_material ( " stream_player_3d_material_secondary " , p_gizmo ) ;
p_gizmo - > add_lines ( points_secondary , material_secondary ) ;
2017-07-15 06:23:10 +02:00
Vector < Vector3 > handles ;
2022-08-13 17:45:42 +02:00
const float ha = Math : : deg_to_rad ( player - > get_emission_angle ( ) ) ;
2017-07-15 06:23:10 +02:00
handles . push_back ( Vector3 ( Math : : sin ( ha ) , 0 , - Math : : cos ( ha ) ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
2017-07-15 06:23:10 +02:00
}
2018-07-25 00:08:49 +02:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
}
//////
2021-09-16 21:28:20 +02:00
AudioListener3DGizmoPlugin : : AudioListener3DGizmoPlugin ( ) {
2022-02-06 15:53:53 +01:00
create_icon_material ( " audio_listener_3d_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoAudioListener3D " ) , SNAME ( " EditorIcons " ) ) ) ;
2021-06-03 18:21:43 +02:00
}
2021-09-16 21:28:20 +02:00
bool AudioListener3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < AudioListener3D > ( p_spatial ) ! = nullptr ;
2021-06-03 18:21:43 +02:00
}
2021-09-16 21:28:20 +02:00
String AudioListener3DGizmoPlugin : : get_gizmo_name ( ) const {
return " AudioListener3D " ;
2021-06-03 18:21:43 +02:00
}
2021-09-16 21:28:20 +02:00
int AudioListener3DGizmoPlugin : : get_priority ( ) const {
2021-06-03 18:21:43 +02:00
return - 1 ;
}
2021-09-16 21:28:20 +02:00
void AudioListener3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
const Ref < Material > icon = get_material ( " audio_listener_3d_icon " , p_gizmo ) ;
2021-06-03 18:21:43 +02:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
}
//////
2020-04-06 12:40:52 +02:00
Camera3DGizmoPlugin : : Camera3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/camera " , Color ( 0.8 , 0.4 , 0.8 ) ) ;
create_material ( " camera_material " , gizmo_color ) ;
create_handle_material ( " handles " ) ;
2017-07-15 06:23:10 +02:00
}
2020-04-06 12:40:52 +02:00
bool Camera3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < Camera3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2017-07-15 06:23:10 +02:00
2020-07-23 00:39:21 +02:00
String Camera3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-26 22:49:16 +01:00
return " Camera3D " ;
2017-07-15 06:23:10 +02:00
}
2020-04-06 12:40:52 +02:00
int Camera3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String Camera3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
Camera3D * camera = Object : : cast_to < Camera3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
if ( camera - > get_projection ( ) = = Camera3D : : PROJECTION_PERSPECTIVE ) {
2016-05-21 01:18:35 +02:00
return " FOV " ;
2015-10-08 20:00:40 +02:00
} else {
2016-05-21 01:18:35 +02:00
return " Size " ;
2015-10-08 20:00:40 +02:00
}
}
2018-07-25 00:08:49 +02:00
2022-01-11 12:33:37 +01:00
Variant Camera3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
Camera3D * camera = Object : : cast_to < Camera3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
if ( camera - > get_projection ( ) = = Camera3D : : PROJECTION_PERSPECTIVE ) {
2015-10-08 20:00:40 +02:00
return camera - > get_fov ( ) ;
} else {
return camera - > get_size ( ) ;
}
}
2018-07-25 00:08:49 +02:00
2022-01-11 12:33:37 +01:00
void Camera3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
Camera3D * camera = Object : : cast_to < Camera3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = camera - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2015-10-08 20:00:40 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 s [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2020-03-26 22:49:16 +01:00
if ( camera - > get_projection ( ) = = Camera3D : : PROJECTION_PERSPECTIVE ) {
2020-10-17 07:08:21 +02:00
Transform3D gt2 = camera - > get_global_transform ( ) ;
2019-02-12 21:10:08 +01:00
float a = _find_closest_angle_to_half_pi_arc ( s [ 0 ] , s [ 1 ] , 1.0 , gt2 ) ;
2019-12-29 04:36:57 +01:00
camera - > set ( " fov " , CLAMP ( a * 2.0 , 1 , 179 ) ) ;
2015-10-08 20:00:40 +02:00
} else {
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( 0 , 0 , - 1 ) , Vector3 ( 4096 , 0 , - 1 ) , s [ 0 ] , s [ 1 ] , ra , rb ) ;
2015-10-08 20:00:40 +02:00
float d = ra . x * 2.0 ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2019-12-29 04:36:57 +01:00
d = CLAMP ( d , 0.1 , 16384 ) ;
2015-10-08 20:00:40 +02:00
camera - > set ( " size " , d ) ;
}
}
2018-07-25 00:08:49 +02:00
2022-01-11 12:33:37 +01:00
void Camera3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
Camera3D * camera = Object : : cast_to < Camera3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
if ( camera - > get_projection ( ) = = Camera3D : : PROJECTION_PERSPECTIVE ) {
2015-10-08 20:00:40 +02:00
if ( p_cancel ) {
camera - > set ( " fov " , p_restore ) ;
} else {
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2016-05-04 03:25:37 +02:00
ur - > create_action ( TTR ( " Change Camera FOV " ) ) ;
2015-10-08 20:00:40 +02:00
ur - > add_do_property ( camera , " fov " , camera - > get_fov ( ) ) ;
ur - > add_undo_property ( camera , " fov " , p_restore ) ;
ur - > commit_action ( ) ;
}
} else {
if ( p_cancel ) {
camera - > set ( " size " , p_restore ) ;
} else {
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2016-05-04 03:25:37 +02:00
ur - > create_action ( TTR ( " Change Camera Size " ) ) ;
2015-10-08 20:00:40 +02:00
ur - > add_do_property ( camera , " size " , camera - > get_size ( ) ) ;
ur - > add_undo_property ( camera , " size " , p_restore ) ;
ur - > commit_action ( ) ;
}
}
}
2020-04-06 12:40:52 +02:00
void Camera3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Camera3D * camera = Object : : cast_to < Camera3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > lines ;
Vector < Vector3 > handles ;
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " camera_material " , p_gizmo ) ;
2017-08-26 05:40:45 +02:00
2019-02-19 17:17:02 +01:00
# define ADD_TRIANGLE(m_a, m_b, m_c) \
{ \
lines . push_back ( m_a ) ; \
lines . push_back ( m_b ) ; \
lines . push_back ( m_b ) ; \
lines . push_back ( m_c ) ; \
lines . push_back ( m_c ) ; \
lines . push_back ( m_a ) ; \
}
# define ADD_QUAD(m_a, m_b, m_c, m_d) \
{ \
lines . push_back ( m_a ) ; \
lines . push_back ( m_b ) ; \
lines . push_back ( m_b ) ; \
lines . push_back ( m_c ) ; \
lines . push_back ( m_c ) ; \
lines . push_back ( m_d ) ; \
lines . push_back ( m_d ) ; \
lines . push_back ( m_a ) ; \
}
2015-10-08 20:00:40 +02:00
switch ( camera - > get_projection ( ) ) {
2020-03-26 22:49:16 +01:00
case Camera3D : : PROJECTION_PERSPECTIVE : {
2018-02-04 23:28:04 +01:00
// The real FOV is halved for accurate representation
float fov = camera - > get_fov ( ) / 2.0 ;
2015-10-08 20:00:40 +02:00
2022-08-13 17:45:42 +02:00
Vector3 side = Vector3 ( Math : : sin ( Math : : deg_to_rad ( fov ) ) , 0 , - Math : : cos ( Math : : deg_to_rad ( fov ) ) ) ;
2015-10-08 20:00:40 +02:00
Vector3 nside = side ;
nside . x = - nside . x ;
Vector3 up = Vector3 ( 0 , side . x , 0 ) ;
ADD_TRIANGLE ( Vector3 ( ) , side + up , side - up ) ;
ADD_TRIANGLE ( Vector3 ( ) , nside + up , nside - up ) ;
ADD_TRIANGLE ( Vector3 ( ) , side + up , nside + up ) ;
ADD_TRIANGLE ( Vector3 ( ) , side - up , nside - up ) ;
handles . push_back ( side ) ;
side . x * = 0.25 ;
nside . x * = 0.25 ;
Vector3 tup ( 0 , up . y * 3 / 2 , side . z ) ;
ADD_TRIANGLE ( tup , side + up , nside + up ) ;
} break ;
2020-03-26 22:49:16 +01:00
case Camera3D : : PROJECTION_ORTHOGONAL : {
2015-10-08 20:00:40 +02:00
float size = camera - > get_size ( ) ;
float hsize = size * 0.5 ;
Vector3 right ( hsize , 0 , 0 ) ;
Vector3 up ( 0 , hsize , 0 ) ;
Vector3 back ( 0 , 0 , - 1.0 ) ;
Vector3 front ( 0 , 0 , 0 ) ;
ADD_QUAD ( - up - right , - up + right , up + right , up - right ) ;
ADD_QUAD ( - up - right + back , - up + right + back , up + right + back , up - right + back ) ;
ADD_QUAD ( up + right , up + right + back , up - right + back , up - right ) ;
ADD_QUAD ( - up + right , - up + right + back , - up - right + back , - up - right ) ;
2019-02-19 17:17:02 +01:00
2015-10-08 20:00:40 +02:00
handles . push_back ( right + back ) ;
right . x * = 0.25 ;
Vector3 tup ( 0 , up . y * 3 / 2 , back . z ) ;
ADD_TRIANGLE ( tup , right + up + back , - right + up + back ) ;
} break ;
2020-03-26 22:49:16 +01:00
case Camera3D : : PROJECTION_FRUSTUM : {
2019-02-19 17:17:02 +01:00
float hsize = camera - > get_size ( ) / 2.0 ;
2020-12-16 13:40:42 +01:00
Vector3 side = Vector3 ( hsize , 0 , - camera - > get_near ( ) ) . normalized ( ) ;
2019-02-19 17:17:02 +01:00
Vector3 nside = side ;
nside . x = - nside . x ;
Vector3 up = Vector3 ( 0 , side . x , 0 ) ;
Vector3 offset = Vector3 ( camera - > get_frustum_offset ( ) . x , camera - > get_frustum_offset ( ) . y , 0.0 ) ;
ADD_TRIANGLE ( Vector3 ( ) , side + up + offset , side - up + offset ) ;
ADD_TRIANGLE ( Vector3 ( ) , nside + up + offset , nside - up + offset ) ;
ADD_TRIANGLE ( Vector3 ( ) , side + up + offset , nside + up + offset ) ;
ADD_TRIANGLE ( Vector3 ( ) , side - up + offset , nside - up + offset ) ;
side . x * = 0.25 ;
nside . x * = 0.25 ;
Vector3 tup ( 0 , up . y * 3 / 2 , side . z ) ;
ADD_TRIANGLE ( tup + offset , side + up + offset , nside + up + offset ) ;
}
2015-10-08 20:00:40 +02:00
}
2019-02-19 17:17:02 +01:00
# undef ADD_TRIANGLE
# undef ADD_QUAD
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
//////
2020-04-06 12:40:52 +02:00
MeshInstance3DGizmoPlugin : : MeshInstance3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
bool MeshInstance3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2022-08-25 19:35:52 +02:00
return Object : : cast_to < MeshInstance3D > ( p_spatial ) ! = nullptr & & Object : : cast_to < SoftBody3D > ( p_spatial ) = = nullptr ;
2015-10-08 20:00:40 +02:00
}
2020-07-23 00:39:21 +02:00
String MeshInstance3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-26 22:49:16 +01:00
return " MeshInstance3D " ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
int MeshInstance3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
bool MeshInstance3DGizmoPlugin : : can_be_hidden ( ) const {
2018-07-25 00:08:49 +02:00
return false ;
2017-08-26 05:40:45 +02:00
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
void MeshInstance3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
MeshInstance3D * mesh = Object : : cast_to < MeshInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2018-05-06 20:49:22 +02:00
2017-08-19 00:25:18 +02:00
Ref < Mesh > m = mesh - > get_mesh ( ) ;
2018-07-25 00:08:49 +02:00
2020-05-14 16:41:43 +02:00
if ( ! m . is_valid ( ) ) {
2015-10-08 20:00:40 +02:00
return ; //none
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
Ref < TriangleMesh > tm = m - > generate_triangle_mesh ( ) ;
2017-09-12 15:06:13 +02:00
if ( tm . is_valid ( ) ) {
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_triangles ( tm ) ;
2017-09-12 15:06:13 +02:00
}
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
/////
2021-04-20 18:40:24 +02:00
OccluderInstance3DGizmoPlugin : : OccluderInstance3DGizmoPlugin ( ) {
create_material ( " line_material " , EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/occluder " , Color ( 0.8 , 0.5 , 1 ) ) ) ;
2022-02-04 16:28:18 +01:00
create_handle_material ( " handles " ) ;
2021-04-20 18:40:24 +02:00
}
bool OccluderInstance3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < OccluderInstance3D > ( p_spatial ) ! = nullptr ;
}
String OccluderInstance3DGizmoPlugin : : get_gizmo_name ( ) const {
return " OccluderInstance3D " ;
}
int OccluderInstance3DGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
2022-02-04 16:28:18 +01:00
String OccluderInstance3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
const OccluderInstance3D * cs = Object : : cast_to < OccluderInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-02-04 16:28:18 +01:00
Ref < Occluder3D > o = cs - > get_occluder ( ) ;
if ( o . is_null ( ) ) {
return " " ;
}
if ( Object : : cast_to < SphereOccluder3D > ( * o ) ) {
return " Radius " ;
}
if ( Object : : cast_to < BoxOccluder3D > ( * o ) | | Object : : cast_to < QuadOccluder3D > ( * o ) ) {
return " Size " ;
}
return " " ;
}
Variant OccluderInstance3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
OccluderInstance3D * oi = Object : : cast_to < OccluderInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-02-04 16:28:18 +01:00
Ref < Occluder3D > o = oi - > get_occluder ( ) ;
if ( o . is_null ( ) ) {
return Variant ( ) ;
}
if ( Object : : cast_to < SphereOccluder3D > ( * o ) ) {
Ref < SphereOccluder3D > so = o ;
return so - > get_radius ( ) ;
}
if ( Object : : cast_to < BoxOccluder3D > ( * o ) ) {
Ref < BoxOccluder3D > bo = o ;
return bo - > get_size ( ) ;
}
if ( Object : : cast_to < QuadOccluder3D > ( * o ) ) {
Ref < QuadOccluder3D > qo = o ;
return qo - > get_size ( ) ;
}
return Variant ( ) ;
}
void OccluderInstance3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
OccluderInstance3D * oi = Object : : cast_to < OccluderInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-02-04 16:28:18 +01:00
Ref < Occluder3D > o = oi - > get_occluder ( ) ;
if ( o . is_null ( ) ) {
return ;
}
Transform3D gt = oi - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
bool snap_enabled = Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ;
float snap = Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ;
if ( Object : : cast_to < SphereOccluder3D > ( * o ) ) {
Ref < SphereOccluder3D > so = o ;
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , Vector3 ( 4096 , 0 , 0 ) , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
float d = ra . x ;
if ( snap_enabled ) {
d = Math : : snapped ( d , snap ) ;
}
if ( d < 0.001 ) {
d = 0.001 ;
}
so - > set_radius ( d ) ;
}
if ( Object : : cast_to < BoxOccluder3D > ( * o ) ) {
Vector3 axis ;
axis [ p_id ] = 1.0 ;
Ref < BoxOccluder3D > bo = o ;
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
float d = ra [ p_id ] ;
if ( snap_enabled ) {
d = Math : : snapped ( d , snap ) ;
}
if ( d < 0.001 ) {
d = 0.001 ;
}
Vector3 he = bo - > get_size ( ) ;
he [ p_id ] = d * 2 ;
bo - > set_size ( he ) ;
}
if ( Object : : cast_to < QuadOccluder3D > ( * o ) ) {
Ref < QuadOccluder3D > qo = o ;
Plane p = Plane ( Vector3 ( 0.0f , 0.0f , 1.0f ) , 0.0f ) ;
Vector3 intersection ;
if ( ! p . intersects_segment ( sg [ 0 ] , sg [ 1 ] , & intersection ) ) {
return ;
}
if ( p_id = = 2 ) {
Vector2 s = Vector2 ( intersection . x , intersection . y ) * 2.0f ;
if ( snap_enabled ) {
s = s . snapped ( Vector2 ( snap , snap ) ) ;
}
s = s . max ( Vector2 ( 0.001 , 0.001 ) ) ;
qo - > set_size ( s ) ;
} else {
float d = intersection [ p_id ] ;
if ( snap_enabled ) {
d = Math : : snapped ( d , snap ) ;
}
if ( d < 0.001 ) {
d = 0.001 ;
}
Vector2 he = qo - > get_size ( ) ;
he [ p_id ] = d * 2.0f ;
qo - > set_size ( he ) ;
}
}
}
void OccluderInstance3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
OccluderInstance3D * oi = Object : : cast_to < OccluderInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-02-04 16:28:18 +01:00
Ref < Occluder3D > o = oi - > get_occluder ( ) ;
if ( o . is_null ( ) ) {
return ;
}
if ( Object : : cast_to < SphereOccluder3D > ( * o ) ) {
Ref < SphereOccluder3D > so = o ;
if ( p_cancel ) {
so - > set_radius ( p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2022-02-04 16:28:18 +01:00
ur - > create_action ( TTR ( " Change Sphere Shape Radius " ) ) ;
ur - > add_do_method ( so . ptr ( ) , " set_radius " , so - > get_radius ( ) ) ;
ur - > add_undo_method ( so . ptr ( ) , " set_radius " , p_restore ) ;
ur - > commit_action ( ) ;
}
if ( Object : : cast_to < BoxOccluder3D > ( * o ) ) {
Ref < BoxOccluder3D > bo = o ;
if ( p_cancel ) {
bo - > set_size ( p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2022-02-04 16:28:18 +01:00
ur - > create_action ( TTR ( " Change Box Shape Size " ) ) ;
ur - > add_do_method ( bo . ptr ( ) , " set_size " , bo - > get_size ( ) ) ;
ur - > add_undo_method ( bo . ptr ( ) , " set_size " , p_restore ) ;
ur - > commit_action ( ) ;
}
if ( Object : : cast_to < QuadOccluder3D > ( * o ) ) {
Ref < QuadOccluder3D > qo = o ;
if ( p_cancel ) {
qo - > set_size ( p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2022-02-04 16:28:18 +01:00
ur - > create_action ( TTR ( " Change Box Shape Size " ) ) ;
ur - > add_do_method ( qo . ptr ( ) , " set_size " , qo - > get_size ( ) ) ;
ur - > add_undo_method ( qo . ptr ( ) , " set_size " , p_restore ) ;
ur - > commit_action ( ) ;
}
}
2021-04-20 18:40:24 +02:00
void OccluderInstance3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
OccluderInstance3D * occluder_instance = Object : : cast_to < OccluderInstance3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-04-20 18:40:24 +02:00
p_gizmo - > clear ( ) ;
Ref < Occluder3D > o = occluder_instance - > get_occluder ( ) ;
if ( ! o . is_valid ( ) ) {
return ;
}
Vector < Vector3 > lines = o - > get_debug_lines ( ) ;
if ( ! lines . is_empty ( ) ) {
Ref < Material > material = get_material ( " line_material " , p_gizmo ) ;
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
}
2022-02-04 16:28:18 +01:00
Ref < Material > handles_material = get_material ( " handles " ) ;
if ( Object : : cast_to < SphereOccluder3D > ( * o ) ) {
Ref < SphereOccluder3D > so = o ;
float r = so - > get_radius ( ) ;
Vector < Vector3 > handles = { Vector3 ( r , 0 , 0 ) } ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
if ( Object : : cast_to < BoxOccluder3D > ( * o ) ) {
Ref < BoxOccluder3D > bo = o ;
Vector < Vector3 > handles ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = bo - > get_size ( ) [ i ] / 2 ;
handles . push_back ( ax ) ;
}
p_gizmo - > add_handles ( handles , handles_material ) ;
}
if ( Object : : cast_to < QuadOccluder3D > ( * o ) ) {
Ref < QuadOccluder3D > qo = o ;
Vector2 size = qo - > get_size ( ) ;
Vector3 s = Vector3 ( size . x , size . y , 0.0f ) / 2.0f ;
Vector < Vector3 > handles = { Vector3 ( s . x , 0.0f , 0.0f ) , Vector3 ( 0.0f , s . y , 0.0f ) , Vector3 ( s . x , s . y , 0.0f ) } ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
2021-04-20 18:40:24 +02:00
}
/////
2020-04-06 12:40:52 +02:00
Sprite3DGizmoPlugin : : Sprite3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
bool Sprite3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < Sprite3D > ( p_spatial ) ! = nullptr ;
2015-10-08 20:00:40 +02:00
}
2020-07-23 00:39:21 +02:00
String Sprite3DGizmoPlugin : : get_gizmo_name ( ) const {
2018-07-25 00:08:49 +02:00
return " Sprite3D " ;
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
int Sprite3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
bool Sprite3DGizmoPlugin : : can_be_hidden ( ) const {
2018-07-25 00:08:49 +02:00
return false ;
2018-05-06 20:49:22 +02:00
}
2020-04-06 12:40:52 +02:00
void Sprite3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Sprite3D * sprite = Object : : cast_to < Sprite3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2018-05-06 20:49:22 +02:00
Ref < TriangleMesh > tm = sprite - > generate_triangle_mesh ( ) ;
if ( tm . is_valid ( ) ) {
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_triangles ( tm ) ;
2018-05-06 20:49:22 +02:00
}
}
///
2022-04-19 12:27:18 +02:00
Label3DGizmoPlugin : : Label3DGizmoPlugin ( ) {
}
bool Label3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < Label3D > ( p_spatial ) ! = nullptr ;
}
String Label3DGizmoPlugin : : get_gizmo_name ( ) const {
return " Label3D " ;
}
int Label3DGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
bool Label3DGizmoPlugin : : can_be_hidden ( ) const {
return false ;
}
void Label3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Label3D * label = Object : : cast_to < Label3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-04-19 12:27:18 +02:00
p_gizmo - > clear ( ) ;
Ref < TriangleMesh > tm = label - > generate_triangle_mesh ( ) ;
if ( tm . is_valid ( ) ) {
p_gizmo - > add_collision_triangles ( tm ) ;
}
}
///
2022-08-13 19:09:58 +02:00
Marker3DGizmoPlugin : : Marker3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
pos3d_mesh = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
cursor_points = Vector < Vector3 > ( ) ;
2015-10-08 20:00:40 +02:00
2020-02-17 22:06:54 +01:00
Vector < Color > cursor_colors ;
2021-05-27 08:29:05 +02:00
const float cs = 0.25 ;
// Add more points to create a "hard stop" in the color gradient.
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( + cs , 0 , 0 ) ) ;
2021-05-27 08:29:05 +02:00
cursor_points . push_back ( Vector3 ( ) ) ;
cursor_points . push_back ( Vector3 ( ) ) ;
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( - cs , 0 , 0 ) ) ;
2021-05-27 08:29:05 +02:00
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( 0 , + cs , 0 ) ) ;
2021-05-27 08:29:05 +02:00
cursor_points . push_back ( Vector3 ( ) ) ;
cursor_points . push_back ( Vector3 ( ) ) ;
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( 0 , - cs , 0 ) ) ;
2021-05-27 08:29:05 +02:00
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( 0 , 0 , + cs ) ) ;
2021-05-27 08:29:05 +02:00
cursor_points . push_back ( Vector3 ( ) ) ;
cursor_points . push_back ( Vector3 ( ) ) ;
2015-10-08 20:00:40 +02:00
cursor_points . push_back ( Vector3 ( 0 , 0 , - cs ) ) ;
2021-05-27 08:29:05 +02:00
// Use the axis color which is brighter for the positive axis.
// Use a darkened axis color for the negative axis.
2022-08-13 19:09:58 +02:00
// This makes it possible to see in which direction the Marker3D node is rotated
2021-05-27 08:29:05 +02:00
// (which can be important depending on how it's used).
2021-07-17 23:22:52 +02:00
const Color color_x = EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_color ( SNAME ( " axis_x_color " ) , SNAME ( " Editor " ) ) ;
2021-05-27 08:29:05 +02:00
cursor_colors . push_back ( color_x ) ;
cursor_colors . push_back ( color_x ) ;
// FIXME: Use less strong darkening factor once GH-48573 is fixed.
// The current darkening factor compensates for lines being too bright in the 3D editor.
cursor_colors . push_back ( color_x . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
cursor_colors . push_back ( color_x . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
2021-07-17 23:22:52 +02:00
const Color color_y = EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_color ( SNAME ( " axis_y_color " ) , SNAME ( " Editor " ) ) ;
2021-05-27 08:29:05 +02:00
cursor_colors . push_back ( color_y ) ;
cursor_colors . push_back ( color_y ) ;
cursor_colors . push_back ( color_y . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
cursor_colors . push_back ( color_y . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
2021-07-17 23:22:52 +02:00
const Color color_z = EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_theme_color ( SNAME ( " axis_z_color " ) , SNAME ( " Editor " ) ) ;
2021-05-27 08:29:05 +02:00
cursor_colors . push_back ( color_z ) ;
cursor_colors . push_back ( color_z ) ;
cursor_colors . push_back ( color_z . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
cursor_colors . push_back ( color_z . lerp ( Color ( 0 , 0 , 0 ) , 0.75 ) ) ;
2018-07-25 00:08:49 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2019-07-12 15:12:48 +02:00
2018-07-25 00:08:49 +02:00
Array d ;
2020-03-27 19:21:27 +01:00
d . resize ( RS : : ARRAY_MAX ) ;
2018-07-25 00:08:49 +02:00
d [ Mesh : : ARRAY_VERTEX ] = cursor_points ;
d [ Mesh : : ARRAY_COLOR ] = cursor_colors ;
pos3d_mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_LINES , d ) ;
pos3d_mesh - > surface_set_material ( 0 , mat ) ;
2015-10-08 20:00:40 +02:00
}
2022-08-13 19:09:58 +02:00
bool Marker3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < Marker3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2022-08-13 19:09:58 +02:00
String Marker3DGizmoPlugin : : get_gizmo_name ( ) const {
return " Marker3D " ;
2018-07-25 00:08:49 +02:00
}
2022-08-13 19:09:58 +02:00
int Marker3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-08-13 19:09:58 +02:00
void Marker3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
p_gizmo - > add_mesh ( pos3d_mesh ) ;
p_gizmo - > add_collision_segments ( cursor_points ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
////
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
PhysicalBone3DGizmoPlugin : : PhysicalBone3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
create_material ( " joint_material " , EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/joint " ) ) ;
2015-10-08 20:00:40 +02:00
}
2017-12-17 15:29:39 +01:00
2020-04-06 12:40:52 +02:00
bool PhysicalBone3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < PhysicalBone3D > ( p_spatial ) ! = nullptr ;
2017-10-03 18:49:32 +02:00
}
2020-07-23 00:39:21 +02:00
String PhysicalBone3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-04-06 12:40:52 +02:00
return " PhysicalBone3D " ;
2018-07-25 00:08:49 +02:00
}
2017-10-03 18:49:32 +02:00
2020-04-06 12:40:52 +02:00
int PhysicalBone3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void PhysicalBone3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2022-09-08 18:38:33 +02:00
PhysicalBone3D * physical_bone = Object : : cast_to < PhysicalBone3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-10-03 18:49:32 +02:00
2020-05-14 16:41:43 +02:00
if ( ! physical_bone ) {
2017-10-03 18:49:32 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-10-03 18:49:32 +02:00
2020-03-26 22:49:16 +01:00
Skeleton3D * sk ( physical_bone - > find_skeleton_parent ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sk ) {
2018-08-26 11:55:58 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-08-26 11:55:58 +02:00
2020-03-26 22:49:16 +01:00
PhysicalBone3D * pb ( sk - > get_physical_bone ( physical_bone - > get_bone_id ( ) ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! pb ) {
2018-08-26 11:55:58 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-08-26 11:55:58 +02:00
2020-03-26 22:49:16 +01:00
PhysicalBone3D * pbp ( sk - > get_physical_bone_parent ( physical_bone - > get_bone_id ( ) ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! pbp ) {
2018-08-26 11:55:58 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-10-03 18:49:32 +02:00
Vector < Vector3 > points ;
switch ( physical_bone - > get_joint_type ( ) ) {
2020-03-26 22:49:16 +01:00
case PhysicalBone3D : : JOINT_TYPE_PIN : {
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : CreatePinJointGizmo ( physical_bone - > get_joint_offset ( ) , points ) ;
2017-10-03 18:49:32 +02:00
} break ;
2020-03-26 22:49:16 +01:00
case PhysicalBone3D : : JOINT_TYPE_CONE : {
const PhysicalBone3D : : ConeJointData * cjd ( static_cast < const PhysicalBone3D : : ConeJointData * > ( physical_bone - > get_joint_data ( ) ) ) ;
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : CreateConeTwistJointGizmo (
2017-10-03 18:49:32 +02:00
physical_bone - > get_joint_offset ( ) ,
physical_bone - > get_global_transform ( ) * physical_bone - > get_joint_offset ( ) ,
2019-06-20 16:59:48 +02:00
pb - > get_global_transform ( ) ,
pbp - > get_global_transform ( ) ,
2017-10-03 18:49:32 +02:00
cjd - > swing_span ,
cjd - > twist_span ,
2019-06-20 16:59:48 +02:00
& points ,
& points ) ;
2017-10-03 18:49:32 +02:00
} break ;
2020-03-26 22:49:16 +01:00
case PhysicalBone3D : : JOINT_TYPE_HINGE : {
const PhysicalBone3D : : HingeJointData * hjd ( static_cast < const PhysicalBone3D : : HingeJointData * > ( physical_bone - > get_joint_data ( ) ) ) ;
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : CreateHingeJointGizmo (
2017-10-03 18:49:32 +02:00
physical_bone - > get_joint_offset ( ) ,
physical_bone - > get_global_transform ( ) * physical_bone - > get_joint_offset ( ) ,
2019-06-20 16:59:48 +02:00
pb - > get_global_transform ( ) ,
pbp - > get_global_transform ( ) ,
2017-10-03 18:49:32 +02:00
hjd - > angular_limit_lower ,
hjd - > angular_limit_upper ,
hjd - > angular_limit_enabled ,
points ,
2019-06-20 16:59:48 +02:00
& points ,
& points ) ;
2017-10-03 18:49:32 +02:00
} break ;
2020-03-26 22:49:16 +01:00
case PhysicalBone3D : : JOINT_TYPE_SLIDER : {
const PhysicalBone3D : : SliderJointData * sjd ( static_cast < const PhysicalBone3D : : SliderJointData * > ( physical_bone - > get_joint_data ( ) ) ) ;
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : CreateSliderJointGizmo (
2017-10-03 18:49:32 +02:00
physical_bone - > get_joint_offset ( ) ,
physical_bone - > get_global_transform ( ) * physical_bone - > get_joint_offset ( ) ,
2019-06-20 16:59:48 +02:00
pb - > get_global_transform ( ) ,
pbp - > get_global_transform ( ) ,
2017-10-03 18:49:32 +02:00
sjd - > angular_limit_lower ,
sjd - > angular_limit_upper ,
sjd - > linear_limit_lower ,
sjd - > linear_limit_upper ,
points ,
2019-06-20 16:59:48 +02:00
& points ,
& points ) ;
2017-10-03 18:49:32 +02:00
} break ;
2020-03-26 22:49:16 +01:00
case PhysicalBone3D : : JOINT_TYPE_6DOF : {
const PhysicalBone3D : : SixDOFJointData * sdofjd ( static_cast < const PhysicalBone3D : : SixDOFJointData * > ( physical_bone - > get_joint_data ( ) ) ) ;
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : CreateGeneric6DOFJointGizmo (
2017-10-03 18:49:32 +02:00
physical_bone - > get_joint_offset ( ) ,
physical_bone - > get_global_transform ( ) * physical_bone - > get_joint_offset ( ) ,
2019-06-20 16:59:48 +02:00
pb - > get_global_transform ( ) ,
pbp - > get_global_transform ( ) ,
2017-10-03 18:49:32 +02:00
sdofjd - > axis_data [ 0 ] . angular_limit_lower ,
sdofjd - > axis_data [ 0 ] . angular_limit_upper ,
sdofjd - > axis_data [ 0 ] . linear_limit_lower ,
sdofjd - > axis_data [ 0 ] . linear_limit_upper ,
sdofjd - > axis_data [ 0 ] . angular_limit_enabled ,
sdofjd - > axis_data [ 0 ] . linear_limit_enabled ,
sdofjd - > axis_data [ 1 ] . angular_limit_lower ,
sdofjd - > axis_data [ 1 ] . angular_limit_upper ,
sdofjd - > axis_data [ 1 ] . linear_limit_lower ,
sdofjd - > axis_data [ 1 ] . linear_limit_upper ,
sdofjd - > axis_data [ 1 ] . angular_limit_enabled ,
sdofjd - > axis_data [ 1 ] . linear_limit_enabled ,
sdofjd - > axis_data [ 2 ] . angular_limit_lower ,
sdofjd - > axis_data [ 2 ] . angular_limit_upper ,
sdofjd - > axis_data [ 2 ] . linear_limit_lower ,
sdofjd - > axis_data [ 2 ] . linear_limit_upper ,
sdofjd - > axis_data [ 2 ] . angular_limit_enabled ,
sdofjd - > axis_data [ 2 ] . linear_limit_enabled ,
points ,
2019-06-20 16:59:48 +02:00
& points ,
& points ) ;
2017-10-03 18:49:32 +02:00
} break ;
default :
return ;
}
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " joint_material " , p_gizmo ) ;
2017-10-03 18:49:32 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( points ) ;
p_gizmo - > add_lines ( points , material ) ;
2017-10-03 18:49:32 +02:00
}
2015-10-08 20:00:40 +02:00
/////
2020-04-06 12:40:52 +02:00
RayCast3DGizmoPlugin : : RayCast3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
const Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-07-25 00:08:49 +02:00
create_material ( " shape_material " , gizmo_color ) ;
2019-08-21 15:27:02 +02:00
const float gizmo_value = gizmo_color . get_v ( ) ;
const Color gizmo_color_disabled = Color ( gizmo_value , gizmo_value , gizmo_value , 0.65 ) ;
create_material ( " shape_material_disabled " , gizmo_color_disabled ) ;
2018-07-25 00:08:49 +02:00
}
2020-04-06 12:40:52 +02:00
bool RayCast3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < RayCast3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2020-07-23 00:39:21 +02:00
String RayCast3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " RayCast3D " ;
2018-07-25 00:08:49 +02:00
}
2020-04-06 12:40:52 +02:00
int RayCast3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void RayCast3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
RayCast3D * raycast = Object : : cast_to < RayCast3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
2021-02-28 22:15:52 +01:00
const Ref < StandardMaterial3D > material = raycast - > is_enabled ( ) ? raycast - > get_debug_material ( ) : get_material ( " shape_material_disabled " ) ;
2015-10-08 20:00:40 +02:00
2021-02-28 22:15:52 +01:00
p_gizmo - > add_lines ( raycast - > get_debug_line_vertices ( ) , material ) ;
2015-10-08 20:00:40 +02:00
2021-02-28 22:15:52 +01:00
if ( raycast - > get_debug_shape_thickness ( ) > 1 ) {
p_gizmo - > add_vertices ( raycast - > get_debug_shape_vertices ( ) , material , Mesh : : PRIMITIVE_TRIANGLE_STRIP ) ;
}
2017-08-26 05:40:45 +02:00
2021-02-28 22:15:52 +01:00
p_gizmo - > add_collision_segments ( raycast - > get_debug_line_vertices ( ) ) ;
2018-07-25 00:08:49 +02:00
}
/////
2022-07-18 20:34:14 +02:00
ShapeCast3DGizmoPlugin : : ShapeCast3DGizmoPlugin ( ) {
const Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
create_material ( " shape_material " , gizmo_color ) ;
const float gizmo_value = gizmo_color . get_v ( ) ;
const Color gizmo_color_disabled = Color ( gizmo_value , gizmo_value , gizmo_value , 0.65 ) ;
create_material ( " shape_material_disabled " , gizmo_color_disabled ) ;
}
bool ShapeCast3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < ShapeCast3D > ( p_spatial ) ! = nullptr ;
}
String ShapeCast3DGizmoPlugin : : get_gizmo_name ( ) const {
return " ShapeCast3D " ;
}
int ShapeCast3DGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
void ShapeCast3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
ShapeCast3D * shapecast = Object : : cast_to < ShapeCast3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-07-18 20:34:14 +02:00
p_gizmo - > clear ( ) ;
const Ref < StandardMaterial3D > material = shapecast - > is_enabled ( ) ? shapecast - > get_debug_material ( ) : get_material ( " shape_material_disabled " ) ;
p_gizmo - > add_lines ( shapecast - > get_debug_line_vertices ( ) , material ) ;
2022-07-30 17:21:53 +02:00
if ( shapecast - > get_shape ( ) . is_valid ( ) ) {
p_gizmo - > add_lines ( shapecast - > get_debug_shape_vertices ( ) , material ) ;
}
2022-07-18 20:34:14 +02:00
p_gizmo - > add_collision_segments ( shapecast - > get_debug_line_vertices ( ) ) ;
}
/////
2020-04-06 12:40:52 +02:00
void SpringArm3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
SpringArm3D * spring_arm = Object : : cast_to < SpringArm3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-05-13 21:27:56 +02:00
p_gizmo - > clear ( ) ;
2022-01-11 16:27:39 +01:00
Vector < Vector3 > lines = {
Vector3 ( ) ,
Vector3 ( 0 , 0 , 1.0 ) * spring_arm - > get_length ( )
} ;
2018-05-13 21:27:56 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > material = get_material ( " shape_material " , p_gizmo ) ;
2018-05-13 21:27:56 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
}
2020-04-06 12:40:52 +02:00
SpringArm3DGizmoPlugin : : SpringArm3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-05-13 21:27:56 +02:00
create_material ( " shape_material " , gizmo_color ) ;
}
2020-04-06 12:40:52 +02:00
bool SpringArm3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < SpringArm3D > ( p_spatial ) ! = nullptr ;
2018-05-13 21:27:56 +02:00
}
2020-07-23 00:39:21 +02:00
String SpringArm3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " SpringArm3D " ;
2018-05-13 21:27:56 +02:00
}
2020-04-06 12:40:52 +02:00
int SpringArm3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2018-05-13 21:27:56 +02:00
/////
2020-04-06 12:40:52 +02:00
VehicleWheel3DGizmoPlugin : : VehicleWheel3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-07-25 00:08:49 +02:00
create_material ( " shape_material " , gizmo_color ) ;
2015-10-08 20:00:40 +02:00
}
2020-04-06 12:40:52 +02:00
bool VehicleWheel3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < VehicleWheel3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-07-23 00:39:21 +02:00
String VehicleWheel3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " VehicleWheel3D " ;
2015-10-08 20:00:40 +02:00
}
2020-04-06 12:40:52 +02:00
int VehicleWheel3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void VehicleWheel3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
VehicleWheel3D * car_wheel = Object : : cast_to < VehicleWheel3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > points ;
float r = car_wheel - > get_radius ( ) ;
const int skip = 10 ;
for ( int i = 0 ; i < = 360 ; i + = skip ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + skip ) ;
2015-10-08 20:00:40 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
points . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
points . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
const int springsec = 4 ;
for ( int j = 0 ; j < springsec ; j + + ) {
float t = car_wheel - > get_suspension_rest_length ( ) * 5 ;
points . push_back ( Vector3 ( a . x , i / 360.0 * t / springsec + j * ( t / springsec ) , a . y ) * 0.2 ) ;
points . push_back ( Vector3 ( b . x , ( i + skip ) / 360.0 * t / springsec + j * ( t / springsec ) , b . y ) * 0.2 ) ;
}
}
//travel
points . push_back ( Vector3 ( 0 , 0 , 0 ) ) ;
points . push_back ( Vector3 ( 0 , car_wheel - > get_suspension_rest_length ( ) , 0 ) ) ;
//axis
points . push_back ( Vector3 ( r * 0.2 , car_wheel - > get_suspension_rest_length ( ) , 0 ) ) ;
points . push_back ( Vector3 ( - r * 0.2 , car_wheel - > get_suspension_rest_length ( ) , 0 ) ) ;
//axis
points . push_back ( Vector3 ( r * 0.2 , 0 , 0 ) ) ;
points . push_back ( Vector3 ( - r * 0.2 , 0 , 0 ) ) ;
//forward line
points . push_back ( Vector3 ( 0 , - r , 0 ) ) ;
points . push_back ( Vector3 ( 0 , - r , r * 2 ) ) ;
points . push_back ( Vector3 ( 0 , - r , r * 2 ) ) ;
points . push_back ( Vector3 ( r * 2 * 0.2 , - r , r * 2 * 0.8 ) ) ;
points . push_back ( Vector3 ( 0 , - r , r * 2 ) ) ;
points . push_back ( Vector3 ( - r * 2 * 0.2 , - r , r * 2 * 0.8 ) ) ;
2017-03-05 16:44:50 +01:00
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " shape_material " , p_gizmo ) ;
2017-08-26 05:40:45 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( points , material ) ;
p_gizmo - > add_collision_segments ( points ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
///////////
2015-10-08 20:00:40 +02:00
2022-08-25 19:35:52 +02:00
SoftBody3DGizmoPlugin : : SoftBody3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-07-25 00:08:49 +02:00
create_material ( " shape_material " , gizmo_color ) ;
create_handle_material ( " handles " ) ;
2015-10-08 20:00:40 +02:00
}
2022-08-25 19:35:52 +02:00
bool SoftBody3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < SoftBody3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2022-08-25 19:35:52 +02:00
String SoftBody3DGizmoPlugin : : get_gizmo_name ( ) const {
return " SoftBody3D " ;
2018-07-25 00:08:49 +02:00
}
2022-08-25 19:35:52 +02:00
int SoftBody3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-08-25 19:35:52 +02:00
bool SoftBody3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2018-07-25 00:08:49 +02:00
return true ;
}
2022-08-25 19:35:52 +02:00
void SoftBody3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
SoftBody3D * soft_body = Object : : cast_to < SoftBody3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2017-11-21 01:36:32 +01:00
if ( ! soft_body | | soft_body - > get_mesh ( ) . is_null ( ) ) {
return ;
}
// find mesh
Vector < Vector3 > lines ;
soft_body - > get_mesh ( ) - > generate_debug_mesh_lines ( lines ) ;
if ( ! lines . size ( ) ) {
return ;
}
2018-07-25 00:08:49 +02:00
Ref < TriangleMesh > tm = soft_body - > get_mesh ( ) - > generate_triangle_mesh ( ) ;
2017-11-21 01:36:32 +01:00
Vector < Vector3 > points ;
2021-03-12 02:28:16 +01:00
for ( int i = 0 ; i < soft_body - > get_mesh ( ) - > get_surface_count ( ) ; i + + ) {
Array arrays = soft_body - > get_mesh ( ) - > surface_get_arrays ( i ) ;
ERR_CONTINUE ( arrays . is_empty ( ) ) ;
const Vector < Vector3 > & vertices = arrays [ Mesh : : ARRAY_VERTEX ] ;
points . append_array ( vertices ) ;
}
2017-11-21 01:36:32 +01:00
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " shape_material " , p_gizmo ) ;
2017-11-21 01:36:32 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_handles ( points , get_material ( " handles " ) ) ;
p_gizmo - > add_collision_triangles ( tm ) ;
2017-11-21 01:36:32 +01:00
}
2022-08-25 19:35:52 +02:00
String SoftBody3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
return " SoftBody3D pin point " ;
2017-11-21 01:36:32 +01:00
}
2022-08-25 19:35:52 +02:00
Variant SoftBody3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
SoftBody3D * soft_body = Object : : cast_to < SoftBody3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-06-23 16:49:50 +02:00
return Variant ( soft_body - > is_point_pinned ( p_id ) ) ;
2017-11-21 01:36:32 +01:00
}
2022-08-25 19:35:52 +02:00
void SoftBody3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
SoftBody3D * soft_body = Object : : cast_to < SoftBody3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-06-23 16:49:50 +02:00
soft_body - > pin_point_toggle ( p_id ) ;
2017-11-21 01:36:32 +01:00
}
2022-08-25 19:35:52 +02:00
bool SoftBody3DGizmoPlugin : : is_handle_highlighted ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
SoftBody3D * soft_body = Object : : cast_to < SoftBody3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-06-23 16:49:50 +02:00
return soft_body - > is_point_pinned ( p_id ) ;
2017-11-21 01:36:32 +01:00
}
///////////
2021-06-17 02:52:30 +02:00
VisibleOnScreenNotifier3DGizmoPlugin : : VisibleOnScreenNotifier3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/visibility_notifier " , Color ( 0.8 , 0.5 , 0.7 ) ) ;
create_material ( " visibility_notifier_material " , gizmo_color ) ;
gizmo_color . a = 0.1 ;
create_material ( " visibility_notifier_solid_material " , gizmo_color ) ;
create_handle_material ( " handles " ) ;
}
2015-10-08 20:00:40 +02:00
2021-06-17 02:52:30 +02:00
bool VisibleOnScreenNotifier3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < VisibleOnScreenNotifier3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-17 02:52:30 +02:00
String VisibleOnScreenNotifier3DGizmoPlugin : : get_gizmo_name ( ) const {
return " VisibleOnScreenNotifier3D " ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-17 02:52:30 +02:00
int VisibleOnScreenNotifier3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String VisibleOnScreenNotifier3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
switch ( p_id ) {
2020-05-10 13:00:47 +02:00
case 0 :
return " Size X " ;
case 1 :
return " Size Y " ;
case 2 :
return " Size Z " ;
case 3 :
return " Pos X " ;
case 4 :
return " Pos Y " ;
case 5 :
return " Pos Z " ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
return " " ;
}
2015-10-08 20:00:40 +02:00
2022-01-11 12:33:37 +01:00
Variant VisibleOnScreenNotifier3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
VisibleOnScreenNotifier3D * notifier = Object : : cast_to < VisibleOnScreenNotifier3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
return notifier - > get_aabb ( ) ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void VisibleOnScreenNotifier3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
VisibleOnScreenNotifier3D * notifier = Object : : cast_to < VisibleOnScreenNotifier3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = notifier - > get_global_transform ( ) ;
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gi = gt . affine_inverse ( ) ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
bool move = p_id > = 3 ;
p_id = p_id % 3 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
AABB aabb = notifier - > get_aabb ( ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2015-10-08 20:00:40 +02:00
2021-09-20 20:48:52 +02:00
Vector3 ofs = aabb . get_center ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
if ( move ) {
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( ofs - axis * 4096 , ofs + axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2018-06-13 00:53:28 +02:00
2021-06-23 16:49:50 +02:00
aabb . position [ p_id ] = d - 1.0 - aabb . size [ p_id ] * 0.5 ;
2018-07-25 00:08:49 +02:00
notifier - > set_aabb ( aabb ) ;
} else {
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( ofs , ofs + axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] - ofs [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
//resize
2021-06-23 16:49:50 +02:00
aabb . position [ p_id ] = ( aabb . position [ p_id ] + aabb . size [ p_id ] * 0.5 ) - d ;
aabb . size [ p_id ] = d * 2 ;
2018-07-25 00:08:49 +02:00
notifier - > set_aabb ( aabb ) ;
2018-06-13 00:53:28 +02:00
}
2018-07-25 00:08:49 +02:00
}
2018-06-13 00:53:28 +02:00
2022-01-11 12:33:37 +01:00
void VisibleOnScreenNotifier3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
VisibleOnScreenNotifier3D * notifier = Object : : cast_to < VisibleOnScreenNotifier3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
notifier - > set_aabb ( p_restore ) ;
return ;
2015-10-08 20:00:40 +02:00
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Notifier AABB " ) ) ;
ur - > add_do_method ( notifier , " set_aabb " , notifier - > get_aabb ( ) ) ;
ur - > add_undo_method ( notifier , " set_aabb " , p_restore ) ;
ur - > commit_action ( ) ;
2015-10-08 20:00:40 +02:00
}
2021-06-17 02:52:30 +02:00
void VisibleOnScreenNotifier3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
VisibleOnScreenNotifier3D * notifier = Object : : cast_to < VisibleOnScreenNotifier3D > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > lines ;
AABB aabb = notifier - > get_aabb ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > handles ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = aabb . position [ i ] + aabb . size [ i ] ;
ax [ ( i + 1 ) % 3 ] = aabb . position [ ( i + 1 ) % 3 ] + aabb . size [ ( i + 1 ) % 3 ] * 0.5 ;
ax [ ( i + 2 ) % 3 ] = aabb . position [ ( i + 2 ) % 3 ] + aabb . size [ ( i + 2 ) % 3 ] * 0.5 ;
handles . push_back ( ax ) ;
2015-10-08 20:00:40 +02:00
}
2021-09-20 20:48:52 +02:00
Vector3 center = aabb . get_center ( ) ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = 1.0 ;
handles . push_back ( center + ax ) ;
lines . push_back ( center ) ;
lines . push_back ( center + ax ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " visibility_notifier_material " , p_gizmo ) ;
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
if ( p_gizmo - > is_selected ( ) ) {
Ref < Material > solid_material = get_material ( " visibility_notifier_solid_material " , p_gizmo ) ;
2021-09-20 20:48:52 +02:00
p_gizmo - > add_solid_box ( solid_material , aabb . get_size ( ) , aabb . get_center ( ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
////
2015-10-08 20:00:40 +02:00
2020-03-30 18:22:57 +02:00
CPUParticles3DGizmoPlugin : : CPUParticles3DGizmoPlugin ( ) {
2021-07-17 23:22:52 +02:00
create_icon_material ( " particles_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoCPUParticles3D " ) , SNAME ( " EditorIcons " ) ) ) ;
2019-08-08 08:18:09 +02:00
}
2020-03-30 18:22:57 +02:00
bool CPUParticles3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < CPUParticles3D > ( p_spatial ) ! = nullptr ;
2019-08-08 08:18:09 +02:00
}
2020-07-23 00:39:21 +02:00
String CPUParticles3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " CPUParticles3D " ;
2019-08-08 08:18:09 +02:00
}
2020-03-30 18:22:57 +02:00
int CPUParticles3DGizmoPlugin : : get_priority ( ) const {
2019-08-08 08:18:09 +02:00
return - 1 ;
}
2020-03-30 18:22:57 +02:00
bool CPUParticles3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2019-08-08 08:18:09 +02:00
return true ;
}
2020-03-30 18:22:57 +02:00
void CPUParticles3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2019-08-08 08:18:09 +02:00
Ref < Material > icon = get_material ( " particles_icon " , p_gizmo ) ;
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
}
////
2020-03-30 18:22:57 +02:00
GPUParticles3DGizmoPlugin : : GPUParticles3DGizmoPlugin ( ) {
2018-07-25 00:08:49 +02:00
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/particles " , Color ( 0.8 , 0.7 , 0.4 ) ) ;
create_material ( " particles_material " , gizmo_color ) ;
2021-11-17 10:58:52 +01:00
gizmo_color . a = MAX ( ( gizmo_color . a - 0.2 ) * 0.02 , 0.0 ) ;
2018-07-25 00:08:49 +02:00
create_material ( " particles_solid_material " , gizmo_color ) ;
2021-07-17 23:22:52 +02:00
create_icon_material ( " particles_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoGPUParticles3D " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
}
2020-03-30 18:22:57 +02:00
bool GPUParticles3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < GPUParticles3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2020-07-23 00:39:21 +02:00
String GPUParticles3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " GPUParticles3D " ;
2018-07-25 00:08:49 +02:00
}
2020-03-30 18:22:57 +02:00
int GPUParticles3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-03-30 18:22:57 +02:00
bool GPUParticles3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2018-07-25 00:08:49 +02:00
return true ;
}
2022-01-11 12:33:37 +01:00
String GPUParticles3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
switch ( p_id ) {
2020-05-10 13:00:47 +02:00
case 0 :
return " Size X " ;
case 1 :
return " Size Y " ;
case 2 :
return " Size Z " ;
case 3 :
return " Pos X " ;
case 4 :
return " Pos Y " ;
case 5 :
return " Pos Z " ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
return " " ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
Variant GPUParticles3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
GPUParticles3D * particles = Object : : cast_to < GPUParticles3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
return particles - > get_visibility_aabb ( ) ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void GPUParticles3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
GPUParticles3D * particles = Object : : cast_to < GPUParticles3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = particles - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
bool move = p_id > = 3 ;
p_id = p_id % 3 ;
2018-07-25 00:08:49 +02:00
AABB aabb = particles - > get_visibility_aabb ( ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2021-09-20 20:48:52 +02:00
Vector3 ofs = aabb . get_center ( ) ;
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2018-07-25 00:08:49 +02:00
if ( move ) {
2015-10-08 20:00:40 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( ofs - axis * 4096 , ofs + axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2018-06-13 00:53:28 +02:00
2021-06-23 16:49:50 +02:00
aabb . position [ p_id ] = d - 1.0 - aabb . size [ p_id ] * 0.5 ;
2018-07-25 00:08:49 +02:00
particles - > set_visibility_aabb ( aabb ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
} else {
2018-06-13 00:53:28 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( ofs , ofs + axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2018-06-13 00:53:28 +02:00
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] - ofs [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-06-13 00:53:28 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
//resize
2021-06-23 16:49:50 +02:00
aabb . position [ p_id ] = ( aabb . position [ p_id ] + aabb . size [ p_id ] * 0.5 ) - d ;
aabb . size [ p_id ] = d * 2 ;
2018-07-25 00:08:49 +02:00
particles - > set_visibility_aabb ( aabb ) ;
2018-06-13 00:53:28 +02:00
}
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
2022-01-11 12:33:37 +01:00
void GPUParticles3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
GPUParticles3D * particles = Object : : cast_to < GPUParticles3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
particles - > set_visibility_aabb ( p_restore ) ;
2015-10-08 20:00:40 +02:00
return ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Particles AABB " ) ) ;
2019-02-08 12:26:52 +01:00
ur - > add_do_method ( particles , " set_visibility_aabb " , particles - > get_visibility_aabb ( ) ) ;
ur - > add_undo_method ( particles , " set_visibility_aabb " , p_restore ) ;
2018-07-25 00:08:49 +02:00
ur - > commit_action ( ) ;
}
2015-10-08 20:00:40 +02:00
2020-03-30 18:22:57 +02:00
void GPUParticles3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
GPUParticles3D * particles = Object : : cast_to < GPUParticles3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
Vector < Vector3 > lines ;
AABB aabb = particles - > get_visibility_aabb ( ) ;
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
Vector < Vector3 > handles ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = aabb . position [ i ] + aabb . size [ i ] ;
ax [ ( i + 1 ) % 3 ] = aabb . position [ ( i + 1 ) % 3 ] + aabb . size [ ( i + 1 ) % 3 ] * 0.5 ;
ax [ ( i + 2 ) % 3 ] = aabb . position [ ( i + 2 ) % 3 ] + aabb . size [ ( i + 2 ) % 3 ] * 0.5 ;
handles . push_back ( ax ) ;
2015-10-08 20:00:40 +02:00
}
2021-09-20 20:48:52 +02:00
Vector3 center = aabb . get_center ( ) ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = 1.0 ;
handles . push_back ( center + ax ) ;
lines . push_back ( center ) ;
lines . push_back ( center + ax ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " particles_material " , p_gizmo ) ;
Ref < Material > icon = get_material ( " particles_icon " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
if ( p_gizmo - > is_selected ( ) ) {
Ref < Material > solid_material = get_material ( " particles_solid_material " , p_gizmo ) ;
2021-09-20 20:48:52 +02:00
p_gizmo - > add_solid_box ( solid_material , aabb . get_size ( ) , aabb . get_center ( ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
}
2020-05-14 14:29:06 +02:00
2018-07-25 00:08:49 +02:00
////
2018-06-13 00:53:28 +02:00
2020-10-08 02:29:49 +02:00
GPUParticlesCollision3DGizmoPlugin : : GPUParticlesCollision3DGizmoPlugin ( ) {
2022-05-16 01:45:12 +02:00
Color gizmo_color_attractor = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/particle_attractor " , Color ( 1 , 0.7 , 0.5 ) ) ;
create_material ( " shape_material_attractor " , gizmo_color_attractor ) ;
gizmo_color_attractor . a = 0.15 ;
create_material ( " shape_material_attractor_internal " , gizmo_color_attractor ) ;
Color gizmo_color_collision = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/particle_collision " , Color ( 0.5 , 0.7 , 1 ) ) ;
create_material ( " shape_material_collision " , gizmo_color_collision ) ;
gizmo_color_collision . a = 0.15 ;
create_material ( " shape_material_collision_internal " , gizmo_color_collision ) ;
2020-10-08 02:29:49 +02:00
create_handle_material ( " handles " ) ;
}
bool GPUParticlesCollision3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return ( Object : : cast_to < GPUParticlesCollision3D > ( p_spatial ) ! = nullptr ) | | ( Object : : cast_to < GPUParticlesAttractor3D > ( p_spatial ) ! = nullptr ) ;
}
2020-07-23 00:39:21 +02:00
String GPUParticlesCollision3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-10-08 02:29:49 +02:00
return " GPUParticlesCollision3D " ;
}
int GPUParticlesCollision3DGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String GPUParticlesCollision3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
const Node3D * cs = p_gizmo - > get_node_3d ( ) ;
2020-10-08 02:29:49 +02:00
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionSphere3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorSphere3D > ( cs ) ) {
2020-10-08 02:29:49 +02:00
return " Radius " ;
}
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorVectorField3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionSDF3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionHeightField3D > ( cs ) ) {
2020-10-08 02:29:49 +02:00
return " Extents " ;
}
return " " ;
}
2022-01-11 12:33:37 +01:00
Variant GPUParticlesCollision3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
const Node3D * cs = p_gizmo - > get_node_3d ( ) ;
2020-10-08 02:29:49 +02:00
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionSphere3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorSphere3D > ( cs ) ) {
2022-09-08 18:38:33 +02:00
return p_gizmo - > get_node_3d ( ) - > call ( " get_radius " ) ;
2020-10-08 02:29:49 +02:00
}
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorVectorField3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionSDF3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionHeightField3D > ( cs ) ) {
2022-09-08 18:38:33 +02:00
return Vector3 ( p_gizmo - > get_node_3d ( ) - > call ( " get_extents " ) ) ;
2020-10-08 02:29:49 +02:00
}
return Variant ( ) ;
}
2022-01-11 12:33:37 +01:00
void GPUParticlesCollision3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
Node3D * sn = p_gizmo - > get_node_3d ( ) ;
2020-10-08 02:29:49 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = sn - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2020-10-08 02:29:49 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionSphere3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorSphere3D > ( sn ) ) {
2020-10-08 02:29:49 +02:00
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , Vector3 ( 4096 , 0 , 0 ) , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
float d = ra . x ;
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2020-10-08 02:29:49 +02:00
}
if ( d < 0.001 ) {
d = 0.001 ;
}
sn - > call ( " set_radius " , d ) ;
}
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionBox3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorBox3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorVectorField3D > ( sn ) | | Object : : cast_to < GPUParticlesCollisionSDF3D > ( sn ) | | Object : : cast_to < GPUParticlesCollisionHeightField3D > ( sn ) ) {
2020-10-08 02:29:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2020-10-08 02:29:49 +02:00
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-10-08 02:29:49 +02:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2020-10-08 02:29:49 +02:00
}
if ( d < 0.001 ) {
d = 0.001 ;
}
Vector3 he = sn - > call ( " get_extents " ) ;
2021-06-23 16:49:50 +02:00
he [ p_id ] = d ;
2020-10-08 02:29:49 +02:00
sn - > call ( " set_extents " , he ) ;
}
}
2022-01-11 12:33:37 +01:00
void GPUParticlesCollision3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
Node3D * sn = p_gizmo - > get_node_3d ( ) ;
2020-10-08 02:29:49 +02:00
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionSphere3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorSphere3D > ( sn ) ) {
2020-10-08 02:29:49 +02:00
if ( p_cancel ) {
sn - > call ( " set_radius " , p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2020-10-08 02:29:49 +02:00
ur - > create_action ( TTR ( " Change Radius " ) ) ;
ur - > add_do_method ( sn , " set_radius " , sn - > call ( " get_radius " ) ) ;
ur - > add_undo_method ( sn , " set_radius " , p_restore ) ;
ur - > commit_action ( ) ;
}
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionBox3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorBox3D > ( sn ) | | Object : : cast_to < GPUParticlesAttractorVectorField3D > ( sn ) | | Object : : cast_to < GPUParticlesCollisionSDF3D > ( sn ) | | Object : : cast_to < GPUParticlesCollisionHeightField3D > ( sn ) ) {
2020-10-08 02:29:49 +02:00
if ( p_cancel ) {
sn - > call ( " set_extents " , p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2020-10-08 02:29:49 +02:00
ur - > create_action ( TTR ( " Change Box Shape Extents " ) ) ;
ur - > add_do_method ( sn , " set_extents " , sn - > call ( " get_extents " ) ) ;
ur - > add_undo_method ( sn , " set_extents " , p_restore ) ;
ur - > commit_action ( ) ;
}
}
void GPUParticlesCollision3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Node3D * cs = p_gizmo - > get_node_3d ( ) ;
2020-10-08 02:29:49 +02:00
p_gizmo - > clear ( ) ;
2022-05-16 01:45:12 +02:00
Ref < Material > material ;
Ref < Material > material_internal ;
if ( Object : : cast_to < GPUParticlesAttractor3D > ( cs ) ) {
material = get_material ( " shape_material_attractor " , p_gizmo ) ;
material_internal = get_material ( " shape_material_attractor_internal " , p_gizmo ) ;
} else {
material = get_material ( " shape_material_collision " , p_gizmo ) ;
material_internal = get_material ( " shape_material_collision_internal " , p_gizmo ) ;
}
2020-10-08 02:29:49 +02:00
2022-05-16 01:45:12 +02:00
const Ref < Material > handles_material = get_material ( " handles " ) ;
2020-10-08 02:29:49 +02:00
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionSphere3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorSphere3D > ( cs ) ) {
2020-10-08 02:29:49 +02:00
float r = cs - > call ( " get_radius " ) ;
Vector < Vector3 > points ;
for ( int i = 0 ; i < = 360 ; i + + ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 1 ) ;
2020-10-08 02:29:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
points . push_back ( Vector3 ( a . x , 0 , a . y ) ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) ) ;
points . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
points . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
points . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
points . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
}
Vector < Vector3 > collision_segments ;
for ( int i = 0 ; i < 64 ; i + + ) {
2020-04-03 11:50:40 +02:00
float ra = i * ( Math_TAU / 64.0 ) ;
float rb = ( i + 1 ) * ( Math_TAU / 64.0 ) ;
2020-10-08 02:29:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) ) ;
collision_segments . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
collision_segments . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
collision_segments . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
collision_segments . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
}
p_gizmo - > add_lines ( points , material ) ;
p_gizmo - > add_collision_segments ( collision_segments ) ;
Vector < Vector3 > handles ;
handles . push_back ( Vector3 ( r , 0 , 0 ) ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
2021-12-06 19:13:12 +01:00
if ( Object : : cast_to < GPUParticlesCollisionBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorBox3D > ( cs ) | | Object : : cast_to < GPUParticlesAttractorVectorField3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionSDF3D > ( cs ) | | Object : : cast_to < GPUParticlesCollisionHeightField3D > ( cs ) ) {
2020-10-08 02:29:49 +02:00
Vector < Vector3 > lines ;
AABB aabb ;
aabb . position = - cs - > call ( " get_extents " ) . operator Vector3 ( ) ;
aabb . size = aabb . position * - 2 ;
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
}
Vector < Vector3 > handles ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = cs - > call ( " get_extents " ) . operator Vector3 ( ) [ i ] ;
handles . push_back ( ax ) ;
}
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
2021-12-06 19:13:12 +01:00
GPUParticlesCollisionSDF3D * col_sdf = Object : : cast_to < GPUParticlesCollisionSDF3D > ( cs ) ;
2020-10-08 02:29:49 +02:00
if ( col_sdf ) {
2021-12-06 19:13:12 +01:00
static const int subdivs [ GPUParticlesCollisionSDF3D : : RESOLUTION_MAX ] = { 16 , 32 , 64 , 128 , 256 , 512 } ;
2020-10-08 02:29:49 +02:00
int subdiv = subdivs [ col_sdf - > get_resolution ( ) ] ;
float cell_size = aabb . get_longest_axis_size ( ) / subdiv ;
lines . clear ( ) ;
for ( int i = 1 ; i < subdiv ; i + + ) {
for ( int j = 0 ; j < 3 ; j + + ) {
if ( cell_size * i > aabb . size [ j ] ) {
continue ;
}
int j_n1 = ( j + 1 ) % 3 ;
int j_n2 = ( j + 2 ) % 3 ;
for ( int k = 0 ; k < 4 ; k + + ) {
Vector3 from = aabb . position , to = aabb . position ;
from [ j ] + = cell_size * i ;
to [ j ] + = cell_size * i ;
if ( k & 1 ) {
to [ j_n1 ] + = aabb . size [ j_n1 ] ;
} else {
to [ j_n2 ] + = aabb . size [ j_n2 ] ;
}
if ( k & 2 ) {
from [ j_n1 ] + = aabb . size [ j_n1 ] ;
from [ j_n2 ] + = aabb . size [ j_n2 ] ;
}
lines . push_back ( from ) ;
lines . push_back ( to ) ;
}
}
}
p_gizmo - > add_lines ( lines , material_internal ) ;
}
}
}
/////
////
2018-07-25 00:08:49 +02:00
ReflectionProbeGizmoPlugin : : ReflectionProbeGizmoPlugin ( ) {
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/reflection_probe " , Color ( 0.6 , 1 , 0.5 ) ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
create_material ( " reflection_probe_material " , gizmo_color ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
gizmo_color . a = 0.5 ;
create_material ( " reflection_internal_material " , gizmo_color ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
gizmo_color . a = 0.1 ;
create_material ( " reflection_probe_solid_material " , gizmo_color ) ;
2015-10-08 20:00:40 +02:00
2021-07-17 23:22:52 +02:00
create_icon_material ( " reflection_probe_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoReflectionProbe " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
}
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
bool ReflectionProbeGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < ReflectionProbe > ( p_spatial ) ! = nullptr ;
2015-10-08 20:00:40 +02:00
}
2020-07-23 00:39:21 +02:00
String ReflectionProbeGizmoPlugin : : get_gizmo_name ( ) const {
2018-07-25 00:08:49 +02:00
return " ReflectionProbe " ;
}
2015-10-08 20:00:40 +02:00
2019-03-12 00:30:50 +01:00
int ReflectionProbeGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String ReflectionProbeGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
switch ( p_id ) {
2020-05-10 13:00:47 +02:00
case 0 :
return " Extents X " ;
case 1 :
return " Extents Y " ;
case 2 :
return " Extents Z " ;
case 3 :
return " Origin X " ;
case 4 :
return " Origin Y " ;
case 5 :
return " Origin Z " ;
2018-07-25 00:08:49 +02:00
}
2017-08-26 05:40:45 +02:00
2018-07-25 00:08:49 +02:00
return " " ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
Variant ReflectionProbeGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
ReflectionProbe * probe = Object : : cast_to < ReflectionProbe > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
return AABB ( probe - > get_extents ( ) , probe - > get_origin_offset ( ) ) ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void ReflectionProbeGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
ReflectionProbe * probe = Object : : cast_to < ReflectionProbe > ( p_gizmo - > get_node_3d ( ) ) ;
2020-10-17 07:08:21 +02:00
Transform3D gt = probe - > get_global_transform ( ) ;
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gi = gt . affine_inverse ( ) ;
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
if ( p_id < 3 ) {
2018-07-25 00:08:49 +02:00
Vector3 extents = probe - > get_extents ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 16384 ) } ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 16384 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
extents [ p_id ] = d ;
2018-07-25 00:08:49 +02:00
probe - > set_extents ( extents ) ;
} else {
2021-06-23 16:49:50 +02:00
p_id - = 3 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 origin = probe - > get_origin_offset ( ) ;
2021-06-23 16:49:50 +02:00
origin [ p_id ] = 0 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 16384 ) } ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( origin - axis * 16384 , origin + axis * 16384 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2019-07-03 12:11:12 +02:00
// Adjust the actual position to account for the gizmo handle position
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] + 0.25 ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2015-10-08 20:00:40 +02:00
2021-06-23 16:49:50 +02:00
origin [ p_id ] = d ;
2018-07-25 00:08:49 +02:00
probe - > set_origin_offset ( origin ) ;
}
}
2022-01-11 12:33:37 +01:00
void ReflectionProbeGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
ReflectionProbe * probe = Object : : cast_to < ReflectionProbe > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
AABB restore = p_restore ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
probe - > set_extents ( restore . position ) ;
probe - > set_origin_offset ( restore . size ) ;
return ;
2015-10-08 20:00:40 +02:00
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Probe Extents " ) ) ;
ur - > add_do_method ( probe , " set_extents " , probe - > get_extents ( ) ) ;
ur - > add_do_method ( probe , " set_origin_offset " , probe - > get_origin_offset ( ) ) ;
ur - > add_undo_method ( probe , " set_extents " , restore . position ) ;
ur - > add_undo_method ( probe , " set_origin_offset " , restore . size ) ;
ur - > commit_action ( ) ;
}
2015-10-08 20:00:40 +02:00
2020-03-26 22:49:16 +01:00
void ReflectionProbeGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
ReflectionProbe * probe = Object : : cast_to < ReflectionProbe > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > lines ;
Vector < Vector3 > internal_lines ;
Vector3 extents = probe - > get_extents ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
AABB aabb ;
aabb . position = - extents ;
aabb . size = extents * 2 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 8 ; i + + ) {
Vector3 ep = aabb . get_endpoint ( i ) ;
internal_lines . push_back ( probe - > get_origin_offset ( ) ) ;
internal_lines . push_back ( ep ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > handles ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = aabb . position [ i ] + aabb . size [ i ] ;
handles . push_back ( ax ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 orig_handle = probe - > get_origin_offset ( ) ;
orig_handle [ i ] - = 0.25 ;
lines . push_back ( orig_handle ) ;
handles . push_back ( orig_handle ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
orig_handle [ i ] + = 0.5 ;
lines . push_back ( orig_handle ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Ref < Material > material = get_material ( " reflection_probe_material " , p_gizmo ) ;
Ref < Material > material_internal = get_material ( " reflection_internal_material " , p_gizmo ) ;
Ref < Material > icon = get_material ( " reflection_probe_icon " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_lines ( internal_lines , material_internal ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
if ( p_gizmo - > is_selected ( ) ) {
Ref < Material > solid_material = get_material ( " reflection_probe_solid_material " , p_gizmo ) ;
p_gizmo - > add_solid_box ( solid_material , probe - > get_extents ( ) * 2.0 ) ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
}
2020-05-14 14:29:06 +02:00
2020-04-14 05:05:21 +02:00
///////////////////////////////
2015-10-08 20:00:40 +02:00
2020-04-14 05:05:21 +02:00
////
DecalGizmoPlugin : : DecalGizmoPlugin ( ) {
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/decal " , Color ( 0.6 , 0.5 , 1.0 ) ) ;
create_material ( " decal_material " , gizmo_color ) ;
create_handle_material ( " handles " ) ;
}
bool DecalGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < Decal > ( p_spatial ) ! = nullptr ;
}
2020-07-23 00:39:21 +02:00
String DecalGizmoPlugin : : get_gizmo_name ( ) const {
2020-04-14 05:05:21 +02:00
return " Decal " ;
}
int DecalGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String DecalGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
switch ( p_id ) {
2020-05-10 13:00:47 +02:00
case 0 :
return " Extents X " ;
case 1 :
return " Extents Y " ;
case 2 :
return " Extents Z " ;
2020-04-14 05:05:21 +02:00
}
return " " ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
Variant DecalGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
Decal * decal = Object : : cast_to < Decal > ( p_gizmo - > get_node_3d ( ) ) ;
2020-04-14 05:05:21 +02:00
return decal - > get_extents ( ) ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void DecalGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
Decal * decal = Object : : cast_to < Decal > ( p_gizmo - > get_node_3d ( ) ) ;
2020-10-17 07:08:21 +02:00
Transform3D gt = decal - > get_global_transform ( ) ;
2020-04-14 05:05:21 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gi = gt . affine_inverse ( ) ;
2020-04-14 05:05:21 +02:00
Vector3 extents = decal - > get_extents ( ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 16384 ) } ;
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2020-04-14 05:05:21 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 16384 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-04-14 05:05:21 +02:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2020-04-14 05:05:21 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2020-04-14 05:05:21 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2020-04-14 05:05:21 +02:00
2021-06-23 16:49:50 +02:00
extents [ p_id ] = d ;
2020-04-14 05:05:21 +02:00
decal - > set_extents ( extents ) ;
}
2022-01-11 12:33:37 +01:00
void DecalGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
Decal * decal = Object : : cast_to < Decal > ( p_gizmo - > get_node_3d ( ) ) ;
2020-04-14 05:05:21 +02:00
Vector3 restore = p_restore ;
if ( p_cancel ) {
decal - > set_extents ( restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2020-04-14 05:05:21 +02:00
ur - > create_action ( TTR ( " Change Decal Extents " ) ) ;
ur - > add_do_method ( decal , " set_extents " , decal - > get_extents ( ) ) ;
ur - > add_undo_method ( decal , " set_extents " , restore ) ;
ur - > commit_action ( ) ;
}
void DecalGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Decal * decal = Object : : cast_to < Decal > ( p_gizmo - > get_node_3d ( ) ) ;
2020-04-14 05:05:21 +02:00
p_gizmo - > clear ( ) ;
Vector < Vector3 > lines ;
Vector3 extents = decal - > get_extents ( ) ;
AABB aabb ;
aabb . position = - extents ;
aabb . size = extents * 2 ;
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
if ( a . y = = b . y ) {
lines . push_back ( a ) ;
lines . push_back ( b ) ;
} else {
2020-03-16 10:07:33 +01:00
Vector3 ah = a . lerp ( b , 0.2 ) ;
2020-04-14 05:05:21 +02:00
lines . push_back ( a ) ;
lines . push_back ( ah ) ;
2020-03-16 10:07:33 +01:00
Vector3 bh = b . lerp ( a , 0.2 ) ;
2020-04-14 05:05:21 +02:00
lines . push_back ( b ) ;
lines . push_back ( bh ) ;
}
}
lines . push_back ( Vector3 ( 0 , extents . y , 0 ) ) ;
lines . push_back ( Vector3 ( 0 , extents . y * 1.2 , 0 ) ) ;
Vector < Vector3 > handles ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = aabb . position [ i ] + aabb . size [ i ] ;
handles . push_back ( ax ) ;
}
Ref < Material > material = get_material ( " decal_material " , p_gizmo ) ;
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
}
///////////////////////////////
2021-06-05 00:47:26 +02:00
VoxelGIGizmoPlugin : : VoxelGIGizmoPlugin ( ) {
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/voxel_gi " , Color ( 0.5 , 1 , 0.6 ) ) ;
2015-10-08 20:00:40 +02:00
2021-06-05 00:47:26 +02:00
create_material ( " voxel_gi_material " , gizmo_color ) ;
2015-10-08 20:00:40 +02:00
2020-03-02 23:00:53 +01:00
// This gizmo draws a lot of lines. Use a low opacity to make it not too intrusive.
gizmo_color . a = 0.1 ;
2021-06-05 00:47:26 +02:00
create_material ( " voxel_gi_internal_material " , gizmo_color ) ;
2015-10-08 20:00:40 +02:00
2020-03-02 23:00:53 +01:00
gizmo_color . a = 0.05 ;
2021-06-05 00:47:26 +02:00
create_material ( " voxel_gi_solid_material " , gizmo_color ) ;
2015-10-08 20:00:40 +02:00
2021-07-17 23:22:52 +02:00
create_icon_material ( " voxel_gi_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoVoxelGI " ) , SNAME ( " EditorIcons " ) ) ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
}
2018-06-13 00:53:28 +02:00
2021-06-05 00:47:26 +02:00
bool VoxelGIGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < VoxelGI > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2018-06-13 00:53:28 +02:00
2021-06-05 00:47:26 +02:00
String VoxelGIGizmoPlugin : : get_gizmo_name ( ) const {
return " VoxelGI " ;
2018-07-25 00:08:49 +02:00
}
2018-06-13 00:53:28 +02:00
2021-06-05 00:47:26 +02:00
int VoxelGIGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String VoxelGIGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-06-23 16:49:50 +02:00
switch ( p_id ) {
2020-05-10 13:00:47 +02:00
case 0 :
return " Extents X " ;
case 1 :
return " Extents Y " ;
case 2 :
return " Extents Z " ;
2018-07-25 00:08:49 +02:00
}
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
return " " ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
Variant VoxelGIGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
VoxelGI * probe = Object : : cast_to < VoxelGI > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
return probe - > get_extents ( ) ;
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void VoxelGIGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
VoxelGI * probe = Object : : cast_to < VoxelGI > ( p_gizmo - > get_node_3d ( ) ) ;
2018-06-13 00:53:28 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = probe - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 extents = probe - > get_extents ( ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 16384 ) } ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 16384 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-06-13 00:53:28 +02:00
2021-06-23 16:49:50 +02:00
extents [ p_id ] = d ;
2018-07-25 00:08:49 +02:00
probe - > set_extents ( extents ) ;
}
2018-06-13 00:53:28 +02:00
2022-01-11 12:33:37 +01:00
void VoxelGIGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
VoxelGI * probe = Object : : cast_to < VoxelGI > ( p_gizmo - > get_node_3d ( ) ) ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
Vector3 restore = p_restore ;
2018-06-13 00:53:28 +02:00
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
probe - > set_extents ( restore ) ;
return ;
2018-06-13 00:53:28 +02:00
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Probe Extents " ) ) ;
ur - > add_do_method ( probe , " set_extents " , probe - > get_extents ( ) ) ;
ur - > add_undo_method ( probe , " set_extents " , restore ) ;
ur - > commit_action ( ) ;
}
2015-10-08 20:00:40 +02:00
2021-06-05 00:47:26 +02:00
void VoxelGIGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
VoxelGI * probe = Object : : cast_to < VoxelGI > ( p_gizmo - > get_node_3d ( ) ) ;
2015-10-08 20:00:40 +02:00
2021-06-05 00:47:26 +02:00
Ref < Material > material = get_material ( " voxel_gi_material " , p_gizmo ) ;
Ref < Material > icon = get_material ( " voxel_gi_icon " , p_gizmo ) ;
Ref < Material > material_internal = get_material ( " voxel_gi_internal_material " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
Vector < Vector3 > lines ;
Vector3 extents = probe - > get_extents ( ) ;
2021-06-05 00:47:26 +02:00
static const int subdivs [ VoxelGI : : SUBDIV_MAX ] = { 64 , 128 , 256 , 512 } ;
2018-07-25 00:08:49 +02:00
AABB aabb = AABB ( - extents , extents * 2 ) ;
int subdiv = subdivs [ probe - > get_subdiv ( ) ] ;
float cell_size = aabb . get_longest_axis_size ( ) / subdiv ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
lines . clear ( ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 1 ; i < subdiv ; i + + ) {
for ( int j = 0 ; j < 3 ; j + + ) {
if ( cell_size * i > aabb . size [ j ] ) {
continue ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
int j_n1 = ( j + 1 ) % 3 ;
int j_n2 = ( j + 2 ) % 3 ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int k = 0 ; k < 4 ; k + + ) {
Vector3 from = aabb . position , to = aabb . position ;
from [ j ] + = cell_size * i ;
to [ j ] + = cell_size * i ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
if ( k & 1 ) {
to [ j_n1 ] + = aabb . size [ j_n1 ] ;
} else {
to [ j_n2 ] + = aabb . size [ j_n2 ] ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
if ( k & 2 ) {
from [ j_n1 ] + = aabb . size [ j_n1 ] ;
from [ j_n2 ] + = aabb . size [ j_n2 ] ;
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
lines . push_back ( from ) ;
lines . push_back ( to ) ;
}
}
}
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material_internal ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > handles ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = aabb . position [ i ] + aabb . size [ i ] ;
handles . push_back ( ax ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
if ( p_gizmo - > is_selected ( ) ) {
2021-06-05 00:47:26 +02:00
Ref < Material > solid_material = get_material ( " voxel_gi_solid_material " , p_gizmo ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_solid_box ( solid_material , aabb . get_size ( ) ) ;
}
2017-08-26 05:40:45 +02:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
p_gizmo - > add_handles ( handles , get_material ( " handles " ) ) ;
2015-10-08 20:00:40 +02:00
}
2018-07-25 00:08:49 +02:00
////
2021-06-05 00:47:26 +02:00
LightmapGIGizmoPlugin : : LightmapGIGizmoPlugin ( ) {
2020-05-01 14:34:23 +02:00
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/lightmap_lines " , Color ( 0.5 , 0.6 , 1 ) ) ;
2015-10-08 20:00:40 +02:00
2018-07-25 00:08:49 +02:00
gizmo_color . a = 0.1 ;
2020-05-01 14:34:23 +02:00
create_material ( " lightmap_lines " , gizmo_color ) ;
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
mat - > set_cull_mode ( StandardMaterial3D : : CULL_DISABLED ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
mat - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , false ) ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
add_material ( " lightmap_probe_material " , mat ) ;
2015-10-08 20:00:40 +02:00
2021-07-17 23:22:52 +02:00
create_icon_material ( " baked_indirect_light_icon " , Node3DEditor : : get_singleton ( ) - > get_theme_icon ( SNAME ( " GizmoLightmapGI " ) , SNAME ( " EditorIcons " ) ) ) ;
2020-05-01 14:34:23 +02:00
}
2021-06-05 00:47:26 +02:00
bool LightmapGIGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < LightmapGI > ( p_spatial ) ! = nullptr ;
2020-05-01 14:34:23 +02:00
}
2021-06-05 00:47:26 +02:00
String LightmapGIGizmoPlugin : : get_gizmo_name ( ) const {
return " LightmapGI " ;
2020-05-01 14:34:23 +02:00
}
2021-06-05 00:47:26 +02:00
int LightmapGIGizmoPlugin : : get_priority ( ) const {
2020-05-01 14:34:23 +02:00
return - 1 ;
}
2021-06-05 00:47:26 +02:00
void LightmapGIGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2020-05-01 14:34:23 +02:00
Ref < Material > icon = get_material ( " baked_indirect_light_icon " , p_gizmo ) ;
2022-09-08 18:38:33 +02:00
LightmapGI * baker = Object : : cast_to < LightmapGI > ( p_gizmo - > get_node_3d ( ) ) ;
2021-06-05 00:47:26 +02:00
Ref < LightmapGIData > data = baker - > get_light_data ( ) ;
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
p_gizmo - > add_unscaled_billboard ( icon , 0.05 ) ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
if ( data . is_null ( ) ) {
return ;
}
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
Ref < Material > material_lines = get_material ( " lightmap_lines " , p_gizmo ) ;
Ref < Material > material_probes = get_material ( " lightmap_probe_material " , p_gizmo ) ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
Vector < Vector3 > lines ;
2022-05-19 17:00:06 +02:00
HashSet < Vector2i > lines_found ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
Vector < Vector3 > points = data - > get_capture_points ( ) ;
if ( points . size ( ) = = 0 ) {
return ;
}
Vector < Color > sh = data - > get_capture_sh ( ) ;
if ( sh . size ( ) ! = points . size ( ) * 9 ) {
return ;
2019-07-03 12:11:12 +02:00
}
2020-05-01 14:34:23 +02:00
Vector < int > tetrahedrons = data - > get_capture_tetrahedra ( ) ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
for ( int i = 0 ; i < tetrahedrons . size ( ) ; i + = 4 ) {
for ( int j = 0 ; j < 4 ; j + + ) {
for ( int k = j + 1 ; k < 4 ; k + + ) {
Vector2i pair ;
pair . x = tetrahedrons [ i + j ] ;
pair . y = tetrahedrons [ i + k ] ;
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
if ( pair . y < pair . x ) {
SWAP ( pair . x , pair . y ) ;
}
if ( lines_found . has ( pair ) ) {
continue ;
}
lines_found . insert ( pair ) ;
lines . push_back ( points [ pair . x ] ) ;
lines . push_back ( points [ pair . y ] ) ;
}
}
}
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
p_gizmo - > add_lines ( lines , material_lines ) ;
int stack_count = 8 ;
int sector_count = 16 ;
2020-04-03 11:50:40 +02:00
float sector_step = ( Math_PI * 2.0 ) / sector_count ;
2020-05-01 14:34:23 +02:00
float stack_step = Math_PI / stack_count ;
Vector < Vector3 > vertices ;
Vector < Color > colors ;
Vector < int > indices ;
float radius = 0.3 ;
for ( int p = 0 ; p < points . size ( ) ; p + + ) {
int vertex_base = vertices . size ( ) ;
Vector3 sh_col [ 9 ] ;
for ( int i = 0 ; i < 9 ; i + + ) {
sh_col [ i ] . x = sh [ p * 9 + i ] . r ;
sh_col [ i ] . y = sh [ p * 9 + i ] . g ;
sh_col [ i ] . z = sh [ p * 9 + i ] . b ;
}
for ( int i = 0 ; i < = stack_count ; + + i ) {
float stack_angle = Math_PI / 2 - i * stack_step ; // starting from pi/2 to -pi/2
float xy = radius * Math : : cos ( stack_angle ) ; // r * cos(u)
float z = radius * Math : : sin ( stack_angle ) ; // r * sin(u)
// add (sector_count+1) vertices per stack
// the first and last vertices have same position and normal, but different tex coords
for ( int j = 0 ; j < = sector_count ; + + j ) {
float sector_angle = j * sector_step ; // starting from 0 to 2pi
// vertex position (x, y, z)
float x = xy * Math : : cos ( sector_angle ) ; // r * cos(u) * cos(v)
float y = xy * Math : : sin ( sector_angle ) ; // r * cos(u) * sin(v)
Vector3 n = Vector3 ( x , z , y ) ;
vertices . push_back ( points [ p ] + n ) ;
n . normalize ( ) ;
const float c1 = 0.429043 ;
const float c2 = 0.511664 ;
const float c3 = 0.743125 ;
const float c4 = 0.886227 ;
const float c5 = 0.247708 ;
Vector3 light = ( c1 * sh_col [ 8 ] * ( n . x * n . x - n . y * n . y ) +
2021-10-28 15:19:35 +02:00
c3 * sh_col [ 6 ] * n . z * n . z +
c4 * sh_col [ 0 ] -
c5 * sh_col [ 6 ] +
2.0 * c1 * sh_col [ 4 ] * n . x * n . y +
2.0 * c1 * sh_col [ 7 ] * n . x * n . z +
2.0 * c1 * sh_col [ 5 ] * n . y * n . z +
2.0 * c2 * sh_col [ 3 ] * n . x +
2.0 * c2 * sh_col [ 1 ] * n . y +
2.0 * c2 * sh_col [ 2 ] * n . z ) ;
2020-05-01 14:34:23 +02:00
colors . push_back ( Color ( light . x , light . y , light . z , 1 ) ) ;
}
}
for ( int i = 0 ; i < stack_count ; + + i ) {
int k1 = i * ( sector_count + 1 ) ; // beginning of current stack
int k2 = k1 + sector_count + 1 ; // beginning of next stack
for ( int j = 0 ; j < sector_count ; + + j , + + k1 , + + k2 ) {
// 2 triangles per sector excluding first and last stacks
// k1 => k2 => k1+1
if ( i ! = 0 ) {
indices . push_back ( vertex_base + k1 ) ;
indices . push_back ( vertex_base + k2 ) ;
indices . push_back ( vertex_base + k1 + 1 ) ;
}
// k1+1 => k2 => k2+1
if ( i ! = ( stack_count - 1 ) ) {
indices . push_back ( vertex_base + k1 + 1 ) ;
indices . push_back ( vertex_base + k2 ) ;
indices . push_back ( vertex_base + k2 + 1 ) ;
}
}
}
2015-10-08 20:00:40 +02:00
}
2020-05-01 14:34:23 +02:00
Array array ;
array . resize ( RS : : ARRAY_MAX ) ;
array [ RS : : ARRAY_VERTEX ] = vertices ;
array [ RS : : ARRAY_INDEX ] = indices ;
array [ RS : : ARRAY_COLOR ] = colors ;
Ref < ArrayMesh > mesh ;
2021-06-18 00:03:09 +02:00
mesh . instantiate ( ) ;
2020-05-01 14:34:23 +02:00
mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , array , Array ( ) , Dictionary ( ) , 0 ) ; //no compression
mesh - > surface_set_material ( 0 , material_probes ) ;
p_gizmo - > add_mesh ( mesh ) ;
2015-10-08 20:00:40 +02:00
}
2020-05-14 14:29:06 +02:00
2020-05-01 14:34:23 +02:00
/////////
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
LightmapProbeGizmoPlugin : : LightmapProbeGizmoPlugin ( ) {
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/lightprobe_lines " , Color ( 0.5 , 0.6 , 1 ) ) ;
gizmo_color . a = 0.3 ;
create_material ( " lightprobe_lines " , gizmo_color ) ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
bool LightmapProbeGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < LightmapProbe > ( p_spatial ) ! = nullptr ;
}
2018-07-25 00:08:49 +02:00
2020-07-23 00:39:21 +02:00
String LightmapProbeGizmoPlugin : : get_gizmo_name ( ) const {
2020-05-01 14:34:23 +02:00
return " LightmapProbe " ;
}
int LightmapProbeGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
void LightmapProbeGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
Ref < Material > material_lines = get_material ( " lightprobe_lines " , p_gizmo ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2015-10-08 20:00:40 +02:00
Vector < Vector3 > lines ;
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
int stack_count = 8 ;
int sector_count = 16 ;
2015-10-08 20:00:40 +02:00
2020-04-03 11:50:40 +02:00
float sector_step = ( Math_PI * 2.0 ) / sector_count ;
2020-05-01 14:34:23 +02:00
float stack_step = Math_PI / stack_count ;
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
Vector < Vector3 > vertices ;
float radius = 0.2 ;
2018-07-25 00:08:49 +02:00
2020-05-01 14:34:23 +02:00
for ( int i = 0 ; i < = stack_count ; + + i ) {
float stack_angle = Math_PI / 2 - i * stack_step ; // starting from pi/2 to -pi/2
float xy = radius * Math : : cos ( stack_angle ) ; // r * cos(u)
float z = radius * Math : : sin ( stack_angle ) ; // r * sin(u)
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
// add (sector_count+1) vertices per stack
// the first and last vertices have same position and normal, but different tex coords
for ( int j = 0 ; j < = sector_count ; + + j ) {
float sector_angle = j * sector_step ; // starting from 0 to 2pi
2015-10-08 20:00:40 +02:00
2020-05-01 14:34:23 +02:00
// vertex position (x, y, z)
float x = xy * Math : : cos ( sector_angle ) ; // r * cos(u) * cos(v)
float y = xy * Math : : sin ( sector_angle ) ; // r * cos(u) * sin(v)
Vector3 n = Vector3 ( x , z , y ) ;
vertices . push_back ( n ) ;
}
2015-10-08 20:00:40 +02:00
}
2020-05-01 14:34:23 +02:00
for ( int i = 0 ; i < stack_count ; + + i ) {
int k1 = i * ( sector_count + 1 ) ; // beginning of current stack
int k2 = k1 + sector_count + 1 ; // beginning of next stack
for ( int j = 0 ; j < sector_count ; + + j , + + k1 , + + k2 ) {
// 2 triangles per sector excluding first and last stacks
// k1 => k2 => k1+1
if ( i ! = 0 ) {
lines . push_back ( vertices [ k1 ] ) ;
lines . push_back ( vertices [ k2 ] ) ;
lines . push_back ( vertices [ k1 ] ) ;
lines . push_back ( vertices [ k1 + 1 ] ) ;
}
if ( i ! = ( stack_count - 1 ) ) {
lines . push_back ( vertices [ k1 + 1 ] ) ;
lines . push_back ( vertices [ k2 ] ) ;
lines . push_back ( vertices [ k2 ] ) ;
lines . push_back ( vertices [ k2 + 1 ] ) ;
}
}
2018-07-25 00:08:49 +02:00
}
2020-05-01 14:34:23 +02:00
p_gizmo - > add_lines ( lines , material_lines ) ;
2015-10-08 20:00:40 +02:00
}
2020-05-14 14:29:06 +02:00
2018-07-25 00:08:49 +02:00
////
2021-02-06 23:21:04 +01:00
CollisionObject3DGizmoPlugin : : CollisionObject3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
const Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2021-02-06 23:21:04 +01:00
create_material ( " shape_material " , gizmo_color ) ;
const float gizmo_value = gizmo_color . get_v ( ) ;
const Color gizmo_color_disabled = Color ( gizmo_value , gizmo_value , gizmo_value , 0.65 ) ;
create_material ( " shape_material_disabled " , gizmo_color_disabled ) ;
}
bool CollisionObject3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < CollisionObject3D > ( p_spatial ) ! = nullptr ;
}
String CollisionObject3DGizmoPlugin : : get_gizmo_name ( ) const {
return " CollisionObject3D " ;
}
int CollisionObject3DGizmoPlugin : : get_priority ( ) const {
2021-03-22 18:29:49 +01:00
return - 2 ;
2021-02-06 23:21:04 +01:00
}
void CollisionObject3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
CollisionObject3D * co = Object : : cast_to < CollisionObject3D > ( p_gizmo - > get_node_3d ( ) ) ;
2021-02-06 23:21:04 +01:00
p_gizmo - > clear ( ) ;
2022-09-29 11:53:28 +02:00
List < uint32_t > owner_ids ;
co - > get_shape_owners ( & owner_ids ) ;
for ( uint32_t & owner_id : owner_ids ) {
2020-10-17 07:08:21 +02:00
Transform3D xform = co - > shape_owner_get_transform ( owner_id ) ;
2021-02-06 23:21:04 +01:00
Object * owner = co - > shape_owner_get_owner ( owner_id ) ;
// Exclude CollisionShape3D and CollisionPolygon3D as they have their gizmo.
if ( ! Object : : cast_to < CollisionShape3D > ( owner ) & & ! Object : : cast_to < CollisionPolygon3D > ( owner ) ) {
Ref < Material > material = get_material ( ! co - > is_shape_owner_disabled ( owner_id ) ? " shape_material " : " shape_material_disabled " , p_gizmo ) ;
for ( int shape_id = 0 ; shape_id < co - > shape_owner_get_shape_count ( owner_id ) ; shape_id + + ) {
Ref < Shape3D > s = co - > shape_owner_get_shape ( owner_id , shape_id ) ;
if ( s . is_null ( ) ) {
continue ;
}
SurfaceTool st ;
st . append_from ( s - > get_debug_mesh ( ) , 0 , xform ) ;
2021-06-23 16:49:50 +02:00
p_gizmo - > add_mesh ( st . commit ( ) , material ) ;
2021-02-06 23:21:04 +01:00
p_gizmo - > add_collision_segments ( s - > get_debug_mesh_lines ( ) ) ;
}
}
}
}
////
2020-04-06 12:40:52 +02:00
CollisionShape3DGizmoPlugin : : CollisionShape3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
const Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-07-25 00:08:49 +02:00
create_material ( " shape_material " , gizmo_color ) ;
2019-08-21 15:27:02 +02:00
const float gizmo_value = gizmo_color . get_v ( ) ;
const Color gizmo_color_disabled = Color ( gizmo_value , gizmo_value , gizmo_value , 0.65 ) ;
create_material ( " shape_material_disabled " , gizmo_color_disabled ) ;
2018-07-25 00:08:49 +02:00
create_handle_material ( " handles " ) ;
2015-10-08 20:00:40 +02:00
}
2020-04-06 12:40:52 +02:00
bool CollisionShape3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < CollisionShape3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2015-10-08 20:00:40 +02:00
2020-07-23 00:39:21 +02:00
String CollisionShape3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-26 22:49:16 +01:00
return " CollisionShape3D " ;
2018-07-25 00:08:49 +02:00
}
2016-11-19 17:23:37 +01:00
2020-04-06 12:40:52 +02:00
int CollisionShape3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String CollisionShape3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
const CollisionShape3D * cs = Object : : cast_to < CollisionShape3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
2020-03-26 22:49:16 +01:00
Ref < Shape3D > s = cs - > get_shape ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . is_null ( ) ) {
2018-07-25 00:08:49 +02:00
return " " ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SphereShape3D > ( * s ) ) {
2018-07-25 00:08:49 +02:00
return " Radius " ;
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < BoxShape3D > ( * s ) ) {
2020-12-07 18:52:11 +01:00
return " Size " ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CapsuleShape3D > ( * s ) ) {
2021-06-23 16:49:50 +02:00
return p_id = = 0 ? " Radius " : " Height " ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CylinderShape3D > ( * s ) ) {
2021-06-23 16:49:50 +02:00
return p_id = = 0 ? " Radius " : " Height " ;
2018-07-25 00:08:49 +02:00
}
2021-08-19 20:21:56 +02:00
if ( Object : : cast_to < SeparationRayShape3D > ( * s ) ) {
2021-08-17 19:15:11 +02:00
return " Length " ;
}
2017-04-09 03:38:11 +02:00
return " " ;
}
2022-01-11 12:33:37 +01:00
Variant CollisionShape3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
CollisionShape3D * cs = Object : : cast_to < CollisionShape3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
Ref < Shape3D > s = cs - > get_shape ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . is_null ( ) ) {
2018-07-25 00:08:49 +02:00
return Variant ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SphereShape3D > ( * s ) ) {
Ref < SphereShape3D > ss = s ;
2018-07-25 00:08:49 +02:00
return ss - > get_radius ( ) ;
}
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < BoxShape3D > ( * s ) ) {
Ref < BoxShape3D > bs = s ;
2020-12-07 18:52:11 +01:00
return bs - > get_size ( ) ;
2018-07-25 00:08:49 +02:00
}
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CapsuleShape3D > ( * s ) ) {
Ref < CapsuleShape3D > cs2 = s ;
2021-08-12 20:26:47 +02:00
return Vector2 ( cs2 - > get_radius ( ) , cs2 - > get_height ( ) ) ;
2018-07-25 00:08:49 +02:00
}
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CylinderShape3D > ( * s ) ) {
Ref < CylinderShape3D > cs2 = s ;
2021-06-23 16:49:50 +02:00
return p_id = = 0 ? cs2 - > get_radius ( ) : cs2 - > get_height ( ) ;
2018-07-25 00:08:49 +02:00
}
2017-04-09 03:38:11 +02:00
2021-08-19 20:21:56 +02:00
if ( Object : : cast_to < SeparationRayShape3D > ( * s ) ) {
Ref < SeparationRayShape3D > cs2 = s ;
2021-08-17 19:15:11 +02:00
return cs2 - > get_length ( ) ;
}
2018-07-25 00:08:49 +02:00
return Variant ( ) ;
2017-04-09 03:38:11 +02:00
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void CollisionShape3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
CollisionShape3D * cs = Object : : cast_to < CollisionShape3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
Ref < Shape3D > s = cs - > get_shape ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . is_null ( ) ) {
2017-04-09 03:38:11 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-04-09 03:38:11 +02:00
2020-10-17 07:08:21 +02:00
Transform3D gt = cs - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
2017-04-09 03:38:11 +02:00
2018-07-25 00:08:49 +02:00
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
2017-04-09 03:38:11 +02:00
2018-07-25 00:08:49 +02:00
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SphereShape3D > ( * s ) ) {
Ref < SphereShape3D > ss = s ;
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , Vector3 ( 4096 , 0 , 0 ) , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2018-07-25 00:08:49 +02:00
float d = ra . x ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
ss - > set_radius ( d ) ;
2017-04-09 03:38:11 +02:00
}
2021-08-19 20:21:56 +02:00
if ( Object : : cast_to < SeparationRayShape3D > ( * s ) ) {
Ref < SeparationRayShape3D > rs = s ;
2021-08-17 19:15:11 +02:00
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , Vector3 ( 0 , 0 , 4096 ) , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
float d = ra . z ;
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
}
if ( d < 0.001 ) {
d = 0.001 ;
}
rs - > set_length ( d ) ;
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < BoxShape3D > ( * s ) ) {
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id ] = 1.0 ;
2020-03-26 22:49:16 +01:00
Ref < BoxShape3D > bs = s ;
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2021-06-23 16:49:50 +02:00
float d = ra [ p_id ] ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
2020-12-07 18:52:11 +01:00
Vector3 he = bs - > get_size ( ) ;
2021-06-23 16:49:50 +02:00
he [ p_id ] = d * 2 ;
2020-12-07 18:52:11 +01:00
bs - > set_size ( he ) ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CapsuleShape3D > ( * s ) ) {
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-08-11 19:38:14 +02:00
axis [ p_id = = 0 ? 0 : 1 ] = 1.0 ;
2020-03-26 22:49:16 +01:00
Ref < CapsuleShape3D > cs2 = s ;
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2018-07-25 00:08:49 +02:00
float d = axis . dot ( ra ) ;
2019-07-03 12:11:12 +02:00
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2019-02-12 21:10:08 +01:00
cs2 - > set_radius ( d ) ;
2021-06-23 16:49:50 +02:00
} else if ( p_id = = 1 ) {
2019-02-12 21:10:08 +01:00
cs2 - > set_height ( d * 2.0 ) ;
2020-05-14 16:41:43 +02:00
}
2017-04-09 03:38:11 +02:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CylinderShape3D > ( * s ) ) {
2018-07-25 00:08:49 +02:00
Vector3 axis ;
2021-06-23 16:49:50 +02:00
axis [ p_id = = 0 ? 0 : 1 ] = 1.0 ;
2020-03-26 22:49:16 +01:00
Ref < CylinderShape3D > cs2 = s ;
2018-07-25 00:08:49 +02:00
Vector3 ra , rb ;
2020-05-25 19:20:45 +02:00
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
2018-07-25 00:08:49 +02:00
float d = axis . dot ( ra ) ;
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
2020-12-21 19:02:57 +01:00
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
2019-07-03 12:11:12 +02:00
}
2017-08-28 08:21:54 +02:00
2020-05-14 16:41:43 +02:00
if ( d < 0.001 ) {
2018-07-25 00:08:49 +02:00
d = 0.001 ;
2020-05-14 16:41:43 +02:00
}
2017-08-28 08:21:54 +02:00
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2019-02-12 21:10:08 +01:00
cs2 - > set_radius ( d ) ;
2021-06-23 16:49:50 +02:00
} else if ( p_id = = 1 ) {
2019-02-12 21:10:08 +01:00
cs2 - > set_height ( d * 2.0 ) ;
2020-05-14 16:41:43 +02:00
}
2017-08-28 08:21:54 +02:00
}
2017-04-09 03:38:11 +02:00
}
2020-05-14 14:29:06 +02:00
2022-01-11 12:33:37 +01:00
void CollisionShape3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
CollisionShape3D * cs = Object : : cast_to < CollisionShape3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
Ref < Shape3D > s = cs - > get_shape ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . is_null ( ) ) {
2018-07-25 00:08:49 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-04-09 03:38:11 +02:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SphereShape3D > ( * s ) ) {
Ref < SphereShape3D > ss = s ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
ss - > set_radius ( p_restore ) ;
return ;
}
2016-11-19 17:23:37 +01:00
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Sphere Shape Radius " ) ) ;
ur - > add_do_method ( ss . ptr ( ) , " set_radius " , ss - > get_radius ( ) ) ;
ur - > add_undo_method ( ss . ptr ( ) , " set_radius " , p_restore ) ;
ur - > commit_action ( ) ;
2016-11-19 17:23:37 +01:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < BoxShape3D > ( * s ) ) {
Ref < BoxShape3D > ss = s ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
2020-12-07 18:52:11 +01:00
ss - > set_size ( p_restore ) ;
2018-07-25 00:08:49 +02:00
return ;
}
2016-11-19 17:23:37 +01:00
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2020-12-07 18:52:11 +01:00
ur - > create_action ( TTR ( " Change Box Shape Size " ) ) ;
ur - > add_do_method ( ss . ptr ( ) , " set_size " , ss - > get_size ( ) ) ;
ur - > add_undo_method ( ss . ptr ( ) , " set_size " , p_restore ) ;
2018-07-25 00:08:49 +02:00
ur - > commit_action ( ) ;
}
2016-11-19 17:23:37 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CapsuleShape3D > ( * s ) ) {
Ref < CapsuleShape3D > ss = s ;
2021-08-12 20:26:47 +02:00
Vector2 values = p_restore ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
2021-08-12 20:26:47 +02:00
ss - > set_radius ( values [ 0 ] ) ;
ss - > set_height ( values [ 1 ] ) ;
2018-07-25 00:08:49 +02:00
return ;
}
2016-11-19 17:23:37 +01:00
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2018-07-25 00:08:49 +02:00
ur - > create_action ( TTR ( " Change Capsule Shape Radius " ) ) ;
ur - > add_do_method ( ss . ptr ( ) , " set_radius " , ss - > get_radius ( ) ) ;
} else {
ur - > create_action ( TTR ( " Change Capsule Shape Height " ) ) ;
ur - > add_do_method ( ss . ptr ( ) , " set_height " , ss - > get_height ( ) ) ;
}
2021-08-12 20:26:47 +02:00
ur - > add_undo_method ( ss . ptr ( ) , " set_radius " , values [ 0 ] ) ;
ur - > add_undo_method ( ss . ptr ( ) , " set_height " , values [ 1 ] ) ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
ur - > commit_action ( ) ;
}
2016-11-19 17:23:37 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CylinderShape3D > ( * s ) ) {
Ref < CylinderShape3D > ss = s ;
2018-07-25 00:08:49 +02:00
if ( p_cancel ) {
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2018-07-25 00:08:49 +02:00
ss - > set_radius ( p_restore ) ;
2020-05-14 16:41:43 +02:00
} else {
2018-07-25 00:08:49 +02:00
ss - > set_height ( p_restore ) ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
return ;
}
2016-11-19 17:23:37 +01:00
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2021-06-23 16:49:50 +02:00
if ( p_id = = 0 ) {
2018-07-25 00:08:49 +02:00
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 ) ;
} else {
ur - > create_action (
///
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
////////
TTR ( " Change Cylinder Shape Height " ) ) ;
ur - > add_do_method ( ss . ptr ( ) , " set_height " , ss - > get_height ( ) ) ;
ur - > add_undo_method ( ss . ptr ( ) , " set_height " , p_restore ) ;
}
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
ur - > commit_action ( ) ;
}
2021-08-17 19:15:11 +02:00
2021-08-19 20:21:56 +02:00
if ( Object : : cast_to < SeparationRayShape3D > ( * s ) ) {
Ref < SeparationRayShape3D > ss = s ;
2021-08-17 19:15:11 +02:00
if ( p_cancel ) {
ss - > set_length ( p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2021-08-19 20:21:56 +02:00
ur - > create_action ( TTR ( " Change Separation Ray Shape Length " ) ) ;
2021-08-17 19:15:11 +02:00
ur - > add_do_method ( ss . ptr ( ) , " set_length " , ss - > get_length ( ) ) ;
ur - > add_undo_method ( ss . ptr ( ) , " set_length " , p_restore ) ;
ur - > commit_action ( ) ;
}
2016-11-19 17:23:37 +01:00
}
2020-05-14 14:29:06 +02:00
2020-04-06 12:40:52 +02:00
void CollisionShape3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
CollisionShape3D * cs = Object : : cast_to < CollisionShape3D > ( p_gizmo - > get_node_3d ( ) ) ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2016-11-19 17:23:37 +01:00
2020-03-26 22:49:16 +01:00
Ref < Shape3D > s = cs - > get_shape ( ) ;
2020-05-14 16:41:43 +02:00
if ( s . is_null ( ) ) {
2016-11-19 17:23:37 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-11-19 17:23:37 +01:00
2019-08-21 15:27:02 +02:00
const Ref < Material > material =
get_material ( ! cs - > is_disabled ( ) ? " shape_material " : " shape_material_disabled " , p_gizmo ) ;
2018-07-25 00:08:49 +02:00
Ref < Material > handles_material = get_material ( " handles " ) ;
2016-11-19 17:23:37 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < SphereShape3D > ( * s ) ) {
Ref < SphereShape3D > sp = s ;
2018-07-25 00:08:49 +02:00
float r = sp - > get_radius ( ) ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > points ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < = 360 ; i + + ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 1 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) ) ;
points . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
points . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
points . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
points . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
}
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > collision_segments ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 64 ; i + + ) {
2020-04-03 11:50:40 +02:00
float ra = i * ( Math_TAU / 64.0 ) ;
float rb = ( i + 1 ) * ( Math_TAU / 64.0 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * r ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * r ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) ) ;
collision_segments . push_back ( Vector3 ( 0 , a . x , a . y ) ) ;
collision_segments . push_back ( Vector3 ( 0 , b . x , b . y ) ) ;
collision_segments . push_back ( Vector3 ( a . x , a . y , 0 ) ) ;
collision_segments . push_back ( Vector3 ( b . x , b . y , 0 ) ) ;
}
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( points , material ) ;
p_gizmo - > add_collision_segments ( collision_segments ) ;
Vector < Vector3 > handles ;
handles . push_back ( Vector3 ( r , 0 , 0 ) ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
2016-11-19 17:23:37 +01:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < BoxShape3D > ( * s ) ) {
Ref < BoxShape3D > bs = s ;
2018-07-25 00:08:49 +02:00
Vector < Vector3 > lines ;
AABB aabb ;
2020-12-07 18:52:11 +01:00
aabb . position = - bs - > get_size ( ) / 2 ;
aabb . size = bs - > get_size ( ) ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
}
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > handles ;
2016-11-19 17:23:37 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
2020-12-07 18:52:11 +01:00
ax [ i ] = bs - > get_size ( ) [ i ] / 2 ;
2018-07-25 00:08:49 +02:00
handles . push_back ( ax ) ;
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
2016-12-20 04:21:07 +01:00
}
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CapsuleShape3D > ( * s ) ) {
Ref < CapsuleShape3D > cs2 = s ;
2019-02-12 21:10:08 +01:00
float radius = cs2 - > get_radius ( ) ;
float height = cs2 - > get_height ( ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > points ;
2016-12-20 04:21:07 +01:00
2021-08-11 19:38:14 +02:00
Vector3 d ( 0 , height * 0.5 - radius , 0 ) ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 360 ; i + + ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 1 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * radius ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * radius ;
2016-12-20 04:21:07 +01:00
2020-02-23 19:41:31 +01:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) + d ) ;
2016-12-20 04:21:07 +01:00
2020-02-23 19:41:31 +01:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) - d ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
if ( i % 90 = = 0 ) {
2020-02-23 19:41:31 +01:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
points . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
2018-07-25 00:08:49 +02:00
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector3 dud = i < 180 ? d : - d ;
2016-12-20 04:21:07 +01:00
2020-02-23 19:41:31 +01:00
points . push_back ( Vector3 ( 0 , a . x , a . y ) + dud ) ;
points . push_back ( Vector3 ( 0 , b . x , b . y ) + dud ) ;
points . push_back ( Vector3 ( a . y , a . x , 0 ) + dud ) ;
points . push_back ( Vector3 ( b . y , b . x , 0 ) + dud ) ;
2018-07-25 00:08:49 +02:00
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( points , material ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > collision_segments ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 64 ; i + + ) {
2020-04-03 11:50:40 +02:00
float ra = i * ( Math_TAU / 64.0 ) ;
float rb = ( i + 1 ) * ( Math_TAU / 64.0 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * radius ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * radius ;
2017-08-26 05:40:45 +02:00
2020-02-23 19:41:31 +01:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) + d ) ;
2016-12-20 04:21:07 +01:00
2020-02-23 19:41:31 +01:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) - d ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
if ( i % 16 = = 0 ) {
2020-02-23 19:41:31 +01:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
2018-07-25 00:08:49 +02:00
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector3 dud = i < 32 ? d : - d ;
2016-12-20 04:21:07 +01:00
2020-02-23 19:41:31 +01:00
collision_segments . push_back ( Vector3 ( 0 , a . x , a . y ) + dud ) ;
collision_segments . push_back ( Vector3 ( 0 , b . x , b . y ) + dud ) ;
collision_segments . push_back ( Vector3 ( a . y , a . x , 0 ) + dud ) ;
collision_segments . push_back ( Vector3 ( b . y , b . x , 0 ) + dud ) ;
2018-07-25 00:08:49 +02:00
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( collision_segments ) ;
2016-12-20 04:21:07 +01:00
2022-01-11 16:27:39 +01:00
Vector < Vector3 > handles = {
Vector3 ( cs2 - > get_radius ( ) , 0 , 0 ) ,
Vector3 ( 0 , cs2 - > get_height ( ) * 0.5 , 0 )
} ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , handles_material ) ;
}
2016-12-20 04:21:07 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < CylinderShape3D > ( * s ) ) {
Ref < CylinderShape3D > cs2 = s ;
2019-02-12 21:10:08 +01:00
float radius = cs2 - > get_radius ( ) ;
float height = cs2 - > get_height ( ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > points ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector3 d ( 0 , height * 0.5 , 0 ) ;
for ( int i = 0 ; i < 360 ; i + + ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 1 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * radius ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * radius ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) + d ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
points . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
points . push_back ( Vector3 ( b . x , 0 , b . y ) - d ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
if ( i % 90 = = 0 ) {
points . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
points . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
2016-12-20 04:21:07 +01:00
}
}
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( points , material ) ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > collision_segments ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 64 ; i + + ) {
2020-04-03 11:50:40 +02:00
float ra = i * ( Math_TAU / 64.0 ) ;
float rb = ( i + 1 ) * ( Math_TAU / 64.0 ) ;
2018-07-25 00:08:49 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * radius ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * radius ;
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) + d ) ;
2017-08-28 08:21:54 +02:00
2018-07-25 00:08:49 +02:00
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
collision_segments . push_back ( Vector3 ( b . x , 0 , b . y ) - d ) ;
2017-08-28 08:21:54 +02:00
2018-07-25 00:08:49 +02:00
if ( i % 16 = = 0 ) {
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) + d ) ;
collision_segments . push_back ( Vector3 ( a . x , 0 , a . y ) - d ) ;
}
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( collision_segments ) ;
2017-12-14 12:59:46 +01:00
2022-01-11 16:27:39 +01:00
Vector < Vector3 > handles = {
Vector3 ( cs2 - > get_radius ( ) , 0 , 0 ) ,
Vector3 ( 0 , cs2 - > get_height ( ) * 0.5 , 0 )
} ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_handles ( handles , handles_material ) ;
}
2017-12-14 12:59:46 +01:00
2021-09-14 19:52:35 +02:00
if ( Object : : cast_to < WorldBoundaryShape3D > ( * s ) ) {
Ref < WorldBoundaryShape3D > wbs = s ;
const Plane & p = wbs - > get_plane ( ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
Vector3 n1 = p . get_any_perpendicular_normal ( ) ;
Vector3 n2 = p . normal . cross ( n1 ) . normalized ( ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
Vector3 pface [ 4 ] = {
2020-05-10 16:47:11 +02:00
p . normal * p . d + n1 * 10.0 + n2 * 10.0 ,
p . normal * p . d + n1 * 10.0 + n2 * - 10.0 ,
p . normal * p . d + n1 * - 10.0 + n2 * - 10.0 ,
p . normal * p . d + n1 * - 10.0 + n2 * 10.0 ,
2018-07-25 00:08:49 +02:00
} ;
2017-12-14 12:59:46 +01:00
2022-01-11 16:27:39 +01:00
Vector < Vector3 > points = {
pface [ 0 ] ,
pface [ 1 ] ,
pface [ 1 ] ,
pface [ 2 ] ,
pface [ 2 ] ,
pface [ 3 ] ,
pface [ 3 ] ,
pface [ 0 ] ,
p . normal * p . d ,
p . normal * p . d + p . normal * 3
} ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( points , material ) ;
p_gizmo - > add_collision_segments ( points ) ;
}
2017-12-14 12:59:46 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < ConvexPolygonShape3D > ( * s ) ) {
Vector < Vector3 > points = Object : : cast_to < ConvexPolygonShape3D > ( * s ) - > get_points ( ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
if ( points . size ( ) > 3 ) {
Vector < Vector3 > varr = Variant ( points ) ;
2020-05-25 19:20:45 +02:00
Geometry3D : : MeshData md ;
2021-05-21 09:58:01 +02:00
Error err = ConvexHullComputer : : convex_hull ( varr , md ) ;
2018-07-25 00:08:49 +02:00
if ( err = = OK ) {
2019-02-12 21:10:08 +01:00
Vector < Vector3 > points2 ;
points2 . resize ( md . edges . size ( ) * 2 ) ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < md . edges . size ( ) ; i + + ) {
2019-02-12 21:10:08 +01:00
points2 . write [ i * 2 + 0 ] = md . vertices [ md . edges [ i ] . a ] ;
points2 . write [ i * 2 + 1 ] = md . vertices [ md . edges [ i ] . b ] ;
2018-07-25 00:08:49 +02:00
}
2017-12-14 12:59:46 +01:00
2019-02-12 21:10:08 +01:00
p_gizmo - > add_lines ( points2 , material ) ;
p_gizmo - > add_collision_segments ( points2 ) ;
2018-07-25 00:08:49 +02:00
}
}
}
2017-12-14 12:59:46 +01:00
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < ConcavePolygonShape3D > ( * s ) ) {
Ref < ConcavePolygonShape3D > cs2 = s ;
2019-02-24 00:20:54 +01:00
Ref < ArrayMesh > mesh = cs2 - > get_debug_mesh ( ) ;
2021-06-23 16:49:50 +02:00
p_gizmo - > add_mesh ( mesh , material ) ;
2019-10-10 22:35:00 +02:00
p_gizmo - > add_collision_segments ( cs2 - > get_debug_mesh_lines ( ) ) ;
2018-09-09 19:39:34 +02:00
}
2021-08-19 20:21:56 +02:00
if ( Object : : cast_to < SeparationRayShape3D > ( * s ) ) {
Ref < SeparationRayShape3D > rs = s ;
2021-08-17 19:15:11 +02:00
2022-01-11 16:27:39 +01:00
Vector < Vector3 > points = {
Vector3 ( ) ,
Vector3 ( 0 , 0 , rs - > get_length ( ) )
} ;
2021-08-17 19:15:11 +02:00
p_gizmo - > add_lines ( points , material ) ;
p_gizmo - > add_collision_segments ( points ) ;
Vector < Vector3 > handles ;
handles . push_back ( Vector3 ( 0 , 0 , rs - > get_length ( ) ) ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
2020-03-27 08:44:44 +01:00
if ( Object : : cast_to < HeightMapShape3D > ( * s ) ) {
Ref < HeightMapShape3D > hms = s ;
2019-06-03 11:59:55 +02:00
Ref < ArrayMesh > mesh = hms - > get_debug_mesh ( ) ;
2021-06-23 16:49:50 +02:00
p_gizmo - > add_mesh ( mesh , material ) ;
2019-06-03 11:59:55 +02:00
}
2017-12-14 12:59:46 +01:00
}
2016-12-20 04:21:07 +01:00
2018-07-25 00:08:49 +02:00
/////
2017-12-14 12:59:46 +01:00
2020-04-06 12:40:52 +02:00
CollisionPolygon3DGizmoPlugin : : CollisionPolygon3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
const Color gizmo_color = EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/shape " ) ;
2018-07-25 00:08:49 +02:00
create_material ( " shape_material " , gizmo_color ) ;
2019-08-21 15:27:02 +02:00
const float gizmo_value = gizmo_color . get_v ( ) ;
const Color gizmo_color_disabled = Color ( gizmo_value , gizmo_value , gizmo_value , 0.65 ) ;
create_material ( " shape_material_disabled " , gizmo_color_disabled ) ;
2018-07-25 00:08:49 +02:00
}
2017-12-14 12:59:46 +01:00
2020-04-06 12:40:52 +02:00
bool CollisionPolygon3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < CollisionPolygon3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2017-12-14 12:59:46 +01:00
2020-07-23 00:39:21 +02:00
String CollisionPolygon3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-26 22:49:16 +01:00
return " CollisionPolygon3D " ;
2018-07-25 00:08:49 +02:00
}
2017-12-14 12:59:46 +01:00
2020-04-06 12:40:52 +02:00
int CollisionPolygon3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void CollisionPolygon3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
CollisionPolygon3D * polygon = Object : : cast_to < CollisionPolygon3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector2 > points = polygon - > get_polygon ( ) ;
float depth = polygon - > get_depth ( ) * 0.5 ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > lines ;
for ( int i = 0 ; i < points . size ( ) ; i + + ) {
int n = ( i + 1 ) % points . size ( ) ;
lines . push_back ( Vector3 ( points [ i ] . x , points [ i ] . y , depth ) ) ;
lines . push_back ( Vector3 ( points [ n ] . x , points [ n ] . y , depth ) ) ;
lines . push_back ( Vector3 ( points [ i ] . x , points [ i ] . y , - depth ) ) ;
lines . push_back ( Vector3 ( points [ n ] . x , points [ n ] . y , - depth ) ) ;
lines . push_back ( Vector3 ( points [ i ] . x , points [ i ] . y , depth ) ) ;
lines . push_back ( Vector3 ( points [ i ] . x , points [ i ] . y , - depth ) ) ;
2017-12-14 12:59:46 +01:00
}
2019-08-21 15:27:02 +02:00
const Ref < Material > material =
get_material ( ! polygon - > is_disabled ( ) ? " shape_material " : " shape_material_disabled " , p_gizmo ) ;
2017-12-14 12:59:46 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
}
////
2020-04-06 12:40:52 +02:00
NavigationRegion3DGizmoPlugin : : NavigationRegion3DGizmoPlugin ( ) {
2022-08-07 08:54:57 +02:00
create_material ( " face_material " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_geometry_face_color ( ) , false , false , true ) ;
create_material ( " face_material_disabled " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_geometry_face_disabled_color ( ) , false , false , true ) ;
create_material ( " edge_material " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_geometry_edge_color ( ) ) ;
create_material ( " edge_material_disabled " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_geometry_edge_disabled_color ( ) ) ;
2018-07-25 00:08:49 +02:00
}
2017-12-14 12:59:46 +01:00
2020-04-06 12:40:52 +02:00
bool NavigationRegion3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < NavigationRegion3D > ( p_spatial ) ! = nullptr ;
2017-12-14 12:59:46 +01:00
}
2020-07-23 00:39:21 +02:00
String NavigationRegion3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-03-30 18:22:57 +02:00
return " NavigationRegion3D " ;
2017-12-14 12:59:46 +01:00
}
2020-04-06 12:40:52 +02:00
int NavigationRegion3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void NavigationRegion3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
NavigationRegion3D * navigationregion = Object : : cast_to < NavigationRegion3D > ( p_gizmo - > get_node_3d ( ) ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2022-07-01 18:58:03 +02:00
Ref < NavigationMesh > navigationmesh = navigationregion - > get_navigation_mesh ( ) ;
if ( navigationmesh . is_null ( ) ) {
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-07-01 18:58:03 +02:00
Vector < Vector3 > vertices = navigationmesh - > get_vertices ( ) ;
2020-02-17 22:06:54 +01:00
const Vector3 * vr = vertices . ptr ( ) ;
2015-10-08 20:00:40 +02:00
List < Face3 > faces ;
2022-07-01 18:58:03 +02:00
for ( int i = 0 ; i < navigationmesh - > get_polygon_count ( ) ; i + + ) {
Vector < int > p = navigationmesh - > get_polygon ( i ) ;
2015-10-08 20:00:40 +02:00
for ( int j = 2 ; j < p . size ( ) ; j + + ) {
Face3 f ;
f . vertex [ 0 ] = vr [ p [ 0 ] ] ;
f . vertex [ 1 ] = vr [ p [ j - 1 ] ] ;
f . vertex [ 2 ] = vr [ p [ j ] ] ;
faces . push_back ( f ) ;
}
}
2020-12-15 13:04:21 +01:00
if ( faces . is_empty ( ) ) {
2015-12-12 18:06:27 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
2022-05-13 15:04:37 +02:00
HashMap < _EdgeKey , bool , _EdgeKey > edge_map ;
2020-02-17 22:06:54 +01:00
Vector < Vector3 > tmeshfaces ;
2015-10-08 20:00:40 +02:00
tmeshfaces . resize ( faces . size ( ) * 3 ) ;
{
2020-02-17 22:06:54 +01:00
Vector3 * tw = tmeshfaces . ptrw ( ) ;
2015-10-08 20:00:40 +02:00
int tidx = 0 ;
2021-07-24 15:46:25 +02:00
for ( const Face3 & f : faces ) {
2015-10-08 20:00:40 +02:00
for ( int j = 0 ; j < 3 ; j + + ) {
tw [ tidx + + ] = f . vertex [ j ] ;
_EdgeKey ek ;
2017-06-30 20:47:17 +02:00
ek . from = f . vertex [ j ] . snapped ( Vector3 ( CMP_EPSILON , CMP_EPSILON , CMP_EPSILON ) ) ;
ek . to = f . vertex [ ( j + 1 ) % 3 ] . snapped ( Vector3 ( CMP_EPSILON , CMP_EPSILON , CMP_EPSILON ) ) ;
2020-05-14 16:41:43 +02:00
if ( ek . from < ek . to ) {
2015-10-08 20:00:40 +02:00
SWAP ( ek . from , ek . to ) ;
2020-05-14 16:41:43 +02:00
}
2015-10-08 20:00:40 +02:00
2022-05-13 15:04:37 +02:00
HashMap < _EdgeKey , bool , _EdgeKey > : : Iterator F = edge_map . find ( ek ) ;
2015-10-08 20:00:40 +02:00
2019-02-12 21:10:08 +01:00
if ( F ) {
2022-05-13 15:04:37 +02:00
F - > value = false ;
2015-10-08 20:00:40 +02:00
} else {
edge_map [ ek ] = true ;
}
}
}
}
Vector < Vector3 > lines ;
2021-08-09 22:13:42 +02:00
for ( const KeyValue < _EdgeKey , bool > & E : edge_map ) {
if ( E . value ) {
lines . push_back ( E . key . from ) ;
lines . push_back ( E . key . to ) ;
2015-10-08 20:00:40 +02:00
}
}
2015-12-12 18:06:27 +01:00
Ref < TriangleMesh > tmesh = memnew ( TriangleMesh ) ;
2015-10-08 20:00:40 +02:00
tmesh - > create ( tmeshfaces ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_triangles ( tmesh ) ;
2022-08-07 08:54:57 +02:00
p_gizmo - > add_collision_segments ( lines ) ;
2022-07-01 18:58:03 +02:00
Ref < ArrayMesh > debug_mesh = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
int polygon_count = navigationmesh - > get_polygon_count ( ) ;
// build geometry face surface
Vector < Vector3 > face_vertex_array ;
face_vertex_array . resize ( polygon_count * 3 ) ;
for ( int i = 0 ; i < polygon_count ; i + + ) {
Vector < int > polygon = navigationmesh - > get_polygon ( i ) ;
face_vertex_array . push_back ( vertices [ polygon [ 0 ] ] ) ;
face_vertex_array . push_back ( vertices [ polygon [ 1 ] ] ) ;
face_vertex_array . push_back ( vertices [ polygon [ 2 ] ] ) ;
}
Array face_mesh_array ;
face_mesh_array . resize ( Mesh : : ARRAY_MAX ) ;
face_mesh_array [ Mesh : : ARRAY_VERTEX ] = face_vertex_array ;
// if enabled add vertex colors to colorize each face individually
2022-08-07 08:54:57 +02:00
RandomPCG rand ;
2022-07-01 18:58:03 +02:00
bool enabled_geometry_face_random_color = NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_enable_geometry_face_random_color ( ) ;
if ( enabled_geometry_face_random_color ) {
Color debug_navigation_geometry_face_color = NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_geometry_face_color ( ) ;
Color polygon_color = debug_navigation_geometry_face_color ;
Vector < Color > face_color_array ;
face_color_array . resize ( polygon_count * 3 ) ;
for ( int i = 0 ; i < polygon_count ; i + + ) {
2022-08-07 08:54:57 +02:00
// Generate the polygon color, slightly randomly modified from the settings one.
polygon_color . set_hsv ( debug_navigation_geometry_face_color . get_h ( ) + rand . random ( - 1.0 , 1.0 ) * 0.1 , debug_navigation_geometry_face_color . get_s ( ) , debug_navigation_geometry_face_color . get_v ( ) + rand . random ( - 1.0 , 1.0 ) * 0.2 ) ;
polygon_color . a = debug_navigation_geometry_face_color . a ;
2022-07-01 18:58:03 +02:00
Vector < int > polygon = navigationmesh - > get_polygon ( i ) ;
face_color_array . push_back ( polygon_color ) ;
face_color_array . push_back ( polygon_color ) ;
face_color_array . push_back ( polygon_color ) ;
}
face_mesh_array [ Mesh : : ARRAY_COLOR ] = face_color_array ;
}
debug_mesh - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , face_mesh_array ) ;
2022-08-07 08:54:57 +02:00
p_gizmo - > add_mesh ( debug_mesh , navigationregion - > is_enabled ( ) ? get_material ( " face_material " , p_gizmo ) : get_material ( " face_material_disabled " , p_gizmo ) ) ;
2022-07-01 18:58:03 +02:00
// if enabled build geometry edge line surface
bool enabled_edge_lines = NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_enable_edge_lines ( ) ;
if ( enabled_edge_lines ) {
Vector < Vector3 > line_vertex_array ;
line_vertex_array . resize ( polygon_count * 6 ) ;
for ( int i = 0 ; i < polygon_count ; i + + ) {
Vector < int > polygon = navigationmesh - > get_polygon ( i ) ;
line_vertex_array . push_back ( vertices [ polygon [ 0 ] ] ) ;
line_vertex_array . push_back ( vertices [ polygon [ 1 ] ] ) ;
line_vertex_array . push_back ( vertices [ polygon [ 1 ] ] ) ;
line_vertex_array . push_back ( vertices [ polygon [ 2 ] ] ) ;
line_vertex_array . push_back ( vertices [ polygon [ 2 ] ] ) ;
line_vertex_array . push_back ( vertices [ polygon [ 0 ] ] ) ;
}
2022-08-07 08:54:57 +02:00
p_gizmo - > add_lines ( line_vertex_array , navigationregion - > is_enabled ( ) ? get_material ( " edge_material " , p_gizmo ) : get_material ( " edge_material_disabled " , p_gizmo ) ) ;
2022-07-01 18:58:03 +02:00
}
2015-10-08 20:00:40 +02:00
}
2022-01-31 00:39:52 +01:00
////
NavigationLink3DGizmoPlugin : : NavigationLink3DGizmoPlugin ( ) {
create_material ( " navigation_link_material " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_link_connection_color ( ) ) ;
create_material ( " navigation_link_material_disabled " , NavigationServer3D : : get_singleton ( ) - > get_debug_navigation_link_connection_disabled_color ( ) ) ;
create_handle_material ( " handles " ) ;
}
bool NavigationLink3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return Object : : cast_to < NavigationLink3D > ( p_spatial ) ! = nullptr ;
}
String NavigationLink3DGizmoPlugin : : get_gizmo_name ( ) const {
return " NavigationLink3D " ;
}
int NavigationLink3DGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
void NavigationLink3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
NavigationLink3D * link = Object : : cast_to < NavigationLink3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-01-31 00:39:52 +01:00
RID nav_map = link - > get_world_3d ( ) - > get_navigation_map ( ) ;
real_t search_radius = NavigationServer3D : : get_singleton ( ) - > map_get_link_connection_radius ( nav_map ) ;
Vector3 up_vector = NavigationServer3D : : get_singleton ( ) - > map_get_up ( nav_map ) ;
Vector3 : : Axis up_axis = up_vector . max_axis_index ( ) ;
Vector3 start_location = link - > get_start_location ( ) ;
Vector3 end_location = link - > get_end_location ( ) ;
Ref < Material > link_material = get_material ( " navigation_link_material " , p_gizmo ) ;
Ref < Material > link_material_disabled = get_material ( " navigation_link_material_disabled " , p_gizmo ) ;
Ref < Material > handles_material = get_material ( " handles " ) ;
p_gizmo - > clear ( ) ;
// Draw line between the points.
Vector < Vector3 > lines ;
lines . append ( start_location ) ;
lines . append ( end_location ) ;
// Draw start location search radius
for ( int i = 0 ; i < 30 ; i + + ) {
// Create a circle
const float ra = Math : : deg_to_rad ( ( float ) ( i * 12 ) ) ;
const float rb = Math : : deg_to_rad ( ( float ) ( ( i + 1 ) * 12 ) ) ;
const Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * search_radius ;
const Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * search_radius ;
// Draw axis-aligned circle
switch ( up_axis ) {
case Vector3 : : AXIS_X :
lines . append ( start_location + Vector3 ( 0 , a . x , a . y ) ) ;
lines . append ( start_location + Vector3 ( 0 , b . x , b . y ) ) ;
break ;
case Vector3 : : AXIS_Y :
lines . append ( start_location + Vector3 ( a . x , 0 , a . y ) ) ;
lines . append ( start_location + Vector3 ( b . x , 0 , b . y ) ) ;
break ;
case Vector3 : : AXIS_Z :
lines . append ( start_location + Vector3 ( a . x , a . y , 0 ) ) ;
lines . append ( start_location + Vector3 ( b . x , b . y , 0 ) ) ;
break ;
}
}
// Draw end location search radius
for ( int i = 0 ; i < 30 ; i + + ) {
// Create a circle
const float ra = Math : : deg_to_rad ( ( float ) ( i * 12 ) ) ;
const float rb = Math : : deg_to_rad ( ( float ) ( ( i + 1 ) * 12 ) ) ;
const Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * search_radius ;
const Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * search_radius ;
// Draw axis-aligned circle
switch ( up_axis ) {
case Vector3 : : AXIS_X :
lines . append ( end_location + Vector3 ( 0 , a . x , a . y ) ) ;
lines . append ( end_location + Vector3 ( 0 , b . x , b . y ) ) ;
break ;
case Vector3 : : AXIS_Y :
lines . append ( end_location + Vector3 ( a . x , 0 , a . y ) ) ;
lines . append ( end_location + Vector3 ( b . x , 0 , b . y ) ) ;
break ;
case Vector3 : : AXIS_Z :
lines . append ( end_location + Vector3 ( a . x , a . y , 0 ) ) ;
lines . append ( end_location + Vector3 ( b . x , b . y , 0 ) ) ;
break ;
}
}
p_gizmo - > add_lines ( lines , link - > is_enabled ( ) ? link_material : link_material_disabled ) ;
p_gizmo - > add_collision_segments ( lines ) ;
Vector < Vector3 > handles ;
handles . append ( start_location ) ;
handles . append ( end_location ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
String NavigationLink3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
return p_id = = 0 ? TTR ( " Start Location " ) : TTR ( " End Location " ) ;
}
Variant NavigationLink3DGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
NavigationLink3D * link = Object : : cast_to < NavigationLink3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-01-31 00:39:52 +01:00
return p_id = = 0 ? link - > get_start_location ( ) : link - > get_end_location ( ) ;
}
void NavigationLink3DGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
NavigationLink3D * link = Object : : cast_to < NavigationLink3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-01-31 00:39:52 +01:00
Transform3D gt = link - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
Transform3D ct = p_camera - > get_global_transform ( ) ;
Vector3 cam_dir = ct . basis . get_column ( Vector3 : : AXIS_Z ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 location = p_id = = 0 ? link - > get_start_location ( ) : link - > get_end_location ( ) ;
Plane move_plane = Plane ( cam_dir , gt . xform ( location ) ) ;
Vector3 intersection ;
if ( ! move_plane . intersects_ray ( ray_from , ray_dir , & intersection ) ) {
return ;
}
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
double snap = Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ;
intersection . snap ( Vector3 ( snap , snap , snap ) ) ;
}
location = gi . xform ( intersection ) ;
if ( p_id = = 0 ) {
link - > set_start_location ( location ) ;
} else if ( p_id = = 1 ) {
link - > set_end_location ( location ) ;
}
}
void NavigationLink3DGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
NavigationLink3D * link = Object : : cast_to < NavigationLink3D > ( p_gizmo - > get_node_3d ( ) ) ;
2022-01-31 00:39:52 +01:00
if ( p_cancel ) {
if ( p_id = = 0 ) {
link - > set_start_location ( p_restore ) ;
} else {
link - > set_end_location ( p_restore ) ;
}
return ;
}
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
if ( p_id = = 0 ) {
ur - > create_action ( TTR ( " Change Start Location " ) ) ;
ur - > add_do_method ( link , " set_start_location " , link - > get_start_location ( ) ) ;
ur - > add_undo_method ( link , " set_start_location " , p_restore ) ;
} else {
ur - > create_action ( TTR ( " Change End Location " ) ) ;
ur - > add_do_method ( link , " set_end_location " , link - > get_end_location ( ) ) ;
ur - > add_undo_method ( link , " set_end_location " , p_restore ) ;
}
ur - > commit_action ( ) ;
}
2018-08-21 21:28:06 +02:00
//////
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
# define BODY_A_RADIUS 0.25
# define BODY_B_RADIUS 0.27
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Basis JointGizmosDrawer : : look_body ( const Transform3D & p_joint_transform , const Transform3D & p_body_transform ) {
2017-12-16 14:05:19 +01:00
const Vector3 & p_eye ( p_joint_transform . origin ) ;
const Vector3 & p_target ( p_body_transform . origin ) ;
2017-08-26 05:40:45 +02:00
2017-12-16 14:05:19 +01:00
Vector3 v_x , v_y , v_z ;
2017-08-26 05:40:45 +02:00
2017-12-16 14:05:19 +01:00
// Look the body with X
v_x = p_target - p_eye ;
v_x . normalize ( ) ;
v_z = v_x . cross ( Vector3 ( 0 , 1 , 0 ) ) ;
v_z . normalize ( ) ;
v_y = v_z . cross ( v_x ) ;
v_y . normalize ( ) ;
Basis base ;
2022-05-03 14:50:35 +02:00
base . set_columns ( v_x , v_y , v_z ) ;
2017-12-16 14:05:19 +01:00
// Absorb current joint transform
base = p_joint_transform . basis . inverse ( ) * base ;
return base ;
2015-10-08 20:00:40 +02:00
}
2020-10-17 07:08:21 +02:00
Basis JointGizmosDrawer : : look_body_toward ( Vector3 : : Axis p_axis , const Transform3D & joint_transform , const Transform3D & body_transform ) {
2017-12-16 14:05:19 +01:00
switch ( p_axis ) {
case Vector3 : : AXIS_X :
return look_body_toward_x ( joint_transform , body_transform ) ;
case Vector3 : : AXIS_Y :
return look_body_toward_y ( joint_transform , body_transform ) ;
case Vector3 : : AXIS_Z :
return look_body_toward_z ( joint_transform , body_transform ) ;
default :
return Basis ( ) ;
}
2015-10-08 20:00:40 +02:00
}
2020-10-17 07:08:21 +02:00
Basis JointGizmosDrawer : : look_body_toward_x ( const Transform3D & p_joint_transform , const Transform3D & p_body_transform ) {
2017-12-16 14:05:19 +01:00
const Vector3 & p_eye ( p_joint_transform . origin ) ;
const Vector3 & p_target ( p_body_transform . origin ) ;
2015-10-08 20:00:40 +02:00
2022-05-03 14:50:35 +02:00
const Vector3 p_front ( p_joint_transform . basis . get_column ( 0 ) ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
Vector3 v_x , v_y , v_z ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Look the body with X
v_x = p_target - p_eye ;
v_x . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_y = p_front . cross ( v_x ) ;
v_y . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_z = v_y . cross ( p_front ) ;
v_z . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Clamp X to FRONT axis
v_x = p_front ;
v_x . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
Basis base ;
2022-05-03 14:50:35 +02:00
base . set_columns ( v_x , v_y , v_z ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Absorb current joint transform
base = p_joint_transform . basis . inverse ( ) * base ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
return base ;
}
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
Basis JointGizmosDrawer : : look_body_toward_y ( const Transform3D & p_joint_transform , const Transform3D & p_body_transform ) {
2017-12-16 14:05:19 +01:00
const Vector3 & p_eye ( p_joint_transform . origin ) ;
const Vector3 & p_target ( p_body_transform . origin ) ;
2015-10-08 20:00:40 +02:00
2022-05-03 14:50:35 +02:00
const Vector3 p_up ( p_joint_transform . basis . get_column ( 1 ) ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
Vector3 v_x , v_y , v_z ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Look the body with X
v_x = p_target - p_eye ;
v_x . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_z = v_x . cross ( p_up ) ;
v_z . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_x = p_up . cross ( v_z ) ;
v_x . normalize ( ) ;
2017-08-26 05:40:45 +02:00
2017-12-16 14:05:19 +01:00
// Clamp Y to UP axis
v_y = p_up ;
v_y . normalize ( ) ;
2017-08-26 05:40:45 +02:00
2017-12-16 14:05:19 +01:00
Basis base ;
2022-05-03 14:50:35 +02:00
base . set_columns ( v_x , v_y , v_z ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Absorb current joint transform
base = p_joint_transform . basis . inverse ( ) * base ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
return base ;
2015-10-08 20:00:40 +02:00
}
2020-10-17 07:08:21 +02:00
Basis JointGizmosDrawer : : look_body_toward_z ( const Transform3D & p_joint_transform , const Transform3D & p_body_transform ) {
2017-12-16 14:05:19 +01:00
const Vector3 & p_eye ( p_joint_transform . origin ) ;
const Vector3 & p_target ( p_body_transform . origin ) ;
2015-10-08 20:00:40 +02:00
2022-05-03 14:50:35 +02:00
const Vector3 p_lateral ( p_joint_transform . basis . get_column ( 2 ) ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
Vector3 v_x , v_y , v_z ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Look the body with X
v_x = p_target - p_eye ;
v_x . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_z = p_lateral ;
v_z . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
v_y = v_z . cross ( v_x ) ;
v_y . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Clamp X to Z axis
v_x = v_y . cross ( v_z ) ;
v_x . normalize ( ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
Basis base ;
2022-05-03 14:50:35 +02:00
base . set_columns ( v_x , v_y , v_z ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
// Absorb current joint transform
base = p_joint_transform . basis . inverse ( ) * base ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
return base ;
}
2015-10-08 20:00:40 +02:00
2020-10-17 07:08:21 +02:00
void JointGizmosDrawer : : draw_circle ( Vector3 : : Axis p_axis , real_t p_radius , const Transform3D & p_offset , const Basis & p_base , real_t p_limit_lower , real_t p_limit_upper , Vector < Vector3 > & r_points , bool p_inverse ) {
2017-12-16 14:05:19 +01:00
if ( p_limit_lower = = p_limit_upper ) {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( Vector3 ( ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( 0.5 , 0 , 0 ) ) ) . origin ) ;
2015-10-08 20:00:40 +02:00
} else {
2017-12-16 14:05:19 +01:00
if ( p_limit_lower > p_limit_upper ) {
p_limit_lower = - Math_PI ;
p_limit_upper = Math_PI ;
}
2015-10-08 20:00:40 +02:00
const int points = 32 ;
for ( int i = 0 ; i < points ; i + + ) {
2017-12-16 14:05:19 +01:00
real_t s = p_limit_lower + i * ( p_limit_upper - p_limit_lower ) / points ;
real_t n = p_limit_lower + ( i + 1 ) * ( p_limit_upper - p_limit_lower ) / points ;
Vector3 from ;
Vector3 to ;
switch ( p_axis ) {
case Vector3 : : AXIS_X :
if ( p_inverse ) {
from = p_base . xform ( Vector3 ( 0 , Math : : sin ( s ) , Math : : cos ( s ) ) ) * p_radius ;
to = p_base . xform ( Vector3 ( 0 , Math : : sin ( n ) , Math : : cos ( n ) ) ) * p_radius ;
} else {
from = p_base . xform ( Vector3 ( 0 , - Math : : sin ( s ) , Math : : cos ( s ) ) ) * p_radius ;
to = p_base . xform ( Vector3 ( 0 , - Math : : sin ( n ) , Math : : cos ( n ) ) ) * p_radius ;
}
break ;
case Vector3 : : AXIS_Y :
if ( p_inverse ) {
from = p_base . xform ( Vector3 ( Math : : cos ( s ) , 0 , - Math : : sin ( s ) ) ) * p_radius ;
to = p_base . xform ( Vector3 ( Math : : cos ( n ) , 0 , - Math : : sin ( n ) ) ) * p_radius ;
} else {
from = p_base . xform ( Vector3 ( Math : : cos ( s ) , 0 , Math : : sin ( s ) ) ) * p_radius ;
to = p_base . xform ( Vector3 ( Math : : cos ( n ) , 0 , Math : : sin ( n ) ) ) * p_radius ;
}
break ;
case Vector3 : : AXIS_Z :
from = p_base . xform ( Vector3 ( Math : : cos ( s ) , Math : : sin ( s ) , 0 ) ) * p_radius ;
to = p_base . xform ( Vector3 ( Math : : cos ( n ) , Math : : sin ( n ) , 0 ) ) * p_radius ;
break ;
}
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
if ( i = = points - 1 ) {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( to ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
}
if ( i = = 0 ) {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( from ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
}
2015-10-08 20:00:40 +02:00
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( from ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( to ) . origin ) ;
2015-10-08 20:00:40 +02:00
}
2017-08-26 05:40:45 +02:00
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , p_radius * 1.5 , 0 ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
}
2015-10-08 20:00:40 +02:00
}
2020-10-17 07:08:21 +02:00
void JointGizmosDrawer : : draw_cone ( const Transform3D & p_offset , const Basis & p_base , real_t p_swing , real_t p_twist , Vector < Vector3 > & r_points ) {
2015-10-08 20:00:40 +02:00
float r = 1.0 ;
2017-12-16 14:05:19 +01:00
float w = r * Math : : sin ( p_swing ) ;
float d = r * Math : : cos ( p_swing ) ;
2015-10-08 20:00:40 +02:00
//swing
for ( int i = 0 ; i < 360 ; i + = 10 ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 10 ) ;
2015-10-08 20:00:40 +02:00
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * w ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * w ;
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( d , a . x , a . y ) ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( d , b . x , b . y ) ) ) . origin ) ;
2015-10-08 20:00:40 +02:00
if ( i % 90 = = 0 ) {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( d , a . x , a . y ) ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( ) ) ) . origin ) ;
2015-10-08 20:00:40 +02:00
}
}
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( ) ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( 1 , 0 , 0 ) ) ) . origin ) ;
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
/// Twist
2022-08-13 17:45:42 +02:00
float ts = Math : : rad_to_deg ( p_twist ) ;
2015-10-08 20:00:40 +02:00
ts = MIN ( ts , 720 ) ;
for ( int i = 0 ; i < int ( ts ) ; i + = 5 ) {
2022-08-13 17:45:42 +02:00
float ra = Math : : deg_to_rad ( ( float ) i ) ;
float rb = Math : : deg_to_rad ( ( float ) i + 5 ) ;
2015-10-08 20:00:40 +02:00
float c = i / 720.0 ;
float cn = ( i + 5 ) / 720.0 ;
Point2 a = Vector2 ( Math : : sin ( ra ) , Math : : cos ( ra ) ) * w * c ;
Point2 b = Vector2 ( Math : : sin ( rb ) , Math : : cos ( rb ) ) * w * cn ;
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( c , a . x , a . y ) ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( p_base . xform ( Vector3 ( cn , b . x , b . y ) ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
}
}
2018-07-25 00:08:49 +02:00
////
2017-12-16 14:05:19 +01:00
2020-04-06 12:40:52 +02:00
Joint3DGizmoPlugin : : Joint3DGizmoPlugin ( ) {
2022-03-06 21:39:19 +01:00
create_material ( " joint_material " , EDITOR_GET ( " editors/3d_gizmos/gizmo_colors/joint " ) ) ;
2018-07-25 00:08:49 +02:00
create_material ( " joint_body_a_material " , EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/joint_body_a " , Color ( 0.6 , 0.8 , 1 ) ) ) ;
create_material ( " joint_body_b_material " , EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/joint_body_b " , Color ( 0.6 , 0.9 , 1 ) ) ) ;
2020-03-20 12:41:07 +01:00
update_timer = memnew ( Timer ) ;
update_timer - > set_name ( " JointGizmoUpdateTimer " ) ;
update_timer - > set_wait_time ( 1.0 / 120.0 ) ;
update_timer - > connect ( " timeout " , callable_mp ( this , & Joint3DGizmoPlugin : : incremental_update_gizmos ) ) ;
update_timer - > set_autostart ( true ) ;
2021-07-17 23:22:52 +02:00
EditorNode : : get_singleton ( ) - > call_deferred ( SNAME ( " add_child " ) , update_timer ) ;
2020-03-20 12:41:07 +01:00
}
void Joint3DGizmoPlugin : : incremental_update_gizmos ( ) {
2020-12-15 13:04:21 +01:00
if ( ! current_gizmos . is_empty ( ) ) {
2020-03-20 12:41:07 +01:00
update_idx + + ;
update_idx = update_idx % current_gizmos . size ( ) ;
redraw ( current_gizmos [ update_idx ] ) ;
}
2017-12-16 14:05:19 +01:00
}
2015-10-08 20:00:40 +02:00
2020-04-06 12:40:52 +02:00
bool Joint3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2020-04-02 01:20:12 +02:00
return Object : : cast_to < Joint3D > ( p_spatial ) ! = nullptr ;
2018-07-25 00:08:49 +02:00
}
2017-12-16 14:05:19 +01:00
2020-07-23 00:39:21 +02:00
String Joint3DGizmoPlugin : : get_gizmo_name ( ) const {
2020-04-06 12:40:52 +02:00
return " Joint3D " ;
2018-07-25 00:08:49 +02:00
}
2017-12-16 14:05:19 +01:00
2020-04-06 12:40:52 +02:00
int Joint3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
return - 1 ;
}
2020-04-06 12:40:52 +02:00
void Joint3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Joint3D * joint = Object : : cast_to < Joint3D > ( p_gizmo - > get_node_3d ( ) ) ;
2017-12-16 14:05:19 +01:00
2018-07-25 00:08:49 +02:00
p_gizmo - > clear ( ) ;
2017-12-16 14:05:19 +01:00
2020-04-02 01:20:12 +02:00
Node3D * node_body_a = nullptr ;
2019-12-05 19:27:57 +01:00
if ( ! joint - > get_node_a ( ) . is_empty ( ) ) {
2020-03-26 22:49:16 +01:00
node_body_a = Object : : cast_to < Node3D > ( joint - > get_node ( joint - > get_node_a ( ) ) ) ;
2019-12-05 19:27:57 +01:00
}
2020-04-02 01:20:12 +02:00
Node3D * node_body_b = nullptr ;
2019-12-05 19:27:57 +01:00
if ( ! joint - > get_node_b ( ) . is_empty ( ) ) {
2020-03-26 22:49:16 +01:00
node_body_b = Object : : cast_to < Node3D > ( joint - > get_node ( joint - > get_node_b ( ) ) ) ;
2019-12-05 19:27:57 +01:00
}
if ( ! node_body_a & & ! node_body_b ) {
return ;
}
2017-12-16 14:05:19 +01:00
2018-07-25 00:08:49 +02:00
Ref < Material > common_material = get_material ( " joint_material " , p_gizmo ) ;
Ref < Material > body_a_material = get_material ( " joint_body_a_material " , p_gizmo ) ;
Ref < Material > body_b_material = get_material ( " joint_body_b_material " , p_gizmo ) ;
2017-12-16 14:05:19 +01:00
2018-07-25 00:08:49 +02:00
Vector < Vector3 > points ;
Vector < Vector3 > body_a_points ;
Vector < Vector3 > body_b_points ;
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < PinJoint3D > ( joint ) ) {
2020-10-17 07:08:21 +02:00
CreatePinJointGizmo ( Transform3D ( ) , points ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( points ) ;
p_gizmo - > add_lines ( points , common_material ) ;
}
2020-03-26 22:49:16 +01:00
HingeJoint3D * hinge = Object : : cast_to < HingeJoint3D > ( joint ) ;
2018-07-25 00:08:49 +02:00
if ( hinge ) {
CreateHingeJointGizmo (
2020-10-17 07:08:21 +02:00
Transform3D ( ) ,
2018-07-25 00:08:49 +02:00
hinge - > get_global_transform ( ) ,
2020-10-17 07:08:21 +02:00
node_body_a ? node_body_a - > get_global_transform ( ) : Transform3D ( ) ,
node_body_b ? node_body_b - > get_global_transform ( ) : Transform3D ( ) ,
2020-03-26 22:49:16 +01:00
hinge - > get_param ( HingeJoint3D : : PARAM_LIMIT_LOWER ) ,
hinge - > get_param ( HingeJoint3D : : PARAM_LIMIT_UPPER ) ,
hinge - > get_flag ( HingeJoint3D : : FLAG_USE_LIMIT ) ,
2018-07-25 00:08:49 +02:00
points ,
2020-04-02 01:20:12 +02:00
node_body_a ? & body_a_points : nullptr ,
node_body_b ? & body_b_points : nullptr ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( points ) ;
p_gizmo - > add_collision_segments ( body_a_points ) ;
p_gizmo - > add_collision_segments ( body_b_points ) ;
p_gizmo - > add_lines ( points , common_material ) ;
p_gizmo - > add_lines ( body_a_points , body_a_material ) ;
p_gizmo - > add_lines ( body_b_points , body_b_material ) ;
}
2020-03-26 22:49:16 +01:00
SliderJoint3D * slider = Object : : cast_to < SliderJoint3D > ( joint ) ;
2018-07-25 00:08:49 +02:00
if ( slider ) {
CreateSliderJointGizmo (
2020-10-17 07:08:21 +02:00
Transform3D ( ) ,
2018-07-25 00:08:49 +02:00
slider - > get_global_transform ( ) ,
2020-10-17 07:08:21 +02:00
node_body_a ? node_body_a - > get_global_transform ( ) : Transform3D ( ) ,
node_body_b ? node_body_b - > get_global_transform ( ) : Transform3D ( ) ,
2020-03-26 22:49:16 +01:00
slider - > get_param ( SliderJoint3D : : PARAM_ANGULAR_LIMIT_LOWER ) ,
slider - > get_param ( SliderJoint3D : : PARAM_ANGULAR_LIMIT_UPPER ) ,
slider - > get_param ( SliderJoint3D : : PARAM_LINEAR_LIMIT_LOWER ) ,
slider - > get_param ( SliderJoint3D : : PARAM_LINEAR_LIMIT_UPPER ) ,
2018-07-25 00:08:49 +02:00
points ,
2020-04-02 01:20:12 +02:00
node_body_a ? & body_a_points : nullptr ,
node_body_b ? & body_b_points : nullptr ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( points ) ;
p_gizmo - > add_collision_segments ( body_a_points ) ;
p_gizmo - > add_collision_segments ( body_b_points ) ;
p_gizmo - > add_lines ( points , common_material ) ;
p_gizmo - > add_lines ( body_a_points , body_a_material ) ;
p_gizmo - > add_lines ( body_b_points , body_b_material ) ;
}
2020-03-26 22:49:16 +01:00
ConeTwistJoint3D * cone = Object : : cast_to < ConeTwistJoint3D > ( joint ) ;
2018-07-25 00:08:49 +02:00
if ( cone ) {
CreateConeTwistJointGizmo (
2020-10-17 07:08:21 +02:00
Transform3D ( ) ,
2018-07-25 00:08:49 +02:00
cone - > get_global_transform ( ) ,
2020-10-17 07:08:21 +02:00
node_body_a ? node_body_a - > get_global_transform ( ) : Transform3D ( ) ,
node_body_b ? node_body_b - > get_global_transform ( ) : Transform3D ( ) ,
2020-03-26 22:49:16 +01:00
cone - > get_param ( ConeTwistJoint3D : : PARAM_SWING_SPAN ) ,
cone - > get_param ( ConeTwistJoint3D : : PARAM_TWIST_SPAN ) ,
2020-04-02 01:20:12 +02:00
node_body_a ? & body_a_points : nullptr ,
node_body_b ? & body_b_points : nullptr ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( body_a_points ) ;
p_gizmo - > add_collision_segments ( body_b_points ) ;
p_gizmo - > add_lines ( body_a_points , body_a_material ) ;
p_gizmo - > add_lines ( body_b_points , body_b_material ) ;
}
2020-03-26 22:49:16 +01:00
Generic6DOFJoint3D * gen = Object : : cast_to < Generic6DOFJoint3D > ( joint ) ;
2018-07-25 00:08:49 +02:00
if ( gen ) {
CreateGeneric6DOFJointGizmo (
2020-10-17 07:08:21 +02:00
Transform3D ( ) ,
2018-07-25 00:08:49 +02:00
gen - > get_global_transform ( ) ,
2020-10-17 07:08:21 +02:00
node_body_a ? node_body_a - > get_global_transform ( ) : Transform3D ( ) ,
node_body_b ? node_body_b - > get_global_transform ( ) : Transform3D ( ) ,
2018-07-25 00:08:49 +02:00
2020-03-26 22:49:16 +01:00
gen - > get_param_x ( Generic6DOFJoint3D : : PARAM_ANGULAR_LOWER_LIMIT ) ,
gen - > get_param_x ( Generic6DOFJoint3D : : PARAM_ANGULAR_UPPER_LIMIT ) ,
gen - > get_param_x ( Generic6DOFJoint3D : : PARAM_LINEAR_LOWER_LIMIT ) ,
gen - > get_param_x ( Generic6DOFJoint3D : : PARAM_LINEAR_UPPER_LIMIT ) ,
gen - > get_flag_x ( Generic6DOFJoint3D : : FLAG_ENABLE_ANGULAR_LIMIT ) ,
gen - > get_flag_x ( Generic6DOFJoint3D : : FLAG_ENABLE_LINEAR_LIMIT ) ,
gen - > get_param_y ( Generic6DOFJoint3D : : PARAM_ANGULAR_LOWER_LIMIT ) ,
gen - > get_param_y ( Generic6DOFJoint3D : : PARAM_ANGULAR_UPPER_LIMIT ) ,
gen - > get_param_y ( Generic6DOFJoint3D : : PARAM_LINEAR_LOWER_LIMIT ) ,
gen - > get_param_y ( Generic6DOFJoint3D : : PARAM_LINEAR_UPPER_LIMIT ) ,
gen - > get_flag_y ( Generic6DOFJoint3D : : FLAG_ENABLE_ANGULAR_LIMIT ) ,
gen - > get_flag_y ( Generic6DOFJoint3D : : FLAG_ENABLE_LINEAR_LIMIT ) ,
gen - > get_param_z ( Generic6DOFJoint3D : : PARAM_ANGULAR_LOWER_LIMIT ) ,
gen - > get_param_z ( Generic6DOFJoint3D : : PARAM_ANGULAR_UPPER_LIMIT ) ,
gen - > get_param_z ( Generic6DOFJoint3D : : PARAM_LINEAR_LOWER_LIMIT ) ,
gen - > get_param_z ( Generic6DOFJoint3D : : PARAM_LINEAR_UPPER_LIMIT ) ,
gen - > get_flag_z ( Generic6DOFJoint3D : : FLAG_ENABLE_ANGULAR_LIMIT ) ,
gen - > get_flag_z ( Generic6DOFJoint3D : : FLAG_ENABLE_LINEAR_LIMIT ) ,
2018-07-25 00:08:49 +02:00
points ,
2020-04-02 01:20:12 +02:00
node_body_a ? & body_a_points : nullptr ,
node_body_a ? & body_b_points : nullptr ) ;
2018-07-25 00:08:49 +02:00
p_gizmo - > add_collision_segments ( points ) ;
p_gizmo - > add_collision_segments ( body_a_points ) ;
p_gizmo - > add_collision_segments ( body_b_points ) ;
p_gizmo - > add_lines ( points , common_material ) ;
p_gizmo - > add_lines ( body_a_points , body_a_material ) ;
p_gizmo - > add_lines ( body_b_points , body_b_material ) ;
}
}
2020-10-17 07:08:21 +02:00
void Joint3DGizmoPlugin : : CreatePinJointGizmo ( const Transform3D & p_offset , Vector < Vector3 > & r_cursor_points ) {
2018-07-25 00:08:49 +02:00
float cs = 0.25 ;
2022-07-16 11:47:54 +02:00
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( + cs , 0 , 0 ) ) . origin ) ;
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( - cs , 0 , 0 ) ) . origin ) ;
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , + cs , 0 ) ) . origin ) ;
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , - cs , 0 ) ) . origin ) ;
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , + cs ) ) . origin ) ;
r_cursor_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , - cs ) ) . origin ) ;
2018-07-25 00:08:49 +02:00
}
2017-12-16 14:05:19 +01:00
2020-10-17 07:08:21 +02:00
void Joint3DGizmoPlugin : : CreateHingeJointGizmo ( const Transform3D & p_offset , const Transform3D & p_trs_joint , const Transform3D & p_trs_body_a , const Transform3D & p_trs_body_b , real_t p_limit_lower , real_t p_limit_upper , bool p_use_limit , Vector < Vector3 > & r_common_points , Vector < Vector3 > * r_body_a_points , Vector < Vector3 > * r_body_b_points ) {
2022-07-16 11:47:54 +02:00
r_common_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , 0.5 ) ) . origin ) ;
r_common_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , - 0.5 ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
if ( ! p_use_limit ) {
p_limit_upper = - 1 ;
p_limit_lower = 0 ;
2015-10-08 20:00:40 +02:00
}
2017-12-16 14:05:19 +01:00
if ( r_body_a_points ) {
JointGizmosDrawer : : draw_circle ( Vector3 : : AXIS_Z ,
BODY_A_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward_z ( p_trs_joint , p_trs_body_a ) ,
p_limit_lower ,
p_limit_upper ,
* r_body_a_points ) ;
}
if ( r_body_b_points ) {
JointGizmosDrawer : : draw_circle ( Vector3 : : AXIS_Z ,
BODY_B_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward_z ( p_trs_joint , p_trs_body_b ) ,
p_limit_lower ,
p_limit_upper ,
* r_body_b_points ) ;
}
}
2020-10-17 07:08:21 +02:00
void Joint3DGizmoPlugin : : CreateSliderJointGizmo ( const Transform3D & p_offset , const Transform3D & p_trs_joint , const Transform3D & p_trs_body_a , const Transform3D & p_trs_body_b , real_t p_angular_limit_lower , real_t p_angular_limit_upper , real_t p_linear_limit_lower , real_t p_linear_limit_upper , Vector < Vector3 > & r_points , Vector < Vector3 > * r_body_a_points , Vector < Vector3 > * r_body_b_points ) {
2017-12-16 14:05:19 +01:00
p_linear_limit_lower = - p_linear_limit_lower ;
p_linear_limit_upper = - p_linear_limit_upper ;
float cs = 0.25 ;
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , 0.5 ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( 0 , 0 , - 0.5 ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
if ( p_linear_limit_lower > = p_linear_limit_upper ) {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , 0 , 0 ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , 0 , 0 ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , - cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , - cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , - cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_upper , - cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , - cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , - cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , - cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , cs , cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , cs , - cs ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( p_linear_limit_lower , - cs , - cs ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
} else {
2022-07-16 11:47:54 +02:00
r_points . push_back ( p_offset . translated_local ( Vector3 ( + cs * 2 , 0 , 0 ) ) . origin ) ;
r_points . push_back ( p_offset . translated_local ( Vector3 ( - cs * 2 , 0 , 0 ) ) . origin ) ;
2017-12-16 14:05:19 +01:00
}
2020-05-14 16:41:43 +02:00
if ( r_body_a_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_circle (
Vector3 : : AXIS_X ,
BODY_A_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward ( Vector3 : : AXIS_X , p_trs_joint , p_trs_body_a ) ,
p_angular_limit_lower ,
p_angular_limit_upper ,
* r_body_a_points ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
2020-05-14 16:41:43 +02:00
if ( r_body_b_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_circle (
Vector3 : : AXIS_X ,
BODY_B_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward ( Vector3 : : AXIS_X , p_trs_joint , p_trs_body_b ) ,
p_angular_limit_lower ,
p_angular_limit_upper ,
* r_body_b_points ,
true ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
}
2020-10-17 07:08:21 +02:00
void Joint3DGizmoPlugin : : CreateConeTwistJointGizmo ( const Transform3D & p_offset , const Transform3D & p_trs_joint , const Transform3D & p_trs_body_a , const Transform3D & p_trs_body_b , real_t p_swing , real_t p_twist , Vector < Vector3 > * r_body_a_points , Vector < Vector3 > * r_body_b_points ) {
2020-05-14 16:41:43 +02:00
if ( r_body_a_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_cone (
p_offset ,
JointGizmosDrawer : : look_body ( p_trs_joint , p_trs_body_a ) ,
p_swing ,
p_twist ,
* r_body_a_points ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
2020-05-14 16:41:43 +02:00
if ( r_body_b_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_cone (
p_offset ,
JointGizmosDrawer : : look_body ( p_trs_joint , p_trs_body_b ) ,
p_swing ,
p_twist ,
* r_body_b_points ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
}
2020-04-06 12:40:52 +02:00
void Joint3DGizmoPlugin : : CreateGeneric6DOFJointGizmo (
2020-10-17 07:08:21 +02:00
const Transform3D & p_offset ,
const Transform3D & p_trs_joint ,
const Transform3D & p_trs_body_a ,
const Transform3D & p_trs_body_b ,
2017-12-16 14:05:19 +01:00
real_t p_angular_limit_lower_x ,
real_t p_angular_limit_upper_x ,
real_t p_linear_limit_lower_x ,
real_t p_linear_limit_upper_x ,
bool p_enable_angular_limit_x ,
bool p_enable_linear_limit_x ,
real_t p_angular_limit_lower_y ,
real_t p_angular_limit_upper_y ,
real_t p_linear_limit_lower_y ,
real_t p_linear_limit_upper_y ,
bool p_enable_angular_limit_y ,
bool p_enable_linear_limit_y ,
real_t p_angular_limit_lower_z ,
real_t p_angular_limit_upper_z ,
real_t p_linear_limit_lower_z ,
real_t p_linear_limit_upper_z ,
bool p_enable_angular_limit_z ,
bool p_enable_linear_limit_z ,
Vector < Vector3 > & r_points ,
Vector < Vector3 > * r_body_a_points ,
Vector < Vector3 > * r_body_b_points ) {
2015-10-08 20:00:40 +02:00
float cs = 0.25 ;
for ( int ax = 0 ; ax < 3 ; ax + + ) {
2018-10-04 18:54:20 +02:00
float ll = 0 ;
float ul = 0 ;
float lll = 0 ;
float lul = 0 ;
int a1 = 0 ;
int a2 = 0 ;
int a3 = 0 ;
bool enable_ang = false ;
bool enable_lin = false ;
2015-10-08 20:00:40 +02:00
switch ( ax ) {
case 0 :
2017-12-16 14:05:19 +01:00
ll = p_angular_limit_lower_x ;
ul = p_angular_limit_upper_x ;
lll = - p_linear_limit_lower_x ;
lul = - p_linear_limit_upper_x ;
enable_ang = p_enable_angular_limit_x ;
enable_lin = p_enable_linear_limit_x ;
2015-10-08 20:00:40 +02:00
a1 = 0 ;
a2 = 1 ;
a3 = 2 ;
break ;
case 1 :
2017-12-16 14:05:19 +01:00
ll = p_angular_limit_lower_y ;
ul = p_angular_limit_upper_y ;
lll = - p_linear_limit_lower_y ;
lul = - p_linear_limit_upper_y ;
enable_ang = p_enable_angular_limit_y ;
enable_lin = p_enable_linear_limit_y ;
2017-12-09 15:01:00 +01:00
a1 = 1 ;
a2 = 2 ;
a3 = 0 ;
2015-10-08 20:00:40 +02:00
break ;
case 2 :
2017-12-16 14:05:19 +01:00
ll = p_angular_limit_lower_z ;
ul = p_angular_limit_upper_z ;
lll = - p_linear_limit_lower_z ;
lul = - p_linear_limit_upper_z ;
enable_ang = p_enable_angular_limit_z ;
enable_lin = p_enable_linear_limit_z ;
2017-12-09 15:01:00 +01:00
a1 = 2 ;
a2 = 0 ;
a3 = 1 ;
2017-03-05 16:44:50 +01:00
break ;
2015-10-08 20:00:40 +02:00
}
2022-07-16 11:47:54 +02:00
# define ADD_VTX(x, y, z) \
{ \
Vector3 v ; \
v [ a1 ] = ( x ) ; \
v [ a2 ] = ( y ) ; \
v [ a3 ] = ( z ) ; \
r_points . push_back ( p_offset . translated_local ( v ) . origin ) ; \
2017-03-05 16:44:50 +01:00
}
2017-12-16 14:05:19 +01:00
if ( enable_lin & & lll > = lul ) {
2015-10-08 20:00:40 +02:00
ADD_VTX ( lul , 0 , 0 ) ;
ADD_VTX ( lll , 0 , 0 ) ;
2017-03-05 16:44:50 +01:00
2015-10-08 20:00:40 +02:00
ADD_VTX ( lul , - cs , - cs ) ;
ADD_VTX ( lul , - cs , cs ) ;
ADD_VTX ( lul , - cs , cs ) ;
ADD_VTX ( lul , cs , cs ) ;
ADD_VTX ( lul , cs , cs ) ;
ADD_VTX ( lul , cs , - cs ) ;
ADD_VTX ( lul , cs , - cs ) ;
ADD_VTX ( lul , - cs , - cs ) ;
2017-03-05 16:44:50 +01:00
2015-10-08 20:00:40 +02:00
ADD_VTX ( lll , - cs , - cs ) ;
ADD_VTX ( lll , - cs , cs ) ;
ADD_VTX ( lll , - cs , cs ) ;
ADD_VTX ( lll , cs , cs ) ;
ADD_VTX ( lll , cs , cs ) ;
ADD_VTX ( lll , cs , - cs ) ;
ADD_VTX ( lll , cs , - cs ) ;
ADD_VTX ( lll , - cs , - cs ) ;
} else {
ADD_VTX ( + cs * 2 , 0 , 0 ) ;
ADD_VTX ( - cs * 2 , 0 , 0 ) ;
}
2017-12-16 14:05:19 +01:00
if ( ! enable_ang ) {
ll = 0 ;
ul = - 1 ;
}
2015-10-08 20:00:40 +02:00
2020-05-14 16:41:43 +02:00
if ( r_body_a_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_circle (
static_cast < Vector3 : : Axis > ( ax ) ,
BODY_A_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward ( static_cast < Vector3 : : Axis > ( ax ) , p_trs_joint , p_trs_body_a ) ,
ll ,
ul ,
* r_body_a_points ,
true ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
2020-05-14 16:41:43 +02:00
if ( r_body_b_points ) {
2017-12-16 14:05:19 +01:00
JointGizmosDrawer : : draw_circle (
static_cast < Vector3 : : Axis > ( ax ) ,
BODY_B_RADIUS ,
p_offset ,
JointGizmosDrawer : : look_body_toward ( static_cast < Vector3 : : Axis > ( ax ) , p_trs_joint , p_trs_body_b ) ,
ll ,
ul ,
* r_body_b_points ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-16 14:05:19 +01:00
}
2015-10-08 20:00:40 +02:00
2017-12-16 14:05:19 +01:00
# undef ADD_VTX
}
2021-10-03 13:28:55 +02:00
////
FogVolumeGizmoPlugin : : FogVolumeGizmoPlugin ( ) {
Color gizmo_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/fog_volume " , Color ( 0.5 , 0.7 , 1 ) ) ;
create_material ( " shape_material " , gizmo_color ) ;
gizmo_color . a = 0.15 ;
create_material ( " shape_material_internal " , gizmo_color ) ;
create_handle_material ( " handles " ) ;
}
bool FogVolumeGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
return ( Object : : cast_to < FogVolume > ( p_spatial ) ! = nullptr ) ;
}
String FogVolumeGizmoPlugin : : get_gizmo_name ( ) const {
return " FogVolume " ;
}
int FogVolumeGizmoPlugin : : get_priority ( ) const {
return - 1 ;
}
2022-01-11 12:33:37 +01:00
String FogVolumeGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2021-10-03 13:28:55 +02:00
return " Extents " ;
}
2022-01-11 12:33:37 +01:00
Variant FogVolumeGizmoPlugin : : get_handle_value ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary ) const {
2022-09-08 18:38:33 +02:00
return Vector3 ( p_gizmo - > get_node_3d ( ) - > call ( " get_extents " ) ) ;
2021-10-03 13:28:55 +02:00
}
2022-01-11 12:33:37 +01:00
void FogVolumeGizmoPlugin : : set_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , Camera3D * p_camera , const Point2 & p_point ) {
2022-09-08 18:38:33 +02:00
Node3D * sn = p_gizmo - > get_node_3d ( ) ;
2021-10-03 13:28:55 +02:00
Transform3D gt = sn - > get_global_transform ( ) ;
Transform3D gi = gt . affine_inverse ( ) ;
Vector3 ray_from = p_camera - > project_ray_origin ( p_point ) ;
Vector3 ray_dir = p_camera - > project_ray_normal ( p_point ) ;
Vector3 sg [ 2 ] = { gi . xform ( ray_from ) , gi . xform ( ray_from + ray_dir * 4096 ) } ;
Vector3 axis ;
axis [ p_id ] = 1.0 ;
Vector3 ra , rb ;
Geometry3D : : get_closest_points_between_segments ( Vector3 ( ) , axis * 4096 , sg [ 0 ] , sg [ 1 ] , ra , rb ) ;
float d = ra [ p_id ] ;
if ( Node3DEditor : : get_singleton ( ) - > is_snap_enabled ( ) ) {
d = Math : : snapped ( d , Node3DEditor : : get_singleton ( ) - > get_translate_snap ( ) ) ;
}
if ( d < 0.001 ) {
d = 0.001 ;
}
Vector3 he = sn - > call ( " get_extents " ) ;
he [ p_id ] = d ;
sn - > call ( " set_extents " , he ) ;
}
2022-01-11 12:33:37 +01:00
void FogVolumeGizmoPlugin : : commit_handle ( const EditorNode3DGizmo * p_gizmo , int p_id , bool p_secondary , const Variant & p_restore , bool p_cancel ) {
2022-09-08 18:38:33 +02:00
Node3D * sn = p_gizmo - > get_node_3d ( ) ;
2021-10-03 13:28:55 +02:00
if ( p_cancel ) {
sn - > call ( " set_extents " , p_restore ) ;
return ;
}
2022-03-25 18:06:46 +01:00
Ref < EditorUndoRedoManager > & ur = EditorNode : : get_undo_redo ( ) ;
2021-10-03 13:28:55 +02:00
ur - > create_action ( TTR ( " Change Fog Volume Extents " ) ) ;
ur - > add_do_method ( sn , " set_extents " , sn - > call ( " get_extents " ) ) ;
ur - > add_undo_method ( sn , " set_extents " , p_restore ) ;
ur - > commit_action ( ) ;
}
void FogVolumeGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2022-09-08 18:38:33 +02:00
Node3D * cs = p_gizmo - > get_node_3d ( ) ;
2021-10-03 13:28:55 +02:00
p_gizmo - > clear ( ) ;
2022-09-08 18:38:33 +02:00
if ( RS : : FogVolumeShape ( int ( p_gizmo - > get_node_3d ( ) - > call ( " get_shape " ) ) ) ! = RS : : FOG_VOLUME_SHAPE_WORLD ) {
2021-10-03 13:28:55 +02:00
const Ref < Material > material =
get_material ( " shape_material " , p_gizmo ) ;
const Ref < Material > material_internal =
get_material ( " shape_material_internal " , p_gizmo ) ;
Ref < Material > handles_material = get_material ( " handles " ) ;
Vector < Vector3 > lines ;
AABB aabb ;
aabb . position = - cs - > call ( " get_extents " ) . operator Vector3 ( ) ;
aabb . size = aabb . position * - 2 ;
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
lines . push_back ( a ) ;
lines . push_back ( b ) ;
}
Vector < Vector3 > handles ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ax ;
ax [ i ] = cs - > call ( " get_extents " ) . operator Vector3 ( ) [ i ] ;
handles . push_back ( ax ) ;
}
p_gizmo - > add_lines ( lines , material ) ;
p_gizmo - > add_collision_segments ( lines ) ;
p_gizmo - > add_handles ( handles , handles_material ) ;
}
}
/////