2014-02-10 02:10:30 +01:00
/*************************************************************************/
2020-03-27 08:44:44 +01:00
/* node_3d_editor_plugin.cpp */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2014-02-10 02:10:30 +01:00
/*************************************************************************/
2021-01-01 20:13:46 +01:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 02:10:30 +01: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_plugin.h"
2014-02-10 02:10:30 +01:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2020-04-28 15:19:37 +02:00
# include "core/input/input.h"
2018-09-04 11:30:04 +02:00
# include "core/math/camera_matrix.h"
# include "core/os/keyboard.h"
2020-11-07 23:33:38 +01:00
# include "core/string/print_string.h"
# include "core/templates/sort_array.h"
2020-02-07 02:52:05 +01:00
# include "editor/debugger/editor_debugger_node.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_node.h"
2019-12-24 08:17:23 +01:00
# include "editor/editor_scale.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_settings.h"
2020-03-27 08:44:44 +01:00
# include "editor/node_3d_editor_gizmos.h"
2017-03-05 16:44:50 +01:00
# include "editor/plugins/animation_player_editor_plugin.h"
2017-09-02 21:47:16 +02:00
# include "editor/plugins/script_editor_plugin.h"
2020-03-26 22:49:16 +01:00
# include "scene/3d/camera_3d.h"
# include "scene/3d/collision_shape_3d.h"
# include "scene/3d/mesh_instance_3d.h"
# include "scene/3d/physics_body_3d.h"
# include "scene/3d/visual_instance_3d.h"
2020-04-01 20:28:09 +02:00
# include "scene/gui/subviewport_container.h"
2017-09-02 21:47:16 +02:00
# include "scene/resources/packed_scene.h"
2017-03-05 16:44:50 +01:00
# include "scene/resources/surface_tool.h"
2016-01-18 00:03:57 +01:00
2014-02-10 02:10:30 +01:00
# define DISTANCE_DEFAULT 4
2017-09-21 23:11:56 +02:00
# define GIZMO_ARROW_SIZE 0.35
2014-02-10 02:10:30 +01:00
# define GIZMO_RING_HALF_WIDTH 0.1
# define GIZMO_SCALE_DEFAULT 0.15
2017-08-29 03:39:45 +02:00
# define GIZMO_PLANE_SIZE 0.2
# define GIZMO_PLANE_DST 0.3
2017-09-21 23:11:56 +02:00
# define GIZMO_CIRCLE_SIZE 1.1
# define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
# define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
2014-02-10 02:10:30 +01:00
2020-06-22 05:40:17 +02:00
# define ZOOM_FREELOOK_MIN 0.01
# define ZOOM_FREELOOK_MULTIPLIER 1.08
# define ZOOM_FREELOOK_INDICATOR_DELAY_S 1.5
2017-05-07 22:59:05 +02:00
2020-06-22 05:40:17 +02:00
# ifdef REAL_T_IS_DOUBLE
# define ZOOM_FREELOOK_MAX 1'000'000'000'000
# else
# define ZOOM_FREELOOK_MAX 10'000
# endif
2017-05-07 22:59:05 +02:00
2017-08-04 13:23:10 +02:00
# define MIN_Z 0.01
2019-07-23 11:42:41 +02:00
# define MAX_Z 1000000.0
2017-08-04 13:23:10 +02:00
# define MIN_FOV 0.01
# define MAX_FOV 179
2019-10-23 11:46:26 +02:00
void ViewportRotationControl : : _notification ( int p_what ) {
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
axis_menu_options . clear ( ) ;
2020-03-26 22:49:16 +01:00
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_RIGHT ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_TOP ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_FRONT ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_LEFT ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_BOTTOM ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_REAR ) ;
2019-10-23 11:46:26 +02:00
axis_colors . clear ( ) ;
2020-03-12 13:37:40 +01:00
axis_colors . push_back ( get_theme_color ( " axis_x_color " , " Editor " ) ) ;
axis_colors . push_back ( get_theme_color ( " axis_y_color " , " Editor " ) ) ;
axis_colors . push_back ( get_theme_color ( " axis_z_color " , " Editor " ) ) ;
2019-10-23 11:46:26 +02:00
update ( ) ;
if ( ! is_connected ( " mouse_exited " , callable_mp ( this , & ViewportRotationControl : : _on_mouse_exited ) ) ) {
connect ( " mouse_exited " , callable_mp ( this , & ViewportRotationControl : : _on_mouse_exited ) ) ;
}
}
if ( p_what = = NOTIFICATION_DRAW & & viewport ! = nullptr ) {
_draw ( ) ;
}
}
void ViewportRotationControl : : _draw ( ) {
Vector2i center = get_size ( ) / 2.0 ;
float radius = get_size ( ) . x / 2.0 ;
if ( focused_axis > - 2 | | orbiting ) {
draw_circle ( center , radius , Color ( 0.5 , 0.5 , 0.5 , 0.25 ) ) ;
}
Vector < Axis2D > axis_to_draw ;
_get_sorted_axis ( axis_to_draw ) ;
for ( int i = 0 ; i < axis_to_draw . size ( ) ; + + i ) {
_draw_axis ( axis_to_draw [ i ] ) ;
}
}
void ViewportRotationControl : : _draw_axis ( const Axis2D & p_axis ) {
bool focused = focused_axis = = p_axis . axis ;
bool positive = p_axis . axis < 3 ;
bool front = ( Math : : abs ( p_axis . z_axis ) < = 0.001 & & positive ) | | p_axis . z_axis > 0.001 ;
int direction = p_axis . axis % 3 ;
Color axis_color = axis_colors [ direction ] ;
if ( ! front ) {
axis_color = axis_color . darkened ( 0.4 ) ;
}
Color c = focused ? Color ( 0.9 , 0.9 , 0.9 ) : axis_color ;
if ( positive ) {
Vector2i center = get_size ( ) / 2.0 ;
draw_line ( center , p_axis . screen_point , c , 1.5 * EDSCALE ) ;
}
if ( front ) {
String axis_name = direction = = 0 ? " X " : ( direction = = 1 ? " Y " : " Z " ) ;
draw_circle ( p_axis . screen_point , AXIS_CIRCLE_RADIUS , c ) ;
2020-09-03 13:22:16 +02:00
draw_char ( get_theme_font ( " rotation_control " , " EditorFonts " ) , p_axis . screen_point + Vector2i ( - 4 , 5 ) * EDSCALE , axis_name , " " , get_theme_font_size ( " rotation_control_size " , " EditorFonts " ) , Color ( 0.3 , 0.3 , 0.3 ) ) ;
2019-10-23 11:46:26 +02:00
} else {
draw_circle ( p_axis . screen_point , AXIS_CIRCLE_RADIUS * ( 0.55 + ( 0.2 * ( 1.0 + p_axis . z_axis ) ) ) , c ) ;
}
}
void ViewportRotationControl : : _get_sorted_axis ( Vector < Axis2D > & r_axis ) {
Vector2i center = get_size ( ) / 2.0 ;
float radius = get_size ( ) . x / 2.0 ;
float axis_radius = radius - AXIS_CIRCLE_RADIUS - 2.0 * EDSCALE ;
Basis camera_basis = viewport - > to_camera_transform ( viewport - > cursor ) . get_basis ( ) . inverse ( ) ;
for ( int i = 0 ; i < 3 ; + + i ) {
Vector3 axis_3d = camera_basis . get_axis ( i ) ;
Vector2i axis_vector = Vector2 ( axis_3d . x , - axis_3d . y ) * axis_radius ;
if ( Math : : abs ( axis_3d . z ) < 1.0 ) {
Axis2D pos_axis ;
pos_axis . axis = i ;
pos_axis . screen_point = center + axis_vector ;
pos_axis . z_axis = axis_3d . z ;
r_axis . push_back ( pos_axis ) ;
Axis2D neg_axis ;
neg_axis . axis = i + 3 ;
neg_axis . screen_point = center - axis_vector ;
neg_axis . z_axis = - axis_3d . z ;
r_axis . push_back ( neg_axis ) ;
} else {
// Special case when the camera is aligned with one axis
Axis2D axis ;
axis . axis = i + ( axis_3d . z < 0 ? 0 : 3 ) ;
axis . screen_point = center ;
axis . z_axis = 1.0 ;
r_axis . push_back ( axis ) ;
}
}
r_axis . sort_custom < Axis2DCompare > ( ) ;
}
void ViewportRotationControl : : _gui_input ( Ref < InputEvent > p_event ) {
const Ref < InputEventMouseButton > mb = p_event ;
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
Vector2 pos = mb - > get_position ( ) ;
if ( mb - > is_pressed ( ) ) {
if ( pos . distance_to ( get_size ( ) / 2.0 ) < get_size ( ) . x / 2.0 ) {
orbiting = true ;
}
} else {
if ( focused_axis > - 1 ) {
viewport - > _menu_option ( axis_menu_options [ focused_axis ] ) ;
_update_focus ( ) ;
}
orbiting = false ;
2020-04-28 16:41:01 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) = = Input : : MOUSE_MODE_CAPTURED ) {
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
Input : : get_singleton ( ) - > warp_mouse_position ( orbiting_mouse_start ) ;
}
2019-10-23 11:46:26 +02:00
}
}
const Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
if ( orbiting ) {
2020-04-28 16:41:01 +02:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) = = Input : : MOUSE_MODE_VISIBLE ) {
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_CAPTURED ) ;
orbiting_mouse_start = mm - > get_global_position ( ) ;
}
2019-10-23 11:46:26 +02:00
viewport - > _nav_orbit ( mm , viewport - > _get_warped_mouse_motion ( mm ) ) ;
focused_axis = - 1 ;
} else {
_update_focus ( ) ;
}
}
}
void ViewportRotationControl : : _update_focus ( ) {
int original_focus = focused_axis ;
focused_axis = - 2 ;
Vector2 mouse_pos = get_local_mouse_position ( ) ;
if ( mouse_pos . distance_to ( get_size ( ) / 2.0 ) < get_size ( ) . x / 2.0 ) {
focused_axis = - 1 ;
}
Vector < Axis2D > axes ;
_get_sorted_axis ( axes ) ;
for ( int i = 0 ; i < axes . size ( ) ; i + + ) {
const Axis2D & axis = axes [ i ] ;
if ( mouse_pos . distance_to ( axis . screen_point ) < AXIS_CIRCLE_RADIUS ) {
focused_axis = axis . axis ;
}
}
if ( focused_axis ! = original_focus ) {
update ( ) ;
}
}
void ViewportRotationControl : : _on_mouse_exited ( ) {
focused_axis = - 2 ;
update ( ) ;
}
2020-03-26 22:49:16 +01:00
void ViewportRotationControl : : set_viewport ( Node3DEditorViewport * p_viewport ) {
2019-10-23 11:46:26 +02:00
viewport = p_viewport ;
}
void ViewportRotationControl : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " _gui_input " ) , & ViewportRotationControl : : _gui_input ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _update_camera ( float p_interp_delta ) {
bool is_orthogonal = camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ;
2016-04-06 08:34:34 +02:00
2017-10-08 02:43:57 +02:00
Cursor old_camera_cursor = camera_cursor ;
camera_cursor = cursor ;
2017-09-16 17:12:11 +02:00
2017-10-08 02:43:57 +02:00
if ( p_interp_delta > 0 ) {
//-------
// Perform smoothing
2017-09-16 17:12:11 +02:00
2017-10-08 02:43:57 +02:00
if ( is_freelook_active ( ) ) {
// Higher inertia should increase "lag" (lerp with factor between 0 and 1)
// Inertia of zero should produce instant movement (lerp with factor of 1) in this case it returns a really high value and gets clamped to 1.
real_t inertia = EDITOR_GET ( " editors/3d/freelook/freelook_inertia " ) ;
inertia = MAX ( 0.001 , inertia ) ;
real_t factor = ( 1.0 / inertia ) * p_interp_delta ;
// We interpolate a different point here, because in freelook mode the focus point (cursor.pos) orbits around eye_pos
2020-03-16 10:07:33 +01:00
camera_cursor . eye_pos = old_camera_cursor . eye_pos . lerp ( cursor . eye_pos , CLAMP ( factor , 0 , 1 ) ) ;
2017-10-08 02:43:57 +02:00
float orbit_inertia = EDITOR_GET ( " editors/3d/navigation_feel/orbit_inertia " ) ;
orbit_inertia = MAX ( 0.0001 , orbit_inertia ) ;
camera_cursor . x_rot = Math : : lerp ( old_camera_cursor . x_rot , cursor . x_rot , MIN ( 1.f , p_interp_delta * ( 1 / orbit_inertia ) ) ) ;
camera_cursor . y_rot = Math : : lerp ( old_camera_cursor . y_rot , cursor . y_rot , MIN ( 1.f , p_interp_delta * ( 1 / orbit_inertia ) ) ) ;
2019-10-23 11:46:26 +02:00
if ( Math : : abs ( camera_cursor . x_rot - cursor . x_rot ) < 0.1 ) {
camera_cursor . x_rot = cursor . x_rot ;
}
if ( Math : : abs ( camera_cursor . y_rot - cursor . y_rot ) < 0.1 ) {
camera_cursor . y_rot = cursor . y_rot ;
}
2017-10-08 02:43:57 +02:00
Vector3 forward = to_camera_transform ( camera_cursor ) . basis . xform ( Vector3 ( 0 , 0 , - 1 ) ) ;
camera_cursor . pos = camera_cursor . eye_pos + forward * camera_cursor . distance ;
} else {
//when not being manipulated, move softly
float free_orbit_inertia = EDITOR_GET ( " editors/3d/navigation_feel/orbit_inertia " ) ;
float free_translation_inertia = EDITOR_GET ( " editors/3d/navigation_feel/translation_inertia " ) ;
//when being manipulated, move more quickly
float manip_orbit_inertia = EDITOR_GET ( " editors/3d/navigation_feel/manipulation_orbit_inertia " ) ;
float manip_translation_inertia = EDITOR_GET ( " editors/3d/navigation_feel/manipulation_translation_inertia " ) ;
2017-05-01 20:57:35 +02:00
2017-10-08 02:43:57 +02:00
float zoom_inertia = EDITOR_GET ( " editors/3d/navigation_feel/zoom_inertia " ) ;
2017-08-26 14:10:57 +02:00
2017-10-08 02:43:57 +02:00
//determine if being manipulated
2020-04-28 15:19:37 +02:00
bool manipulated = Input : : get_singleton ( ) - > get_mouse_button_mask ( ) & ( 2 | 4 ) ;
manipulated | = Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ;
manipulated | = Input : : get_singleton ( ) - > is_key_pressed ( KEY_ALT ) ;
manipulated | = Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ;
2017-10-08 02:43:57 +02:00
float orbit_inertia = MAX ( 0.00001 , manipulated ? manip_orbit_inertia : free_orbit_inertia ) ;
float translation_inertia = MAX ( 0.0001 , manipulated ? manip_translation_inertia : free_translation_inertia ) ;
zoom_inertia = MAX ( 0.0001 , zoom_inertia ) ;
camera_cursor . x_rot = Math : : lerp ( old_camera_cursor . x_rot , cursor . x_rot , MIN ( 1.f , p_interp_delta * ( 1 / orbit_inertia ) ) ) ;
camera_cursor . y_rot = Math : : lerp ( old_camera_cursor . y_rot , cursor . y_rot , MIN ( 1.f , p_interp_delta * ( 1 / orbit_inertia ) ) ) ;
2019-10-23 11:46:26 +02:00
if ( Math : : abs ( camera_cursor . x_rot - cursor . x_rot ) < 0.1 ) {
camera_cursor . x_rot = cursor . x_rot ;
}
if ( Math : : abs ( camera_cursor . y_rot - cursor . y_rot ) < 0.1 ) {
camera_cursor . y_rot = cursor . y_rot ;
}
2020-03-16 10:07:33 +01:00
camera_cursor . pos = old_camera_cursor . pos . lerp ( cursor . pos , MIN ( 1.f , p_interp_delta * ( 1 / translation_inertia ) ) ) ;
2017-10-08 02:43:57 +02:00
camera_cursor . distance = Math : : lerp ( old_camera_cursor . distance , cursor . distance , MIN ( 1.f , p_interp_delta * ( 1 / zoom_inertia ) ) ) ;
}
2017-08-26 05:40:45 +02:00
}
2017-10-08 02:43:57 +02:00
//-------
// Apply camera transform
2019-04-21 12:15:45 +02:00
real_t tolerance = 0.001 ;
2017-08-26 05:40:45 +02:00
bool equal = true ;
2019-04-21 12:15:45 +02:00
if ( ! Math : : is_equal_approx ( old_camera_cursor . x_rot , camera_cursor . x_rot , tolerance ) | | ! Math : : is_equal_approx ( old_camera_cursor . y_rot , camera_cursor . y_rot , tolerance ) ) {
2017-09-06 19:53:00 +02:00
equal = false ;
2019-04-21 12:15:45 +02:00
} else if ( ! old_camera_cursor . pos . is_equal_approx ( camera_cursor . pos ) ) {
2017-08-26 05:40:45 +02:00
equal = false ;
2019-04-21 12:15:45 +02:00
} else if ( ! Math : : is_equal_approx ( old_camera_cursor . distance , camera_cursor . distance , tolerance ) ) {
2017-09-06 19:53:00 +02:00
equal = false ;
2017-09-23 22:27:29 +02:00
}
2017-08-26 05:40:45 +02:00
2017-09-23 22:27:29 +02:00
if ( ! equal | | p_interp_delta = = 0 | | is_freelook_active ( ) | | is_orthogonal ! = orthogonal ) {
2017-09-06 19:53:00 +02:00
camera - > set_global_transform ( to_camera_transform ( camera_cursor ) ) ;
2017-09-23 22:27:29 +02:00
2019-10-23 11:46:26 +02:00
if ( orthogonal ) {
float half_fov = Math : : deg2rad ( get_fov ( ) ) / 2.0 ;
float height = 2.0 * cursor . distance * Math : : tan ( half_fov ) ;
2020-04-05 01:16:11 +02:00
camera - > set_orthogonal ( height , get_znear ( ) , get_zfar ( ) ) ;
2019-10-23 11:46:26 +02:00
} else {
2017-09-23 22:27:29 +02:00
camera - > set_perspective ( get_fov ( ) , get_znear ( ) , get_zfar ( ) ) ;
2019-10-23 11:46:26 +02:00
}
2017-12-19 23:54:54 +01:00
update_transform_gizmo_view ( ) ;
2019-10-23 11:46:26 +02:00
rotation_control - > update ( ) ;
2020-11-04 10:03:28 +01:00
spatial_editor - > update_grid ( ) ;
2017-05-01 20:57:35 +02:00
}
}
2020-03-26 22:49:16 +01:00
Transform Node3DEditorViewport : : to_camera_transform ( const Cursor & p_cursor ) const {
2016-04-06 08:34:34 +02:00
Transform camera_transform ;
2017-05-01 20:57:35 +02:00
camera_transform . translate ( p_cursor . pos ) ;
camera_transform . basis . rotate ( Vector3 ( 1 , 0 , 0 ) , - p_cursor . x_rot ) ;
camera_transform . basis . rotate ( Vector3 ( 0 , 1 , 0 ) , - p_cursor . y_rot ) ;
2016-04-06 08:34:34 +02:00
2020-05-14 16:41:43 +02:00
if ( orthogonal ) {
2020-04-05 01:16:11 +02:00
camera_transform . translate ( 0 , 0 , ( get_zfar ( ) - get_znear ( ) ) / 2.0 ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-05-01 20:57:35 +02:00
camera_transform . translate ( 0 , 0 , p_cursor . distance ) ;
2020-05-14 16:41:43 +02:00
}
2016-04-06 08:34:34 +02:00
2017-05-01 20:57:35 +02:00
return camera_transform ;
2016-04-06 08:34:34 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
int Node3DEditorViewport : : get_selected_count ( ) const {
2017-03-05 16:44:50 +01:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
int count = 0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > key ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
count + + ;
}
return count ;
}
2020-03-26 22:49:16 +01:00
float Node3DEditorViewport : : get_znear ( ) const {
2017-08-04 13:23:10 +02:00
return CLAMP ( spatial_editor - > get_znear ( ) , MIN_Z , MAX_Z ) ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
float Node3DEditorViewport : : get_zfar ( ) const {
2017-08-04 13:23:10 +02:00
return CLAMP ( spatial_editor - > get_zfar ( ) , MIN_Z , MAX_Z ) ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
float Node3DEditorViewport : : get_fov ( ) const {
2017-08-04 13:23:10 +02:00
return CLAMP ( spatial_editor - > get_fov ( ) , MIN_FOV , MAX_FOV ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Transform Node3DEditorViewport : : _get_camera_transform ( ) const {
2014-02-10 02:10:30 +01:00
return camera - > get_global_transform ( ) ;
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_camera_position ( ) const {
2014-02-10 02:10:30 +01:00
return _get_camera_transform ( ) . origin ;
}
2020-03-26 22:49:16 +01:00
Point2 Node3DEditorViewport : : _point_to_screen ( const Vector3 & p_point ) {
2020-04-01 20:28:09 +02:00
return camera - > unproject_position ( p_point ) * subviewport_container - > get_stretch_shrink ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_ray_pos ( const Vector2 & p_pos ) const {
2020-04-01 20:28:09 +02:00
return camera - > project_ray_origin ( p_pos / subviewport_container - > get_stretch_shrink ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_camera_normal ( ) const {
2014-02-10 02:10:30 +01:00
return - _get_camera_transform ( ) . basis . get_axis ( 2 ) ;
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_ray ( const Vector2 & p_pos ) const {
2020-04-01 20:28:09 +02:00
return camera - > project_ray_normal ( p_pos / subviewport_container - > get_stretch_shrink ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _clear_selected ( ) {
2014-02-10 02:10:30 +01:00
editor_selection - > clear ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _select_clicked ( bool p_append , bool p_single , bool p_allow_locked ) {
2020-05-14 16:41:43 +02:00
if ( clicked . is_null ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2019-04-17 18:24:28 +02:00
Node * node = Object : : cast_to < Node > ( ObjectDB : : get_instance ( clicked ) ) ;
2020-03-26 22:49:16 +01:00
Node3D * selected = Object : : cast_to < Node3D > ( node ) ;
2020-05-14 16:41:43 +02:00
if ( ! selected ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-02-10 13:59:24 +01:00
if ( ! p_allow_locked ) {
// Replace the node by the group if grouped
while ( node & & node ! = editor - > get_edited_scene ( ) - > get_parent ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( node ) ;
2020-02-10 13:59:24 +01:00
if ( selected_tmp & & node - > has_meta ( " _edit_group_ " ) ) {
selected = selected_tmp ;
}
node = node - > get_parent ( ) ;
2019-04-17 18:24:28 +02:00
}
}
2020-02-10 13:59:24 +01:00
if ( p_allow_locked | | ! _is_node_locked ( selected ) ) {
2019-07-15 21:50:00 +02:00
_select ( selected , clicked_wants_append , true ) ;
2020-02-10 13:59:24 +01:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _select ( Node * p_node , bool p_append , bool p_single ) {
2014-02-10 02:10:30 +01:00
if ( ! p_append ) {
2018-05-06 20:49:22 +02:00
editor_selection - > clear ( ) ;
}
2014-02-10 02:10:30 +01:00
2018-05-06 20:49:22 +02:00
if ( editor_selection - > is_selected ( p_node ) ) {
//erase
editor_selection - > remove_node ( p_node ) ;
} else {
2014-02-10 02:10:30 +01:00
editor_selection - > add_node ( p_node ) ;
2018-05-06 20:49:22 +02:00
}
2014-02-10 02:10:30 +01:00
2018-05-06 20:49:22 +02:00
if ( p_single ) {
2020-05-14 16:41:43 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2018-02-07 07:27:39 +01:00
editor - > call ( " edit_node " , p_node ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
ObjectID Node3DEditorViewport : : _select_ray ( const Point2 & p_pos , bool p_append , bool & r_includes_current , int * r_gizmo_handle , bool p_alt_select ) {
2020-05-14 16:41:43 +02:00
if ( r_gizmo_handle ) {
2017-03-05 16:44:50 +01:00
* r_gizmo_handle = - 1 ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Vector3 ray = _get_ray ( p_pos ) ;
Vector3 pos = _get_ray_pos ( p_pos ) ;
2020-04-01 20:28:09 +02:00
Vector2 shrinked_pos = p_pos / subviewport_container - > get_stretch_shrink ( ) ;
2014-02-10 02:10:30 +01:00
2020-06-25 15:33:28 +02:00
if ( viewport - > get_debug_draw ( ) = = Viewport : : DEBUG_DRAW_SDFGI_PROBES ) {
RS : : get_singleton ( ) - > sdfgi_set_debug_probe_select ( pos , ray ) ;
}
2020-04-18 11:00:51 +02:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_ray ( pos , ray , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-26 22:49:16 +01:00
Set < Ref < EditorNode3DGizmo > > found_gizmos ;
2014-02-10 02:10:30 +01:00
2017-08-26 05:40:45 +02:00
Node * edited_scene = get_tree ( ) - > get_edited_scene_root ( ) ;
2020-02-12 18:24:06 +01:00
ObjectID closest ;
2020-04-02 01:20:12 +02:00
Node * item = nullptr ;
2017-03-05 16:44:50 +01:00
float closest_dist = 1e20 ;
int selected_handle = - 1 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * spat = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! spat ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = spat - > get_gizmo ( ) ;
2014-02-10 02:10:30 +01:00
2017-08-09 18:40:02 +02:00
if ( ( ! seg . is_valid ( ) ) | | found_gizmos . has ( seg ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2017-08-09 18:40:02 +02:00
}
2014-02-10 02:10:30 +01:00
found_gizmos . insert ( seg ) ;
Vector3 point ;
Vector3 normal ;
2017-03-05 16:44:50 +01:00
int handle = - 1 ;
2019-12-18 23:49:37 +01:00
bool inters = seg - > intersect_ray ( camera , shrinked_pos , point , normal , & handle , p_alt_select ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! inters ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
float dist = pos . distance_to ( point ) ;
2020-05-14 16:41:43 +02:00
if ( dist < 0 ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-02-06 04:38:39 +01:00
if ( dist < closest_dist ) {
2018-09-02 22:31:03 +02:00
item = Object : : cast_to < Node > ( spat ) ;
while ( item - > get_owner ( ) & & item - > get_owner ( ) ! = edited_scene & & ! edited_scene - > is_editable_instance ( item - > get_owner ( ) ) ) {
item = item - > get_owner ( ) ;
2017-08-26 05:40:45 +02:00
}
2018-08-27 16:02:49 +02:00
closest = item - > get_instance_id ( ) ;
closest_dist = dist ;
selected_handle = handle ;
2017-02-06 04:38:39 +01:00
}
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
if ( ! item ) {
2020-02-12 18:24:06 +01:00
return ObjectID ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
if ( ! editor_selection - > is_selected ( item ) | | ( r_gizmo_handle & & selected_handle > = 0 ) ) {
2020-05-14 16:41:43 +02:00
if ( r_gizmo_handle ) {
2017-03-05 16:44:50 +01:00
* r_gizmo_handle = selected_handle ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-02-06 04:38:39 +01:00
return closest ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _find_items_at_pos ( const Point2 & p_pos , bool & r_includes_current , Vector < _RayResult > & results , bool p_alt_select ) {
2017-03-05 16:44:50 +01:00
Vector3 ray = _get_ray ( p_pos ) ;
Vector3 pos = _get_ray_pos ( p_pos ) ;
2015-11-04 22:39:07 +01:00
2020-04-18 11:00:51 +02:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_ray ( pos , ray , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-26 22:49:16 +01:00
Set < Ref < EditorNode3DGizmo > > found_gizmos ;
2015-11-04 22:39:07 +01:00
2017-03-05 16:44:50 +01:00
r_includes_current = false ;
2015-11-04 22:39:07 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * spat = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2015-11-04 22:39:07 +01:00
2020-05-14 16:41:43 +02:00
if ( ! spat ) {
2015-11-04 22:39:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = spat - > get_gizmo ( ) ;
2015-11-04 22:39:07 +01:00
2020-05-14 16:41:43 +02:00
if ( ! seg . is_valid ( ) ) {
2015-11-04 22:39:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
2020-05-14 16:41:43 +02:00
if ( found_gizmos . has ( seg ) ) {
2015-11-04 22:39:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
found_gizmos . insert ( seg ) ;
Vector3 point ;
Vector3 normal ;
2017-03-05 16:44:50 +01:00
int handle = - 1 ;
2020-04-02 01:20:12 +02:00
bool inters = seg - > intersect_ray ( camera , p_pos , point , normal , nullptr , p_alt_select ) ;
2015-11-04 22:39:07 +01:00
2020-05-14 16:41:43 +02:00
if ( ! inters ) {
2015-11-04 22:39:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
float dist = pos . distance_to ( point ) ;
2020-05-14 16:41:43 +02:00
if ( dist < 0 ) {
2015-11-04 22:39:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
2020-05-14 16:41:43 +02:00
if ( editor_selection - > is_selected ( spat ) ) {
2017-03-05 16:44:50 +01:00
r_includes_current = true ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
_RayResult res ;
2017-03-05 16:44:50 +01:00
res . item = spat ;
res . depth = dist ;
res . handle = handle ;
2015-11-04 22:39:07 +01:00
results . push_back ( res ) ;
}
2020-12-15 13:04:21 +01:00
if ( results . is_empty ( ) ) {
2015-11-04 22:39:07 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
results . sort ( ) ;
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_screen_to_space ( const Vector3 & p_vector3 ) {
2014-02-10 02:10:30 +01:00
CameraMatrix cm ;
2018-06-27 16:59:45 +02:00
if ( orthogonal ) {
cm . set_orthogonal ( camera - > get_size ( ) , get_size ( ) . aspect ( ) , get_znear ( ) + p_vector3 . z , get_zfar ( ) ) ;
} else {
cm . set_perspective ( get_fov ( ) , get_size ( ) . aspect ( ) , get_znear ( ) + p_vector3 . z , get_zfar ( ) ) ;
}
2020-01-21 19:39:16 +01:00
Vector2 screen_he = cm . get_viewport_half_extents ( ) ;
2014-02-10 02:10:30 +01:00
Transform camera_transform ;
2017-03-05 16:44:50 +01:00
camera_transform . translate ( cursor . pos ) ;
camera_transform . basis . rotate ( Vector3 ( 1 , 0 , 0 ) , - cursor . x_rot ) ;
camera_transform . basis . rotate ( Vector3 ( 0 , 1 , 0 ) , - cursor . y_rot ) ;
camera_transform . translate ( 0 , 0 , cursor . distance ) ;
2014-02-10 02:10:30 +01:00
2020-01-21 19:39:16 +01:00
return camera_transform . xform ( Vector3 ( ( ( p_vector3 . x / get_size ( ) . width ) * 2.0 - 1.0 ) * screen_he . x , ( ( 1.0 - ( p_vector3 . y / get_size ( ) . height ) ) * 2.0 - 1.0 ) * screen_he . y , - ( get_znear ( ) + p_vector3 . z ) ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _select_region ( ) {
2020-05-14 16:41:43 +02:00
if ( cursor . region_begin = = cursor . region_end ) {
2014-02-10 02:10:30 +01:00
return ; //nothing really
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-05-06 20:49:22 +02:00
float z_offset = MAX ( 0.0 , 5.0 - get_znear ( ) ) ;
2017-03-05 16:44:50 +01:00
Vector3 box [ 4 ] = {
2014-02-10 02:10:30 +01:00
Vector3 (
2017-03-05 16:44:50 +01:00
MIN ( cursor . region_begin . x , cursor . region_end . x ) ,
MIN ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 20:49:22 +02:00
z_offset ) ,
2014-02-10 02:10:30 +01:00
Vector3 (
2017-03-05 16:44:50 +01:00
MAX ( cursor . region_begin . x , cursor . region_end . x ) ,
MIN ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 20:49:22 +02:00
z_offset ) ,
2014-02-10 02:10:30 +01:00
Vector3 (
2017-03-05 16:44:50 +01:00
MAX ( cursor . region_begin . x , cursor . region_end . x ) ,
MAX ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 20:49:22 +02:00
z_offset ) ,
2014-02-10 02:10:30 +01:00
Vector3 (
2017-03-05 16:44:50 +01:00
MIN ( cursor . region_begin . x , cursor . region_end . x ) ,
MAX ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 20:49:22 +02:00
z_offset )
2014-02-10 02:10:30 +01:00
} ;
Vector < Plane > frustum ;
2017-09-10 15:37:49 +02:00
Vector3 cam_pos = _get_camera_position ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
Vector3 a = _get_screen_to_space ( box [ i ] ) ;
Vector3 b = _get_screen_to_space ( box [ ( i + 1 ) % 4 ] ) ;
2018-06-27 16:59:45 +02:00
if ( orthogonal ) {
frustum . push_back ( Plane ( a , ( a - b ) . normalized ( ) ) ) ;
} else {
frustum . push_back ( Plane ( a , b , cam_pos ) ) ;
}
2014-02-10 02:10:30 +01:00
}
2020-04-29 02:14:06 +02:00
Plane near ( cam_pos , - _get_camera_normal ( ) ) ;
2020-05-10 16:47:11 +02:00
near . d - = get_znear ( ) ;
2020-04-29 02:14:06 +02:00
frustum . push_back ( near ) ;
2014-02-10 02:10:30 +01:00
2020-04-29 02:14:06 +02:00
Plane far = - near ;
2020-05-10 16:47:11 +02:00
far . d + = get_zfar ( ) ;
2020-04-29 02:14:06 +02:00
frustum . push_back ( far ) ;
2014-02-10 02:10:30 +01:00
2020-04-18 11:00:51 +02:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_convex ( frustum , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2018-09-02 22:31:03 +02:00
Vector < Node * > selected ;
2017-09-12 15:06:13 +02:00
Node * edited_scene = get_tree ( ) - > get_edited_scene_root ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp | | _is_node_locked ( sp ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-09-02 22:31:03 +02:00
Node * item = Object : : cast_to < Node > ( sp ) ;
while ( item - > get_owner ( ) & & item - > get_owner ( ) ! = edited_scene & & ! edited_scene - > is_editable_instance ( item - > get_owner ( ) ) ) {
item = item - > get_owner ( ) ;
2018-05-06 20:49:22 +02:00
}
2019-04-17 18:24:28 +02:00
// Replace the node by the group if grouped
2020-03-26 22:49:16 +01:00
if ( item - > is_class ( " Node3D " ) ) {
Node3D * sel = Object : : cast_to < Node3D > ( item ) ;
2019-04-17 18:24:28 +02:00
while ( item & & item ! = editor - > get_edited_scene ( ) - > get_parent ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( item ) ;
2019-04-17 18:24:28 +02:00
if ( selected_tmp & & item - > has_meta ( " _edit_group_ " ) ) {
sel = selected_tmp ;
}
item = item - > get_parent ( ) ;
}
item = sel ;
}
2020-05-14 16:41:43 +02:00
if ( selected . find ( item ) ! = - 1 ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2018-05-06 20:49:22 +02:00
2020-05-14 16:41:43 +02:00
if ( _is_node_locked ( item ) ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-07-15 21:50:00 +02:00
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = sp - > get_gizmo ( ) ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! seg . is_valid ( ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-05-06 20:49:22 +02:00
if ( seg - > intersect_frustum ( camera , frustum ) ) {
2018-09-02 22:31:03 +02:00
selected . push_back ( item ) ;
2017-09-12 15:06:13 +02:00
}
2018-05-06 20:49:22 +02:00
}
2014-02-10 02:10:30 +01:00
2018-05-06 20:49:22 +02:00
bool single = selected . size ( ) = = 1 ;
for ( int i = 0 ; i < selected . size ( ) ; i + + ) {
_select ( selected [ i ] , true , single ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _update_name ( ) {
2018-10-01 08:00:49 +02:00
String view_mode = orthogonal ? TTR ( " Orthogonal " ) : TTR ( " Perspective " ) ;
2015-03-21 21:47:21 +01:00
2019-10-23 11:46:26 +02:00
if ( auto_orthogonal ) {
view_mode + = " [auto] " ;
}
2020-05-14 16:41:43 +02:00
if ( name ! = " " ) {
2018-10-06 22:53:11 +02:00
view_menu - > set_text ( name + " " + view_mode ) ;
2020-05-14 16:41:43 +02:00
} else {
2018-10-06 22:53:11 +02:00
view_menu - > set_text ( view_mode ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
view_menu - > set_size ( Vector2 ( 0 , 0 ) ) ; // resets the button size
2015-03-21 21:47:21 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _compute_edit ( const Point2 & p_point ) {
2017-03-05 16:44:50 +01:00
_edit . click_ray = _get_ray ( Vector2 ( p_point . x , p_point . y ) ) ;
_edit . click_ray_pos = _get_ray_pos ( Vector2 ( p_point . x , p_point . y ) ) ;
_edit . plane = TRANSFORM_VIEW ;
2014-02-10 02:10:30 +01:00
spatial_editor - > update_transform_gizmo ( ) ;
2017-03-05 16:44:50 +01:00
_edit . center = spatial_editor - > get_gizmo_transform ( ) . origin ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-03 18:49:32 +02:00
se - > original = se - > sp - > get_global_gizmo_transform ( ) ;
se - > original_local = se - > sp - > get_local_gizmo_transform ( ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-07-23 02:02:18 +02:00
static int _get_key_modifier_setting ( const String & p_property ) {
2017-03-05 16:44:50 +01:00
switch ( EditorSettings : : get_singleton ( ) - > get ( p_property ) . operator int ( ) ) {
2020-05-10 13:00:47 +02:00
case 0 :
return 0 ;
case 1 :
return KEY_SHIFT ;
case 2 :
return KEY_ALT ;
case 3 :
return KEY_META ;
case 4 :
return KEY_CONTROL ;
2014-02-10 02:10:30 +01:00
}
return 0 ;
}
2017-07-23 02:02:18 +02:00
static int _get_key_modifier ( Ref < InputEventWithModifiers > e ) {
2020-05-14 16:41:43 +02:00
if ( e - > get_shift ( ) ) {
2017-07-23 02:02:18 +02:00
return KEY_SHIFT ;
2020-05-14 16:41:43 +02:00
}
if ( e - > get_alt ( ) ) {
2017-07-23 02:02:18 +02:00
return KEY_ALT ;
2020-05-14 16:41:43 +02:00
}
if ( e - > get_control ( ) ) {
2017-07-23 02:02:18 +02:00
return KEY_CONTROL ;
2020-05-14 16:41:43 +02:00
}
if ( e - > get_metakey ( ) ) {
2017-07-23 02:02:18 +02:00
return KEY_META ;
2020-05-14 16:41:43 +02:00
}
2017-07-23 02:02:18 +02:00
return 0 ;
}
2020-03-26 22:49:16 +01:00
bool Node3DEditorViewport : : _gizmo_select ( const Vector2 & p_screenpos , bool p_highlight_only ) {
2020-05-14 16:41:43 +02:00
if ( ! spatial_editor - > is_gizmo_visible ( ) ) {
2014-02-10 02:10:30 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
if ( get_selected_count ( ) = = 0 ) {
2020-05-14 16:41:43 +02:00
if ( p_highlight_only ) {
2017-04-06 17:35:08 +02:00
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return false ;
}
2017-03-05 16:44:50 +01:00
Vector3 ray_pos = _get_ray_pos ( Vector2 ( p_screenpos . x , p_screenpos . y ) ) ;
Vector3 ray = _get_ray ( Vector2 ( p_screenpos . x , p_screenpos . y ) ) ;
2014-02-10 02:10:30 +01:00
Transform gt = spatial_editor - > get_gizmo_transform ( ) ;
2017-03-05 16:44:50 +01:00
float gs = gizmo_scale ;
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) {
2017-03-05 16:44:50 +01:00
int col_axis = - 1 ;
float col_d = 1e20 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2017-09-21 23:11:56 +02:00
Vector3 grabber_pos = gt . origin + gt . basis . get_axis ( i ) * gs * ( GIZMO_ARROW_OFFSET + ( GIZMO_ARROW_SIZE * 0.5 ) ) ;
2017-03-05 16:44:50 +01:00
float grabber_radius = gs * GIZMO_ARROW_SIZE ;
2014-02-10 02:10:30 +01:00
Vector3 r ;
2017-08-29 03:39:45 +02:00
2020-05-25 19:20:45 +02:00
if ( Geometry3D : : segment_intersects_sphere ( ray_pos , ray_pos + ray * MAX_Z , grabber_pos , grabber_radius , & r ) ) {
2014-02-10 02:10:30 +01:00
float d = r . distance_to ( ray_pos ) ;
2017-03-05 16:44:50 +01:00
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
2014-02-10 02:10:30 +01:00
}
}
}
2017-08-29 03:39:45 +02:00
bool is_plane_translate = false ;
2017-09-21 23:11:56 +02:00
// plane select
2017-08-29 03:39:45 +02:00
if ( col_axis = = - 1 ) {
col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ivec2 = gt . basis . get_axis ( ( i + 1 ) % 3 ) . normalized ( ) ;
Vector3 ivec3 = gt . basis . get_axis ( ( i + 2 ) % 3 ) . normalized ( ) ;
Vector3 grabber_pos = gt . origin + ( ivec2 + ivec3 ) * gs * ( GIZMO_PLANE_SIZE + GIZMO_PLANE_DST ) ;
Vector3 r ;
Plane plane ( gt . origin , gt . basis . get_axis ( i ) . normalized ( ) ) ;
if ( plane . intersects_ray ( ray_pos , ray , & r ) ) {
float dist = r . distance_to ( grabber_pos ) ;
if ( dist < ( gs * GIZMO_PLANE_SIZE ) ) {
float d = ray_pos . distance_to ( r ) ;
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
is_plane_translate = true ;
}
}
}
}
}
2017-03-05 16:44:50 +01:00
if ( col_axis ! = - 1 ) {
2017-05-02 22:13:12 +02:00
if ( p_highlight_only ) {
2017-08-29 03:39:45 +02:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + ( is_plane_translate ? 6 : 0 ) ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-08-29 03:39:45 +02:00
//handle plane translate
2017-03-05 16:44:50 +01:00
_edit . mode = TRANSFORM_TRANSLATE ;
_compute_edit ( Point2 ( p_screenpos . x , p_screenpos . y ) ) ;
2017-08-29 03:39:45 +02:00
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis + ( is_plane_translate ? 3 : 0 ) ) ;
2014-02-10 02:10:30 +01:00
}
return true ;
}
}
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) {
2017-03-05 16:44:50 +01:00
int col_axis = - 1 ;
float col_d = 1e20 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
Plane plane ( gt . origin , gt . basis . get_axis ( i ) . normalized ( ) ) ;
2014-02-10 02:10:30 +01:00
Vector3 r ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( ray_pos , ray , & r ) ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
float dist = r . distance_to ( gt . origin ) ;
2020-09-13 18:22:51 +02:00
Vector3 r_dir = ( r - gt . origin ) . normalized ( ) ;
if ( _get_camera_normal ( ) . dot ( r_dir ) < = 0.005 ) {
if ( dist > gs * ( GIZMO_CIRCLE_SIZE - GIZMO_RING_HALF_WIDTH ) & & dist < gs * ( GIZMO_CIRCLE_SIZE + GIZMO_RING_HALF_WIDTH ) ) {
float d = ray_pos . distance_to ( r ) ;
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
}
2014-02-10 02:10:30 +01:00
}
}
}
2017-03-05 16:44:50 +01:00
if ( col_axis ! = - 1 ) {
2017-05-02 22:13:12 +02:00
if ( p_highlight_only ) {
2017-04-06 17:35:08 +02:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + 3 ) ;
2014-02-10 02:10:30 +01:00
} else {
//handle rotate
2017-03-05 16:44:50 +01:00
_edit . mode = TRANSFORM_ROTATE ;
_compute_edit ( Point2 ( p_screenpos . x , p_screenpos . y ) ) ;
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis ) ;
2014-02-10 02:10:30 +01:00
}
return true ;
}
}
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) {
2017-09-21 23:11:56 +02:00
int col_axis = - 1 ;
float col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 grabber_pos = gt . origin + gt . basis . get_axis ( i ) * gs * GIZMO_SCALE_OFFSET ;
float grabber_radius = gs * GIZMO_ARROW_SIZE ;
Vector3 r ;
2020-05-25 19:20:45 +02:00
if ( Geometry3D : : segment_intersects_sphere ( ray_pos , ray_pos + ray * MAX_Z , grabber_pos , grabber_radius , & r ) ) {
2017-09-21 23:11:56 +02:00
float d = r . distance_to ( ray_pos ) ;
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
}
}
}
2017-11-14 23:50:19 +01:00
bool is_plane_scale = false ;
// plane select
if ( col_axis = = - 1 ) {
col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
Vector3 ivec2 = gt . basis . get_axis ( ( i + 1 ) % 3 ) . normalized ( ) ;
Vector3 ivec3 = gt . basis . get_axis ( ( i + 2 ) % 3 ) . normalized ( ) ;
Vector3 grabber_pos = gt . origin + ( ivec2 + ivec3 ) * gs * ( GIZMO_PLANE_SIZE + GIZMO_PLANE_DST ) ;
Vector3 r ;
Plane plane ( gt . origin , gt . basis . get_axis ( i ) . normalized ( ) ) ;
if ( plane . intersects_ray ( ray_pos , ray , & r ) ) {
float dist = r . distance_to ( grabber_pos ) ;
if ( dist < ( gs * GIZMO_PLANE_SIZE ) ) {
float d = ray_pos . distance_to ( r ) ;
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
is_plane_scale = true ;
}
}
}
}
}
2017-09-21 23:11:56 +02:00
if ( col_axis ! = - 1 ) {
if ( p_highlight_only ) {
2017-11-14 23:50:19 +01:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + ( is_plane_scale ? 12 : 9 ) ) ;
2017-09-21 23:11:56 +02:00
} else {
//handle scale
_edit . mode = TRANSFORM_SCALE ;
_compute_edit ( Point2 ( p_screenpos . x , p_screenpos . y ) ) ;
2017-11-14 23:50:19 +01:00
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis + ( is_plane_scale ? 3 : 0 ) ) ;
2017-09-21 23:11:56 +02:00
}
return true ;
}
}
2020-05-14 16:41:43 +02:00
if ( p_highlight_only ) {
2017-04-06 17:35:08 +02:00
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
return false ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _surface_mouse_enter ( ) {
2020-05-14 16:41:43 +02:00
if ( ! surface - > has_focus ( ) & & ( ! get_focus_owner ( ) | | ! get_focus_owner ( ) - > is_text_field ( ) ) ) {
2017-03-05 16:44:50 +01:00
surface - > grab_focus ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _surface_mouse_exit ( ) {
2017-09-02 21:47:16 +02:00
_remove_preview ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _surface_focus_enter ( ) {
2017-12-19 15:29:55 +01:00
view_menu - > set_disable_shortcuts ( false ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _surface_focus_exit ( ) {
2017-12-19 15:29:55 +01:00
view_menu - > set_disable_shortcuts ( true ) ;
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
bool Node3DEditorViewport : : _is_node_locked ( const Node * p_node ) {
2019-07-15 21:50:00 +02:00
return p_node - > has_meta ( " _edit_lock_ " ) & & p_node - > get_meta ( " _edit_lock_ " ) ;
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _list_select ( Ref < InputEventMouseButton > b ) {
2017-06-03 10:54:24 +02:00
_find_items_at_pos ( b - > get_position ( ) , clicked_includes_current , selection_results , b - > get_shift ( ) ) ;
2015-12-13 21:16:13 +01:00
2017-03-05 16:44:50 +01:00
Node * scene = editor - > get_edited_scene ( ) ;
2015-12-13 21:16:13 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < selection_results . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * item = selection_results [ i ] . item ;
2017-03-05 16:44:50 +01:00
if ( item ! = scene & & item - > get_owner ( ) ! = scene & & ! scene - > is_editable_instance ( item - > get_owner ( ) ) ) {
2015-12-13 21:16:13 +01:00
//invalid result
selection_results . remove ( i ) ;
i - - ;
}
}
2017-05-20 17:38:03 +02:00
clicked_wants_append = b - > get_shift ( ) ;
2015-12-13 21:16:13 +01:00
if ( selection_results . size ( ) = = 1 ) {
2017-08-07 12:17:31 +02:00
clicked = selection_results [ 0 ] . item - > get_instance_id ( ) ;
2015-12-13 21:16:13 +01:00
selection_results . clear ( ) ;
2020-02-12 18:24:06 +01:00
if ( clicked . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
_select_clicked ( clicked_wants_append , true , spatial_editor - > get_tool_mode ( ) ! = Node3DEditor : : TOOL_MODE_LIST_SELECT ) ;
2020-02-12 18:24:06 +01:00
clicked = ObjectID ( ) ;
2015-12-13 21:16:13 +01:00
}
2020-12-15 13:04:21 +01:00
} else if ( ! selection_results . is_empty ( ) ) {
2015-12-13 21:16:13 +01:00
NodePath root_path = get_tree ( ) - > get_edited_scene_root ( ) - > get_path ( ) ;
2017-03-05 16:44:50 +01:00
StringName root_name = root_path . get_name ( root_path . get_name_count ( ) - 1 ) ;
2015-12-13 21:16:13 +01:00
for ( int i = 0 ; i < selection_results . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * spat = selection_results [ i ] . item ;
2015-12-13 21:16:13 +01:00
2019-06-11 20:43:37 +02:00
Ref < Texture2D > icon = EditorNode : : get_singleton ( ) - > get_object_icon ( spat , " Node " ) ;
2015-12-13 21:16:13 +01:00
2017-03-05 16:44:50 +01:00
String node_path = " / " + root_name + " / " + root_path . rel_path_to ( spat - > get_path ( ) ) ;
2015-12-13 21:16:13 +01:00
2020-02-10 13:59:24 +01:00
int locked = 0 ;
if ( _is_node_locked ( spat ) ) {
locked = 1 ;
} else {
Node * ed_scene = editor - > get_edited_scene ( ) ;
Node * node = spat ;
while ( node & & node ! = ed_scene - > get_parent ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( node ) ;
2020-02-10 13:59:24 +01:00
if ( selected_tmp & & node - > has_meta ( " _edit_group_ " ) ) {
locked = 2 ;
}
node = node - > get_parent ( ) ;
}
}
String suffix = String ( ) ;
if ( locked = = 1 ) {
suffix = " ( " + TTR ( " Locked " ) + " ) " ;
} else if ( locked = = 2 ) {
suffix = " ( " + TTR ( " Grouped " ) + " ) " ;
}
selection_menu - > add_item ( ( String ) spat - > get_name ( ) + suffix ) ;
2017-03-05 16:44:50 +01:00
selection_menu - > set_item_icon ( i , icon ) ;
2015-12-13 21:16:13 +01:00
selection_menu - > set_item_metadata ( i , node_path ) ;
2017-05-01 20:57:35 +02:00
selection_menu - > set_item_tooltip ( i , String ( spat - > get_name ( ) ) + " \n Type: " + spat - > get_class ( ) + " \n Path: " + node_path ) ;
2015-12-13 21:16:13 +01:00
}
2020-03-12 13:37:40 +01:00
selection_menu - > set_position ( get_screen_transform ( ) . xform ( b - > get_position ( ) ) ) ;
2015-12-13 21:16:13 +01:00
selection_menu - > popup ( ) ;
}
}
2017-10-30 01:22:48 +01:00
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _sinput ( const Ref < InputEvent > & p_event ) {
2020-05-14 16:41:43 +02:00
if ( previewing ) {
2014-02-10 02:10:30 +01:00
return ; //do NONE
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
{
2017-06-08 19:57:35 +02:00
EditorNode * en = editor ;
EditorPluginList * force_input_forwarding_list = en - > get_editor_plugins_force_input_forwarding ( ) ;
2020-12-15 13:04:21 +01:00
if ( ! force_input_forwarding_list - > is_empty ( ) ) {
2017-06-08 19:57:35 +02:00
bool discard = force_input_forwarding_list - > forward_spatial_gui_input ( camera , p_event , true ) ;
2020-05-14 16:41:43 +02:00
if ( discard ) {
2017-06-08 19:57:35 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-06-08 19:57:35 +02:00
}
}
{
2014-02-10 02:10:30 +01:00
EditorNode * en = editor ;
2016-03-30 01:02:53 +02:00
EditorPluginList * over_plugin_list = en - > get_editor_plugins_over ( ) ;
2020-12-15 13:04:21 +01:00
if ( ! over_plugin_list - > is_empty ( ) ) {
2017-06-08 19:57:35 +02:00
bool discard = over_plugin_list - > forward_spatial_gui_input ( camera , p_event , false ) ;
2020-05-14 16:41:43 +02:00
if ( discard ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseButton > b = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( b . is_valid ( ) ) {
2019-04-06 22:55:01 +02:00
emit_signal ( " clicked " , this ) ;
2020-06-22 05:40:17 +02:00
float zoom_factor = 1 + ( ZOOM_FREELOOK_MULTIPLIER - 1 ) * b - > get_factor ( ) ;
2017-05-20 17:38:03 +02:00
switch ( b - > get_button_index ( ) ) {
case BUTTON_WHEEL_UP : {
2020-05-14 16:41:43 +02:00
if ( is_freelook_active ( ) ) {
2017-10-08 02:43:57 +02:00
scale_freelook_speed ( zoom_factor ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-10-08 02:43:57 +02:00
scale_cursor_distance ( 1.0 / zoom_factor ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
} break ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
case BUTTON_WHEEL_DOWN : {
2020-05-14 16:41:43 +02:00
if ( is_freelook_active ( ) ) {
2017-10-08 02:43:57 +02:00
scale_freelook_speed ( 1.0 / zoom_factor ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-10-08 02:43:57 +02:00
scale_cursor_distance ( zoom_factor ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
} break ;
2017-05-07 22:59:05 +02:00
2017-05-20 17:38:03 +02:00
case BUTTON_RIGHT : {
2017-09-19 02:30:48 +02:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( b - > is_pressed ( ) & & _edit . gizmo . is_valid ( ) ) {
//restore
_edit . gizmo - > commit_handle ( _edit . gizmo_handle , _edit . gizmo_initial_value , true ) ;
2020-03-26 22:49:16 +01:00
_edit . gizmo = Ref < EditorNode3DGizmo > ( ) ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( _edit . mode = = TRANSFORM_NONE & & b - > is_pressed ( ) ) {
if ( b - > get_alt ( ) ) {
2020-05-14 16:41:43 +02:00
if ( nav_scheme = = NAVIGATION_MAYA ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2015-11-19 15:47:04 +01:00
2017-05-20 17:38:03 +02:00
_list_select ( b ) ;
return ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( _edit . mode ! = TRANSFORM_NONE & & b - > is_pressed ( ) ) {
//cancel motion
_edit . mode = TRANSFORM_NONE ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
sp - > set_global_transform ( se - > original ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
set_message ( TTR ( " Transform Aborted. " ) , 3 ) ;
}
2017-05-07 22:59:05 +02:00
2017-07-23 02:02:18 +02:00
if ( b - > is_pressed ( ) ) {
2019-11-13 21:54:44 +01:00
const int mod = _get_key_modifier ( b ) ;
2018-10-20 12:49:33 +02:00
if ( ! orthogonal ) {
if ( mod = = _get_key_modifier_setting ( " editors/3d/freelook/freelook_activation_modifier " ) ) {
set_freelook_active ( true ) ;
}
2017-07-23 02:02:18 +02:00
}
} else {
2017-10-08 02:43:57 +02:00
set_freelook_active ( false ) ;
2017-07-23 02:02:18 +02:00
}
2017-06-20 02:24:35 +02:00
if ( freelook_active & & ! surface - > has_focus ( ) ) {
// Focus usually doesn't trigger on right-click, but in case of freelook it should,
// otherwise using keyboard navigation would misbehave
surface - > grab_focus ( ) ;
}
2017-05-07 22:59:05 +02:00
2017-05-20 17:38:03 +02:00
} break ;
case BUTTON_MIDDLE : {
if ( b - > is_pressed ( ) & & _edit . mode ! = TRANSFORM_NONE ) {
switch ( _edit . plane ) {
case TRANSFORM_VIEW : {
_edit . plane = TRANSFORM_X_AXIS ;
set_message ( TTR ( " X-Axis Transform. " ) , 2 ) ;
name = " " ;
_update_name ( ) ;
} break ;
case TRANSFORM_X_AXIS : {
_edit . plane = TRANSFORM_Y_AXIS ;
set_message ( TTR ( " Y-Axis Transform. " ) , 2 ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} break ;
case TRANSFORM_Y_AXIS : {
_edit . plane = TRANSFORM_Z_AXIS ;
set_message ( TTR ( " Z-Axis Transform. " ) , 2 ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} break ;
case TRANSFORM_Z_AXIS : {
_edit . plane = TRANSFORM_VIEW ;
set_message ( TTR ( " View Plane Transform. " ) , 2 ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} break ;
2018-09-26 13:13:56 +02:00
case TRANSFORM_YZ :
case TRANSFORM_XZ :
case TRANSFORM_XY : {
} break ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
}
} break ;
case BUTTON_LEFT : {
if ( b - > is_pressed ( ) ) {
2017-09-19 02:30:48 +02:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2017-05-20 17:38:03 +02:00
if ( ( nav_scheme = = NAVIGATION_MAYA | | nav_scheme = = NAVIGATION_MODO ) & & b - > get_alt ( ) ) {
break ;
}
2014-03-31 10:27:41 +02:00
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_LIST_SELECT ) {
2017-05-20 17:38:03 +02:00
_list_select ( b ) ;
break ;
}
2015-12-13 21:16:13 +01:00
2017-06-03 10:54:24 +02:00
_edit . mouse_pos = b - > get_position ( ) ;
2019-03-16 09:15:39 +01:00
_edit . snap = spatial_editor - > is_snap_enabled ( ) ;
2017-05-20 17:38:03 +02:00
_edit . mode = TRANSFORM_NONE ;
2014-10-12 07:13:22 +02:00
2017-05-20 17:38:03 +02:00
//gizmo has priority over everything
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
bool can_select_gizmos = true ;
2014-10-12 07:13:22 +02:00
2017-05-20 17:38:03 +02:00
{
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ;
can_select_gizmos = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
}
2014-10-12 07:13:22 +02:00
2017-05-20 17:38:03 +02:00
if ( can_select_gizmos & & spatial_editor - > get_selected ( ) ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = spatial_editor - > get_selected ( ) - > get_gizmo ( ) ;
2017-05-20 17:38:03 +02:00
if ( seg . is_valid ( ) ) {
int handle = - 1 ;
Vector3 point ;
Vector3 normal ;
bool inters = seg - > intersect_ray ( camera , _edit . mouse_pos , point , normal , & handle , b - > get_shift ( ) ) ;
if ( inters & & handle ! = - 1 ) {
_edit . gizmo = seg ;
_edit . gizmo_handle = handle ;
_edit . gizmo_initial_value = seg - > get_handle_value ( handle ) ;
break ;
2014-05-05 03:50:23 +02:00
}
}
2017-05-20 17:38:03 +02:00
}
2014-05-05 03:50:23 +02:00
2020-05-14 16:41:43 +02:00
if ( _gizmo_select ( _edit . mouse_pos ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-02-12 18:24:06 +01:00
clicked = ObjectID ( ) ;
2017-05-20 17:38:03 +02:00
clicked_includes_current = false ;
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
if ( ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT & & b - > get_control ( ) ) | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) {
2017-05-20 17:38:03 +02:00
/* HANDLE ROTATION */
2020-05-14 16:41:43 +02:00
if ( get_selected_count ( ) = = 0 ) {
2017-05-20 17:38:03 +02:00
break ; //bye
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
//handle rotate
_edit . mode = TRANSFORM_ROTATE ;
2017-06-03 10:54:24 +02:00
_compute_edit ( b - > get_position ( ) ) ;
2017-05-20 17:38:03 +02:00
break ;
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) {
2020-05-14 16:41:43 +02:00
if ( get_selected_count ( ) = = 0 ) {
2017-05-20 17:38:03 +02:00
break ; //bye
2020-05-14 16:41:43 +02:00
}
2017-08-29 03:39:45 +02:00
//handle translate
2017-05-20 17:38:03 +02:00
_edit . mode = TRANSFORM_TRANSLATE ;
2017-06-03 10:54:24 +02:00
_compute_edit ( b - > get_position ( ) ) ;
2017-05-20 17:38:03 +02:00
break ;
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) {
2020-05-14 16:41:43 +02:00
if ( get_selected_count ( ) = = 0 ) {
2017-05-20 17:38:03 +02:00
break ; //bye
2020-05-14 16:41:43 +02:00
}
2017-10-23 21:21:15 +02:00
//handle scale
2017-05-20 17:38:03 +02:00
_edit . mode = TRANSFORM_SCALE ;
2017-06-03 10:54:24 +02:00
_compute_edit ( b - > get_position ( ) ) ;
2017-05-20 17:38:03 +02:00
break ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
// todo scale
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
int gizmo_handle = - 1 ;
2014-02-10 02:10:30 +01:00
2017-06-03 10:54:24 +02:00
clicked = _select_ray ( b - > get_position ( ) , b - > get_shift ( ) , clicked_includes_current , & gizmo_handle , b - > get_shift ( ) ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
//clicking is always deferred to either move or release
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
clicked_wants_append = b - > get_shift ( ) ;
2014-02-10 02:10:30 +01:00
2020-02-12 18:24:06 +01:00
if ( clicked . is_null ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! clicked_wants_append ) {
2017-05-20 17:38:03 +02:00
_clear_selected ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
//default to regionselect
cursor . region_select = true ;
2017-06-03 10:54:24 +02:00
cursor . region_begin = b - > get_position ( ) ;
cursor . region_end = b - > get_position ( ) ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2020-02-12 18:24:06 +01:00
if ( clicked . is_valid ( ) & & gizmo_handle > = 0 ) {
2020-03-26 22:49:16 +01:00
Node3D * spa = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( clicked ) ) ;
2017-08-24 22:58:51 +02:00
if ( spa ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = spa - > get_gizmo ( ) ;
2017-08-24 22:58:51 +02:00
if ( seg . is_valid ( ) ) {
_edit . gizmo = seg ;
_edit . gizmo_handle = gizmo_handle ;
_edit . gizmo_initial_value = seg - > get_handle_value ( gizmo_handle ) ;
break ;
2014-02-10 02:10:30 +01:00
}
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
} else {
if ( _edit . gizmo . is_valid ( ) ) {
_edit . gizmo - > commit_handle ( _edit . gizmo_handle , _edit . gizmo_initial_value , false ) ;
2020-03-26 22:49:16 +01:00
_edit . gizmo = Ref < EditorNode3DGizmo > ( ) ;
2017-05-20 17:38:03 +02:00
break ;
}
2020-02-12 18:24:06 +01:00
if ( clicked . is_valid ( ) ) {
2017-05-20 17:38:03 +02:00
_select_clicked ( clicked_wants_append , true ) ;
2018-10-20 12:49:33 +02:00
// Processing was deferred.
2020-02-12 18:24:06 +01:00
clicked = ObjectID ( ) ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( cursor . region_select ) {
2020-05-14 16:41:43 +02:00
if ( ! clicked_wants_append ) {
2020-05-10 12:56:01 +02:00
_clear_selected ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-05-06 20:49:22 +02:00
2017-05-20 17:38:03 +02:00
_select_region ( ) ;
cursor . region_select = false ;
surface - > update ( ) ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( _edit . mode ! = TRANSFORM_NONE ) {
static const char * _transform_name [ 4 ] = { " None " , " Rotate " , " Translate " , " Scale " } ;
undo_redo - > create_action ( _transform_name [ _edit . mode ] ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-03 18:49:32 +02:00
undo_redo - > add_do_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
2017-05-20 17:38:03 +02:00
undo_redo - > add_undo_method ( sp , " set_global_transform " , se - > original ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
undo_redo - > commit_action ( ) ;
_edit . mode = TRANSFORM_NONE ;
set_message ( " " ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-07 22:59:05 +02:00
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
}
2016-05-21 15:29:25 +02:00
2017-05-20 17:38:03 +02:00
} break ;
}
}
2014-05-05 03:50:23 +02:00
2017-05-20 17:38:03 +02:00
Ref < InputEventMouseMotion > m = p_event ;
2014-05-05 03:50:23 +02:00
2017-05-20 17:38:03 +02:00
if ( m . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
_edit . mouse_pos = m - > get_position ( ) ;
2014-05-05 03:50:23 +02:00
2017-05-20 17:38:03 +02:00
if ( spatial_editor - > get_selected ( ) ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = spatial_editor - > get_selected ( ) - > get_gizmo ( ) ;
2017-05-20 17:38:03 +02:00
if ( seg . is_valid ( ) ) {
int selected_handle = - 1 ;
int handle = - 1 ;
Vector3 point ;
Vector3 normal ;
bool inters = seg - > intersect_ray ( camera , _edit . mouse_pos , point , normal , & handle , false ) ;
if ( inters & & handle ! = - 1 ) {
selected_handle = handle ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( selected_handle ! = spatial_editor - > get_over_gizmo_handle ( ) ) {
spatial_editor - > set_over_gizmo_handle ( selected_handle ) ;
spatial_editor - > get_selected ( ) - > update_gizmo ( ) ;
2020-05-14 16:41:43 +02:00
if ( selected_handle ! = - 1 ) {
2017-05-20 17:38:03 +02:00
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( spatial_editor - > get_over_gizmo_handle ( ) = = - 1 & & ! ( m - > get_button_mask ( ) & 1 ) & & ! _edit . gizmo . is_valid ( ) ) {
_gizmo_select ( _edit . mouse_pos , true ) ;
}
2014-02-10 02:10:30 +01:00
2017-09-19 02:30:48 +02:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2017-05-20 17:38:03 +02:00
NavigationMode nav_mode = NAVIGATION_NONE ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( _edit . gizmo . is_valid ( ) ) {
2017-06-03 10:54:24 +02:00
_edit . gizmo - > set_handle ( _edit . gizmo_handle , camera , m - > get_position ( ) ) ;
2017-05-20 17:38:03 +02:00
Variant v = _edit . gizmo - > get_handle_value ( _edit . gizmo_handle ) ;
String n = _edit . gizmo - > get_handle_name ( _edit . gizmo_handle ) ;
set_message ( n + " : " + String ( v ) ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} else if ( m - > get_button_mask ( ) & BUTTON_MASK_LEFT ) {
if ( nav_scheme = = NAVIGATION_MAYA & & m - > get_alt ( ) ) {
nav_mode = NAVIGATION_ORBIT ;
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > get_alt ( ) & & m - > get_shift ( ) ) {
nav_mode = NAVIGATION_PAN ;
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > get_alt ( ) & & m - > get_control ( ) ) {
nav_mode = NAVIGATION_ZOOM ;
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > get_alt ( ) ) {
nav_mode = NAVIGATION_ORBIT ;
} else {
2020-02-12 18:24:06 +01:00
if ( clicked . is_valid ( ) ) {
2017-05-20 17:38:03 +02:00
if ( ! clicked_includes_current ) {
_select_clicked ( clicked_wants_append , true ) ;
2018-10-20 12:49:33 +02:00
// Processing was deferred.
2014-03-31 05:59:42 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
_compute_edit ( _edit . mouse_pos ) ;
2020-02-12 18:24:06 +01:00
clicked = ObjectID ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
_edit . mode = TRANSFORM_TRANSLATE ;
}
2014-02-10 02:10:30 +01:00
2019-06-20 16:59:48 +02:00
if ( cursor . region_select ) {
2017-06-03 10:54:24 +02:00
cursor . region_end = m - > get_position ( ) ;
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
return ;
}
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( _edit . mode = = TRANSFORM_NONE ) {
2017-05-20 17:38:03 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-06-03 10:54:24 +02:00
Vector3 ray_pos = _get_ray_pos ( m - > get_position ( ) ) ;
Vector3 ray = _get_ray ( m - > get_position ( ) ) ;
2019-07-24 14:41:09 +02:00
float snap = EDITOR_GET ( " interface/inspector/default_float_step " ) ;
int snap_step_decimals = Math : : range_step_decimals ( snap ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
switch ( _edit . mode ) {
case TRANSFORM_SCALE : {
2017-09-21 23:11:56 +02:00
Vector3 motion_mask ;
Plane plane ;
2017-11-14 23:50:19 +01:00
bool plane_mv = false ;
2017-09-21 23:11:56 +02:00
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
motion_mask = Vector3 ( 0 , 0 , 0 ) ;
plane = Plane ( _edit . center , _get_camera_normal ( ) ) ;
break ;
case TRANSFORM_X_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
break ;
case TRANSFORM_Y_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
break ;
case TRANSFORM_Z_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
break ;
2017-11-14 23:50:19 +01:00
case TRANSFORM_YZ :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ;
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ) ;
plane_mv = true ;
break ;
case TRANSFORM_XZ :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ;
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ) ;
plane_mv = true ;
break ;
case TRANSFORM_XY :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ;
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) ) ;
plane_mv = true ;
break ;
2017-09-21 23:11:56 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 intersection ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 click ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
Vector3 motion = intersection - click ;
2017-11-14 23:50:19 +01:00
if ( _edit . plane ! = TRANSFORM_VIEW ) {
if ( ! plane_mv ) {
motion = motion_mask . dot ( motion ) * motion_mask ;
} else {
// Alternative planar scaling mode
if ( _get_key_modifier ( m ) ! = KEY_SHIFT ) {
motion = motion_mask . dot ( motion ) * motion_mask ;
}
}
2014-02-10 02:10:30 +01:00
2017-11-08 16:07:30 +01:00
} else {
2017-09-21 23:11:56 +02:00
float center_click_dist = click . distance_to ( _edit . center ) ;
float center_inters_dist = intersection . distance_to ( _edit . center ) ;
2020-05-14 16:41:43 +02:00
if ( center_click_dist = = 0 ) {
2017-09-21 23:11:56 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
float scale = center_inters_dist - center_click_dist ;
motion = Vector3 ( scale , scale , scale ) ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2018-10-20 12:49:33 +02:00
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ;
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
snap = spatial_editor - > get_scale_snap ( ) / 100 ;
}
2019-07-24 14:41:09 +02:00
Vector3 motion_snapped = motion ;
motion_snapped . snap ( Vector3 ( snap , snap , snap ) ) ;
// This might not be necessary anymore after issue #288 is solved (in 4.0?).
set_message ( TTR ( " Scaling: " ) + " ( " + String : : num ( motion_snapped . x , snap_step_decimals ) + " , " +
String : : num ( motion_snapped . y , snap_step_decimals ) + " , " + String : : num ( motion_snapped . z , snap_step_decimals ) + " ) " ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2017-09-21 23:11:56 +02:00
if ( ! sp ) {
2017-05-20 17:38:03 +02:00
continue ;
2017-09-21 23:11:56 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2017-09-21 23:11:56 +02:00
if ( ! se ) {
2017-05-20 17:38:03 +02:00
continue ;
2017-09-21 23:11:56 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-23 21:21:15 +02:00
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
2017-05-20 17:38:03 +02:00
Transform original = se - > original ;
2017-09-21 23:11:56 +02:00
Transform original_local = se - > original_local ;
2017-05-20 17:38:03 +02:00
Transform base = Transform ( Basis ( ) , _edit . center ) ;
2017-09-21 23:11:56 +02:00
Transform t ;
Vector3 local_scale ;
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
if ( local_coords ) {
Basis g = original . basis . orthonormalized ( ) ;
Vector3 local_motion = g . inverse ( ) . xform ( motion ) ;
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
local_motion . snap ( Vector3 ( snap , snap , snap ) ) ;
}
local_scale = original_local . basis . get_scale ( ) * ( local_motion + Vector3 ( 1 , 1 , 1 ) ) ;
2017-11-08 16:07:30 +01:00
// Prevent scaling to 0 it would break the gizmo
Basis check = original_local . basis ;
check . scale ( local_scale ) ;
if ( check . determinant ( ) ! = 0 ) {
// Apply scale
sp - > set_scale ( local_scale ) ;
}
2017-09-21 23:11:56 +02:00
} else {
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
motion . snap ( Vector3 ( snap , snap , snap ) ) ;
}
Transform r ;
r . basis . scale ( motion + Vector3 ( 1 , 1 , 1 ) ) ;
t = base * ( r * ( base . inverse ( ) * original ) ) ;
2017-11-08 16:07:30 +01:00
// Apply scale
2017-09-21 23:11:56 +02:00
sp - > set_global_transform ( t ) ;
}
2017-05-20 17:38:03 +02:00
}
2014-03-31 05:59:42 +02:00
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
2014-03-31 05:59:42 +02:00
2017-05-20 17:38:03 +02:00
} break ;
2014-03-31 05:59:42 +02:00
2017-05-20 17:38:03 +02:00
case TRANSFORM_TRANSLATE : {
Vector3 motion_mask ;
Plane plane ;
2017-11-13 22:54:33 +01:00
bool plane_mv = false ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
plane = Plane ( _edit . center , _get_camera_normal ( ) ) ;
break ;
case TRANSFORM_X_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
break ;
case TRANSFORM_Y_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
2014-03-31 05:59:42 +02:00
break ;
2017-05-20 17:38:03 +02:00
case TRANSFORM_Z_AXIS :
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) ;
plane = Plane ( _edit . center , motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) ) ;
break ;
2017-08-29 03:39:45 +02:00
case TRANSFORM_YZ :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ) ;
plane_mv = true ;
break ;
case TRANSFORM_XZ :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ) ;
plane_mv = true ;
break ;
case TRANSFORM_XY :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) ) ;
plane_mv = true ;
break ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 intersection ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 click ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 motion = intersection - click ;
2017-11-14 23:50:19 +01:00
if ( _edit . plane ! = TRANSFORM_VIEW ) {
2017-11-08 16:07:30 +01:00
if ( ! plane_mv ) {
2017-08-29 03:39:45 +02:00
motion = motion_mask . dot ( motion ) * motion_mask ;
2017-11-08 16:07:30 +01:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-08-08 12:55:21 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2018-10-20 12:49:33 +02:00
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
snap = spatial_editor - > get_translate_snap ( ) ;
2017-08-08 12:55:21 +02:00
}
2019-07-24 14:41:09 +02:00
Vector3 motion_snapped = motion ;
motion_snapped . snap ( Vector3 ( snap , snap , snap ) ) ;
set_message ( TTR ( " Translating: " ) + " ( " + String : : num ( motion_snapped . x , snap_step_decimals ) + " , " +
String : : num ( motion_snapped . y , snap_step_decimals ) + " , " + String : : num ( motion_snapped . z , snap_step_decimals ) + " ) " ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2017-05-20 17:38:03 +02:00
if ( ! sp ) {
continue ;
2014-02-10 02:10:30 +01:00
}
2014-03-31 05:59:42 +02:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2017-05-20 17:38:03 +02:00
if ( ! se ) {
continue ;
}
2014-03-31 05:59:42 +02:00
2017-10-23 21:21:15 +02:00
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
2017-11-08 16:07:30 +01:00
Transform original = se - > original ;
Transform t ;
if ( local_coords ) {
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
Basis g = original . basis . orthonormalized ( ) ;
Vector3 local_motion = g . inverse ( ) . xform ( motion ) ;
local_motion . snap ( Vector3 ( snap , snap , snap ) ) ;
motion = g . xform ( local_motion ) ;
}
} else {
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
motion . snap ( Vector3 ( snap , snap , snap ) ) ;
}
}
// Apply translation
t = original ;
2017-05-20 17:38:03 +02:00
t . origin + = motion ;
sp - > set_global_transform ( t ) ;
}
2017-11-08 16:07:30 +01:00
surface - > update ( ) ;
2017-05-20 17:38:03 +02:00
} break ;
2014-03-31 05:59:42 +02:00
2017-05-20 17:38:03 +02:00
case TRANSFORM_ROTATE : {
Plane plane ;
2017-10-04 09:34:58 +02:00
Vector3 axis ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
plane = Plane ( _edit . center , _get_camera_normal ( ) ) ;
break ;
case TRANSFORM_X_AXIS :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 0 ) ) ;
2017-10-04 09:34:58 +02:00
axis = Vector3 ( 1 , 0 , 0 ) ;
2014-03-31 05:59:42 +02:00
break ;
2017-05-20 17:38:03 +02:00
case TRANSFORM_Y_AXIS :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 1 ) ) ;
2017-10-04 09:34:58 +02:00
axis = Vector3 ( 0 , 1 , 0 ) ;
2017-05-20 17:38:03 +02:00
break ;
case TRANSFORM_Z_AXIS :
plane = Plane ( _edit . center , spatial_editor - > get_gizmo_transform ( ) . basis . get_axis ( 2 ) ) ;
2017-10-04 09:34:58 +02:00
axis = Vector3 ( 0 , 0 , 1 ) ;
2017-05-20 17:38:03 +02:00
break ;
2018-09-26 13:13:56 +02:00
case TRANSFORM_YZ :
case TRANSFORM_XZ :
case TRANSFORM_XY :
break ;
2017-05-20 17:38:03 +02:00
}
Vector3 intersection ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 click ;
2020-05-14 16:41:43 +02:00
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
2017-05-20 17:38:03 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Vector3 y_axis = ( click - _edit . center ) . normalized ( ) ;
Vector3 x_axis = plane . normal . cross ( y_axis ) . normalized ( ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
float angle = Math : : atan2 ( x_axis . dot ( intersection - _edit . center ) , y_axis . dot ( intersection - _edit . center ) ) ;
2017-10-04 09:34:58 +02:00
2017-05-20 17:38:03 +02:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
2019-07-24 14:41:09 +02:00
snap = spatial_editor - > get_rotate_snap ( ) ;
2017-05-20 17:38:03 +02:00
}
2019-07-24 14:41:09 +02:00
angle = Math : : rad2deg ( angle ) + snap * 0.5 ; //else it won't reach +180
angle - = Math : : fmod ( angle , snap ) ;
set_message ( vformat ( TTR ( " Rotating %s degrees. " ) , String : : num ( angle , snap_step_decimals ) ) ) ;
angle = Math : : deg2rad ( angle ) ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2017-11-13 09:15:41 +01:00
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ; // Disable local transformation for TRANSFORM_VIEW
2017-10-04 09:34:58 +02:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-23 21:21:15 +02:00
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
2017-10-04 09:34:58 +02:00
Transform t ;
2014-02-10 02:10:30 +01:00
2017-10-04 09:34:58 +02:00
if ( local_coords ) {
Transform original_local = se - > original_local ;
Basis rot = Basis ( axis , angle ) ;
2017-11-08 16:07:30 +01:00
t . basis = original_local . get_basis ( ) . orthonormalized ( ) * rot ;
2017-10-04 09:34:58 +02:00
t . origin = original_local . origin ;
2017-11-08 16:07:30 +01:00
// Apply rotation
2017-10-04 09:34:58 +02:00
sp - > set_transform ( t ) ;
2017-11-08 16:07:30 +01:00
sp - > set_scale ( original_local . basis . get_scale ( ) ) ; // re-apply original scale
2017-10-04 09:34:58 +02:00
} else {
Transform original = se - > original ;
Transform r ;
Transform base = Transform ( Basis ( ) , _edit . center ) ;
r . basis . rotate ( plane . normal , angle ) ;
t = base * r * base . inverse ( ) * original ;
2017-11-08 16:07:30 +01:00
// Apply rotation
2017-10-04 09:34:58 +02:00
sp - > set_global_transform ( t ) ;
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
surface - > update ( ) ;
2017-10-04 09:34:58 +02:00
2017-05-20 17:38:03 +02:00
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-30 01:22:48 +01:00
} else if ( ( m - > get_button_mask ( ) & BUTTON_MASK_RIGHT ) | | freelook_active ) {
2017-05-20 17:38:03 +02:00
if ( nav_scheme = = NAVIGATION_MAYA & & m - > get_alt ( ) ) {
nav_mode = NAVIGATION_ZOOM ;
2017-07-23 02:02:18 +02:00
} else if ( freelook_active ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_LOOK ;
2018-10-20 12:49:33 +02:00
} else if ( orthogonal ) {
nav_mode = NAVIGATION_PAN ;
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
} else if ( m - > get_button_mask ( ) & BUTTON_MASK_MIDDLE ) {
if ( nav_scheme = = NAVIGATION_GODOT ) {
2019-11-13 21:54:44 +01:00
const int mod = _get_key_modifier ( m ) ;
2016-05-21 15:29:25 +02:00
2019-11-13 21:54:44 +01:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_ZOOM ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = KEY_ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
// Always allow Alt as a modifier to better support graphic tablets.
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 21:54:44 +01:00
}
2017-05-20 17:38:03 +02:00
} else if ( nav_scheme = = NAVIGATION_MAYA ) {
2020-05-14 16:41:43 +02:00
if ( m - > get_alt ( ) ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_PAN ;
2020-05-14 16:41:43 +02:00
}
2014-03-31 05:07:21 +02:00
}
2014-02-10 02:10:30 +01:00
2017-09-19 02:30:48 +02:00
} else if ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/emulate_3_button_mouse " ) ) {
2017-05-20 17:38:03 +02:00
// Handle trackpad (no external mouse) use case
2019-11-13 21:54:44 +01:00
const int mod = _get_key_modifier ( m ) ;
2017-05-20 17:38:03 +02:00
if ( mod ) {
2019-11-13 21:54:44 +01:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_ZOOM ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = KEY_ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
// Always allow Alt as a modifier to better support graphic tablets.
2017-05-20 17:38:03 +02:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 21:54:44 +01:00
}
2017-05-20 17:38:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
switch ( nav_mode ) {
case NAVIGATION_PAN : {
2017-11-01 21:49:39 +01:00
_nav_pan ( m , _get_warped_mouse_motion ( m ) ) ;
2014-02-10 02:10:30 +01:00
2017-11-01 21:49:39 +01:00
} break ;
case NAVIGATION_ZOOM : {
_nav_zoom ( m , m - > get_relative ( ) ) ;
} break ;
case NAVIGATION_ORBIT : {
_nav_orbit ( m , _get_warped_mouse_motion ( m ) ) ;
} break ;
case NAVIGATION_LOOK : {
_nav_look ( m , _get_warped_mouse_motion ( m ) ) ;
} break ;
2019-04-09 17:08:36 +02:00
default : {
}
2017-11-01 21:49:39 +01:00
}
}
2017-03-22 21:18:47 +01:00
2017-11-01 21:49:39 +01:00
Ref < InputEventMagnifyGesture > magnify_gesture = p_event ;
if ( magnify_gesture . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
if ( is_freelook_active ( ) ) {
2017-11-01 21:49:39 +01:00
scale_freelook_speed ( magnify_gesture - > get_factor ( ) ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-11-01 21:49:39 +01:00
scale_cursor_distance ( 1.0 / magnify_gesture - > get_factor ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
}
Ref < InputEventPanGesture > pan_gesture = p_event ;
if ( pan_gesture . is_valid ( ) ) {
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
NavigationMode nav_mode = NAVIGATION_NONE ;
2017-05-20 17:38:03 +02:00
2017-11-01 21:49:39 +01:00
if ( nav_scheme = = NAVIGATION_GODOT ) {
2019-11-13 21:54:44 +01:00
const int mod = _get_key_modifier ( pan_gesture ) ;
2017-11-01 21:49:39 +01:00
2019-11-13 21:54:44 +01:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-11-01 21:49:39 +01:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-11-01 21:49:39 +01:00
nav_mode = NAVIGATION_ZOOM ;
2019-11-13 21:54:44 +01:00
} else if ( mod = = KEY_ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
// Always allow Alt as a modifier to better support graphic tablets.
2017-11-01 21:49:39 +01:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 21:54:44 +01:00
}
2017-11-01 21:49:39 +01:00
} else if ( nav_scheme = = NAVIGATION_MAYA ) {
2020-05-14 16:41:43 +02:00
if ( pan_gesture - > get_alt ( ) ) {
2017-11-01 21:49:39 +01:00
nav_mode = NAVIGATION_PAN ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
}
switch ( nav_mode ) {
case NAVIGATION_PAN : {
2020-07-23 16:38:31 +02:00
_nav_pan ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-20 17:38:03 +02:00
} break ;
case NAVIGATION_ZOOM : {
2020-07-23 16:38:31 +02:00
_nav_zoom ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-20 17:38:03 +02:00
} break ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
case NAVIGATION_ORBIT : {
2020-07-23 16:38:31 +02:00
_nav_orbit ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-11-01 21:49:39 +01:00
2017-05-20 17:38:03 +02:00
} break ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
case NAVIGATION_LOOK : {
2020-07-23 16:38:31 +02:00
_nav_look ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-01 20:57:35 +02:00
2017-05-20 17:38:03 +02:00
} break ;
2017-05-01 20:57:35 +02:00
2019-04-09 17:08:36 +02:00
default : {
}
2017-05-20 17:38:03 +02:00
}
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
Ref < InputEventKey > k = p_event ;
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
if ( k . is_valid ( ) ) {
2020-05-14 16:41:43 +02:00
if ( ! k - > is_pressed ( ) ) {
2017-05-20 17:38:03 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
if ( ED_IS_SHORTCUT ( " spatial_editor/snap " , p_event ) ) {
if ( _edit . mode ! = TRANSFORM_NONE ) {
2019-03-16 09:15:39 +01:00
_edit . snap = ! _edit . snap ;
2017-05-20 17:38:03 +02:00
}
}
if ( ED_IS_SHORTCUT ( " spatial_editor/bottom_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_BOTTOM ) ;
2017-05-20 17:38:03 +02:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/top_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_TOP ) ;
2017-05-20 17:38:03 +02:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/rear_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_REAR ) ;
2017-05-20 17:38:03 +02:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/front_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_FRONT ) ;
2017-05-20 17:38:03 +02:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/left_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_LEFT ) ;
2017-05-20 17:38:03 +02:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/right_view " , p_event ) ) {
2017-12-19 15:29:55 +01:00
_menu_option ( VIEW_RIGHT ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/focus_origin " , p_event ) ) {
_menu_option ( VIEW_CENTER_TO_ORIGIN ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/focus_selection " , p_event ) ) {
_menu_option ( VIEW_CENTER_TO_SELECTION ) ;
2017-05-20 17:38:03 +02:00
}
2018-10-20 12:49:33 +02:00
// Orthgonal mode doesn't work in freelook.
if ( ! freelook_active & & ED_IS_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " , p_event ) ) {
2017-05-20 17:38:03 +02:00
_menu_option ( orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL ) ;
_update_name ( ) ;
}
2018-10-27 23:43:19 +02:00
if ( ED_IS_SHORTCUT ( " spatial_editor/align_transform_with_view " , p_event ) ) {
_menu_option ( VIEW_ALIGN_TRANSFORM_WITH_VIEW ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/align_rotation_with_view " , p_event ) ) {
_menu_option ( VIEW_ALIGN_ROTATION_WITH_VIEW ) ;
2017-12-19 15:29:55 +01:00
}
2017-05-20 17:38:03 +02:00
if ( ED_IS_SHORTCUT ( " spatial_editor/insert_anim_key " , p_event ) ) {
2020-05-14 16:41:43 +02:00
if ( ! get_selected_count ( ) | | _edit . mode ! = TRANSFORM_NONE ) {
2017-05-20 17:38:03 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2018-06-07 17:46:14 +02:00
if ( ! AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > has_keying ( ) ) {
2017-05-20 17:38:03 +02:00
set_message ( TTR ( " Keying is disabled (no key inserted). " ) ) ;
return ;
}
2014-02-10 02:10:30 +01:00
2017-05-20 17:38:03 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-03-31 17:06:36 +02:00
2017-05-20 17:38:03 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2017-05-20 17:38:03 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
2019-04-14 22:27:59 +02:00
spatial_editor - > emit_signal ( " transform_key_request " , sp , " " , sp - > get_transform ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-05-20 17:38:03 +02:00
set_message ( TTR ( " Animation Key Inserted. " ) ) ;
}
2014-02-10 02:10:30 +01:00
2018-10-20 12:49:33 +02:00
// Freelook doesn't work in orthogonal mode.
if ( ! orthogonal & & ED_IS_SHORTCUT ( " spatial_editor/freelook_toggle " , p_event ) ) {
2017-10-30 01:22:48 +01:00
set_freelook_active ( ! is_freelook_active ( ) ) ;
2018-04-05 19:59:35 +02:00
} else if ( k - > get_keycode ( ) = = KEY_ESCAPE ) {
2017-10-30 01:22:48 +01:00
set_freelook_active ( false ) ;
}
2018-04-05 19:59:35 +02:00
if ( k - > get_keycode ( ) = = KEY_SPACE ) {
2020-05-14 16:41:43 +02:00
if ( ! k - > is_pressed ( ) ) {
2020-05-10 12:56:01 +02:00
emit_signal ( " toggle_maximize_view " , this ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-20 17:38:03 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-10-29 21:31:38 +01:00
// freelook uses most of the useful shortcuts, like save, so its ok
// to consider freelook active as end of the line for future events.
2020-05-14 16:41:43 +02:00
if ( freelook_active ) {
2017-10-29 21:31:38 +01:00
accept_event ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _nav_pan ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2017-11-01 21:49:39 +01:00
const NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
real_t pan_speed = 1 / 150.0 ;
int pan_speed_modifier = 10 ;
2020-05-14 16:41:43 +02:00
if ( nav_scheme = = NAVIGATION_MAYA & & p_event - > get_shift ( ) ) {
2017-11-01 21:49:39 +01:00
pan_speed * = pan_speed_modifier ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
Transform camera_transform ;
camera_transform . translate ( cursor . pos ) ;
camera_transform . basis . rotate ( Vector3 ( 1 , 0 , 0 ) , - cursor . x_rot ) ;
camera_transform . basis . rotate ( Vector3 ( 0 , 1 , 0 ) , - cursor . y_rot ) ;
2020-08-15 13:18:01 +02:00
const bool invert_x_axis = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/invert_x_axis " ) ;
const bool invert_y_axis = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/invert_y_axis " ) ;
Vector3 translation (
( invert_x_axis ? - 1 : 1 ) * - p_relative . x * pan_speed ,
( invert_y_axis ? - 1 : 1 ) * p_relative . y * pan_speed ,
0 ) ;
2017-11-01 21:49:39 +01:00
translation * = cursor . distance / DISTANCE_DEFAULT ;
camera_transform . translate ( translation ) ;
cursor . pos = camera_transform . origin ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _nav_zoom ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2017-11-01 21:49:39 +01:00
const NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
real_t zoom_speed = 1 / 80.0 ;
int zoom_speed_modifier = 10 ;
2020-05-14 16:41:43 +02:00
if ( nav_scheme = = NAVIGATION_MAYA & & p_event - > get_shift ( ) ) {
2017-11-01 21:49:39 +01:00
zoom_speed * = zoom_speed_modifier ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
NavigationZoomStyle zoom_style = ( NavigationZoomStyle ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/zoom_style " ) . operator int ( ) ;
if ( zoom_style = = NAVIGATION_ZOOM_HORIZONTAL ) {
2020-05-14 16:41:43 +02:00
if ( p_relative . x > 0 ) {
2017-11-01 21:49:39 +01:00
scale_cursor_distance ( 1 - p_relative . x * zoom_speed ) ;
2020-05-14 16:41:43 +02:00
} else if ( p_relative . x < 0 ) {
2017-11-01 21:49:39 +01:00
scale_cursor_distance ( 1.0 / ( 1 + p_relative . x * zoom_speed ) ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
} else {
2020-05-14 16:41:43 +02:00
if ( p_relative . y > 0 ) {
2017-11-01 21:49:39 +01:00
scale_cursor_distance ( 1 + p_relative . y * zoom_speed ) ;
2020-05-14 16:41:43 +02:00
} else if ( p_relative . y < 0 ) {
2017-11-01 21:49:39 +01:00
scale_cursor_distance ( 1.0 / ( 1 - p_relative . y * zoom_speed ) ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-01 21:49:39 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _nav_orbit ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2018-06-25 03:24:31 +02:00
if ( lock_rotation ) {
_nav_pan ( p_event , p_relative ) ;
return ;
}
2019-10-23 11:46:26 +02:00
if ( orthogonal & & auto_orthogonal ) {
_menu_option ( VIEW_PERSPECTIVE ) ;
}
2020-08-15 13:18:01 +02:00
const real_t degrees_per_pixel = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation_feel/orbit_sensitivity " ) ;
const real_t radians_per_pixel = Math : : deg2rad ( degrees_per_pixel ) ;
const bool invert_y_axis = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/invert_y_axis " ) ;
const bool invert_x_axis = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/invert_x_axis " ) ;
2017-11-01 21:49:39 +01:00
2018-03-14 14:32:29 +01:00
if ( invert_y_axis ) {
cursor . x_rot - = p_relative . y * radians_per_pixel ;
} else {
cursor . x_rot + = p_relative . y * radians_per_pixel ;
}
2020-08-15 13:18:01 +02:00
// Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
2020-06-20 11:05:43 +02:00
cursor . x_rot = CLAMP ( cursor . x_rot , - 1.57 , 1.57 ) ;
2020-08-15 13:18:01 +02:00
if ( invert_x_axis ) {
cursor . y_rot - = p_relative . x * radians_per_pixel ;
} else {
cursor . y_rot + = p_relative . x * radians_per_pixel ;
}
2017-11-01 21:49:39 +01:00
name = " " ;
_update_name ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _nav_look ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2018-10-20 12:49:33 +02:00
if ( orthogonal ) {
_nav_pan ( p_event , p_relative ) ;
return ;
}
2017-11-01 21:49:39 +01:00
2019-10-23 11:46:26 +02:00
if ( orthogonal & & auto_orthogonal ) {
_menu_option ( VIEW_PERSPECTIVE ) ;
}
2020-08-15 13:18:01 +02:00
const real_t degrees_per_pixel = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_sensitivity " ) ;
const real_t radians_per_pixel = Math : : deg2rad ( degrees_per_pixel ) ;
const bool invert_y_axis = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/invert_y_axis " ) ;
2017-11-01 21:49:39 +01:00
2018-10-20 12:49:33 +02:00
// Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
2020-08-15 13:18:01 +02:00
const Transform prev_camera_transform = to_camera_transform ( cursor ) ;
2018-10-20 12:49:33 +02:00
if ( invert_y_axis ) {
cursor . x_rot - = p_relative . y * radians_per_pixel ;
} else {
cursor . x_rot + = p_relative . y * radians_per_pixel ;
2017-11-01 21:49:39 +01:00
}
2020-08-15 13:18:01 +02:00
// Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
2020-06-20 11:05:43 +02:00
cursor . x_rot = CLAMP ( cursor . x_rot , - 1.57 , 1.57 ) ;
2018-10-20 12:49:33 +02:00
2020-08-15 13:18:01 +02:00
cursor . y_rot + = p_relative . x * radians_per_pixel ;
2018-10-20 12:49:33 +02:00
// Look is like the opposite of Orbit: the focus point rotates around the camera
Transform camera_transform = to_camera_transform ( cursor ) ;
Vector3 pos = camera_transform . xform ( Vector3 ( 0 , 0 , 0 ) ) ;
Vector3 prev_pos = prev_camera_transform . xform ( Vector3 ( 0 , 0 , 0 ) ) ;
Vector3 diff = prev_pos - pos ;
cursor . pos + = diff ;
name = " " ;
_update_name ( ) ;
2017-11-01 21:49:39 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : set_freelook_active ( bool active_now ) {
2017-10-08 02:43:57 +02:00
if ( ! freelook_active & & active_now ) {
// Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
cursor = camera_cursor ;
// Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos
Vector3 forward = to_camera_transform ( cursor ) . basis . xform ( Vector3 ( 0 , 0 , - 1 ) ) ;
cursor . eye_pos = cursor . pos - cursor . distance * forward ;
// Also sync the camera cursor, otherwise switching to freelook will be trippy if inertia is active
camera_cursor . eye_pos = cursor . eye_pos ;
if ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_speed_zoom_link " ) ) {
// Re-adjust freelook speed from the current zoom level
real_t base_speed = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_base_speed " ) ;
freelook_speed = base_speed * cursor . distance ;
}
2020-06-17 20:02:46 +02:00
previous_mouse_position = get_local_mouse_position ( ) ;
2017-10-30 01:22:48 +01:00
// Hide mouse like in an FPS (warping doesn't work)
2020-04-28 16:41:01 +02:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_CAPTURED ) ;
2017-10-30 01:22:48 +01:00
2017-10-08 02:43:57 +02:00
} else if ( freelook_active & & ! active_now ) {
// Sync camera cursor to cursor to "cut" interpolation jumps due to changing referential
cursor = camera_cursor ;
2017-10-30 01:22:48 +01:00
// Restore mouse
2020-04-28 16:41:01 +02:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
2020-06-17 20:02:46 +02:00
// Restore the previous mouse position when leaving freelook mode.
// This is done because leaving `Input.MOUSE_MODE_CAPTURED` will center the cursor
// due to OS limitations.
warp_mouse ( previous_mouse_position ) ;
2017-10-08 02:43:57 +02:00
}
freelook_active = active_now ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : scale_cursor_distance ( real_t scale ) {
2020-12-16 13:40:42 +01:00
real_t min_distance = MAX ( camera - > get_near ( ) * 4 , ZOOM_FREELOOK_MIN ) ;
real_t max_distance = MIN ( camera - > get_far ( ) / 4 , ZOOM_FREELOOK_MAX ) ;
2020-06-22 05:40:17 +02:00
if ( unlikely ( min_distance > max_distance ) ) {
cursor . distance = ( min_distance + max_distance ) / 2 ;
} else {
cursor . distance = CLAMP ( cursor . distance * scale , min_distance , max_distance ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-07 22:59:05 +02:00
2020-06-22 05:40:17 +02:00
zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S ;
2017-10-08 02:43:57 +02:00
surface - > update ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : scale_freelook_speed ( real_t scale ) {
2020-12-16 13:40:42 +01:00
real_t min_speed = MAX ( camera - > get_near ( ) * 4 , ZOOM_FREELOOK_MIN ) ;
real_t max_speed = MIN ( camera - > get_far ( ) / 4 , ZOOM_FREELOOK_MAX ) ;
2020-06-22 05:40:17 +02:00
if ( unlikely ( min_speed > max_speed ) ) {
freelook_speed = ( min_speed + max_speed ) / 2 ;
} else {
freelook_speed = CLAMP ( freelook_speed * scale , min_speed , max_speed ) ;
2020-05-14 16:41:43 +02:00
}
2017-05-07 22:59:05 +02:00
2020-06-22 05:40:17 +02:00
zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S ;
2017-05-07 22:59:05 +02:00
surface - > update ( ) ;
}
2020-03-26 22:49:16 +01:00
Point2i Node3DEditorViewport : : _get_warped_mouse_motion ( const Ref < InputEventMouseMotion > & p_ev_mouse_motion ) const {
2017-05-05 23:42:48 +02:00
Point2i relative ;
2017-09-19 02:30:48 +02:00
if ( bool ( EDITOR_DEF ( " editors/3d/navigation/warped_mouse_panning " , false ) ) ) {
2020-04-28 15:19:37 +02:00
relative = Input : : get_singleton ( ) - > warp_mouse_motion ( p_ev_mouse_motion , surface - > get_global_rect ( ) ) ;
2017-05-05 23:42:48 +02:00
} else {
2017-05-20 17:38:03 +02:00
relative = p_ev_mouse_motion - > get_relative ( ) ;
2017-05-05 23:42:48 +02:00
}
return relative ;
}
2018-01-15 00:32:27 +01:00
static bool is_shortcut_pressed ( const String & p_path ) {
2020-09-09 21:53:24 +02:00
Ref < Shortcut > shortcut = ED_GET_SHORTCUT ( p_path ) ;
2018-01-15 00:32:27 +01:00
if ( shortcut . is_null ( ) ) {
return false ;
}
InputEventKey * k = Object : : cast_to < InputEventKey > ( shortcut - > get_shortcut ( ) . ptr ( ) ) ;
2020-04-02 01:20:12 +02:00
if ( k = = nullptr ) {
2018-01-15 00:32:27 +01:00
return false ;
}
2020-04-28 15:19:37 +02:00
const Input & input = * Input : : get_singleton ( ) ;
2018-04-05 19:59:35 +02:00
int keycode = k - > get_keycode ( ) ;
return input . is_key_pressed ( keycode ) ;
2018-01-15 00:32:27 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _update_freelook ( real_t delta ) {
2017-08-26 21:55:09 +02:00
if ( ! is_freelook_active ( ) ) {
2017-05-01 20:57:35 +02:00
return ;
2017-08-26 21:55:09 +02:00
}
2017-05-01 20:57:35 +02:00
2020-04-18 16:20:35 +02:00
const FreelookNavigationScheme navigation_scheme = ( FreelookNavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_navigation_scheme " ) . operator int ( ) ;
Vector3 forward ;
if ( navigation_scheme = = FREELOOK_FULLY_AXIS_LOCKED ) {
// Forward/backward keys will always go straight forward/backward, never moving on the Y axis.
forward = Vector3 ( 0 , 0 , - 1 ) . rotated ( Vector3 ( 0 , 1 , 0 ) , camera - > get_rotation ( ) . y ) ;
} else {
// Forward/backward keys will be relative to the camera pitch.
forward = camera - > get_transform ( ) . basis . xform ( Vector3 ( 0 , 0 , - 1 ) ) ;
}
2019-10-14 22:47:47 +02:00
const Vector3 right = camera - > get_transform ( ) . basis . xform ( Vector3 ( 1 , 0 , 0 ) ) ;
2020-04-18 16:20:35 +02:00
Vector3 up ;
if ( navigation_scheme = = FREELOOK_PARTIALLY_AXIS_LOCKED | | navigation_scheme = = FREELOOK_FULLY_AXIS_LOCKED ) {
// Up/down keys will always go up/down regardless of camera pitch.
up = Vector3 ( 0 , 1 , 0 ) ;
} else {
// Up/down keys will be relative to the camera pitch.
up = camera - > get_transform ( ) . basis . xform ( Vector3 ( 0 , 1 , 0 ) ) ;
}
2017-05-01 20:57:35 +02:00
2017-08-26 21:55:09 +02:00
Vector3 direction ;
2017-05-01 20:57:35 +02:00
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_left " ) ) {
2017-08-26 21:55:09 +02:00
direction - = right ;
2017-05-01 20:57:35 +02:00
}
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_right " ) ) {
2017-08-26 21:55:09 +02:00
direction + = right ;
2017-05-01 20:57:35 +02:00
}
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_forward " ) ) {
2017-08-26 21:55:09 +02:00
direction + = forward ;
2017-05-01 20:57:35 +02:00
}
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_backwards " ) ) {
2017-08-26 21:55:09 +02:00
direction - = forward ;
2017-05-01 20:57:35 +02:00
}
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_up " ) ) {
2017-08-26 21:55:09 +02:00
direction + = up ;
2017-05-01 20:57:35 +02:00
}
2018-01-15 00:32:27 +01:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_down " ) ) {
2017-08-26 21:55:09 +02:00
direction - = up ;
2017-05-01 20:57:35 +02:00
}
2017-10-08 02:43:57 +02:00
real_t speed = freelook_speed ;
2019-10-14 22:47:47 +02:00
if ( is_shortcut_pressed ( " spatial_editor/freelook_speed_modifier " ) ) {
speed * = 3.0 ;
}
if ( is_shortcut_pressed ( " spatial_editor/freelook_slow_modifier " ) ) {
speed * = 0.333333 ;
2017-10-08 02:43:57 +02:00
}
2017-05-07 22:59:05 +02:00
2019-10-14 22:47:47 +02:00
const Vector3 motion = direction * speed * delta ;
2017-10-08 02:43:57 +02:00
cursor . pos + = motion ;
cursor . eye_pos + = motion ;
2017-05-01 20:57:35 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : set_message ( String p_message , float p_time ) {
2017-03-05 16:44:50 +01:00
message = p_message ;
message_time = p_time ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : edited_scene_changed ( ) {
for ( uint32_t i = 0 ; i < Node3DEditor : : VIEWPORTS_COUNT ; i + + ) {
Node3DEditorViewport * viewport = Node3DEditor : : get_singleton ( ) - > get_editor_viewport ( i ) ;
2018-08-14 23:13:48 +02:00
if ( viewport - > is_visible ( ) ) {
viewport - > notification ( Control : : NOTIFICATION_VISIBILITY_CHANGED ) ;
}
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_VISIBILITY_CHANGED ) {
bool visible = is_visible_in_tree ( ) ;
2014-02-10 02:10:30 +01:00
set_process ( visible ) ;
2016-04-06 08:34:34 +02:00
2019-01-30 14:46:44 +01:00
if ( visible ) {
2020-02-19 08:22:31 +01:00
orthogonal = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ORTHOGONAL ) ) ;
_update_name ( ) ;
2017-08-26 05:40:45 +02:00
_update_camera ( 0 ) ;
2019-01-30 14:46:44 +01:00
} else {
set_freelook_active ( false ) ;
}
2014-05-05 03:50:23 +02:00
call_deferred ( " update_transform_gizmo_view " ) ;
2019-10-23 11:46:26 +02:00
rotation_control - > set_visible ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/show_viewport_rotation_gizmo " ) ) ;
2014-05-05 03:50:23 +02:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_RESIZED ) {
2014-05-05 03:50:23 +02:00
call_deferred ( " update_transform_gizmo_view " ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_PROCESS ) {
2017-10-08 02:43:57 +02:00
real_t delta = get_process_delta_time ( ) ;
2017-05-07 22:59:05 +02:00
if ( zoom_indicator_delay > 0 ) {
zoom_indicator_delay - = delta ;
if ( zoom_indicator_delay < = 0 ) {
surface - > update ( ) ;
}
}
_update_freelook ( delta ) ;
2017-05-01 20:57:35 +02:00
2018-07-27 00:36:05 +02:00
Node * scene_root = editor - > get_scene_tree_dock ( ) - > get_editor_data ( ) - > get_edited_scene_root ( ) ;
2020-04-02 01:20:12 +02:00
if ( previewing_cinema & & scene_root ! = nullptr ) {
2020-03-26 22:49:16 +01:00
Camera3D * cam = scene_root - > get_viewport ( ) - > get_camera ( ) ;
2020-04-02 01:20:12 +02:00
if ( cam ! = nullptr & & cam ! = previewing ) {
2018-07-27 00:36:05 +02:00
//then switch the viewport's camera to the scene's viewport camera
2020-04-02 01:20:12 +02:00
if ( previewing ! = nullptr ) {
2020-03-26 22:49:16 +01:00
previewing - > disconnect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2018-07-27 00:36:05 +02:00
}
previewing = cam ;
2020-03-26 22:49:16 +01:00
previewing - > connect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , cam - > get_camera ( ) ) ;
2018-07-27 00:36:05 +02:00
surface - > update ( ) ;
}
}
2017-10-08 02:43:57 +02:00
_update_camera ( delta ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool changed = false ;
bool exist = false ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > key ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-10 16:23:22 +01:00
Transform t = sp - > get_global_gizmo_transform ( ) ;
2020-10-05 11:03:23 +02:00
VisualInstance3D * vi = Object : : cast_to < VisualInstance3D > ( sp ) ;
AABB new_aabb = vi ? vi - > get_aabb ( ) : _calculate_spatial_bounds ( sp ) ;
2020-03-10 16:23:22 +01:00
exist = true ;
2020-10-05 11:03:23 +02:00
if ( se - > last_xform = = t & & se - > aabb = = new_aabb & & ! se - > last_xform_dirty ) {
2020-03-10 16:23:22 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2020-03-10 16:23:22 +01:00
changed = true ;
2020-03-19 07:43:25 +01:00
se - > last_xform_dirty = false ;
2020-03-10 16:23:22 +01:00
se - > last_xform = t ;
2020-10-05 11:03:23 +02:00
se - > aabb = new_aabb ;
2014-02-10 02:10:30 +01:00
2017-06-06 20:33:51 +02:00
t . translate ( se - > aabb . position ) ;
2017-08-23 02:05:41 +02:00
// apply AABB scaling before item's global transform
Basis aabb_s ;
aabb_s . scale ( se - > aabb . size ) ;
t . basis = t . basis * aabb_s ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance , t ) ;
2020-07-04 00:11:56 +02:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance_xray , t ) ;
2014-02-10 02:10:30 +01:00
}
if ( changed | | ( spatial_editor - > is_gizmo_visible ( ) & & ! exist ) ) {
spatial_editor - > update_transform_gizmo ( ) ;
}
2017-03-05 16:44:50 +01:00
if ( message_time > 0 ) {
if ( message ! = last_message ) {
2014-02-10 02:10:30 +01:00
surface - > update ( ) ;
2017-03-05 16:44:50 +01:00
last_message = message ;
2014-02-10 02:10:30 +01:00
}
2017-09-30 16:19:07 +02:00
message_time - = get_physics_process_delta_time ( ) ;
2020-05-14 16:41:43 +02:00
if ( message_time < 0 ) {
2014-02-10 02:10:30 +01:00
surface - > update ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-01-02 02:16:52 +01:00
//update shadow atlas if changed
2016-11-10 03:55:06 +01:00
2017-07-19 22:00:46 +02:00
int shadowmap_size = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/shadow_atlas/size " ) ;
int atlas_q0 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/shadow_atlas/quadrant_0_subdiv " ) ;
int atlas_q1 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/shadow_atlas/quadrant_1_subdiv " ) ;
int atlas_q2 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/shadow_atlas/quadrant_2_subdiv " ) ;
int atlas_q3 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/shadow_atlas/quadrant_3_subdiv " ) ;
2016-11-10 03:55:06 +01:00
viewport - > set_shadow_atlas_size ( shadowmap_size ) ;
2017-03-05 16:44:50 +01:00
viewport - > set_shadow_atlas_quadrant_subdiv ( 0 , Viewport : : ShadowAtlasQuadrantSubdiv ( atlas_q0 ) ) ;
viewport - > set_shadow_atlas_quadrant_subdiv ( 1 , Viewport : : ShadowAtlasQuadrantSubdiv ( atlas_q1 ) ) ;
viewport - > set_shadow_atlas_quadrant_subdiv ( 2 , Viewport : : ShadowAtlasQuadrantSubdiv ( atlas_q2 ) ) ;
viewport - > set_shadow_atlas_quadrant_subdiv ( 3 , Viewport : : ShadowAtlasQuadrantSubdiv ( atlas_q3 ) ) ;
2016-11-10 03:55:06 +01:00
2017-10-31 18:23:25 +01:00
bool shrink = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_HALF_RESOLUTION ) ) ;
2020-04-01 20:28:09 +02:00
if ( shrink ! = ( subviewport_container - > get_stretch_shrink ( ) > 1 ) ) {
subviewport_container - > set_stretch_shrink ( shrink ? 2 : 1 ) ;
2017-10-31 18:23:25 +01:00
}
2020-04-20 23:34:47 +02:00
// Update MSAA, screen-space AA and debanding if changed
2017-01-02 02:16:52 +01:00
2020-04-20 23:34:47 +02:00
const int msaa_mode = ProjectSettings : : get_singleton ( ) - > get ( " rendering/quality/screen_filters/msaa " ) ;
2017-01-02 02:16:52 +01:00
viewport - > set_msaa ( Viewport : : MSAA ( msaa_mode ) ) ;
2020-04-20 23:34:47 +02:00
const int ssaa_mode = GLOBAL_GET ( " rendering/quality/screen_filters/screen_space_aa " ) ;
2020-04-12 06:49:10 +02:00
viewport - > set_screen_space_aa ( Viewport : : ScreenSpaceAA ( ssaa_mode ) ) ;
2020-04-20 23:34:47 +02:00
const bool use_debanding = GLOBAL_GET ( " rendering/quality/screen_filters/use_debanding " ) ;
viewport - > set_use_debanding ( use_debanding ) ;
2017-01-02 02:16:52 +01:00
2017-06-11 23:13:04 +02:00
bool show_info = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_INFORMATION ) ) ;
2020-04-10 19:18:42 +02:00
if ( show_info ! = info_label - > is_visible ( ) ) {
info_label - > set_visible ( show_info ) ;
}
2017-06-11 23:13:04 +02:00
2020-03-26 22:49:16 +01:00
Camera3D * current_camera ;
2018-08-30 00:44:47 +02:00
if ( previewing ) {
current_camera = previewing ;
} else {
current_camera = camera ;
}
2017-06-11 23:13:04 +02:00
if ( show_info ) {
String text ;
2018-08-30 00:44:47 +02:00
text + = " X: " + rtos ( current_camera - > get_translation ( ) . x ) . pad_decimals ( 1 ) + " \n " ;
text + = " Y: " + rtos ( current_camera - > get_translation ( ) . y ) . pad_decimals ( 1 ) + " \n " ;
text + = " Z: " + rtos ( current_camera - > get_translation ( ) . z ) . pad_decimals ( 1 ) + " \n " ;
text + = TTR ( " Pitch " ) + " : " + itos ( Math : : round ( current_camera - > get_rotation_degrees ( ) . x ) ) + " \n " ;
text + = TTR ( " Yaw " ) + " : " + itos ( Math : : round ( current_camera - > get_rotation_degrees ( ) . y ) ) + " \n \n " ;
2017-06-11 23:13:04 +02:00
text + = TTR ( " Objects Drawn " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_OBJECTS_IN_FRAME ) ) + " \n " ;
text + = TTR ( " Material Changes " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_MATERIAL_CHANGES_IN_FRAME ) ) + " \n " ;
text + = TTR ( " Shader Changes " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_SHADER_CHANGES_IN_FRAME ) ) + " \n " ;
text + = TTR ( " Surface Changes " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_SURFACE_CHANGES_IN_FRAME ) ) + " \n " ;
text + = TTR ( " Draw Calls " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_DRAW_CALLS_IN_FRAME ) ) + " \n " ;
text + = TTR ( " Vertices " ) + " : " + itos ( viewport - > get_render_info ( Viewport : : RENDER_INFO_VERTICES_IN_FRAME ) ) ;
2020-04-10 19:18:42 +02:00
2017-12-17 13:06:21 +01:00
info_label - > set_text ( text ) ;
2017-06-11 23:13:04 +02:00
}
2017-11-19 21:00:16 +01:00
// FPS Counter.
2020-04-10 19:18:42 +02:00
bool show_fps = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ) ;
if ( show_fps ! = fps_label - > is_visible ( ) ) {
2020-12-26 20:21:07 +01:00
cpu_time_label - > set_visible ( show_fps ) ;
gpu_time_label - > set_visible ( show_fps ) ;
2020-04-10 19:18:42 +02:00
fps_label - > set_visible ( show_fps ) ;
RS : : get_singleton ( ) - > viewport_set_measure_render_time ( viewport - > get_viewport_rid ( ) , show_fps ) ;
for ( int i = 0 ; i < FRAME_TIME_HISTORY ; i + + ) {
cpu_time_history [ i ] = 0 ;
gpu_time_history [ i ] = 0 ;
}
cpu_time_history_index = 0 ;
2020-12-08 19:58:49 +01:00
gpu_time_history_index = 0 ;
2020-04-10 19:18:42 +02:00
}
2017-11-19 21:00:16 +01:00
if ( show_fps ) {
2020-04-10 19:18:42 +02:00
cpu_time_history [ cpu_time_history_index ] = RS : : get_singleton ( ) - > viewport_get_measured_render_time_cpu ( viewport - > get_viewport_rid ( ) ) ;
cpu_time_history_index = ( cpu_time_history_index + 1 ) % FRAME_TIME_HISTORY ;
float cpu_time = 0.0 ;
for ( int i = 0 ; i < FRAME_TIME_HISTORY ; i + + ) {
cpu_time + = cpu_time_history [ i ] ;
}
cpu_time / = FRAME_TIME_HISTORY ;
gpu_time_history [ gpu_time_history_index ] = RS : : get_singleton ( ) - > viewport_get_measured_render_time_gpu ( viewport - > get_viewport_rid ( ) ) ;
gpu_time_history_index = ( gpu_time_history_index + 1 ) % FRAME_TIME_HISTORY ;
float gpu_time = 0.0 ;
for ( int i = 0 ; i < FRAME_TIME_HISTORY ; i + + ) {
gpu_time + = gpu_time_history [ i ] ;
}
gpu_time / = FRAME_TIME_HISTORY ;
2020-12-26 20:21:07 +01:00
// Color labels depending on performance level ("good" = green, "OK" = yellow, "bad" = red).
// Middle point is at 15 ms.
cpu_time_label - > set_text ( vformat ( TTR ( " CPU Time: %s ms " ) , String : : num ( cpu_time , 1 ) ) ) ;
cpu_time_label - > add_theme_color_override (
" font_color " ,
frame_time_gradient - > get_color_at_offset (
Math : : range_lerp ( cpu_time , 0 , 30 , 0 , 1 ) ) ) ;
gpu_time_label - > set_text ( vformat ( TTR ( " GPU Time: %s ms " ) , String : : num ( gpu_time , 1 ) ) ) ;
// Middle point is at 15 ms.
gpu_time_label - > add_theme_color_override (
" font_color " ,
frame_time_gradient - > get_color_at_offset (
Math : : range_lerp ( gpu_time , 0 , 30 , 0 , 1 ) ) ) ;
const float fps = 1000.0 / gpu_time ;
fps_label - > set_text ( vformat ( TTR ( " FPS: %d " ) , fps ) ) ;
// Middle point is at 60 FPS.
fps_label - > add_theme_color_override (
" font_color " ,
frame_time_gradient - > get_color_at_offset (
Math : : range_lerp ( fps , 110 , 10 , 0 , 1 ) ) ) ;
2017-11-19 21:00:16 +01:00
}
2018-07-27 00:36:05 +02:00
bool show_cinema = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_CINEMATIC_PREVIEW ) ) ;
cinema_label - > set_visible ( show_cinema ) ;
if ( show_cinema ) {
float cinema_half_width = cinema_label - > get_size ( ) . width / 2.0f ;
2020-12-22 17:24:29 +01:00
cinema_label - > set_anchor_and_offset ( SIDE_LEFT , 0.5f , - cinema_half_width ) ;
2018-07-27 00:36:05 +02:00
}
2018-10-10 09:25:59 +02:00
if ( lock_rotation ) {
float locked_half_width = locked_label - > get_size ( ) . width / 2.0f ;
2020-12-22 17:24:29 +01:00
locked_label - > set_anchor_and_offset ( SIDE_LEFT , 0.5f , - locked_half_width ) ;
2018-10-10 09:25:59 +02:00
}
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2020-03-26 22:49:16 +01:00
surface - > connect ( " draw " , callable_mp ( this , & Node3DEditorViewport : : _draw ) ) ;
surface - > connect ( " gui_input " , callable_mp ( this , & Node3DEditorViewport : : _sinput ) ) ;
surface - > connect ( " mouse_entered " , callable_mp ( this , & Node3DEditorViewport : : _surface_mouse_enter ) ) ;
surface - > connect ( " mouse_exited " , callable_mp ( this , & Node3DEditorViewport : : _surface_mouse_exit ) ) ;
surface - > connect ( " focus_entered " , callable_mp ( this , & Node3DEditorViewport : : _surface_focus_enter ) ) ;
surface - > connect ( " focus_exited " , callable_mp ( this , & Node3DEditorViewport : : _surface_focus_exit ) ) ;
2018-10-10 09:25:59 +02:00
2014-05-05 03:50:23 +02:00
_init_gizmo_instance ( index ) ;
2015-04-21 00:38:02 +02:00
}
2018-10-10 09:25:59 +02:00
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_EXIT_TREE ) {
2015-04-21 00:38:02 +02:00
_finish_gizmo_instances ( ) ;
2014-02-10 02:10:30 +01:00
}
2018-10-10 09:25:59 +02:00
if ( p_what = = NOTIFICATION_THEME_CHANGED ) {
2020-07-11 17:32:27 +02:00
view_menu - > set_icon ( get_theme_icon ( " GuiTabMenuHl " , " EditorIcons " ) ) ;
2020-03-26 22:49:16 +01:00
preview_camera - > set_icon ( get_theme_icon ( " Camera3D " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
2020-03-12 13:37:40 +01:00
view_menu - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
view_menu - > add_theme_style_override ( " hover " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
view_menu - > add_theme_style_override ( " pressed " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
view_menu - > add_theme_style_override ( " focus " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
view_menu - > add_theme_style_override ( " disabled " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
2018-10-10 09:25:59 +02:00
2020-03-12 13:37:40 +01:00
preview_camera - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
preview_camera - > add_theme_style_override ( " hover " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
preview_camera - > add_theme_style_override ( " pressed " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
preview_camera - > add_theme_style_override ( " focus " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
preview_camera - > add_theme_style_override ( " disabled " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
2018-10-10 09:25:59 +02:00
2020-12-26 20:21:07 +01:00
frame_time_gradient - > set_color ( 0 , get_theme_color ( " success_color " , " Editor " ) ) ;
frame_time_gradient - > set_color ( 1 , get_theme_color ( " warning_color " , " Editor " ) ) ;
frame_time_gradient - > set_color ( 2 , get_theme_color ( " error_color " , " Editor " ) ) ;
2020-03-12 13:37:40 +01:00
info_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
2020-12-26 20:21:07 +01:00
cpu_time_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
gpu_time_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
2020-03-12 13:37:40 +01:00
fps_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
cinema_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
locked_label - > add_theme_style_override ( " normal " , editor - > get_gui_base ( ) - > get_theme_stylebox ( " Information3dViewport " , " EditorStyles " ) ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-09-03 13:22:16 +02:00
static void draw_indicator_bar ( Control & surface , real_t fill , const Ref < Texture2D > icon , const Ref < Font > font , int font_size , const String & text ) {
2017-10-15 21:20:51 +02:00
// Adjust bar size from control height
2020-06-13 21:56:03 +02:00
const Vector2 surface_size = surface . get_size ( ) ;
const real_t h = surface_size . y / 2.0 ;
const real_t y = ( surface_size . y - h ) / 2.0 ;
2017-10-15 21:20:51 +02:00
2020-06-13 21:56:03 +02:00
const Rect2 r ( 10 * EDSCALE , y , 6 * EDSCALE , h ) ;
const real_t sy = r . size . y * fill ;
2017-10-15 21:20:51 +02:00
// Note: because this bar appears over the viewport, it has to stay readable for any background color
// Draw both neutral dark and bright colors to account this
surface . draw_rect ( r , Color ( 1 , 1 , 1 , 0.2 ) ) ;
surface . draw_rect ( Rect2 ( r . position . x , r . position . y + r . size . y - sy , r . size . x , sy ) , Color ( 1 , 1 , 1 , 0.6 ) ) ;
2019-07-09 15:22:01 +02:00
surface . draw_rect ( r . grow ( 1 ) , Color ( 0 , 0 , 0 , 0.7 ) , false , Math : : round ( EDSCALE ) ) ;
2017-10-15 21:20:51 +02:00
2020-06-13 21:56:03 +02:00
const Vector2 icon_size = icon - > get_size ( ) ;
const Vector2 icon_pos = Vector2 ( r . position . x - ( icon_size . x - r . size . x ) / 2 , r . position . y + r . size . y + 2 * EDSCALE ) ;
2017-10-15 21:20:51 +02:00
surface . draw_texture ( icon , icon_pos ) ;
2020-06-13 21:56:03 +02:00
// Draw text below the bar (for speed/zoom information).
2020-09-03 13:22:16 +02:00
surface . draw_string ( font , Vector2 ( icon_pos . x , icon_pos . y + icon_size . y + 16 * EDSCALE ) , text , HALIGN_LEFT , - 1.f , font_size ) ;
2017-05-07 22:59:05 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _draw ( ) {
2017-10-29 20:32:09 +01:00
EditorPluginList * over_plugin_list = EditorNode : : get_singleton ( ) - > get_editor_plugins_over ( ) ;
2020-12-15 13:04:21 +01:00
if ( ! over_plugin_list - > is_empty ( ) ) {
2018-09-18 20:00:07 +02:00
over_plugin_list - > forward_spatial_draw_over_viewport ( surface ) ;
2017-10-29 20:32:09 +01:00
}
EditorPluginList * force_over_plugin_list = editor - > get_editor_plugins_force_over ( ) ;
2020-12-15 13:04:21 +01:00
if ( ! force_over_plugin_list - > is_empty ( ) ) {
2018-09-18 20:00:07 +02:00
force_over_plugin_list - > forward_spatial_force_draw_over_viewport ( surface ) ;
2017-10-29 20:32:09 +01:00
}
2014-02-10 02:10:30 +01:00
if ( surface - > has_focus ( ) ) {
Size2 size = surface - > get_size ( ) ;
2017-03-05 16:44:50 +01:00
Rect2 r = Rect2 ( Point2 ( ) , size ) ;
2020-03-12 13:37:40 +01:00
get_theme_stylebox ( " Focus " , " EditorStyles " ) - > draw ( surface - > get_canvas_item ( ) , r ) ;
2014-02-10 02:10:30 +01:00
}
if ( cursor . region_select ) {
2019-08-15 22:17:08 +02:00
const Rect2 selection_rect = Rect2 ( cursor . region_begin , cursor . region_end - cursor . region_begin ) ;
surface - > draw_rect (
selection_rect ,
2020-03-12 13:37:40 +01:00
get_theme_color ( " box_selection_fill_color " , " Editor " ) ) ;
2014-02-10 02:10:30 +01:00
2019-08-15 22:17:08 +02:00
surface - > draw_rect (
selection_rect ,
2020-03-12 13:37:40 +01:00
get_theme_color ( " box_selection_stroke_color " , " Editor " ) ,
2019-08-15 22:17:08 +02:00
false ,
Math : : round ( EDSCALE ) ) ;
2014-02-10 02:10:30 +01:00
}
2019-08-15 22:17:08 +02:00
RID ci = surface - > get_canvas_item ( ) ;
2017-03-05 16:44:50 +01:00
if ( message_time > 0 ) {
2020-03-12 13:37:40 +01:00
Ref < Font > font = get_theme_font ( " font " , " Label " ) ;
2020-09-03 13:22:16 +02:00
int font_size = get_theme_font_size ( " font_size " , " Label " ) ;
2017-03-05 16:44:50 +01:00
Point2 msgpos = Point2 ( 5 , get_size ( ) . y - 20 ) ;
2020-09-03 13:22:16 +02:00
font - > draw_string ( ci , msgpos + Point2 ( 1 , 1 ) , message , HALIGN_LEFT , - 1 , font_size , Color ( 0 , 0 , 0 , 0.8 ) ) ;
font - > draw_string ( ci , msgpos + Point2 ( - 1 , - 1 ) , message , HALIGN_LEFT , - 1 , font_size , Color ( 0 , 0 , 0 , 0.8 ) ) ;
font - > draw_string ( ci , msgpos , message , HALIGN_LEFT , - 1 , font_size , Color ( 1 , 1 , 1 , 1 ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
if ( _edit . mode = = TRANSFORM_ROTATE ) {
2014-02-10 02:10:30 +01:00
Point2 center = _point_to_screen ( _edit . center ) ;
2020-12-16 14:32:02 +01:00
Color handle_color ;
switch ( _edit . plane ) {
case TRANSFORM_X_AXIS :
handle_color = get_theme_color ( " axis_x_color " , " Editor " ) ;
break ;
case TRANSFORM_Y_AXIS :
handle_color = get_theme_color ( " axis_y_color " , " Editor " ) ;
break ;
case TRANSFORM_Z_AXIS :
handle_color = get_theme_color ( " axis_z_color " , " Editor " ) ;
break ;
default :
handle_color = get_theme_color ( " accent_color " , " Editor " ) ;
break ;
}
handle_color . a = 1.0 ;
2020-12-18 16:28:12 +01:00
const float brightness = 1.3 ;
handle_color * = Color ( brightness , brightness , brightness ) ;
2020-12-16 14:32:02 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_line (
2019-03-29 14:19:44 +01:00
ci ,
_edit . mouse_pos ,
center ,
2020-12-16 14:32:02 +01:00
handle_color ,
2019-06-25 03:24:07 +02:00
Math : : round ( 2 * EDSCALE ) ) ;
2014-02-10 02:10:30 +01:00
}
2014-09-16 01:06:37 +02:00
if ( previewing ) {
2017-07-19 22:00:46 +02:00
Size2 ss = Size2 ( ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/width " ) , ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/height " ) ) ;
2017-01-14 00:00:43 +01:00
float aspect = ss . aspect ( ) ;
2014-09-16 01:06:37 +02:00
Size2 s = get_size ( ) ;
Rect2 draw_rect ;
2017-03-05 16:44:50 +01:00
switch ( previewing - > get_keep_aspect_mode ( ) ) {
2020-03-26 22:49:16 +01:00
case Camera3D : : KEEP_WIDTH : {
2017-03-05 16:44:50 +01:00
draw_rect . size = Size2 ( s . width , s . width / aspect ) ;
2017-06-04 00:25:13 +02:00
draw_rect . position . x = 0 ;
draw_rect . position . y = ( s . height - draw_rect . size . y ) * 0.5 ;
2014-09-16 01:06:37 +02:00
} break ;
2020-03-26 22:49:16 +01:00
case Camera3D : : KEEP_HEIGHT : {
2017-03-05 16:44:50 +01:00
draw_rect . size = Size2 ( s . height * aspect , s . height ) ;
2017-06-04 00:25:13 +02:00
draw_rect . position . y = 0 ;
draw_rect . position . x = ( s . width - draw_rect . size . x ) * 0.5 ;
2014-09-16 01:06:37 +02:00
} break ;
}
2020-12-19 13:43:35 +01:00
draw_rect = Rect2 ( Vector2 ( ) , s ) . intersection ( draw_rect ) ;
2014-09-16 01:06:37 +02:00
2019-07-09 15:22:01 +02:00
surface - > draw_rect ( draw_rect , Color ( 0.6 , 0.6 , 0.1 , 0.5 ) , false , Math : : round ( 2 * EDSCALE ) ) ;
2017-05-07 22:59:05 +02:00
} else {
if ( zoom_indicator_delay > 0.0 ) {
2017-10-15 21:20:51 +02:00
if ( is_freelook_active ( ) ) {
// Show speed
2017-05-07 22:59:05 +02:00
2020-12-16 13:40:42 +01:00
real_t min_speed = MAX ( camera - > get_near ( ) * 4 , ZOOM_FREELOOK_MIN ) ;
real_t max_speed = MIN ( camera - > get_far ( ) / 4 , ZOOM_FREELOOK_MAX ) ;
2017-10-15 21:20:51 +02:00
real_t scale_length = ( max_speed - min_speed ) ;
2017-05-07 22:59:05 +02:00
2019-01-16 16:42:53 +01:00
if ( ! Math : : is_zero_approx ( scale_length ) ) {
2017-10-15 21:20:51 +02:00
real_t logscale_t = 1.0 - Math : : log ( 1 + freelook_speed - min_speed ) / Math : : log ( 1 + scale_length ) ;
2017-05-07 22:59:05 +02:00
2020-06-13 21:56:03 +02:00
// Display the freelook speed to help the user get a better sense of scale.
const int precision = freelook_speed < 1.0 ? 2 : 1 ;
draw_indicator_bar (
* surface ,
1.0 - logscale_t ,
get_theme_icon ( " ViewportSpeed " , " EditorIcons " ) ,
get_theme_font ( " font " , " Label " ) ,
2020-09-03 13:22:16 +02:00
get_theme_font_size ( " font_size " , " Label " ) ,
2020-06-13 21:56:03 +02:00
vformat ( " %s u/s " , String : : num ( freelook_speed ) . pad_decimals ( precision ) ) ) ;
2017-10-15 21:20:51 +02:00
}
2017-05-07 22:59:05 +02:00
2017-10-15 21:20:51 +02:00
} else {
// Show zoom
2020-12-16 13:40:42 +01:00
real_t min_distance = MAX ( camera - > get_near ( ) * 4 , ZOOM_FREELOOK_MIN ) ;
real_t max_distance = MIN ( camera - > get_far ( ) / 4 , ZOOM_FREELOOK_MAX ) ;
2017-10-15 21:20:51 +02:00
real_t scale_length = ( max_distance - min_distance ) ;
2019-01-16 16:42:53 +01:00
if ( ! Math : : is_zero_approx ( scale_length ) ) {
2017-10-15 21:20:51 +02:00
real_t logscale_t = 1.0 - Math : : log ( 1 + cursor . distance - min_distance ) / Math : : log ( 1 + scale_length ) ;
2020-06-13 21:56:03 +02:00
// Display the zoom center distance to help the user get a better sense of scale.
const int precision = cursor . distance < 1.0 ? 2 : 1 ;
draw_indicator_bar (
* surface ,
logscale_t ,
get_theme_icon ( " ViewportZoom " , " EditorIcons " ) ,
get_theme_font ( " font " , " Label " ) ,
2020-09-03 13:22:16 +02:00
get_theme_font_size ( " font_size " , " Label " ) ,
2020-06-13 21:56:03 +02:00
vformat ( " %s u " , String : : num ( cursor . distance ) . pad_decimals ( precision ) ) ) ;
2017-10-15 21:20:51 +02:00
}
2017-05-07 22:59:05 +02:00
}
}
2014-09-16 01:06:37 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _menu_option ( int p_option ) {
2017-03-05 16:44:50 +01:00
switch ( p_option ) {
2014-02-10 02:10:30 +01:00
case VIEW_TOP : {
2017-03-05 16:44:50 +01:00
cursor . y_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . x_rot = Math_PI / 2.0 ;
set_message ( TTR ( " Top View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Top " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2017-12-19 15:29:55 +01:00
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_BOTTOM : {
2017-03-05 16:44:50 +01:00
cursor . y_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . x_rot = - Math_PI / 2.0 ;
set_message ( TTR ( " Bottom View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Bottom " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_LEFT : {
2017-03-05 16:44:50 +01:00
cursor . x_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . y_rot = Math_PI / 2.0 ;
set_message ( TTR ( " Left View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Left " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_RIGHT : {
2017-03-05 16:44:50 +01:00
cursor . x_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . y_rot = - Math_PI / 2.0 ;
set_message ( TTR ( " Right View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Right " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_FRONT : {
2017-03-05 16:44:50 +01:00
cursor . x_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . y_rot = 0 ;
set_message ( TTR ( " Front View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Front " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_REAR : {
2017-03-05 16:44:50 +01:00
cursor . x_rot = 0 ;
2017-12-19 15:29:55 +01:00
cursor . y_rot = Math_PI ;
set_message ( TTR ( " Rear View. " ) , 2 ) ;
2017-03-05 16:44:50 +01:00
name = TTR ( " Rear " ) ;
2019-10-23 11:46:26 +02:00
_set_auto_orthogonal ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
2016-10-04 20:39:38 +02:00
} break ;
case VIEW_CENTER_TO_ORIGIN : {
2017-03-05 16:44:50 +01:00
cursor . pos = Vector3 ( 0 , 0 , 0 ) ;
2016-10-04 20:39:38 +02:00
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_CENTER_TO_SELECTION : {
2016-07-28 21:37:52 +02:00
focus_selection ( ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-10-27 23:43:19 +02:00
case VIEW_ALIGN_TRANSFORM_WITH_VIEW : {
2020-05-14 16:41:43 +02:00
if ( ! get_selected_count ( ) ) {
2014-03-31 17:06:36 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2014-03-31 17:06:36 +02:00
Transform camera_transform = camera - > get_global_transform ( ) ;
2017-03-05 16:44:50 +01:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-03-31 17:06:36 +02:00
2018-10-27 23:43:19 +02:00
undo_redo - > create_action ( TTR ( " Align Transform with View " ) ) ;
2017-03-05 16:44:50 +01:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-03-31 17:06:36 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-03-31 17:06:36 +02:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-03-31 17:06:36 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-03-31 17:06:36 +02:00
2018-10-22 16:52:39 +02:00
Transform xform ;
if ( orthogonal ) {
xform = sp - > get_global_transform ( ) ;
xform . basis . set_euler ( camera_transform . basis . get_euler ( ) ) ;
} else {
xform = camera_transform ;
xform . scale_basis ( sp - > get_scale ( ) ) ;
}
2015-10-30 00:44:12 +01:00
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( sp , " set_global_transform " , xform ) ;
2017-10-03 18:49:32 +02:00
undo_redo - > add_undo_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
2014-03-31 17:06:36 +02:00
}
undo_redo - > commit_action ( ) ;
2018-10-27 23:43:19 +02:00
} break ;
case VIEW_ALIGN_ROTATION_WITH_VIEW : {
2020-05-14 16:41:43 +02:00
if ( ! get_selected_count ( ) ) {
2018-10-27 23:43:19 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2018-10-27 23:43:19 +02:00
Transform camera_transform = camera - > get_global_transform ( ) ;
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
undo_redo - > create_action ( TTR ( " Align Rotation with View " ) ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2018-10-27 23:43:19 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2018-10-27 23:43:19 +02:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2018-10-27 23:43:19 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2018-10-27 23:43:19 +02:00
undo_redo - > add_do_method ( sp , " set_rotation " , camera_transform . basis . get_rotation ( ) ) ;
undo_redo - > add_undo_method ( sp , " set_rotation " , sp - > get_rotation ( ) ) ;
}
undo_redo - > commit_action ( ) ;
2014-03-31 17:06:36 +02:00
} break ;
2014-02-10 02:10:30 +01:00
case VIEW_ENVIRONMENT : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_ENVIRONMENT ) ;
2017-03-05 16:44:50 +01:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2014-02-10 02:10:30 +01:00
if ( current ) {
camera - > set_environment ( RES ( ) ) ;
} else {
2020-03-26 22:49:16 +01:00
camera - > set_environment ( Node3DEditor : : get_singleton ( ) - > get_viewport_environment ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_PERSPECTIVE : {
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_PERSPECTIVE ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ORTHOGONAL ) , false ) ;
orthogonal = false ;
2019-10-23 11:46:26 +02:00
auto_orthogonal = false ;
2014-05-05 03:50:23 +02:00
call_deferred ( " update_transform_gizmo_view " ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-05-05 03:50:23 +02:00
2014-02-10 02:10:30 +01:00
} break ;
case VIEW_ORTHOGONAL : {
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_PERSPECTIVE ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ORTHOGONAL ) , true ) ;
orthogonal = true ;
2019-10-23 11:46:26 +02:00
auto_orthogonal = false ;
2014-05-05 03:50:23 +02:00
call_deferred ( " update_transform_gizmo_view " ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-02-10 02:10:30 +01:00
2018-06-25 03:24:31 +02:00
} break ;
2019-10-23 11:46:26 +02:00
case VIEW_AUTO_ORTHOGONAL : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUTO_ORTHOGONAL ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
if ( auto_orthogonal ) {
auto_orthogonal = false ;
_update_name ( ) ;
}
} break ;
2018-06-25 03:24:31 +02:00
case VIEW_LOCK_ROTATION : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_LOCK_ROTATION ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
lock_rotation = ! current ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , ! current ) ;
if ( lock_rotation ) {
2018-10-10 09:25:59 +02:00
locked_label - > show ( ) ;
2018-06-25 03:24:31 +02:00
} else {
2018-10-10 09:25:59 +02:00
locked_label - > hide ( ) ;
2018-06-25 03:24:31 +02:00
}
2014-02-10 02:10:30 +01:00
} break ;
2014-10-03 05:10:51 +02:00
case VIEW_AUDIO_LISTENER : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) ;
2017-03-05 16:44:50 +01:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2014-10-03 05:10:51 +02:00
viewport - > set_as_audio_listener ( current ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-03 05:10:51 +02:00
2017-07-15 06:23:10 +02:00
} break ;
case VIEW_AUDIO_DOPPLER : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_DOPPLER ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2020-03-26 22:49:16 +01:00
camera - > set_doppler_tracking ( current ? Camera3D : : DOPPLER_TRACKING_IDLE_STEP : Camera3D : : DOPPLER_TRACKING_DISABLED ) ;
2017-07-15 06:23:10 +02:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-03 05:10:51 +02:00
} break ;
2018-07-27 00:36:05 +02:00
case VIEW_CINEMATIC_PREVIEW : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_CINEMATIC_PREVIEW ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
previewing_cinema = true ;
_toggle_cinema_preview ( current ) ;
if ( current ) {
preview_camera - > hide ( ) ;
} else {
2020-05-14 16:41:43 +02:00
if ( previewing ! = nullptr ) {
2018-07-27 00:36:05 +02:00
preview_camera - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-07-27 00:36:05 +02:00
}
} break ;
2014-10-12 07:13:22 +02:00
case VIEW_GIZMOS : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ;
2017-03-05 16:44:50 +01:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2020-11-26 20:00:03 +01:00
uint32_t layers = ( ( 1 < < 20 ) - 1 ) | ( 1 < < ( GIZMO_BASE_LAYER + index ) ) | ( 1 < < GIZMO_GRID_LAYER ) | ( 1 < < MISC_TOOL_LAYER ) ;
2020-05-14 16:41:43 +02:00
if ( current ) {
2020-11-26 20:00:03 +01:00
layers | = ( 1 < < GIZMO_EDIT_LAYER ) ;
2020-05-14 16:41:43 +02:00
}
2020-11-26 20:00:03 +01:00
camera - > set_cull_mask ( layers ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-12 07:13:22 +02:00
2017-06-11 23:13:04 +02:00
} break ;
2017-10-31 18:23:25 +01:00
case VIEW_HALF_RESOLUTION : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_HALF_RESOLUTION ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
} break ;
2017-06-11 23:13:04 +02:00
case VIEW_INFORMATION : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_INFORMATION ) ;
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , ! current ) ;
2017-11-19 21:00:16 +01:00
} break ;
2020-04-10 19:18:42 +02:00
case VIEW_FRAME_TIME : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ;
2017-11-19 21:00:16 +01:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , ! current ) ;
2014-10-12 07:13:22 +02:00
} break ;
2019-10-03 22:39:08 +02:00
case VIEW_DISPLAY_NORMAL :
case VIEW_DISPLAY_WIREFRAME :
case VIEW_DISPLAY_OVERDRAW :
case VIEW_DISPLAY_SHADELESS :
case VIEW_DISPLAY_LIGHTING :
2020-01-27 00:09:40 +01:00
case VIEW_DISPLAY_NORMAL_BUFFER :
2019-10-03 22:39:08 +02:00
case VIEW_DISPLAY_DEBUG_SHADOW_ATLAS :
case VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS :
case VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO :
2019-10-05 15:27:43 +02:00
case VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING :
2020-01-12 02:26:52 +01:00
case VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION :
2020-01-25 11:18:55 +01:00
case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE :
2020-01-27 00:09:40 +01:00
case VIEW_DISPLAY_DEBUG_SSAO :
2020-04-08 03:51:52 +02:00
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS :
2020-04-14 05:05:21 +02:00
case VIEW_DISPLAY_DEBUG_DECAL_ATLAS :
2020-06-25 15:33:28 +02:00
case VIEW_DISPLAY_DEBUG_SDFGI :
case VIEW_DISPLAY_DEBUG_SDFGI_PROBES :
2020-12-17 19:56:59 +01:00
case VIEW_DISPLAY_DEBUG_GI_BUFFER :
2021-01-17 17:25:38 +01:00
case VIEW_DISPLAY_DEBUG_DISABLE_LOD :
case VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS :
case VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS :
case VIEW_DISPLAY_DEBUG_CLUSTER_DECALS :
case VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES : {
2019-10-03 22:39:08 +02:00
static const int display_options [ ] = {
VIEW_DISPLAY_NORMAL ,
VIEW_DISPLAY_WIREFRAME ,
VIEW_DISPLAY_OVERDRAW ,
VIEW_DISPLAY_SHADELESS ,
VIEW_DISPLAY_LIGHTING ,
2020-01-27 00:09:40 +01:00
VIEW_DISPLAY_NORMAL_BUFFER ,
2019-10-04 03:59:14 +02:00
VIEW_DISPLAY_WIREFRAME ,
2019-10-03 22:39:08 +02:00
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS ,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS ,
VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO ,
VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING ,
2019-10-05 15:27:43 +02:00
VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION ,
2020-01-12 02:26:52 +01:00
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE ,
2020-01-25 11:18:55 +01:00
VIEW_DISPLAY_DEBUG_SSAO ,
2020-06-25 15:33:28 +02:00
VIEW_DISPLAY_DEBUG_GI_BUFFER ,
2020-12-17 19:56:59 +01:00
VIEW_DISPLAY_DEBUG_DISABLE_LOD ,
2020-04-08 03:51:52 +02:00
VIEW_DISPLAY_DEBUG_PSSM_SPLITS ,
2020-04-14 05:05:21 +02:00
VIEW_DISPLAY_DEBUG_DECAL_ATLAS ,
2020-06-25 15:33:28 +02:00
VIEW_DISPLAY_DEBUG_SDFGI ,
VIEW_DISPLAY_DEBUG_SDFGI_PROBES ,
2021-01-17 17:25:38 +01:00
VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS ,
VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS ,
VIEW_DISPLAY_DEBUG_CLUSTER_DECALS ,
VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES ,
2019-10-03 22:39:08 +02:00
VIEW_MAX
} ;
static const Viewport : : DebugDraw debug_draw_modes [ ] = {
Viewport : : DEBUG_DRAW_DISABLED ,
Viewport : : DEBUG_DRAW_WIREFRAME ,
Viewport : : DEBUG_DRAW_OVERDRAW ,
Viewport : : DEBUG_DRAW_UNSHADED ,
Viewport : : DEBUG_DRAW_LIGHTING ,
2020-01-27 00:09:40 +01:00
Viewport : : DEBUG_DRAW_NORMAL_BUFFER ,
2019-10-03 22:39:08 +02:00
Viewport : : DEBUG_DRAW_WIREFRAME ,
Viewport : : DEBUG_DRAW_SHADOW_ATLAS ,
Viewport : : DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS ,
2019-10-04 03:59:14 +02:00
Viewport : : DEBUG_DRAW_GI_PROBE_ALBEDO ,
2019-10-05 15:27:43 +02:00
Viewport : : DEBUG_DRAW_GI_PROBE_LIGHTING ,
2020-01-12 02:26:52 +01:00
Viewport : : DEBUG_DRAW_GI_PROBE_EMISSION ,
2020-01-25 11:18:55 +01:00
Viewport : : DEBUG_DRAW_SCENE_LUMINANCE ,
2020-01-27 00:09:40 +01:00
Viewport : : DEBUG_DRAW_SSAO ,
2020-06-25 15:33:28 +02:00
Viewport : : DEBUG_DRAW_GI_BUFFER ,
2020-12-17 19:56:59 +01:00
Viewport : : DEBUG_DRAW_DISABLE_LOD ,
2020-04-08 03:51:52 +02:00
Viewport : : DEBUG_DRAW_PSSM_SPLITS ,
2020-04-14 05:05:21 +02:00
Viewport : : DEBUG_DRAW_DECAL_ATLAS ,
2020-06-25 15:33:28 +02:00
Viewport : : DEBUG_DRAW_SDFGI ,
Viewport : : DEBUG_DRAW_SDFGI_PROBES ,
2021-01-17 17:25:38 +01:00
Viewport : : DEBUG_DRAW_CLUSTER_OMNI_LIGHTS ,
Viewport : : DEBUG_DRAW_CLUSTER_SPOT_LIGHTS ,
Viewport : : DEBUG_DRAW_CLUSTER_DECALS ,
Viewport : : DEBUG_DRAW_CLUSTER_REFLECTION_PROBES ,
2019-10-03 22:39:08 +02:00
} ;
int idx = 0 ;
while ( display_options [ idx ] ! = VIEW_MAX ) {
int id = display_options [ idx ] ;
int item_idx = view_menu - > get_popup ( ) - > get_item_index ( id ) ;
if ( item_idx ! = - 1 ) {
view_menu - > get_popup ( ) - > set_item_checked ( item_idx , id = = p_option ) ;
}
item_idx = display_submenu - > get_item_index ( id ) ;
if ( item_idx ! = - 1 ) {
display_submenu - > set_item_checked ( item_idx , id = = p_option ) ;
}
2017-06-11 20:52:03 +02:00
2019-10-03 22:39:08 +02:00
if ( id = = p_option ) {
viewport - > set_debug_draw ( debug_draw_modes [ idx ] ) ;
}
idx + + ;
}
2017-06-11 20:52:03 +02:00
} break ;
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _set_auto_orthogonal ( ) {
2019-10-23 11:46:26 +02:00
if ( ! orthogonal & & view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUTO_ORTHOGONAL ) ) ) {
_menu_option ( VIEW_ORTHOGONAL ) ;
auto_orthogonal = true ;
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _preview_exited_scene ( ) {
preview_camera - > disconnect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 02:10:30 +01:00
preview_camera - > set_pressed ( false ) ;
_toggle_camera_preview ( false ) ;
2020-03-26 22:49:16 +01:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 02:10:30 +01:00
view_menu - > show ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _init_gizmo_instance ( int p_idx ) {
2017-12-19 06:25:00 +01:00
uint32_t layer = 1 < < ( GIZMO_BASE_LAYER + p_idx ) ;
2014-05-05 03:50:23 +02:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 19:21:27 +01:00
move_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( move_gizmo_instance [ i ] , spatial_editor - > get_move_gizmo ( i ) - > get_rid ( ) ) ;
2020-04-18 11:00:51 +02:00
RS : : get_singleton ( ) - > instance_set_scenario ( move_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_visible ( move_gizmo_instance [ i ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( move_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( move_gizmo_instance [ i ] , layer ) ;
move_plane_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( move_plane_gizmo_instance [ i ] , spatial_editor - > get_move_plane_gizmo ( i ) - > get_rid ( ) ) ;
2020-04-18 11:00:51 +02:00
RS : : get_singleton ( ) - > instance_set_scenario ( move_plane_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_visible ( move_plane_gizmo_instance [ i ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( move_plane_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( move_plane_gizmo_instance [ i ] , layer ) ;
rotate_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( rotate_gizmo_instance [ i ] , spatial_editor - > get_rotate_gizmo ( i ) - > get_rid ( ) ) ;
2020-04-18 11:00:51 +02:00
RS : : get_singleton ( ) - > instance_set_scenario ( rotate_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ i ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( rotate_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( rotate_gizmo_instance [ i ] , layer ) ;
scale_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( scale_gizmo_instance [ i ] , spatial_editor - > get_scale_gizmo ( i ) - > get_rid ( ) ) ;
2020-04-18 11:00:51 +02:00
RS : : get_singleton ( ) - > instance_set_scenario ( scale_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_visible ( scale_gizmo_instance [ i ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( scale_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( scale_gizmo_instance [ i ] , layer ) ;
scale_plane_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( scale_plane_gizmo_instance [ i ] , spatial_editor - > get_scale_plane_gizmo ( i ) - > get_rid ( ) ) ;
2020-04-18 11:00:51 +02:00
RS : : get_singleton ( ) - > instance_set_scenario ( scale_plane_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_visible ( scale_plane_gizmo_instance [ i ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( scale_plane_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( scale_plane_gizmo_instance [ i ] , layer ) ;
2014-05-05 03:50:23 +02:00
}
2020-09-13 18:22:51 +02:00
// Rotation white outline
rotate_gizmo_instance [ 3 ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( rotate_gizmo_instance [ 3 ] , spatial_editor - > get_rotate_gizmo ( 3 ) - > get_rid ( ) ) ;
RS : : get_singleton ( ) - > instance_set_scenario ( rotate_gizmo_instance [ 3 ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
RS : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ 3 ] , false ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( rotate_gizmo_instance [ 3 ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( rotate_gizmo_instance [ 3 ] , layer ) ;
2014-05-05 03:50:23 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _finish_gizmo_instances ( ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > free ( move_gizmo_instance [ i ] ) ;
RS : : get_singleton ( ) - > free ( move_plane_gizmo_instance [ i ] ) ;
RS : : get_singleton ( ) - > free ( rotate_gizmo_instance [ i ] ) ;
RS : : get_singleton ( ) - > free ( scale_gizmo_instance [ i ] ) ;
RS : : get_singleton ( ) - > free ( scale_plane_gizmo_instance [ i ] ) ;
2015-04-21 00:38:02 +02:00
}
2020-09-13 18:22:51 +02:00
// Rotation white outline
RS : : get_singleton ( ) - > free ( rotate_gizmo_instance [ 3 ] ) ;
2015-04-21 00:38:02 +02:00
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _toggle_camera_preview ( bool p_activate ) {
2014-02-10 02:10:30 +01:00
ERR_FAIL_COND ( p_activate & & ! preview ) ;
ERR_FAIL_COND ( ! p_activate & & ! previewing ) ;
2020-05-08 03:14:24 +02:00
rotation_control - > set_visible ( ! p_activate ) ;
2014-02-10 02:10:30 +01:00
if ( ! p_activate ) {
2020-03-26 22:49:16 +01:00
previewing - > disconnect ( " tree_exiting " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-04-02 01:20:12 +02:00
previewing = nullptr ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , camera - > get_camera ( ) ) ; //restore
2020-05-14 16:41:43 +02:00
if ( ! preview ) {
2014-02-10 02:10:30 +01:00
preview_camera - > hide ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-10-10 09:25:59 +02:00
view_menu - > set_disabled ( false ) ;
2014-09-16 01:06:37 +02:00
surface - > update ( ) ;
2014-02-10 02:10:30 +01:00
} else {
2017-03-05 16:44:50 +01:00
previewing = preview ;
2020-03-26 22:49:16 +01:00
previewing - > connect ( " tree_exiting " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , preview - > get_camera ( ) ) ; //replace
2018-10-10 09:25:59 +02:00
view_menu - > set_disabled ( true ) ;
2014-09-16 01:06:37 +02:00
surface - > update ( ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _toggle_cinema_preview ( bool p_activate ) {
2018-07-27 00:36:05 +02:00
previewing_cinema = p_activate ;
2021-01-18 03:19:05 +01:00
rotation_control - > set_visible ( ! p_activate ) ;
2018-07-27 00:36:05 +02:00
if ( ! previewing_cinema ) {
2020-05-14 16:41:43 +02:00
if ( previewing ! = nullptr ) {
2020-03-26 22:49:16 +01:00
previewing - > disconnect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-05-14 16:41:43 +02:00
}
2018-07-27 00:36:05 +02:00
2020-04-02 01:20:12 +02:00
previewing = nullptr ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , camera - > get_camera ( ) ) ; //restore
2018-07-27 00:36:05 +02:00
preview_camera - > set_pressed ( false ) ;
if ( ! preview ) {
preview_camera - > hide ( ) ;
} else {
preview_camera - > show ( ) ;
}
view_menu - > show ( ) ;
surface - > update ( ) ;
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _selection_result_pressed ( int p_result ) {
2020-05-14 16:41:43 +02:00
if ( selection_results . size ( ) < = p_result ) {
2015-11-04 22:39:07 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-11-04 22:39:07 +01:00
2017-08-07 12:17:31 +02:00
clicked = selection_results [ p_result ] . item - > get_instance_id ( ) ;
2015-11-04 22:39:07 +01:00
2020-02-12 18:24:06 +01:00
if ( clicked . is_valid ( ) ) {
2020-03-26 22:49:16 +01:00
_select_clicked ( clicked_wants_append , true , spatial_editor - > get_tool_mode ( ) ! = Node3DEditor : : TOOL_MODE_LIST_SELECT ) ;
2020-02-12 18:24:06 +01:00
clicked = ObjectID ( ) ;
2015-11-04 22:39:07 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _selection_menu_hide ( ) {
2015-11-04 22:39:07 +01:00
selection_results . clear ( ) ;
selection_menu - > clear ( ) ;
selection_menu - > set_size ( Vector2 ( 0 , 0 ) ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : set_can_preview ( Camera3D * p_preview ) {
2017-03-05 16:44:50 +01:00
preview = p_preview ;
2014-02-10 02:10:30 +01:00
2020-05-14 16:41:43 +02:00
if ( ! preview_camera - > is_pressed ( ) & & ! previewing_cinema ) {
2017-12-19 06:25:00 +01:00
preview_camera - > set_visible ( p_preview ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : update_transform_gizmo_view ( ) {
2020-05-14 16:41:43 +02:00
if ( ! is_visible_in_tree ( ) ) {
2014-05-05 03:50:23 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-05-05 03:50:23 +02:00
Transform xform = spatial_editor - > get_gizmo_transform ( ) ;
Transform camera_xform = camera - > get_transform ( ) ;
2019-01-25 00:52:28 +01:00
if ( xform . origin . distance_squared_to ( camera_xform . origin ) < 0.01 ) {
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( move_gizmo_instance [ i ] , false ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( move_plane_gizmo_instance [ i ] , false ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ i ] , false ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( scale_gizmo_instance [ i ] , false ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( scale_plane_gizmo_instance [ i ] , false ) ;
2019-01-25 00:52:28 +01:00
}
2020-09-13 18:22:51 +02:00
// Rotation white outline
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ 3 ] , false ) ;
2019-01-25 00:52:28 +01:00
return ;
}
2014-05-05 03:50:23 +02:00
Vector3 camz = - camera_xform . get_basis ( ) . get_axis ( 2 ) . normalized ( ) ;
Vector3 camy = - camera_xform . get_basis ( ) . get_axis ( 1 ) . normalized ( ) ;
2017-03-05 16:44:50 +01:00
Plane p ( camera_xform . origin , camz ) ;
2020-06-22 10:53:22 +02:00
float gizmo_d = MAX ( Math : : abs ( p . distance_to ( xform . origin ) ) , CMP_EPSILON ) ;
2017-03-05 16:44:50 +01:00
float d0 = camera - > unproject_position ( camera_xform . origin + camz * gizmo_d ) . y ;
float d1 = camera - > unproject_position ( camera_xform . origin + camz * gizmo_d + camy ) . y ;
float dd = Math : : abs ( d0 - d1 ) ;
2020-05-14 16:41:43 +02:00
if ( dd = = 0 ) {
2017-03-05 16:44:50 +01:00
dd = 0.0001 ;
2020-05-14 16:41:43 +02:00
}
2014-05-05 03:50:23 +02:00
2019-08-03 03:01:32 +02:00
float gizmo_size = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/manipulator_gizmo_size " ) ;
// At low viewport heights, multiply the gizmo scale based on the viewport height.
// This prevents the gizmo from growing very large and going outside the viewport.
const int viewport_base_height = 400 * MAX ( 1 , EDSCALE ) ;
gizmo_scale =
( gizmo_size / Math : : abs ( dd ) ) * MAX ( 1 , EDSCALE ) *
2020-04-01 20:28:09 +02:00
MIN ( viewport_base_height , subviewport_container - > get_size ( ) . height ) / viewport_base_height /
subviewport_container - > get_stretch_shrink ( ) ;
2017-03-05 16:44:50 +01:00
Vector3 scale = Vector3 ( 1 , 1 , 1 ) * gizmo_scale ;
2014-05-05 03:50:23 +02:00
xform . basis . scale ( scale ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( move_gizmo_instance [ i ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( move_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( move_plane_gizmo_instance [ i ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( move_plane_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( rotate_gizmo_instance [ i ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( scale_gizmo_instance [ i ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( scale_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( scale_plane_gizmo_instance [ i ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( scale_plane_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) ) ;
2014-05-05 03:50:23 +02:00
}
2020-09-13 18:22:51 +02:00
// Rotation white outline
RenderingServer : : get_singleton ( ) - > instance_set_transform ( rotate_gizmo_instance [ 3 ] , xform ) ;
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ 3 ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) ) ;
2014-05-05 03:50:23 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : set_state ( const Dictionary & p_state ) {
2020-05-14 16:41:43 +02:00
if ( p_state . has ( " position " ) ) {
2017-12-19 06:25:00 +01:00
cursor . pos = p_state [ " position " ] ;
2020-05-14 16:41:43 +02:00
}
if ( p_state . has ( " x_rotation " ) ) {
2017-12-19 06:25:00 +01:00
cursor . x_rot = p_state [ " x_rotation " ] ;
2020-05-14 16:41:43 +02:00
}
if ( p_state . has ( " y_rotation " ) ) {
2017-12-19 06:25:00 +01:00
cursor . y_rot = p_state [ " y_rotation " ] ;
2020-05-14 16:41:43 +02:00
}
if ( p_state . has ( " distance " ) ) {
2017-12-19 06:25:00 +01:00
cursor . distance = p_state [ " distance " ] ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
if ( p_state . has ( " use_orthogonal " ) ) {
bool orth = p_state [ " use_orthogonal " ] ;
2020-05-14 16:41:43 +02:00
if ( orth ) {
2017-12-19 06:25:00 +01:00
_menu_option ( VIEW_ORTHOGONAL ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-12-19 06:25:00 +01:00
_menu_option ( VIEW_PERSPECTIVE ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
}
2019-10-23 11:46:26 +02:00
if ( p_state . has ( " view_name " ) ) {
name = p_state [ " view_name " ] ;
_update_name ( ) ;
}
if ( p_state . has ( " auto_orthogonal " ) ) {
auto_orthogonal = p_state [ " auto_orthogonal " ] ;
_update_name ( ) ;
}
if ( p_state . has ( " auto_orthogonal_enabled " ) ) {
bool enabled = p_state [ " auto_orthogonal_enabled " ] ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUTO_ORTHOGONAL ) , enabled ) ;
}
2017-12-19 06:25:00 +01:00
if ( p_state . has ( " display_mode " ) ) {
int display = p_state [ " display_mode " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( display ) ;
2020-05-14 16:41:43 +02:00
if ( ! view_menu - > get_popup ( ) - > is_item_checked ( idx ) ) {
2017-12-19 06:25:00 +01:00
_menu_option ( display ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
}
2018-06-25 03:24:31 +02:00
if ( p_state . has ( " lock_rotation " ) ) {
lock_rotation = p_state [ " lock_rotation " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_LOCK_ROTATION ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , lock_rotation ) ;
}
2017-12-19 06:25:00 +01:00
if ( p_state . has ( " use_environment " ) ) {
bool env = p_state [ " use_environment " ] ;
2020-05-14 16:41:43 +02:00
if ( env ! = camera - > get_environment ( ) . is_valid ( ) ) {
2017-12-19 06:25:00 +01:00
_menu_option ( VIEW_ENVIRONMENT ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
}
2014-10-03 05:10:51 +02:00
if ( p_state . has ( " listener " ) ) {
bool listener = p_state [ " listener " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) ;
viewport - > set_as_audio_listener ( listener ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , listener ) ;
2014-10-03 05:10:51 +02:00
}
2017-07-15 06:23:10 +02:00
if ( p_state . has ( " doppler " ) ) {
bool doppler = p_state [ " doppler " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_DOPPLER ) ;
2020-03-26 22:49:16 +01:00
camera - > set_doppler_tracking ( doppler ? Camera3D : : DOPPLER_TRACKING_IDLE_STEP : Camera3D : : DOPPLER_TRACKING_DISABLED ) ;
2017-07-15 06:23:10 +02:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , doppler ) ;
}
2017-11-20 01:45:56 +01:00
if ( p_state . has ( " gizmos " ) ) {
bool gizmos = p_state [ " gizmos " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ;
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = gizmos ) {
2017-11-20 01:45:56 +01:00
_menu_option ( VIEW_GIZMOS ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-20 01:45:56 +01:00
}
if ( p_state . has ( " information " ) ) {
bool information = p_state [ " information " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_INFORMATION ) ;
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = information ) {
2017-11-20 01:45:56 +01:00
_menu_option ( VIEW_INFORMATION ) ;
2020-05-14 16:41:43 +02:00
}
2017-11-20 01:45:56 +01:00
}
2020-04-10 19:18:42 +02:00
if ( p_state . has ( " frame_time " ) ) {
bool fps = p_state [ " frame_time " ] ;
2017-12-19 06:25:00 +01:00
2020-04-10 19:18:42 +02:00
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ;
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = fps ) {
2020-04-10 19:18:42 +02:00
_menu_option ( VIEW_FRAME_TIME ) ;
2020-05-14 16:41:43 +02:00
}
2017-12-19 06:25:00 +01:00
}
2017-10-31 18:23:25 +01:00
if ( p_state . has ( " half_res " ) ) {
bool half_res = p_state [ " half_res " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_HALF_RESOLUTION ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , half_res ) ;
}
2018-07-27 00:36:05 +02:00
if ( p_state . has ( " cinematic_preview " ) ) {
previewing_cinema = p_state [ " cinematic_preview " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_CINEMATIC_PREVIEW ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , previewing_cinema ) ;
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
if ( preview_camera - > is_connected ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ) {
preview_camera - > disconnect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2019-10-27 13:04:29 +01:00
}
2015-08-30 03:59:25 +02:00
if ( p_state . has ( " previewing " ) ) {
Node * pv = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_node ( p_state [ " previewing " ] ) ;
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < Camera3D > ( pv ) ) {
previewing = Object : : cast_to < Camera3D > ( pv ) ;
previewing - > connect ( " tree_exiting " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , previewing - > get_camera ( ) ) ; //replace
2019-03-11 18:10:00 +01:00
view_menu - > set_disabled ( true ) ;
2015-08-30 03:59:25 +02:00
surface - > update ( ) ;
preview_camera - > set_pressed ( true ) ;
preview_camera - > show ( ) ;
}
}
2020-03-26 22:49:16 +01:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Dictionary Node3DEditorViewport : : get_state ( ) const {
2014-02-10 02:10:30 +01:00
Dictionary d ;
2017-09-10 15:37:49 +02:00
d [ " position " ] = cursor . pos ;
d [ " x_rotation " ] = cursor . x_rot ;
d [ " y_rotation " ] = cursor . y_rot ;
2017-03-05 16:44:50 +01:00
d [ " distance " ] = cursor . distance ;
d [ " use_environment " ] = camera - > get_environment ( ) . is_valid ( ) ;
2020-03-26 22:49:16 +01:00
d [ " use_orthogonal " ] = camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ;
2019-10-23 11:46:26 +02:00
d [ " view_name " ] = name ;
d [ " auto_orthogonal " ] = auto_orthogonal ;
d [ " auto_orthogonal_enabled " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUTO_ORTHOGONAL ) ) ;
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_NORMAL ) ) ) {
2017-12-19 06:25:00 +01:00
d [ " display_mode " ] = VIEW_DISPLAY_NORMAL ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_WIREFRAME ) ) ) {
2017-12-19 06:25:00 +01:00
d [ " display_mode " ] = VIEW_DISPLAY_WIREFRAME ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_OVERDRAW ) ) ) {
2017-12-19 06:25:00 +01:00
d [ " display_mode " ] = VIEW_DISPLAY_OVERDRAW ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_SHADELESS ) ) ) {
2017-12-19 06:25:00 +01:00
d [ " display_mode " ] = VIEW_DISPLAY_SHADELESS ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
d [ " listener " ] = viewport - > is_audio_listener ( ) ;
2017-11-20 01:45:56 +01:00
d [ " doppler " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_DOPPLER ) ) ;
d [ " gizmos " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ) ;
d [ " information " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_INFORMATION ) ) ;
2020-04-10 19:18:42 +02:00
d [ " frame_time " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ) ;
2020-04-01 20:28:09 +02:00
d [ " half_res " ] = subviewport_container - > get_stretch_shrink ( ) > 1 ;
2018-07-27 00:36:05 +02:00
d [ " cinematic_preview " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_CINEMATIC_PREVIEW ) ) ;
2020-05-14 16:41:43 +02:00
if ( previewing ) {
2017-03-05 16:44:50 +01:00
d [ " previewing " ] = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( previewing ) ;
2020-05-14 16:41:43 +02:00
}
if ( lock_rotation ) {
2018-06-25 03:24:31 +02:00
d [ " lock_rotation " ] = lock_rotation ;
2020-05-14 16:41:43 +02:00
}
2015-08-30 03:59:25 +02:00
2014-02-10 02:10:30 +01:00
return d ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " update_transform_gizmo_view " ) , & Node3DEditorViewport : : update_transform_gizmo_view ) ; // Used by call_deferred.
ClassDB : : bind_method ( D_METHOD ( " can_drop_data_fw " ) , & Node3DEditorViewport : : can_drop_data_fw ) ;
ClassDB : : bind_method ( D_METHOD ( " drop_data_fw " ) , & Node3DEditorViewport : : drop_data_fw ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " toggle_maximize_view " , PropertyInfo ( Variant : : OBJECT , " viewport " ) ) ) ;
2019-04-06 22:55:01 +02:00
ADD_SIGNAL ( MethodInfo ( " clicked " , PropertyInfo ( Variant : : OBJECT , " viewport " ) ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : reset ( ) {
2017-03-05 16:44:50 +01:00
orthogonal = false ;
2019-10-23 11:46:26 +02:00
auto_orthogonal = false ;
2018-06-25 03:24:31 +02:00
lock_rotation = false ;
2017-03-05 16:44:50 +01:00
message_time = 0 ;
message = " " ;
last_message = " " ;
name = " " ;
2014-09-19 23:39:50 +02:00
2020-06-07 19:21:29 +02:00
cursor = Cursor ( ) ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2014-09-19 23:39:50 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : focus_selection ( ) {
2020-05-14 16:41:43 +02:00
if ( ! get_selected_count ( ) ) {
2016-07-28 21:37:52 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2016-07-28 21:37:52 +02:00
Vector3 center ;
2017-03-05 16:44:50 +01:00
int count = 0 ;
2016-07-28 21:37:52 +02:00
2017-03-05 16:44:50 +01:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2016-07-28 21:37:52 +02:00
2017-03-05 16:44:50 +01:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2016-07-28 21:37:52 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-07-28 21:37:52 +02:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2016-07-28 21:37:52 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-07-28 21:37:52 +02:00
2017-10-03 18:49:32 +02:00
center + = sp - > get_global_gizmo_transform ( ) . origin ;
2016-07-28 21:37:52 +02:00
count + + ;
}
2017-03-05 16:44:50 +01:00
if ( count ! = 0 ) {
center / = float ( count ) ;
2016-07-28 21:37:52 +02:00
}
2017-03-05 16:44:50 +01:00
cursor . pos = center ;
2016-07-28 21:37:52 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : assign_pending_data_pointers ( Node3D * p_preview_node , AABB * p_preview_bounds , AcceptDialog * p_accept ) {
2017-09-02 21:47:16 +02:00
preview_node = p_preview_node ;
preview_bounds = p_preview_bounds ;
accept = p_accept ;
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditorViewport : : _get_instance_position ( const Point2 & p_pos ) const {
2017-09-02 21:47:16 +02:00
const float MAX_DISTANCE = 10 ;
Vector3 world_ray = _get_ray ( p_pos ) ;
Vector3 world_pos = _get_ray_pos ( p_pos ) ;
2020-04-18 11:00:51 +02:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_ray ( world_pos , world_ray , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-26 22:49:16 +01:00
Set < Ref < EditorNode3DGizmo > > found_gizmos ;
2017-09-02 21:47:16 +02:00
float closest_dist = MAX_DISTANCE ;
Vector3 point = world_pos + world_ray * MAX_DISTANCE ;
Vector3 normal = Vector3 ( 0.0 , 0.0 , 0.0 ) ;
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
MeshInstance3D * mesh_instance = Object : : cast_to < MeshInstance3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2017-09-02 21:47:16 +02:00
2020-05-14 16:41:43 +02:00
if ( ! mesh_instance ) {
2017-09-02 21:47:16 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-09-02 21:47:16 +02:00
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = mesh_instance - > get_gizmo ( ) ;
2017-09-02 21:47:16 +02:00
if ( ( ! seg . is_valid ( ) ) | | found_gizmos . has ( seg ) ) {
continue ;
}
found_gizmos . insert ( seg ) ;
Vector3 hit_point ;
Vector3 hit_normal ;
2020-04-02 01:20:12 +02:00
bool inters = seg - > intersect_ray ( camera , p_pos , hit_point , hit_normal , nullptr , false ) ;
2017-09-02 21:47:16 +02:00
2020-05-14 16:41:43 +02:00
if ( ! inters ) {
2017-09-02 21:47:16 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-09-02 21:47:16 +02:00
float dist = world_pos . distance_to ( hit_point ) ;
2020-05-14 16:41:43 +02:00
if ( dist < 0 ) {
2017-09-02 21:47:16 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-09-02 21:47:16 +02:00
if ( dist < closest_dist ) {
closest_dist = dist ;
point = hit_point ;
normal = hit_normal ;
}
}
2017-10-18 06:16:05 +02:00
Vector3 offset = Vector3 ( ) ;
for ( int i = 0 ; i < 3 ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( normal [ i ] > 0.0 ) {
2017-10-18 06:16:05 +02:00
offset [ i ] = ( preview_bounds - > get_size ( ) [ i ] - ( preview_bounds - > get_size ( ) [ i ] + preview_bounds - > get_position ( ) [ i ] ) ) ;
2020-05-14 16:41:43 +02:00
} else if ( normal [ i ] < 0.0 ) {
2017-10-18 06:16:05 +02:00
offset [ i ] = - ( preview_bounds - > get_size ( ) [ i ] + preview_bounds - > get_position ( ) [ i ] ) ;
2020-05-14 16:41:43 +02:00
}
2017-10-18 06:16:05 +02:00
}
return point + offset ;
2017-09-02 21:47:16 +02:00
}
2020-10-02 23:03:52 +02:00
AABB Node3DEditorViewport : : _calculate_spatial_bounds ( const Node3D * p_parent , bool p_exclude_top_level_transform ) {
2019-10-04 15:28:30 +02:00
AABB bounds ;
2020-03-26 22:49:16 +01:00
const MeshInstance3D * mesh_instance = Object : : cast_to < MeshInstance3D > ( p_parent ) ;
2019-10-04 15:28:30 +02:00
if ( mesh_instance ) {
bounds = mesh_instance - > get_aabb ( ) ;
}
2017-09-02 21:47:16 +02:00
for ( int i = 0 ; i < p_parent - > get_child_count ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
Node3D * child = Object : : cast_to < Node3D > ( p_parent - > get_child ( i ) ) ;
2017-09-02 21:47:16 +02:00
if ( child ) {
2019-10-04 15:28:30 +02:00
AABB child_bounds = _calculate_spatial_bounds ( child , false ) ;
2020-03-26 22:49:16 +01:00
if ( bounds . size = = Vector3 ( ) & & p_parent - > get_class_name ( ) = = StringName ( " Node3D " ) ) {
2019-10-04 15:28:30 +02:00
bounds = child_bounds ;
} else {
bounds . merge_with ( child_bounds ) ;
2017-09-02 21:47:16 +02:00
}
}
}
2019-10-04 15:28:30 +02:00
2020-03-26 22:49:16 +01:00
if ( bounds . size = = Vector3 ( ) & & p_parent - > get_class_name ( ) ! = StringName ( " Node3D " ) ) {
2019-10-04 15:28:30 +02:00
bounds = AABB ( Vector3 ( - 0.2 , - 0.2 , - 0.2 ) , Vector3 ( 0.4 , 0.4 , 0.4 ) ) ;
}
2020-10-02 23:03:52 +02:00
if ( ! p_exclude_top_level_transform ) {
2019-10-04 15:28:30 +02:00
bounds = p_parent - > get_transform ( ) . xform ( bounds ) ;
}
2017-09-02 21:47:16 +02:00
return bounds ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _create_preview ( const Vector < String > & files ) const {
2017-09-02 21:47:16 +02:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
String path = files [ i ] ;
RES res = ResourceLoader : : load ( path ) ;
2019-09-29 14:17:42 +02:00
ERR_CONTINUE ( res . is_null ( ) ) ;
2017-09-02 21:47:16 +02:00
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2017-09-16 15:57:17 +02:00
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2020-04-02 01:20:12 +02:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
if ( mesh ! = nullptr ) {
2020-03-26 22:49:16 +01:00
MeshInstance3D * mesh_instance = memnew ( MeshInstance3D ) ;
2017-09-16 15:57:17 +02:00
mesh_instance - > set_mesh ( mesh ) ;
preview_node - > add_child ( mesh_instance ) ;
} else {
if ( scene . is_valid ( ) ) {
Node * instance = scene - > instance ( ) ;
if ( instance ) {
preview_node - > add_child ( instance ) ;
}
2017-09-02 21:47:16 +02:00
}
}
editor - > get_scene_root ( ) - > add_child ( preview_node ) ;
}
}
2019-10-04 15:28:30 +02:00
* preview_bounds = _calculate_spatial_bounds ( preview_node ) ;
2017-09-02 21:47:16 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _remove_preview ( ) {
2017-09-02 21:47:16 +02:00
if ( preview_node - > get_parent ( ) ) {
for ( int i = preview_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
Node * node = preview_node - > get_child ( i ) ;
node - > queue_delete ( ) ;
preview_node - > remove_child ( node ) ;
}
editor - > get_scene_root ( ) - > remove_child ( preview_node ) ;
}
}
2020-03-26 22:49:16 +01:00
bool Node3DEditorViewport : : _cyclical_dependency_exists ( const String & p_target_scene_path , Node * p_desired_node ) {
2017-09-02 21:47:16 +02:00
if ( p_desired_node - > get_filename ( ) = = p_target_scene_path ) {
return true ;
}
int childCount = p_desired_node - > get_child_count ( ) ;
for ( int i = 0 ; i < childCount ; i + + ) {
Node * child = p_desired_node - > get_child ( i ) ;
if ( _cyclical_dependency_exists ( p_target_scene_path , child ) ) {
return true ;
}
}
return false ;
}
2020-03-26 22:49:16 +01:00
bool Node3DEditorViewport : : _create_instance ( Node * parent , String & path , const Point2 & p_point ) {
2017-09-16 15:57:17 +02:00
RES res = ResourceLoader : : load ( path ) ;
2019-09-29 14:17:42 +02:00
ERR_FAIL_COND_V ( res . is_null ( ) , false ) ;
2017-09-16 15:57:17 +02:00
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2020-04-02 01:20:12 +02:00
Node * instanced_scene = nullptr ;
2017-09-16 15:57:17 +02:00
2020-04-02 01:20:12 +02:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
if ( mesh ! = nullptr ) {
2020-03-26 22:49:16 +01:00
MeshInstance3D * mesh_instance = memnew ( MeshInstance3D ) ;
2017-09-16 15:57:17 +02:00
mesh_instance - > set_mesh ( mesh ) ;
2018-11-29 21:14:53 +01:00
mesh_instance - > set_name ( path . get_file ( ) . get_basename ( ) ) ;
2017-09-16 15:57:17 +02:00
instanced_scene = mesh_instance ;
} else {
if ( ! scene . is_valid ( ) ) { // invalid scene
return false ;
} else {
2018-05-06 19:13:23 +02:00
instanced_scene = scene - > instance ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
2017-09-16 15:57:17 +02:00
}
}
2017-09-02 21:47:16 +02:00
}
2020-04-02 01:20:12 +02:00
if ( instanced_scene = = nullptr ) {
2017-09-02 21:47:16 +02:00
return false ;
}
if ( editor - > get_edited_scene ( ) - > get_filename ( ) ! = " " ) { // cyclical instancing
if ( _cyclical_dependency_exists ( editor - > get_edited_scene ( ) - > get_filename ( ) , instanced_scene ) ) {
memdelete ( instanced_scene ) ;
return false ;
}
}
2020-04-02 01:20:12 +02:00
if ( scene ! = nullptr ) {
2017-11-10 22:31:53 +01:00
instanced_scene - > set_filename ( ProjectSettings : : get_singleton ( ) - > localize_path ( path ) ) ;
}
2017-09-02 21:47:16 +02:00
editor_data - > get_undo_redo ( ) . add_do_method ( parent , " add_child " , instanced_scene ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( instanced_scene , " set_owner " , editor - > get_edited_scene ( ) ) ;
editor_data - > get_undo_redo ( ) . add_do_reference ( instanced_scene ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( parent , " remove_child " , instanced_scene ) ;
String new_name = parent - > validate_child_name ( instanced_scene ) ;
2020-02-07 02:52:05 +01:00
EditorDebuggerNode * ed = EditorDebuggerNode : : get_singleton ( ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( ed , " live_debug_instance_node " , editor - > get_edited_scene ( ) - > get_path_to ( parent ) , path , new_name ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( ed , " live_debug_remove_node " , NodePath ( String ( editor - > get_edited_scene ( ) - > get_path_to ( parent ) ) + " / " + new_name ) ) ;
2017-09-02 21:47:16 +02:00
2020-06-07 22:09:41 +02:00
Node3D * node3d = Object : : cast_to < Node3D > ( instanced_scene ) ;
if ( node3d ) {
Transform global_transform ;
Node3D * parent_node3d = Object : : cast_to < Node3D > ( parent ) ;
if ( parent_node3d ) {
global_transform = parent_node3d - > get_global_gizmo_transform ( ) ;
}
2017-09-02 21:47:16 +02:00
2020-06-07 22:09:41 +02:00
global_transform . origin = spatial_editor - > snap_point ( _get_instance_position ( p_point ) ) ;
global_transform . basis * = node3d - > get_transform ( ) . basis ;
2017-09-02 21:47:16 +02:00
2020-06-07 22:09:41 +02:00
editor_data - > get_undo_redo ( ) . add_do_method ( instanced_scene , " set_global_transform " , global_transform ) ;
}
2017-09-02 21:47:16 +02:00
return true ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : _perform_drop_data ( ) {
2017-09-02 21:47:16 +02:00
_remove_preview ( ) ;
Vector < String > error_files ;
editor_data - > get_undo_redo ( ) . create_action ( TTR ( " Create Node " ) ) ;
for ( int i = 0 ; i < selected_files . size ( ) ; i + + ) {
String path = selected_files [ i ] ;
RES res = ResourceLoader : : load ( path ) ;
if ( res . is_null ( ) ) {
continue ;
}
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2017-09-16 15:57:17 +02:00
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2020-04-02 01:20:12 +02:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
2017-09-02 21:47:16 +02:00
bool success = _create_instance ( target_node , path , drop_pos ) ;
if ( ! success ) {
error_files . push_back ( path ) ;
}
}
}
editor_data - > get_undo_redo ( ) . commit_action ( ) ;
if ( error_files . size ( ) > 0 ) {
String files_str ;
for ( int i = 0 ; i < error_files . size ( ) ; i + + ) {
files_str + = error_files [ i ] . get_file ( ) . get_basename ( ) + " , " ;
}
files_str = files_str . substr ( 0 , files_str . length ( ) - 1 ) ;
2020-07-27 12:43:20 +02:00
accept - > set_text ( vformat ( TTR ( " Error instancing scene from %s " ) , files_str . get_data ( ) ) ) ;
2020-03-06 18:00:16 +01:00
accept - > popup_centered ( ) ;
2017-09-02 21:47:16 +02:00
}
}
2020-03-26 22:49:16 +01:00
bool Node3DEditorViewport : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) const {
2017-09-02 21:47:16 +02:00
bool can_instance = false ;
if ( ! preview_node - > is_inside_tree ( ) ) {
Dictionary d = p_data ;
if ( d . has ( " type " ) & & ( String ( d [ " type " ] ) = = " files " ) ) {
Vector < String > files = d [ " files " ] ;
List < String > scene_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " PackedScene " , & scene_extensions ) ;
2017-09-16 15:57:17 +02:00
List < String > mesh_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " Mesh " , & mesh_extensions ) ;
2017-09-02 21:47:16 +02:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
2017-09-16 15:57:17 +02:00
if ( mesh_extensions . find ( files [ i ] . get_extension ( ) ) | | scene_extensions . find ( files [ i ] . get_extension ( ) ) ) {
2017-09-02 21:47:16 +02:00
RES res = ResourceLoader : : load ( files [ i ] ) ;
if ( res . is_null ( ) ) {
continue ;
}
String type = res - > get_class ( ) ;
if ( type = = " PackedScene " ) {
Ref < PackedScene > sdata = ResourceLoader : : load ( files [ i ] ) ;
Node * instanced_scene = sdata - > instance ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
if ( ! instanced_scene ) {
continue ;
}
memdelete ( instanced_scene ) ;
2017-12-31 05:22:16 +01:00
} else if ( type = = " Mesh " | | type = = " ArrayMesh " | | type = = " PrimitiveMesh " ) {
2017-09-16 15:57:17 +02:00
Ref < Mesh > mesh = ResourceLoader : : load ( files [ i ] ) ;
if ( ! mesh . is_valid ( ) ) {
continue ;
}
} else {
continue ;
2017-09-02 21:47:16 +02:00
}
can_instance = true ;
break ;
}
}
if ( can_instance ) {
_create_preview ( files ) ;
}
}
} else {
can_instance = true ;
}
if ( can_instance ) {
Transform global_transform = Transform ( Basis ( ) , _get_instance_position ( p_point ) ) ;
preview_node - > set_global_transform ( global_transform ) ;
}
return can_instance ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewport : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) {
2020-05-14 16:41:43 +02:00
if ( ! can_drop_data_fw ( p_point , p_data , p_from ) ) {
2017-09-02 21:47:16 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-09-02 21:47:16 +02:00
2020-04-28 15:19:37 +02:00
bool is_shift = Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ;
2017-09-02 21:47:16 +02:00
selected_files . clear ( ) ;
Dictionary d = p_data ;
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " files " ) {
selected_files = d [ " files " ] ;
}
List < Node * > list = editor - > get_editor_selection ( ) - > get_selected_node_list ( ) ;
if ( list . size ( ) = = 0 ) {
Node * root_node = editor - > get_edited_scene ( ) ;
if ( root_node ) {
list . push_back ( root_node ) ;
} else {
accept - > set_text ( TTR ( " No parent to instance a child at. " ) ) ;
2020-03-06 18:00:16 +01:00
accept - > popup_centered ( ) ;
2017-09-02 21:47:16 +02:00
_remove_preview ( ) ;
return ;
}
}
if ( list . size ( ) ! = 1 ) {
accept - > set_text ( TTR ( " This operation requires a single selected node. " ) ) ;
2020-03-06 18:00:16 +01:00
accept - > popup_centered ( ) ;
2017-09-02 21:47:16 +02:00
_remove_preview ( ) ;
return ;
}
target_node = list [ 0 ] ;
if ( is_shift & & target_node ! = editor - > get_edited_scene ( ) ) {
target_node = target_node - > get_parent ( ) ;
}
drop_pos = p_point ;
_perform_drop_data ( ) ;
}
2020-03-26 22:49:16 +01:00
Node3DEditorViewport : : Node3DEditorViewport ( Node3DEditor * p_spatial_editor , EditorNode * p_editor , int p_index ) {
2020-04-10 19:18:42 +02:00
cpu_time_history_index = 0 ;
2020-04-13 12:11:55 +02:00
gpu_time_history_index = 0 ;
2020-04-10 19:18:42 +02:00
2017-03-05 16:44:50 +01:00
_edit . mode = TRANSFORM_NONE ;
_edit . plane = TRANSFORM_VIEW ;
_edit . edited_gizmo = 0 ;
2020-05-14 11:00:19 +02:00
_edit . snap = true ;
2017-03-05 16:44:50 +01:00
_edit . gizmo_handle = 0 ;
index = p_index ;
editor = p_editor ;
2017-09-02 21:47:16 +02:00
editor_data = editor - > get_scene_tree_dock ( ) - > get_editor_data ( ) ;
2017-03-05 16:44:50 +01:00
editor_selection = editor - > get_editor_selection ( ) ;
undo_redo = editor - > get_undo_redo ( ) ;
2020-02-12 18:24:06 +01:00
2017-03-05 16:44:50 +01:00
clicked_includes_current = false ;
orthogonal = false ;
2019-10-23 11:46:26 +02:00
auto_orthogonal = false ;
2018-08-05 20:24:11 +02:00
lock_rotation = false ;
2017-03-05 16:44:50 +01:00
message_time = 0 ;
2017-05-07 22:59:05 +02:00
zoom_indicator_delay = 0.0 ;
2017-03-05 16:44:50 +01:00
spatial_editor = p_spatial_editor ;
2020-04-01 20:28:09 +02:00
SubViewportContainer * c = memnew ( SubViewportContainer ) ;
subviewport_container = c ;
2016-10-19 16:14:41 +02:00
c - > set_stretch ( true ) ;
2014-02-10 02:10:30 +01:00
add_child ( c ) ;
2020-12-22 17:24:29 +01:00
c - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2020-03-04 02:51:12 +01:00
viewport = memnew ( SubViewport ) ;
2016-01-18 23:49:11 +01:00
viewport - > set_disable_input ( true ) ;
2016-11-10 03:55:06 +01:00
2014-02-10 02:10:30 +01:00
c - > add_child ( viewport ) ;
2017-03-05 16:44:50 +01:00
surface = memnew ( Control ) ;
2017-09-02 21:47:16 +02:00
surface - > set_drag_forwarding ( this ) ;
2014-02-10 02:10:30 +01:00
add_child ( surface ) ;
2020-12-22 17:24:29 +01:00
surface - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2017-06-11 23:13:04 +02:00
surface - > set_clip_contents ( true ) ;
2020-03-26 22:49:16 +01:00
camera = memnew ( Camera3D ) ;
2014-02-10 02:10:30 +01:00
camera - > set_disable_gizmo ( true ) ;
2020-11-26 20:00:03 +01:00
camera - > set_cull_mask ( ( ( 1 < < 20 ) - 1 ) | ( 1 < < ( GIZMO_BASE_LAYER + p_index ) ) | ( 1 < < GIZMO_EDIT_LAYER ) | ( 1 < < GIZMO_GRID_LAYER ) | ( 1 < < MISC_TOOL_LAYER ) ) ;
2014-02-10 02:10:30 +01:00
viewport - > add_child ( camera ) ;
camera - > make_current ( ) ;
surface - > set_focus_mode ( FOCUS_ALL ) ;
2019-05-24 21:21:07 +02:00
VBoxContainer * vbox = memnew ( VBoxContainer ) ;
surface - > add_child ( vbox ) ;
vbox - > set_position ( Point2 ( 10 , 10 ) * EDSCALE ) ;
2017-03-05 16:44:50 +01:00
view_menu = memnew ( MenuButton ) ;
2018-10-10 09:25:59 +02:00
view_menu - > set_flat ( false ) ;
2019-05-24 21:21:07 +02:00
view_menu - > set_h_size_flags ( 0 ) ;
2020-09-17 03:40:00 +02:00
view_menu - > set_shortcut_context ( this ) ;
vbox - > add_child ( view_menu ) ;
2018-10-10 09:25:59 +02:00
2019-10-03 22:39:08 +02:00
display_submenu = memnew ( PopupMenu ) ;
view_menu - > get_popup ( ) - > add_child ( display_submenu ) ;
2016-06-30 22:54:34 +02:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/top_view " ) , VIEW_TOP ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/bottom_view " ) , VIEW_BOTTOM ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/left_view " ) , VIEW_LEFT ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/right_view " ) , VIEW_RIGHT ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/front_view " ) , VIEW_FRONT ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/rear_view " ) , VIEW_REAR ) ;
2014-02-10 02:10:30 +01:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2018-03-24 03:05:20 +01:00
view_menu - > get_popup ( ) - > add_radio_check_item ( TTR ( " Perspective " ) + " ( " + ED_GET_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " ) - > get_as_text ( ) + " ) " , VIEW_PERSPECTIVE ) ;
view_menu - > get_popup ( ) - > add_radio_check_item ( TTR ( " Orthogonal " ) + " ( " + ED_GET_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " ) - > get_as_text ( ) + " ) " , VIEW_ORTHOGONAL ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_PERSPECTIVE ) , true ) ;
2019-10-23 11:46:26 +02:00
view_menu - > get_popup ( ) - > add_check_item ( TTR ( " Auto Orthogonal Enabled " ) , VIEW_AUTO_ORTHOGONAL ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUTO_ORTHOGONAL ) , true ) ;
2014-02-10 02:10:30 +01:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2018-06-25 03:24:31 +02:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_lock_rotation " , TTR ( " Lock View Rotation " ) ) , VIEW_LOCK_ROTATION ) ;
view_menu - > get_popup ( ) - > add_separator ( ) ;
2018-03-24 03:05:20 +01:00
view_menu - > get_popup ( ) - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_display_normal " , TTR ( " Display Normal " ) ) , VIEW_DISPLAY_NORMAL ) ;
view_menu - > get_popup ( ) - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_display_wireframe " , TTR ( " Display Wireframe " ) ) , VIEW_DISPLAY_WIREFRAME ) ;
view_menu - > get_popup ( ) - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_display_overdraw " , TTR ( " Display Overdraw " ) ) , VIEW_DISPLAY_OVERDRAW ) ;
2019-10-04 03:59:14 +02:00
view_menu - > get_popup ( ) - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_display_lighting " , TTR ( " Display Lighting " ) ) , VIEW_DISPLAY_LIGHTING ) ;
2018-03-24 03:05:20 +01:00
view_menu - > get_popup ( ) - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_display_unshaded " , TTR ( " Display Unshaded " ) ) , VIEW_DISPLAY_SHADELESS ) ;
2017-06-11 20:52:03 +02:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_NORMAL ) , true ) ;
2020-04-08 03:51:52 +02:00
display_submenu - > add_radio_check_item ( TTR ( " Directional Shadow Splits " ) , VIEW_DISPLAY_DEBUG_PSSM_SPLITS ) ;
display_submenu - > add_separator ( ) ;
2020-01-27 00:09:40 +01:00
display_submenu - > add_radio_check_item ( TTR ( " Normal Buffer " ) , VIEW_DISPLAY_NORMAL_BUFFER ) ;
display_submenu - > add_separator ( ) ;
2019-10-03 22:39:08 +02:00
display_submenu - > add_radio_check_item ( TTR ( " Shadow Atlas " ) , VIEW_DISPLAY_DEBUG_SHADOW_ATLAS ) ;
display_submenu - > add_radio_check_item ( TTR ( " Directional Shadow " ) , VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS ) ;
display_submenu - > add_separator ( ) ;
2020-04-14 05:05:21 +02:00
display_submenu - > add_radio_check_item ( TTR ( " Decal Atlas " ) , VIEW_DISPLAY_DEBUG_DECAL_ATLAS ) ;
display_submenu - > add_separator ( ) ;
2019-10-03 22:39:08 +02:00
display_submenu - > add_radio_check_item ( TTR ( " GIProbe Lighting " ) , VIEW_DISPLAY_DEBUG_GIPROBE_LIGHTING ) ;
display_submenu - > add_radio_check_item ( TTR ( " GIProbe Albedo " ) , VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO ) ;
2019-10-05 15:27:43 +02:00
display_submenu - > add_radio_check_item ( TTR ( " GIProbe Emission " ) , VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION ) ;
2020-01-12 02:26:52 +01:00
display_submenu - > add_separator ( ) ;
2020-06-25 15:33:28 +02:00
display_submenu - > add_radio_check_item ( TTR ( " SDFGI Cascades " ) , VIEW_DISPLAY_DEBUG_SDFGI ) ;
display_submenu - > add_radio_check_item ( TTR ( " SDFGI Probes " ) , VIEW_DISPLAY_DEBUG_SDFGI_PROBES ) ;
display_submenu - > add_separator ( ) ;
2020-01-12 02:26:52 +01:00
display_submenu - > add_radio_check_item ( TTR ( " Scene Luminance " ) , VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE ) ;
2020-01-25 11:18:55 +01:00
display_submenu - > add_separator ( ) ;
display_submenu - > add_radio_check_item ( TTR ( " SSAO " ) , VIEW_DISPLAY_DEBUG_SSAO ) ;
2020-01-27 00:09:40 +01:00
display_submenu - > add_separator ( ) ;
2020-06-25 15:33:28 +02:00
display_submenu - > add_radio_check_item ( TTR ( " GI Buffer " ) , VIEW_DISPLAY_DEBUG_GI_BUFFER ) ;
2020-12-17 19:56:59 +01:00
display_submenu - > add_separator ( ) ;
display_submenu - > add_radio_check_item ( TTR ( " Disable LOD " ) , VIEW_DISPLAY_DEBUG_DISABLE_LOD ) ;
2021-01-17 17:25:38 +01:00
display_submenu - > add_separator ( ) ;
display_submenu - > add_radio_check_item ( TTR ( " Omni Light Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS ) ;
display_submenu - > add_radio_check_item ( TTR ( " Spot Light Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS ) ;
display_submenu - > add_radio_check_item ( TTR ( " Decal Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_DECALS ) ;
display_submenu - > add_radio_check_item ( TTR ( " Reflection Probe Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES ) ;
2019-10-03 22:39:08 +02:00
display_submenu - > set_name ( " display_advanced " ) ;
2020-03-08 19:23:04 +01:00
view_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Display Advanced... " ) , " display_advanced " , VIEW_DISPLAY_ADVANCED ) ;
2017-06-11 20:52:03 +02:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_environment " , TTR ( " View Environment " ) ) , VIEW_ENVIRONMENT ) ;
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_gizmos " , TTR ( " View Gizmos " ) ) , VIEW_GIZMOS ) ;
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_information " , TTR ( " View Information " ) ) , VIEW_INFORMATION ) ;
2020-04-10 19:18:42 +02:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_fps " , TTR ( " View Frame Time " ) ) , VIEW_FRAME_TIME ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ENVIRONMENT ) , true ) ;
2014-10-03 05:10:51 +02:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2017-10-31 18:23:25 +01:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_half_resolution " , TTR ( " Half Resolution " ) ) , VIEW_HALF_RESOLUTION ) ;
view_menu - > get_popup ( ) - > add_separator ( ) ;
2016-06-30 22:54:34 +02:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_audio_listener " , TTR ( " Audio Listener " ) ) , VIEW_AUDIO_LISTENER ) ;
2019-08-12 22:23:00 +02:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_audio_doppler " , TTR ( " Enable Doppler " ) ) , VIEW_AUDIO_DOPPLER ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) , true ) ;
2014-10-03 05:10:51 +02:00
2018-07-27 00:36:05 +02:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_cinematic_preview " , TTR ( " Cinematic Preview " ) ) , VIEW_CINEMATIC_PREVIEW ) ;
2014-02-10 02:10:30 +01:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2016-10-04 20:39:38 +02:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/focus_origin " ) , VIEW_CENTER_TO_ORIGIN ) ;
2016-06-30 22:54:34 +02:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/focus_selection " ) , VIEW_CENTER_TO_SELECTION ) ;
2018-10-27 23:43:19 +02:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/align_transform_with_view " ) , VIEW_ALIGN_TRANSFORM_WITH_VIEW ) ;
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/align_rotation_with_view " ) , VIEW_ALIGN_ROTATION_WITH_VIEW ) ;
2020-03-26 22:49:16 +01:00
view_menu - > get_popup ( ) - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditorViewport : : _menu_option ) ) ;
display_submenu - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditorViewport : : _menu_option ) ) ;
2017-12-19 15:29:55 +01:00
view_menu - > set_disable_shortcuts ( true ) ;
2020-03-03 14:36:29 +01:00
# ifndef _MSC_VER
# warning this needs to be fixed
# endif
//if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
if ( false ) {
2020-02-13 10:08:52 +01:00
// Alternate display modes only work when using the Vulkan renderer; make this explicit.
2020-01-17 16:06:47 +01:00
const int normal_idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_NORMAL ) ;
const int wireframe_idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_WIREFRAME ) ;
const int overdraw_idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_OVERDRAW ) ;
const int shadeless_idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_SHADELESS ) ;
const String unsupported_tooltip = TTR ( " Not available when using the GLES2 renderer. " ) ;
view_menu - > get_popup ( ) - > set_item_disabled ( normal_idx , true ) ;
view_menu - > get_popup ( ) - > set_item_tooltip ( normal_idx , unsupported_tooltip ) ;
view_menu - > get_popup ( ) - > set_item_disabled ( wireframe_idx , true ) ;
view_menu - > get_popup ( ) - > set_item_tooltip ( wireframe_idx , unsupported_tooltip ) ;
view_menu - > get_popup ( ) - > set_item_disabled ( overdraw_idx , true ) ;
view_menu - > get_popup ( ) - > set_item_tooltip ( overdraw_idx , unsupported_tooltip ) ;
view_menu - > get_popup ( ) - > set_item_disabled ( shadeless_idx , true ) ;
view_menu - > get_popup ( ) - > set_item_tooltip ( shadeless_idx , unsupported_tooltip ) ;
}
2017-07-27 04:00:23 +02:00
ED_SHORTCUT ( " spatial_editor/freelook_left " , TTR ( " Freelook Left " ) , KEY_A ) ;
ED_SHORTCUT ( " spatial_editor/freelook_right " , TTR ( " Freelook Right " ) , KEY_D ) ;
ED_SHORTCUT ( " spatial_editor/freelook_forward " , TTR ( " Freelook Forward " ) , KEY_W ) ;
ED_SHORTCUT ( " spatial_editor/freelook_backwards " , TTR ( " Freelook Backwards " ) , KEY_S ) ;
2017-09-14 01:36:42 +02:00
ED_SHORTCUT ( " spatial_editor/freelook_up " , TTR ( " Freelook Up " ) , KEY_E ) ;
ED_SHORTCUT ( " spatial_editor/freelook_down " , TTR ( " Freelook Down " ) , KEY_Q ) ;
2017-07-27 04:00:23 +02:00
ED_SHORTCUT ( " spatial_editor/freelook_speed_modifier " , TTR ( " Freelook Speed Modifier " ) , KEY_SHIFT ) ;
2019-10-14 22:47:47 +02:00
ED_SHORTCUT ( " spatial_editor/freelook_slow_modifier " , TTR ( " Freelook Slow Modifier " ) , KEY_ALT ) ;
2017-07-27 04:00:23 +02:00
2018-10-10 09:25:59 +02:00
preview_camera = memnew ( CheckBox ) ;
2017-12-19 06:25:00 +01:00
preview_camera - > set_text ( TTR ( " Preview " ) ) ;
2019-05-24 21:21:07 +02:00
vbox - > add_child ( preview_camera ) ;
preview_camera - > set_h_size_flags ( 0 ) ;
2014-02-10 02:10:30 +01:00
preview_camera - > hide ( ) ;
2020-03-26 22:49:16 +01:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2020-04-02 01:20:12 +02:00
previewing = nullptr ;
2017-03-05 16:44:50 +01:00
gizmo_scale = 1.0 ;
2017-05-07 22:59:05 +02:00
2020-04-02 01:20:12 +02:00
preview_node = nullptr ;
2017-09-02 21:47:16 +02:00
2017-06-11 23:13:04 +02:00
info_label = memnew ( Label ) ;
2020-12-22 17:24:29 +01:00
info_label - > set_anchor_and_offset ( SIDE_LEFT , ANCHOR_END , - 90 * EDSCALE ) ;
info_label - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_END , - 90 * EDSCALE ) ;
info_label - > set_anchor_and_offset ( SIDE_RIGHT , ANCHOR_END , - 10 * EDSCALE ) ;
info_label - > set_anchor_and_offset ( SIDE_BOTTOM , ANCHOR_END , - 10 * EDSCALE ) ;
2017-12-17 13:06:21 +01:00
info_label - > set_h_grow_direction ( GROW_DIRECTION_BEGIN ) ;
info_label - > set_v_grow_direction ( GROW_DIRECTION_BEGIN ) ;
surface - > add_child ( info_label ) ;
info_label - > hide ( ) ;
2017-06-11 23:13:04 +02:00
2018-07-27 00:36:05 +02:00
cinema_label = memnew ( Label ) ;
2020-12-22 17:24:29 +01:00
cinema_label - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_BEGIN , 10 * EDSCALE ) ;
2018-07-27 00:36:05 +02:00
cinema_label - > set_h_grow_direction ( GROW_DIRECTION_END ) ;
cinema_label - > set_align ( Label : : ALIGN_CENTER ) ;
surface - > add_child ( cinema_label ) ;
cinema_label - > set_text ( TTR ( " Cinematic Preview " ) ) ;
cinema_label - > hide ( ) ;
previewing_cinema = false ;
2018-10-10 09:25:59 +02:00
locked_label = memnew ( Label ) ;
2020-12-22 17:24:29 +01:00
locked_label - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_END , - 20 * EDSCALE ) ;
locked_label - > set_anchor_and_offset ( SIDE_BOTTOM , ANCHOR_END , - 10 * EDSCALE ) ;
2018-10-10 09:25:59 +02:00
locked_label - > set_h_grow_direction ( GROW_DIRECTION_END ) ;
locked_label - > set_v_grow_direction ( GROW_DIRECTION_BEGIN ) ;
locked_label - > set_align ( Label : : ALIGN_CENTER ) ;
surface - > add_child ( locked_label ) ;
locked_label - > set_text ( TTR ( " View Rotation Locked " ) ) ;
locked_label - > hide ( ) ;
2020-12-26 20:21:07 +01:00
frame_time_gradient = memnew ( Gradient ) ;
// The color is set when the theme changes.
frame_time_gradient - > add_point ( 0.5 , Color ( ) ) ;
2019-10-23 11:46:26 +02:00
top_right_vbox = memnew ( VBoxContainer ) ;
2020-12-22 17:24:29 +01:00
top_right_vbox - > set_anchors_and_offsets_preset ( PRESET_TOP_RIGHT , PRESET_MODE_MINSIZE , 2.0 * EDSCALE ) ;
2019-10-23 11:46:26 +02:00
top_right_vbox - > set_h_grow_direction ( GROW_DIRECTION_BEGIN ) ;
2020-12-26 20:21:07 +01:00
// Make sure frame time labels don't touch the viewport's edge.
top_right_vbox - > set_custom_minimum_size ( Size2 ( 100 , 0 ) * EDSCALE ) ;
// Prevent visible spacing between frame time labels.
top_right_vbox - > add_theme_constant_override ( " separation " , 0 ) ;
2019-10-23 11:46:26 +02:00
rotation_control = memnew ( ViewportRotationControl ) ;
rotation_control - > set_custom_minimum_size ( Size2 ( 80 , 80 ) * EDSCALE ) ;
rotation_control - > set_h_size_flags ( SIZE_SHRINK_END ) ;
rotation_control - > set_viewport ( this ) ;
top_right_vbox - > add_child ( rotation_control ) ;
2020-12-26 20:21:07 +01:00
// Individual Labels are used to allow coloring each label with its own color.
cpu_time_label = memnew ( Label ) ;
top_right_vbox - > add_child ( cpu_time_label ) ;
cpu_time_label - > hide ( ) ;
gpu_time_label = memnew ( Label ) ;
top_right_vbox - > add_child ( gpu_time_label ) ;
gpu_time_label - > hide ( ) ;
2019-10-23 11:46:26 +02:00
fps_label = memnew ( Label ) ;
top_right_vbox - > add_child ( fps_label ) ;
fps_label - > hide ( ) ;
surface - > add_child ( top_right_vbox ) ;
2020-04-02 01:20:12 +02:00
accept = nullptr ;
2017-09-02 21:47:16 +02:00
2017-05-07 22:59:05 +02:00
freelook_active = false ;
2017-10-08 02:43:57 +02:00
freelook_speed = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_base_speed " ) ;
2014-10-03 05:10:51 +02:00
2017-03-05 16:44:50 +01:00
selection_menu = memnew ( PopupMenu ) ;
2015-11-04 22:39:07 +01:00
add_child ( selection_menu ) ;
2020-03-12 13:37:40 +01:00
selection_menu - > set_min_size ( Size2 ( 100 , 0 ) * EDSCALE ) ;
2020-03-26 22:49:16 +01:00
selection_menu - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditorViewport : : _selection_result_pressed ) ) ;
selection_menu - > connect ( " popup_hide " , callable_mp ( this , & Node3DEditorViewport : : _selection_menu_hide ) ) ;
2015-11-04 22:39:07 +01:00
2017-03-05 16:44:50 +01:00
if ( p_index = = 0 ) {
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) , true ) ;
2014-10-03 05:10:51 +02:00
viewport - > set_as_audio_listener ( true ) ;
}
2017-08-04 15:46:22 +02:00
name = " " ;
2015-03-21 21:47:21 +01:00
_update_name ( ) ;
2020-03-26 22:49:16 +01:00
EditorSettings : : get_singleton ( ) - > connect ( " settings_changed " , callable_mp ( this , & Node3DEditorViewport : : update_transform_gizmo_view ) ) ;
2014-02-10 02:10:30 +01:00
}
2021-01-04 10:06:46 +01:00
Node3DEditorViewport : : ~ Node3DEditorViewport ( ) {
memdelete ( frame_time_gradient ) ;
}
2017-06-11 16:29:27 +02:00
//////////////////////////////////////////////////////////////
2020-03-26 22:49:16 +01:00
void Node3DEditorViewportContainer : : _gui_input ( const Ref < InputEvent > & p_event ) {
2017-06-11 16:29:27 +02:00
Ref < InputEventMouseButton > mb = p_event ;
2018-08-25 08:47:04 +02:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = BUTTON_LEFT ) {
if ( mb - > is_pressed ( ) ) {
Vector2 size = get_size ( ) ;
2017-06-11 16:29:27 +02:00
2020-03-12 13:37:40 +01:00
int h_sep = get_theme_constant ( " separation " , " HSplitContainer " ) ;
int v_sep = get_theme_constant ( " separation " , " VSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
dragging_h = mb - > get_position ( ) . x > ( mid_w - h_sep / 2 ) & & mb - > get_position ( ) . x < ( mid_w + h_sep / 2 ) ;
dragging_v = mb - > get_position ( ) . y > ( mid_h - v_sep / 2 ) & & mb - > get_position ( ) . y < ( mid_h + v_sep / 2 ) ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
drag_begin_pos = mb - > get_position ( ) ;
drag_begin_ratio . x = ratio_h ;
drag_begin_ratio . y = ratio_v ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
dragging_h = false ;
dragging_v = false ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
} break ;
case VIEW_USE_2_VIEWPORTS : {
dragging_h = false ;
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
} break ;
case VIEW_USE_2_VIEWPORTS_ALT : {
2017-06-11 16:29:27 +02:00
dragging_v = false ;
2018-08-25 08:47:04 +02:00
} break ;
case VIEW_USE_3_VIEWPORTS :
case VIEW_USE_3_VIEWPORTS_ALT :
case VIEW_USE_4_VIEWPORTS : {
// Do nothing.
2017-06-11 16:29:27 +02:00
2018-08-25 08:47:04 +02:00
} break ;
}
} else {
dragging_h = false ;
dragging_v = false ;
2017-06-11 16:29:27 +02:00
}
}
Ref < InputEventMouseMotion > mm = p_event ;
2018-08-25 08:47:04 +02:00
if ( mm . is_valid ( ) ) {
if ( view = = VIEW_USE_3_VIEWPORTS | | view = = VIEW_USE_3_VIEWPORTS_ALT | | view = = VIEW_USE_4_VIEWPORTS ) {
Vector2 size = get_size ( ) ;
2020-03-12 13:37:40 +01:00
int h_sep = get_theme_constant ( " separation " , " HSplitContainer " ) ;
int v_sep = get_theme_constant ( " separation " , " VSplitContainer " ) ;
2018-08-25 08:47:04 +02:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
bool was_hovering_h = hovering_h ;
bool was_hovering_v = hovering_v ;
hovering_h = mm - > get_position ( ) . x > ( mid_w - h_sep / 2 ) & & mm - > get_position ( ) . x < ( mid_w + h_sep / 2 ) ;
hovering_v = mm - > get_position ( ) . y > ( mid_h - v_sep / 2 ) & & mm - > get_position ( ) . y < ( mid_h + v_sep / 2 ) ;
if ( was_hovering_h ! = hovering_h | | was_hovering_v ! = hovering_v ) {
update ( ) ;
}
}
2017-06-11 16:29:27 +02:00
if ( dragging_h ) {
float new_ratio = drag_begin_ratio . x + ( mm - > get_position ( ) . x - drag_begin_pos . x ) / get_size ( ) . width ;
new_ratio = CLAMP ( new_ratio , 40 / get_size ( ) . width , ( get_size ( ) . width - 40 ) / get_size ( ) . width ) ;
ratio_h = new_ratio ;
queue_sort ( ) ;
update ( ) ;
}
if ( dragging_v ) {
float new_ratio = drag_begin_ratio . y + ( mm - > get_position ( ) . y - drag_begin_pos . y ) / get_size ( ) . height ;
new_ratio = CLAMP ( new_ratio , 40 / get_size ( ) . height , ( get_size ( ) . height - 40 ) / get_size ( ) . height ) ;
ratio_v = new_ratio ;
queue_sort ( ) ;
update ( ) ;
}
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewportContainer : : _notification ( int p_what ) {
2017-06-11 16:29:27 +02:00
if ( p_what = = NOTIFICATION_MOUSE_ENTER | | p_what = = NOTIFICATION_MOUSE_EXIT ) {
mouseover = ( p_what = = NOTIFICATION_MOUSE_ENTER ) ;
update ( ) ;
}
if ( p_what = = NOTIFICATION_DRAW & & mouseover ) {
2020-03-12 13:37:40 +01:00
Ref < Texture2D > h_grabber = get_theme_icon ( " grabber " , " HSplitContainer " ) ;
Ref < Texture2D > v_grabber = get_theme_icon ( " grabber " , " VSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
2020-03-12 13:37:40 +01:00
Ref < Texture2D > hdiag_grabber = get_theme_icon ( " GuiViewportHdiagsplitter " , " EditorIcons " ) ;
Ref < Texture2D > vdiag_grabber = get_theme_icon ( " GuiViewportVdiagsplitter " , " EditorIcons " ) ;
Ref < Texture2D > vh_grabber = get_theme_icon ( " GuiViewportVhsplitter " , " EditorIcons " ) ;
2018-08-25 08:47:04 +02:00
2017-06-11 16:29:27 +02:00
Vector2 size = get_size ( ) ;
2020-03-12 13:37:40 +01:00
int h_sep = get_theme_constant ( " separation " , " HSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
2020-03-12 13:37:40 +01:00
int v_sep = get_theme_constant ( " separation " , " VSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
int size_left = mid_w - h_sep / 2 ;
int size_bottom = size . height - mid_h - v_sep / 2 ;
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
2018-08-25 08:47:04 +02:00
// Nothing to show.
2017-06-11 16:29:27 +02:00
} break ;
case VIEW_USE_2_VIEWPORTS : {
draw_texture ( v_grabber , Vector2 ( ( size . width - v_grabber - > get_width ( ) ) / 2 , mid_h - v_grabber - > get_height ( ) / 2 ) ) ;
2018-08-25 08:47:04 +02:00
set_default_cursor_shape ( CURSOR_VSPLIT ) ;
2017-06-11 16:29:27 +02:00
} break ;
case VIEW_USE_2_VIEWPORTS_ALT : {
draw_texture ( h_grabber , Vector2 ( mid_w - h_grabber - > get_width ( ) / 2 , ( size . height - h_grabber - > get_height ( ) ) / 2 ) ) ;
2018-08-25 08:47:04 +02:00
set_default_cursor_shape ( CURSOR_HSPLIT ) ;
2017-06-11 16:29:27 +02:00
} break ;
case VIEW_USE_3_VIEWPORTS : {
2018-08-25 08:47:04 +02:00
if ( ( hovering_v & & hovering_h & & ! dragging_v & & ! dragging_h ) | | ( dragging_v & & dragging_h ) ) {
draw_texture ( hdiag_grabber , Vector2 ( mid_w - hdiag_grabber - > get_width ( ) / 2 , mid_h - v_grabber - > get_height ( ) / 4 ) ) ;
set_default_cursor_shape ( CURSOR_DRAG ) ;
} else if ( ( hovering_v & & ! dragging_h ) | | dragging_v ) {
draw_texture ( v_grabber , Vector2 ( ( size . width - v_grabber - > get_width ( ) ) / 2 , mid_h - v_grabber - > get_height ( ) / 2 ) ) ;
set_default_cursor_shape ( CURSOR_VSPLIT ) ;
} else if ( hovering_h | | dragging_h ) {
draw_texture ( h_grabber , Vector2 ( mid_w - h_grabber - > get_width ( ) / 2 , mid_h + v_grabber - > get_height ( ) / 2 + ( size_bottom - h_grabber - > get_height ( ) ) / 2 ) ) ;
set_default_cursor_shape ( CURSOR_HSPLIT ) ;
}
2017-06-11 16:29:27 +02:00
} break ;
case VIEW_USE_3_VIEWPORTS_ALT : {
2018-08-25 08:47:04 +02:00
if ( ( hovering_v & & hovering_h & & ! dragging_v & & ! dragging_h ) | | ( dragging_v & & dragging_h ) ) {
draw_texture ( vdiag_grabber , Vector2 ( mid_w - vdiag_grabber - > get_width ( ) + v_grabber - > get_height ( ) / 4 , mid_h - vdiag_grabber - > get_height ( ) / 2 ) ) ;
set_default_cursor_shape ( CURSOR_DRAG ) ;
} else if ( ( hovering_v & & ! dragging_h ) | | dragging_v ) {
draw_texture ( v_grabber , Vector2 ( ( size_left - v_grabber - > get_width ( ) ) / 2 , mid_h - v_grabber - > get_height ( ) / 2 ) ) ;
set_default_cursor_shape ( CURSOR_VSPLIT ) ;
} else if ( hovering_h | | dragging_h ) {
draw_texture ( h_grabber , Vector2 ( mid_w - h_grabber - > get_width ( ) / 2 , ( size . height - h_grabber - > get_height ( ) ) / 2 ) ) ;
set_default_cursor_shape ( CURSOR_HSPLIT ) ;
}
2017-06-11 16:29:27 +02:00
} break ;
case VIEW_USE_4_VIEWPORTS : {
Vector2 half ( mid_w , mid_h ) ;
2018-08-25 08:47:04 +02:00
if ( ( hovering_v & & hovering_h & & ! dragging_v & & ! dragging_h ) | | ( dragging_v & & dragging_h ) ) {
draw_texture ( vh_grabber , half - vh_grabber - > get_size ( ) / 2.0 ) ;
set_default_cursor_shape ( CURSOR_DRAG ) ;
} else if ( ( hovering_v & & ! dragging_h ) | | dragging_v ) {
draw_texture ( v_grabber , half - v_grabber - > get_size ( ) / 2.0 ) ;
set_default_cursor_shape ( CURSOR_VSPLIT ) ;
} else if ( hovering_h | | dragging_h ) {
draw_texture ( h_grabber , half - h_grabber - > get_size ( ) / 2.0 ) ;
set_default_cursor_shape ( CURSOR_HSPLIT ) ;
}
2017-06-11 16:29:27 +02:00
} break ;
}
}
if ( p_what = = NOTIFICATION_SORT_CHILDREN ) {
2020-03-26 22:49:16 +01:00
Node3DEditorViewport * viewports [ 4 ] ;
2017-06-11 16:29:27 +02:00
int vc = 0 ;
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
2020-03-26 22:49:16 +01:00
viewports [ vc ] = Object : : cast_to < Node3DEditorViewport > ( get_child ( i ) ) ;
2017-06-11 16:29:27 +02:00
if ( viewports [ vc ] ) {
vc + + ;
}
}
ERR_FAIL_COND ( vc ! = 4 ) ;
Size2 size = get_size ( ) ;
if ( size . x < 10 | | size . y < 10 ) {
for ( int i = 0 ; i < 4 ; i + + ) {
viewports [ i ] - > hide ( ) ;
}
return ;
}
2020-03-12 13:37:40 +01:00
int h_sep = get_theme_constant ( " separation " , " HSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
2020-03-12 13:37:40 +01:00
int v_sep = get_theme_constant ( " separation " , " VSplitContainer " ) ;
2017-06-11 16:29:27 +02:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
int size_left = mid_w - h_sep / 2 ;
int size_right = size . width - mid_w - h_sep / 2 ;
int size_top = mid_h - v_sep / 2 ;
int size_bottom = size . height - mid_h - v_sep / 2 ;
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
2018-09-30 19:09:31 +02:00
viewports [ 0 ] - > show ( ) ;
2017-06-11 16:29:27 +02:00
for ( int i = 1 ; i < 4 ; i + + ) {
viewports [ i ] - > hide ( ) ;
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , size ) ) ;
} break ;
case VIEW_USE_2_VIEWPORTS : {
2018-09-30 19:09:31 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( i = = 1 | | i = = 3 ) {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > hide ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-06-11 16:29:27 +02:00
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , Vector2 ( size . width , size_top ) ) ) ;
fit_child_in_rect ( viewports [ 2 ] , Rect2 ( Vector2 ( 0 , mid_h + v_sep / 2 ) , Vector2 ( size . width , size_bottom ) ) ) ;
} break ;
case VIEW_USE_2_VIEWPORTS_ALT : {
2018-09-30 19:09:31 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( i = = 1 | | i = = 3 ) {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > hide ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-06-11 16:29:27 +02:00
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , Vector2 ( size_left , size . height ) ) ) ;
fit_child_in_rect ( viewports [ 2 ] , Rect2 ( Vector2 ( mid_w + h_sep / 2 , 0 ) , Vector2 ( size_right , size . height ) ) ) ;
} break ;
case VIEW_USE_3_VIEWPORTS : {
2018-09-30 19:09:31 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( i = = 1 ) {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > hide ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-06-11 16:29:27 +02:00
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , Vector2 ( size . width , size_top ) ) ) ;
fit_child_in_rect ( viewports [ 2 ] , Rect2 ( Vector2 ( 0 , mid_h + v_sep / 2 ) , Vector2 ( size_left , size_bottom ) ) ) ;
fit_child_in_rect ( viewports [ 3 ] , Rect2 ( Vector2 ( mid_w + h_sep / 2 , mid_h + v_sep / 2 ) , Vector2 ( size_right , size_bottom ) ) ) ;
} break ;
case VIEW_USE_3_VIEWPORTS_ALT : {
2018-09-30 19:09:31 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( i = = 1 ) {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > hide ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2017-06-11 16:29:27 +02:00
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , Vector2 ( size_left , size_top ) ) ) ;
fit_child_in_rect ( viewports [ 2 ] , Rect2 ( Vector2 ( 0 , mid_h + v_sep / 2 ) , Vector2 ( size_left , size_bottom ) ) ) ;
fit_child_in_rect ( viewports [ 3 ] , Rect2 ( Vector2 ( mid_w + h_sep / 2 , 0 ) , Vector2 ( size_right , size . height ) ) ) ;
} break ;
case VIEW_USE_4_VIEWPORTS : {
2018-09-30 19:09:31 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
2017-06-11 16:29:27 +02:00
viewports [ i ] - > show ( ) ;
}
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , Vector2 ( size_left , size_top ) ) ) ;
fit_child_in_rect ( viewports [ 1 ] , Rect2 ( Vector2 ( mid_w + h_sep / 2 , 0 ) , Vector2 ( size_right , size_top ) ) ) ;
fit_child_in_rect ( viewports [ 2 ] , Rect2 ( Vector2 ( 0 , mid_h + v_sep / 2 ) , Vector2 ( size_left , size_bottom ) ) ) ;
fit_child_in_rect ( viewports [ 3 ] , Rect2 ( Vector2 ( mid_w + h_sep / 2 , mid_h + v_sep / 2 ) , Vector2 ( size_right , size_bottom ) ) ) ;
} break ;
}
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewportContainer : : set_view ( View p_view ) {
2017-06-11 16:29:27 +02:00
view = p_view ;
queue_sort ( ) ;
}
2020-03-26 22:49:16 +01:00
Node3DEditorViewportContainer : : View Node3DEditorViewportContainer : : get_view ( ) {
2017-06-11 16:29:27 +02:00
return view ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorViewportContainer : : _bind_methods ( ) {
ClassDB : : bind_method ( " _gui_input " , & Node3DEditorViewportContainer : : _gui_input ) ;
2017-06-11 16:29:27 +02:00
}
2020-03-26 22:49:16 +01:00
Node3DEditorViewportContainer : : Node3DEditorViewportContainer ( ) {
2018-08-25 08:47:04 +02:00
set_clip_contents ( true ) ;
2017-06-11 16:29:27 +02:00
view = VIEW_USE_1_VIEWPORT ;
mouseover = false ;
ratio_h = 0.5 ;
ratio_v = 0.5 ;
2018-08-25 08:47:04 +02:00
hovering_v = false ;
hovering_h = false ;
2017-06-11 16:29:27 +02:00
dragging_v = false ;
dragging_h = false ;
}
///////////////////////////////////////////////////////////////////
2020-04-02 01:20:12 +02:00
Node3DEditor * Node3DEditor : : singleton = nullptr ;
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem : : ~ Node3DEditorSelectedItem ( ) {
2020-05-14 16:41:43 +02:00
if ( sbox_instance . is_valid ( ) ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( sbox_instance ) ;
2020-05-14 16:41:43 +02:00
}
2020-07-04 00:11:56 +02:00
if ( sbox_instance_xray . is_valid ( ) ) {
RenderingServer : : get_singleton ( ) - > free ( sbox_instance_xray ) ;
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : select_gizmo_highlight_axis ( int p_axis ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2019-08-01 14:23:29 +02:00
move_gizmo [ i ] - > surface_set_material ( 0 , i = = p_axis ? gizmo_color_hl [ i ] : gizmo_color [ i ] ) ;
move_plane_gizmo [ i ] - > surface_set_material ( 0 , ( i + 6 ) = = p_axis ? plane_gizmo_color_hl [ i ] : plane_gizmo_color [ i ] ) ;
2020-09-13 18:22:51 +02:00
rotate_gizmo [ i ] - > surface_set_material ( 0 , ( i + 3 ) = = p_axis ? rotate_gizmo_color_hl [ i ] : rotate_gizmo_color [ i ] ) ;
2019-08-01 14:23:29 +02:00
scale_gizmo [ i ] - > surface_set_material ( 0 , ( i + 9 ) = = p_axis ? gizmo_color_hl [ i ] : gizmo_color [ i ] ) ;
scale_plane_gizmo [ i ] - > surface_set_material ( 0 , ( i + 12 ) = = p_axis ? plane_gizmo_color_hl [ i ] : plane_gizmo_color [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : update_transform_gizmo ( ) {
2017-03-05 16:44:50 +01:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2017-11-17 03:09:00 +01:00
AABB center ;
2017-03-05 16:44:50 +01:00
bool first = true ;
2014-02-10 02:10:30 +01:00
2017-01-11 04:52:51 +01:00
Basis gizmo_basis ;
2017-09-21 23:11:56 +02:00
bool local_gizmo_coords = are_local_coords_enabled ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-10-03 18:49:32 +02:00
Transform xf = se - > sp - > get_global_gizmo_transform ( ) ;
2014-02-10 02:10:30 +01:00
if ( first ) {
2017-06-06 20:33:51 +02:00
center . position = xf . origin ;
2017-03-05 16:44:50 +01:00
first = false ;
2014-02-10 02:10:30 +01:00
if ( local_gizmo_coords ) {
2017-03-05 16:44:50 +01:00
gizmo_basis = xf . basis ;
2014-02-10 02:10:30 +01:00
gizmo_basis . orthonormalize ( ) ;
}
} else {
center . expand_to ( xf . origin ) ;
2017-03-05 16:44:50 +01:00
gizmo_basis = Basis ( ) ;
2014-02-10 02:10:30 +01:00
}
}
2017-06-06 20:33:51 +02:00
Vector3 pcenter = center . position + center . size * 0.5 ;
2017-03-05 16:44:50 +01:00
gizmo . visible = ! first ;
gizmo . transform . origin = pcenter ;
gizmo . transform . basis = gizmo_basis ;
2014-02-10 02:10:30 +01:00
2017-08-31 23:30:35 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-05-05 03:50:23 +02:00
viewports [ i ] - > update_transform_gizmo_view ( ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-11-22 22:29:27 +01:00
void _update_all_gizmos ( Node * p_node ) {
for ( int i = p_node - > get_child_count ( ) - 1 ; 0 < = i ; - - i ) {
2020-03-26 22:49:16 +01:00
Node3D * spatial_node = Object : : cast_to < Node3D > ( p_node - > get_child ( i ) ) ;
2017-11-22 22:29:27 +01:00
if ( spatial_node ) {
spatial_node - > update_gizmo ( ) ;
}
_update_all_gizmos ( p_node - > get_child ( i ) ) ;
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : update_all_gizmos ( Node * p_node ) {
2019-09-03 12:42:34 +02:00
if ( ! p_node ) {
p_node = SceneTree : : get_singleton ( ) - > get_root ( ) ;
}
2018-09-02 22:31:03 +02:00
_update_all_gizmos ( p_node ) ;
2017-11-22 22:29:27 +01:00
}
2020-03-26 22:49:16 +01:00
Object * Node3DEditor : : _get_editor_data ( Object * p_what ) {
Node3D * sp = Object : : cast_to < Node3D > ( p_what ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2020-04-02 01:20:12 +02:00
return nullptr ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * si = memnew ( Node3DEditorSelectedItem ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
si - > sp = sp ;
2020-07-04 00:11:56 +02:00
si - > sbox_instance = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2020-11-26 20:00:03 +01:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance , 1 < < Node3DEditorViewport : : MISC_TOOL_LAYER ) ;
2020-07-04 00:11:56 +02:00
si - > sbox_instance_xray = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box_xray - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance_xray ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2020-11-26 20:00:03 +01:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance_xray , 1 < < Node3DEditorViewport : : MISC_TOOL_LAYER ) ;
2014-02-10 02:10:30 +01:00
return si ;
}
2020-07-04 00:11:56 +02:00
void Node3DEditor : : _generate_selection_boxes ( ) {
// Use two AABBs to create the illusion of a slightly thicker line.
2017-11-17 03:09:00 +01:00
AABB aabb ( Vector3 ( ) , Vector3 ( 1 , 1 , 1 ) ) ;
2020-07-04 00:11:56 +02:00
AABB aabb_offset ( Vector3 ( ) , Vector3 ( 1 , 1 , 1 ) ) ;
// Grow the bounding boxes slightly to avoid Z-fighting with the mesh's edges.
aabb . grow_by ( 0.005 ) ;
aabb_offset . grow_by ( 0.01 ) ;
// Create a x-ray (visible through solid surfaces) and standard version of the selection box.
// Both will be drawn at the same position, but with different opacity.
// This lets the user see where the selection is while still having a sense of depth.
2017-03-05 16:44:50 +01:00
Ref < SurfaceTool > st = memnew ( SurfaceTool ) ;
2020-07-04 00:11:56 +02:00
Ref < SurfaceTool > st_xray = memnew ( SurfaceTool ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
st - > begin ( Mesh : : PRIMITIVE_LINES ) ;
2020-07-04 00:11:56 +02:00
st_xray - > begin ( Mesh : : PRIMITIVE_LINES ) ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
st - > add_vertex ( a ) ;
2020-07-04 00:11:56 +02:00
st - > add_vertex ( b ) ;
st_xray - > add_vertex ( a ) ;
st_xray - > add_vertex ( b ) ;
}
2014-02-10 02:10:30 +01:00
2020-07-04 00:11:56 +02:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb_offset . get_edge ( i , a , b ) ;
st - > add_vertex ( a ) ;
2014-02-10 02:10:30 +01:00
st - > add_vertex ( b ) ;
2020-07-04 00:11:56 +02:00
st_xray - > add_vertex ( a ) ;
st_xray - > add_vertex ( b ) ;
2014-02-10 02:10:30 +01:00
}
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2020-12-29 07:35:59 +01:00
const Color selection_box_color = EDITOR_GET ( " editors/3d/selection_box_color " ) ;
mat - > set_albedo ( selection_box_color ) ;
2019-09-15 06:01:52 +02:00
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2014-02-10 02:10:30 +01:00
st - > set_material ( mat ) ;
selection_box = st - > commit ( ) ;
2020-07-04 00:11:56 +02:00
Ref < StandardMaterial3D > mat_xray = memnew ( StandardMaterial3D ) ;
mat_xray - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
mat_xray - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_DEPTH_TEST , true ) ;
2020-12-29 07:35:59 +01:00
mat_xray - > set_albedo ( selection_box_color * Color ( 1 , 1 , 1 , 0.15 ) ) ;
2020-07-04 00:11:56 +02:00
mat_xray - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
st_xray - > set_material ( mat_xray ) ;
selection_box_xray = st_xray - > commit ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Dictionary Node3DEditor : : get_state ( ) const {
2014-02-10 02:10:30 +01:00
Dictionary d ;
2017-03-05 16:44:50 +01:00
d [ " snap_enabled " ] = snap_enabled ;
d [ " translate_snap " ] = get_translate_snap ( ) ;
d [ " rotate_snap " ] = get_rotate_snap ( ) ;
d [ " scale_snap " ] = get_scale_snap ( ) ;
2017-11-18 19:51:37 +01:00
d [ " local_coords " ] = tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > is_pressed ( ) ;
2017-03-05 16:44:50 +01:00
int vc = 0 ;
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 1 ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 2 ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 3 ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 4 ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 5 ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ) ) {
2017-03-05 16:44:50 +01:00
vc = 6 ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
d [ " viewport_mode " ] = vc ;
2014-02-10 02:10:30 +01:00
Array vpdata ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
vpdata . push_back ( viewports [ i ] - > get_state ( ) ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
d [ " viewports " ] = vpdata ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
d [ " show_grid " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_GRID ) ) ;
d [ " show_origin " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_ORIGIN ) ) ;
d [ " fov " ] = get_fov ( ) ;
d [ " znear " ] = get_znear ( ) ;
d [ " zfar " ] = get_zfar ( ) ;
2014-02-10 02:10:30 +01:00
2018-07-25 00:08:49 +02:00
Dictionary gizmos_status ;
2019-03-12 00:30:50 +01:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2018-08-11 23:07:00 +02:00
int state = gizmos_menu - > get_item_state ( gizmos_menu - > get_item_index ( i ) ) ;
2019-03-12 00:30:50 +01:00
String name = gizmo_plugins_by_name [ i ] - > get_name ( ) ;
2018-08-11 23:07:00 +02:00
gizmos_status [ name ] = state ;
2018-07-25 00:08:49 +02:00
}
d [ " gizmos_status " ] = gizmos_status ;
2014-02-10 02:10:30 +01:00
return d ;
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
void Node3DEditor : : set_state ( const Dictionary & p_state ) {
2014-02-10 02:10:30 +01:00
Dictionary d = p_state ;
2016-01-10 21:59:12 +01:00
if ( d . has ( " snap_enabled " ) ) {
2017-03-05 16:44:50 +01:00
snap_enabled = d [ " snap_enabled " ] ;
2018-01-10 21:22:49 +01:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_pressed ( d [ " snap_enabled " ] ) ;
2016-01-10 21:59:12 +01:00
}
2020-05-14 16:41:43 +02:00
if ( d . has ( " translate_snap " ) ) {
2020-03-08 20:31:11 +01:00
snap_translate_value = d [ " translate_snap " ] ;
2020-05-14 16:41:43 +02:00
}
2016-01-10 21:59:12 +01:00
2020-05-14 16:41:43 +02:00
if ( d . has ( " rotate_snap " ) ) {
2020-03-08 20:31:11 +01:00
snap_rotate_value = d [ " rotate_snap " ] ;
2020-05-14 16:41:43 +02:00
}
2016-01-10 21:59:12 +01:00
2020-05-14 16:41:43 +02:00
if ( d . has ( " scale_snap " ) ) {
2020-03-08 20:31:11 +01:00
snap_scale_value = d [ " scale_snap " ] ;
2020-05-14 16:41:43 +02:00
}
2020-03-08 20:31:11 +01:00
_snap_update ( ) ;
2016-01-10 21:59:12 +01:00
if ( d . has ( " local_coords " ) ) {
2017-11-18 19:51:37 +01:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_pressed ( d [ " local_coords " ] ) ;
2016-01-10 21:59:12 +01:00
update_transform_gizmo ( ) ;
}
2016-01-11 14:35:11 +01:00
if ( d . has ( " viewport_mode " ) ) {
int vc = d [ " viewport_mode " ] ;
2020-05-14 16:41:43 +02:00
if ( vc = = 1 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2020-05-14 16:41:43 +02:00
} else if ( vc = = 2 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
} else if ( vc = = 3 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
} else if ( vc = = 4 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_4_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
} else if ( vc = = 5 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
2020-05-14 16:41:43 +02:00
} else if ( vc = = 6 ) {
2016-01-11 14:35:11 +01:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
2020-05-14 16:41:43 +02:00
}
2016-01-11 14:35:11 +01:00
}
2014-02-10 02:10:30 +01:00
2016-01-11 14:35:11 +01:00
if ( d . has ( " viewports " ) ) {
Array vp = d [ " viewports " ] ;
2019-03-12 03:17:30 +01:00
uint32_t vp_size = static_cast < uint32_t > ( vp . size ( ) ) ;
if ( vp_size > VIEWPORTS_COUNT ) {
2019-06-11 14:49:34 +02:00
WARN_PRINT ( " Ignoring superfluous viewport settings from spatial editor state. " ) ;
2019-03-12 03:17:30 +01:00
vp_size = VIEWPORTS_COUNT ;
}
2014-02-10 02:10:30 +01:00
2019-03-12 03:17:30 +01:00
for ( uint32_t i = 0 ; i < vp_size ; i + + ) {
2016-01-11 14:35:11 +01:00
viewports [ i ] - > set_state ( vp [ i ] ) ;
}
2014-02-10 02:10:30 +01:00
}
2020-05-14 16:41:43 +02:00
if ( d . has ( " zfar " ) ) {
2017-01-04 05:16:14 +01:00
settings_zfar - > set_value ( float ( d [ " zfar " ] ) ) ;
2020-05-14 16:41:43 +02:00
}
if ( d . has ( " znear " ) ) {
2017-01-04 05:16:14 +01:00
settings_znear - > set_value ( float ( d [ " znear " ] ) ) ;
2020-05-14 16:41:43 +02:00
}
if ( d . has ( " fov " ) ) {
2017-01-04 05:16:14 +01:00
settings_fov - > set_value ( float ( d [ " fov " ] ) ) ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
if ( d . has ( " show_grid " ) ) {
bool use = d [ " show_grid " ] ;
2017-03-05 16:44:50 +01:00
if ( use ! = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_GRID ) ) ) {
2014-07-15 09:06:55 +02:00
_menu_item_pressed ( MENU_VIEW_GRID ) ;
2014-02-10 02:10:30 +01:00
}
}
if ( d . has ( " show_origin " ) ) {
bool use = d [ " show_origin " ] ;
2017-03-05 16:44:50 +01:00
if ( use ! = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_ORIGIN ) ) ) {
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_ORIGIN ) , use ) ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , use ) ;
2014-02-10 02:10:30 +01:00
}
}
2018-07-25 00:08:49 +02:00
if ( d . has ( " gizmos_status " ) ) {
Dictionary gizmos_status = d [ " gizmos_status " ] ;
List < Variant > keys ;
gizmos_status . get_key_list ( & keys ) ;
2019-03-12 00:30:50 +01:00
for ( int j = 0 ; j < gizmo_plugins_by_name . size ( ) ; + + j ) {
2020-05-14 16:41:43 +02:00
if ( ! gizmo_plugins_by_name [ j ] - > can_be_hidden ( ) ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2020-03-26 22:49:16 +01:00
int state = EditorNode3DGizmoPlugin : : VISIBLE ;
2018-09-26 17:38:02 +02:00
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
2020-11-05 03:01:55 +01:00
if ( gizmo_plugins_by_name . write [ j ] - > get_name ( ) = = String ( keys [ i ] ) ) {
2018-08-11 23:07:00 +02:00
state = gizmos_status [ keys [ i ] ] ;
2019-03-12 00:30:50 +01:00
break ;
2018-07-25 00:08:49 +02:00
}
}
2018-08-11 23:07:00 +02:00
2019-03-12 00:30:50 +01:00
gizmo_plugins_by_name . write [ j ] - > set_state ( state ) ;
2018-07-25 00:08:49 +02:00
}
2019-03-12 00:30:50 +01:00
_update_gizmos_menu ( ) ;
2018-07-25 00:08:49 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : edit ( Node3D * p_spatial ) {
2017-03-05 16:44:50 +01:00
if ( p_spatial ! = selected ) {
2014-05-05 03:50:23 +02:00
if ( selected ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = selected - > get_gizmo ( ) ;
2014-05-05 03:50:23 +02:00
if ( seg . is_valid ( ) ) {
seg - > set_selected ( false ) ;
selected - > update_gizmo ( ) ;
}
}
2017-03-05 16:44:50 +01:00
selected = p_spatial ;
over_gizmo_handle = - 1 ;
2014-05-05 03:50:23 +02:00
if ( selected ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg = selected - > get_gizmo ( ) ;
2014-05-05 03:50:23 +02:00
if ( seg . is_valid ( ) ) {
seg - > set_selected ( true ) ;
selected - > update_gizmo ( ) ;
}
}
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _snap_changed ( ) {
2020-07-24 20:07:57 +02:00
snap_translate_value = snap_translate - > get_text ( ) . to_float ( ) ;
snap_rotate_value = snap_rotate - > get_text ( ) . to_float ( ) ;
snap_scale_value = snap_scale - > get_text ( ) . to_float ( ) ;
2020-03-08 20:31:11 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _snap_update ( ) {
2020-03-08 20:31:11 +01:00
snap_translate - > set_text ( String : : num ( snap_translate_value ) ) ;
snap_rotate - > set_text ( String : : num ( snap_rotate_value ) ) ;
snap_scale - > set_text ( String : : num ( snap_scale_value ) ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _xform_dialog_action ( ) {
2014-02-10 02:10:30 +01:00
Transform t ;
//translation
Vector3 scale ;
Vector3 rotate ;
Vector3 translate ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-07-24 20:07:57 +02:00
translate [ i ] = xform_translate [ i ] - > get_text ( ) . to_float ( ) ;
rotate [ i ] = Math : : deg2rad ( xform_rotate [ i ] - > get_text ( ) . to_float ( ) ) ;
scale [ i ] = xform_scale [ i ] - > get_text ( ) . to_float ( ) ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
2017-01-05 18:31:39 +01:00
t . basis . scale ( scale ) ;
t . basis . rotate ( rotate ) ;
2017-03-05 16:44:50 +01:00
t . origin = translate ;
2014-02-10 02:10:30 +01:00
2016-05-04 03:25:37 +02:00
undo_redo - > create_action ( TTR ( " XForm Dialog " ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 16:41:43 +02:00
if ( ! se ) {
2014-02-10 02:10:30 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
bool post = xform_type - > get_selected ( ) > 0 ;
2014-02-10 02:10:30 +01:00
2017-10-03 18:49:32 +02:00
Transform tr = sp - > get_global_gizmo_transform ( ) ;
2020-05-14 16:41:43 +02:00
if ( post ) {
2014-02-10 02:10:30 +01:00
tr = tr * t ;
2020-05-14 16:41:43 +02:00
} else {
2014-02-10 02:10:30 +01:00
tr . basis = t . basis * tr . basis ;
2017-03-05 16:44:50 +01:00
tr . origin + = t . origin ;
2014-02-10 02:10:30 +01:00
}
2017-03-05 16:44:50 +01:00
undo_redo - > add_do_method ( sp , " set_global_transform " , tr ) ;
2017-10-03 18:49:32 +02:00
undo_redo - > add_undo_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
2014-02-10 02:10:30 +01:00
}
undo_redo - > commit_action ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _menu_item_toggled ( bool pressed , int p_option ) {
2017-11-18 19:51:37 +01:00
switch ( p_option ) {
case MENU_TOOL_LOCAL_COORDS : {
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_pressed ( pressed ) ;
update_transform_gizmo ( ) ;
} break ;
case MENU_TOOL_USE_SNAP : {
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_pressed ( pressed ) ;
snap_enabled = pressed ;
} break ;
2019-04-06 22:55:01 +02:00
case MENU_TOOL_OVERRIDE_CAMERA : {
2020-02-07 02:52:05 +01:00
EditorDebuggerNode * const debugger = EditorDebuggerNode : : get_singleton ( ) ;
2019-04-06 22:55:01 +02:00
2020-02-24 06:21:15 +01:00
using Override = EditorDebuggerNode : : CameraOverride ;
2019-04-06 22:55:01 +02:00
if ( pressed ) {
debugger - > set_camera_override ( ( Override ) ( Override : : OVERRIDE_3D_1 + camera_override_viewport_id ) ) ;
} else {
2020-02-24 06:21:15 +01:00
debugger - > set_camera_override ( Override : : OVERRIDE_NONE ) ;
2019-04-06 22:55:01 +02:00
}
} break ;
2017-11-18 19:51:37 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _menu_gizmo_toggled ( int p_option ) {
2018-08-11 23:07:00 +02:00
const int idx = gizmos_menu - > get_item_index ( p_option ) ;
gizmos_menu - > toggle_item_multistate ( idx ) ;
// Change icon
const int state = gizmos_menu - > get_item_state ( idx ) ;
switch ( state ) {
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( " visibility_visible " ) ) ;
2018-08-11 23:07:00 +02:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( " visibility_xray " ) ) ;
2018-08-11 23:07:00 +02:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( " visibility_hidden " ) ) ;
2018-08-11 23:07:00 +02:00
break ;
}
2019-03-12 00:30:50 +01:00
gizmo_plugins_by_name . write [ p_option ] - > set_state ( state ) ;
2018-07-25 00:08:49 +02:00
2018-08-11 23:07:00 +02:00
update_all_gizmos ( ) ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _update_camera_override_button ( bool p_game_running ) {
2019-04-06 22:55:01 +02:00
Button * const button = tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] ;
if ( p_game_running ) {
button - > set_disabled ( false ) ;
2019-11-11 15:46:23 +01:00
button - > set_tooltip ( TTR ( " Game Camera Override \n No game instance running. " ) ) ;
2019-04-06 22:55:01 +02:00
} else {
button - > set_disabled ( true ) ;
button - > set_pressed ( false ) ;
2019-11-11 15:46:23 +01:00
button - > set_tooltip ( TTR ( " Game Camera Override \n Overrides game camera with editor viewport camera. " ) ) ;
2019-04-06 22:55:01 +02:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _update_camera_override_viewport ( Object * p_viewport ) {
Node3DEditorViewport * current_viewport = Object : : cast_to < Node3DEditorViewport > ( p_viewport ) ;
2019-04-06 22:55:01 +02:00
2020-05-14 16:41:43 +02:00
if ( ! current_viewport ) {
2019-04-06 22:55:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-04-06 22:55:01 +02:00
2020-02-07 02:52:05 +01:00
EditorDebuggerNode * const debugger = EditorDebuggerNode : : get_singleton ( ) ;
2019-04-06 22:55:01 +02:00
camera_override_viewport_id = current_viewport - > index ;
2020-02-24 06:21:15 +01:00
if ( debugger - > get_camera_override ( ) > = EditorDebuggerNode : : OVERRIDE_3D_1 ) {
using Override = EditorDebuggerNode : : CameraOverride ;
2019-04-06 22:55:01 +02:00
debugger - > set_camera_override ( ( Override ) ( Override : : OVERRIDE_3D_1 + camera_override_viewport_id ) ) ;
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _menu_item_pressed ( int p_option ) {
2017-03-05 16:44:50 +01:00
switch ( p_option ) {
2014-02-10 02:10:30 +01:00
case MENU_TOOL_SELECT :
case MENU_TOOL_MOVE :
case MENU_TOOL_ROTATE :
2015-12-13 21:16:13 +01:00
case MENU_TOOL_SCALE :
case MENU_TOOL_LIST_SELECT : {
2020-05-14 16:41:43 +02:00
for ( int i = 0 ; i < TOOL_MAX ; i + + ) {
2017-03-05 16:44:50 +01:00
tool_button [ i ] - > set_pressed ( i = = p_option ) ;
2020-05-14 16:41:43 +02:00
}
2017-03-05 16:44:50 +01:00
tool_mode = ( ToolMode ) p_option ;
2014-02-10 02:10:30 +01:00
update_transform_gizmo ( ) ;
} break ;
case MENU_TRANSFORM_CONFIGURE_SNAP : {
2017-03-05 16:44:50 +01:00
snap_dialog - > popup_centered ( Size2 ( 200 , 180 ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_TRANSFORM_DIALOG : {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2014-02-10 02:10:30 +01:00
xform_translate [ i ] - > set_text ( " 0 " ) ;
xform_rotate [ i ] - > set_text ( " 0 " ) ;
xform_scale [ i ] - > set_text ( " 1 " ) ;
}
2017-07-31 15:00:02 +02:00
xform_dialog - > popup_centered ( Size2 ( 320 , 240 ) * EDSCALE ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_USE_1_VIEWPORT : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_1_VIEWPORT ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , false ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_USE_2_VIEWPORTS : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_2_VIEWPORTS ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , false ) ;
2014-10-09 05:06:51 +02:00
} break ;
case MENU_VIEW_USE_2_VIEWPORTS_ALT : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_2_VIEWPORTS_ALT ) ;
2014-10-09 05:06:51 +02:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , false ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_USE_3_VIEWPORTS : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_3_VIEWPORTS ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , false ) ;
2014-10-09 05:06:51 +02:00
} break ;
case MENU_VIEW_USE_3_VIEWPORTS_ALT : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_3_VIEWPORTS_ALT ) ;
2014-10-09 05:06:51 +02:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , true ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_USE_4_VIEWPORTS : {
2020-03-26 22:49:16 +01:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_4_VIEWPORTS ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , true ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , false ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , false ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_ORIGIN : {
2017-03-05 16:44:50 +01:00
bool is_checked = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) ) ;
2014-02-10 02:10:30 +01:00
2018-08-17 23:21:08 +02:00
origin_enabled = ! is_checked ;
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , origin_enabled ) ;
2018-08-17 23:21:08 +02:00
// Update the grid since its appearance depends on whether the origin is enabled
_finish_grid ( ) ;
_init_grid ( ) ;
2014-02-10 02:10:30 +01:00
2018-08-17 23:21:08 +02:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) , origin_enabled ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_GRID : {
2017-03-05 16:44:50 +01:00
bool is_checked = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
grid_enabled = ! is_checked ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; + + i ) {
2014-07-15 07:29:03 +02:00
if ( grid_enable [ i ] ) {
2017-03-05 16:44:50 +01:00
grid_visible [ i ] = grid_enabled ;
2014-07-15 07:29:03 +02:00
}
}
2020-11-19 11:29:37 +01:00
_finish_grid ( ) ;
_init_grid ( ) ;
2014-07-15 07:29:03 +02:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) , grid_enabled ) ;
2014-02-10 02:10:30 +01:00
} break ;
case MENU_VIEW_CAMERA_SETTINGS : {
2017-03-05 16:44:50 +01:00
settings_dialog - > popup_centered ( settings_vbc - > get_combined_minimum_size ( ) + Size2 ( 50 , 50 ) ) ;
2014-02-10 02:10:30 +01:00
} break ;
2018-07-26 08:34:40 +02:00
case MENU_SNAP_TO_FLOOR : {
snap_selected_nodes_to_floor ( ) ;
} break ;
2017-10-23 21:21:15 +02:00
case MENU_LOCK_SELECTED : {
2019-04-26 19:23:50 +02:00
undo_redo - > create_action ( TTR ( " Lock Selected " ) ) ;
2017-10-23 21:21:15 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * spatial = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-06-24 17:09:53 +02:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2017-10-23 21:21:15 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-10-23 21:21:15 +02:00
2020-05-14 16:41:43 +02:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2017-10-23 21:21:15 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-10-23 21:21:15 +02:00
2019-04-26 19:23:50 +02:00
undo_redo - > add_do_method ( spatial , " set_meta " , " _edit_lock_ " , true ) ;
undo_redo - > add_undo_method ( spatial , " remove_meta " , " _edit_lock_ " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " item_lock_status_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " item_lock_status_changed " ) ;
2017-10-23 21:21:15 +02:00
}
2020-06-24 17:09:53 +02:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 19:23:50 +02:00
undo_redo - > commit_action ( ) ;
2017-10-23 21:21:15 +02:00
} break ;
case MENU_UNLOCK_SELECTED : {
2019-04-26 19:23:50 +02:00
undo_redo - > create_action ( TTR ( " Unlock Selected " ) ) ;
2017-10-23 21:21:15 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * spatial = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-06-24 17:09:53 +02:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2017-10-23 21:21:15 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-10-23 21:21:15 +02:00
2020-05-14 16:41:43 +02:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2017-10-23 21:21:15 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-10-23 21:21:15 +02:00
2019-04-26 19:23:50 +02:00
undo_redo - > add_do_method ( spatial , " remove_meta " , " _edit_lock_ " ) ;
undo_redo - > add_undo_method ( spatial , " set_meta " , " _edit_lock_ " , true ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " item_lock_status_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " item_lock_status_changed " ) ;
2017-10-23 21:21:15 +02:00
}
2020-06-24 17:09:53 +02:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 19:23:50 +02:00
undo_redo - > commit_action ( ) ;
2019-04-17 18:24:28 +02:00
} break ;
case MENU_GROUP_SELECTED : {
2019-04-26 19:23:50 +02:00
undo_redo - > create_action ( TTR ( " Group Selected " ) ) ;
2019-04-17 18:24:28 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * spatial = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-06-24 17:09:53 +02:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2019-04-17 18:24:28 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-04-17 18:24:28 +02:00
2020-05-14 16:41:43 +02:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2019-04-17 18:24:28 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-04-17 18:24:28 +02:00
2019-04-26 19:23:50 +02:00
undo_redo - > add_do_method ( spatial , " set_meta " , " _edit_group_ " , true ) ;
undo_redo - > add_undo_method ( spatial , " remove_meta " , " _edit_group_ " ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " item_group_status_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " item_group_status_changed " ) ;
2019-04-17 18:24:28 +02:00
}
2020-06-24 17:09:53 +02:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 19:23:50 +02:00
undo_redo - > commit_action ( ) ;
2019-04-17 18:24:28 +02:00
} break ;
case MENU_UNGROUP_SELECTED : {
2019-04-26 19:23:50 +02:00
undo_redo - > create_action ( TTR ( " Ungroup Selected " ) ) ;
2019-04-17 18:24:28 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * spatial = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2020-06-24 17:09:53 +02:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2019-04-17 18:24:28 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-04-17 18:24:28 +02:00
2020-05-14 16:41:43 +02:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2019-04-17 18:24:28 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-04-17 18:24:28 +02:00
2019-04-26 19:23:50 +02:00
undo_redo - > add_do_method ( spatial , " remove_meta " , " _edit_group_ " ) ;
undo_redo - > add_undo_method ( spatial , " set_meta " , " _edit_group_ " , true ) ;
undo_redo - > add_do_method ( this , " emit_signal " , " item_group_status_changed " ) ;
undo_redo - > add_undo_method ( this , " emit_signal " , " item_group_status_changed " ) ;
2019-04-17 18:24:28 +02:00
}
2020-06-24 17:09:53 +02:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 19:23:50 +02:00
undo_redo - > commit_action ( ) ;
2017-10-23 21:21:15 +02:00
} break ;
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _init_indicators ( ) {
2014-02-10 02:10:30 +01:00
{
2018-09-20 13:27:32 +02:00
origin_enabled = true ;
grid_enabled = true ;
2014-02-10 02:10:30 +01:00
2017-01-14 18:03:38 +01:00
indicator_mat . instance ( ) ;
2019-09-15 06:01:52 +02:00
indicator_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
indicator_mat - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
indicator_mat - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
2019-04-21 12:15:45 +02:00
indicator_mat - > set_transparency ( StandardMaterial3D : : Transparency : : TRANSPARENCY_ALPHA_DEPTH_PRE_PASS ) ;
2016-10-30 01:48:09 +02:00
2014-02-10 02:10:30 +01:00
Vector < Color > origin_colors ;
Vector < Vector3 > origin_points ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2014-02-10 02:10:30 +01:00
Vector3 axis ;
2017-03-05 16:44:50 +01:00
axis [ i ] = 1 ;
2019-08-23 18:14:47 +02:00
Color origin_color ;
switch ( i ) {
case 0 :
2020-03-12 13:37:40 +01:00
origin_color = get_theme_color ( " axis_x_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
case 1 :
2020-03-12 13:37:40 +01:00
origin_color = get_theme_color ( " axis_y_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
case 2 :
2020-03-12 13:37:40 +01:00
origin_color = get_theme_color ( " axis_z_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
default :
origin_color = Color ( ) ;
break ;
}
2017-12-08 23:45:33 +01:00
grid_enable [ i ] = false ;
grid_visible [ i ] = false ;
2014-02-10 02:10:30 +01:00
2019-08-01 14:23:29 +02:00
origin_colors . push_back ( origin_color ) ;
origin_colors . push_back ( origin_color ) ;
2019-04-21 12:15:45 +02:00
origin_colors . push_back ( origin_color ) ;
origin_colors . push_back ( origin_color ) ;
origin_colors . push_back ( origin_color ) ;
origin_colors . push_back ( origin_color ) ;
// To both allow having a large origin size and avoid jitter
// at small scales, we should segment the line into pieces.
// 3 pieces seems to do the trick, and let's use powers of 2.
origin_points . push_back ( axis * 1048576 ) ;
origin_points . push_back ( axis * 1024 ) ;
origin_points . push_back ( axis * 1024 ) ;
origin_points . push_back ( axis * - 1024 ) ;
origin_points . push_back ( axis * - 1024 ) ;
origin_points . push_back ( axis * - 1048576 ) ;
}
grid_enable [ 0 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_xy_plane " ) ;
grid_enable [ 1 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_yz_plane " ) ;
grid_enable [ 2 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_xz_plane " ) ;
grid_visible [ 0 ] = grid_enable [ 0 ] ;
grid_visible [ 1 ] = grid_enable [ 1 ] ;
grid_visible [ 2 ] = grid_enable [ 2 ] ;
2017-03-05 16:44:50 +01:00
2017-12-08 23:45:33 +01:00
_init_grid ( ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
origin = RenderingServer : : get_singleton ( ) - > mesh_create ( ) ;
2014-02-10 02:10:30 +01:00
Array d ;
2020-03-27 19:21:27 +01:00
d . resize ( RS : : ARRAY_MAX ) ;
d [ RenderingServer : : ARRAY_VERTEX ] = origin_points ;
d [ RenderingServer : : ARRAY_COLOR ] = origin_colors ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > mesh_add_surface_from_arrays ( origin , RenderingServer : : PRIMITIVE_LINES , d ) ;
RenderingServer : : get_singleton ( ) - > mesh_surface_set_material ( origin , 0 , indicator_mat - > get_rid ( ) ) ;
2014-02-10 02:10:30 +01:00
2020-04-18 11:00:51 +02:00
origin_instance = RenderingServer : : get_singleton ( ) - > instance_create2 ( origin , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 19:21:27 +01:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( origin_instance , 1 < < Node3DEditorViewport : : GIZMO_GRID_LAYER ) ;
2014-10-16 05:06:34 +02:00
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( origin_instance , RS : : SHADOW_CASTING_SETTING_OFF ) ;
2014-02-10 02:10:30 +01:00
}
{
//move gizmo
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2019-08-23 18:14:47 +02:00
Color col ;
switch ( i ) {
case 0 :
2020-03-12 13:37:40 +01:00
col = get_theme_color ( " axis_x_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
case 1 :
2020-03-12 13:37:40 +01:00
col = get_theme_color ( " axis_y_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
case 2 :
2020-03-12 13:37:40 +01:00
col = get_theme_color ( " axis_z_color " , " Editor " ) ;
2019-08-23 18:14:47 +02:00
break ;
default :
col = Color ( ) ;
break ;
}
2019-08-01 14:23:29 +02:00
col . a = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/manipulator_gizmo_opacity " ) ;
2017-06-07 23:18:55 +02:00
move_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-08-29 03:39:45 +02:00
move_plane_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-06-07 23:18:55 +02:00
rotate_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-09-21 23:11:56 +02:00
scale_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-11-14 23:50:19 +01:00
scale_plane_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2014-02-10 02:10:30 +01:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-09-01 17:56:52 +02:00
mat - > set_on_top_of_alpha ( ) ;
2019-09-15 06:01:52 +02:00
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2016-10-27 16:50:26 +02:00
mat - > set_albedo ( col ) ;
2017-03-05 16:44:50 +01:00
gizmo_color [ i ] = mat ;
2014-02-10 02:10:30 +01:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat_hl = mat - > duplicate ( ) ;
2020-12-18 16:28:12 +01:00
const float brightness = 1.3 ;
const Color albedo = Color ( col . r * brightness , col . g * brightness , col . b * brightness ) ;
mat_hl - > set_albedo ( albedo ) ;
2019-08-01 14:23:29 +02:00
gizmo_color_hl [ i ] = mat_hl ;
2014-02-10 02:10:30 +01:00
Vector3 ivec ;
2017-03-05 16:44:50 +01:00
ivec [ i ] = 1 ;
2014-02-10 02:10:30 +01:00
Vector3 nivec ;
2017-03-05 16:44:50 +01:00
nivec [ ( i + 1 ) % 3 ] = 1 ;
nivec [ ( i + 2 ) % 3 ] = 1 ;
2014-02-10 02:10:30 +01:00
Vector3 ivec2 ;
2017-03-05 16:44:50 +01:00
ivec2 [ ( i + 1 ) % 3 ] = 1 ;
2014-02-10 02:10:30 +01:00
Vector3 ivec3 ;
2017-03-05 16:44:50 +01:00
ivec3 [ ( i + 2 ) % 3 ] = 1 ;
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
//translate
2014-02-10 02:10:30 +01:00
{
2017-03-05 16:44:50 +01:00
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
2014-02-10 02:10:30 +01:00
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2017-09-21 23:11:56 +02:00
// Arrow profile
2017-03-05 16:44:50 +01:00
const int arrow_points = 5 ;
Vector3 arrow [ 5 ] = {
nivec * 0.0 + ivec * 0.0 ,
nivec * 0.01 + ivec * 0.0 ,
2017-09-21 23:11:56 +02:00
nivec * 0.01 + ivec * GIZMO_ARROW_OFFSET ,
nivec * 0.065 + ivec * GIZMO_ARROW_OFFSET ,
nivec * 0.0 + ivec * ( GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE ) ,
2014-02-10 02:10:30 +01:00
} ;
2018-08-09 16:34:18 +02:00
int arrow_sides = 16 ;
2014-02-10 02:10:30 +01:00
2018-08-09 16:34:18 +02:00
for ( int k = 0 ; k < arrow_sides ; k + + ) {
2017-03-05 16:44:50 +01:00
Basis ma ( ivec , Math_PI * 2 * float ( k ) / arrow_sides ) ;
Basis mb ( ivec , Math_PI * 2 * float ( k + 1 ) / arrow_sides ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int j = 0 ; j < arrow_points - 1 ; j + + ) {
Vector3 points [ 4 ] = {
2014-02-10 02:10:30 +01:00
ma . xform ( arrow [ j ] ) ,
mb . xform ( arrow [ j ] ) ,
2017-03-05 16:44:50 +01:00
mb . xform ( arrow [ j + 1 ] ) ,
ma . xform ( arrow [ j + 1 ] ) ,
2014-02-10 02:10:30 +01:00
} ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 1 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 3 ] ) ;
}
}
surftool - > set_material ( mat ) ;
surftool - > commit ( move_gizmo [ i ] ) ;
}
2017-09-21 23:11:56 +02:00
// Plane Translation
2017-08-29 03:39:45 +02:00
{
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
Vector3 vec = ivec2 - ivec3 ;
Vector3 plane [ 4 ] = {
vec * GIZMO_PLANE_DST ,
vec * GIZMO_PLANE_DST + ivec2 * GIZMO_PLANE_SIZE ,
vec * ( GIZMO_PLANE_DST + GIZMO_PLANE_SIZE ) ,
vec * GIZMO_PLANE_DST - ivec3 * GIZMO_PLANE_SIZE
} ;
Basis ma ( ivec , Math_PI / 2 ) ;
Vector3 points [ 4 ] = {
ma . xform ( plane [ 0 ] ) ,
ma . xform ( plane [ 1 ] ) ,
ma . xform ( plane [ 2 ] ) ,
ma . xform ( plane [ 3 ] ) ,
} ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 1 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 3 ] ) ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > plane_mat = memnew ( StandardMaterial3D ) ;
plane_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-09-01 17:56:52 +02:00
plane_mat - > set_on_top_of_alpha ( ) ;
2019-09-15 06:01:52 +02:00
plane_mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
plane_mat - > set_cull_mode ( StandardMaterial3D : : CULL_DISABLED ) ;
2019-08-01 14:23:29 +02:00
plane_mat - > set_albedo ( col ) ;
2017-08-29 03:39:45 +02:00
plane_gizmo_color [ i ] = plane_mat ; // needed, so we can draw planes from both sides
surftool - > set_material ( plane_mat ) ;
surftool - > commit ( move_plane_gizmo [ i ] ) ;
2019-08-01 14:23:29 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > plane_mat_hl = plane_mat - > duplicate ( ) ;
2020-12-18 16:28:12 +01:00
plane_mat_hl - > set_albedo ( albedo ) ;
2019-08-01 14:23:29 +02:00
plane_gizmo_color_hl [ i ] = plane_mat_hl ; // needed, so we can draw planes from both sides
2017-08-29 03:39:45 +02:00
}
2017-09-21 23:11:56 +02:00
// Rotate
2014-02-10 02:10:30 +01:00
{
2017-03-05 16:44:50 +01:00
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
2014-02-10 02:10:30 +01:00
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2020-09-13 18:22:51 +02:00
int n = 128 ; // number of circle segments
int m = 6 ; // number of thickness segments
2014-02-10 02:10:30 +01:00
2020-09-13 18:22:51 +02:00
for ( int j = 0 ; j < n ; + + j ) {
Basis basis = Basis ( ivec , ( Math_PI * 2.0f * j ) / n ) ;
2014-02-10 02:10:30 +01:00
2020-09-13 18:22:51 +02:00
Vector3 vertex = basis . xform ( ivec2 * GIZMO_CIRCLE_SIZE ) ;
2014-02-10 02:10:30 +01:00
2020-09-13 18:22:51 +02:00
for ( int k = 0 ; k < m ; + + k ) {
Vector2 ofs = Vector2 ( Math : : cos ( ( Math_PI * 2.0 * k ) / m ) , Math : : sin ( ( Math_PI * 2.0 * k ) / m ) ) ;
Vector3 normal = ivec * ofs . x + ivec2 * ofs . y ;
2020-12-02 02:40:47 +01:00
surftool - > set_normal ( basis . xform ( normal ) ) ;
2020-09-13 18:22:51 +02:00
surftool - > add_vertex ( vertex ) ;
2014-02-10 02:10:30 +01:00
}
}
2020-09-13 18:22:51 +02:00
for ( int j = 0 ; j < n ; + + j ) {
for ( int k = 0 ; k < m ; + + k ) {
int current_ring = j * m ;
int next_ring = ( ( j + 1 ) % n ) * m ;
int current_segment = k ;
int next_segment = ( k + 1 ) % m ;
surftool - > add_index ( current_ring + next_segment ) ;
surftool - > add_index ( current_ring + current_segment ) ;
surftool - > add_index ( next_ring + current_segment ) ;
surftool - > add_index ( next_ring + current_segment ) ;
surftool - > add_index ( next_ring + next_segment ) ;
surftool - > add_index ( current_ring + next_segment ) ;
}
}
Ref < Shader > rotate_shader = memnew ( Shader ) ;
rotate_shader - > set_code ( " \n "
" shader_type spatial; \n "
" render_mode unshaded, depth_test_disabled; \n "
" uniform vec4 albedo; \n "
" \n "
" mat3 orthonormalize(mat3 m) { \n "
" vec3 x = normalize(m[0]); \n "
" vec3 y = normalize(m[1] - x * dot(x, m[1])); \n "
" vec3 z = m[2] - x * dot(x, m[2]); \n "
" z = normalize(z - y * (dot(y,m[2]))); \n "
" return mat3(x,y,z); \n "
" } \n "
" \n "
" void vertex() { \n "
" mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n "
" vec3 n = mv * VERTEX; \n "
" float orientation = dot(vec3(0,0,-1),n); \n "
" if (orientation <= 0.005) { \n "
" VERTEX += NORMAL*0.02; \n "
" } \n "
" } \n "
" \n "
" void fragment() { \n "
" ALBEDO = albedo.rgb; \n "
" ALPHA = albedo.a; \n "
" } " ) ;
Ref < ShaderMaterial > rotate_mat = memnew ( ShaderMaterial ) ;
rotate_mat - > set_render_priority ( Material : : RENDER_PRIORITY_MAX ) ;
rotate_mat - > set_shader ( rotate_shader ) ;
rotate_mat - > set_shader_param ( " albedo " , col ) ;
rotate_gizmo_color [ i ] = rotate_mat ;
Array arrays = surftool - > commit_to_arrays ( ) ;
rotate_gizmo [ i ] - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , arrays ) ;
rotate_gizmo [ i ] - > surface_set_material ( 0 , rotate_mat ) ;
Ref < ShaderMaterial > rotate_mat_hl = rotate_mat - > duplicate ( ) ;
2020-12-18 16:28:12 +01:00
rotate_mat_hl - > set_shader_param ( " albedo " , albedo ) ;
2020-09-13 18:22:51 +02:00
rotate_gizmo_color_hl [ i ] = rotate_mat_hl ;
if ( i = = 2 ) { // Rotation white outline
Ref < ShaderMaterial > border_mat = rotate_mat - > duplicate ( ) ;
Ref < Shader > border_shader = memnew ( Shader ) ;
border_shader - > set_code ( " \n "
" shader_type spatial; \n "
" render_mode unshaded, depth_test_disabled; \n "
" uniform vec4 albedo; \n "
" \n "
" mat3 orthonormalize(mat3 m) { \n "
" vec3 x = normalize(m[0]); \n "
" vec3 y = normalize(m[1] - x * dot(x, m[1])); \n "
" vec3 z = m[2] - x * dot(x, m[2]); \n "
" z = normalize(z - y * (dot(y,m[2]))); \n "
" return mat3(x,y,z); \n "
" } \n "
" \n "
" void vertex() { \n "
" mat3 mv = orthonormalize(mat3(MODELVIEW_MATRIX)); \n "
" mv = inverse(mv); \n "
" VERTEX += NORMAL*0.008; \n "
" vec3 camera_dir_local = mv * vec3(0,0,1); \n "
" vec3 camera_up_local = mv * vec3(0,1,0); \n "
" mat3 rotation_matrix = mat3(cross(camera_dir_local, camera_up_local), camera_up_local, camera_dir_local); \n "
" VERTEX = rotation_matrix * VERTEX; \n "
" } \n "
" \n "
" void fragment() { \n "
" ALBEDO = albedo.rgb; \n "
" ALPHA = albedo.a; \n "
" } " ) ;
border_mat - > set_shader ( border_shader ) ;
border_mat - > set_shader_param ( " albedo " , Color ( 0.75 , 0.75 , 0.75 , col . a / 3.0 ) ) ;
rotate_gizmo [ 3 ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
rotate_gizmo [ 3 ] - > add_surface_from_arrays ( Mesh : : PRIMITIVE_TRIANGLES , arrays ) ;
rotate_gizmo [ 3 ] - > surface_set_material ( 0 , border_mat ) ;
}
2014-02-10 02:10:30 +01:00
}
2017-09-21 23:11:56 +02:00
// Scale
{
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2014-05-05 03:50:23 +02:00
2017-09-21 23:11:56 +02:00
// Cube arrow profile
const int arrow_points = 6 ;
Vector3 arrow [ 6 ] = {
nivec * 0.0 + ivec * 0.0 ,
nivec * 0.01 + ivec * 0.0 ,
nivec * 0.01 + ivec * 1.0 * GIZMO_SCALE_OFFSET ,
nivec * 0.07 + ivec * 1.0 * GIZMO_SCALE_OFFSET ,
nivec * 0.07 + ivec * 1.11 * GIZMO_SCALE_OFFSET ,
nivec * 0.0 + ivec * 1.11 * GIZMO_SCALE_OFFSET ,
} ;
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
int arrow_sides = 4 ;
for ( int k = 0 ; k < 4 ; k + + ) {
Basis ma ( ivec , Math_PI * 2 * float ( k ) / arrow_sides ) ;
Basis mb ( ivec , Math_PI * 2 * float ( k + 1 ) / arrow_sides ) ;
2014-02-10 02:10:30 +01:00
2017-09-21 23:11:56 +02:00
for ( int j = 0 ; j < arrow_points - 1 ; j + + ) {
Vector3 points [ 4 ] = {
ma . xform ( arrow [ j ] ) ,
mb . xform ( arrow [ j ] ) ,
mb . xform ( arrow [ j + 1 ] ) ,
ma . xform ( arrow [ j + 1 ] ) ,
} ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 1 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 3 ] ) ;
}
}
surftool - > set_material ( mat ) ;
surftool - > commit ( scale_gizmo [ i ] ) ;
}
2017-11-14 23:50:19 +01:00
// Plane Scale
{
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
Vector3 vec = ivec2 - ivec3 ;
Vector3 plane [ 4 ] = {
vec * GIZMO_PLANE_DST ,
vec * GIZMO_PLANE_DST + ivec2 * GIZMO_PLANE_SIZE ,
vec * ( GIZMO_PLANE_DST + GIZMO_PLANE_SIZE ) ,
vec * GIZMO_PLANE_DST - ivec3 * GIZMO_PLANE_SIZE
} ;
Basis ma ( ivec , Math_PI / 2 ) ;
Vector3 points [ 4 ] = {
ma . xform ( plane [ 0 ] ) ,
ma . xform ( plane [ 1 ] ) ,
ma . xform ( plane [ 2 ] ) ,
ma . xform ( plane [ 3 ] ) ,
} ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 1 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 0 ] ) ;
surftool - > add_vertex ( points [ 2 ] ) ;
surftool - > add_vertex ( points [ 3 ] ) ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > plane_mat = memnew ( StandardMaterial3D ) ;
plane_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-11-14 23:50:19 +01:00
plane_mat - > set_on_top_of_alpha ( ) ;
2019-09-15 06:01:52 +02:00
plane_mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
plane_mat - > set_cull_mode ( StandardMaterial3D : : CULL_DISABLED ) ;
2019-08-01 14:23:29 +02:00
plane_mat - > set_albedo ( col ) ;
2017-11-14 23:50:19 +01:00
plane_gizmo_color [ i ] = plane_mat ; // needed, so we can draw planes from both sides
surftool - > set_material ( plane_mat ) ;
surftool - > commit ( scale_plane_gizmo [ i ] ) ;
2019-08-01 14:23:29 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > plane_mat_hl = plane_mat - > duplicate ( ) ;
2020-12-18 16:28:12 +01:00
plane_mat_hl - > set_albedo ( Color ( col . r * 1.3 , col . g * 1.3 , col . b * 1.3 ) ) ;
2019-08-01 14:23:29 +02:00
plane_gizmo_color_hl [ i ] = plane_mat_hl ; // needed, so we can draw planes from both sides
2017-11-14 23:50:19 +01:00
}
2017-09-21 23:11:56 +02:00
}
}
2020-07-04 00:11:56 +02:00
_generate_selection_boxes ( ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _update_gizmos_menu ( ) {
2018-10-29 11:30:28 +01:00
gizmos_menu - > clear ( ) ;
2018-07-25 00:08:49 +02:00
2019-03-12 00:30:50 +01:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; + + i ) {
2020-05-14 16:41:43 +02:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-03-12 00:30:50 +01:00
String plugin_name = gizmo_plugins_by_name [ i ] - > get_name ( ) ;
const int plugin_state = gizmo_plugins_by_name [ i ] - > get_state ( ) ;
2020-07-24 15:14:56 +02:00
gizmos_menu - > add_multistate_item ( plugin_name , 3 , plugin_state , i ) ;
2019-03-12 00:30:50 +01:00
const int idx = gizmos_menu - > get_item_index ( i ) ;
2020-06-07 15:34:01 +02:00
gizmos_menu - > set_item_tooltip (
idx ,
TTR ( " Click to toggle between visibility states. \n \n Open eye: Gizmo is visible. \n Closed eye: Gizmo is hidden. \n Half-open eye: Gizmo is also visible through opaque surfaces ( \" x-ray \" ). " ) ) ;
2019-03-12 00:30:50 +01:00
switch ( plugin_state ) {
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_visible " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_xray " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_hidden " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
}
2018-07-25 00:08:49 +02:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _update_gizmos_menu_theme ( ) {
2019-03-12 00:30:50 +01:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; + + i ) {
2020-05-14 16:41:43 +02:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 12:56:01 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2019-03-12 00:30:50 +01:00
const int plugin_state = gizmo_plugins_by_name [ i ] - > get_state ( ) ;
const int idx = gizmos_menu - > get_item_index ( i ) ;
switch ( plugin_state ) {
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_visible " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_xray " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
2020-03-26 22:49:16 +01:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2020-03-12 13:37:40 +01:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( " visibility_hidden " ) ) ;
2019-03-12 00:30:50 +01:00
break ;
}
2019-02-15 18:32:38 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _init_grid ( ) {
2019-04-21 12:15:45 +02:00
if ( ! grid_enabled ) {
return ;
}
Camera3D * camera = get_editor_viewport ( 0 ) - > camera ;
Vector3 camera_position = camera - > get_translation ( ) ;
if ( camera_position = = Vector3 ( ) ) {
return ; // Camera3D is invalid, don't draw the grid.
}
2020-02-17 22:06:54 +01:00
Vector < Color > grid_colors [ 3 ] ;
Vector < Vector3 > grid_points [ 3 ] ;
2017-12-08 23:45:33 +01:00
2018-04-30 01:43:20 +02:00
Color primary_grid_color = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/primary_grid_color " ) ;
Color secondary_grid_color = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/secondary_grid_color " ) ;
int grid_size = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_size " ) ;
int primary_grid_steps = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/primary_grid_steps " ) ;
2017-12-08 23:45:33 +01:00
2019-04-21 12:15:45 +02:00
// Which grid planes are enabled? Which should we generate?
grid_enable [ 0 ] = grid_visible [ 0 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_xy_plane " ) ;
grid_enable [ 1 ] = grid_visible [ 1 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_yz_plane " ) ;
grid_enable [ 2 ] = grid_visible [ 2 ] = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_xz_plane " ) ;
// Offsets division_level for bigger or smaller grids.
// Default value is -0.2. -1.0 gives Blender-like behavior, 0.5 gives huge grids.
real_t division_level_bias = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_division_level_bias " ) ;
// Default largest grid size is 100m, 10^2 (default value is 2).
int division_level_max = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_division_level_max " ) ;
// Default smallest grid size is 1cm, 10^-2 (default value is -2).
int division_level_min = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/grid_division_level_min " ) ;
ERR_FAIL_COND_MSG ( division_level_max < division_level_min , " The 3D grid's maximum division level cannot be lower than its minimum division level. " ) ;
if ( primary_grid_steps ! = 10 ) { // Log10 of 10 is 1.
// Change of base rule, divide by ln(10).
real_t div = Math : : log ( ( real_t ) primary_grid_steps ) / ( real_t ) 2.302585092994045901094 ;
// Trucation (towards zero) is intentional.
division_level_max = ( int ) ( division_level_max / div ) ;
division_level_min = ( int ) ( division_level_min / div ) ;
}
for ( int a = 0 ; a < 3 ; a + + ) {
if ( ! grid_enable [ a ] ) {
continue ; // If this grid plane is disabled, skip generation.
}
int b = ( a + 1 ) % 3 ;
int c = ( a + 2 ) % 3 ;
real_t division_level = Math : : log ( Math : : abs ( camera_position [ c ] ) ) / Math : : log ( ( double ) primary_grid_steps ) + division_level_bias ;
division_level = CLAMP ( division_level , division_level_min , division_level_max ) ;
real_t division_level_floored = Math : : floor ( division_level ) ;
real_t division_level_decimals = division_level - division_level_floored ;
real_t small_step_size = Math : : pow ( primary_grid_steps , division_level_floored ) ;
real_t large_step_size = small_step_size * primary_grid_steps ;
real_t center_a = large_step_size * ( int ) ( camera_position [ a ] / large_step_size ) ;
real_t center_b = large_step_size * ( int ) ( camera_position [ b ] / large_step_size ) ;
real_t bgn_a = center_a - grid_size * small_step_size ;
real_t end_a = center_a + grid_size * small_step_size ;
real_t bgn_b = center_b - grid_size * small_step_size ;
real_t end_b = center_b + grid_size * small_step_size ;
// In each iteration of this loop, draw one line in each direction (so two lines per loop, in each if statement).
for ( int i = - grid_size ; i < = grid_size ; i + + ) {
Color line_color ;
// Is this a primary line? Set the appropriate color.
if ( i % primary_grid_steps = = 0 ) {
line_color = primary_grid_color . lerp ( secondary_grid_color , division_level_decimals ) ;
} else {
line_color = secondary_grid_color ;
line_color . a = line_color . a * ( 1 - division_level_decimals ) ;
}
// Makes lines farther from the center fade out.
// Due to limitations of lines, any that come near the camera have full opacity always.
// This should eventually be replaced by some kind of "distance fade" system, outside of this function.
// But the effect is still somewhat convincing...
line_color . a * = 1 - ( 1 - division_level_decimals * 0.9 ) * ( Math : : abs ( i / ( float ) grid_size ) ) ;
real_t position_a = center_a + i * small_step_size ;
real_t position_b = center_b + i * small_step_size ;
// Don't draw lines over the origin if it's enabled.
if ( ! ( origin_enabled & & Math : : is_zero_approx ( position_a ) ) ) {
Vector3 line_bgn = Vector3 ( ) ;
Vector3 line_end = Vector3 ( ) ;
line_bgn [ a ] = position_a ;
line_end [ a ] = position_a ;
line_bgn [ b ] = bgn_b ;
line_end [ b ] = end_b ;
grid_points [ c ] . push_back ( line_bgn ) ;
grid_points [ c ] . push_back ( line_end ) ;
grid_colors [ c ] . push_back ( line_color ) ;
grid_colors [ c ] . push_back ( line_color ) ;
2017-12-08 23:45:33 +01:00
}
2019-04-21 12:15:45 +02:00
if ( ! ( origin_enabled & & Math : : is_zero_approx ( position_b ) ) ) {
Vector3 line_bgn = Vector3 ( ) ;
Vector3 line_end = Vector3 ( ) ;
line_bgn [ b ] = position_b ;
line_end [ b ] = position_b ;
line_bgn [ a ] = bgn_a ;
line_end [ a ] = end_a ;
grid_points [ c ] . push_back ( line_bgn ) ;
grid_points [ c ] . push_back ( line_end ) ;
grid_colors [ c ] . push_back ( line_color ) ;
grid_colors [ c ] . push_back ( line_color ) ;
}
2017-12-08 23:45:33 +01:00
}
2019-04-21 12:15:45 +02:00
// Create a mesh from the pushed vector points and colors.
grid [ c ] = RenderingServer : : get_singleton ( ) - > mesh_create ( ) ;
2017-12-08 23:45:33 +01:00
Array d ;
2020-03-27 19:21:27 +01:00
d . resize ( RS : : ARRAY_MAX ) ;
2019-04-21 12:15:45 +02:00
d [ RenderingServer : : ARRAY_VERTEX ] = grid_points [ c ] ;
d [ RenderingServer : : ARRAY_COLOR ] = grid_colors [ c ] ;
RenderingServer : : get_singleton ( ) - > mesh_add_surface_from_arrays ( grid [ c ] , RenderingServer : : PRIMITIVE_LINES , d ) ;
RenderingServer : : get_singleton ( ) - > mesh_surface_set_material ( grid [ c ] , 0 , indicator_mat - > get_rid ( ) ) ;
grid_instance [ c ] = RenderingServer : : get_singleton ( ) - > instance_create2 ( grid [ c ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2017-12-08 23:45:33 +01:00
2019-04-21 12:15:45 +02:00
// Yes, the end of this line is supposed to be a.
RenderingServer : : get_singleton ( ) - > instance_set_visible ( grid_instance [ c ] , grid_visible [ a ] ) ;
RenderingServer : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( grid_instance [ c ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( grid_instance [ c ] , 1 < < Node3DEditorViewport : : GIZMO_GRID_LAYER ) ;
2017-12-08 23:45:33 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _finish_indicators ( ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( origin_instance ) ;
RenderingServer : : get_singleton ( ) - > free ( origin ) ;
2017-12-08 23:45:33 +01:00
_finish_grid ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _finish_grid ( ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > free ( grid_instance [ i ] ) ;
RenderingServer : : get_singleton ( ) - > free ( grid [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
}
2019-04-21 12:15:45 +02:00
void Node3DEditor : : update_grid ( ) {
_finish_grid ( ) ;
_init_grid ( ) ;
}
2020-03-26 22:49:16 +01:00
bool Node3DEditor : : is_any_freelook_active ( ) const {
2017-05-07 22:59:05 +02:00
for ( unsigned int i = 0 ; i < VIEWPORTS_COUNT ; + + i ) {
2020-05-14 16:41:43 +02:00
if ( viewports [ i ] - > is_freelook_active ( ) ) {
2017-05-07 22:59:05 +02:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-05-07 22:59:05 +02:00
}
return false ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _refresh_menu_icons ( ) {
2017-10-23 21:21:15 +02:00
bool all_locked = true ;
2019-04-17 18:24:28 +02:00
bool all_grouped = true ;
2017-10-23 21:21:15 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2020-12-15 13:04:21 +01:00
if ( selection . is_empty ( ) ) {
2017-10-23 21:21:15 +02:00
all_locked = false ;
2019-04-17 18:24:28 +02:00
all_grouped = false ;
2017-10-23 21:21:15 +02:00
} else {
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < Node3D > ( E - > get ( ) ) & & ! Object : : cast_to < Node3D > ( E - > get ( ) ) - > has_meta ( " _edit_lock_ " ) ) {
2017-10-23 21:21:15 +02:00
all_locked = false ;
break ;
}
}
2019-04-17 18:24:28 +02:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
if ( Object : : cast_to < Node3D > ( E - > get ( ) ) & & ! Object : : cast_to < Node3D > ( E - > get ( ) ) - > has_meta ( " _edit_group_ " ) ) {
2019-04-17 18:24:28 +02:00
all_grouped = false ;
break ;
}
}
2017-10-23 21:21:15 +02:00
}
tool_button [ TOOL_LOCK_SELECTED ] - > set_visible ( ! all_locked ) ;
2020-12-15 13:04:21 +01:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_disabled ( selection . is_empty ( ) ) ;
2017-10-23 21:21:15 +02:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_visible ( all_locked ) ;
2019-04-17 18:24:28 +02:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_visible ( ! all_grouped ) ;
2020-12-15 13:04:21 +01:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_disabled ( selection . is_empty ( ) ) ;
2019-04-17 18:24:28 +02:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_visible ( all_grouped ) ;
2017-10-23 21:21:15 +02:00
}
2018-07-26 08:34:40 +02:00
template < typename T >
Set < T * > _get_child_nodes ( Node * parent_node ) {
Set < T * > nodes = Set < T * > ( ) ;
T * node = Node : : cast_to < T > ( parent_node ) ;
if ( node ) {
nodes . insert ( node ) ;
}
for ( int i = 0 ; i < parent_node - > get_child_count ( ) ; i + + ) {
Node * child_node = parent_node - > get_child ( i ) ;
Set < T * > child_nodes = _get_child_nodes < T > ( child_node ) ;
for ( typename Set < T * > : : Element * I = child_nodes . front ( ) ; I ; I = I - > next ( ) ) {
nodes . insert ( I - > get ( ) ) ;
}
}
return nodes ;
}
Set < RID > _get_physics_bodies_rid ( Node * node ) {
Set < RID > rids = Set < RID > ( ) ;
2020-03-26 22:49:16 +01:00
PhysicsBody3D * pb = Node : : cast_to < PhysicsBody3D > ( node ) ;
2018-07-26 08:34:40 +02:00
if ( pb ) {
rids . insert ( pb - > get_rid ( ) ) ;
}
2020-03-26 22:49:16 +01:00
Set < PhysicsBody3D * > child_nodes = _get_child_nodes < PhysicsBody3D > ( node ) ;
for ( Set < PhysicsBody3D * > : : Element * I = child_nodes . front ( ) ; I ; I = I - > next ( ) ) {
2018-07-26 08:34:40 +02:00
rids . insert ( I - > get ( ) - > get_rid ( ) ) ;
}
return rids ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : snap_selected_nodes_to_floor ( ) {
2018-07-26 08:34:40 +02:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
Dictionary snap_data ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
2018-07-26 08:34:40 +02:00
if ( sp ) {
Vector3 from = Vector3 ( ) ;
Vector3 position_offset = Vector3 ( ) ;
// Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin
2020-03-26 22:49:16 +01:00
Set < VisualInstance3D * > vi = _get_child_nodes < VisualInstance3D > ( sp ) ;
Set < CollisionShape3D * > cs = _get_child_nodes < CollisionShape3D > ( sp ) ;
2020-12-10 21:44:09 +01:00
bool found_valid_shape = false ;
2018-07-26 08:34:40 +02:00
if ( cs . size ( ) ) {
2020-12-09 18:40:30 +01:00
AABB aabb ;
2020-12-10 21:44:09 +01:00
Set < CollisionShape3D * > : : Element * I = cs . front ( ) ;
if ( I - > get ( ) - > get_shape ( ) . is_valid ( ) ) {
CollisionShape3D * collision_shape = cs . front ( ) - > get ( ) ;
aabb = collision_shape - > get_global_transform ( ) . xform ( collision_shape - > get_shape ( ) - > get_debug_mesh ( ) - > get_aabb ( ) ) ;
2020-12-09 18:40:30 +01:00
found_valid_shape = true ;
}
2020-12-10 21:44:09 +01:00
for ( I = I - > next ( ) ; I ; I = I - > next ( ) ) {
CollisionShape3D * col_shape = I - > get ( ) ;
if ( col_shape - > get_shape ( ) . is_valid ( ) ) {
aabb . merge_with ( col_shape - > get_global_transform ( ) . xform ( col_shape - > get_shape ( ) - > get_debug_mesh ( ) - > get_aabb ( ) ) ) ;
2020-12-09 18:40:30 +01:00
found_valid_shape = true ;
}
}
if ( found_valid_shape ) {
Vector3 size = aabb . size * Vector3 ( 0.5 , 0.0 , 0.5 ) ;
from = aabb . position + size ;
position_offset . y = from . y - sp - > get_global_transform ( ) . origin . y ;
2018-07-26 08:34:40 +02:00
}
2020-12-10 21:44:09 +01:00
}
if ( ! found_valid_shape & & vi . size ( ) ) {
2018-07-26 08:34:40 +02:00
AABB aabb = vi . front ( ) - > get ( ) - > get_transformed_aabb ( ) ;
2020-03-26 22:49:16 +01:00
for ( Set < VisualInstance3D * > : : Element * I = vi . front ( ) ; I ; I = I - > next ( ) ) {
2018-07-26 08:34:40 +02:00
aabb . merge_with ( I - > get ( ) - > get_transformed_aabb ( ) ) ;
}
Vector3 size = aabb . size * Vector3 ( 0.5 , 0.0 , 0.5 ) ;
from = aabb . position + size ;
position_offset . y = from . y - sp - > get_global_transform ( ) . origin . y ;
2020-12-10 21:44:09 +01:00
} else if ( ! found_valid_shape ) {
2018-07-26 08:34:40 +02:00
from = sp - > get_global_transform ( ) . origin ;
}
// We add a bit of margin to the from position to avoid it from snapping
// when the spatial is already on a floor and there's another floor under
// it
2019-08-18 01:42:42 +02:00
from = from + Vector3 ( 0.0 , 0.2 , 0.0 ) ;
2018-07-26 08:34:40 +02:00
Dictionary d ;
d [ " from " ] = from ;
d [ " position_offset " ] = position_offset ;
snap_data [ sp ] = d ;
}
}
2020-04-18 11:00:51 +02:00
PhysicsDirectSpaceState3D * ss = get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_direct_space_state ( ) ;
2020-03-27 19:21:27 +01:00
PhysicsDirectSpaceState3D : : RayResult result ;
2018-07-26 08:34:40 +02:00
Array keys = snap_data . keys ( ) ;
2019-08-18 01:42:42 +02:00
// The maximum height an object can travel to be snapped
const float max_snap_height = 20.0 ;
Fix misc. source comment typos
Found using `codespell -q 3 -S ./thirdparty,*.po -L ang,ba,cas,dof,doubleclick,fave,hist,leapyear,lod,nd,numer,ois,paket,seeked,sinc,switchs,te,uint -D ~/Projects/codespell/codespell_lib/data/dictionary.txt `
2019-09-19 20:36:39 +02:00
// Will be set to `true` if at least one node from the selection was successfully snapped
2019-08-18 01:42:42 +02:00
bool snapped_to_floor = false ;
2018-07-26 08:34:40 +02:00
2019-08-18 01:42:42 +02:00
if ( keys . size ( ) ) {
// For snapping to be performed, there must be solid geometry under at least one of the selected nodes.
// We need to check this before snapping to register the undo/redo action only if needed.
2018-07-26 08:34:40 +02:00
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
Node * node = keys [ i ] ;
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( node ) ;
2018-07-26 08:34:40 +02:00
Dictionary d = snap_data [ node ] ;
Vector3 from = d [ " from " ] ;
2019-08-18 01:42:42 +02:00
Vector3 to = from - Vector3 ( 0.0 , max_snap_height , 0.0 ) ;
2018-07-26 08:34:40 +02:00
Set < RID > excluded = _get_physics_bodies_rid ( sp ) ;
if ( ss - > intersect_ray ( from , to , result , excluded ) ) {
2019-08-18 01:42:42 +02:00
snapped_to_floor = true ;
2018-07-26 08:34:40 +02:00
}
}
2019-08-18 01:42:42 +02:00
if ( snapped_to_floor ) {
undo_redo - > create_action ( TTR ( " Snap Nodes To Floor " ) ) ;
// Perform snapping if at least one node can be snapped
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
Node * node = keys [ i ] ;
2020-03-26 22:49:16 +01:00
Node3D * sp = Object : : cast_to < Node3D > ( node ) ;
2019-08-18 01:42:42 +02:00
Dictionary d = snap_data [ node ] ;
Vector3 from = d [ " from " ] ;
Vector3 to = from - Vector3 ( 0.0 , max_snap_height , 0.0 ) ;
Set < RID > excluded = _get_physics_bodies_rid ( sp ) ;
if ( ss - > intersect_ray ( from , to , result , excluded ) ) {
Vector3 position_offset = d [ " position_offset " ] ;
Transform new_transform = sp - > get_global_transform ( ) ;
new_transform . origin . y = result . position . y ;
new_transform . origin = new_transform . origin - position_offset ;
undo_redo - > add_do_method ( sp , " set_global_transform " , new_transform ) ;
undo_redo - > add_undo_method ( sp , " set_global_transform " , sp - > get_global_transform ( ) ) ;
}
}
undo_redo - > commit_action ( ) ;
} else {
EditorNode : : get_singleton ( ) - > show_warning ( TTR ( " Couldn't find a solid floor to snap the selection to. " ) ) ;
}
2018-07-26 08:34:40 +02:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _unhandled_key_input ( Ref < InputEvent > p_event ) {
2020-05-14 16:41:43 +02:00
if ( ! is_visible_in_tree ( ) ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-02-10 02:10:30 +01:00
2020-04-28 15:19:37 +02:00
snap_key_enabled = Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ;
2014-02-10 02:10:30 +01:00
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _notification ( int p_what ) {
2017-03-05 16:44:50 +01:00
if ( p_what = = NOTIFICATION_READY ) {
2020-03-26 22:49:16 +01:00
tool_button [ Node3DEditor : : TOOL_MODE_SELECT ] - > set_icon ( get_theme_icon ( " ToolSelect " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_MOVE ] - > set_icon ( get_theme_icon ( " ToolMove " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_ROTATE ] - > set_icon ( get_theme_icon ( " ToolRotate " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_SCALE ] - > set_icon ( get_theme_icon ( " ToolScale " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_LIST_SELECT ] - > set_icon ( get_theme_icon ( " ListSelect " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_LOCK_SELECTED ] - > set_icon ( get_theme_icon ( " Lock " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_UNLOCK_SELECTED ] - > set_icon ( get_theme_icon ( " Unlock " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_GROUP_SELECTED ] - > set_icon ( get_theme_icon ( " Group " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_UNGROUP_SELECTED ] - > set_icon ( get_theme_icon ( " Ungroup " , " EditorIcons " ) ) ;
2020-03-12 13:37:40 +01:00
2020-03-26 22:49:16 +01:00
tool_option_button [ Node3DEditor : : TOOL_OPT_LOCAL_COORDS ] - > set_icon ( get_theme_icon ( " Object " , " EditorIcons " ) ) ;
tool_option_button [ Node3DEditor : : TOOL_OPT_USE_SNAP ] - > set_icon ( get_theme_icon ( " Snap " , " EditorIcons " ) ) ;
tool_option_button [ Node3DEditor : : TOOL_OPT_OVERRIDE_CAMERA ] - > set_icon ( get_theme_icon ( " Camera3D " , " EditorIcons " ) ) ;
2020-03-12 13:37:40 +01:00
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , get_theme_icon ( " Panels1 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , get_theme_icon ( " Panels2 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , get_theme_icon ( " Panels2Alt " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , get_theme_icon ( " Panels3 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , get_theme_icon ( " Panels3Alt " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , get_theme_icon ( " Panels4 " , " EditorIcons " ) ) ;
2014-02-10 02:10:30 +01:00
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2017-10-23 21:21:15 +02:00
_refresh_menu_icons ( ) ;
2020-03-26 22:49:16 +01:00
get_tree ( ) - > connect ( " node_removed " , callable_mp ( this , & Node3DEditor : : _node_removed ) ) ;
EditorNode : : get_singleton ( ) - > get_scene_tree_dock ( ) - > get_tree_editor ( ) - > connect ( " node_changed " , callable_mp ( this , & Node3DEditor : : _refresh_menu_icons ) ) ;
editor_selection - > connect ( " selection_changed " , callable_mp ( this , & Node3DEditor : : _refresh_menu_icons ) ) ;
2019-04-06 22:55:01 +02:00
2020-03-26 22:49:16 +01:00
editor - > connect ( " stop_pressed " , callable_mp ( this , & Node3DEditor : : _update_camera_override_button ) , make_binds ( false ) ) ;
editor - > connect ( " play_pressed " , callable_mp ( this , & Node3DEditor : : _update_camera_override_button ) , make_binds ( true ) ) ;
2019-02-15 18:32:38 +01:00
} else if ( p_what = = NOTIFICATION_ENTER_TREE ) {
2018-10-29 11:30:28 +01:00
_register_all_gizmos ( ) ;
_update_gizmos_menu ( ) ;
2014-02-10 02:10:30 +01:00
_init_indicators ( ) ;
2019-02-15 18:32:38 +01:00
} else if ( p_what = = NOTIFICATION_THEME_CHANGED ) {
_update_gizmos_menu_theme ( ) ;
} else if ( p_what = = NOTIFICATION_EXIT_TREE ) {
2014-02-10 02:10:30 +01:00
_finish_indicators ( ) ;
2019-02-15 18:32:38 +01:00
} else if ( p_what = = EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED ) {
2020-03-26 22:49:16 +01:00
tool_button [ Node3DEditor : : TOOL_MODE_SELECT ] - > set_icon ( get_theme_icon ( " ToolSelect " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_MOVE ] - > set_icon ( get_theme_icon ( " ToolMove " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_ROTATE ] - > set_icon ( get_theme_icon ( " ToolRotate " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_SCALE ] - > set_icon ( get_theme_icon ( " ToolScale " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_MODE_LIST_SELECT ] - > set_icon ( get_theme_icon ( " ListSelect " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_LOCK_SELECTED ] - > set_icon ( get_theme_icon ( " Lock " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_UNLOCK_SELECTED ] - > set_icon ( get_theme_icon ( " Unlock " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_GROUP_SELECTED ] - > set_icon ( get_theme_icon ( " Group " , " EditorIcons " ) ) ;
tool_button [ Node3DEditor : : TOOL_UNGROUP_SELECTED ] - > set_icon ( get_theme_icon ( " Ungroup " , " EditorIcons " ) ) ;
tool_option_button [ Node3DEditor : : TOOL_OPT_LOCAL_COORDS ] - > set_icon ( get_theme_icon ( " Object " , " EditorIcons " ) ) ;
tool_option_button [ Node3DEditor : : TOOL_OPT_USE_SNAP ] - > set_icon ( get_theme_icon ( " Snap " , " EditorIcons " ) ) ;
2020-03-12 13:37:40 +01:00
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , get_theme_icon ( " Panels1 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , get_theme_icon ( " Panels2 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , get_theme_icon ( " Panels2Alt " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , get_theme_icon ( " Panels3 " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , get_theme_icon ( " Panels3Alt " , " EditorIcons " ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , get_theme_icon ( " Panels4 " , " EditorIcons " ) ) ;
2017-12-08 23:45:33 +01:00
// Update grid color by rebuilding grid.
_finish_grid ( ) ;
_init_grid ( ) ;
2019-04-06 22:55:01 +02:00
} else if ( p_what = = NOTIFICATION_VISIBILITY_CHANGED ) {
if ( ! is_visible ( ) & & tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > is_pressed ( ) ) {
2020-02-07 02:52:05 +01:00
EditorDebuggerNode * debugger = EditorDebuggerNode : : get_singleton ( ) ;
2019-04-06 22:55:01 +02:00
2020-02-24 06:21:15 +01:00
debugger - > set_camera_override ( EditorDebuggerNode : : OVERRIDE_NONE ) ;
2019-04-06 22:55:01 +02:00
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_pressed ( false ) ;
}
2017-08-30 01:03:13 +02:00
}
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : add_control_to_menu_panel ( Control * p_control ) {
2014-02-10 02:10:30 +01:00
hbc_menu - > add_child ( p_control ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : remove_control_from_menu_panel ( Control * p_control ) {
2018-02-13 22:21:19 +01:00
hbc_menu - > remove_child ( p_control ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : set_can_preview ( Camera3D * p_preview ) {
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
2014-02-10 02:10:30 +01:00
viewports [ i ] - > set_can_preview ( p_preview ) ;
}
}
2020-03-26 22:49:16 +01:00
VSplitContainer * Node3DEditor : : get_shader_split ( ) {
2014-02-10 02:10:30 +01:00
return shader_split ;
}
2020-03-26 22:49:16 +01:00
HSplitContainer * Node3DEditor : : get_palette_split ( ) {
2017-12-01 01:50:09 +01:00
return palette_split ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _request_gizmo ( Object * p_obj ) {
Node3D * sp = Object : : cast_to < Node3D > ( p_obj ) ;
2020-05-14 16:41:43 +02:00
if ( ! sp ) {
2014-02-10 02:10:30 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2017-08-26 05:40:45 +02:00
if ( editor - > get_edited_scene ( ) & & ( sp = = editor - > get_edited_scene ( ) | | ( sp - > get_owner ( ) & & editor - > get_edited_scene ( ) - > is_a_parent_of ( sp ) ) ) ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > seg ;
2014-02-10 02:10:30 +01:00
2019-03-12 00:30:50 +01:00
for ( int i = 0 ; i < gizmo_plugins_by_priority . size ( ) ; + + i ) {
seg = gizmo_plugins_by_priority . write [ i ] - > get_gizmo ( sp ) ;
2014-02-10 02:10:30 +01:00
2018-07-25 00:08:49 +02:00
if ( seg . is_valid ( ) ) {
sp - > set_gizmo ( seg ) ;
2014-05-05 03:50:23 +02:00
2018-07-25 00:08:49 +02:00
if ( sp = = selected ) {
seg - > set_selected ( true ) ;
selected - > update_gizmo ( ) ;
}
2014-05-05 03:50:23 +02:00
2018-07-25 00:08:49 +02:00
break ;
}
2014-05-05 03:50:23 +02:00
}
2014-02-10 02:10:30 +01:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _toggle_maximize_view ( Object * p_viewport ) {
2020-05-14 16:41:43 +02:00
if ( ! p_viewport ) {
2020-05-10 12:56:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-03-26 22:49:16 +01:00
Node3DEditorViewport * current_viewport = Object : : cast_to < Node3DEditorViewport > ( p_viewport ) ;
2020-05-14 16:41:43 +02:00
if ( ! current_viewport ) {
2020-05-10 12:56:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
2017-03-05 16:44:50 +01:00
int index = - 1 ;
2014-04-01 12:45:48 +02:00
bool maximized = false ;
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( viewports [ i ] = = current_viewport ) {
index = i ;
2020-05-14 16:41:43 +02:00
if ( current_viewport - > get_global_rect ( ) = = viewport_base - > get_global_rect ( ) ) {
2017-03-05 16:44:50 +01:00
maximized = true ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
break ;
}
}
2020-05-14 16:41:43 +02:00
if ( index = = - 1 ) {
2020-05-10 12:56:01 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
if ( ! maximized ) {
2017-08-31 23:30:35 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( i = = ( uint32_t ) index ) {
2020-12-22 17:24:29 +01:00
viewports [ i ] - > set_anchors_and_offsets_preset ( Control : : PRESET_WIDE ) ;
2020-05-14 16:41:43 +02:00
} else {
2014-04-01 12:45:48 +02:00
viewports [ i ] - > hide ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
}
} else {
2020-05-14 16:41:43 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-04-01 12:45:48 +02:00
viewports [ i ] - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
2020-05-14 16:41:43 +02:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) ) ) {
2014-04-01 12:45:48 +02:00
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) ) ) {
2014-04-01 12:45:48 +02:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ) ) {
2014-10-09 05:06:51 +02:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) ) ) {
2014-04-01 12:45:48 +02:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ) ) {
2014-10-09 05:06:51 +02:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
2020-05-14 16:41:43 +02:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) ) ) {
2014-04-01 12:45:48 +02:00
_menu_item_pressed ( MENU_VIEW_USE_4_VIEWPORTS ) ;
2020-05-14 16:41:43 +02:00
}
2014-04-01 12:45:48 +02:00
}
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _node_removed ( Node * p_node ) {
2020-05-14 16:41:43 +02:00
if ( p_node = = selected ) {
2020-04-02 01:20:12 +02:00
selected = nullptr ;
2020-05-14 16:41:43 +02:00
}
2014-05-05 03:50:23 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _register_all_gizmos ( ) {
2020-04-06 12:40:52 +02:00
add_gizmo_plugin ( Ref < Camera3DGizmoPlugin > ( memnew ( Camera3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Light3DGizmoPlugin > ( memnew ( Light3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < AudioStreamPlayer3DGizmoPlugin > ( memnew ( AudioStreamPlayer3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < MeshInstance3DGizmoPlugin > ( memnew ( MeshInstance3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < SoftBody3DGizmoPlugin > ( memnew ( SoftBody3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Sprite3DGizmoPlugin > ( memnew ( Sprite3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Skeleton3DGizmoPlugin > ( memnew ( Skeleton3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Position3DGizmoPlugin > ( memnew ( Position3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < RayCast3DGizmoPlugin > ( memnew ( RayCast3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < SpringArm3DGizmoPlugin > ( memnew ( SpringArm3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < VehicleWheel3DGizmoPlugin > ( memnew ( VehicleWheel3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < VisibilityNotifier3DGizmoPlugin > ( memnew ( VisibilityNotifier3DGizmoPlugin ) ) ) ;
2020-03-30 18:22:57 +02:00
add_gizmo_plugin ( Ref < GPUParticles3DGizmoPlugin > ( memnew ( GPUParticles3DGizmoPlugin ) ) ) ;
2020-10-08 02:29:49 +02:00
add_gizmo_plugin ( Ref < GPUParticlesCollision3DGizmoPlugin > ( memnew ( GPUParticlesCollision3DGizmoPlugin ) ) ) ;
2020-03-30 18:22:57 +02:00
add_gizmo_plugin ( Ref < CPUParticles3DGizmoPlugin > ( memnew ( CPUParticles3DGizmoPlugin ) ) ) ;
2018-10-29 11:30:28 +01:00
add_gizmo_plugin ( Ref < ReflectionProbeGizmoPlugin > ( memnew ( ReflectionProbeGizmoPlugin ) ) ) ;
2020-04-14 05:05:21 +02:00
add_gizmo_plugin ( Ref < DecalGizmoPlugin > ( memnew ( DecalGizmoPlugin ) ) ) ;
2018-10-29 11:30:28 +01:00
add_gizmo_plugin ( Ref < GIProbeGizmoPlugin > ( memnew ( GIProbeGizmoPlugin ) ) ) ;
2020-05-01 14:34:23 +02:00
add_gizmo_plugin ( Ref < BakedLightmapGizmoPlugin > ( memnew ( BakedLightmapGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < LightmapProbeGizmoPlugin > ( memnew ( LightmapProbeGizmoPlugin ) ) ) ;
2020-04-06 12:40:52 +02:00
add_gizmo_plugin ( Ref < CollisionShape3DGizmoPlugin > ( memnew ( CollisionShape3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < CollisionPolygon3DGizmoPlugin > ( memnew ( CollisionPolygon3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < NavigationRegion3DGizmoPlugin > ( memnew ( NavigationRegion3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Joint3DGizmoPlugin > ( memnew ( Joint3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < PhysicalBone3DGizmoPlugin > ( memnew ( PhysicalBone3DGizmoPlugin ) ) ) ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : _bind_methods ( ) {
ClassDB : : bind_method ( " _unhandled_key_input " , & Node3DEditor : : _unhandled_key_input ) ;
ClassDB : : bind_method ( " _get_editor_data " , & Node3DEditor : : _get_editor_data ) ;
ClassDB : : bind_method ( " _request_gizmo " , & Node3DEditor : : _request_gizmo ) ;
2020-06-24 17:09:53 +02:00
ClassDB : : bind_method ( " _refresh_menu_icons " , & Node3DEditor : : _refresh_menu_icons ) ;
2014-04-01 12:45:48 +02:00
2017-03-05 16:44:50 +01:00
ADD_SIGNAL ( MethodInfo ( " transform_key_request " ) ) ;
2017-10-23 21:21:15 +02:00
ADD_SIGNAL ( MethodInfo ( " item_lock_status_changed " ) ) ;
2019-04-17 18:24:28 +02:00
ADD_SIGNAL ( MethodInfo ( " item_group_status_changed " ) ) ;
2014-09-19 23:39:50 +02:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : clear ( ) {
2019-10-31 14:32:46 +01:00
settings_fov - > set_value ( EDITOR_GET ( " editors/3d/default_fov " ) ) ;
settings_znear - > set_value ( EDITOR_GET ( " editors/3d/default_z_near " ) ) ;
settings_zfar - > set_value ( EDITOR_GET ( " editors/3d/default_z_far " ) ) ;
2014-09-19 23:39:50 +02:00
2017-08-31 23:30:35 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-09-19 23:39:50 +02:00
viewports [ i ] - > reset ( ) ;
}
2020-03-27 19:21:27 +01:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , true ) ;
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_ORIGIN ) , true ) ;
for ( int i = 0 ; i < 3 ; + + i ) {
2014-09-19 23:39:50 +02:00
if ( grid_enable [ i ] ) {
2017-03-05 16:44:50 +01:00
grid_visible [ i ] = true ;
2014-09-19 23:39:50 +02:00
}
}
2017-08-31 23:30:35 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2020-03-26 22:49:16 +01:00
viewports [ i ] - > view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( Node3DEditorViewport : : VIEW_AUDIO_LISTENER ) , i = = 0 ) ;
2017-03-05 16:44:50 +01:00
viewports [ i ] - > viewport - > set_as_audio_listener ( i = = 0 ) ;
2014-10-03 05:10:51 +02:00
}
2014-10-12 07:13:22 +02:00
2017-03-05 16:44:50 +01:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_GRID ) , true ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Node3DEditor : : Node3DEditor ( EditorNode * p_editor ) {
2017-03-05 16:44:50 +01:00
gizmo . visible = true ;
gizmo . scale = 1.0 ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
viewport_environment = Ref < Environment > ( memnew ( Environment ) ) ;
undo_redo = p_editor - > get_undo_redo ( ) ;
2014-02-10 02:10:30 +01:00
VBoxContainer * vbc = this ;
2020-04-02 01:20:12 +02:00
custom_camera = nullptr ;
2017-03-05 16:44:50 +01:00
singleton = this ;
editor = p_editor ;
editor_selection = editor - > get_editor_selection ( ) ;
2014-02-10 02:10:30 +01:00
editor_selection - > add_editor_plugin ( this ) ;
2017-03-05 16:44:50 +01:00
snap_enabled = false ;
2018-02-21 15:14:26 +01:00
snap_key_enabled = false ;
2014-02-10 02:10:30 +01:00
tool_mode = TOOL_MODE_SELECT ;
2019-04-06 22:55:01 +02:00
camera_override_viewport_id = 0 ;
2017-03-05 16:44:50 +01:00
hbc_menu = memnew ( HBoxContainer ) ;
2014-02-10 02:10:30 +01:00
vbc - > add_child ( hbc_menu ) ;
Vector < Variant > button_binds ;
button_binds . resize ( 1 ) ;
2017-11-18 19:51:37 +01:00
String sct ;
2014-02-10 02:10:30 +01:00
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_MODE_SELECT ] = memnew ( Button ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( tool_button [ TOOL_MODE_SELECT ] ) ;
2014-02-10 02:10:30 +01:00
tool_button [ TOOL_MODE_SELECT ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_SELECT ] - > set_flat ( true ) ;
tool_button [ TOOL_MODE_SELECT ] - > set_pressed ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_SELECT ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_MODE_SELECT ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_button [ TOOL_MODE_SELECT ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_select " , TTR ( " Select Mode " ) , KEY_Q ) ) ;
2020-09-17 03:40:00 +02:00
tool_button [ TOOL_MODE_SELECT ] - > set_shortcut_context ( this ) ;
2019-08-17 23:37:13 +02:00
tool_button [ TOOL_MODE_SELECT ] - > set_tooltip ( keycode_get_string ( KEY_MASK_CMD ) + TTR ( " Drag: Rotate \n Alt+Drag: Move \n Alt+RMB: Depth list selection " ) ) ;
2014-02-10 02:10:30 +01:00
2018-09-15 17:44:26 +02:00
hbc_menu - > add_child ( memnew ( VSeparator ) ) ;
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_MODE_MOVE ] = memnew ( Button ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( tool_button [ TOOL_MODE_MOVE ] ) ;
2014-02-10 02:10:30 +01:00
tool_button [ TOOL_MODE_MOVE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_MOVE ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_MOVE ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_MODE_MOVE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_button [ TOOL_MODE_MOVE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_move " , TTR ( " Move Mode " ) , KEY_W ) ) ;
2020-09-17 03:40:00 +02:00
tool_button [ TOOL_MODE_MOVE ] - > set_shortcut_context ( this ) ;
2014-02-10 02:10:30 +01:00
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_MODE_ROTATE ] = memnew ( Button ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( tool_button [ TOOL_MODE_ROTATE ] ) ;
2014-02-10 02:10:30 +01:00
tool_button [ TOOL_MODE_ROTATE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_ROTATE ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_ROTATE ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_MODE_ROTATE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_button [ TOOL_MODE_ROTATE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_rotate " , TTR ( " Rotate Mode " ) , KEY_E ) ) ;
2020-09-17 03:40:00 +02:00
tool_button [ TOOL_MODE_ROTATE ] - > set_shortcut_context ( this ) ;
2014-02-10 02:10:30 +01:00
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_MODE_SCALE ] = memnew ( Button ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( tool_button [ TOOL_MODE_SCALE ] ) ;
2014-02-10 02:10:30 +01:00
tool_button [ TOOL_MODE_SCALE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_SCALE ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_SCALE ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_MODE_SCALE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_button [ TOOL_MODE_SCALE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_scale " , TTR ( " Scale Mode " ) , KEY_R ) ) ;
2020-09-17 03:40:00 +02:00
tool_button [ TOOL_MODE_SCALE ] - > set_shortcut_context ( this ) ;
2014-02-10 02:10:30 +01:00
2018-09-15 17:44:26 +02:00
hbc_menu - > add_child ( memnew ( VSeparator ) ) ;
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_MODE_LIST_SELECT ] = memnew ( Button ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( tool_button [ TOOL_MODE_LIST_SELECT ] ) ;
2015-12-13 21:16:13 +01:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_LIST_SELECT ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2016-06-01 13:32:20 +02:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_tooltip ( TTR ( " Show a list of all objects at the position clicked \n (same as Alt+RMB in select mode). " ) ) ;
2015-12-13 21:16:13 +01:00
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_LOCK_SELECTED ] = memnew ( Button ) ;
2017-10-23 21:21:15 +02:00
hbc_menu - > add_child ( tool_button [ TOOL_LOCK_SELECTED ] ) ;
2020-06-24 17:09:53 +02:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_LOCK_SELECTED ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_LOCK_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2017-10-23 21:21:15 +02:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_tooltip ( TTR ( " Lock the selected object in place (can't be moved). " ) ) ;
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_UNLOCK_SELECTED ] = memnew ( Button ) ;
2017-10-23 21:21:15 +02:00
hbc_menu - > add_child ( tool_button [ TOOL_UNLOCK_SELECTED ] ) ;
2020-06-24 17:09:53 +02:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_UNLOCK_SELECTED ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2017-10-23 21:21:15 +02:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_tooltip ( TTR ( " Unlock the selected object (can be moved). " ) ) ;
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_GROUP_SELECTED ] = memnew ( Button ) ;
2019-04-17 18:24:28 +02:00
hbc_menu - > add_child ( tool_button [ TOOL_GROUP_SELECTED ] ) ;
2020-06-24 17:09:53 +02:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_flat ( true ) ;
2019-04-17 18:24:28 +02:00
button_binds . write [ 0 ] = MENU_GROUP_SELECTED ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_GROUP_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-04-17 18:24:28 +02:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_tooltip ( TTR ( " Makes sure the object's children are not selectable. " ) ) ;
2020-06-19 20:49:04 +02:00
tool_button [ TOOL_UNGROUP_SELECTED ] = memnew ( Button ) ;
2019-04-17 18:24:28 +02:00
hbc_menu - > add_child ( tool_button [ TOOL_UNGROUP_SELECTED ] ) ;
2020-06-24 17:09:53 +02:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_flat ( true ) ;
2019-04-17 18:24:28 +02:00
button_binds . write [ 0 ] = MENU_UNGROUP_SELECTED ;
2020-03-26 22:49:16 +01:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-04-17 18:24:28 +02:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_tooltip ( TTR ( " Restores the object's children's ability to be selected. " ) ) ;
2018-09-15 17:44:26 +02:00
hbc_menu - > add_child ( memnew ( VSeparator ) ) ;
2017-11-18 19:51:37 +01:00
2020-06-19 20:49:04 +02:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] = memnew ( Button ) ;
2017-11-18 19:51:37 +01:00
hbc_menu - > add_child ( tool_option_button [ TOOL_OPT_LOCAL_COORDS ] ) ;
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_toggle_mode ( true ) ;
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_LOCAL_COORDS ;
2020-03-26 22:49:16 +01:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/local_coords " , TTR ( " Use Local Space " ) , KEY_T ) ) ;
2020-09-17 03:40:00 +02:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_shortcut_context ( this ) ;
2017-11-18 19:51:37 +01:00
2020-06-19 20:49:04 +02:00
tool_option_button [ TOOL_OPT_USE_SNAP ] = memnew ( Button ) ;
2017-11-18 19:51:37 +01:00
hbc_menu - > add_child ( tool_option_button [ TOOL_OPT_USE_SNAP ] ) ;
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_toggle_mode ( true ) ;
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_flat ( true ) ;
2018-07-25 03:11:03 +02:00
button_binds . write [ 0 ] = MENU_TOOL_USE_SNAP ;
2020-03-26 22:49:16 +01:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2019-08-17 23:37:13 +02:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/snap " , TTR ( " Use Snap " ) , KEY_Y ) ) ;
2020-09-17 03:40:00 +02:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_shortcut_context ( this ) ;
2017-11-18 19:51:37 +01:00
2018-09-15 17:44:26 +02:00
hbc_menu - > add_child ( memnew ( VSeparator ) ) ;
2015-12-13 21:16:13 +01:00
2020-06-19 20:49:04 +02:00
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] = memnew ( Button ) ;
2019-04-06 22:55:01 +02:00
hbc_menu - > add_child ( tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] ) ;
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_toggle_mode ( true ) ;
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_flat ( true ) ;
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_disabled ( true ) ;
button_binds . write [ 0 ] = MENU_TOOL_OVERRIDE_CAMERA ;
2020-03-26 22:49:16 +01:00
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2019-04-06 22:55:01 +02:00
_update_camera_override_button ( false ) ;
hbc_menu - > add_child ( memnew ( VSeparator ) ) ;
2017-09-02 21:47:16 +02:00
// Drag and drop support;
2020-03-26 22:49:16 +01:00
preview_node = memnew ( Node3D ) ;
2017-11-17 03:09:00 +01:00
preview_bounds = AABB ( ) ;
2017-09-02 21:47:16 +02:00
2017-03-05 16:44:50 +01:00
ED_SHORTCUT ( " spatial_editor/bottom_view " , TTR ( " Bottom View " ) , KEY_MASK_ALT + KEY_KP_7 ) ;
2016-06-30 22:54:34 +02:00
ED_SHORTCUT ( " spatial_editor/top_view " , TTR ( " Top View " ) , KEY_KP_7 ) ;
2017-03-05 16:44:50 +01:00
ED_SHORTCUT ( " spatial_editor/rear_view " , TTR ( " Rear View " ) , KEY_MASK_ALT + KEY_KP_1 ) ;
2016-06-30 22:54:34 +02:00
ED_SHORTCUT ( " spatial_editor/front_view " , TTR ( " Front View " ) , KEY_KP_1 ) ;
2017-03-05 16:44:50 +01:00
ED_SHORTCUT ( " spatial_editor/left_view " , TTR ( " Left View " ) , KEY_MASK_ALT + KEY_KP_3 ) ;
2016-06-30 22:54:34 +02:00
ED_SHORTCUT ( " spatial_editor/right_view " , TTR ( " Right View " ) , KEY_KP_3 ) ;
2019-05-19 23:08:07 +02:00
ED_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " , TTR ( " Switch Perspective/Orthogonal View " ) , KEY_KP_5 ) ;
2016-06-30 22:54:34 +02:00
ED_SHORTCUT ( " spatial_editor/insert_anim_key " , TTR ( " Insert Animation Key " ) , KEY_K ) ;
2016-10-04 20:39:38 +02:00
ED_SHORTCUT ( " spatial_editor/focus_origin " , TTR ( " Focus Origin " ) , KEY_O ) ;
2016-06-30 22:54:34 +02:00
ED_SHORTCUT ( " spatial_editor/focus_selection " , TTR ( " Focus Selection " ) , KEY_F ) ;
2018-10-27 23:43:19 +02:00
ED_SHORTCUT ( " spatial_editor/align_transform_with_view " , TTR ( " Align Transform with View " ) , KEY_MASK_ALT + KEY_MASK_CMD + KEY_M ) ;
ED_SHORTCUT ( " spatial_editor/align_rotation_with_view " , TTR ( " Align Rotation with View " ) , KEY_MASK_ALT + KEY_MASK_CMD + KEY_F ) ;
2017-10-30 01:22:48 +01:00
ED_SHORTCUT ( " spatial_editor/freelook_toggle " , TTR ( " Toggle Freelook " ) , KEY_MASK_SHIFT + KEY_F ) ;
2014-02-10 02:10:30 +01:00
PopupMenu * p ;
2017-03-05 16:44:50 +01:00
transform_menu = memnew ( MenuButton ) ;
2016-05-30 20:47:53 +02:00
transform_menu - > set_text ( TTR ( " Transform " ) ) ;
2018-07-30 00:26:43 +02:00
transform_menu - > set_switch_on_hover ( true ) ;
2020-09-17 03:40:00 +02:00
transform_menu - > set_shortcut_context ( this ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( transform_menu ) ;
2014-02-10 02:10:30 +01:00
p = transform_menu - > get_popup ( ) ;
2019-05-19 23:08:07 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/snap_to_floor " , TTR ( " Snap Object to Floor " ) , KEY_PAGEDOWN ) , MENU_SNAP_TO_FLOOR ) ;
2018-04-22 19:36:01 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/transform_dialog " , TTR ( " Transform Dialog... " ) ) , MENU_TRANSFORM_DIALOG ) ;
2014-02-10 02:10:30 +01:00
2019-08-12 22:23:00 +02:00
p - > add_separator ( ) ;
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/configure_snap " , TTR ( " Configure Snap... " ) ) , MENU_TRANSFORM_CONFIGURE_SNAP ) ;
2020-03-26 22:49:16 +01:00
p - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
view_menu = memnew ( MenuButton ) ;
2016-05-04 03:25:37 +02:00
view_menu - > set_text ( TTR ( " View " ) ) ;
2018-07-30 00:26:43 +02:00
view_menu - > set_switch_on_hover ( true ) ;
2020-09-17 03:40:00 +02:00
view_menu - > set_shortcut_context ( this ) ;
2017-03-05 16:44:50 +01:00
hbc_menu - > add_child ( view_menu ) ;
2014-02-10 02:10:30 +01:00
p = view_menu - > get_popup ( ) ;
2017-09-02 21:47:16 +02:00
accept = memnew ( AcceptDialog ) ;
editor - > get_gui_base ( ) - > add_child ( accept ) ;
2018-03-24 03:05:20 +01:00
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/1_viewport " , TTR ( " 1 Viewport " ) , KEY_MASK_CMD + KEY_1 ) , MENU_VIEW_USE_1_VIEWPORT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/2_viewports " , TTR ( " 2 Viewports " ) , KEY_MASK_CMD + KEY_2 ) , MENU_VIEW_USE_2_VIEWPORTS ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/2_viewports_alt " , TTR ( " 2 Viewports (Alt) " ) , KEY_MASK_ALT + KEY_MASK_CMD + KEY_2 ) , MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/3_viewports " , TTR ( " 3 Viewports " ) , KEY_MASK_CMD + KEY_3 ) , MENU_VIEW_USE_3_VIEWPORTS ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/3_viewports_alt " , TTR ( " 3 Viewports (Alt) " ) , KEY_MASK_ALT + KEY_MASK_CMD + KEY_3 ) , MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/4_viewports " , TTR ( " 4 Viewports " ) , KEY_MASK_CMD + KEY_4 ) , MENU_VIEW_USE_4_VIEWPORTS ) ;
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2018-08-11 23:07:00 +02:00
p - > add_submenu_item ( TTR ( " Gizmos " ) , " GizmosMenu " ) ;
2018-08-12 15:20:20 +02:00
p - > add_separator ( ) ;
2016-06-30 22:54:34 +02:00
p - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_origin " , TTR ( " View Origin " ) ) , MENU_VIEW_ORIGIN ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_grid " , TTR ( " View Grid " ) ) , MENU_VIEW_GRID ) ;
2019-08-12 22:23:00 +02:00
2014-02-10 02:10:30 +01:00
p - > add_separator ( ) ;
2019-08-12 22:23:00 +02:00
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/settings " , TTR ( " Settings... " ) ) , MENU_VIEW_CAMERA_SETTINGS ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
p - > set_item_checked ( p - > get_item_index ( MENU_VIEW_ORIGIN ) , true ) ;
p - > set_item_checked ( p - > get_item_index ( MENU_VIEW_GRID ) , true ) ;
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
p - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) ) ;
2014-02-10 02:10:30 +01:00
2018-08-11 23:07:00 +02:00
gizmos_menu = memnew ( PopupMenu ) ;
p - > add_child ( gizmos_menu ) ;
gizmos_menu - > set_name ( " GizmosMenu " ) ;
gizmos_menu - > set_hide_on_checkable_item_selection ( false ) ;
2020-03-26 22:49:16 +01:00
gizmos_menu - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_gizmo_toggled ) ) ;
2018-07-25 00:08:49 +02:00
2014-02-10 02:10:30 +01:00
/* REST OF MENU */
2017-03-05 16:44:50 +01:00
palette_split = memnew ( HSplitContainer ) ;
2014-02-10 02:10:30 +01:00
palette_split - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
vbc - > add_child ( palette_split ) ;
2017-03-05 16:44:50 +01:00
shader_split = memnew ( VSplitContainer ) ;
2014-02-10 02:10:30 +01:00
shader_split - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
palette_split - > add_child ( shader_split ) ;
2020-03-26 22:49:16 +01:00
viewport_base = memnew ( Node3DEditorViewportContainer ) ;
2014-02-10 02:10:30 +01:00
shader_split - > add_child ( viewport_base ) ;
viewport_base - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2017-08-31 23:30:35 +02:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2020-03-26 22:49:16 +01:00
viewports [ i ] = memnew ( Node3DEditorViewport ( this , editor , i ) ) ;
viewports [ i ] - > connect ( " toggle_maximize_view " , callable_mp ( this , & Node3DEditor : : _toggle_maximize_view ) ) ;
viewports [ i ] - > connect ( " clicked " , callable_mp ( this , & Node3DEditor : : _update_camera_override_viewport ) ) ;
2017-09-02 21:47:16 +02:00
viewports [ i ] - > assign_pending_data_pointers ( preview_node , & preview_bounds , accept ) ;
2014-02-10 02:10:30 +01:00
viewport_base - > add_child ( viewports [ i ] ) ;
}
/* SNAP DIALOG */
2020-03-08 20:31:11 +01:00
snap_translate_value = 1 ;
snap_rotate_value = 15 ;
snap_scale_value = 10 ;
2017-03-05 16:44:50 +01:00
snap_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 03:25:37 +02:00
snap_dialog - > set_title ( TTR ( " Snap Settings " ) ) ;
2014-02-10 02:10:30 +01:00
add_child ( snap_dialog ) ;
2020-03-26 22:49:16 +01:00
snap_dialog - > connect ( " confirmed " , callable_mp ( this , & Node3DEditor : : _snap_changed ) ) ;
2020-12-14 19:37:30 +01:00
snap_dialog - > get_cancel_button ( ) - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _snap_update ) ) ;
2015-10-18 18:31:44 +02:00
2017-03-05 16:44:50 +01:00
VBoxContainer * snap_dialog_vbc = memnew ( VBoxContainer ) ;
2015-10-18 18:31:44 +02:00
snap_dialog - > add_child ( snap_dialog_vbc ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
snap_translate = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Translate Snap: " ) , snap_translate ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
snap_rotate = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Rotate Snap (deg.): " ) , snap_rotate ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
snap_scale = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Scale Snap (%): " ) , snap_scale ) ;
2014-02-10 02:10:30 +01:00
2020-03-08 20:31:11 +01:00
_snap_update ( ) ;
2015-10-18 18:31:44 +02:00
/* SETTINGS DIALOG */
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
settings_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 03:25:37 +02:00
settings_dialog - > set_title ( TTR ( " Viewport Settings " ) ) ;
2014-02-10 02:10:30 +01:00
add_child ( settings_dialog ) ;
2017-03-05 16:44:50 +01:00
settings_vbc = memnew ( VBoxContainer ) ;
2017-08-04 13:23:10 +02:00
settings_vbc - > set_custom_minimum_size ( Size2 ( 200 , 0 ) * EDSCALE ) ;
2014-10-12 07:13:22 +02:00
settings_dialog - > add_child ( settings_vbc ) ;
2017-03-05 16:44:50 +01:00
settings_fov = memnew ( SpinBox ) ;
2017-08-04 13:23:10 +02:00
settings_fov - > set_max ( MAX_FOV ) ;
settings_fov - > set_min ( MIN_FOV ) ;
2019-10-31 14:32:46 +01:00
settings_fov - > set_step ( 0.1 ) ;
settings_fov - > set_value ( EDITOR_GET ( " editors/3d/default_fov " ) ) ;
2017-03-05 16:44:50 +01:00
settings_vbc - > add_margin_child ( TTR ( " Perspective FOV (deg.): " ) , settings_fov ) ;
2014-10-12 07:13:22 +02:00
2017-03-05 16:44:50 +01:00
settings_znear = memnew ( SpinBox ) ;
2017-08-04 13:23:10 +02:00
settings_znear - > set_max ( MAX_Z ) ;
settings_znear - > set_min ( MIN_Z ) ;
2014-10-12 07:13:22 +02:00
settings_znear - > set_step ( 0.01 ) ;
2019-10-31 14:32:46 +01:00
settings_znear - > set_value ( EDITOR_GET ( " editors/3d/default_z_near " ) ) ;
2017-03-05 16:44:50 +01:00
settings_vbc - > add_margin_child ( TTR ( " View Z-Near: " ) , settings_znear ) ;
2014-10-12 07:13:22 +02:00
2017-03-05 16:44:50 +01:00
settings_zfar = memnew ( SpinBox ) ;
2017-08-04 13:23:10 +02:00
settings_zfar - > set_max ( MAX_Z ) ;
settings_zfar - > set_min ( MIN_Z ) ;
2019-10-31 14:32:46 +01:00
settings_zfar - > set_step ( 0.1 ) ;
settings_zfar - > set_value ( EDITOR_GET ( " editors/3d/default_z_far " ) ) ;
2017-03-05 16:44:50 +01:00
settings_vbc - > add_margin_child ( TTR ( " View Z-Far: " ) , settings_zfar ) ;
2014-02-10 02:10:30 +01:00
2020-03-10 17:56:46 +01:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; + + i ) {
2020-03-26 22:49:16 +01:00
settings_dialog - > connect ( " confirmed " , callable_mp ( viewports [ i ] , & Node3DEditorViewport : : _update_camera ) , varray ( 0.0 ) ) ;
2020-03-10 17:56:46 +01:00
}
2014-02-10 02:10:30 +01:00
/* XFORM DIALOG */
2017-03-05 16:44:50 +01:00
xform_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 03:25:37 +02:00
xform_dialog - > set_title ( TTR ( " Transform Change " ) ) ;
2014-02-10 02:10:30 +01:00
add_child ( xform_dialog ) ;
2017-07-31 15:00:02 +02:00
VBoxContainer * xform_vbc = memnew ( VBoxContainer ) ;
xform_dialog - > add_child ( xform_vbc ) ;
2015-10-18 18:31:44 +02:00
Label * l = memnew ( Label ) ;
2016-05-04 03:25:37 +02:00
l - > set_text ( TTR ( " Translate: " ) ) ;
2017-07-31 15:00:02 +02:00
xform_vbc - > add_child ( l ) ;
HBoxContainer * xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_translate [ i ] = memnew ( LineEdit ) ;
2017-07-31 15:00:02 +02:00
xform_translate [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_translate [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
l = memnew ( Label ) ;
2016-05-04 03:25:37 +02:00
l - > set_text ( TTR ( " Rotate (deg.): " ) ) ;
2017-07-31 15:00:02 +02:00
xform_vbc - > add_child ( l ) ;
xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_rotate [ i ] = memnew ( LineEdit ) ;
2017-07-31 15:00:02 +02:00
xform_rotate [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_rotate [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
l = memnew ( Label ) ;
2016-05-04 03:25:37 +02:00
l - > set_text ( TTR ( " Scale (ratio): " ) ) ;
2017-07-31 15:00:02 +02:00
xform_vbc - > add_child ( l ) ;
xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_scale [ i ] = memnew ( LineEdit ) ;
2017-07-31 15:00:02 +02:00
xform_scale [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_scale [ i ] ) ;
2014-02-10 02:10:30 +01:00
}
l = memnew ( Label ) ;
2016-05-04 03:25:37 +02:00
l - > set_text ( TTR ( " Transform Type " ) ) ;
2017-07-31 15:00:02 +02:00
xform_vbc - > add_child ( l ) ;
2014-02-10 02:10:30 +01:00
2017-03-05 16:44:50 +01:00
xform_type = memnew ( OptionButton ) ;
2017-07-31 15:00:02 +02:00
xform_type - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2016-05-04 03:25:37 +02:00
xform_type - > add_item ( TTR ( " Pre " ) ) ;
xform_type - > add_item ( TTR ( " Post " ) ) ;
2017-07-31 15:00:02 +02:00
xform_vbc - > add_child ( xform_type ) ;
2014-02-10 02:10:30 +01:00
2020-03-26 22:49:16 +01:00
xform_dialog - > connect ( " confirmed " , callable_mp ( this , & Node3DEditor : : _xform_dialog_action ) ) ;
2014-02-10 02:10:30 +01:00
2020-03-27 19:21:27 +01:00
scenario_debug = RenderingServer : : SCENARIO_DEBUG_DISABLED ;
2014-02-10 02:10:30 +01:00
2020-04-02 01:20:12 +02:00
selected = nullptr ;
2014-02-10 02:10:30 +01:00
2014-04-10 05:18:27 +02:00
set_process_unhandled_key_input ( true ) ;
2014-02-10 02:10:30 +01:00
add_to_group ( " _spatial_editor_group " ) ;
2014-05-05 03:50:23 +02:00
2017-03-05 16:44:50 +01:00
EDITOR_DEF ( " editors/3d/manipulator_gizmo_size " , 80 ) ;
2020-12-14 23:33:47 +01:00
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : INT , " editors/3d/manipulator_gizmo_size " , PROPERTY_HINT_RANGE , " 16,160,1 " ) ) ;
EDITOR_DEF ( " editors/3d/manipulator_gizmo_opacity " , 0.9 ) ;
Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
2020-02-24 19:20:53 +01:00
EditorSettings : : get_singleton ( ) - > add_property_hint ( PropertyInfo ( Variant : : FLOAT , " editors/3d/manipulator_gizmo_opacity " , PROPERTY_HINT_RANGE , " 0,1,0.01 " ) ) ;
2019-10-23 11:46:26 +02:00
EDITOR_DEF ( " editors/3d/navigation/show_viewport_rotation_gizmo " , true ) ;
2014-05-05 03:50:23 +02:00
2017-03-05 16:44:50 +01:00
over_gizmo_handle = - 1 ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Node3DEditor : : ~ Node3DEditor ( ) {
2017-09-02 21:47:16 +02:00
memdelete ( preview_node ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : make_visible ( bool p_visible ) {
2014-02-10 02:10:30 +01:00
if ( p_visible ) {
spatial_editor - > show ( ) ;
spatial_editor - > set_process ( true ) ;
} else {
spatial_editor - > hide ( ) ;
spatial_editor - > set_process ( false ) ;
}
}
2020-05-14 14:29:06 +02:00
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : edit ( Object * p_object ) {
spatial_editor - > edit ( Object : : cast_to < Node3D > ( p_object ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
bool Node3DEditorPlugin : : handles ( Object * p_object ) const {
return p_object - > is_class ( " Node3D " ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Dictionary Node3DEditorPlugin : : get_state ( ) const {
2014-02-10 02:10:30 +01:00
return spatial_editor - > get_state ( ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : set_state ( const Dictionary & p_state ) {
2014-02-10 02:10:30 +01:00
spatial_editor - > set_state ( p_state ) ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : snap_cursor_to_plane ( const Plane & p_plane ) {
2017-01-14 12:26:56 +01:00
//cursor.pos=p_plane.project(cursor.pos);
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Vector3 Node3DEditor : : snap_point ( Vector3 p_target , Vector3 p_start ) const {
2017-09-18 23:44:04 +02:00
if ( is_snap_enabled ( ) ) {
p_target . x = Math : : snap_scalar ( 0.0 , get_translate_snap ( ) , p_target . x ) ;
p_target . y = Math : : snap_scalar ( 0.0 , get_translate_snap ( ) , p_target . y ) ;
p_target . z = Math : : snap_scalar ( 0.0 , get_translate_snap ( ) , p_target . z ) ;
}
return p_target ;
}
2020-03-26 22:49:16 +01:00
float Node3DEditor : : get_translate_snap ( ) const {
2019-04-09 17:55:44 +02:00
float snap_value ;
2020-04-28 15:19:37 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ) {
2020-07-24 20:07:57 +02:00
snap_value = snap_translate - > get_text ( ) . to_float ( ) / 10.0 ;
2019-04-09 17:55:44 +02:00
} else {
2020-07-24 20:07:57 +02:00
snap_value = snap_translate - > get_text ( ) . to_float ( ) ;
2019-04-09 17:55:44 +02:00
}
return snap_value ;
}
2020-03-26 22:49:16 +01:00
float Node3DEditor : : get_rotate_snap ( ) const {
2019-04-09 17:55:44 +02:00
float snap_value ;
2020-04-28 15:19:37 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ) {
2020-07-24 20:07:57 +02:00
snap_value = snap_rotate - > get_text ( ) . to_float ( ) / 3.0 ;
2019-04-09 17:55:44 +02:00
} else {
2020-07-24 20:07:57 +02:00
snap_value = snap_rotate - > get_text ( ) . to_float ( ) ;
2019-04-09 17:55:44 +02:00
}
return snap_value ;
}
2020-03-26 22:49:16 +01:00
float Node3DEditor : : get_scale_snap ( ) const {
2019-04-09 17:55:44 +02:00
float snap_value ;
2020-04-28 15:19:37 +02:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ) {
2020-07-24 20:07:57 +02:00
snap_value = snap_scale - > get_text ( ) . to_float ( ) / 2.0 ;
2019-04-09 17:55:44 +02:00
} else {
2020-07-24 20:07:57 +02:00
snap_value = snap_scale - > get_text ( ) . to_float ( ) ;
2019-04-09 17:55:44 +02:00
}
return snap_value ;
}
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : _bind_methods ( ) {
ClassDB : : bind_method ( " snap_cursor_to_plane " , & Node3DEditorPlugin : : snap_cursor_to_plane ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditorPlugin : : snap_cursor_to_plane ( const Plane & p_plane ) {
2014-02-10 02:10:30 +01:00
spatial_editor - > snap_cursor_to_plane ( p_plane ) ;
}
2019-03-12 00:30:50 +01:00
struct _GizmoPluginPriorityComparator {
2020-03-26 22:49:16 +01:00
bool operator ( ) ( const Ref < EditorNode3DGizmoPlugin > & p_a , const Ref < EditorNode3DGizmoPlugin > & p_b ) const {
2019-03-12 00:30:50 +01:00
if ( p_a - > get_priority ( ) = = p_b - > get_priority ( ) ) {
return p_a - > get_name ( ) < p_b - > get_name ( ) ;
}
return p_a - > get_priority ( ) > p_b - > get_priority ( ) ;
}
} ;
struct _GizmoPluginNameComparator {
2020-03-26 22:49:16 +01:00
bool operator ( ) ( const Ref < EditorNode3DGizmoPlugin > & p_a , const Ref < EditorNode3DGizmoPlugin > & p_b ) const {
2019-03-12 00:30:50 +01:00
return p_a - > get_name ( ) < p_b - > get_name ( ) ;
}
} ;
2020-03-26 22:49:16 +01:00
void Node3DEditor : : add_gizmo_plugin ( Ref < EditorNode3DGizmoPlugin > p_plugin ) {
2019-01-25 12:57:32 +01:00
ERR_FAIL_NULL ( p_plugin . ptr ( ) ) ;
2019-03-12 00:30:50 +01:00
gizmo_plugins_by_priority . push_back ( p_plugin ) ;
gizmo_plugins_by_priority . sort_custom < _GizmoPluginPriorityComparator > ( ) ;
gizmo_plugins_by_name . push_back ( p_plugin ) ;
gizmo_plugins_by_name . sort_custom < _GizmoPluginNameComparator > ( ) ;
2018-10-29 11:30:28 +01:00
_update_gizmos_menu ( ) ;
2020-03-26 22:49:16 +01:00
Node3DEditor : : get_singleton ( ) - > update_all_gizmos ( ) ;
2018-10-29 11:30:28 +01:00
}
2020-03-26 22:49:16 +01:00
void Node3DEditor : : remove_gizmo_plugin ( Ref < EditorNode3DGizmoPlugin > p_plugin ) {
2019-03-12 00:30:50 +01:00
gizmo_plugins_by_priority . erase ( p_plugin ) ;
gizmo_plugins_by_name . erase ( p_plugin ) ;
2018-10-29 11:30:28 +01:00
_update_gizmos_menu ( ) ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
Node3DEditorPlugin : : Node3DEditorPlugin ( EditorNode * p_node ) {
2017-03-05 16:44:50 +01:00
editor = p_node ;
2020-03-26 22:49:16 +01:00
spatial_editor = memnew ( Node3DEditor ( p_node ) ) ;
2016-02-08 17:01:54 +01:00
spatial_editor - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2020-12-28 19:51:39 +01:00
editor - > get_main_control ( ) - > add_child ( spatial_editor ) ;
2016-02-08 17:01:54 +01:00
2014-02-10 02:10:30 +01:00
spatial_editor - > hide ( ) ;
2020-12-05 22:01:27 +01:00
spatial_editor - > connect ( " transform_key_request " , Callable ( editor - > get_inspector_dock ( ) , " _transform_keyed " ) ) ;
2014-02-10 02:10:30 +01:00
}
2020-03-26 22:49:16 +01:00
Node3DEditorPlugin : : ~ Node3DEditorPlugin ( ) {
2014-02-10 02:10:30 +01:00
}
2018-07-25 00:08:49 +02:00
2020-03-26 22:49:16 +01: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 ) {
2018-09-02 22:31:03 +02:00
Color instanced_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/instanced " , Color ( 0.7 , 0.7 , 0.7 , 0.6 ) ) ;
2018-07-25 00:08:49 +02:00
2020-03-17 07:33:00 +01:00
Vector < Ref < StandardMaterial3D > > mats ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
bool selected = i % 2 = = 1 ;
bool instanced = i < 2 ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
2018-07-25 00:08:49 +02:00
Color color = instanced ? instanced_color : p_color ;
if ( ! selected ) {
color . a * = 0.3 ;
}
material - > set_albedo ( color ) ;
2019-09-15 06:01:52 +02:00
material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
material - > set_render_priority ( StandardMaterial3D : : RENDER_PRIORITY_MIN + 1 ) ;
2018-07-25 00:08:49 +02:00
if ( p_use_vertex_color ) {
2019-09-15 06:01:52 +02:00
material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
2018-07-25 00:08:49 +02:00
}
if ( p_billboard ) {
2019-09-15 06:01:52 +02:00
material - > set_billboard_mode ( StandardMaterial3D : : BILLBOARD_ENABLED ) ;
2018-07-25 00:08:49 +02:00
}
if ( p_on_top & & selected ) {
material - > set_on_top_of_alpha ( ) ;
}
mats . push_back ( material ) ;
}
materials [ p_name ] = mats ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : create_icon_material ( const String & p_name , const Ref < Texture2D > & p_texture , bool p_on_top , const Color & p_albedo ) {
2018-09-02 22:31:03 +02:00
Color instanced_color = EDITOR_DEF ( " editors/3d_gizmos/gizmo_colors/instanced " , Color ( 0.7 , 0.7 , 0.7 , 0.6 ) ) ;
2018-07-25 00:08:49 +02:00
2020-03-17 07:33:00 +01:00
Vector < Ref < StandardMaterial3D > > icons ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < 4 ; i + + ) {
bool selected = i % 2 = = 1 ;
bool instanced = i < 2 ;
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > icon = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
2018-07-25 00:08:49 +02:00
Color color = instanced ? instanced_color : p_albedo ;
if ( ! selected ) {
2018-09-02 22:31:03 +02:00
color . a * = 0.85 ;
2018-07-25 00:08:49 +02:00
}
icon - > set_albedo ( color ) ;
2019-09-15 06:01:52 +02:00
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 ) ;
2018-07-25 00:08:49 +02:00
if ( p_on_top & & selected ) {
icon - > set_on_top_of_alpha ( ) ;
}
icons . push_back ( icon ) ;
}
materials [ p_name ] = icons ;
}
2020-11-09 04:16:26 +01:00
void EditorNode3DGizmoPlugin : : create_handle_material ( const String & p_name , bool p_billboard , const Ref < Texture2D > & p_icon ) {
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > handle_material = Ref < StandardMaterial3D > ( memnew ( StandardMaterial3D ) ) ;
2018-07-25 00:08:49 +02:00
2019-09-15 06:01:52 +02:00
handle_material - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
handle_material - > set_flag ( StandardMaterial3D : : FLAG_USE_POINT_SIZE , true ) ;
2020-11-09 04:16:26 +01:00
Ref < Texture2D > handle_t = p_icon ! = nullptr ? p_icon : Node3DEditor : : get_singleton ( ) - > get_theme_icon ( " Editor3DHandle " , " EditorIcons " ) ;
2018-07-25 00:08:49 +02:00
handle_material - > set_point_size ( handle_t - > get_width ( ) ) ;
2019-09-15 06:01:52 +02:00
handle_material - > set_texture ( StandardMaterial3D : : TEXTURE_ALBEDO , handle_t ) ;
2018-07-25 00:08:49 +02:00
handle_material - > set_albedo ( Color ( 1 , 1 , 1 ) ) ;
2019-09-15 06:01:52 +02:00
handle_material - > set_flag ( StandardMaterial3D : : FLAG_ALBEDO_FROM_VERTEX_COLOR , true ) ;
handle_material - > set_flag ( StandardMaterial3D : : FLAG_SRGB_VERTEX_COLOR , true ) ;
2018-07-25 00:08:49 +02:00
handle_material - > set_on_top_of_alpha ( ) ;
if ( p_billboard ) {
2019-09-15 06:01:52 +02:00
handle_material - > set_billboard_mode ( StandardMaterial3D : : BILLBOARD_ENABLED ) ;
2018-07-25 00:08:49 +02:00
handle_material - > set_on_top_of_alpha ( ) ;
}
2020-10-25 19:37:09 +01:00
handle_material - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2018-07-25 00:08:49 +02:00
2020-03-17 07:33:00 +01:00
materials [ p_name ] = Vector < Ref < StandardMaterial3D > > ( ) ;
2018-07-25 00:08:49 +02:00
materials [ p_name ] . push_back ( handle_material ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : add_material ( const String & p_name , Ref < StandardMaterial3D > p_material ) {
2020-03-17 07:33:00 +01:00
materials [ p_name ] = Vector < Ref < StandardMaterial3D > > ( ) ;
2018-07-25 00:08:49 +02:00
materials [ p_name ] . push_back ( p_material ) ;
}
2020-03-26 22:49:16 +01:00
Ref < StandardMaterial3D > EditorNode3DGizmoPlugin : : get_material ( const String & p_name , const Ref < EditorNode3DGizmo > & p_gizmo ) {
2019-09-15 06:01:52 +02:00
ERR_FAIL_COND_V ( ! materials . has ( p_name ) , Ref < StandardMaterial3D > ( ) ) ;
ERR_FAIL_COND_V ( materials [ p_name ] . size ( ) = = 0 , Ref < StandardMaterial3D > ( ) ) ;
2018-07-25 00:08:49 +02:00
2020-05-14 16:41:43 +02:00
if ( p_gizmo . is_null ( ) | | materials [ p_name ] . size ( ) = = 1 ) {
2020-05-10 12:56:01 +02:00
return materials [ p_name ] [ 0 ] ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
int index = ( p_gizmo - > is_selected ( ) ? 1 : 0 ) + ( p_gizmo - > is_editable ( ) ? 2 : 0 ) ;
2018-08-11 23:07:00 +02:00
2019-09-15 06:01:52 +02:00
Ref < StandardMaterial3D > mat = materials [ p_name ] [ index ] ;
2018-08-11 23:07:00 +02:00
if ( current_state = = ON_TOP & & p_gizmo - > is_selected ( ) ) {
2019-09-15 06:01:52 +02:00
mat - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_DEPTH_TEST , true ) ;
2018-08-11 23:07:00 +02:00
} else {
2019-09-15 06:01:52 +02:00
mat - > set_flag ( StandardMaterial3D : : FLAG_DISABLE_DEPTH_TEST , false ) ;
2018-08-11 23:07:00 +02:00
}
return mat ;
2018-07-25 00:08:49 +02:00
}
2020-07-23 00:39:21 +02:00
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 " ) ;
2018-10-29 11:30:28 +01:00
}
2019-01-25 12:57:32 +01:00
return TTR ( " Nameless gizmo " ) ;
2018-10-29 11:30:28 +01:00
}
2020-03-26 22:49:16 +01:00
int EditorNode3DGizmoPlugin : : get_priority ( ) const {
2019-03-12 00:30:50 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " get_priority " ) ) {
return get_script_instance ( ) - > call ( " get_priority " ) ;
}
return 0 ;
}
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > EditorNode3DGizmoPlugin : : get_gizmo ( Node3D * p_spatial ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " get_gizmo " ) ) {
return get_script_instance ( ) - > call ( " get_gizmo " , p_spatial ) ;
}
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > ref = create_gizmo ( p_spatial ) ;
2018-07-25 00:08:49 +02:00
2020-05-14 16:41:43 +02:00
if ( ref . is_null ( ) ) {
2020-05-10 12:56:01 +02:00
return ref ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
ref - > set_plugin ( this ) ;
ref - > set_spatial_node ( p_spatial ) ;
2018-08-11 23:07:00 +02:00
ref - > set_hidden ( current_state = = HIDDEN ) ;
2018-07-25 00:08:49 +02:00
current_gizmos . push_back ( ref . ptr ( ) ) ;
return ref ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : _bind_methods ( ) {
# define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
2018-10-29 11:30:28 +01:00
2020-03-26 22:49:16 +01:00
BIND_VMETHOD ( MethodInfo ( Variant : : BOOL , " has_gizmo " , PropertyInfo ( Variant : : OBJECT , " spatial " , PROPERTY_HINT_RESOURCE_TYPE , " Node3D " ) ) ) ;
BIND_VMETHOD ( MethodInfo ( GIZMO_REF , " create_gizmo " , PropertyInfo ( Variant : : OBJECT , " spatial " , PROPERTY_HINT_RESOURCE_TYPE , " Node3D " ) ) ) ;
2018-10-29 11:30:28 +01:00
2020-03-26 22:49:16 +01:00
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 ) ) ) ;
2020-11-09 04:16:26 +01:00
ClassDB : : bind_method ( D_METHOD ( " create_handle_material " , " name " , " billboard " , " texture " ) , & EditorNode3DGizmoPlugin : : create_handle_material , DEFVAL ( false ) , DEFVAL ( Variant ( ) ) ) ;
2020-03-26 22:49:16 +01:00
ClassDB : : bind_method ( D_METHOD ( " add_material " , " name " , " material " ) , & EditorNode3DGizmoPlugin : : add_material ) ;
2018-10-29 11:30:28 +01:00
2020-11-25 18:45:10 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_material " , " name " , " gizmo " ) , & EditorNode3DGizmoPlugin : : get_material , DEFVAL ( Ref < EditorNode3DGizmo > ( ) ) ) ;
2018-10-29 11:30:28 +01:00
BIND_VMETHOD ( MethodInfo ( Variant : : STRING , " get_name " ) ) ;
2020-07-17 20:45:54 +02:00
BIND_VMETHOD ( MethodInfo ( Variant : : INT , " get_priority " ) ) ;
2018-10-29 11:30:28 +01:00
BIND_VMETHOD ( MethodInfo ( Variant : : BOOL , " can_be_hidden " ) ) ;
BIND_VMETHOD ( MethodInfo ( Variant : : BOOL , " is_selectable_when_hidden " ) ) ;
BIND_VMETHOD ( MethodInfo ( " redraw " , GIZMO_REF ) ) ;
BIND_VMETHOD ( MethodInfo ( Variant : : STRING , " get_handle_name " , GIZMO_REF , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
MethodInfo hvget ( Variant : : NIL , " get_handle_value " , GIZMO_REF , PropertyInfo ( Variant : : INT , " index " ) ) ;
hvget . return_val . usage | = PROPERTY_USAGE_NIL_IS_VARIANT ;
BIND_VMETHOD ( hvget ) ;
2020-03-26 22:49:16 +01:00
BIND_VMETHOD ( MethodInfo ( " set_handle " , GIZMO_REF , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : OBJECT , " camera " , PROPERTY_HINT_RESOURCE_TYPE , " Camera3D " ) , PropertyInfo ( Variant : : VECTOR2 , " point " ) ) ) ;
2018-10-29 11:30:28 +01:00
MethodInfo cm = MethodInfo ( " commit_handle " , GIZMO_REF , PropertyInfo ( Variant : : INT , " index " ) , PropertyInfo ( Variant : : NIL , " restore " ) , PropertyInfo ( Variant : : BOOL , " cancel " ) ) ;
cm . default_arguments . push_back ( false ) ;
BIND_VMETHOD ( cm ) ;
2019-01-25 12:57:32 +01:00
BIND_VMETHOD ( MethodInfo ( Variant : : BOOL , " is_handle_highlighted " , GIZMO_REF , PropertyInfo ( Variant : : INT , " index " ) ) ) ;
2018-10-29 11:30:28 +01:00
# undef GIZMO_REF
}
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmoPlugin : : has_gizmo ( Node3D * p_spatial ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " has_gizmo " ) ) {
return get_script_instance ( ) - > call ( " has_gizmo " , p_spatial ) ;
}
2018-07-25 00:08:49 +02:00
return false ;
}
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > EditorNode3DGizmoPlugin : : create_gizmo ( Node3D * p_spatial ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " create_gizmo " ) ) {
return get_script_instance ( ) - > call ( " create_gizmo " , p_spatial ) ;
}
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > ref ;
2020-05-14 16:41:43 +02:00
if ( has_gizmo ( p_spatial ) ) {
2020-05-10 12:56:01 +02:00
ref . instance ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 00:08:49 +02:00
return ref ;
}
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmoPlugin : : can_be_hidden ( ) const {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " can_be_hidden " ) ) {
return get_script_instance ( ) - > call ( " can_be_hidden " ) ;
}
2018-07-25 00:08:49 +02:00
return true ;
}
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmoPlugin : : is_selectable_when_hidden ( ) const {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " is_selectable_when_hidden " ) ) {
return get_script_instance ( ) - > call ( " is_selectable_when_hidden " ) ;
}
return false ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : redraw ( EditorNode3DGizmo * p_gizmo ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " redraw " ) ) {
2020-03-26 22:49:16 +01:00
Ref < EditorNode3DGizmo > ref ( p_gizmo ) ;
2018-10-29 11:30:28 +01:00
get_script_instance ( ) - > call ( " redraw " , ref ) ;
}
}
2020-03-26 22:49:16 +01:00
String EditorNode3DGizmoPlugin : : get_handle_name ( const EditorNode3DGizmo * p_gizmo , int p_idx ) const {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " get_handle_name " ) ) {
return get_script_instance ( ) - > call ( " get_handle_name " , p_gizmo , p_idx ) ;
}
return " " ;
}
2020-03-26 22:49:16 +01:00
Variant EditorNode3DGizmoPlugin : : get_handle_value ( EditorNode3DGizmo * p_gizmo , int p_idx ) const {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " get_handle_value " ) ) {
return get_script_instance ( ) - > call ( " get_handle_value " , p_gizmo , p_idx ) ;
}
return Variant ( ) ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : set_handle ( EditorNode3DGizmo * p_gizmo , int p_idx , Camera3D * p_camera , const Point2 & p_point ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " set_handle " ) ) {
get_script_instance ( ) - > call ( " set_handle " , p_gizmo , p_idx , p_camera , p_point ) ;
}
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : commit_handle ( EditorNode3DGizmo * p_gizmo , int p_idx , const Variant & p_restore , bool p_cancel ) {
2018-10-29 11:30:28 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " commit_handle " ) ) {
get_script_instance ( ) - > call ( " commit_handle " , p_gizmo , p_idx , p_restore , p_cancel ) ;
}
}
2020-03-26 22:49:16 +01:00
bool EditorNode3DGizmoPlugin : : is_handle_highlighted ( const EditorNode3DGizmo * p_gizmo , int p_idx ) const {
2019-01-25 12:57:32 +01:00
if ( get_script_instance ( ) & & get_script_instance ( ) - > has_method ( " is_handle_highlighted " ) ) {
return get_script_instance ( ) - > call ( " is_handle_highlighted " , p_gizmo , p_idx ) ;
2018-10-29 11:30:28 +01:00
}
2018-07-25 00:08:49 +02:00
return false ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : set_state ( int p_state ) {
2018-08-11 23:07:00 +02:00
current_state = p_state ;
2018-07-25 00:08:49 +02:00
for ( int i = 0 ; i < current_gizmos . size ( ) ; + + i ) {
2018-08-11 23:07:00 +02:00
current_gizmos [ i ] - > set_hidden ( current_state = = HIDDEN ) ;
2018-07-25 00:08:49 +02:00
}
}
2020-03-26 22:49:16 +01:00
int EditorNode3DGizmoPlugin : : get_state ( ) const {
2019-03-12 00:30:50 +01:00
return current_state ;
}
2020-03-26 22:49:16 +01:00
void EditorNode3DGizmoPlugin : : unregister_gizmo ( EditorNode3DGizmo * p_gizmo ) {
2018-07-25 00:08:49 +02:00
current_gizmos . erase ( p_gizmo ) ;
}
2020-03-26 22:49:16 +01:00
EditorNode3DGizmoPlugin : : EditorNode3DGizmoPlugin ( ) {
2018-11-18 22:01:09 +01:00
current_state = VISIBLE ;
2018-07-25 00:08:49 +02:00
}
2020-03-26 22:49:16 +01:00
EditorNode3DGizmoPlugin : : ~ EditorNode3DGizmoPlugin ( ) {
2018-10-29 11:30:28 +01:00
for ( int i = 0 ; i < current_gizmos . size ( ) ; + + i ) {
2020-04-02 01:20:12 +02:00
current_gizmos [ i ] - > set_plugin ( nullptr ) ;
current_gizmos [ i ] - > get_spatial_node ( ) - > set_gizmo ( nullptr ) ;
2018-10-29 11:30:28 +01:00
}
2020-03-26 22:49:16 +01:00
if ( Node3DEditor : : get_singleton ( ) ) {
Node3DEditor : : get_singleton ( ) - > update_all_gizmos ( ) ;
2019-09-28 11:04:50 +02:00
}
2018-07-25 00:08:49 +02:00
}