2014-02-10 01:10:30 +00:00
/*************************************************************************/
2020-03-27 07:44:44 +00:00
/* node_3d_editor_plugin.cpp */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 12:16:55 +00:00
/* https://godotengine.org */
2014-02-10 01:10:30 +00:00
/*************************************************************************/
2022-01-03 20:27:34 +00:00
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
2014-02-10 01:10:30 +00: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-04 23:50:27 +00:00
2020-03-27 07:44:44 +00:00
# include "node_3d_editor_plugin.h"
2014-02-10 01:10:30 +00:00
2020-11-07 22:33:38 +00:00
# include "core/config/project_settings.h"
2020-04-28 13:19:37 +00:00
# include "core/input/input.h"
2021-11-02 15:02:31 +00:00
# include "core/input/input_map.h"
2018-09-04 09:30:04 +00:00
# include "core/math/camera_matrix.h"
2021-02-22 21:20:44 +00:00
# include "core/math/math_funcs.h"
2018-09-04 09:30:04 +00:00
# include "core/os/keyboard.h"
2020-11-07 22:33:38 +00:00
# include "core/templates/sort_array.h"
2020-02-07 01:52:05 +00:00
# include "editor/debugger/editor_debugger_node.h"
2017-03-05 13:21:25 +00:00
# include "editor/editor_node.h"
# include "editor/editor_settings.h"
2017-03-05 15:44:50 +00:00
# include "editor/plugins/animation_player_editor_plugin.h"
2021-06-23 14:49:50 +00:00
# include "editor/plugins/node_3d_editor_gizmos.h"
2017-09-02 19:47:16 +00:00
# include "editor/plugins/script_editor_plugin.h"
2022-02-12 01:46:22 +00:00
# include "editor/scene_tree_dock.h"
2020-03-26 21:49:16 +00:00
# include "scene/3d/camera_3d.h"
# include "scene/3d/collision_shape_3d.h"
2021-06-23 14:49:50 +00:00
# include "scene/3d/light_3d.h"
2020-03-26 21:49:16 +00:00
# include "scene/3d/mesh_instance_3d.h"
# include "scene/3d/physics_body_3d.h"
# include "scene/3d/visual_instance_3d.h"
2021-06-23 14:49:50 +00:00
# include "scene/3d/world_environment.h"
2021-02-22 13:54:12 +00:00
# include "scene/gui/center_container.h"
2022-07-20 01:00:25 +00:00
# include "scene/gui/flow_container.h"
2020-04-01 18:28:09 +00:00
# include "scene/gui/subviewport_container.h"
2017-09-02 19:47:16 +00:00
# include "scene/resources/packed_scene.h"
2017-03-05 15:44:50 +00:00
# include "scene/resources/surface_tool.h"
2016-01-17 23:03:57 +00:00
2022-03-08 14:10:48 +00:00
constexpr real_t DISTANCE_DEFAULT = 4 ;
2014-02-10 01:10:30 +00:00
2022-03-08 14:10:48 +00:00
constexpr real_t GIZMO_ARROW_SIZE = 0.35 ;
constexpr real_t GIZMO_RING_HALF_WIDTH = 0.1 ;
constexpr real_t GIZMO_PLANE_SIZE = 0.2 ;
constexpr real_t GIZMO_PLANE_DST = 0.3 ;
constexpr real_t GIZMO_CIRCLE_SIZE = 1.1 ;
constexpr real_t GIZMO_SCALE_OFFSET = GIZMO_CIRCLE_SIZE + 0.3 ;
constexpr real_t GIZMO_ARROW_OFFSET = GIZMO_CIRCLE_SIZE + 0.3 ;
2014-02-10 01:10:30 +00:00
2022-03-08 14:10:48 +00:00
constexpr real_t ZOOM_FREELOOK_MIN = 0.01 ;
constexpr real_t ZOOM_FREELOOK_MULTIPLIER = 1.08 ;
constexpr real_t ZOOM_FREELOOK_INDICATOR_DELAY_S = 1.5 ;
2017-05-07 20:59:05 +00:00
2020-06-22 03:40:17 +00:00
# ifdef REAL_T_IS_DOUBLE
2022-03-08 14:10:48 +00:00
constexpr double ZOOM_FREELOOK_MAX = 1'000'000'000'000 ;
2020-06-22 03:40:17 +00:00
# else
2022-03-08 14:10:48 +00:00
constexpr float ZOOM_FREELOOK_MAX = 10'000 ;
2020-06-22 03:40:17 +00:00
# endif
2017-05-07 20:59:05 +00:00
2022-03-08 14:10:48 +00:00
constexpr real_t MIN_Z = 0.01 ;
constexpr real_t MAX_Z = 1000000.0 ;
2017-08-04 11:23:10 +00:00
2022-03-08 14:10:48 +00:00
constexpr real_t MIN_FOV = 0.01 ;
constexpr real_t MAX_FOV = 179 ;
2017-08-04 11:23:10 +00:00
2019-10-23 09:46:26 +00:00
void ViewportRotationControl : : _notification ( int p_what ) {
2022-02-16 02:44:22 +00:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
axis_menu_options . clear ( ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_RIGHT ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_TOP ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_REAR ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_LEFT ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_BOTTOM ) ;
axis_menu_options . push_back ( Node3DEditorViewport : : VIEW_FRONT ) ;
axis_colors . clear ( ) ;
axis_colors . push_back ( get_theme_color ( SNAME ( " axis_x_color " ) , SNAME ( " Editor " ) ) ) ;
axis_colors . push_back ( get_theme_color ( SNAME ( " axis_y_color " ) , SNAME ( " Editor " ) ) ) ;
axis_colors . push_back ( get_theme_color ( SNAME ( " axis_z_color " ) , SNAME ( " Editor " ) ) ) ;
update ( ) ;
2019-10-23 09:46:26 +00:00
2022-02-16 02:44:22 +00:00
if ( ! is_connected ( " mouse_exited " , callable_mp ( this , & ViewportRotationControl : : _on_mouse_exited ) ) ) {
connect ( " mouse_exited " , callable_mp ( this , & ViewportRotationControl : : _on_mouse_exited ) ) ;
}
} break ;
2019-10-23 09:46:26 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_DRAW : {
if ( viewport ! = nullptr ) {
_draw ( ) ;
}
} break ;
2019-10-23 09:46:26 +00:00
}
}
void ViewportRotationControl : : _draw ( ) {
2021-06-21 03:30:19 +00:00
const Vector2i center = get_size ( ) / 2.0 ;
const real_t radius = get_size ( ) . x / 2.0 ;
2019-10-23 09:46:26 +00:00
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 ) {
2021-08-06 16:31:43 +00:00
const bool focused = focused_axis = = p_axis . axis ;
const bool positive = p_axis . axis < 3 ;
const int direction = p_axis . axis % 3 ;
2019-10-23 09:46:26 +00:00
2021-08-06 16:31:43 +00:00
const Color axis_color = axis_colors [ direction ] ;
const double alpha = focused ? 1.0 : ( ( p_axis . z_axis + 1.0 ) / 2.0 ) * 0.5 + 0.5 ;
2021-09-23 14:58:43 +00:00
const Color c = focused ? Color ( 0.9 , 0.9 , 0.9 ) : Color ( axis_color , alpha ) ;
2019-10-23 09:46:26 +00:00
if ( positive ) {
2021-08-06 16:31:43 +00:00
// Draw axis lines for the positive axes.
const Vector2i center = get_size ( ) / 2.0 ;
2019-10-23 09:46:26 +00:00
draw_line ( center , p_axis . screen_point , c , 1.5 * EDSCALE ) ;
draw_circle ( p_axis . screen_point , AXIS_CIRCLE_RADIUS , c ) ;
2021-08-06 16:31:43 +00:00
// Draw the axis letter for the positive axes.
const String axis_name = direction = = 0 ? " X " : ( direction = = 1 ? " Y " : " Z " ) ;
2022-05-09 09:47:10 +00:00
draw_char ( get_theme_font ( SNAME ( " rotation_control " ) , SNAME ( " EditorFonts " ) ) , p_axis . screen_point + Vector2i ( Math : : round ( - 4.0 * EDSCALE ) , Math : : round ( 5.0 * EDSCALE ) ) , axis_name , get_theme_font_size ( SNAME ( " rotation_control_size " ) , SNAME ( " EditorFonts " ) ) , Color ( 0.0 , 0.0 , 0.0 , alpha ) ) ;
2019-10-23 09:46:26 +00:00
} else {
2021-08-06 16:31:43 +00:00
// Draw an outline around the negative axes.
draw_circle ( p_axis . screen_point , AXIS_CIRCLE_RADIUS , c ) ;
draw_circle ( p_axis . screen_point , AXIS_CIRCLE_RADIUS * 0.8 , c . darkened ( 0.4 ) ) ;
2019-10-23 09:46:26 +00:00
}
}
void ViewportRotationControl : : _get_sorted_axis ( Vector < Axis2D > & r_axis ) {
2021-06-21 03:30:19 +00:00
const Vector2i center = get_size ( ) / 2.0 ;
const real_t radius = get_size ( ) . x / 2.0 - AXIS_CIRCLE_RADIUS - 2.0 * EDSCALE ;
const Basis camera_basis = viewport - > to_camera_transform ( viewport - > cursor ) . get_basis ( ) . inverse ( ) ;
2019-10-23 09:46:26 +00:00
for ( int i = 0 ; i < 3 ; + + i ) {
2022-05-03 12:50:35 +00:00
Vector3 axis_3d = camera_basis . get_column ( i ) ;
2021-06-21 03:30:19 +00:00
Vector2i axis_vector = Vector2 ( axis_3d . x , - axis_3d . y ) * radius ;
2019-10-23 09:46:26 +00:00
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 > ( ) ;
}
2021-08-22 15:37:22 +00:00
void ViewportRotationControl : : gui_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 06:52:21 +00:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2019-10-23 09:46:26 +00:00
const Ref < InputEventMouseButton > mb = p_event ;
2021-08-13 21:31:57 +00:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2019-10-23 09:46:26 +00:00
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 14:41:01 +00:00
if ( Input : : get_singleton ( ) - > get_mouse_mode ( ) = = Input : : MOUSE_MODE_CAPTURED ) {
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
2022-03-27 09:17:36 +00:00
Input : : get_singleton ( ) - > warp_mouse ( orbiting_mouse_start ) ;
2020-04-28 14:41:01 +00:00
}
2019-10-23 09:46:26 +00:00
}
}
const Ref < InputEventMouseMotion > mm = p_event ;
if ( mm . is_valid ( ) ) {
if ( orbiting ) {
2020-04-28 14:41:01 +00: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 09:46:26 +00: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 21:49:16 +00:00
void ViewportRotationControl : : set_viewport ( Node3DEditorViewport * p_viewport ) {
2019-10-23 09:46:26 +00:00
viewport = p_viewport ;
}
2021-10-14 22:00:27 +00:00
void Node3DEditorViewport : : _view_settings_confirmed ( real_t p_interp_delta ) {
// Set FOV override multiplier back to the default, so that the FOV
// setting specified in the View menu is correctly applied.
cursor . fov_scale = 1.0 ;
_update_camera ( p_interp_delta ) ;
}
2021-06-21 03:30:19 +00:00
void Node3DEditorViewport : : _update_camera ( real_t p_interp_delta ) {
2020-03-26 21:49:16 +00:00
bool is_orthogonal = camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ;
2016-04-06 06:34:34 +00:00
2017-10-08 00:43:57 +00:00
Cursor old_camera_cursor = camera_cursor ;
camera_cursor = cursor ;
2017-09-16 15:12:11 +00:00
2017-10-08 00:43:57 +00:00
if ( p_interp_delta > 0 ) {
//-------
// Perform smoothing
2017-09-16 15:12:11 +00:00
2017-10-08 00:43:57 +00: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.
2020-01-13 23:26:26 +00:00
const real_t inertia = EDITOR_GET ( " editors/3d/freelook/freelook_inertia " ) ;
2017-10-08 00:43:57 +00:00
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 09:07:33 +00:00
camera_cursor . eye_pos = old_camera_cursor . eye_pos . lerp ( cursor . eye_pos , CLAMP ( factor , 0 , 1 ) ) ;
2017-10-08 00:43:57 +00:00
2020-01-13 23:26:26 +00:00
const real_t orbit_inertia = EDITOR_GET ( " editors/3d/navigation_feel/orbit_inertia " ) ;
2017-10-08 00:43:57 +00:00
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 09:46:26 +00: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 00:43:57 +00: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 {
2020-01-13 23:26:26 +00:00
const real_t orbit_inertia = EDITOR_GET ( " editors/3d/navigation_feel/orbit_inertia " ) ;
const real_t translation_inertia = EDITOR_GET ( " editors/3d/navigation_feel/translation_inertia " ) ;
const real_t zoom_inertia = EDITOR_GET ( " editors/3d/navigation_feel/zoom_inertia " ) ;
2017-10-08 00:43:57 +00:00
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 09:46:26 +00: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 09:07:33 +00:00
camera_cursor . pos = old_camera_cursor . pos . lerp ( cursor . pos , MIN ( 1.f , p_interp_delta * ( 1 / translation_inertia ) ) ) ;
2021-06-21 03:30:19 +00:00
camera_cursor . distance = Math : : lerp ( old_camera_cursor . distance , cursor . distance , MIN ( ( real_t ) 1.0 , p_interp_delta * ( 1 / zoom_inertia ) ) ) ;
2017-10-08 00:43:57 +00:00
}
2017-08-26 03:40:45 +00:00
}
2017-10-08 00:43:57 +00:00
//-------
// Apply camera transform
2019-04-21 10:15:45 +00:00
real_t tolerance = 0.001 ;
2017-08-26 03:40:45 +00:00
bool equal = true ;
2019-04-21 10:15:45 +00: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 17:53:00 +00:00
equal = false ;
2019-04-21 10:15:45 +00:00
} else if ( ! old_camera_cursor . pos . is_equal_approx ( camera_cursor . pos ) ) {
2017-08-26 03:40:45 +00:00
equal = false ;
2019-04-21 10:15:45 +00:00
} else if ( ! Math : : is_equal_approx ( old_camera_cursor . distance , camera_cursor . distance , tolerance ) ) {
2017-09-06 17:53:00 +00:00
equal = false ;
2021-10-14 22:00:27 +00:00
} else if ( ! Math : : is_equal_approx ( old_camera_cursor . fov_scale , camera_cursor . fov_scale , tolerance ) ) {
equal = false ;
2017-09-23 20:27:29 +00:00
}
2017-08-26 03:40:45 +00:00
2021-05-23 17:50:53 +00:00
if ( ! equal | | p_interp_delta = = 0 | | is_orthogonal ! = orthogonal ) {
2017-09-06 17:53:00 +00:00
camera - > set_global_transform ( to_camera_transform ( camera_cursor ) ) ;
2017-09-23 20:27:29 +00:00
2019-10-23 09:46:26 +00:00
if ( orthogonal ) {
float half_fov = Math : : deg2rad ( get_fov ( ) ) / 2.0 ;
float height = 2.0 * cursor . distance * Math : : tan ( half_fov ) ;
2020-04-04 23:16:11 +00:00
camera - > set_orthogonal ( height , get_znear ( ) , get_zfar ( ) ) ;
2019-10-23 09:46:26 +00:00
} else {
2017-09-23 20:27:29 +00:00
camera - > set_perspective ( get_fov ( ) , get_znear ( ) , get_zfar ( ) ) ;
2019-10-23 09:46:26 +00:00
}
2017-12-19 22:54:54 +00:00
update_transform_gizmo_view ( ) ;
2019-10-23 09:46:26 +00:00
rotation_control - > update ( ) ;
2020-11-04 09:03:28 +00:00
spatial_editor - > update_grid ( ) ;
2017-05-01 18:57:35 +00:00
}
}
2020-10-17 05:08:21 +00:00
Transform3D Node3DEditorViewport : : to_camera_transform ( const Cursor & p_cursor ) const {
Transform3D camera_transform ;
2017-05-01 18:57:35 +00: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 06:34:34 +00:00
2020-05-14 14:41:43 +00:00
if ( orthogonal ) {
2020-04-04 23:16:11 +00:00
camera_transform . translate ( 0 , 0 , ( get_zfar ( ) - get_znear ( ) ) / 2.0 ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-05-01 18:57:35 +00:00
camera_transform . translate ( 0 , 0 , p_cursor . distance ) ;
2020-05-14 14:41:43 +00:00
}
2016-04-06 06:34:34 +00:00
2017-05-01 18:57:35 +00:00
return camera_transform ;
2016-04-06 06:34:34 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
int Node3DEditorViewport : : get_selected_count ( ) const {
2022-05-13 13:04:37 +00:00
const HashMap < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
int count = 0 ;
2014-02-10 01:10:30 +00:00
2021-08-09 20:13:42 +00:00
for ( const KeyValue < Node * , Object * > & E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E . key ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 14:41:43 +00:00
if ( ! se ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
count + + ;
}
return count ;
}
2020-07-18 19:03:08 +00:00
void Node3DEditorViewport : : cancel_transform ( ) {
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
sp - > set_global_transform ( se - > original ) ;
}
2022-02-10 13:23:10 +00:00
finish_transform ( ) ;
2020-07-18 19:03:08 +00:00
set_message ( TTR ( " Transform Aborted. " ) , 3 ) ;
}
2022-06-03 00:12:41 +00:00
void Node3DEditorViewport : : _update_shrink ( ) {
bool shrink = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_HALF_RESOLUTION ) ) ;
subviewport_container - > set_stretch_shrink ( shrink ? 2 : 1 ) ;
2022-06-05 16:24:05 +00:00
subviewport_container - > set_texture_filter ( shrink ? TEXTURE_FILTER_NEAREST : TEXTURE_FILTER_PARENT_NODE ) ;
2022-06-03 00:12:41 +00:00
}
2020-03-26 21:49:16 +00:00
float Node3DEditorViewport : : get_znear ( ) const {
2017-08-04 11:23:10 +00:00
return CLAMP ( spatial_editor - > get_znear ( ) , MIN_Z , MAX_Z ) ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
float Node3DEditorViewport : : get_zfar ( ) const {
2017-08-04 11:23:10 +00:00
return CLAMP ( spatial_editor - > get_zfar ( ) , MIN_Z , MAX_Z ) ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
float Node3DEditorViewport : : get_fov ( ) const {
2021-10-14 22:00:27 +00:00
return CLAMP ( spatial_editor - > get_fov ( ) * cursor . fov_scale , MIN_FOV , MAX_FOV ) ;
2014-02-10 01:10:30 +00:00
}
2020-10-17 05:08:21 +00:00
Transform3D Node3DEditorViewport : : _get_camera_transform ( ) const {
2014-02-10 01:10:30 +00:00
return camera - > get_global_transform ( ) ;
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_camera_position ( ) const {
2014-02-10 01:10:30 +00:00
return _get_camera_transform ( ) . origin ;
}
2020-03-26 21:49:16 +00:00
Point2 Node3DEditorViewport : : _point_to_screen ( const Vector3 & p_point ) {
2020-04-01 18:28:09 +00:00
return camera - > unproject_position ( p_point ) * subviewport_container - > get_stretch_shrink ( ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_ray_pos ( const Vector2 & p_pos ) const {
2020-04-01 18:28:09 +00:00
return camera - > project_ray_origin ( p_pos / subviewport_container - > get_stretch_shrink ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_camera_normal ( ) const {
2022-05-03 12:50:35 +00:00
return - _get_camera_transform ( ) . basis . get_column ( 2 ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_ray ( const Vector2 & p_pos ) const {
2020-04-01 18:28:09 +00:00
return camera - > project_ray_normal ( p_pos / subviewport_container - > get_stretch_shrink ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _clear_selected ( ) {
2021-06-23 14:49:50 +00:00
_edit . gizmo = Ref < EditorNode3DGizmo > ( ) ;
_edit . gizmo_handle = - 1 ;
2022-01-11 11:33:37 +00:00
_edit . gizmo_handle_secondary = false ;
2021-06-23 14:49:50 +00:00
_edit . gizmo_initial_value = Variant ( ) ;
Node3D * selected = spatial_editor - > get_single_selected_node ( ) ;
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
if ( se & & se - > gizmo . is_valid ( ) ) {
se - > subgizmos . clear ( ) ;
se - > gizmo - > redraw ( ) ;
se - > gizmo . unref ( ) ;
spatial_editor - > update_transform_gizmo ( ) ;
} else {
editor_selection - > clear ( ) ;
Node3DEditor : : get_singleton ( ) - > edit ( nullptr ) ;
2020-05-14 14:41:43 +00:00
}
2021-06-23 14:49:50 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
void Node3DEditorViewport : : _select_clicked ( bool p_allow_locked ) {
Node * node = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( clicked ) ) ;
2020-03-26 21:49:16 +00:00
Node3D * selected = Object : : cast_to < Node3D > ( node ) ;
2021-06-23 14:49:50 +00:00
clicked = ObjectID ( ) ;
2020-05-14 14:41:43 +00:00
if ( ! selected ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-02-10 12:59:24 +00:00
if ( ! p_allow_locked ) {
// Replace the node by the group if grouped
2022-01-27 09:36:51 +00:00
while ( node & & node ! = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_parent ( ) ) {
2020-03-26 21:49:16 +00:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( node ) ;
2020-02-10 12:59:24 +00:00
if ( selected_tmp & & node - > has_meta ( " _edit_group_ " ) ) {
selected = selected_tmp ;
}
node = node - > get_parent ( ) ;
2019-04-17 16:24:28 +00:00
}
}
2020-02-10 12:59:24 +00:00
if ( p_allow_locked | | ! _is_node_locked ( selected ) ) {
2021-06-23 14:49:50 +00:00
if ( clicked_wants_append ) {
if ( editor_selection - > is_selected ( selected ) ) {
editor_selection - > remove_node ( selected ) ;
} else {
editor_selection - > add_node ( selected ) ;
}
2021-06-19 02:25:24 +00:00
} else {
2021-06-23 14:49:50 +00:00
if ( ! editor_selection - > is_selected ( selected ) ) {
editor_selection - > clear ( ) ;
editor_selection - > add_node ( selected ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > edit_node ( selected ) ;
2021-06-23 14:49:50 +00:00
}
2020-05-14 14:41:43 +00:00
}
2021-06-19 02:25:24 +00:00
2021-06-23 14:49:50 +00:00
if ( editor_selection - > get_selected_node_list ( ) . size ( ) = = 1 ) {
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > edit_node ( editor_selection - > get_selected_node_list ( ) [ 0 ] ) ;
2021-06-23 14:49:50 +00:00
}
2021-06-19 02:25:24 +00:00
}
2014-02-10 01:10:30 +00:00
}
2021-06-23 14:49:50 +00:00
ObjectID Node3DEditorViewport : : _select_ray ( const Point2 & p_pos ) {
2017-03-05 15:44:50 +00:00
Vector3 ray = _get_ray ( p_pos ) ;
Vector3 pos = _get_ray_pos ( p_pos ) ;
2020-04-01 18:28:09 +00:00
Vector2 shrinked_pos = p_pos / subviewport_container - > get_stretch_shrink ( ) ;
2014-02-10 01:10:30 +00:00
2020-06-25 13:33:28 +00:00
if ( viewport - > get_debug_draw ( ) = = Viewport : : DEBUG_DRAW_SDFGI_PROBES ) {
RS : : get_singleton ( ) - > sdfgi_set_debug_probe_select ( pos , ray ) ;
}
2021-10-26 15:42:27 +00:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_ray ( pos , pos + ray * camera - > get_far ( ) , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2022-05-19 15:00:06 +00:00
HashSet < Ref < EditorNode3DGizmo > > found_gizmos ;
2014-02-10 01:10:30 +00:00
2017-08-26 03:40:45 +00:00
Node * edited_scene = get_tree ( ) - > get_edited_scene_root ( ) ;
2020-02-12 17:24:06 +00:00
ObjectID closest ;
2020-04-01 23:20:12 +00:00
Node * item = nullptr ;
2017-03-05 15:44:50 +00:00
float closest_dist = 1e20 ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * spat = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( ! spat ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = spat - > get_gizmos ( ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
for ( int j = 0 ; j < gizmos . size ( ) ; j + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ j ] ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( ( ! seg . is_valid ( ) ) | | found_gizmos . has ( seg ) ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
found_gizmos . insert ( seg ) ;
Vector3 point ;
Vector3 normal ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
bool inters = seg - > intersect_ray ( camera , shrinked_pos , point , normal ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( ! inters ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2021-06-21 03:30:19 +00:00
const real_t dist = pos . distance_to ( point ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( dist < 0 ) {
continue ;
2021-02-26 18:28:09 +00:00
}
2018-08-27 14:02:49 +00:00
2021-06-23 14:49:50 +00:00
if ( dist < closest_dist ) {
item = Object : : cast_to < Node > ( spat ) ;
if ( item ! = edited_scene ) {
item = edited_scene - > get_deepest_editable_node ( item ) ;
}
closest = item - > get_instance_id ( ) ;
closest_dist = dist ;
}
2017-02-06 03:38:39 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-05-14 14:41:43 +00:00
if ( ! item ) {
2020-02-12 17:24:06 +00:00
return ObjectID ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2017-02-06 03:38:39 +00:00
return closest ;
2014-02-10 01:10:30 +00:00
}
2021-06-23 14:49:50 +00:00
void Node3DEditorViewport : : _find_items_at_pos ( const Point2 & p_pos , Vector < _RayResult > & r_results , bool p_include_locked_nodes ) {
2017-03-05 15:44:50 +00:00
Vector3 ray = _get_ray ( p_pos ) ;
Vector3 pos = _get_ray_pos ( p_pos ) ;
2015-11-04 21:39:07 +00:00
2021-10-26 15:42:27 +00:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_ray ( pos , pos + ray * camera - > get_far ( ) , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2022-05-19 15:00:06 +00:00
HashSet < Node3D * > found_nodes ;
2015-11-04 21:39:07 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * spat = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2015-11-04 21:39:07 +00:00
2020-05-14 14:41:43 +00:00
if ( ! spat ) {
2015-11-04 21:39:07 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
if ( found_nodes . has ( spat ) ) {
2015-11-04 21:39:07 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
if ( ! p_include_locked_nodes & & _is_node_locked ( spat ) ) {
2015-11-04 21:39:07 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = spat - > get_gizmos ( ) ;
for ( int j = 0 ; j < gizmos . size ( ) ; j + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ j ] ;
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
if ( ! seg . is_valid ( ) ) {
continue ;
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
Vector3 point ;
Vector3 normal ;
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
bool inters = seg - > intersect_ray ( camera , p_pos , point , normal ) ;
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
if ( ! inters ) {
continue ;
}
2015-11-04 21:39:07 +00:00
2021-06-21 03:30:19 +00:00
const real_t dist = pos . distance_to ( point ) ;
2021-06-04 13:31:28 +00:00
2021-06-23 14:49:50 +00:00
if ( dist < 0 ) {
continue ;
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
found_nodes . insert ( spat ) ;
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
_RayResult res ;
res . item = spat ;
res . depth = dist ;
r_results . push_back ( res ) ;
break ;
}
2020-05-14 14:41:43 +00:00
}
2015-11-04 21:39:07 +00:00
2021-06-23 14:49:50 +00:00
r_results . sort ( ) ;
2015-11-04 21:39:07 +00:00
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_screen_to_space ( const Vector3 & p_vector3 ) {
2014-02-10 01:10:30 +00:00
CameraMatrix cm ;
2018-06-27 14:59:45 +00: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 18:39:16 +00:00
Vector2 screen_he = cm . get_viewport_half_extents ( ) ;
2014-02-10 01:10:30 +00:00
2020-10-17 05:08:21 +00:00
Transform3D camera_transform ;
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
2020-01-21 18:39:16 +00: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 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _select_region ( ) {
2020-05-14 14:41:43 +00:00
if ( cursor . region_begin = = cursor . region_end ) {
2021-06-23 14:49:50 +00:00
if ( ! clicked_wants_append ) {
_clear_selected ( ) ;
}
2014-02-10 01:10:30 +00:00
return ; //nothing really
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-21 03:30:19 +00:00
const real_t z_offset = MAX ( 0.0 , 5.0 - get_znear ( ) ) ;
2018-05-06 18:49:22 +00:00
2017-03-05 15:44:50 +00:00
Vector3 box [ 4 ] = {
2014-02-10 01:10:30 +00:00
Vector3 (
2017-03-05 15:44:50 +00:00
MIN ( cursor . region_begin . x , cursor . region_end . x ) ,
MIN ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 18:49:22 +00:00
z_offset ) ,
2014-02-10 01:10:30 +00:00
Vector3 (
2017-03-05 15:44:50 +00:00
MAX ( cursor . region_begin . x , cursor . region_end . x ) ,
MIN ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 18:49:22 +00:00
z_offset ) ,
2014-02-10 01:10:30 +00:00
Vector3 (
2017-03-05 15:44:50 +00:00
MAX ( cursor . region_begin . x , cursor . region_end . x ) ,
MAX ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 18:49:22 +00:00
z_offset ) ,
2014-02-10 01:10:30 +00:00
Vector3 (
2017-03-05 15:44:50 +00:00
MIN ( cursor . region_begin . x , cursor . region_end . x ) ,
MAX ( cursor . region_begin . y , cursor . region_end . y ) ,
2018-05-06 18:49:22 +00:00
z_offset )
2014-02-10 01:10:30 +00:00
} ;
Vector < Plane > frustum ;
2017-09-10 13:37:49 +00:00
Vector3 cam_pos = _get_camera_position ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 14:59:45 +00:00
if ( orthogonal ) {
2021-04-08 14:26:14 +00:00
frustum . push_back ( Plane ( ( a - b ) . normalized ( ) , a ) ) ;
2018-06-27 14:59:45 +00:00
} else {
frustum . push_back ( Plane ( a , b , cam_pos ) ) ;
}
2014-02-10 01:10:30 +00:00
}
2021-04-08 14:26:14 +00:00
Plane near ( - _get_camera_normal ( ) , cam_pos ) ;
2020-05-10 14:47:11 +00:00
near . d - = get_znear ( ) ;
2020-04-29 00:14:06 +00:00
frustum . push_back ( near ) ;
2014-02-10 01:10:30 +00:00
2020-04-29 00:14:06 +00:00
Plane far = - near ;
2020-05-10 14:47:11 +00:00
far . d + = get_zfar ( ) ;
2020-04-29 00:14:06 +00:00
frustum . push_back ( far ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( spatial_editor - > get_single_selected_node ( ) ) {
Node3D * single_selected = spatial_editor - > get_single_selected_node ( ) ;
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( single_selected ) ;
2021-07-27 15:43:12 +00:00
if ( se ) {
Ref < EditorNode3DGizmo > old_gizmo ;
if ( ! clicked_wants_append ) {
se - > subgizmos . clear ( ) ;
old_gizmo = se - > gizmo ;
se - > gizmo . unref ( ) ;
2021-06-23 14:49:50 +00:00
}
2021-07-27 15:43:12 +00:00
bool found_subgizmos = false ;
Vector < Ref < Node3DGizmo > > gizmos = single_selected - > get_gizmos ( ) ;
for ( int j = 0 ; j < gizmos . size ( ) ; j + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ j ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
}
if ( se - > gizmo . is_valid ( ) & & se - > gizmo ! = seg ) {
continue ;
}
2021-06-23 14:49:50 +00:00
2021-07-27 15:43:12 +00:00
Vector < int > subgizmos = seg - > subgizmos_intersect_frustum ( camera , frustum ) ;
if ( ! subgizmos . is_empty ( ) ) {
se - > gizmo = seg ;
for ( int i = 0 ; i < subgizmos . size ( ) ; i + + ) {
int subgizmo_id = subgizmos [ i ] ;
if ( ! se - > subgizmos . has ( subgizmo_id ) ) {
se - > subgizmos . insert ( subgizmo_id , se - > gizmo - > get_subgizmo_transform ( subgizmo_id ) ) ;
}
2021-06-23 14:49:50 +00:00
}
2021-07-27 15:43:12 +00:00
found_subgizmos = true ;
break ;
2021-06-23 14:49:50 +00:00
}
}
2021-07-27 15:43:12 +00:00
if ( ! clicked_wants_append | | found_subgizmos ) {
if ( se - > gizmo . is_valid ( ) ) {
se - > gizmo - > redraw ( ) ;
}
2021-06-23 14:49:50 +00:00
2021-07-27 15:43:12 +00:00
if ( old_gizmo ! = se - > gizmo & & old_gizmo . is_valid ( ) ) {
old_gizmo - > redraw ( ) ;
}
2021-06-23 14:49:50 +00:00
2021-07-27 15:43:12 +00:00
spatial_editor - > update_transform_gizmo ( ) ;
}
2021-06-23 14:49:50 +00:00
2021-07-27 15:43:12 +00:00
if ( found_subgizmos ) {
return ;
}
2021-06-23 14:49:50 +00:00
}
}
if ( ! clicked_wants_append ) {
_clear_selected ( ) ;
}
2020-04-18 09:00:51 +00:00
Vector < ObjectID > instances = RenderingServer : : get_singleton ( ) - > instances_cull_convex ( frustum , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2022-05-19 15:00:06 +00:00
HashSet < Node3D * > found_nodes ;
2018-09-02 20:31:03 +00:00
Vector < Node * > selected ;
2017-09-12 13:06:13 +00:00
Node * edited_scene = get_tree ( ) - > get_edited_scene_root ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < instances . size ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * sp = Object : : cast_to < Node3D > ( ObjectDB : : get_instance ( instances [ i ] ) ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp | | _is_node_locked ( sp ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( found_nodes . has ( sp ) ) {
continue ;
}
found_nodes . insert ( sp ) ;
2021-02-26 18:28:09 +00:00
Node * item = Object : : cast_to < Node > ( sp ) ;
if ( item ! = edited_scene ) {
item = edited_scene - > get_deepest_editable_node ( item ) ;
}
2018-05-06 18:49:22 +00:00
2019-04-17 16:24:28 +00:00
// Replace the node by the group if grouped
2020-03-26 21:49:16 +00:00
if ( item - > is_class ( " Node3D " ) ) {
Node3D * sel = Object : : cast_to < Node3D > ( item ) ;
2022-01-27 09:36:51 +00:00
while ( item & & item ! = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_parent ( ) ) {
2020-03-26 21:49:16 +00:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( item ) ;
2019-04-17 16:24:28 +00:00
if ( selected_tmp & & item - > has_meta ( " _edit_group_ " ) ) {
sel = selected_tmp ;
}
item = item - > get_parent ( ) ;
}
item = sel ;
}
2020-05-14 14:41:43 +00:00
if ( _is_node_locked ( item ) ) {
2020-05-10 10:56:01 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-07-15 19:50:00 +00:00
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = sp - > get_gizmos ( ) ;
for ( int j = 0 ; j < gizmos . size ( ) ; j + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ j ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( seg - > intersect_frustum ( camera , frustum ) ) {
selected . push_back ( item ) ;
}
2020-05-14 14:41:43 +00:00
}
2021-06-23 14:49:50 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
for ( int i = 0 ; i < selected . size ( ) ; i + + ) {
if ( ! editor_selection - > is_selected ( selected [ i ] ) ) {
editor_selection - > add_node ( selected [ i ] ) ;
2017-09-12 13:06:13 +00:00
}
2018-05-06 18:49:22 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( editor_selection - > get_selected_node_list ( ) . size ( ) = = 1 ) {
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > edit_node ( editor_selection - > get_selected_node_list ( ) [ 0 ] ) ;
2014-02-10 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _update_name ( ) {
2021-08-14 07:24:02 +00:00
String name ;
2015-03-21 20:47:21 +00:00
2021-08-14 07:24:02 +00:00
switch ( view_type ) {
case VIEW_TYPE_USER : {
if ( orthogonal ) {
name = TTR ( " Orthogonal " ) ;
} else {
name = TTR ( " Perspective " ) ;
}
} break ;
case VIEW_TYPE_TOP : {
if ( orthogonal ) {
name = TTR ( " Top Orthogonal " ) ;
} else {
name = TTR ( " Top Perspective " ) ;
}
} break ;
case VIEW_TYPE_BOTTOM : {
if ( orthogonal ) {
name = TTR ( " Bottom Orthogonal " ) ;
} else {
name = TTR ( " Bottom Perspective " ) ;
}
} break ;
case VIEW_TYPE_LEFT : {
if ( orthogonal ) {
name = TTR ( " Left Orthogonal " ) ;
} else {
2021-09-22 02:30:48 +00:00
name = TTR ( " Left Perspective " ) ;
2021-08-14 07:24:02 +00:00
}
} break ;
case VIEW_TYPE_RIGHT : {
if ( orthogonal ) {
name = TTR ( " Right Orthogonal " ) ;
} else {
name = TTR ( " Right Perspective " ) ;
}
} break ;
case VIEW_TYPE_FRONT : {
if ( orthogonal ) {
name = TTR ( " Front Orthogonal " ) ;
} else {
name = TTR ( " Front Perspective " ) ;
}
} break ;
case VIEW_TYPE_REAR : {
if ( orthogonal ) {
name = TTR ( " Rear Orthogonal " ) ;
} else {
name = TTR ( " Rear Perspective " ) ;
}
} break ;
2019-10-23 09:46:26 +00:00
}
2021-08-14 07:24:02 +00:00
if ( auto_orthogonal ) {
// TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled.
name + = TTR ( " [auto] " ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
2021-08-14 07:24:02 +00:00
view_menu - > set_text ( name ) ;
2021-11-20 08:04:57 +00:00
view_menu - > reset_size ( ) ;
2015-03-21 20:47:21 +00:00
}
2022-02-09 08:39:28 +00:00
void Node3DEditorViewport : : _compute_edit ( const Point2 & p_point ) {
2020-07-18 19:03:08 +00:00
_edit . original_local = spatial_editor - > are_local_coords_enabled ( ) ;
2021-09-23 14:58:43 +00:00
_edit . click_ray = _get_ray ( p_point ) ;
_edit . click_ray_pos = _get_ray_pos ( p_point ) ;
2017-03-05 15:44:50 +00:00
_edit . plane = TRANSFORM_VIEW ;
2014-02-10 01:10:30 +00:00
spatial_editor - > update_transform_gizmo ( ) ;
2022-02-09 08:39:28 +00:00
_edit . center = spatial_editor - > get_gizmo_transform ( ) . origin ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
Node3D * selected = spatial_editor - > get_single_selected_node ( ) ;
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( se & & se - > gizmo . is_valid ( ) ) {
2021-08-09 20:13:42 +00:00
for ( const KeyValue < int , Transform3D > & E : se - > subgizmos ) {
int subgizmo_id = E . key ;
2021-06-23 14:49:50 +00:00
se - > subgizmos [ subgizmo_id ] = se - > gizmo - > get_subgizmo_transform ( subgizmo_id ) ;
2020-05-14 14:41:43 +00:00
}
2021-06-23 14:49:50 +00:00
se - > original_local = selected - > get_transform ( ) ;
se - > original = selected - > get_global_transform ( ) ;
} else {
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * sel_item = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! sel_item ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
sel_item - > original_local = sel_item - > sp - > get_local_gizmo_transform ( ) ;
sel_item - > original = sel_item - > sp - > get_global_gizmo_transform ( ) ;
}
2014-02-10 01:10:30 +00:00
}
}
2021-08-13 21:31:57 +00:00
static Key _get_key_modifier_setting ( const String & p_property ) {
2017-03-05 15:44:50 +00:00
switch ( EditorSettings : : get_singleton ( ) - > get ( p_property ) . operator int ( ) ) {
2020-05-10 11:00:47 +00:00
case 0 :
2021-08-13 21:31:57 +00:00
return Key : : NONE ;
2020-05-10 11:00:47 +00:00
case 1 :
2021-08-13 21:31:57 +00:00
return Key : : SHIFT ;
2020-05-10 11:00:47 +00:00
case 2 :
2021-08-13 21:31:57 +00:00
return Key : : ALT ;
2020-05-10 11:00:47 +00:00
case 3 :
2021-08-13 21:31:57 +00:00
return Key : : META ;
2020-05-10 11:00:47 +00:00
case 4 :
2021-08-13 21:31:57 +00:00
return Key : : CTRL ;
2014-02-10 01:10:30 +00:00
}
2021-08-13 21:31:57 +00:00
return Key : : NONE ;
2014-02-10 01:10:30 +00:00
}
2021-08-13 21:31:57 +00:00
static Key _get_key_modifier ( Ref < InputEventWithModifiers > e ) {
2021-04-24 20:33:50 +00:00
if ( e - > is_shift_pressed ( ) ) {
2021-08-13 21:31:57 +00:00
return Key : : SHIFT ;
2020-05-14 14:41:43 +00:00
}
2021-04-24 20:33:50 +00:00
if ( e - > is_alt_pressed ( ) ) {
2021-08-13 21:31:57 +00:00
return Key : : ALT ;
2020-05-14 14:41:43 +00:00
}
2021-04-24 20:33:50 +00:00
if ( e - > is_ctrl_pressed ( ) ) {
2021-08-13 21:31:57 +00:00
return Key : : CTRL ;
2020-05-14 14:41:43 +00:00
}
2021-04-24 20:33:50 +00:00
if ( e - > is_meta_pressed ( ) ) {
2021-08-13 21:31:57 +00:00
return Key : : META ;
2020-05-14 14:41:43 +00:00
}
2021-08-13 21:31:57 +00:00
return Key : : NONE ;
2017-07-23 00:02:18 +00:00
}
2021-06-23 14:49:50 +00:00
bool Node3DEditorViewport : : _transform_gizmo_select ( const Vector2 & p_screenpos , bool p_highlight_only ) {
2020-05-14 14:41:43 +00:00
if ( ! spatial_editor - > is_gizmo_visible ( ) ) {
2014-02-10 01:10:30 +00:00
return false ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
if ( get_selected_count ( ) = = 0 ) {
2020-05-14 14:41:43 +00:00
if ( p_highlight_only ) {
2017-04-06 15:35:08 +00:00
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
return false ;
}
2021-09-23 14:58:43 +00:00
Vector3 ray_pos = _get_ray_pos ( p_screenpos ) ;
Vector3 ray = _get_ray ( p_screenpos ) ;
2014-02-10 01:10:30 +00:00
2020-10-17 05:08:21 +00:00
Transform3D gt = spatial_editor - > get_gizmo_transform ( ) ;
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) {
2017-03-05 15:44:50 +00:00
int col_axis = - 1 ;
2021-06-21 03:30:19 +00:00
real_t col_d = 1e20 ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2022-05-03 12:50:35 +00:00
const Vector3 grabber_pos = gt . origin + gt . basis . get_column ( i ) . normalized ( ) * gizmo_scale * ( GIZMO_ARROW_OFFSET + ( GIZMO_ARROW_SIZE * 0.5 ) ) ;
2021-06-21 03:30:19 +00:00
const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE ;
2014-02-10 01:10:30 +00:00
Vector3 r ;
2017-08-29 01:39:45 +00:00
2020-05-25 17:20:45 +00:00
if ( Geometry3D : : segment_intersects_sphere ( ray_pos , ray_pos + ray * MAX_Z , grabber_pos , grabber_radius , & r ) ) {
2021-06-21 03:30:19 +00:00
const real_t d = r . distance_to ( ray_pos ) ;
2017-03-05 15:44:50 +00:00
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
2014-02-10 01:10:30 +00:00
}
}
}
2017-08-29 01:39:45 +00:00
bool is_plane_translate = false ;
2017-09-21 21:11:56 +00:00
// plane select
2017-08-29 01:39:45 +00:00
if ( col_axis = = - 1 ) {
col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
2022-05-03 12:50:35 +00:00
Vector3 ivec2 = gt . basis . get_column ( ( i + 1 ) % 3 ) . normalized ( ) ;
Vector3 ivec3 = gt . basis . get_column ( ( i + 2 ) % 3 ) . normalized ( ) ;
2017-08-29 01:39:45 +00:00
2021-07-18 22:09:59 +00:00
// Allow some tolerance to make the plane easier to click,
// even if the click is actually slightly outside the plane.
2021-06-21 03:30:19 +00:00
const Vector3 grabber_pos = gt . origin + ( ivec2 + ivec3 ) * gizmo_scale * ( GIZMO_PLANE_SIZE + GIZMO_PLANE_DST * 0.6667 ) ;
2017-08-29 01:39:45 +00:00
Vector3 r ;
2022-05-03 12:50:35 +00:00
Plane plane ( gt . basis . get_column ( i ) . normalized ( ) , gt . origin ) ;
2017-08-29 01:39:45 +00:00
if ( plane . intersects_ray ( ray_pos , ray , & r ) ) {
2021-06-21 03:30:19 +00:00
const real_t dist = r . distance_to ( grabber_pos ) ;
2021-07-18 22:09:59 +00:00
// Allow some tolerance to make the plane easier to click,
// even if the click is actually slightly outside the plane.
2021-06-21 03:30:19 +00:00
if ( dist < ( gizmo_scale * GIZMO_PLANE_SIZE * 1.5 ) ) {
const real_t d = ray_pos . distance_to ( r ) ;
2017-08-29 01:39:45 +00:00
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
is_plane_translate = true ;
}
}
}
}
}
2017-03-05 15:44:50 +00:00
if ( col_axis ! = - 1 ) {
2017-05-02 20:13:12 +00:00
if ( p_highlight_only ) {
2017-08-29 01:39:45 +00:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + ( is_plane_translate ? 6 : 0 ) ) ;
2014-02-10 01:10:30 +00:00
} else {
2017-08-29 01:39:45 +00:00
//handle plane translate
2017-03-05 15:44:50 +00:00
_edit . mode = TRANSFORM_TRANSLATE ;
2021-09-23 14:58:43 +00:00
_compute_edit ( p_screenpos ) ;
2017-08-29 01:39:45 +00:00
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis + ( is_plane_translate ? 3 : 0 ) ) ;
2014-02-10 01:10:30 +00:00
}
return true ;
}
}
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) {
2017-03-05 15:44:50 +00:00
int col_axis = - 1 ;
2014-02-10 01:10:30 +00:00
2022-01-17 14:48:21 +00:00
Vector3 hit_position ;
Vector3 hit_normal ;
real_t ray_length = gt . origin . distance_to ( ray_pos ) + ( GIZMO_CIRCLE_SIZE * gizmo_scale ) * 4.0f ;
if ( Geometry3D : : segment_intersects_sphere ( ray_pos , ray_pos + ray * ray_length , gt . origin , gizmo_scale * ( GIZMO_CIRCLE_SIZE ) , & hit_position , & hit_normal ) ) {
if ( hit_normal . dot ( _get_camera_normal ( ) ) < 0.05 ) {
hit_position = gt . xform_inv ( hit_position ) . abs ( ) ;
int min_axis = hit_position . min_axis_index ( ) ;
if ( hit_position [ min_axis ] < gizmo_scale * GIZMO_RING_HALF_WIDTH ) {
col_axis = min_axis ;
}
2020-05-14 14:41:43 +00:00
}
2022-01-17 14:48:21 +00:00
}
2014-02-10 01:10:30 +00:00
2022-01-17 14:48:21 +00:00
if ( col_axis = = - 1 ) {
float col_d = 1e20 ;
2020-09-13 16:22:51 +00:00
2022-01-17 14:48:21 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2022-05-03 12:50:35 +00:00
Plane plane ( gt . basis . get_column ( i ) . normalized ( ) , gt . origin ) ;
2022-01-17 14:48:21 +00:00
Vector3 r ;
if ( ! plane . intersects_ray ( ray_pos , ray , & r ) ) {
continue ;
}
const real_t dist = r . distance_to ( gt . origin ) ;
const Vector3 r_dir = ( r - gt . origin ) . normalized ( ) ;
if ( _get_camera_normal ( ) . dot ( r_dir ) < = 0.005 ) {
if ( dist > gizmo_scale * ( GIZMO_CIRCLE_SIZE - GIZMO_RING_HALF_WIDTH ) & & dist < gizmo_scale * ( GIZMO_CIRCLE_SIZE + GIZMO_RING_HALF_WIDTH ) ) {
const real_t d = ray_pos . distance_to ( r ) ;
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
}
2020-09-13 16:22:51 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
}
2017-03-05 15:44:50 +00:00
if ( col_axis ! = - 1 ) {
2017-05-02 20:13:12 +00:00
if ( p_highlight_only ) {
2017-04-06 15:35:08 +00:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + 3 ) ;
2014-02-10 01:10:30 +00:00
} else {
//handle rotate
2017-03-05 15:44:50 +00:00
_edit . mode = TRANSFORM_ROTATE ;
2021-09-23 14:58:43 +00:00
_compute_edit ( p_screenpos ) ;
2017-03-05 15:44:50 +00:00
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis ) ;
2014-02-10 01:10:30 +00:00
}
return true ;
}
}
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) {
2017-09-21 21:11:56 +00:00
int col_axis = - 1 ;
float col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
2022-05-03 12:50:35 +00:00
const Vector3 grabber_pos = gt . origin + gt . basis . get_column ( i ) . normalized ( ) * gizmo_scale * GIZMO_SCALE_OFFSET ;
2021-06-21 03:30:19 +00:00
const real_t grabber_radius = gizmo_scale * GIZMO_ARROW_SIZE ;
2017-09-21 21:11:56 +00:00
Vector3 r ;
2020-05-25 17:20:45 +00:00
if ( Geometry3D : : segment_intersects_sphere ( ray_pos , ray_pos + ray * MAX_Z , grabber_pos , grabber_radius , & r ) ) {
2021-06-21 03:30:19 +00:00
const real_t d = r . distance_to ( ray_pos ) ;
2017-09-21 21:11:56 +00:00
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
}
}
}
2017-11-14 22:50:19 +00:00
bool is_plane_scale = false ;
// plane select
if ( col_axis = = - 1 ) {
col_d = 1e20 ;
for ( int i = 0 ; i < 3 ; i + + ) {
2022-05-03 12:50:35 +00:00
const Vector3 ivec2 = gt . basis . get_column ( ( i + 1 ) % 3 ) . normalized ( ) ;
const Vector3 ivec3 = gt . basis . get_column ( ( i + 2 ) % 3 ) . normalized ( ) ;
2017-11-14 22:50:19 +00:00
2021-07-18 22:09:59 +00:00
// Allow some tolerance to make the plane easier to click,
// even if the click is actually slightly outside the plane.
2021-06-21 03:30:19 +00:00
const Vector3 grabber_pos = gt . origin + ( ivec2 + ivec3 ) * gizmo_scale * ( GIZMO_PLANE_SIZE + GIZMO_PLANE_DST * 0.6667 ) ;
2017-11-14 22:50:19 +00:00
Vector3 r ;
2022-05-03 12:50:35 +00:00
Plane plane ( gt . basis . get_column ( i ) . normalized ( ) , gt . origin ) ;
2017-11-14 22:50:19 +00:00
if ( plane . intersects_ray ( ray_pos , ray , & r ) ) {
2021-06-21 03:30:19 +00:00
const real_t dist = r . distance_to ( grabber_pos ) ;
2021-07-18 22:09:59 +00:00
// Allow some tolerance to make the plane easier to click,
// even if the click is actually slightly outside the plane.
2021-06-21 03:30:19 +00:00
if ( dist < ( gizmo_scale * GIZMO_PLANE_SIZE * 1.5 ) ) {
const real_t d = ray_pos . distance_to ( r ) ;
2017-11-14 22:50:19 +00:00
if ( d < col_d ) {
col_d = d ;
col_axis = i ;
is_plane_scale = true ;
}
}
}
}
}
2017-09-21 21:11:56 +00:00
if ( col_axis ! = - 1 ) {
if ( p_highlight_only ) {
2017-11-14 22:50:19 +00:00
spatial_editor - > select_gizmo_highlight_axis ( col_axis + ( is_plane_scale ? 12 : 9 ) ) ;
2017-09-21 21:11:56 +00:00
} else {
//handle scale
_edit . mode = TRANSFORM_SCALE ;
2021-09-23 14:58:43 +00:00
_compute_edit ( p_screenpos ) ;
2017-11-14 22:50:19 +00:00
_edit . plane = TransformPlane ( TRANSFORM_X_AXIS + col_axis + ( is_plane_scale ? 3 : 0 ) ) ;
2017-09-21 21:11:56 +00:00
}
return true ;
}
}
2020-05-14 14:41:43 +00:00
if ( p_highlight_only ) {
2017-04-06 15:35:08 +00:00
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
return false ;
}
2021-06-23 14:49:50 +00:00
void Node3DEditorViewport : : _transform_gizmo_apply ( Node3D * p_node , const Transform3D & p_transform , bool p_local ) {
if ( p_transform . basis . determinant ( ) = = 0 ) {
return ;
}
if ( p_local ) {
p_node - > set_transform ( p_transform ) ;
} else {
p_node - > set_global_transform ( p_transform ) ;
}
}
2021-10-09 10:24:26 +00:00
Transform3D Node3DEditorViewport : : _compute_transform ( TransformMode p_mode , const Transform3D & p_original , const Transform3D & p_original_local , Vector3 p_motion , double p_extra , bool p_local , bool p_orthogonal ) {
2021-06-23 14:49:50 +00:00
switch ( p_mode ) {
case TRANSFORM_SCALE : {
2021-10-09 10:24:26 +00:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
p_motion . snap ( Vector3 ( p_extra , p_extra , p_extra ) ) ;
}
Transform3D s ;
2021-06-23 14:49:50 +00:00
if ( p_local ) {
2021-10-09 10:24:26 +00:00
s . basis = p_original_local . basis . scaled_local ( p_motion + Vector3 ( 1 , 1 , 1 ) ) ;
s . origin = p_original_local . origin ;
2021-06-23 14:49:50 +00:00
} else {
2021-10-09 10:24:26 +00:00
s . basis . scale ( p_motion + Vector3 ( 1 , 1 , 1 ) ) ;
2021-06-23 14:49:50 +00:00
Transform3D base = Transform3D ( Basis ( ) , _edit . center ) ;
2021-10-09 10:24:26 +00:00
s = base * ( s * ( base . inverse ( ) * p_original ) ) ;
// Recalculate orthogonalized scale without moving origin.
if ( p_orthogonal ) {
s . basis = p_original_local . basis . scaled_orthogonal ( p_motion + Vector3 ( 1 , 1 , 1 ) ) ;
// The scaled_orthogonal() does not require orthogonal Basis,
// but it may make a bit skew by precision problems.
s . basis . orthogonalize ( ) ;
2021-06-23 14:49:50 +00:00
}
}
2021-10-09 10:24:26 +00:00
return s ;
2021-06-23 14:49:50 +00:00
}
case TRANSFORM_TRANSLATE : {
2021-10-09 10:24:26 +00:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
p_motion . snap ( Vector3 ( p_extra , p_extra , p_extra ) ) ;
}
2021-06-23 14:49:50 +00:00
2021-10-09 10:24:26 +00:00
if ( p_local ) {
p_motion = p_original . basis . xform ( p_motion ) ;
2021-06-23 14:49:50 +00:00
}
// Apply translation
Transform3D t = p_original ;
t . origin + = p_motion ;
2021-10-09 10:24:26 +00:00
2021-06-23 14:49:50 +00:00
return t ;
}
case TRANSFORM_ROTATE : {
2021-10-09 10:24:26 +00:00
Transform3D r ;
2021-06-23 14:49:50 +00:00
if ( p_local ) {
2021-08-01 00:28:37 +00:00
Vector3 axis = p_original_local . basis . xform ( p_motion ) ;
r . basis = Basis ( axis . normalized ( ) , p_extra ) * p_original_local . basis ;
r . origin = p_original_local . origin ;
2021-06-23 14:49:50 +00:00
} else {
2021-08-01 00:28:37 +00:00
Basis local = p_original . basis * p_original_local . basis . inverse ( ) ;
Vector3 axis = local . xform_inv ( p_motion ) ;
r . basis = local * Basis ( axis . normalized ( ) , p_extra ) * p_original_local . basis ;
r . origin = Basis ( p_motion , p_extra ) . xform ( p_original . origin - _edit . center ) + _edit . center ;
2021-06-23 14:49:50 +00:00
}
2021-10-09 10:24:26 +00:00
return r ;
2021-06-23 14:49:50 +00:00
}
default : {
ERR_FAIL_V_MSG ( Transform3D ( ) , " Invalid mode in '_compute_transform' " ) ;
}
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _surface_mouse_enter ( ) {
2022-02-03 10:59:32 +00:00
if ( ! surface - > has_focus ( ) & & ( ! get_viewport ( ) - > gui_get_focus_owner ( ) | | ! get_viewport ( ) - > gui_get_focus_owner ( ) - > is_text_field ( ) ) ) {
2017-03-05 15:44:50 +00:00
surface - > grab_focus ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _surface_mouse_exit ( ) {
2017-09-02 19:47:16 +00:00
_remove_preview ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _surface_focus_enter ( ) {
2017-12-19 14:29:55 +00:00
view_menu - > set_disable_shortcuts ( false ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _surface_focus_exit ( ) {
2017-12-19 14:29:55 +00:00
view_menu - > set_disable_shortcuts ( true ) ;
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
bool Node3DEditorViewport : : _is_node_locked ( const Node * p_node ) {
2022-04-01 18:30:23 +00:00
return p_node - > get_meta ( " _edit_lock_ " , false ) ;
2019-07-15 19:50:00 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _list_select ( Ref < InputEventMouseButton > b ) {
2021-06-23 14:49:50 +00:00
_find_items_at_pos ( b - > get_position ( ) , selection_results , spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT ) ;
2015-12-13 20:16:13 +00:00
2022-01-27 09:36:51 +00:00
Node * scene = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
2015-12-13 20:16:13 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < selection_results . size ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * item = selection_results [ i ] . item ;
2021-02-21 08:19:48 +00:00
if ( item ! = scene & & item - > get_owner ( ) ! = scene & & item ! = scene - > get_deepest_editable_node ( item ) ) {
2015-12-13 20:16:13 +00:00
//invalid result
2021-07-03 22:17:03 +00:00
selection_results . remove_at ( i ) ;
2015-12-13 20:16:13 +00:00
i - - ;
}
}
2021-04-24 20:33:50 +00:00
clicked_wants_append = b - > is_shift_pressed ( ) ;
2015-12-13 20:16:13 +00:00
if ( selection_results . size ( ) = = 1 ) {
2017-08-07 10:17:31 +00:00
clicked = selection_results [ 0 ] . item - > get_instance_id ( ) ;
2015-12-13 20:16:13 +00:00
selection_results . clear ( ) ;
2020-02-12 17:24:06 +00:00
if ( clicked . is_valid ( ) ) {
2021-06-23 14:49:50 +00:00
_select_clicked ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT ) ;
2015-12-13 20:16:13 +00:00
}
2020-12-15 12:04:21 +00:00
} else if ( ! selection_results . is_empty ( ) ) {
2015-12-13 20:16:13 +00:00
NodePath root_path = get_tree ( ) - > get_edited_scene_root ( ) - > get_path ( ) ;
2017-03-05 15:44:50 +00:00
StringName root_name = root_path . get_name ( root_path . get_name_count ( ) - 1 ) ;
2015-12-13 20:16:13 +00:00
for ( int i = 0 ; i < selection_results . size ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * spat = selection_results [ i ] . item ;
2015-12-13 20:16:13 +00:00
2019-06-11 18:43:37 +00:00
Ref < Texture2D > icon = EditorNode : : get_singleton ( ) - > get_object_icon ( spat , " Node " ) ;
2015-12-13 20:16:13 +00:00
2017-03-05 15:44:50 +00:00
String node_path = " / " + root_name + " / " + root_path . rel_path_to ( spat - > get_path ( ) ) ;
2015-12-13 20:16:13 +00:00
2020-02-10 12:59:24 +00:00
int locked = 0 ;
if ( _is_node_locked ( spat ) ) {
locked = 1 ;
} else {
2022-01-27 09:36:51 +00:00
Node * ed_scene = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
2020-02-10 12:59:24 +00:00
Node * node = spat ;
while ( node & & node ! = ed_scene - > get_parent ( ) ) {
2020-03-26 21:49:16 +00:00
Node3D * selected_tmp = Object : : cast_to < Node3D > ( node ) ;
2020-02-10 12:59:24 +00: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 15:44:50 +00:00
selection_menu - > set_item_icon ( i , icon ) ;
2015-12-13 20:16:13 +00:00
selection_menu - > set_item_metadata ( i , node_path ) ;
2017-05-01 18:57:35 +00:00
selection_menu - > set_item_tooltip ( i , String ( spat - > get_name ( ) ) + " \n Type: " + spat - > get_class ( ) + " \n Path: " + node_path ) ;
2015-12-13 20:16:13 +00:00
}
2021-08-31 15:43:35 +00:00
selection_menu - > set_position ( get_screen_position ( ) + b - > get_position ( ) ) ;
selection_menu - > reset_size ( ) ;
2015-12-13 20:16:13 +00:00
selection_menu - > popup ( ) ;
}
}
2017-10-30 00:22:48 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _sinput ( const Ref < InputEvent > & p_event ) {
2020-05-14 14:41:43 +00:00
if ( previewing ) {
2014-02-10 01:10:30 +00:00
return ; //do NONE
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-02-04 08:20:26 +00:00
EditorPlugin : : AfterGUIInput after = EditorPlugin : : AFTER_GUI_INPUT_PASS ;
2014-02-10 01:10:30 +00:00
{
2022-01-27 09:36:51 +00:00
EditorNode * en = EditorNode : : get_singleton ( ) ;
2017-06-08 17:57:35 +00:00
EditorPluginList * force_input_forwarding_list = en - > get_editor_plugins_force_input_forwarding ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! force_input_forwarding_list - > is_empty ( ) ) {
2021-02-04 08:20:26 +00:00
EditorPlugin : : AfterGUIInput discard = force_input_forwarding_list - > forward_spatial_gui_input ( camera , p_event , true ) ;
if ( discard = = EditorPlugin : : AFTER_GUI_INPUT_STOP ) {
2017-06-08 17:57:35 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2021-02-04 08:20:26 +00:00
if ( discard = = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ) {
after = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ;
}
2017-06-08 17:57:35 +00:00
}
}
{
2022-01-27 09:36:51 +00:00
EditorNode * en = EditorNode : : get_singleton ( ) ;
2016-03-29 23:02:53 +00:00
EditorPluginList * over_plugin_list = en - > get_editor_plugins_over ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! over_plugin_list - > is_empty ( ) ) {
2021-02-04 08:20:26 +00:00
EditorPlugin : : AfterGUIInput discard = over_plugin_list - > forward_spatial_gui_input ( camera , p_event , false ) ;
if ( discard = = EditorPlugin : : AFTER_GUI_INPUT_STOP ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2021-02-04 08:20:26 +00:00
if ( discard = = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ) {
after = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ;
}
2014-02-10 01:10:30 +00:00
}
}
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseButton > b = p_event ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( b . is_valid ( ) ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " clicked " ) , this ) ;
2019-04-06 20:55:01 +00:00
2021-06-21 03:30:19 +00:00
const real_t zoom_factor = 1 + ( ZOOM_FREELOOK_MULTIPLIER - 1 ) * b - > get_factor ( ) ;
2017-05-20 15:38:03 +00:00
switch ( b - > get_button_index ( ) ) {
2021-08-13 21:31:57 +00:00
case MouseButton : : WHEEL_UP : {
2021-10-14 22:00:27 +00:00
if ( b - > is_alt_pressed ( ) ) {
scale_fov ( - 0.05 ) ;
2020-05-14 14:41:43 +00:00
} else {
2021-10-14 22:00:27 +00:00
if ( is_freelook_active ( ) ) {
scale_freelook_speed ( zoom_factor ) ;
} else {
scale_cursor_distance ( 1.0 / zoom_factor ) ;
}
2020-05-14 14:41:43 +00:00
}
2017-05-20 15:38:03 +00:00
} break ;
2021-08-13 21:31:57 +00:00
case MouseButton : : WHEEL_DOWN : {
2021-10-14 22:00:27 +00:00
if ( b - > is_alt_pressed ( ) ) {
scale_fov ( 0.05 ) ;
2020-05-14 14:41:43 +00:00
} else {
2021-10-14 22:00:27 +00:00
if ( is_freelook_active ( ) ) {
scale_freelook_speed ( 1.0 / zoom_factor ) ;
} else {
scale_cursor_distance ( zoom_factor ) ;
}
2020-05-14 14:41:43 +00:00
}
2017-05-20 15:38:03 +00:00
} break ;
2021-08-13 21:31:57 +00:00
case MouseButton : : RIGHT : {
2017-09-19 00:30:48 +00:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( b - > is_pressed ( ) & & _edit . gizmo . is_valid ( ) ) {
//restore
2022-01-11 11:33:37 +00:00
_edit . gizmo - > commit_handle ( _edit . gizmo_handle , _edit . gizmo_handle_secondary , _edit . gizmo_initial_value , true ) ;
2020-03-26 21:49:16 +00:00
_edit . gizmo = Ref < EditorNode3DGizmo > ( ) ;
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( _edit . mode = = TRANSFORM_NONE & & b - > is_pressed ( ) ) {
2021-04-24 20:33:50 +00:00
if ( b - > is_alt_pressed ( ) ) {
2020-05-14 14:41:43 +00:00
if ( nav_scheme = = NAVIGATION_MAYA ) {
2017-05-20 15:38:03 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2015-11-19 14:47:04 +00:00
2017-05-20 15:38:03 +00:00
_list_select ( b ) ;
return ;
2014-02-10 01:10:30 +00:00
}
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( _edit . mode ! = TRANSFORM_NONE & & b - > is_pressed ( ) ) {
2020-07-18 19:03:08 +00:00
cancel_transform ( ) ;
2017-05-20 15:38:03 +00:00
}
2017-05-07 20:59:05 +00:00
2017-07-23 00:02:18 +00:00
if ( b - > is_pressed ( ) ) {
2021-08-13 21:31:57 +00:00
const Key mod = _get_key_modifier ( b ) ;
2018-10-20 10:49:33 +00:00
if ( ! orthogonal ) {
if ( mod = = _get_key_modifier_setting ( " editors/3d/freelook/freelook_activation_modifier " ) ) {
set_freelook_active ( true ) ;
}
2017-07-23 00:02:18 +00:00
}
} else {
2017-10-08 00:43:57 +00:00
set_freelook_active ( false ) ;
2017-07-23 00:02:18 +00:00
}
2017-06-20 00:24:35 +00: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 20:59:05 +00:00
2017-05-20 15:38:03 +00:00
} break ;
2021-08-13 21:31:57 +00:00
case MouseButton : : MIDDLE : {
2017-05-20 15:38:03 +00:00
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 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_USER ;
2017-05-20 15:38:03 +00:00
_update_name ( ) ;
} break ;
case TRANSFORM_X_AXIS : {
_edit . plane = TRANSFORM_Y_AXIS ;
set_message ( TTR ( " Y-Axis Transform. " ) , 2 ) ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
} break ;
case TRANSFORM_Y_AXIS : {
_edit . plane = TRANSFORM_Z_AXIS ;
set_message ( TTR ( " Z-Axis Transform. " ) , 2 ) ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
} break ;
case TRANSFORM_Z_AXIS : {
_edit . plane = TRANSFORM_VIEW ;
set_message ( TTR ( " View Plane Transform. " ) , 2 ) ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
} break ;
2018-09-26 11:13:56 +00:00
case TRANSFORM_YZ :
case TRANSFORM_XZ :
case TRANSFORM_XY : {
} break ;
2014-02-10 01:10:30 +00:00
}
2017-05-20 15:38:03 +00:00
}
} break ;
2021-08-13 21:31:57 +00:00
case MouseButton : : LEFT : {
2017-05-20 15:38:03 +00:00
if ( b - > is_pressed ( ) ) {
2022-02-09 09:32:03 +00:00
clicked_wants_append = b - > is_shift_pressed ( ) ;
2020-07-18 19:03:08 +00:00
if ( _edit . mode ! = TRANSFORM_NONE & & _edit . instant ) {
commit_transform ( ) ;
break ; // just commit the edit, stop processing the event so we don't deselect the object
}
2017-09-19 00:30:48 +00:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2021-04-24 20:33:50 +00:00
if ( ( nav_scheme = = NAVIGATION_MAYA | | nav_scheme = = NAVIGATION_MODO ) & & b - > is_alt_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
break ;
}
2014-03-31 08:27:41 +00:00
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_LIST_SELECT ) {
2017-05-20 15:38:03 +00:00
_list_select ( b ) ;
break ;
}
2015-12-13 20:16:13 +00:00
2017-06-03 08:54:24 +00:00
_edit . mouse_pos = b - > get_position ( ) ;
2021-06-04 15:39:46 +00:00
_edit . original_mouse_pos = b - > get_position ( ) ;
2019-03-16 08:15:39 +00:00
_edit . snap = spatial_editor - > is_snap_enabled ( ) ;
2017-05-20 15:38:03 +00:00
_edit . mode = TRANSFORM_NONE ;
2021-10-09 10:24:26 +00:00
_edit . original = spatial_editor - > get_gizmo_transform ( ) ; // To prevent to break when flipping with scale.
2014-10-12 05:13:22 +00:00
2021-07-27 10:55:57 +00:00
bool can_select_gizmos = spatial_editor - > get_single_selected_node ( ) ;
2014-10-12 05:13:22 +00:00
2017-05-20 15:38:03 +00:00
{
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ;
2021-07-27 10:55:57 +00:00
can_select_gizmos = can_select_gizmos & & view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
2017-05-20 15:38:03 +00:00
}
2014-10-12 05:13:22 +00:00
2021-07-27 10:55:57 +00:00
// Gizmo handles
if ( can_select_gizmos ) {
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = spatial_editor - > get_single_selected_node ( ) - > get_gizmos ( ) ;
bool intersected_handle = false ;
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ( ! seg . is_valid ( ) ) ) {
continue ;
}
2021-07-27 10:55:57 +00:00
int gizmo_handle = - 1 ;
2022-01-11 11:33:37 +00:00
bool gizmo_secondary = false ;
seg - > handles_intersect_ray ( camera , _edit . mouse_pos , b - > is_shift_pressed ( ) , gizmo_handle , gizmo_secondary ) ;
2021-07-27 10:55:57 +00:00
if ( gizmo_handle ! = - 1 ) {
_edit . gizmo = seg ;
_edit . gizmo_handle = gizmo_handle ;
2022-01-11 11:33:37 +00:00
_edit . gizmo_handle_secondary = gizmo_secondary ;
_edit . gizmo_initial_value = seg - > get_handle_value ( gizmo_handle , gizmo_secondary ) ;
2021-07-27 10:55:57 +00:00
intersected_handle = true ;
break ;
}
}
if ( intersected_handle ) {
break ;
}
}
// Transform gizmo
if ( _transform_gizmo_select ( _edit . mouse_pos ) ) {
break ;
}
// Subgizmos
if ( can_select_gizmos ) {
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( spatial_editor - > get_single_selected_node ( ) ) ;
Vector < Ref < Node3DGizmo > > gizmos = spatial_editor - > get_single_selected_node ( ) - > get_gizmos ( ) ;
bool intersected_subgizmo = false ;
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ( ! seg . is_valid ( ) ) ) {
continue ;
}
2021-06-23 14:49:50 +00:00
int subgizmo_id = seg - > subgizmos_intersect_ray ( camera , _edit . mouse_pos ) ;
if ( subgizmo_id ! = - 1 ) {
ERR_CONTINUE ( ! se ) ;
if ( b - > is_shift_pressed ( ) ) {
if ( se - > subgizmos . has ( subgizmo_id ) ) {
se - > subgizmos . erase ( subgizmo_id ) ;
} else {
se - > subgizmos . insert ( subgizmo_id , seg - > get_subgizmo_transform ( subgizmo_id ) ) ;
}
} else {
se - > subgizmos . clear ( ) ;
se - > subgizmos . insert ( subgizmo_id , seg - > get_subgizmo_transform ( subgizmo_id ) ) ;
}
if ( se - > subgizmos . is_empty ( ) ) {
se - > gizmo = Ref < EditorNode3DGizmo > ( ) ;
} else {
se - > gizmo = seg ;
}
seg - > redraw ( ) ;
spatial_editor - > update_transform_gizmo ( ) ;
2021-07-27 10:55:57 +00:00
intersected_subgizmo = true ;
2017-05-20 15:38:03 +00:00
break ;
2014-05-05 01:50:23 +00:00
}
}
2021-06-23 14:49:50 +00:00
2021-07-27 10:55:57 +00:00
if ( intersected_subgizmo ) {
2021-06-23 14:49:50 +00:00
break ;
}
2017-05-20 15:38:03 +00:00
}
2014-05-05 01:50:23 +00:00
2020-02-12 17:24:06 +00:00
clicked = ObjectID ( ) ;
2014-02-10 01:10:30 +00:00
2021-04-24 20:33:50 +00:00
if ( ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT & & b - > is_command_pressed ( ) ) | | spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_ROTATE ) {
2020-07-18 19:03:08 +00:00
begin_transform ( TRANSFORM_ROTATE , false ) ;
2017-05-20 15:38:03 +00:00
break ;
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_MOVE ) {
2020-07-18 19:03:08 +00:00
begin_transform ( TRANSFORM_TRANSLATE , false ) ;
2017-05-20 15:38:03 +00:00
break ;
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
if ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) {
2020-07-18 19:03:08 +00:00
begin_transform ( TRANSFORM_SCALE , false ) ;
2017-05-20 15:38:03 +00:00
break ;
}
2014-02-10 01:10:30 +00:00
2021-02-04 08:20:26 +00:00
if ( after ! = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ) {
//clicking is always deferred to either move or release
2022-02-09 23:24:52 +00:00
clicked = _select_ray ( b - > get_position ( ) ) ;
selection_in_progress = true ;
2014-02-10 01:10:30 +00:00
2021-02-04 08:20:26 +00:00
if ( clicked . is_null ( ) ) {
//default to regionselect
cursor . region_select = true ;
cursor . region_begin = b - > get_position ( ) ;
cursor . region_end = b - > get_position ( ) ;
}
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
surface - > update ( ) ;
} else {
if ( _edit . gizmo . is_valid ( ) ) {
2022-01-11 11:33:37 +00:00
_edit . gizmo - > commit_handle ( _edit . gizmo_handle , _edit . gizmo_handle_secondary , _edit . gizmo_initial_value , false ) ;
2020-03-26 21:49:16 +00:00
_edit . gizmo = Ref < EditorNode3DGizmo > ( ) ;
2017-05-20 15:38:03 +00:00
break ;
}
2021-06-23 14:49:50 +00:00
2021-02-04 08:20:26 +00:00
if ( after ! = EditorPlugin : : AFTER_GUI_INPUT_DESELECT ) {
2022-02-09 23:24:52 +00:00
selection_in_progress = false ;
2021-02-04 08:20:26 +00:00
if ( clicked . is_valid ( ) ) {
_select_clicked ( false ) ;
}
2014-02-10 01:10:30 +00:00
2021-02-04 08:20:26 +00:00
if ( cursor . region_select ) {
_select_region ( ) ;
cursor . region_select = false ;
surface - > update ( ) ;
}
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( _edit . mode ! = TRANSFORM_NONE ) {
2021-06-23 14:49:50 +00:00
Node3D * selected = spatial_editor - > get_single_selected_node ( ) ;
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( se & & se - > gizmo . is_valid ( ) ) {
Vector < int > ids ;
Vector < Transform3D > restore ;
2014-02-10 01:10:30 +00:00
2021-08-09 20:13:42 +00:00
for ( const KeyValue < int , Transform3D > & GE : se - > subgizmos ) {
ids . push_back ( GE . key ) ;
restore . push_back ( GE . value ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
se - > gizmo - > commit_subgizmos ( ids , restore , false ) ;
spatial_editor - > update_transform_gizmo ( ) ;
} else {
2020-07-18 19:03:08 +00:00
commit_transform ( ) ;
2014-02-10 01:10:30 +00:00
}
2017-05-20 15:38:03 +00:00
_edit . mode = TRANSFORM_NONE ;
set_message ( " " ) ;
2014-02-10 01:10:30 +00:00
}
2017-05-20 15:38:03 +00:00
surface - > update ( ) ;
}
2016-05-21 13:29:25 +00:00
2017-05-20 15:38:03 +00:00
} break ;
2021-03-25 20:56:12 +00:00
default :
break ;
2017-05-20 15:38:03 +00:00
}
}
2014-05-05 01:50:23 +00:00
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseMotion > m = p_event ;
2014-05-05 01:50:23 +00:00
2017-05-20 15:38:03 +00:00
if ( m . is_valid ( ) ) {
2017-06-03 08:54:24 +00:00
_edit . mouse_pos = m - > get_position ( ) ;
2014-05-05 01:50:23 +00:00
2021-06-23 14:49:50 +00:00
if ( spatial_editor - > get_single_selected_node ( ) ) {
Vector < Ref < Node3DGizmo > > gizmos = spatial_editor - > get_single_selected_node ( ) - > get_gizmos ( ) ;
Ref < EditorNode3DGizmo > found_gizmo ;
int found_handle = - 1 ;
2022-01-11 11:33:37 +00:00
bool found_handle_secondary = false ;
2021-06-23 14:49:50 +00:00
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2022-01-11 11:33:37 +00:00
seg - > handles_intersect_ray ( camera , _edit . mouse_pos , false , found_handle , found_handle_secondary ) ;
2021-06-23 14:49:50 +00:00
if ( found_handle ! = - 1 ) {
found_gizmo = seg ;
break ;
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
}
2021-06-23 14:49:50 +00:00
if ( found_gizmo . is_valid ( ) ) {
spatial_editor - > select_gizmo_highlight_axis ( - 1 ) ;
}
2022-01-11 11:33:37 +00:00
bool current_hover_handle_secondary = false ;
int curreny_hover_handle = spatial_editor - > get_current_hover_gizmo_handle ( current_hover_handle_secondary ) ;
if ( found_gizmo ! = spatial_editor - > get_current_hover_gizmo ( ) | | found_handle ! = curreny_hover_handle | | found_handle_secondary ! = current_hover_handle_secondary ) {
2021-06-23 14:49:50 +00:00
spatial_editor - > set_current_hover_gizmo ( found_gizmo ) ;
2022-01-11 11:33:37 +00:00
spatial_editor - > set_current_hover_gizmo_handle ( found_handle , found_handle_secondary ) ;
2021-06-23 14:49:50 +00:00
spatial_editor - > get_single_selected_node ( ) - > update_gizmos ( ) ;
}
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-13 21:31:57 +00:00
if ( spatial_editor - > get_current_hover_gizmo ( ) . is_null ( ) & & ( m - > get_button_mask ( ) & MouseButton : : MASK_LEFT ) = = MouseButton : : NONE & & ! _edit . gizmo . is_valid ( ) ) {
2021-06-23 14:49:50 +00:00
_transform_gizmo_select ( _edit . mouse_pos , true ) ;
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2017-09-19 00:30:48 +00:00
NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
2017-05-20 15:38:03 +00:00
NavigationMode nav_mode = NAVIGATION_NONE ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( _edit . gizmo . is_valid ( ) ) {
2022-01-11 11:33:37 +00:00
_edit . gizmo - > set_handle ( _edit . gizmo_handle , _edit . gizmo_handle_secondary , camera , m - > get_position ( ) ) ;
Variant v = _edit . gizmo - > get_handle_value ( _edit . gizmo_handle , _edit . gizmo_handle_secondary ) ;
String n = _edit . gizmo - > get_handle_name ( _edit . gizmo_handle , _edit . gizmo_handle_secondary ) ;
2017-05-20 15:38:03 +00:00
set_message ( n + " : " + String ( v ) ) ;
2014-02-10 01:10:30 +00:00
2020-07-18 19:03:08 +00:00
} else if ( ( m - > get_button_mask ( ) & MouseButton : : MASK_LEFT ) ! = MouseButton : : NONE | | _edit . instant ) {
2021-04-24 20:33:50 +00:00
if ( nav_scheme = = NAVIGATION_MAYA & & m - > is_alt_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ORBIT ;
2021-04-24 20:33:50 +00:00
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > is_alt_pressed ( ) & & m - > is_shift_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_PAN ;
2021-04-24 20:33:50 +00:00
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > is_alt_pressed ( ) & & m - > is_ctrl_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ZOOM ;
2021-04-24 20:33:50 +00:00
} else if ( nav_scheme = = NAVIGATION_MODO & & m - > is_alt_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ORBIT ;
} else {
2021-07-16 04:17:40 +00:00
const bool movement_threshold_passed = _edit . original_mouse_pos . distance_to ( _edit . mouse_pos ) > 8 * EDSCALE ;
2014-02-10 01:10:30 +00:00
2022-02-09 09:32:03 +00:00
// enable region-select if nothing has been selected yet or multi-select (shift key) is active
2022-02-09 23:24:52 +00:00
if ( selection_in_progress & & movement_threshold_passed ) {
if ( get_selected_count ( ) = = 0 | | clicked_wants_append ) {
cursor . region_select = true ;
cursor . region_begin = _edit . original_mouse_pos ;
clicked = ObjectID ( ) ;
}
2022-02-09 09:32:03 +00:00
}
2019-06-20 14:59:48 +00:00
if ( cursor . region_select ) {
2017-06-03 08:54:24 +00:00
cursor . region_end = m - > get_position ( ) ;
2017-05-20 15:38:03 +00:00
surface - > update ( ) ;
return ;
}
2014-02-10 01:10:30 +00:00
2022-02-09 23:24:52 +00:00
if ( clicked . is_valid ( ) & & movement_threshold_passed ) {
_compute_edit ( _edit . original_mouse_pos ) ;
clicked = ObjectID ( ) ;
_edit . mode = TRANSFORM_TRANSLATE ;
}
2020-05-14 14:41:43 +00:00
if ( _edit . mode = = TRANSFORM_NONE ) {
2017-05-20 15:38:03 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-07-18 19:03:08 +00:00
update_transform ( m - > get_position ( ) , _get_key_modifier ( m ) = = Key : : SHIFT ) ;
2017-05-20 15:38:03 +00:00
}
2021-08-13 21:31:57 +00:00
} else if ( ( m - > get_button_mask ( ) & MouseButton : : MASK_RIGHT ) ! = MouseButton : : NONE | | freelook_active ) {
2021-04-24 20:33:50 +00:00
if ( nav_scheme = = NAVIGATION_MAYA & & m - > is_alt_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ZOOM ;
2017-07-23 00:02:18 +00:00
} else if ( freelook_active ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_LOOK ;
2018-10-20 10:49:33 +00:00
} else if ( orthogonal ) {
nav_mode = NAVIGATION_PAN ;
2017-05-20 15:38:03 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-13 21:31:57 +00:00
} else if ( ( m - > get_button_mask ( ) & MouseButton : : MASK_MIDDLE ) ! = MouseButton : : NONE ) {
const Key mod = _get_key_modifier ( m ) ;
2017-05-20 15:38:03 +00:00
if ( nav_scheme = = NAVIGATION_GODOT ) {
2019-11-13 20:54:44 +00:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 20:54:44 +00:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ZOOM ;
2021-08-13 21:31:57 +00:00
} else if ( mod = = Key : : ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
2019-11-13 20:54:44 +00:00
// Always allow Alt as a modifier to better support graphic tablets.
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 20:54:44 +00:00
}
2017-05-20 15:38:03 +00:00
} else if ( nav_scheme = = NAVIGATION_MAYA ) {
2021-03-13 19:45:14 +00:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_PAN ;
2020-05-14 14:41:43 +00:00
}
2014-03-31 03:07:21 +00:00
}
2017-09-19 00:30:48 +00:00
} else if ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/emulate_3_button_mouse " ) ) {
2017-05-20 15:38:03 +00:00
// Handle trackpad (no external mouse) use case
2021-08-13 21:31:57 +00:00
const Key mod = _get_key_modifier ( m ) ;
2017-05-20 15:38:03 +00:00
2021-08-13 21:31:57 +00:00
if ( mod ! = Key : : NONE ) {
2019-11-13 20:54:44 +00:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 20:54:44 +00:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ZOOM ;
2021-08-13 21:31:57 +00:00
} else if ( mod = = Key : : ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
2019-11-13 20:54:44 +00:00
// Always allow Alt as a modifier to better support graphic tablets.
2017-05-20 15:38:03 +00:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 20:54:44 +00:00
}
2017-05-20 15:38:03 +00:00
}
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
switch ( nav_mode ) {
case NAVIGATION_PAN : {
2017-11-01 20:49:39 +00:00
_nav_pan ( m , _get_warped_mouse_motion ( m ) ) ;
2014-02-10 01:10:30 +00:00
2017-11-01 20:49:39 +00: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 15:08:36 +00:00
default : {
}
2017-11-01 20:49:39 +00:00
}
}
2017-03-22 20:18:47 +00:00
2017-11-01 20:49:39 +00:00
Ref < InputEventMagnifyGesture > magnify_gesture = p_event ;
if ( magnify_gesture . is_valid ( ) ) {
2020-05-14 14:41:43 +00:00
if ( is_freelook_active ( ) ) {
2017-11-01 20:49:39 +00:00
scale_freelook_speed ( magnify_gesture - > get_factor ( ) ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-11-01 20:49:39 +00:00
scale_cursor_distance ( 1.0 / magnify_gesture - > get_factor ( ) ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00: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 15:38:03 +00:00
2017-11-01 20:49:39 +00:00
if ( nav_scheme = = NAVIGATION_GODOT ) {
2021-08-13 21:31:57 +00:00
const Key mod = _get_key_modifier ( pan_gesture ) ;
2017-11-01 20:49:39 +00:00
2019-11-13 20:54:44 +00:00
if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/pan_modifier " ) ) {
2017-11-01 20:49:39 +00:00
nav_mode = NAVIGATION_PAN ;
2019-11-13 20:54:44 +00:00
} else if ( mod = = _get_key_modifier_setting ( " editors/3d/navigation/zoom_modifier " ) ) {
2017-11-01 20:49:39 +00:00
nav_mode = NAVIGATION_ZOOM ;
2021-08-13 21:31:57 +00:00
} else if ( mod = = Key : : ALT | | mod = = _get_key_modifier_setting ( " editors/3d/navigation/orbit_modifier " ) ) {
2019-11-13 20:54:44 +00:00
// Always allow Alt as a modifier to better support graphic tablets.
2017-11-01 20:49:39 +00:00
nav_mode = NAVIGATION_ORBIT ;
2019-11-13 20:54:44 +00:00
}
2017-11-01 20:49:39 +00:00
} else if ( nav_scheme = = NAVIGATION_MAYA ) {
2021-04-24 20:33:50 +00:00
if ( pan_gesture - > is_alt_pressed ( ) ) {
2017-11-01 20:49:39 +00:00
nav_mode = NAVIGATION_PAN ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00:00
}
switch ( nav_mode ) {
case NAVIGATION_PAN : {
2020-07-23 14:38:31 +00:00
_nav_pan ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-20 15:38:03 +00:00
} break ;
case NAVIGATION_ZOOM : {
2020-07-23 14:38:31 +00:00
_nav_zoom ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-20 15:38:03 +00:00
} break ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
case NAVIGATION_ORBIT : {
2020-07-23 14:38:31 +00:00
_nav_orbit ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-11-01 20:49:39 +00:00
2017-05-20 15:38:03 +00:00
} break ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
case NAVIGATION_LOOK : {
2020-07-23 14:38:31 +00:00
_nav_look ( pan_gesture , pan_gesture - > get_delta ( ) ) ;
2017-05-01 18:57:35 +00:00
2017-05-20 15:38:03 +00:00
} break ;
2017-05-01 18:57:35 +00:00
2019-04-09 15:08:36 +00:00
default : {
}
2017-05-20 15:38:03 +00:00
}
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
Ref < InputEventKey > k = p_event ;
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
if ( k . is_valid ( ) ) {
2020-05-14 14:41:43 +00:00
if ( ! k - > is_pressed ( ) ) {
2017-05-20 15:38:03 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-05-20 15:38:03 +00:00
2021-07-02 07:27:12 +00:00
if ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/emulate_numpad " ) ) {
2022-02-12 19:40:39 +00:00
const Key code = k - > get_physical_keycode ( ) ;
2021-08-13 21:31:57 +00:00
if ( code > = Key : : KEY_0 & & code < = Key : : KEY_9 ) {
k - > set_keycode ( code - Key : : KEY_0 + Key : : KP_0 ) ;
2021-07-02 07:27:12 +00:00
}
}
2022-02-11 10:36:47 +00:00
if ( _edit . mode = = TRANSFORM_NONE ) {
if ( k - > get_keycode ( ) = = Key : : ESCAPE & & ! cursor . region_select ) {
_clear_selected ( ) ;
return ;
}
} else {
2020-07-18 19:03:08 +00:00
// We're actively transforming, handle keys specially
TransformPlane new_plane = TRANSFORM_VIEW ;
String new_message ;
if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_x " , p_event ) ) {
new_plane = TRANSFORM_X_AXIS ;
new_message = TTR ( " X-Axis Transform. " ) ;
} else if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_y " , p_event ) ) {
new_plane = TRANSFORM_Y_AXIS ;
new_message = TTR ( " Y-Axis Transform. " ) ;
} else if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_z " , p_event ) ) {
new_plane = TRANSFORM_Z_AXIS ;
new_message = TTR ( " Z-Axis Transform. " ) ;
} else if ( _edit . mode ! = TRANSFORM_ROTATE ) { // rotating on a plane doesn't make sense
if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_yz " , p_event ) ) {
new_plane = TRANSFORM_YZ ;
new_message = TTR ( " YZ-Plane Transform. " ) ;
} else if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_xz " , p_event ) ) {
new_plane = TRANSFORM_XZ ;
new_message = TTR ( " XZ-Plane Transform. " ) ;
} else if ( ED_IS_SHORTCUT ( " spatial_editor/lock_transform_xy " , p_event ) ) {
new_plane = TRANSFORM_XY ;
new_message = TTR ( " XY-Plane Transform. " ) ;
}
}
if ( new_plane ! = TRANSFORM_VIEW ) {
if ( new_plane ! = _edit . plane ) {
// lock me once and get a global constraint
_edit . plane = new_plane ;
spatial_editor - > set_local_coords_enabled ( false ) ;
} else if ( ! spatial_editor - > are_local_coords_enabled ( ) ) {
// lock me twice and get a local constraint
spatial_editor - > set_local_coords_enabled ( true ) ;
} else {
// lock me thrice and we're back where we started
_edit . plane = TRANSFORM_VIEW ;
spatial_editor - > set_local_coords_enabled ( false ) ;
}
update_transform ( _edit . mouse_pos , Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) ;
set_message ( new_message , 2 ) ;
accept_event ( ) ;
return ;
}
}
2017-05-20 15:38:03 +00:00
if ( ED_IS_SHORTCUT ( " spatial_editor/snap " , p_event ) ) {
if ( _edit . mode ! = TRANSFORM_NONE ) {
2019-03-16 08:15:39 +00:00
_edit . snap = ! _edit . snap ;
2017-05-20 15:38:03 +00:00
}
}
if ( ED_IS_SHORTCUT ( " spatial_editor/bottom_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_BOTTOM ) ;
2017-05-20 15:38:03 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/top_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_TOP ) ;
2017-05-20 15:38:03 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/rear_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_REAR ) ;
2017-05-20 15:38:03 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/front_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_FRONT ) ;
2017-05-20 15:38:03 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/left_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_LEFT ) ;
2017-05-20 15:38:03 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/right_view " , p_event ) ) {
2017-12-19 14:29:55 +00:00
_menu_option ( VIEW_RIGHT ) ;
}
2021-08-22 16:23:32 +00:00
if ( ED_IS_SHORTCUT ( " spatial_editor/orbit_view_down " , p_event ) ) {
2021-11-08 22:53:35 +00:00
// Clamp rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
cursor . x_rot = CLAMP ( cursor . x_rot - Math_PI / 12.0 , - 1.57 , 1.57 ) ;
2021-10-20 05:05:59 +00:00
view_type = VIEW_TYPE_USER ;
_update_name ( ) ;
2021-08-22 16:23:32 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/orbit_view_up " , p_event ) ) {
2021-11-08 22:53:35 +00:00
// Clamp rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
cursor . x_rot = CLAMP ( cursor . x_rot + Math_PI / 12.0 , - 1.57 , 1.57 ) ;
2021-10-20 05:05:59 +00:00
view_type = VIEW_TYPE_USER ;
_update_name ( ) ;
2021-08-22 16:23:32 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/orbit_view_right " , p_event ) ) {
cursor . y_rot - = Math_PI / 12.0 ;
2021-10-20 05:05:59 +00:00
view_type = VIEW_TYPE_USER ;
_update_name ( ) ;
2021-08-22 16:23:32 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/orbit_view_left " , p_event ) ) {
cursor . y_rot + = Math_PI / 12.0 ;
2021-10-20 05:05:59 +00:00
view_type = VIEW_TYPE_USER ;
_update_name ( ) ;
2021-08-22 16:23:32 +00:00
}
if ( ED_IS_SHORTCUT ( " spatial_editor/orbit_view_180 " , p_event ) ) {
cursor . y_rot + = Math_PI ;
2021-10-20 05:05:59 +00:00
view_type = VIEW_TYPE_USER ;
_update_name ( ) ;
2021-08-22 16:23:32 +00:00
}
2017-12-19 14:29:55 +00:00
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 15:38:03 +00:00
}
2018-10-20 10:49:33 +00:00
// Orthgonal mode doesn't work in freelook.
if ( ! freelook_active & & ED_IS_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " , p_event ) ) {
2017-05-20 15:38:03 +00:00
_menu_option ( orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL ) ;
_update_name ( ) ;
}
2018-10-27 21:43:19 +00: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 14:29:55 +00:00
}
2017-05-20 15:38:03 +00:00
if ( ED_IS_SHORTCUT ( " spatial_editor/insert_anim_key " , p_event ) ) {
2020-05-14 14:41:43 +00:00
if ( ! get_selected_count ( ) | | _edit . mode ! = TRANSFORM_NONE ) {
2017-05-20 15:38:03 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-02-04 08:20:26 +00:00
if ( ! AnimationPlayerEditor : : get_singleton ( ) - > get_track_editor ( ) - > has_keying ( ) ) {
2017-05-20 15:38:03 +00:00
set_message ( TTR ( " Keying is disabled (no key inserted). " ) ) ;
return ;
}
2014-02-10 01:10:30 +00:00
2017-05-20 15:38:03 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-03-31 15:06:36 +00:00
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2017-05-20 15:38:03 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
2021-07-17 21:22:52 +00:00
spatial_editor - > emit_signal ( SNAME ( " transform_key_request " ) , sp , " " , sp - > get_transform ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-05-20 15:38:03 +00:00
set_message ( TTR ( " Animation Key Inserted. " ) ) ;
}
2020-07-18 19:03:08 +00:00
if ( ED_IS_SHORTCUT ( " spatial_editor/cancel_transform " , p_event ) & & _edit . mode ! = TRANSFORM_NONE ) {
cancel_transform ( ) ;
}
2022-03-05 19:57:51 +00:00
if ( ! is_freelook_active ( ) ) {
if ( ED_IS_SHORTCUT ( " spatial_editor/instant_translate " , p_event ) ) {
begin_transform ( TRANSFORM_TRANSLATE , true ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/instant_rotate " , p_event ) ) {
begin_transform ( TRANSFORM_ROTATE , true ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/instant_scale " , p_event ) ) {
begin_transform ( TRANSFORM_SCALE , true ) ;
}
2020-07-18 19:03:08 +00:00
}
2014-02-10 01:10:30 +00:00
2018-10-20 10:49:33 +00:00
// Freelook doesn't work in orthogonal mode.
if ( ! orthogonal & & ED_IS_SHORTCUT ( " spatial_editor/freelook_toggle " , p_event ) ) {
2017-10-30 00:22:48 +00:00
set_freelook_active ( ! is_freelook_active ( ) ) ;
2021-08-13 21:31:57 +00:00
} else if ( k - > get_keycode ( ) = = Key : : ESCAPE ) {
2017-10-30 00:22:48 +00:00
set_freelook_active ( false ) ;
}
2021-08-13 21:31:57 +00:00
if ( k - > get_keycode ( ) = = Key : : SPACE ) {
2020-05-14 14:41:43 +00:00
if ( ! k - > is_pressed ( ) ) {
2021-07-17 21:22:52 +00:00
emit_signal ( SNAME ( " toggle_maximize_view " ) , this ) ;
2020-05-14 14:41:43 +00:00
}
2017-05-20 15:38:03 +00:00
}
2021-10-14 22:00:27 +00:00
if ( ED_IS_SHORTCUT ( " spatial_editor/decrease_fov " , p_event ) ) {
scale_fov ( - 0.05 ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/increase_fov " , p_event ) ) {
scale_fov ( 0.05 ) ;
}
if ( ED_IS_SHORTCUT ( " spatial_editor/reset_fov " , p_event ) ) {
reset_fov ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2017-10-29 20:31:38 +00: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 14:41:43 +00:00
if ( freelook_active ) {
2017-10-29 20:31:38 +00:00
accept_event ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _nav_pan ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2017-11-01 20:49:39 +00:00
const NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
real_t pan_speed = 1 / 150.0 ;
2021-04-24 20:33:50 +00:00
if ( nav_scheme = = NAVIGATION_MAYA & & p_event - > is_shift_pressed ( ) ) {
2022-04-07 10:23:40 +00:00
pan_speed * = 10 ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00:00
2020-10-17 05:08:21 +00:00
Transform3D camera_transform ;
2017-11-01 20:49:39 +00: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 ) ;
2020-08-15 11:18:01 +00: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 20:49:39 +00:00
translation * = cursor . distance / DISTANCE_DEFAULT ;
camera_transform . translate ( translation ) ;
cursor . pos = camera_transform . origin ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _nav_zoom ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2017-11-01 20:49:39 +00:00
const NavigationScheme nav_scheme = ( NavigationScheme ) EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/navigation_scheme " ) . operator int ( ) ;
real_t zoom_speed = 1 / 80.0 ;
2021-04-24 20:33:50 +00:00
if ( nav_scheme = = NAVIGATION_MAYA & & p_event - > is_shift_pressed ( ) ) {
2022-04-07 10:23:40 +00:00
zoom_speed * = 10 ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00: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 14:41:43 +00:00
if ( p_relative . x > 0 ) {
2017-11-01 20:49:39 +00:00
scale_cursor_distance ( 1 - p_relative . x * zoom_speed ) ;
2020-05-14 14:41:43 +00:00
} else if ( p_relative . x < 0 ) {
2017-11-01 20:49:39 +00:00
scale_cursor_distance ( 1.0 / ( 1 + p_relative . x * zoom_speed ) ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00:00
} else {
2020-05-14 14:41:43 +00:00
if ( p_relative . y > 0 ) {
2017-11-01 20:49:39 +00:00
scale_cursor_distance ( 1 + p_relative . y * zoom_speed ) ;
2020-05-14 14:41:43 +00:00
} else if ( p_relative . y < 0 ) {
2017-11-01 20:49:39 +00:00
scale_cursor_distance ( 1.0 / ( 1 - p_relative . y * zoom_speed ) ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-01 20:49:39 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _nav_orbit ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2018-06-25 01:24:31 +00:00
if ( lock_rotation ) {
_nav_pan ( p_event , p_relative ) ;
return ;
}
2019-10-23 09:46:26 +00:00
if ( orthogonal & & auto_orthogonal ) {
_menu_option ( VIEW_PERSPECTIVE ) ;
}
2020-08-15 11:18:01 +00: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 20:49:39 +00:00
2018-03-14 13:32:29 +00: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 11:18:01 +00: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 09:05:43 +00:00
cursor . x_rot = CLAMP ( cursor . x_rot , - 1.57 , 1.57 ) ;
2020-08-15 11:18:01 +00:00
if ( invert_x_axis ) {
cursor . y_rot - = p_relative . x * radians_per_pixel ;
} else {
cursor . y_rot + = p_relative . x * radians_per_pixel ;
}
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_USER ;
2017-11-01 20:49:39 +00:00
_update_name ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _nav_look ( Ref < InputEventWithModifiers > p_event , const Vector2 & p_relative ) {
2018-10-20 10:49:33 +00:00
if ( orthogonal ) {
_nav_pan ( p_event , p_relative ) ;
return ;
}
2017-11-01 20:49:39 +00:00
2019-10-23 09:46:26 +00:00
if ( orthogonal & & auto_orthogonal ) {
_menu_option ( VIEW_PERSPECTIVE ) ;
}
2022-01-02 19:07:19 +00:00
// Scale mouse sensitivity with camera FOV scale when zoomed in to make it easier to point at things.
const real_t degrees_per_pixel = real_t ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_sensitivity " ) ) * MIN ( 1.0 , cursor . fov_scale ) ;
2020-08-15 11:18:01 +00:00
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 20:49:39 +00:00
2018-10-20 10:49:33 +00:00
// Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag".
2020-10-17 05:08:21 +00:00
const Transform3D prev_camera_transform = to_camera_transform ( cursor ) ;
2018-10-20 10:49:33 +00: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 20:49:39 +00:00
}
2020-08-15 11:18:01 +00: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 09:05:43 +00:00
cursor . x_rot = CLAMP ( cursor . x_rot , - 1.57 , 1.57 ) ;
2018-10-20 10:49:33 +00:00
2020-08-15 11:18:01 +00:00
cursor . y_rot + = p_relative . x * radians_per_pixel ;
2018-10-20 10:49:33 +00:00
// Look is like the opposite of Orbit: the focus point rotates around the camera
2020-10-17 05:08:21 +00:00
Transform3D camera_transform = to_camera_transform ( cursor ) ;
2018-10-20 10:49:33 +00:00
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 ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_USER ;
2018-10-20 10:49:33 +00:00
_update_name ( ) ;
2017-11-01 20:49:39 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : set_freelook_active ( bool active_now ) {
2017-10-08 00:43:57 +00: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 18:02:46 +00:00
previous_mouse_position = get_local_mouse_position ( ) ;
2017-10-30 00:22:48 +00:00
// Hide mouse like in an FPS (warping doesn't work)
2020-04-28 14:41:01 +00:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_CAPTURED ) ;
2017-10-30 00:22:48 +00:00
2017-10-08 00:43:57 +00: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 00:22:48 +00:00
// Restore mouse
2020-04-28 14:41:01 +00:00
Input : : get_singleton ( ) - > set_mouse_mode ( Input : : MOUSE_MODE_VISIBLE ) ;
2020-06-17 18:02:46 +00: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 00:43:57 +00:00
}
freelook_active = active_now ;
}
2021-10-14 22:00:27 +00:00
void Node3DEditorViewport : : scale_fov ( real_t p_fov_offset ) {
cursor . fov_scale = CLAMP ( cursor . fov_scale + p_fov_offset , 0.1 , 2.5 ) ;
surface - > update ( ) ;
}
void Node3DEditorViewport : : reset_fov ( ) {
cursor . fov_scale = 1.0 ;
surface - > update ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : scale_cursor_distance ( real_t scale ) {
2020-12-16 12:40:42 +00: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 03:40:17 +00: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 14:41:43 +00:00
}
2017-05-07 20:59:05 +00:00
2021-04-09 12:52:10 +00:00
if ( cursor . distance = = max_distance | | cursor . distance = = min_distance ) {
zoom_failed_attempts_count + + ;
} else {
zoom_failed_attempts_count = 0 ;
}
2020-06-22 03:40:17 +00:00
zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S ;
2017-10-08 00:43:57 +00:00
surface - > update ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : scale_freelook_speed ( real_t scale ) {
2020-12-16 12:40:42 +00: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 03:40:17 +00: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 14:41:43 +00:00
}
2017-05-07 20:59:05 +00:00
2020-06-22 03:40:17 +00:00
zoom_indicator_delay = ZOOM_FREELOOK_INDICATOR_DELAY_S ;
2017-05-07 20:59:05 +00:00
surface - > update ( ) ;
}
2020-03-26 21:49:16 +00:00
Point2i Node3DEditorViewport : : _get_warped_mouse_motion ( const Ref < InputEventMouseMotion > & p_ev_mouse_motion ) const {
2017-05-05 21:42:48 +00:00
Point2i relative ;
2022-03-06 20:39:19 +00:00
if ( bool ( EDITOR_GET ( " editors/3d/navigation/warped_mouse_panning " ) ) ) {
2020-04-28 13:19:37 +00:00
relative = Input : : get_singleton ( ) - > warp_mouse_motion ( p_ev_mouse_motion , surface - > get_global_rect ( ) ) ;
2017-05-05 21:42:48 +00:00
} else {
2017-05-20 15:38:03 +00:00
relative = p_ev_mouse_motion - > get_relative ( ) ;
2017-05-05 21:42:48 +00:00
}
return relative ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _update_freelook ( real_t delta ) {
2017-08-26 19:55:09 +00:00
if ( ! is_freelook_active ( ) ) {
2017-05-01 18:57:35 +00:00
return ;
2017-08-26 19:55:09 +00:00
}
2017-05-01 18:57:35 +00:00
2020-04-18 14:20:35 +00: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 20:47:47 +00:00
const Vector3 right = camera - > get_transform ( ) . basis . xform ( Vector3 ( 1 , 0 , 0 ) ) ;
2020-04-18 14:20:35 +00: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 18:57:35 +00:00
2017-08-26 19:55:09 +00:00
Vector3 direction ;
2017-05-01 18:57:35 +00:00
2021-11-02 15:02:31 +00:00
// Use actions from the inputmap, as this is the only way to reliably detect input in this method.
// See #54469 for more discussion and explanation.
Input * inp = Input : : get_singleton ( ) ;
if ( inp - > is_action_pressed ( " spatial_editor/freelook_left " ) ) {
2017-08-26 19:55:09 +00:00
direction - = right ;
2017-05-01 18:57:35 +00:00
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_right " ) ) {
2017-08-26 19:55:09 +00:00
direction + = right ;
2017-05-01 18:57:35 +00:00
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_forward " ) ) {
2017-08-26 19:55:09 +00:00
direction + = forward ;
2017-05-01 18:57:35 +00:00
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_backwards " ) ) {
2017-08-26 19:55:09 +00:00
direction - = forward ;
2017-05-01 18:57:35 +00:00
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_up " ) ) {
2017-08-26 19:55:09 +00:00
direction + = up ;
2017-05-01 18:57:35 +00:00
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_down " ) ) {
2017-08-26 19:55:09 +00:00
direction - = up ;
2017-05-01 18:57:35 +00:00
}
2017-10-08 00:43:57 +00:00
real_t speed = freelook_speed ;
2019-10-14 20:47:47 +00:00
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_speed_modifier " ) ) {
2019-10-14 20:47:47 +00:00
speed * = 3.0 ;
}
2021-11-02 15:02:31 +00:00
if ( inp - > is_action_pressed ( " spatial_editor/freelook_slow_modifier " ) ) {
2019-10-14 20:47:47 +00:00
speed * = 0.333333 ;
2017-10-08 00:43:57 +00:00
}
2017-05-07 20:59:05 +00:00
2019-10-14 20:47:47 +00:00
const Vector3 motion = direction * speed * delta ;
2017-10-08 00:43:57 +00:00
cursor . pos + = motion ;
cursor . eye_pos + = motion ;
2017-05-01 18:57:35 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : set_message ( String p_message , float p_time ) {
2017-03-05 15:44:50 +00:00
message = p_message ;
message_time = p_time ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00: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 21:13:48 +00:00
if ( viewport - > is_visible ( ) ) {
viewport - > notification ( Control : : NOTIFICATION_VISIBILITY_CHANGED ) ;
}
}
}
2021-02-13 14:06:56 +00:00
void Node3DEditorViewport : : _project_settings_changed ( ) {
//update shadow atlas if changed
2022-04-30 23:40:30 +00:00
int shadowmap_size = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_size " ) ;
bool shadowmap_16_bits = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_16_bits " ) ;
int atlas_q0 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_quadrant_0_subdiv " ) ;
int atlas_q1 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_quadrant_1_subdiv " ) ;
int atlas_q2 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_quadrant_2_subdiv " ) ;
int atlas_q3 = ProjectSettings : : get_singleton ( ) - > get ( " rendering/shadows/positional_shadow/atlas_quadrant_3_subdiv " ) ;
viewport - > set_positional_shadow_atlas_size ( shadowmap_size ) ;
viewport - > set_positional_shadow_atlas_16_bits ( shadowmap_16_bits ) ;
viewport - > set_positional_shadow_atlas_quadrant_subdiv ( 0 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q0 ) ) ;
viewport - > set_positional_shadow_atlas_quadrant_subdiv ( 1 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q1 ) ) ;
viewport - > set_positional_shadow_atlas_quadrant_subdiv ( 2 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q2 ) ) ;
viewport - > set_positional_shadow_atlas_quadrant_subdiv ( 3 , Viewport : : PositionalShadowAtlasQuadrantSubdiv ( atlas_q3 ) ) ;
2021-02-13 14:06:56 +00:00
2022-06-03 00:12:41 +00:00
_update_shrink ( ) ;
2021-02-13 14:06:56 +00:00
// Update MSAA, screen-space AA and debanding if changed
2021-02-17 16:44:49 +00:00
const int msaa_mode = ProjectSettings : : get_singleton ( ) - > get ( " rendering/anti_aliasing/quality/msaa " ) ;
2021-02-13 14:06:56 +00:00
viewport - > set_msaa ( Viewport : : MSAA ( msaa_mode ) ) ;
2021-02-17 16:44:49 +00:00
const int ssaa_mode = GLOBAL_GET ( " rendering/anti_aliasing/quality/screen_space_aa " ) ;
2021-02-13 14:06:56 +00:00
viewport - > set_screen_space_aa ( Viewport : : ScreenSpaceAA ( ssaa_mode ) ) ;
2022-04-04 14:10:22 +00:00
const bool use_taa = GLOBAL_GET ( " rendering/anti_aliasing/quality/use_taa " ) ;
viewport - > set_use_taa ( use_taa ) ;
2021-02-17 16:44:49 +00:00
const bool use_debanding = GLOBAL_GET ( " rendering/anti_aliasing/quality/use_debanding " ) ;
2021-02-13 14:06:56 +00:00
viewport - > set_use_debanding ( use_debanding ) ;
2021-04-20 16:40:24 +00:00
const bool use_occlusion_culling = GLOBAL_GET ( " rendering/occlusion_culling/use_occlusion_culling " ) ;
viewport - > set_use_occlusion_culling ( use_occlusion_culling ) ;
2021-09-07 15:44:50 +00:00
2021-12-28 23:10:41 +00:00
const float mesh_lod_threshold = GLOBAL_GET ( " rendering/mesh_lod/lod_change/threshold_pixels " ) ;
viewport - > set_mesh_lod_threshold ( mesh_lod_threshold ) ;
2022-06-18 23:05:17 +00:00
const Viewport : : Scaling3DMode scaling_3d_mode = Viewport : : Scaling3DMode ( int ( GLOBAL_GET ( " rendering/scaling_3d/mode " ) ) ) ;
viewport - > set_scaling_3d_mode ( scaling_3d_mode ) ;
const float scaling_3d_scale = GLOBAL_GET ( " rendering/scaling_3d/scale " ) ;
viewport - > set_scaling_3d_scale ( scaling_3d_scale ) ;
const float fsr_sharpness = GLOBAL_GET ( " rendering/scaling_3d/fsr_sharpness " ) ;
viewport - > set_fsr_sharpness ( fsr_sharpness ) ;
const float fsr_mipmap_bias = GLOBAL_GET ( " rendering/scaling_3d/fsr_mipmap_bias " ) ;
viewport - > set_fsr_mipmap_bias ( fsr_mipmap_bias ) ;
2021-02-13 14:06:56 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _notification ( int p_what ) {
2022-02-16 02:44:22 +00:00
switch ( p_what ) {
case NOTIFICATION_READY : {
EditorNode : : get_singleton ( ) - > connect ( " project_settings_changed " , callable_mp ( this , & Node3DEditorViewport : : _project_settings_changed ) ) ;
} break ;
2021-02-13 14:06:56 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_VISIBILITY_CHANGED : {
bool visible = is_visible_in_tree ( ) ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
set_process ( visible ) ;
2016-04-06 06:34:34 +00:00
2022-02-16 02:44:22 +00:00
if ( visible ) {
orthogonal = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ORTHOGONAL ) ) ;
_update_name ( ) ;
_update_camera ( 0 ) ;
} else {
set_freelook_active ( false ) ;
}
call_deferred ( SNAME ( " update_transform_gizmo_view " ) ) ;
rotation_control - > set_visible ( EditorSettings : : get_singleton ( ) - > get ( " editors/3d/navigation/show_viewport_rotation_gizmo " ) ) ;
} break ;
2014-05-05 01:50:23 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_RESIZED : {
call_deferred ( SNAME ( " update_transform_gizmo_view " ) ) ;
} break ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_PROCESS : {
real_t delta = get_process_delta_time ( ) ;
2017-05-07 20:59:05 +00:00
2022-02-16 02:44:22 +00:00
if ( zoom_indicator_delay > 0 ) {
zoom_indicator_delay - = delta ;
if ( zoom_indicator_delay < = 0 ) {
surface - > update ( ) ;
zoom_limit_label - > hide ( ) ;
}
2017-05-07 20:59:05 +00:00
}
2022-02-16 02:44:22 +00:00
_update_freelook ( delta ) ;
2017-05-01 18:57:35 +00:00
2022-02-16 02:44:22 +00:00
Node * scene_root = SceneTreeDock : : get_singleton ( ) - > get_editor_data ( ) - > get_edited_scene_root ( ) ;
if ( previewing_cinema & & scene_root ! = nullptr ) {
Camera3D * cam = scene_root - > get_viewport ( ) - > get_camera_3d ( ) ;
if ( cam ! = nullptr & & cam ! = previewing ) {
//then switch the viewport's camera to the scene's viewport camera
if ( previewing ! = nullptr ) {
previewing - > disconnect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
}
previewing = cam ;
previewing - > connect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , cam - > get_camera ( ) ) ;
surface - > update ( ) ;
2018-07-26 22:36:05 +00:00
}
}
2022-02-16 02:44:22 +00:00
_update_camera ( delta ) ;
2014-02-10 01:10:30 +00:00
2022-05-13 13:04:37 +00:00
const HashMap < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
bool changed = false ;
bool exist = false ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
for ( const KeyValue < Node * , Object * > & E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E . key ) ;
if ( ! sp ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
Transform3D t = sp - > get_global_gizmo_transform ( ) ;
VisualInstance3D * vi = Object : : cast_to < VisualInstance3D > ( sp ) ;
AABB new_aabb = vi ? vi - > get_aabb ( ) : _calculate_spatial_bounds ( sp ) ;
2020-03-10 15:23:22 +00:00
2022-02-16 02:44:22 +00:00
exist = true ;
if ( se - > last_xform = = t & & se - > aabb = = new_aabb & & ! se - > last_xform_dirty ) {
continue ;
}
changed = true ;
se - > last_xform_dirty = false ;
se - > last_xform = t ;
2020-03-10 15:23:22 +00:00
2022-02-16 02:44:22 +00:00
se - > aabb = new_aabb ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
Transform3D t_offset = t ;
2017-08-23 00:05:41 +00:00
2022-02-16 02:44:22 +00:00
// apply AABB scaling before item's global transform
{
const Vector3 offset ( 0.005 , 0.005 , 0.005 ) ;
Basis aabb_s ;
aabb_s . scale ( se - > aabb . size + offset ) ;
t . translate ( se - > aabb . position - offset / 2 ) ;
t . basis = t . basis * aabb_s ;
}
{
const Vector3 offset ( 0.01 , 0.01 , 0.01 ) ;
Basis aabb_s ;
aabb_s . scale ( se - > aabb . size + offset ) ;
t_offset . translate ( se - > aabb . position - offset / 2 ) ;
t_offset . basis = t_offset . basis * aabb_s ;
}
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance , t ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance_offset , t_offset ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance_xray , t ) ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( se - > sbox_instance_xray_offset , t_offset ) ;
2021-08-09 14:51:30 +00:00
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
if ( changed | | ( spatial_editor - > is_gizmo_visible ( ) & & ! exist ) ) {
spatial_editor - > update_transform_gizmo ( ) ;
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
if ( message_time > 0 ) {
if ( message ! = last_message ) {
surface - > update ( ) ;
last_message = message ;
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
message_time - = get_physics_process_delta_time ( ) ;
if ( message_time < 0 ) {
surface - > update ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2022-02-16 02:44:22 +00:00
bool show_info = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_INFORMATION ) ) ;
if ( show_info ! = info_label - > is_visible ( ) ) {
info_label - > set_visible ( show_info ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
Camera3D * current_camera ;
2017-06-11 21:13:04 +00:00
2022-02-16 02:44:22 +00:00
if ( previewing ) {
current_camera = previewing ;
} else {
current_camera = camera ;
}
if ( show_info ) {
const String viewport_size = vformat ( String : : utf8 ( " %d × %d " ) , viewport - > get_size ( ) . x , viewport - > get_size ( ) . y ) ;
String text ;
text + = vformat ( TTR ( " X: %s \n " ) , rtos ( current_camera - > get_position ( ) . x ) . pad_decimals ( 1 ) ) ;
text + = vformat ( TTR ( " Y: %s \n " ) , rtos ( current_camera - > get_position ( ) . y ) . pad_decimals ( 1 ) ) ;
text + = vformat ( TTR ( " Z: %s \n " ) , rtos ( current_camera - > get_position ( ) . z ) . pad_decimals ( 1 ) ) ;
text + = " \n " ;
text + = vformat (
TTR ( " Size: %s (%.1fMP) \n " ) ,
viewport_size ,
viewport - > get_size ( ) . x * viewport - > get_size ( ) . y * 0.000001 ) ;
text + = " \n " ;
text + = vformat ( TTR ( " Objects: %d \n " ) , viewport - > get_render_info ( Viewport : : RENDER_INFO_TYPE_VISIBLE , Viewport : : RENDER_INFO_OBJECTS_IN_FRAME ) ) ;
2022-03-26 17:25:13 +00:00
text + = vformat ( TTR ( " Primitive Indices: %d \n " ) , viewport - > get_render_info ( Viewport : : RENDER_INFO_TYPE_VISIBLE , Viewport : : RENDER_INFO_PRIMITIVES_IN_FRAME ) ) ;
2022-02-16 02:44:22 +00:00
text + = vformat ( TTR ( " Draw Calls: %d " ) , viewport - > get_render_info ( Viewport : : RENDER_INFO_TYPE_VISIBLE , Viewport : : RENDER_INFO_DRAW_CALLS_IN_FRAME ) ) ;
info_label - > set_text ( text ) ;
}
// FPS Counter.
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 ( ) ) {
cpu_time_label - > set_visible ( show_fps ) ;
gpu_time_label - > set_visible ( show_fps ) ;
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 ;
gpu_time_history_index = 0 ;
}
if ( show_fps ) {
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 ;
double cpu_time = 0.0 ;
for ( int i = 0 ; i < FRAME_TIME_HISTORY ; i + + ) {
cpu_time + = cpu_time_history [ i ] ;
}
cpu_time / = FRAME_TIME_HISTORY ;
// Prevent unrealistically low values.
cpu_time = MAX ( 0.01 , cpu_time ) ;
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 ;
double gpu_time = 0.0 ;
for ( int i = 0 ; i < FRAME_TIME_HISTORY ; i + + ) {
gpu_time + = gpu_time_history [ i ] ;
}
gpu_time / = FRAME_TIME_HISTORY ;
// Prevent division by zero for the FPS counter (and unrealistically low values).
// This limits the reported FPS to 100000.
gpu_time = MAX ( 0.01 , gpu_time ) ;
// 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 " ) , rtos ( cpu_time ) . pad_decimals ( 2 ) ) ) ;
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 " ) , rtos ( gpu_time ) . pad_decimals ( 2 ) ) ) ;
// 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 double 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 ) ) ) ;
}
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 ;
cinema_label - > set_anchor_and_offset ( SIDE_LEFT , 0.5f , - cinema_half_width ) ;
}
2018-08-29 22:44:47 +00:00
2022-02-16 02:44:22 +00:00
if ( lock_rotation ) {
float locked_half_width = locked_label - > get_size ( ) . width / 2.0f ;
locked_label - > set_anchor_and_offset ( SIDE_LEFT , 0.5f , - locked_half_width ) ;
}
} break ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_ENTER_TREE : {
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 ) ) ;
_init_gizmo_instance ( index ) ;
} break ;
2014-02-10 01:10:30 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_EXIT_TREE : {
_finish_gizmo_instances ( ) ;
} break ;
2020-12-26 19:21:07 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_THEME_CHANGED : {
view_menu - > set_icon ( get_theme_icon ( SNAME ( " GuiTabMenuHl " ) , SNAME ( " EditorIcons " ) ) ) ;
preview_camera - > set_icon ( get_theme_icon ( SNAME ( " Camera3D " ) , SNAME ( " EditorIcons " ) ) ) ;
Control * gui_base = EditorNode : : get_singleton ( ) - > get_gui_base ( ) ;
view_menu - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
view_menu - > add_theme_style_override ( " hover " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
view_menu - > add_theme_style_override ( " pressed " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
view_menu - > add_theme_style_override ( " focus " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
view_menu - > add_theme_style_override ( " disabled " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
preview_camera - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
preview_camera - > add_theme_style_override ( " hover " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
preview_camera - > add_theme_style_override ( " pressed " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
preview_camera - > add_theme_style_override ( " focus " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
preview_camera - > add_theme_style_override ( " disabled " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
frame_time_gradient - > set_color ( 0 , get_theme_color ( SNAME ( " success_color " ) , SNAME ( " Editor " ) ) ) ;
frame_time_gradient - > set_color ( 1 , get_theme_color ( SNAME ( " warning_color " ) , SNAME ( " Editor " ) ) ) ;
frame_time_gradient - > set_color ( 2 , get_theme_color ( SNAME ( " error_color " ) , SNAME ( " Editor " ) ) ) ;
info_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
cpu_time_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
gpu_time_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
fps_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
cinema_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
locked_label - > add_theme_style_override ( " normal " , gui_base - > get_theme_stylebox ( SNAME ( " Information3dViewport " ) , SNAME ( " EditorStyles " ) ) ) ;
} break ;
2014-02-10 01:10:30 +00:00
}
}
2022-03-13 17:57:28 +00:00
static void draw_indicator_bar ( Control & p_surface , real_t p_fill , const Ref < Texture2D > p_icon , const Ref < Font > p_font , int p_font_size , const String & p_text , const Color & p_color ) {
2017-10-15 19:20:51 +00:00
// Adjust bar size from control height
2022-03-13 17:57:28 +00:00
const Vector2 surface_size = p_surface . get_size ( ) ;
2020-06-13 19:56:03 +00:00
const real_t h = surface_size . y / 2.0 ;
const real_t y = ( surface_size . y - h ) / 2.0 ;
2017-10-15 19:20:51 +00:00
2020-06-13 19:56:03 +00:00
const Rect2 r ( 10 * EDSCALE , y , 6 * EDSCALE , h ) ;
2022-03-13 17:57:28 +00:00
const real_t sy = r . size . y * p_fill ;
2017-10-15 19:20:51 +00: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
2022-03-13 17:57:28 +00:00
p_surface . draw_rect ( r , p_color * Color ( 1 , 1 , 1 , 0.2 ) ) ;
p_surface . draw_rect ( Rect2 ( r . position . x , r . position . y + r . size . y - sy , r . size . x , sy ) , p_color * Color ( 1 , 1 , 1 , 0.6 ) ) ;
p_surface . draw_rect ( r . grow ( 1 ) , Color ( 0 , 0 , 0 , 0.7 ) , false , Math : : round ( EDSCALE ) ) ;
2017-10-15 19:20:51 +00:00
2022-03-13 17:57:28 +00:00
const Vector2 icon_size = p_icon - > get_size ( ) ;
2020-06-13 19:56:03 +00:00
const Vector2 icon_pos = Vector2 ( r . position . x - ( icon_size . x - r . size . x ) / 2 , r . position . y + r . size . y + 2 * EDSCALE ) ;
2022-03-13 17:57:28 +00:00
p_surface . draw_texture ( p_icon , icon_pos , p_color ) ;
2020-06-13 19:56:03 +00:00
// Draw text below the bar (for speed/zoom information).
2022-05-09 09:47:10 +00:00
p_surface . draw_string_outline ( p_font , Vector2 ( icon_pos . x , icon_pos . y + icon_size . y + 16 * EDSCALE ) , p_text , HORIZONTAL_ALIGNMENT_LEFT , - 1.f , p_font_size , Math : : round ( 2 * EDSCALE ) , Color ( 0 , 0 , 0 ) ) ;
p_surface . draw_string ( p_font , Vector2 ( icon_pos . x , icon_pos . y + icon_size . y + 16 * EDSCALE ) , p_text , HORIZONTAL_ALIGNMENT_LEFT , - 1.f , p_font_size , p_color ) ;
2017-05-07 20:59:05 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _draw ( ) {
2017-10-29 19:32:09 +00:00
EditorPluginList * over_plugin_list = EditorNode : : get_singleton ( ) - > get_editor_plugins_over ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! over_plugin_list - > is_empty ( ) ) {
2018-09-18 18:00:07 +00:00
over_plugin_list - > forward_spatial_draw_over_viewport ( surface ) ;
2017-10-29 19:32:09 +00:00
}
2022-01-27 09:36:51 +00:00
EditorPluginList * force_over_plugin_list = EditorNode : : get_singleton ( ) - > get_editor_plugins_force_over ( ) ;
2020-12-15 12:04:21 +00:00
if ( ! force_over_plugin_list - > is_empty ( ) ) {
2018-09-18 18:00:07 +00:00
force_over_plugin_list - > forward_spatial_force_draw_over_viewport ( surface ) ;
2017-10-29 19:32:09 +00:00
}
2014-02-10 01:10:30 +00:00
if ( surface - > has_focus ( ) ) {
Size2 size = surface - > get_size ( ) ;
2017-03-05 15:44:50 +00:00
Rect2 r = Rect2 ( Point2 ( ) , size ) ;
2021-05-08 23:56:22 +00:00
get_theme_stylebox ( SNAME ( " FocusViewport " ) , SNAME ( " EditorStyles " ) ) - > draw ( surface - > get_canvas_item ( ) , r ) ;
2014-02-10 01:10:30 +00:00
}
if ( cursor . region_select ) {
2019-08-15 20:17:08 +00:00
const Rect2 selection_rect = Rect2 ( cursor . region_begin , cursor . region_end - cursor . region_begin ) ;
surface - > draw_rect (
selection_rect ,
2021-07-17 21:22:52 +00:00
get_theme_color ( SNAME ( " box_selection_fill_color " ) , SNAME ( " Editor " ) ) ) ;
2014-02-10 01:10:30 +00:00
2019-08-15 20:17:08 +00:00
surface - > draw_rect (
selection_rect ,
2021-07-17 21:22:52 +00:00
get_theme_color ( SNAME ( " box_selection_stroke_color " ) , SNAME ( " Editor " ) ) ,
2019-08-15 20:17:08 +00:00
false ,
Math : : round ( EDSCALE ) ) ;
2014-02-10 01:10:30 +00:00
}
2019-08-15 20:17:08 +00:00
RID ci = surface - > get_canvas_item ( ) ;
2017-03-05 15:44:50 +00:00
if ( message_time > 0 ) {
2021-07-17 21:22:52 +00:00
Ref < Font > font = get_theme_font ( SNAME ( " font " ) , SNAME ( " Label " ) ) ;
int font_size = get_theme_font_size ( SNAME ( " font_size " ) , SNAME ( " Label " ) ) ;
2017-03-05 15:44:50 +00:00
Point2 msgpos = Point2 ( 5 , get_size ( ) . y - 20 ) ;
2021-11-25 02:58:47 +00:00
font - > draw_string ( ci , msgpos + Point2 ( 1 , 1 ) , message , HORIZONTAL_ALIGNMENT_LEFT , - 1 , font_size , Color ( 0 , 0 , 0 , 0.8 ) ) ;
font - > draw_string ( ci , msgpos + Point2 ( - 1 , - 1 ) , message , HORIZONTAL_ALIGNMENT_LEFT , - 1 , font_size , Color ( 0 , 0 , 0 , 0.8 ) ) ;
font - > draw_string ( ci , msgpos , message , HORIZONTAL_ALIGNMENT_LEFT , - 1 , font_size , Color ( 1 , 1 , 1 , 1 ) ) ;
2014-02-10 01:10:30 +00:00
}
2022-01-17 14:48:21 +00:00
if ( _edit . mode = = TRANSFORM_ROTATE & & _edit . show_rotation_line ) {
2014-02-10 01:10:30 +00:00
Point2 center = _point_to_screen ( _edit . center ) ;
2020-12-16 13:32:02 +00:00
Color handle_color ;
switch ( _edit . plane ) {
case TRANSFORM_X_AXIS :
2021-07-17 21:22:52 +00:00
handle_color = get_theme_color ( SNAME ( " axis_x_color " ) , SNAME ( " Editor " ) ) ;
2020-12-16 13:32:02 +00:00
break ;
case TRANSFORM_Y_AXIS :
2021-07-17 21:22:52 +00:00
handle_color = get_theme_color ( SNAME ( " axis_y_color " ) , SNAME ( " Editor " ) ) ;
2020-12-16 13:32:02 +00:00
break ;
case TRANSFORM_Z_AXIS :
2021-07-17 21:22:52 +00:00
handle_color = get_theme_color ( SNAME ( " axis_z_color " ) , SNAME ( " Editor " ) ) ;
2020-12-16 13:32:02 +00:00
break ;
default :
2021-07-17 21:22:52 +00:00
handle_color = get_theme_color ( SNAME ( " accent_color " ) , SNAME ( " Editor " ) ) ;
2020-12-16 13:32:02 +00:00
break ;
}
2021-07-18 22:09:59 +00:00
handle_color = handle_color . from_hsv ( handle_color . get_h ( ) , 0.25 , 1.0 , 1 ) ;
2020-12-16 13:32:02 +00:00
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > canvas_item_add_line (
2019-03-29 13:19:44 +00:00
ci ,
_edit . mouse_pos ,
center ,
2020-12-16 13:32:02 +00:00
handle_color ,
2019-06-25 01:24:07 +00:00
Math : : round ( 2 * EDSCALE ) ) ;
2014-02-10 01:10:30 +00:00
}
2014-09-15 23:06:37 +00:00
if ( previewing ) {
2021-03-31 11:50:24 +00:00
Size2 ss = Size2 ( ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/viewport_width " ) , ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/viewport_height " ) ) ;
2017-01-13 23:00:43 +00:00
float aspect = ss . aspect ( ) ;
2014-09-15 23:06:37 +00:00
Size2 s = get_size ( ) ;
Rect2 draw_rect ;
2017-03-05 15:44:50 +00:00
switch ( previewing - > get_keep_aspect_mode ( ) ) {
2020-03-26 21:49:16 +00:00
case Camera3D : : KEEP_WIDTH : {
2017-03-05 15:44:50 +00:00
draw_rect . size = Size2 ( s . width , s . width / aspect ) ;
2017-06-03 22:25:13 +00:00
draw_rect . position . x = 0 ;
draw_rect . position . y = ( s . height - draw_rect . size . y ) * 0.5 ;
2014-09-15 23:06:37 +00:00
} break ;
2020-03-26 21:49:16 +00:00
case Camera3D : : KEEP_HEIGHT : {
2017-03-05 15:44:50 +00:00
draw_rect . size = Size2 ( s . height * aspect , s . height ) ;
2017-06-03 22:25:13 +00:00
draw_rect . position . y = 0 ;
draw_rect . position . x = ( s . width - draw_rect . size . x ) * 0.5 ;
2014-09-15 23:06:37 +00:00
} break ;
}
2020-12-19 12:43:35 +00:00
draw_rect = Rect2 ( Vector2 ( ) , s ) . intersection ( draw_rect ) ;
2014-09-15 23:06:37 +00:00
2019-07-09 13:22:01 +00:00
surface - > draw_rect ( draw_rect , Color ( 0.6 , 0.6 , 0.1 , 0.5 ) , false , Math : : round ( 2 * EDSCALE ) ) ;
2017-05-07 20:59:05 +00:00
} else {
if ( zoom_indicator_delay > 0.0 ) {
2017-10-15 19:20:51 +00:00
if ( is_freelook_active ( ) ) {
// Show speed
2017-05-07 20:59:05 +00:00
2020-12-16 12:40:42 +00: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 19:20:51 +00:00
real_t scale_length = ( max_speed - min_speed ) ;
2017-05-07 20:59:05 +00:00
2019-01-16 15:42:53 +00:00
if ( ! Math : : is_zero_approx ( scale_length ) ) {
2022-04-07 10:23:40 +00:00
real_t logscale_t = 1.0 - Math : : log1p ( freelook_speed - min_speed ) / Math : : log1p ( scale_length ) ;
2017-05-07 20:59:05 +00:00
2020-06-13 19:56:03 +00: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 ,
2021-07-17 21:22:52 +00:00
get_theme_icon ( SNAME ( " ViewportSpeed " ) , SNAME ( " EditorIcons " ) ) ,
get_theme_font ( SNAME ( " font " ) , SNAME ( " Label " ) ) ,
get_theme_font_size ( SNAME ( " font_size " ) , SNAME ( " Label " ) ) ,
2022-03-13 17:57:28 +00:00
vformat ( " %s u/s " , String : : num ( freelook_speed ) . pad_decimals ( precision ) ) ,
Color ( 1.0 , 0.95 , 0.7 ) ) ;
2017-10-15 19:20:51 +00:00
}
2017-05-07 20:59:05 +00:00
2017-10-15 19:20:51 +00:00
} else {
// Show zoom
2021-04-09 12:52:10 +00:00
zoom_limit_label - > set_visible ( zoom_failed_attempts_count > 15 ) ;
2017-10-15 19:20:51 +00:00
2020-12-16 12:40:42 +00: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 19:20:51 +00:00
real_t scale_length = ( max_distance - min_distance ) ;
2019-01-16 15:42:53 +00:00
if ( ! Math : : is_zero_approx ( scale_length ) ) {
2022-04-07 10:23:40 +00:00
real_t logscale_t = 1.0 - Math : : log1p ( cursor . distance - min_distance ) / Math : : log1p ( scale_length ) ;
2017-10-15 19:20:51 +00:00
2020-06-13 19:56:03 +00: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 ,
2021-07-17 21:22:52 +00:00
get_theme_icon ( SNAME ( " ViewportZoom " ) , SNAME ( " EditorIcons " ) ) ,
get_theme_font ( SNAME ( " font " ) , SNAME ( " Label " ) ) ,
get_theme_font_size ( SNAME ( " font_size " ) , SNAME ( " Label " ) ) ,
2022-03-13 17:57:28 +00:00
vformat ( " %s u " , String : : num ( cursor . distance ) . pad_decimals ( precision ) ) ,
Color ( 0.7 , 0.95 , 1.0 ) ) ;
2017-10-15 19:20:51 +00:00
}
2017-05-07 20:59:05 +00:00
}
}
2014-09-15 23:06:37 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _menu_option ( int p_option ) {
2017-03-05 15:44:50 +00:00
switch ( p_option ) {
2014-02-10 01:10:30 +00:00
case VIEW_TOP : {
2017-03-05 15:44:50 +00:00
cursor . y_rot = 0 ;
2017-12-19 14:29:55 +00:00
cursor . x_rot = Math_PI / 2.0 ;
set_message ( TTR ( " Top View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_TOP ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2017-12-19 14:29:55 +00:00
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_BOTTOM : {
2017-03-05 15:44:50 +00:00
cursor . y_rot = 0 ;
2017-12-19 14:29:55 +00:00
cursor . x_rot = - Math_PI / 2.0 ;
set_message ( TTR ( " Bottom View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_BOTTOM ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_LEFT : {
2017-03-05 15:44:50 +00:00
cursor . x_rot = 0 ;
2017-12-19 14:29:55 +00:00
cursor . y_rot = Math_PI / 2.0 ;
set_message ( TTR ( " Left View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_LEFT ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_RIGHT : {
2017-03-05 15:44:50 +00:00
cursor . x_rot = 0 ;
2017-12-19 14:29:55 +00:00
cursor . y_rot = - Math_PI / 2.0 ;
set_message ( TTR ( " Right View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_RIGHT ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_FRONT : {
2017-03-05 15:44:50 +00:00
cursor . x_rot = 0 ;
2021-02-02 18:44:38 +00:00
cursor . y_rot = Math_PI ;
2017-12-19 14:29:55 +00:00
set_message ( TTR ( " Front View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_FRONT ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_REAR : {
2017-03-05 15:44:50 +00:00
cursor . x_rot = 0 ;
2021-02-02 18:44:38 +00:00
cursor . y_rot = 0 ;
2017-12-19 14:29:55 +00:00
set_message ( TTR ( " Rear View. " ) , 2 ) ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_REAR ;
2019-10-23 09:46:26 +00:00
_set_auto_orthogonal ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
2016-10-04 18:39:38 +00:00
} break ;
case VIEW_CENTER_TO_ORIGIN : {
2017-03-05 15:44:50 +00:00
cursor . pos = Vector3 ( 0 , 0 , 0 ) ;
2016-10-04 18:39:38 +00:00
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_CENTER_TO_SELECTION : {
2016-07-28 19:37:52 +00:00
focus_selection ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
2018-10-27 21:43:19 +00:00
case VIEW_ALIGN_TRANSFORM_WITH_VIEW : {
2020-05-14 14:41:43 +00:00
if ( ! get_selected_count ( ) ) {
2014-03-31 15:06:36 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2014-03-31 15:06:36 +00:00
2020-10-17 05:08:21 +00:00
Transform3D camera_transform = camera - > get_global_transform ( ) ;
2014-03-31 15:06:36 +00:00
2017-03-05 15:44:50 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-03-31 15:06:36 +00:00
2018-10-27 21:43:19 +00:00
undo_redo - > create_action ( TTR ( " Align Transform with View " ) ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2014-03-31 15:06:36 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-03-31 15:06:36 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 14:41:43 +00:00
if ( ! se ) {
2014-03-31 15:06:36 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-03-31 15:06:36 +00:00
2020-10-17 05:08:21 +00:00
Transform3D xform ;
2018-10-22 14:52:39 +00:00
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-29 23:44:12 +00:00
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( sp , " set_global_transform " , xform ) ;
2017-10-03 16:49:32 +00:00
undo_redo - > add_undo_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
2014-03-31 15:06:36 +00:00
}
undo_redo - > commit_action ( ) ;
2018-10-27 21:43:19 +00:00
} break ;
case VIEW_ALIGN_ROTATION_WITH_VIEW : {
2020-05-14 14:41:43 +00:00
if ( ! get_selected_count ( ) ) {
2018-10-27 21:43:19 +00:00
break ;
2020-05-14 14:41:43 +00:00
}
2018-10-27 21:43:19 +00:00
2020-10-17 05:08:21 +00:00
Transform3D camera_transform = camera - > get_global_transform ( ) ;
2018-10-27 21:43:19 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
undo_redo - > create_action ( TTR ( " Align Rotation with View " ) ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2018-10-27 21:43:19 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-10-27 21:43:19 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 14:41:43 +00:00
if ( ! se ) {
2018-10-27 21:43:19 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-10-27 21:43:19 +00:00
2021-10-21 16:38:20 +00:00
undo_redo - > add_do_method ( sp , " set_rotation " , camera_transform . basis . get_euler_normalized ( ) ) ;
2018-10-27 21:43:19 +00:00
undo_redo - > add_undo_method ( sp , " set_rotation " , sp - > get_rotation ( ) ) ;
}
undo_redo - > commit_action ( ) ;
2014-03-31 15:06:36 +00:00
} break ;
2014-02-10 01:10:30 +00:00
case VIEW_ENVIRONMENT : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_ENVIRONMENT ) ;
2017-03-05 15:44:50 +00:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2014-02-10 01:10:30 +00:00
if ( current ) {
2022-05-02 23:43:50 +00:00
camera - > set_environment ( Ref < Resource > ( ) ) ;
2014-02-10 01:10:30 +00:00
} else {
2020-03-26 21:49:16 +00:00
camera - > set_environment ( Node3DEditor : : get_singleton ( ) - > get_viewport_environment ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_PERSPECTIVE : {
2017-03-05 15:44:50 +00: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 09:46:26 +00:00
auto_orthogonal = false ;
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " update_transform_gizmo_view " ) ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-05-05 01:50:23 +00:00
2014-02-10 01:10:30 +00:00
} break ;
case VIEW_ORTHOGONAL : {
2017-03-05 15:44:50 +00: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 09:46:26 +00:00
auto_orthogonal = false ;
2021-07-17 21:22:52 +00:00
call_deferred ( SNAME ( " update_transform_gizmo_view " ) ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-02-10 01:10:30 +00:00
2018-06-25 01:24:31 +00:00
} break ;
2019-10-23 09:46:26 +00: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 01:24:31 +00: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 07:25:59 +00:00
locked_label - > show ( ) ;
2018-06-25 01:24:31 +00:00
} else {
2018-10-10 07:25:59 +00:00
locked_label - > hide ( ) ;
2018-06-25 01:24:31 +00:00
}
2014-02-10 01:10:30 +00:00
} break ;
2014-10-03 03:10:51 +00:00
case VIEW_AUDIO_LISTENER : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) ;
2017-03-05 15:44:50 +00:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2021-08-02 17:31:51 +00:00
viewport - > set_as_audio_listener_3d ( current ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-03 03:10:51 +00:00
2017-07-15 04:23:10 +00: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 21:49:16 +00:00
camera - > set_doppler_tracking ( current ? Camera3D : : DOPPLER_TRACKING_IDLE_STEP : Camera3D : : DOPPLER_TRACKING_DISABLED ) ;
2017-07-15 04:23:10 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-03 03:10:51 +00:00
} break ;
2018-07-26 22:36:05 +00: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 14:41:43 +00:00
if ( previewing ! = nullptr ) {
2018-07-26 22:36:05 +00:00
preview_camera - > show ( ) ;
2020-05-14 14:41:43 +00:00
}
2018-07-26 22:36:05 +00:00
}
} break ;
2014-10-12 05:13:22 +00:00
case VIEW_GIZMOS : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) ;
2017-03-05 15:44:50 +00:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
current = ! current ;
2020-11-26 19:00:03 +00:00
uint32_t layers = ( ( 1 < < 20 ) - 1 ) | ( 1 < < ( GIZMO_BASE_LAYER + index ) ) | ( 1 < < GIZMO_GRID_LAYER ) | ( 1 < < MISC_TOOL_LAYER ) ;
2020-05-14 14:41:43 +00:00
if ( current ) {
2020-11-26 19:00:03 +00:00
layers | = ( 1 < < GIZMO_EDIT_LAYER ) ;
2020-05-14 14:41:43 +00:00
}
2020-11-26 19:00:03 +00:00
camera - > set_cull_mask ( layers ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , current ) ;
2014-10-12 05:13:22 +00:00
2017-06-11 21:13:04 +00:00
} break ;
2017-10-31 17:23:25 +00: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 ) ;
2022-06-03 00:12:41 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , ! current ) ;
_update_shrink ( ) ;
2017-10-31 17:23:25 +00:00
} break ;
2017-06-11 21:13:04 +00: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 20:00:16 +00:00
} break ;
2020-04-10 17:18:42 +00:00
case VIEW_FRAME_TIME : {
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ;
2017-11-19 20:00:16 +00:00
bool current = view_menu - > get_popup ( ) - > is_item_checked ( idx ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , ! current ) ;
2014-10-12 05:13:22 +00:00
} break ;
2019-10-03 20:39:08 +00:00
case VIEW_DISPLAY_NORMAL :
case VIEW_DISPLAY_WIREFRAME :
case VIEW_DISPLAY_OVERDRAW :
case VIEW_DISPLAY_SHADELESS :
case VIEW_DISPLAY_LIGHTING :
2020-01-26 23:09:40 +00:00
case VIEW_DISPLAY_NORMAL_BUFFER :
2019-10-03 20:39:08 +00:00
case VIEW_DISPLAY_DEBUG_SHADOW_ATLAS :
case VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS :
2021-06-04 22:47:26 +00:00
case VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO :
case VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING :
case VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION :
2020-01-25 10:18:55 +00:00
case VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE :
2020-01-26 23:09:40 +00:00
case VIEW_DISPLAY_DEBUG_SSAO :
2021-08-03 07:07:32 +00:00
case VIEW_DISPLAY_DEBUG_SSIL :
2020-04-08 01:51:52 +00:00
case VIEW_DISPLAY_DEBUG_PSSM_SPLITS :
2020-04-14 03:05:21 +00:00
case VIEW_DISPLAY_DEBUG_DECAL_ATLAS :
2020-06-25 13:33:28 +00:00
case VIEW_DISPLAY_DEBUG_SDFGI :
case VIEW_DISPLAY_DEBUG_SDFGI_PROBES :
2020-12-17 18:56:59 +00:00
case VIEW_DISPLAY_DEBUG_GI_BUFFER :
2021-01-17 16:25:38 +00: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 :
2021-04-20 16:40:24 +00:00
case VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES :
2022-04-04 14:10:22 +00:00
case VIEW_DISPLAY_DEBUG_OCCLUDERS :
case VIEW_DISPLAY_MOTION_VECTORS : {
2019-10-03 20:39:08 +00:00
static const int display_options [ ] = {
VIEW_DISPLAY_NORMAL ,
VIEW_DISPLAY_WIREFRAME ,
VIEW_DISPLAY_OVERDRAW ,
VIEW_DISPLAY_SHADELESS ,
VIEW_DISPLAY_LIGHTING ,
2020-01-26 23:09:40 +00:00
VIEW_DISPLAY_NORMAL_BUFFER ,
2019-10-04 01:59:14 +00:00
VIEW_DISPLAY_WIREFRAME ,
2019-10-03 20:39:08 +00:00
VIEW_DISPLAY_DEBUG_SHADOW_ATLAS ,
VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS ,
2021-06-04 22:47:26 +00:00
VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO ,
VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING ,
VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION ,
2020-01-12 01:26:52 +00:00
VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE ,
2020-01-25 10:18:55 +00:00
VIEW_DISPLAY_DEBUG_SSAO ,
2021-08-03 07:07:32 +00:00
VIEW_DISPLAY_DEBUG_SSIL ,
2020-06-25 13:33:28 +00:00
VIEW_DISPLAY_DEBUG_GI_BUFFER ,
2020-12-17 18:56:59 +00:00
VIEW_DISPLAY_DEBUG_DISABLE_LOD ,
2020-04-08 01:51:52 +00:00
VIEW_DISPLAY_DEBUG_PSSM_SPLITS ,
2020-04-14 03:05:21 +00:00
VIEW_DISPLAY_DEBUG_DECAL_ATLAS ,
2020-06-25 13:33:28 +00:00
VIEW_DISPLAY_DEBUG_SDFGI ,
VIEW_DISPLAY_DEBUG_SDFGI_PROBES ,
2021-01-17 16:25:38 +00:00
VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS ,
VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS ,
VIEW_DISPLAY_DEBUG_CLUSTER_DECALS ,
VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES ,
2021-04-20 16:40:24 +00:00
VIEW_DISPLAY_DEBUG_OCCLUDERS ,
2022-04-04 14:10:22 +00:00
VIEW_DISPLAY_MOTION_VECTORS ,
2019-10-03 20:39:08 +00: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-26 23:09:40 +00:00
Viewport : : DEBUG_DRAW_NORMAL_BUFFER ,
2019-10-03 20:39:08 +00:00
Viewport : : DEBUG_DRAW_WIREFRAME ,
Viewport : : DEBUG_DRAW_SHADOW_ATLAS ,
Viewport : : DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS ,
2021-06-04 22:47:26 +00:00
Viewport : : DEBUG_DRAW_VOXEL_GI_ALBEDO ,
Viewport : : DEBUG_DRAW_VOXEL_GI_LIGHTING ,
Viewport : : DEBUG_DRAW_VOXEL_GI_EMISSION ,
2020-01-25 10:18:55 +00:00
Viewport : : DEBUG_DRAW_SCENE_LUMINANCE ,
2020-01-26 23:09:40 +00:00
Viewport : : DEBUG_DRAW_SSAO ,
2021-08-03 07:07:32 +00:00
Viewport : : DEBUG_DRAW_SSIL ,
2020-06-25 13:33:28 +00:00
Viewport : : DEBUG_DRAW_GI_BUFFER ,
2020-12-17 18:56:59 +00:00
Viewport : : DEBUG_DRAW_DISABLE_LOD ,
2020-04-08 01:51:52 +00:00
Viewport : : DEBUG_DRAW_PSSM_SPLITS ,
2020-04-14 03:05:21 +00:00
Viewport : : DEBUG_DRAW_DECAL_ATLAS ,
2020-06-25 13:33:28 +00:00
Viewport : : DEBUG_DRAW_SDFGI ,
Viewport : : DEBUG_DRAW_SDFGI_PROBES ,
2021-01-17 16:25:38 +00:00
Viewport : : DEBUG_DRAW_CLUSTER_OMNI_LIGHTS ,
Viewport : : DEBUG_DRAW_CLUSTER_SPOT_LIGHTS ,
Viewport : : DEBUG_DRAW_CLUSTER_DECALS ,
Viewport : : DEBUG_DRAW_CLUSTER_REFLECTION_PROBES ,
2021-04-20 16:40:24 +00:00
Viewport : : DEBUG_DRAW_OCCLUDERS ,
2022-04-04 14:10:22 +00:00
Viewport : : DEBUG_DRAW_MOTION_VECTORS ,
2019-10-03 20:39:08 +00: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 18:52:03 +00:00
2019-10-03 20:39:08 +00:00
if ( id = = p_option ) {
viewport - > set_debug_draw ( debug_draw_modes [ idx ] ) ;
}
idx + + ;
}
2017-06-11 18:52:03 +00:00
} break ;
2014-02-10 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _set_auto_orthogonal ( ) {
2019-10-23 09:46:26 +00: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 21:49:16 +00:00
void Node3DEditorViewport : : _preview_exited_scene ( ) {
preview_camera - > disconnect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 01:10:30 +00:00
preview_camera - > set_pressed ( false ) ;
_toggle_camera_preview ( false ) ;
2020-03-26 21:49:16 +00:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 01:10:30 +00:00
view_menu - > show ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _init_gizmo_instance ( int p_idx ) {
2017-12-19 05:25:00 +00:00
uint32_t layer = 1 < < ( GIZMO_BASE_LAYER + p_idx ) ;
2014-05-05 01:50:23 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 18:21:27 +00: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 09:00:51 +00:00
RS : : get_singleton ( ) - > instance_set_scenario ( move_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( move_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( move_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-03-27 18:21:27 +00:00
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 09:00:51 +00:00
RS : : get_singleton ( ) - > instance_set_scenario ( move_plane_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( move_plane_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( move_plane_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-03-27 18:21:27 +00:00
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 09:00:51 +00:00
RS : : get_singleton ( ) - > instance_set_scenario ( rotate_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( rotate_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( rotate_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-03-27 18:21:27 +00:00
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 09:00:51 +00:00
RS : : get_singleton ( ) - > instance_set_scenario ( scale_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( scale_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( scale_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-03-27 18:21:27 +00:00
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 09:00:51 +00:00
RS : : get_singleton ( ) - > instance_set_scenario ( scale_plane_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( scale_plane_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( scale_plane_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-07-18 19:03:08 +00:00
axis_gizmo_instance [ i ] = RS : : get_singleton ( ) - > instance_create ( ) ;
RS : : get_singleton ( ) - > instance_set_base ( axis_gizmo_instance [ i ] , spatial_editor - > get_axis_gizmo ( i ) - > get_rid ( ) ) ;
RS : : get_singleton ( ) - > instance_set_scenario ( axis_gizmo_instance [ i ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
RS : : get_singleton ( ) - > instance_set_visible ( axis_gizmo_instance [ i ] , true ) ;
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( axis_gizmo_instance [ i ] , RS : : SHADOW_CASTING_SETTING_OFF ) ;
RS : : get_singleton ( ) - > instance_set_layer_mask ( axis_gizmo_instance [ i ] , layer ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( axis_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
RS : : get_singleton ( ) - > instance_geometry_set_flag ( axis_gizmo_instance [ i ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2014-05-05 01:50:23 +00:00
}
2020-09-13 16:22:51 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( rotate_gizmo_instance [ 3 ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( rotate_gizmo_instance [ 3 ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2014-05-05 01:50:23 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _finish_gizmo_instances ( ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 18:21:27 +00: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 ] ) ;
2020-07-18 19:03:08 +00:00
RS : : get_singleton ( ) - > free ( axis_gizmo_instance [ i ] ) ;
2015-04-20 22:38:02 +00:00
}
2020-09-13 16:22:51 +00:00
// Rotation white outline
RS : : get_singleton ( ) - > free ( rotate_gizmo_instance [ 3 ] ) ;
2015-04-20 22:38:02 +00:00
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _toggle_camera_preview ( bool p_activate ) {
2014-02-10 01:10:30 +00:00
ERR_FAIL_COND ( p_activate & & ! preview ) ;
ERR_FAIL_COND ( ! p_activate & & ! previewing ) ;
2020-05-08 01:14:24 +00:00
rotation_control - > set_visible ( ! p_activate ) ;
2014-02-10 01:10:30 +00:00
if ( ! p_activate ) {
2020-03-26 21:49:16 +00:00
previewing - > disconnect ( " tree_exiting " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-04-01 23:20:12 +00:00
previewing = nullptr ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , camera - > get_camera ( ) ) ; //restore
2020-05-14 14:41:43 +00:00
if ( ! preview ) {
2014-02-10 01:10:30 +00:00
preview_camera - > hide ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-09-15 23:06:37 +00:00
surface - > update ( ) ;
2014-02-10 01:10:30 +00:00
} else {
2017-03-05 15:44:50 +00:00
previewing = preview ;
2020-03-26 21:49:16 +00:00
previewing - > connect ( " tree_exiting " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , preview - > get_camera ( ) ) ; //replace
2014-09-15 23:06:37 +00:00
surface - > update ( ) ;
2014-02-10 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _toggle_cinema_preview ( bool p_activate ) {
2018-07-26 22:36:05 +00:00
previewing_cinema = p_activate ;
2021-01-18 02:19:05 +00:00
rotation_control - > set_visible ( ! p_activate ) ;
2018-07-26 22:36:05 +00:00
if ( ! previewing_cinema ) {
2020-05-14 14:41:43 +00:00
if ( previewing ! = nullptr ) {
2020-03-26 21:49:16 +00:00
previewing - > disconnect ( " tree_exited " , callable_mp ( this , & Node3DEditorViewport : : _preview_exited_scene ) ) ;
2020-05-14 14:41:43 +00:00
}
2018-07-26 22:36:05 +00:00
2020-04-01 23:20:12 +00:00
previewing = nullptr ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , camera - > get_camera ( ) ) ; //restore
2018-07-26 22:36:05 +00:00
preview_camera - > set_pressed ( false ) ;
if ( ! preview ) {
preview_camera - > hide ( ) ;
} else {
preview_camera - > show ( ) ;
}
view_menu - > show ( ) ;
surface - > update ( ) ;
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _selection_result_pressed ( int p_result ) {
2020-05-14 14:41:43 +00:00
if ( selection_results . size ( ) < = p_result ) {
2015-11-04 21:39:07 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2015-11-04 21:39:07 +00:00
2017-08-07 10:17:31 +00:00
clicked = selection_results [ p_result ] . item - > get_instance_id ( ) ;
2015-11-04 21:39:07 +00:00
2020-02-12 17:24:06 +00:00
if ( clicked . is_valid ( ) ) {
2021-06-23 14:49:50 +00:00
_select_clicked ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SELECT ) ;
2015-11-04 21:39:07 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _selection_menu_hide ( ) {
2015-11-04 21:39:07 +00:00
selection_results . clear ( ) ;
selection_menu - > clear ( ) ;
2021-11-20 08:04:57 +00:00
selection_menu - > reset_size ( ) ;
2015-11-04 21:39:07 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : set_can_preview ( Camera3D * p_preview ) {
2017-03-05 15:44:50 +00:00
preview = p_preview ;
2014-02-10 01:10:30 +00:00
2020-05-14 14:41:43 +00:00
if ( ! preview_camera - > is_pressed ( ) & & ! previewing_cinema ) {
2017-12-19 05:25:00 +00:00
preview_camera - > set_visible ( p_preview ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : update_transform_gizmo_view ( ) {
2020-05-14 14:41:43 +00:00
if ( ! is_visible_in_tree ( ) ) {
2014-05-05 01:50:23 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-05-05 01:50:23 +00:00
2020-10-17 05:08:21 +00:00
Transform3D xform = spatial_editor - > get_gizmo_transform ( ) ;
2014-05-05 01:50:23 +00:00
2022-02-09 08:39:28 +00:00
Transform3D camera_xform = camera - > get_transform ( ) ;
2019-01-24 23:52:28 +00:00
2021-07-16 17:19:55 +00:00
if ( xform . origin . is_equal_approx ( camera_xform . origin ) ) {
2019-01-24 23:52:28 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 18:21:27 +00: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 ) ;
2020-07-18 19:03:08 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( axis_gizmo_instance [ i ] , false ) ;
2019-01-24 23:52:28 +00:00
}
2020-09-13 16:22:51 +00:00
// Rotation white outline
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ 3 ] , false ) ;
2019-01-24 23:52:28 +00:00
return ;
}
2022-05-03 12:50:35 +00:00
const Vector3 camz = - camera_xform . get_basis ( ) . get_column ( 2 ) . normalized ( ) ;
const Vector3 camy = - camera_xform . get_basis ( ) . get_column ( 1 ) . normalized ( ) ;
2021-04-08 14:26:14 +00:00
const Plane p = Plane ( camz , camera_xform . origin ) ;
2022-02-09 08:39:28 +00:00
const real_t gizmo_d = MAX ( Math : : abs ( p . distance_to ( xform . origin ) ) , CMP_EPSILON ) ;
2021-06-21 03:30:19 +00:00
const real_t d0 = camera - > unproject_position ( camera_xform . origin + camz * gizmo_d ) . y ;
const real_t d1 = camera - > unproject_position ( camera_xform . origin + camz * gizmo_d + camy ) . y ;
const real_t dd = MAX ( Math : : abs ( d0 - d1 ) , CMP_EPSILON ) ;
2014-05-05 01:50:23 +00:00
2021-06-21 03:30:19 +00:00
const real_t gizmo_size = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/manipulator_gizmo_size " ) ;
2019-08-03 01:01:32 +00:00
// 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 18:28:09 +00:00
MIN ( viewport_base_height , subviewport_container - > get_size ( ) . height ) / viewport_base_height /
subviewport_container - > get_stretch_shrink ( ) ;
2022-02-09 08:39:28 +00:00
Vector3 scale = Vector3 ( 1 , 1 , 1 ) * gizmo_scale ;
2014-05-05 01:50:23 +00:00
2020-12-30 09:56:49 +00:00
// if the determinant is zero, we should disable the gizmo from being rendered
// this prevents supplying bad values to the renderer and then having to filter it out again
if ( xform . basis . determinant ( ) = = 0 ) {
for ( int i = 0 ; i < 3 ; i + + ) {
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 ) ;
}
// Rotation white outline
RenderingServer : : get_singleton ( ) - > instance_set_visible ( rotate_gizmo_instance [ 3 ] , false ) ;
return ;
}
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2021-10-09 10:24:26 +00:00
Transform3D axis_angle = Transform3D ( ) ;
2022-05-03 12:50:35 +00:00
if ( xform . basis . get_column ( i ) . normalized ( ) . dot ( xform . basis . get_column ( ( i + 1 ) % 3 ) . normalized ( ) ) < 1.0 ) {
axis_angle = axis_angle . looking_at ( xform . basis . get_column ( i ) . normalized ( ) , xform . basis . get_column ( ( i + 1 ) % 3 ) . normalized ( ) ) ;
2021-10-09 10:24:26 +00:00
}
2022-02-09 08:39:28 +00:00
axis_angle . basis . scale ( scale ) ;
2021-10-09 10:24:26 +00:00
axis_angle . origin = xform . origin ;
RenderingServer : : get_singleton ( ) - > instance_set_transform ( move_gizmo_instance [ i ] , axis_angle ) ;
2020-03-27 18:21:27 +00:00
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 ) ) ;
2021-10-09 10:24:26 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( move_plane_gizmo_instance [ i ] , axis_angle ) ;
2020-03-27 18:21:27 +00:00
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 ) ) ;
2021-10-09 10:24:26 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( rotate_gizmo_instance [ i ] , axis_angle ) ;
2020-03-27 18:21:27 +00:00
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 ) ) ;
2021-10-09 10:24:26 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( scale_gizmo_instance [ i ] , axis_angle ) ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( scale_gizmo_instance [ i ] , spatial_editor - > is_gizmo_visible ( ) & & ( spatial_editor - > get_tool_mode ( ) = = Node3DEditor : : TOOL_MODE_SCALE ) ) ;
2021-10-09 10:24:26 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( scale_plane_gizmo_instance [ i ] , axis_angle ) ;
2020-03-27 18:21:27 +00:00
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 ) ) ;
2020-07-18 19:03:08 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_transform ( axis_gizmo_instance [ i ] , xform ) ;
2014-05-05 01:50:23 +00:00
}
2020-07-18 19:03:08 +00:00
bool show_axes = spatial_editor - > is_gizmo_visible ( ) & & _edit . mode ! = TRANSFORM_NONE ;
RenderingServer * rs = RenderingServer : : get_singleton ( ) ;
rs - > instance_set_visible ( axis_gizmo_instance [ 0 ] , show_axes & & ( _edit . plane = = TRANSFORM_X_AXIS | | _edit . plane = = TRANSFORM_XY | | _edit . plane = = TRANSFORM_XZ ) ) ;
rs - > instance_set_visible ( axis_gizmo_instance [ 1 ] , show_axes & & ( _edit . plane = = TRANSFORM_Y_AXIS | | _edit . plane = = TRANSFORM_XY | | _edit . plane = = TRANSFORM_YZ ) ) ;
rs - > instance_set_visible ( axis_gizmo_instance [ 2 ] , show_axes & & ( _edit . plane = = TRANSFORM_Z_AXIS | | _edit . plane = = TRANSFORM_XZ | | _edit . plane = = TRANSFORM_YZ ) ) ;
2020-09-13 16:22:51 +00:00
// Rotation white outline
2021-10-09 10:24:26 +00:00
xform . orthonormalize ( ) ;
2022-02-09 08:39:28 +00:00
xform . basis . scale ( scale ) ;
2020-09-13 16:22:51 +00:00
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 01:50:23 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : set_state ( const Dictionary & p_state ) {
2020-05-14 14:41:43 +00:00
if ( p_state . has ( " position " ) ) {
2017-12-19 05:25:00 +00:00
cursor . pos = p_state [ " position " ] ;
2020-05-14 14:41:43 +00:00
}
if ( p_state . has ( " x_rotation " ) ) {
2017-12-19 05:25:00 +00:00
cursor . x_rot = p_state [ " x_rotation " ] ;
2020-05-14 14:41:43 +00:00
}
if ( p_state . has ( " y_rotation " ) ) {
2017-12-19 05:25:00 +00:00
cursor . y_rot = p_state [ " y_rotation " ] ;
2020-05-14 14:41:43 +00:00
}
if ( p_state . has ( " distance " ) ) {
2017-12-19 05:25:00 +00:00
cursor . distance = p_state [ " distance " ] ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
if ( p_state . has ( " use_orthogonal " ) ) {
bool orth = p_state [ " use_orthogonal " ] ;
2020-05-14 14:41:43 +00:00
if ( orth ) {
2017-12-19 05:25:00 +00:00
_menu_option ( VIEW_ORTHOGONAL ) ;
2020-05-14 14:41:43 +00:00
} else {
2017-12-19 05:25:00 +00:00
_menu_option ( VIEW_PERSPECTIVE ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
}
2021-08-14 07:24:02 +00:00
if ( p_state . has ( " view_type " ) ) {
view_type = ViewType ( p_state [ " view_type " ] . operator int ( ) ) ;
2019-10-23 09:46:26 +00:00
_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 05:25:00 +00: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 14:41:43 +00:00
if ( ! view_menu - > get_popup ( ) - > is_item_checked ( idx ) ) {
2017-12-19 05:25:00 +00:00
_menu_option ( display ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
}
2018-06-25 01:24:31 +00: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 05:25:00 +00:00
if ( p_state . has ( " use_environment " ) ) {
bool env = p_state [ " use_environment " ] ;
2020-05-14 14:41:43 +00:00
if ( env ! = camera - > get_environment ( ) . is_valid ( ) ) {
2017-12-19 05:25:00 +00:00
_menu_option ( VIEW_ENVIRONMENT ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
}
2014-10-03 03:10:51 +00:00
if ( p_state . has ( " listener " ) ) {
bool listener = p_state [ " listener " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) ;
2021-08-02 17:31:51 +00:00
viewport - > set_as_audio_listener_3d ( listener ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , listener ) ;
2014-10-03 03:10:51 +00:00
}
2017-07-15 04:23:10 +00: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 21:49:16 +00:00
camera - > set_doppler_tracking ( doppler ? Camera3D : : DOPPLER_TRACKING_IDLE_STEP : Camera3D : : DOPPLER_TRACKING_DISABLED ) ;
2017-07-15 04:23:10 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( idx , doppler ) ;
}
2017-11-20 00:45:56 +00: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 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = gizmos ) {
2017-11-20 00:45:56 +00:00
_menu_option ( VIEW_GIZMOS ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-20 00:45:56 +00: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 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = information ) {
2017-11-20 00:45:56 +00:00
_menu_option ( VIEW_INFORMATION ) ;
2020-05-14 14:41:43 +00:00
}
2017-11-20 00:45:56 +00:00
}
2020-04-10 17:18:42 +00:00
if ( p_state . has ( " frame_time " ) ) {
bool fps = p_state [ " frame_time " ] ;
2017-12-19 05:25:00 +00:00
2020-04-10 17:18:42 +00:00
int idx = view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ;
2020-05-14 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( idx ) ! = fps ) {
2020-04-10 17:18:42 +00:00
_menu_option ( VIEW_FRAME_TIME ) ;
2020-05-14 14:41:43 +00:00
}
2017-12-19 05:25:00 +00:00
}
2017-10-31 17:23:25 +00: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-26 22:36:05 +00: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 01:10:30 +00:00
2020-03-26 21:49:16 +00: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 12:04:29 +00:00
}
2015-08-30 01:59:25 +00:00
if ( p_state . has ( " previewing " ) ) {
Node * pv = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_node ( p_state [ " previewing " ] ) ;
2020-03-26 21:49:16 +00: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 18:21:27 +00:00
RS : : get_singleton ( ) - > viewport_attach_camera ( viewport - > get_viewport_rid ( ) , previewing - > get_camera ( ) ) ; //replace
2015-08-30 01:59:25 +00:00
surface - > update ( ) ;
preview_camera - > set_pressed ( true ) ;
preview_camera - > show ( ) ;
}
}
2020-03-26 21:49:16 +00:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Dictionary Node3DEditorViewport : : get_state ( ) const {
2014-02-10 01:10:30 +00:00
Dictionary d ;
2017-09-10 13:37:49 +00:00
d [ " position " ] = cursor . pos ;
d [ " x_rotation " ] = cursor . x_rot ;
d [ " y_rotation " ] = cursor . y_rot ;
2017-03-05 15:44:50 +00:00
d [ " distance " ] = cursor . distance ;
d [ " use_environment " ] = camera - > get_environment ( ) . is_valid ( ) ;
2020-03-26 21:49:16 +00:00
d [ " use_orthogonal " ] = camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ;
2021-08-14 07:24:02 +00:00
d [ " view_type " ] = view_type ;
2019-10-23 09:46:26 +00:00
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 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_NORMAL ) ) ) {
2017-12-19 05:25:00 +00:00
d [ " display_mode " ] = VIEW_DISPLAY_NORMAL ;
2020-05-14 14:41:43 +00:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_WIREFRAME ) ) ) {
2017-12-19 05:25:00 +00:00
d [ " display_mode " ] = VIEW_DISPLAY_WIREFRAME ;
2020-05-14 14:41:43 +00:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_OVERDRAW ) ) ) {
2017-12-19 05:25:00 +00:00
d [ " display_mode " ] = VIEW_DISPLAY_OVERDRAW ;
2020-05-14 14:41:43 +00:00
} else if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_SHADELESS ) ) ) {
2017-12-19 05:25:00 +00:00
d [ " display_mode " ] = VIEW_DISPLAY_SHADELESS ;
2020-05-14 14:41:43 +00:00
}
2021-08-02 17:31:51 +00:00
d [ " listener " ] = viewport - > is_audio_listener_3d ( ) ;
2017-11-20 00:45:56 +00: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 17:18:42 +00:00
d [ " frame_time " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_FRAME_TIME ) ) ;
2020-04-01 18:28:09 +00:00
d [ " half_res " ] = subviewport_container - > get_stretch_shrink ( ) > 1 ;
2018-07-26 22:36:05 +00:00
d [ " cinematic_preview " ] = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_CINEMATIC_PREVIEW ) ) ;
2020-05-14 14:41:43 +00:00
if ( previewing ) {
2017-03-05 15:44:50 +00:00
d [ " previewing " ] = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( previewing ) ;
2020-05-14 14:41:43 +00:00
}
if ( lock_rotation ) {
2018-06-25 01:24:31 +00:00
d [ " lock_rotation " ] = lock_rotation ;
2020-05-14 14:41:43 +00:00
}
2015-08-30 01:59:25 +00:00
2014-02-10 01:10:30 +00:00
return d ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " update_transform_gizmo_view " ) , & Node3DEditorViewport : : update_transform_gizmo_view ) ; // Used by call_deferred.
2021-05-15 21:48:59 +00:00
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 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ADD_SIGNAL ( MethodInfo ( " toggle_maximize_view " , PropertyInfo ( Variant : : OBJECT , " viewport " ) ) ) ;
2019-04-06 20:55:01 +00:00
ADD_SIGNAL ( MethodInfo ( " clicked " , PropertyInfo ( Variant : : OBJECT , " viewport " ) ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : reset ( ) {
2017-03-05 15:44:50 +00:00
orthogonal = false ;
2019-10-23 09:46:26 +00:00
auto_orthogonal = false ;
2018-06-25 01:24:31 +00:00
lock_rotation = false ;
2017-03-05 15:44:50 +00:00
message_time = 0 ;
message = " " ;
last_message = " " ;
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_USER ;
2014-09-19 21:39:50 +00:00
2020-06-07 17:21:29 +00:00
cursor = Cursor ( ) ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2014-09-19 21:39:50 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : focus_selection ( ) {
2016-07-28 19:37:52 +00:00
Vector3 center ;
2017-03-05 15:44:50 +00:00
int count = 0 ;
2016-07-28 19:37:52 +00:00
2022-04-07 10:23:40 +00:00
const List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2016-07-28 19:37:52 +00:00
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2016-07-28 19:37:52 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-07-28 19:37:52 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 14:41:43 +00:00
if ( ! se ) {
2016-07-28 19:37:52 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2016-07-28 19:37:52 +00:00
2021-06-23 14:49:50 +00:00
if ( se - > gizmo . is_valid ( ) ) {
2021-08-09 20:13:42 +00:00
for ( const KeyValue < int , Transform3D > & GE : se - > subgizmos ) {
center + = se - > gizmo - > get_subgizmo_transform ( GE . key ) . origin ;
2021-06-23 14:49:50 +00:00
count + + ;
}
}
2017-10-03 16:49:32 +00:00
center + = sp - > get_global_gizmo_transform ( ) . origin ;
2016-07-28 19:37:52 +00:00
count + + ;
}
2017-03-05 15:44:50 +00:00
if ( count ! = 0 ) {
2021-06-21 03:30:19 +00:00
center / = count ;
2016-07-28 19:37:52 +00:00
}
2017-03-05 15:44:50 +00:00
cursor . pos = center ;
2016-07-28 19:37:52 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : assign_pending_data_pointers ( Node3D * p_preview_node , AABB * p_preview_bounds , AcceptDialog * p_accept ) {
2017-09-02 19:47:16 +00:00
preview_node = p_preview_node ;
preview_bounds = p_preview_bounds ;
accept = p_accept ;
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditorViewport : : _get_instance_position ( const Point2 & p_pos ) const {
2021-10-12 14:38:33 +00:00
const float MAX_DISTANCE = 50.0 ;
2017-09-02 19:47:16 +00:00
Vector3 world_ray = _get_ray ( p_pos ) ;
Vector3 world_pos = _get_ray_pos ( p_pos ) ;
Vector3 point = world_pos + world_ray * MAX_DISTANCE ;
2021-07-21 19:32:55 +00:00
PhysicsDirectSpaceState3D * ss = get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_direct_space_state ( ) ;
2017-09-02 19:47:16 +00:00
2021-11-02 01:00:58 +00:00
PhysicsDirectSpaceState3D : : RayParameters ray_params ;
ray_params . from = world_pos ;
ray_params . to = world_pos + world_ray * MAX_DISTANCE ;
PhysicsDirectSpaceState3D : : RayResult result ;
if ( ss - > intersect_ray ( ray_params , result ) ) {
2021-07-21 19:32:55 +00:00
point = result . position ;
2017-09-02 19:47:16 +00:00
}
2021-06-23 14:49:50 +00:00
2021-07-21 19:32:55 +00:00
return point ;
2017-09-02 19:47:16 +00:00
}
2020-10-02 21:03:52 +00:00
AABB Node3DEditorViewport : : _calculate_spatial_bounds ( const Node3D * p_parent , bool p_exclude_top_level_transform ) {
2019-10-04 13:28:30 +00:00
AABB bounds ;
2021-04-11 07:15:52 +00:00
const VisualInstance3D * visual_instance = Object : : cast_to < VisualInstance3D > ( p_parent ) ;
if ( visual_instance ) {
bounds = visual_instance - > get_aabb ( ) ;
2019-10-04 13:28:30 +00:00
}
2017-09-02 19:47:16 +00:00
for ( int i = 0 ; i < p_parent - > get_child_count ( ) ; i + + ) {
2020-03-26 21:49:16 +00:00
Node3D * child = Object : : cast_to < Node3D > ( p_parent - > get_child ( i ) ) ;
2017-09-02 19:47:16 +00:00
if ( child ) {
2019-10-04 13:28:30 +00:00
AABB child_bounds = _calculate_spatial_bounds ( child , false ) ;
2022-02-06 13:12:19 +00:00
if ( bounds . size = = Vector3 ( ) & & Object : : cast_to < Node3D > ( p_parent ) ) {
2019-10-04 13:28:30 +00:00
bounds = child_bounds ;
} else {
bounds . merge_with ( child_bounds ) ;
2017-09-02 19:47:16 +00:00
}
}
}
2019-10-04 13:28:30 +00:00
2022-02-06 13:12:19 +00:00
if ( bounds . size = = Vector3 ( ) & & ! Object : : cast_to < Node3D > ( p_parent ) ) {
2019-10-04 13:28:30 +00:00
bounds = AABB ( Vector3 ( - 0.2 , - 0.2 , - 0.2 ) , Vector3 ( 0.4 , 0.4 , 0.4 ) ) ;
}
2020-10-02 21:03:52 +00:00
if ( ! p_exclude_top_level_transform ) {
2019-10-04 13:28:30 +00:00
bounds = p_parent - > get_transform ( ) . xform ( bounds ) ;
}
2017-09-02 19:47:16 +00:00
return bounds ;
}
2021-12-30 14:07:56 +00:00
Node * Node3DEditorViewport : : _sanitize_preview_node ( Node * p_node ) const {
Node3D * node_3d = Object : : cast_to < Node3D > ( p_node ) ;
if ( node_3d = = nullptr ) {
Node3D * replacement_node = memnew ( Node3D ) ;
replacement_node - > set_name ( p_node - > get_name ( ) ) ;
p_node - > replace_by ( replacement_node ) ;
memdelete ( p_node ) ;
p_node = replacement_node ;
} else {
VisualInstance3D * visual_instance = Object : : cast_to < VisualInstance3D > ( node_3d ) ;
if ( visual_instance = = nullptr ) {
Node3D * replacement_node = memnew ( Node3D ) ;
replacement_node - > set_name ( node_3d - > get_name ( ) ) ;
replacement_node - > set_visible ( node_3d - > is_visible ( ) ) ;
replacement_node - > set_transform ( node_3d - > get_transform ( ) ) ;
replacement_node - > set_rotation_edit_mode ( node_3d - > get_rotation_edit_mode ( ) ) ;
replacement_node - > set_rotation_order ( node_3d - > get_rotation_order ( ) ) ;
replacement_node - > set_as_top_level ( node_3d - > is_set_as_top_level ( ) ) ;
p_node - > replace_by ( replacement_node ) ;
memdelete ( p_node ) ;
p_node = replacement_node ;
}
}
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
_sanitize_preview_node ( p_node - > get_child ( i ) ) ;
}
return p_node ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _create_preview ( const Vector < String > & files ) const {
2017-09-02 19:47:16 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
String path = files [ i ] ;
2022-05-02 23:43:50 +00:00
Ref < Resource > res = ResourceLoader : : load ( path ) ;
2019-09-29 12:17:42 +00:00
ERR_CONTINUE ( res . is_null ( ) ) ;
2017-09-02 19:47:16 +00:00
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2017-09-16 13:57:17 +00:00
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2020-04-01 23:20:12 +00:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
if ( mesh ! = nullptr ) {
2020-03-26 21:49:16 +00:00
MeshInstance3D * mesh_instance = memnew ( MeshInstance3D ) ;
2017-09-16 13:57:17 +00:00
mesh_instance - > set_mesh ( mesh ) ;
preview_node - > add_child ( mesh_instance ) ;
} else {
if ( scene . is_valid ( ) ) {
2021-06-17 22:03:09 +00:00
Node * instance = scene - > instantiate ( ) ;
2017-09-16 13:57:17 +00:00
if ( instance ) {
2021-12-30 14:07:56 +00:00
instance = _sanitize_preview_node ( instance ) ;
2017-09-16 13:57:17 +00:00
preview_node - > add_child ( instance ) ;
}
2017-09-02 19:47:16 +00:00
}
}
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_scene_root ( ) - > add_child ( preview_node ) ;
2017-09-02 19:47:16 +00:00
}
}
2019-10-04 13:28:30 +00:00
* preview_bounds = _calculate_spatial_bounds ( preview_node ) ;
2017-09-02 19:47:16 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _remove_preview ( ) {
2017-09-02 19:47:16 +00: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 ) ;
}
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_scene_root ( ) - > remove_child ( preview_node ) ;
2017-09-02 19:47:16 +00:00
}
}
2020-03-26 21:49:16 +00:00
bool Node3DEditorViewport : : _cyclical_dependency_exists ( const String & p_target_scene_path , Node * p_desired_node ) {
2021-09-30 14:30:55 +00:00
if ( p_desired_node - > get_scene_file_path ( ) = = p_target_scene_path ) {
2017-09-02 19:47:16 +00:00
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 21:49:16 +00:00
bool Node3DEditorViewport : : _create_instance ( Node * parent , String & path , const Point2 & p_point ) {
2022-05-02 23:43:50 +00:00
Ref < Resource > res = ResourceLoader : : load ( path ) ;
2019-09-29 12:17:42 +00:00
ERR_FAIL_COND_V ( res . is_null ( ) , false ) ;
2017-09-16 13:57:17 +00:00
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2021-06-17 22:03:09 +00:00
Node * instantiated_scene = nullptr ;
2017-09-16 13:57:17 +00:00
2020-04-01 23:20:12 +00:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
if ( mesh ! = nullptr ) {
2020-03-26 21:49:16 +00:00
MeshInstance3D * mesh_instance = memnew ( MeshInstance3D ) ;
2017-09-16 13:57:17 +00:00
mesh_instance - > set_mesh ( mesh ) ;
2021-12-01 18:36:14 +00:00
// Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others.
String name = path . get_file ( ) . get_basename ( ) ;
switch ( ProjectSettings : : get_singleton ( ) - > get ( " editor/node_naming/name_casing " ) . operator int ( ) ) {
case NAME_CASING_PASCAL_CASE :
name = name . capitalize ( ) . replace ( " " , " " ) ;
break ;
case NAME_CASING_CAMEL_CASE :
name = name . capitalize ( ) . replace ( " " , " " ) ;
name [ 0 ] = name . to_lower ( ) [ 0 ] ;
break ;
case NAME_CASING_SNAKE_CASE :
name = name . capitalize ( ) . replace ( " " , " _ " ) . to_lower ( ) ;
break ;
}
mesh_instance - > set_name ( name ) ;
2021-06-17 22:03:09 +00:00
instantiated_scene = mesh_instance ;
2017-09-16 13:57:17 +00:00
} else {
if ( ! scene . is_valid ( ) ) { // invalid scene
return false ;
} else {
2021-06-17 22:03:09 +00:00
instantiated_scene = scene - > instantiate ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
2017-09-16 13:57:17 +00:00
}
}
2017-09-02 19:47:16 +00:00
}
2021-06-17 22:03:09 +00:00
if ( instantiated_scene = = nullptr ) {
2017-09-02 19:47:16 +00:00
return false ;
}
2022-01-27 09:36:51 +00:00
if ( ! EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_scene_file_path ( ) . is_empty ( ) ) { // cyclical instancing
if ( _cyclical_dependency_exists ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_scene_file_path ( ) , instantiated_scene ) ) {
2021-06-17 22:03:09 +00:00
memdelete ( instantiated_scene ) ;
2017-09-02 19:47:16 +00:00
return false ;
}
}
2020-04-01 23:20:12 +00:00
if ( scene ! = nullptr ) {
2021-09-30 14:30:55 +00:00
instantiated_scene - > set_scene_file_path ( ProjectSettings : : get_singleton ( ) - > localize_path ( path ) ) ;
2017-11-10 21:31:53 +00:00
}
2017-09-02 19:47:16 +00:00
2022-01-05 12:11:18 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( parent , " add_child " , instantiated_scene , true ) ;
2022-01-27 09:36:51 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( instantiated_scene , " set_owner " , EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) ;
2021-06-17 22:03:09 +00:00
editor_data - > get_undo_redo ( ) . add_do_reference ( instantiated_scene ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( parent , " remove_child " , instantiated_scene ) ;
2017-09-02 19:47:16 +00:00
2021-06-17 22:03:09 +00:00
String new_name = parent - > validate_child_name ( instantiated_scene ) ;
2020-02-07 01:52:05 +00:00
EditorDebuggerNode * ed = EditorDebuggerNode : : get_singleton ( ) ;
2022-01-27 09:36:51 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( ed , " live_debug_instance_node " , EditorNode : : get_singleton ( ) - > 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 ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_path_to ( parent ) ) + " / " + new_name ) ) ;
2017-09-02 19:47:16 +00:00
2021-06-17 22:03:09 +00:00
Node3D * node3d = Object : : cast_to < Node3D > ( instantiated_scene ) ;
2020-06-07 20:09:41 +00:00
if ( node3d ) {
2020-10-17 05:08:21 +00:00
Transform3D global_transform ;
2020-06-07 20:09:41 +00:00
Node3D * parent_node3d = Object : : cast_to < Node3D > ( parent ) ;
if ( parent_node3d ) {
global_transform = parent_node3d - > get_global_gizmo_transform ( ) ;
}
2017-09-02 19:47:16 +00:00
2020-06-07 20:09:41 +00:00
global_transform . origin = spatial_editor - > snap_point ( _get_instance_position ( p_point ) ) ;
global_transform . basis * = node3d - > get_transform ( ) . basis ;
2017-09-02 19:47:16 +00:00
2021-06-17 22:03:09 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( instantiated_scene , " set_global_transform " , global_transform ) ;
2020-06-07 20:09:41 +00:00
}
2017-09-02 19:47:16 +00:00
return true ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : _perform_drop_data ( ) {
2017-09-02 19:47:16 +00: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 ] ;
2022-05-02 23:43:50 +00:00
Ref < Resource > res = ResourceLoader : : load ( path ) ;
2017-09-02 19:47:16 +00:00
if ( res . is_null ( ) ) {
continue ;
}
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2017-09-16 13:57:17 +00:00
Ref < Mesh > mesh = Ref < Mesh > ( Object : : cast_to < Mesh > ( * res ) ) ;
2020-04-01 23:20:12 +00:00
if ( mesh ! = nullptr | | scene ! = nullptr ) {
2017-09-02 19:47:16 +00: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 10:43:20 +00:00
accept - > set_text ( vformat ( TTR ( " Error instancing scene from %s " ) , files_str . get_data ( ) ) ) ;
2020-03-06 17:00:16 +00:00
accept - > popup_centered ( ) ;
2017-09-02 19:47:16 +00:00
}
}
2020-03-26 21:49:16 +00:00
bool Node3DEditorViewport : : can_drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) const {
2021-06-17 22:03:09 +00:00
bool can_instantiate = false ;
2017-09-02 19:47:16 +00:00
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 13:57:17 +00:00
List < String > mesh_extensions ;
ResourceLoader : : get_recognized_extensions_for_type ( " Mesh " , & mesh_extensions ) ;
2017-09-02 19:47:16 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
2022-02-06 13:12:19 +00:00
// Check if dragged files with mesh or scene extension can be created at least once.
2017-09-16 13:57:17 +00:00
if ( mesh_extensions . find ( files [ i ] . get_extension ( ) ) | | scene_extensions . find ( files [ i ] . get_extension ( ) ) ) {
2022-05-02 23:43:50 +00:00
Ref < Resource > res = ResourceLoader : : load ( files [ i ] ) ;
2017-09-02 19:47:16 +00:00
if ( res . is_null ( ) ) {
continue ;
}
2022-02-06 13:12:19 +00:00
Ref < PackedScene > scn = res ;
if ( scn . is_valid ( ) ) {
Node * instantiated_scene = scn - > instantiate ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
2021-06-17 22:03:09 +00:00
if ( ! instantiated_scene ) {
2017-09-02 19:47:16 +00:00
continue ;
}
2021-06-17 22:03:09 +00:00
memdelete ( instantiated_scene ) ;
2017-09-02 19:47:16 +00:00
}
2021-06-17 22:03:09 +00:00
can_instantiate = true ;
2017-09-02 19:47:16 +00:00
break ;
}
}
2021-06-17 22:03:09 +00:00
if ( can_instantiate ) {
2017-09-02 19:47:16 +00:00
_create_preview ( files ) ;
}
}
} else {
2021-06-17 22:03:09 +00:00
can_instantiate = true ;
2017-09-02 19:47:16 +00:00
}
2021-06-17 22:03:09 +00:00
if ( can_instantiate ) {
2020-10-17 05:08:21 +00:00
Transform3D global_transform = Transform3D ( Basis ( ) , _get_instance_position ( p_point ) ) ;
2017-09-02 19:47:16 +00:00
preview_node - > set_global_transform ( global_transform ) ;
}
2021-06-17 22:03:09 +00:00
return can_instantiate ;
2017-09-02 19:47:16 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewport : : drop_data_fw ( const Point2 & p_point , const Variant & p_data , Control * p_from ) {
2020-05-14 14:41:43 +00:00
if ( ! can_drop_data_fw ( p_point , p_data , p_from ) ) {
2017-09-02 19:47:16 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2017-09-02 19:47:16 +00:00
2021-08-13 21:31:57 +00:00
bool is_shift = Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ;
bool is_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2017-09-02 19:47:16 +00:00
selected_files . clear ( ) ;
Dictionary d = p_data ;
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " files " ) {
selected_files = d [ " files " ] ;
}
2022-01-27 09:36:51 +00:00
List < Node * > selected_nodes = EditorNode : : get_singleton ( ) - > get_editor_selection ( ) - > get_selected_node_list ( ) ;
Node * root_node = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
2021-07-29 11:15:46 +00:00
if ( selected_nodes . size ( ) = = 1 ) {
Node * selected_node = selected_nodes [ 0 ] ;
target_node = root_node ;
if ( is_ctrl ) {
target_node = selected_node ;
} else if ( is_shift & & selected_node ! = root_node ) {
target_node = selected_node - > get_parent ( ) ;
}
} else if ( selected_nodes . size ( ) = = 0 ) {
2017-09-02 19:47:16 +00:00
if ( root_node ) {
2021-07-29 11:15:46 +00:00
target_node = root_node ;
2017-09-02 19:47:16 +00:00
} else {
2021-12-01 18:36:14 +00:00
// Create a root node so we can add child nodes to it.
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > add_root_node ( memnew ( Node3D ) ) ;
2021-12-01 18:36:14 +00:00
target_node = get_tree ( ) - > get_edited_scene_root ( ) ;
2017-09-02 19:47:16 +00:00
}
2021-07-29 11:15:46 +00:00
} else {
accept - > set_text ( TTR ( " Cannot drag and drop into multiple selected nodes. " ) ) ;
2020-03-06 17:00:16 +00:00
accept - > popup_centered ( ) ;
2017-09-02 19:47:16 +00:00
_remove_preview ( ) ;
return ;
}
drop_pos = p_point ;
_perform_drop_data ( ) ;
}
2020-07-18 19:03:08 +00:00
void Node3DEditorViewport : : begin_transform ( TransformMode p_mode , bool instant ) {
if ( get_selected_count ( ) > 0 ) {
_edit . mode = p_mode ;
2022-02-09 08:39:28 +00:00
_compute_edit ( _edit . mouse_pos ) ;
2020-07-18 19:03:08 +00:00
_edit . instant = instant ;
_edit . snap = spatial_editor - > is_snap_enabled ( ) ;
}
}
void Node3DEditorViewport : : commit_transform ( ) {
ERR_FAIL_COND ( _edit . mode = = TRANSFORM_NONE ) ;
static const char * _transform_name [ 4 ] = {
TTRC ( " None " ) ,
TTRC ( " Rotate " ) ,
// TRANSLATORS: This refers to the movement that changes the position of an object.
TTRC ( " Translate " ) ,
TTRC ( " Scale " ) ,
} ;
undo_redo - > create_action ( _transform_name [ _edit . mode ] ) ;
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
undo_redo - > add_do_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
undo_redo - > add_undo_method ( sp , " set_global_transform " , se - > original ) ;
}
undo_redo - > commit_action ( ) ;
2022-02-10 13:23:10 +00:00
finish_transform ( ) ;
2020-07-18 19:03:08 +00:00
set_message ( " " ) ;
}
void Node3DEditorViewport : : update_transform ( Point2 p_mousepos , bool p_shift ) {
Vector3 ray_pos = _get_ray_pos ( p_mousepos ) ;
Vector3 ray = _get_ray ( p_mousepos ) ;
double snap = EDITOR_GET ( " interface/inspector/default_float_step " ) ;
int snap_step_decimals = Math : : range_step_decimals ( snap ) ;
switch ( _edit . mode ) {
case TRANSFORM_SCALE : {
Vector3 motion_mask ;
Plane plane ;
bool plane_mv = false ;
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
motion_mask = Vector3 ( 0 , 0 , 0 ) ;
plane = Plane ( _get_camera_normal ( ) , _edit . center ) ;
break ;
case TRANSFORM_X_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_Y_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_Z_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_YZ :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) ;
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
case TRANSFORM_XZ :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) ;
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
case TRANSFORM_XY :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) + spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) ;
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
}
Vector3 intersection ;
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
break ;
}
Vector3 click ;
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
break ;
}
Vector3 motion = intersection - click ;
if ( _edit . plane ! = TRANSFORM_VIEW ) {
if ( ! plane_mv ) {
motion = motion_mask . dot ( motion ) * motion_mask ;
} else {
// Alternative planar scaling mode
if ( p_shift ) {
motion = motion_mask . dot ( motion ) * motion_mask ;
}
}
} else {
const real_t center_click_dist = click . distance_to ( _edit . center ) ;
const real_t center_inters_dist = intersection . distance_to ( _edit . center ) ;
if ( center_click_dist = = 0 ) {
break ;
}
const real_t scale = center_inters_dist - center_click_dist ;
motion = Vector3 ( scale , scale , scale ) ;
}
motion / = click . distance_to ( _edit . center ) ;
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ;
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
snap = spatial_editor - > get_scale_snap ( ) / 100 ;
}
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?).
2022-06-08 09:42:51 +00:00
// TRANSLATORS: Refers to changing the scale of a node in the 3D editor.
set_message ( TTR ( " Scaling: " ) + " ( " + String : : num ( motion_snapped . x , snap_step_decimals ) + " , " +
2020-07-18 19:03:08 +00:00
String : : num ( motion_snapped . y , snap_step_decimals ) + " , " + String : : num ( motion_snapped . z , snap_step_decimals ) + " ) " ) ;
motion = _edit . original . basis . inverse ( ) . xform ( motion ) ;
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
if ( se - > gizmo . is_valid ( ) ) {
for ( KeyValue < int , Transform3D > & GE : se - > subgizmos ) {
Transform3D xform = GE . value ;
Transform3D new_xform = _compute_transform ( TRANSFORM_SCALE , se - > original * xform , xform , motion , snap , local_coords , true ) ; // Force orthogonal with subgizmo.
if ( ! local_coords ) {
new_xform = se - > original . affine_inverse ( ) * new_xform ;
}
se - > gizmo - > set_subgizmo_transform ( GE . key , new_xform ) ;
}
} else {
Transform3D new_xform = _compute_transform ( TRANSFORM_SCALE , se - > original , se - > original_local , motion , snap , local_coords , sp - > get_rotation_edit_mode ( ) ! = Node3D : : ROTATION_EDIT_MODE_BASIS ) ;
_transform_gizmo_apply ( se - > sp , new_xform , local_coords ) ;
}
}
spatial_editor - > update_transform_gizmo ( ) ;
surface - > update ( ) ;
} break ;
case TRANSFORM_TRANSLATE : {
Vector3 motion_mask ;
Plane plane ;
bool plane_mv = false ;
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
plane = Plane ( _get_camera_normal ( ) , _edit . center ) ;
break ;
case TRANSFORM_X_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_Y_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_Z_AXIS :
2022-05-03 12:50:35 +00:00
motion_mask = spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) ;
2020-07-18 19:03:08 +00:00
plane = Plane ( motion_mask . cross ( motion_mask . cross ( _get_camera_normal ( ) ) ) . normalized ( ) , _edit . center ) ;
break ;
case TRANSFORM_YZ :
2022-05-03 12:50:35 +00:00
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 0 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
case TRANSFORM_XZ :
2022-05-03 12:50:35 +00:00
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 1 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
case TRANSFORM_XY :
2022-05-03 12:50:35 +00:00
plane = Plane ( spatial_editor - > get_gizmo_transform ( ) . basis . get_column ( 2 ) . normalized ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
plane_mv = true ;
break ;
}
Vector3 intersection ;
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
break ;
}
Vector3 click ;
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
break ;
}
Vector3 motion = intersection - click ;
if ( _edit . plane ! = TRANSFORM_VIEW ) {
if ( ! plane_mv ) {
motion = motion_mask . dot ( motion ) * motion_mask ;
}
}
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ;
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
snap = spatial_editor - > get_translate_snap ( ) ;
}
Vector3 motion_snapped = motion ;
motion_snapped . snap ( Vector3 ( snap , snap , snap ) ) ;
2022-06-08 09:42:51 +00:00
// TRANSLATORS: Refers to changing the position of a node in the 3D editor.
set_message ( TTR ( " Translating: " ) + " ( " + String : : num ( motion_snapped . x , snap_step_decimals ) + " , " +
2020-07-18 19:03:08 +00:00
String : : num ( motion_snapped . y , snap_step_decimals ) + " , " + String : : num ( motion_snapped . z , snap_step_decimals ) + " ) " ) ;
motion = spatial_editor - > get_gizmo_transform ( ) . basis . inverse ( ) . xform ( motion ) ;
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
if ( se - > gizmo . is_valid ( ) ) {
for ( KeyValue < int , Transform3D > & GE : se - > subgizmos ) {
Transform3D xform = GE . value ;
Transform3D new_xform = _compute_transform ( TRANSFORM_TRANSLATE , se - > original * xform , xform , motion , snap , local_coords , true ) ; // Force orthogonal with subgizmo.
new_xform = se - > original . affine_inverse ( ) * new_xform ;
se - > gizmo - > set_subgizmo_transform ( GE . key , new_xform ) ;
}
} else {
Transform3D new_xform = _compute_transform ( TRANSFORM_TRANSLATE , se - > original , se - > original_local , motion , snap , local_coords , sp - > get_rotation_edit_mode ( ) ! = Node3D : : ROTATION_EDIT_MODE_BASIS ) ;
_transform_gizmo_apply ( se - > sp , new_xform , false ) ;
}
}
spatial_editor - > update_transform_gizmo ( ) ;
surface - > update ( ) ;
} break ;
case TRANSFORM_ROTATE : {
2022-01-17 14:48:21 +00:00
Plane plane = Plane ( _get_camera_normal ( ) , _edit . center ) ;
2020-07-18 19:03:08 +00:00
2022-01-17 14:48:21 +00:00
Vector3 local_axis ;
Vector3 global_axis ;
2020-07-18 19:03:08 +00:00
switch ( _edit . plane ) {
case TRANSFORM_VIEW :
2022-01-17 14:48:21 +00:00
// local_axis unused
global_axis = _get_camera_normal ( ) ;
2020-07-18 19:03:08 +00:00
break ;
case TRANSFORM_X_AXIS :
2022-01-17 14:48:21 +00:00
local_axis = Vector3 ( 1 , 0 , 0 ) ;
2020-07-18 19:03:08 +00:00
break ;
case TRANSFORM_Y_AXIS :
2022-01-17 14:48:21 +00:00
local_axis = Vector3 ( 0 , 1 , 0 ) ;
2020-07-18 19:03:08 +00:00
break ;
case TRANSFORM_Z_AXIS :
2022-01-17 14:48:21 +00:00
local_axis = Vector3 ( 0 , 0 , 1 ) ;
2020-07-18 19:03:08 +00:00
break ;
case TRANSFORM_YZ :
case TRANSFORM_XZ :
case TRANSFORM_XY :
break ;
}
2022-01-17 14:48:21 +00:00
if ( _edit . plane ! = TRANSFORM_VIEW ) {
global_axis = spatial_editor - > get_gizmo_transform ( ) . basis . xform ( local_axis ) . normalized ( ) ;
}
2020-07-18 19:03:08 +00:00
Vector3 intersection ;
if ( ! plane . intersects_ray ( ray_pos , ray , & intersection ) ) {
break ;
}
Vector3 click ;
if ( ! plane . intersects_ray ( _edit . click_ray_pos , _edit . click_ray , & click ) ) {
break ;
}
2022-01-17 14:48:21 +00:00
static const float orthogonal_threshold = Math : : cos ( Math : : deg2rad ( 87.0f ) ) ;
bool axis_is_orthogonal = ABS ( plane . normal . dot ( global_axis ) ) < orthogonal_threshold ;
2020-07-18 19:03:08 +00:00
2022-01-17 14:48:21 +00:00
double angle = 0.0f ;
if ( axis_is_orthogonal ) {
_edit . show_rotation_line = false ;
Vector3 projection_axis = plane . normal . cross ( global_axis ) ;
Vector3 delta = intersection - click ;
float projection = delta . dot ( projection_axis ) ;
angle = ( projection * ( Math_PI / 2.0f ) ) / ( gizmo_scale * GIZMO_CIRCLE_SIZE ) ;
} else {
_edit . show_rotation_line = true ;
Vector3 click_axis = ( click - _edit . center ) . normalized ( ) ;
Vector3 current_axis = ( intersection - _edit . center ) . normalized ( ) ;
angle = click_axis . signed_angle_to ( current_axis , global_axis ) ;
}
2020-07-18 19:03:08 +00:00
if ( _edit . snap | | spatial_editor - > is_snap_enabled ( ) ) {
snap = spatial_editor - > get_rotate_snap ( ) ;
}
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 ) ;
bool local_coords = ( spatial_editor - > are_local_coords_enabled ( ) & & _edit . plane ! = TRANSFORM_VIEW ) ; // Disable local transformation for TRANSFORM_VIEW
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
if ( ! sp ) {
continue ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! se ) {
continue ;
}
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
2022-01-17 14:48:21 +00:00
Vector3 compute_axis = local_coords ? local_axis : global_axis ;
2020-07-18 19:03:08 +00:00
if ( se - > gizmo . is_valid ( ) ) {
for ( KeyValue < int , Transform3D > & GE : se - > subgizmos ) {
Transform3D xform = GE . value ;
Transform3D new_xform = _compute_transform ( TRANSFORM_ROTATE , se - > original * xform , xform , compute_axis , angle , local_coords , true ) ; // Force orthogonal with subgizmo.
if ( ! local_coords ) {
new_xform = se - > original . affine_inverse ( ) * new_xform ;
}
se - > gizmo - > set_subgizmo_transform ( GE . key , new_xform ) ;
}
} else {
Transform3D new_xform = _compute_transform ( TRANSFORM_ROTATE , se - > original , se - > original_local , compute_axis , angle , local_coords , sp - > get_rotation_edit_mode ( ) ! = Node3D : : ROTATION_EDIT_MODE_BASIS ) ;
_transform_gizmo_apply ( se - > sp , new_xform , local_coords ) ;
}
}
spatial_editor - > update_transform_gizmo ( ) ;
surface - > update ( ) ;
} break ;
default : {
}
}
}
2022-02-10 13:23:10 +00:00
void Node3DEditorViewport : : finish_transform ( ) {
spatial_editor - > set_local_coords_enabled ( _edit . original_local ) ;
spatial_editor - > update_transform_gizmo ( ) ;
_edit . mode = TRANSFORM_NONE ;
_edit . instant = false ;
surface - > update ( ) ;
}
2021-11-02 15:02:31 +00:00
// Register a shortcut and also add it as an input action with the same events.
void Node3DEditorViewport : : register_shortcut_action ( const String & p_path , const String & p_name , Key p_keycode ) {
Ref < Shortcut > sc = ED_SHORTCUT ( p_path , p_name , p_keycode ) ;
shortcut_changed_callback ( sc , p_path ) ;
// Connect to the change event on the shortcut so the input binding can be updated.
sc - > connect ( " changed " , callable_mp ( this , & Node3DEditorViewport : : shortcut_changed_callback ) , varray ( sc , p_path ) ) ;
}
// Update the action in the InputMap to the provided shortcut events.
void Node3DEditorViewport : : shortcut_changed_callback ( const Ref < Shortcut > p_shortcut , const String & p_shortcut_path ) {
InputMap * im = InputMap : : get_singleton ( ) ;
if ( im - > has_action ( p_shortcut_path ) ) {
im - > action_erase_events ( p_shortcut_path ) ;
} else {
im - > add_action ( p_shortcut_path ) ;
}
for ( int i = 0 ; i < p_shortcut - > get_events ( ) . size ( ) ; i + + ) {
im - > action_add_event ( p_shortcut_path , p_shortcut - > get_events ( ) [ i ] ) ;
}
}
2022-01-27 09:36:51 +00:00
Node3DEditorViewport : : Node3DEditorViewport ( Node3DEditor * p_spatial_editor , int p_index ) {
2020-04-10 17:18:42 +00:00
cpu_time_history_index = 0 ;
2020-04-13 10:11:55 +00:00
gpu_time_history_index = 0 ;
2020-04-10 17:18:42 +00:00
2017-03-05 15:44:50 +00:00
_edit . mode = TRANSFORM_NONE ;
_edit . plane = TRANSFORM_VIEW ;
2020-05-14 09:00:19 +00:00
_edit . snap = true ;
2022-01-17 14:48:21 +00:00
_edit . show_rotation_line = true ;
2022-02-08 18:24:50 +00:00
_edit . instant = false ;
2021-06-23 14:49:50 +00:00
_edit . gizmo_handle = - 1 ;
2022-01-11 11:33:37 +00:00
_edit . gizmo_handle_secondary = false ;
2017-03-05 15:44:50 +00:00
index = p_index ;
2021-11-17 20:08:55 +00:00
editor_data = SceneTreeDock : : get_singleton ( ) - > get_editor_data ( ) ;
2022-01-27 09:36:51 +00:00
editor_selection = EditorNode : : get_singleton ( ) - > get_editor_selection ( ) ;
undo_redo = EditorNode : : get_singleton ( ) - > get_undo_redo ( ) ;
2020-02-12 17:24:06 +00:00
2017-03-05 15:44:50 +00:00
orthogonal = false ;
2019-10-23 09:46:26 +00:00
auto_orthogonal = false ;
2018-08-05 18:24:11 +00:00
lock_rotation = false ;
2017-03-05 15:44:50 +00:00
message_time = 0 ;
2017-05-07 20:59:05 +00:00
zoom_indicator_delay = 0.0 ;
2017-03-05 15:44:50 +00:00
spatial_editor = p_spatial_editor ;
2022-02-09 08:39:28 +00:00
SubViewportContainer * c = memnew ( SubViewportContainer ) ;
subviewport_container = c ;
c - > set_stretch ( true ) ;
add_child ( c ) ;
2022-03-19 00:02:57 +00:00
c - > set_anchors_and_offsets_preset ( Control : : PRESET_FULL_RECT ) ;
2020-03-04 01:51:12 +00:00
viewport = memnew ( SubViewport ) ;
2016-01-18 22:49:11 +00:00
viewport - > set_disable_input ( true ) ;
2016-11-10 02:55:06 +00:00
2022-02-09 08:39:28 +00:00
c - > add_child ( viewport ) ;
2017-03-05 15:44:50 +00:00
surface = memnew ( Control ) ;
2017-09-02 19:47:16 +00:00
surface - > set_drag_forwarding ( this ) ;
2014-02-10 01:10:30 +00:00
add_child ( surface ) ;
2022-03-19 00:02:57 +00:00
surface - > set_anchors_and_offsets_preset ( Control : : PRESET_FULL_RECT ) ;
2017-06-11 21:13:04 +00:00
surface - > set_clip_contents ( true ) ;
2020-03-26 21:49:16 +00:00
camera = memnew ( Camera3D ) ;
2021-06-23 14:49:50 +00:00
camera - > set_disable_gizmos ( true ) ;
2020-11-26 19:00:03 +00: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 01:10:30 +00:00
viewport - > add_child ( camera ) ;
camera - > make_current ( ) ;
surface - > set_focus_mode ( FOCUS_ALL ) ;
2019-05-24 19:21:07 +00:00
VBoxContainer * vbox = memnew ( VBoxContainer ) ;
surface - > add_child ( vbox ) ;
2021-09-21 07:35:23 +00:00
vbox - > set_offset ( SIDE_LEFT , 10 * EDSCALE ) ;
vbox - > set_offset ( SIDE_TOP , 10 * EDSCALE ) ;
2019-05-24 19:21:07 +00:00
2017-03-05 15:44:50 +00:00
view_menu = memnew ( MenuButton ) ;
2018-10-10 07:25:59 +00:00
view_menu - > set_flat ( false ) ;
2019-05-24 19:21:07 +00:00
view_menu - > set_h_size_flags ( 0 ) ;
2020-09-17 01:40:00 +00:00
view_menu - > set_shortcut_context ( this ) ;
vbox - > add_child ( view_menu ) ;
2018-10-10 07:25:59 +00:00
2019-10-03 20:39:08 +00:00
display_submenu = memnew ( PopupMenu ) ;
2022-07-03 15:22:06 +00:00
view_menu - > get_popup ( ) - > set_hide_on_checkable_item_selection ( false ) ;
2019-10-03 20:39:08 +00:00
view_menu - > get_popup ( ) - > add_child ( display_submenu ) ;
2016-06-30 20:54:34 +00: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 01:10:30 +00:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2018-03-24 02:05:20 +00: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 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_PERSPECTIVE ) , true ) ;
2019-10-23 09:46:26 +00: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 01:10:30 +00:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2018-06-25 01:24:31 +00: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 02:05:20 +00: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 01:59:14 +00: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 02:05:20 +00: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 18:52:03 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_DISPLAY_NORMAL ) , true ) ;
2022-07-03 15:22:06 +00:00
display_submenu - > set_hide_on_checkable_item_selection ( false ) ;
2020-04-08 01:51:52 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Directional Shadow Splits " ) , VIEW_DISPLAY_DEBUG_PSSM_SPLITS ) ;
display_submenu - > add_separator ( ) ;
2020-01-26 23:09:40 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Normal Buffer " ) , VIEW_DISPLAY_NORMAL_BUFFER ) ;
display_submenu - > add_separator ( ) ;
2019-10-03 20:39:08 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Shadow Atlas " ) , VIEW_DISPLAY_DEBUG_SHADOW_ATLAS ) ;
2022-02-04 15:36:19 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Directional Shadow Map " ) , VIEW_DISPLAY_DEBUG_DIRECTIONAL_SHADOW_ATLAS ) ;
2019-10-03 20:39:08 +00:00
display_submenu - > add_separator ( ) ;
2020-04-14 03:05:21 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Decal Atlas " ) , VIEW_DISPLAY_DEBUG_DECAL_ATLAS ) ;
display_submenu - > add_separator ( ) ;
2021-06-04 22:47:26 +00:00
display_submenu - > add_radio_check_item ( TTR ( " VoxelGI Lighting " ) , VIEW_DISPLAY_DEBUG_VOXEL_GI_LIGHTING ) ;
display_submenu - > add_radio_check_item ( TTR ( " VoxelGI Albedo " ) , VIEW_DISPLAY_DEBUG_VOXEL_GI_ALBEDO ) ;
display_submenu - > add_radio_check_item ( TTR ( " VoxelGI Emission " ) , VIEW_DISPLAY_DEBUG_VOXEL_GI_EMISSION ) ;
2020-01-12 01:26:52 +00:00
display_submenu - > add_separator ( ) ;
2020-06-25 13:33:28 +00: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 01:26:52 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Scene Luminance " ) , VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE ) ;
2020-01-25 10:18:55 +00:00
display_submenu - > add_separator ( ) ;
display_submenu - > add_radio_check_item ( TTR ( " SSAO " ) , VIEW_DISPLAY_DEBUG_SSAO ) ;
2021-08-03 07:07:32 +00:00
display_submenu - > add_radio_check_item ( TTR ( " SSIL " ) , VIEW_DISPLAY_DEBUG_SSIL ) ;
2020-01-26 23:09:40 +00:00
display_submenu - > add_separator ( ) ;
2022-02-04 15:36:19 +00:00
display_submenu - > add_radio_check_item ( TTR ( " VoxelGI/SDFGI Buffer " ) , VIEW_DISPLAY_DEBUG_GI_BUFFER ) ;
2020-12-17 18:56:59 +00:00
display_submenu - > add_separator ( ) ;
2022-02-04 15:36:19 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Disable Mesh LOD " ) , VIEW_DISPLAY_DEBUG_DISABLE_LOD ) ;
2021-01-17 16:25:38 +00:00
display_submenu - > add_separator ( ) ;
2022-02-04 15:36:19 +00:00
display_submenu - > add_radio_check_item ( TTR ( " OmniLight3D Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_OMNI_LIGHTS ) ;
display_submenu - > add_radio_check_item ( TTR ( " SpotLight3D Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_SPOT_LIGHTS ) ;
2021-01-17 16:25:38 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Decal Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_DECALS ) ;
2022-02-04 15:36:19 +00:00
display_submenu - > add_radio_check_item ( TTR ( " ReflectionProbe Cluster " ) , VIEW_DISPLAY_DEBUG_CLUSTER_REFLECTION_PROBES ) ;
2021-04-20 16:40:24 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Occlusion Culling Buffer " ) , VIEW_DISPLAY_DEBUG_OCCLUDERS ) ;
2022-04-04 14:10:22 +00:00
display_submenu - > add_radio_check_item ( TTR ( " Motion Vectors " ) , VIEW_DISPLAY_MOTION_VECTORS ) ;
2021-01-17 16:25:38 +00:00
2019-10-03 20:39:08 +00:00
display_submenu - > set_name ( " display_advanced " ) ;
2020-03-08 18:23:04 +00:00
view_menu - > get_popup ( ) - > add_submenu_item ( TTR ( " Display Advanced... " ) , " display_advanced " , VIEW_DISPLAY_ADVANCED ) ;
2017-06-11 18:52:03 +00: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 17:18:42 +00:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_fps " , TTR ( " View Frame Time " ) ) , VIEW_FRAME_TIME ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_ENVIRONMENT ) , true ) ;
2014-10-03 03:10:51 +00:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2017-10-31 17:23:25 +00: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 20:54:34 +00:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_audio_listener " , TTR ( " Audio Listener " ) ) , VIEW_AUDIO_LISTENER ) ;
2019-08-12 20:23:00 +00:00
view_menu - > get_popup ( ) - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_audio_doppler " , TTR ( " Enable Doppler " ) ) , VIEW_AUDIO_DOPPLER ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_GIZMOS ) , true ) ;
2014-10-03 03:10:51 +00:00
2018-07-26 22:36:05 +00: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 01:10:30 +00:00
view_menu - > get_popup ( ) - > add_separator ( ) ;
2016-10-04 18:39:38 +00:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/focus_origin " ) , VIEW_CENTER_TO_ORIGIN ) ;
2016-06-30 20:54:34 +00:00
view_menu - > get_popup ( ) - > add_shortcut ( ED_GET_SHORTCUT ( " spatial_editor/focus_selection " ) , VIEW_CENTER_TO_SELECTION ) ;
2018-10-27 21:43:19 +00: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 21:49:16 +00: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 14:29:55 +00:00
view_menu - > set_disable_shortcuts ( true ) ;
2020-03-03 13:36:29 +00: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 09:08:52 +00:00
// Alternate display modes only work when using the Vulkan renderer; make this explicit.
2020-01-17 15:06:47 +00: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 ) ;
2021-09-26 23:07:10 +00:00
const String unsupported_tooltip = TTR ( " Not available when using the OpenGL renderer. " ) ;
2020-01-17 15:06:47 +00:00
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 ) ;
}
2021-11-02 15:02:31 +00:00
register_shortcut_action ( " spatial_editor/freelook_left " , TTR ( " Freelook Left " ) , Key : : A ) ;
register_shortcut_action ( " spatial_editor/freelook_right " , TTR ( " Freelook Right " ) , Key : : D ) ;
register_shortcut_action ( " spatial_editor/freelook_forward " , TTR ( " Freelook Forward " ) , Key : : W ) ;
register_shortcut_action ( " spatial_editor/freelook_backwards " , TTR ( " Freelook Backwards " ) , Key : : S ) ;
register_shortcut_action ( " spatial_editor/freelook_up " , TTR ( " Freelook Up " ) , Key : : E ) ;
register_shortcut_action ( " spatial_editor/freelook_down " , TTR ( " Freelook Down " ) , Key : : Q ) ;
register_shortcut_action ( " spatial_editor/freelook_speed_modifier " , TTR ( " Freelook Speed Modifier " ) , Key : : SHIFT ) ;
register_shortcut_action ( " spatial_editor/freelook_slow_modifier " , TTR ( " Freelook Slow Modifier " ) , Key : : ALT ) ;
2020-07-18 19:03:08 +00:00
ED_SHORTCUT ( " spatial_editor/lock_transform_x " , TTR ( " Lock Transformation to X axis " ) , Key : : X ) ;
ED_SHORTCUT ( " spatial_editor/lock_transform_y " , TTR ( " Lock Transformation to Y axis " ) , Key : : Y ) ;
ED_SHORTCUT ( " spatial_editor/lock_transform_z " , TTR ( " Lock Transformation to Z axis " ) , Key : : Z ) ;
ED_SHORTCUT ( " spatial_editor/lock_transform_yz " , TTR ( " Lock Transformation to YZ plane " ) , KeyModifierMask : : SHIFT | Key : : X ) ;
ED_SHORTCUT ( " spatial_editor/lock_transform_xz " , TTR ( " Lock Transformation to XZ plane " ) , KeyModifierMask : : SHIFT | Key : : Y ) ;
ED_SHORTCUT ( " spatial_editor/lock_transform_xy " , TTR ( " Lock Transformation to XY plane " ) , KeyModifierMask : : SHIFT | Key : : Z ) ;
ED_SHORTCUT ( " spatial_editor/cancel_transform " , TTR ( " Cancel Transformation " ) , Key : : ESCAPE ) ;
ED_SHORTCUT ( " spatial_editor/instant_translate " , TTR ( " Begin Translate Transformation " ) ) ;
ED_SHORTCUT ( " spatial_editor/instant_rotate " , TTR ( " Begin Rotate Transformation " ) ) ;
ED_SHORTCUT ( " spatial_editor/instant_scale " , TTR ( " Begin Scale Transformation " ) ) ;
2017-07-27 02:00:23 +00:00
2018-10-10 07:25:59 +00:00
preview_camera = memnew ( CheckBox ) ;
2017-12-19 05:25:00 +00:00
preview_camera - > set_text ( TTR ( " Preview " ) ) ;
2021-08-13 21:31:57 +00:00
preview_camera - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/toggle_camera_preview " , TTR ( " Toggle Camera Preview " ) , KeyModifierMask : : CMD | Key : : P ) ) ;
2019-05-24 19:21:07 +00:00
vbox - > add_child ( preview_camera ) ;
preview_camera - > set_h_size_flags ( 0 ) ;
2014-02-10 01:10:30 +00:00
preview_camera - > hide ( ) ;
2020-03-26 21:49:16 +00:00
preview_camera - > connect ( " toggled " , callable_mp ( this , & Node3DEditorViewport : : _toggle_camera_preview ) ) ;
2020-04-01 23:20:12 +00:00
previewing = nullptr ;
2017-03-05 15:44:50 +00:00
gizmo_scale = 1.0 ;
2017-05-07 20:59:05 +00:00
2020-04-01 23:20:12 +00:00
preview_node = nullptr ;
2017-09-02 19:47:16 +00:00
2017-06-11 21:13:04 +00:00
info_label = memnew ( Label ) ;
2020-12-22 16:24:29 +00: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 12:06:21 +00: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 21:13:04 +00:00
2018-07-26 22:36:05 +00:00
cinema_label = memnew ( Label ) ;
2020-12-22 16:24:29 +00:00
cinema_label - > set_anchor_and_offset ( SIDE_TOP , ANCHOR_BEGIN , 10 * EDSCALE ) ;
2018-07-26 22:36:05 +00:00
cinema_label - > set_h_grow_direction ( GROW_DIRECTION_END ) ;
2021-11-25 02:58:47 +00:00
cinema_label - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2018-07-26 22:36:05 +00:00
surface - > add_child ( cinema_label ) ;
cinema_label - > set_text ( TTR ( " Cinematic Preview " ) ) ;
cinema_label - > hide ( ) ;
previewing_cinema = false ;
2018-10-10 07:25:59 +00:00
locked_label = memnew ( Label ) ;
2020-12-22 16:24:29 +00: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 07:25:59 +00:00
locked_label - > set_h_grow_direction ( GROW_DIRECTION_END ) ;
locked_label - > set_v_grow_direction ( GROW_DIRECTION_BEGIN ) ;
2021-11-25 02:58:47 +00:00
locked_label - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2018-10-10 07:25:59 +00:00
surface - > add_child ( locked_label ) ;
locked_label - > set_text ( TTR ( " View Rotation Locked " ) ) ;
locked_label - > hide ( ) ;
2021-04-09 12:52:10 +00:00
zoom_limit_label = memnew ( Label ) ;
zoom_limit_label - > set_anchors_and_offsets_preset ( LayoutPreset : : PRESET_BOTTOM_LEFT ) ;
zoom_limit_label - > set_offset ( Side : : SIDE_TOP , - 28 * EDSCALE ) ;
zoom_limit_label - > set_text ( TTR ( " To zoom further, change the camera's clipping planes (View -> Settings...) " ) ) ;
zoom_limit_label - > set_name ( " ZoomLimitMessageLabel " ) ;
2022-02-08 09:14:58 +00:00
zoom_limit_label - > add_theme_color_override ( " font_color " , Color ( 1 , 1 , 1 , 1 ) ) ;
2021-04-09 12:52:10 +00:00
zoom_limit_label - > hide ( ) ;
surface - > add_child ( zoom_limit_label ) ;
2020-12-26 19:21:07 +00: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 09:46:26 +00:00
top_right_vbox = memnew ( VBoxContainer ) ;
2020-04-21 14:03:14 +00:00
top_right_vbox - > set_anchors_and_offsets_preset ( PRESET_TOP_RIGHT , PRESET_MODE_MINSIZE , 10.0 * EDSCALE ) ;
2019-10-23 09:46:26 +00:00
top_right_vbox - > set_h_grow_direction ( GROW_DIRECTION_BEGIN ) ;
2020-12-26 19:21:07 +00: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.
2022-02-08 09:14:58 +00:00
top_right_vbox - > add_theme_constant_override ( " separation " , 0 ) ;
2019-10-23 09:46:26 +00: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 19:21:07 +00: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 09:46:26 +00:00
fps_label = memnew ( Label ) ;
top_right_vbox - > add_child ( fps_label ) ;
fps_label - > hide ( ) ;
surface - > add_child ( top_right_vbox ) ;
2020-04-01 23:20:12 +00:00
accept = nullptr ;
2017-09-02 19:47:16 +00:00
2017-05-07 20:59:05 +00:00
freelook_active = false ;
2017-10-08 00:43:57 +00:00
freelook_speed = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/freelook/freelook_base_speed " ) ;
2014-10-03 03:10:51 +00:00
2017-03-05 15:44:50 +00:00
selection_menu = memnew ( PopupMenu ) ;
2015-11-04 21:39:07 +00:00
add_child ( selection_menu ) ;
2020-03-12 12:37:40 +00:00
selection_menu - > set_min_size ( Size2 ( 100 , 0 ) * EDSCALE ) ;
2020-03-26 21:49:16 +00: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 21:39:07 +00:00
2017-03-05 15:44:50 +00:00
if ( p_index = = 0 ) {
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( VIEW_AUDIO_LISTENER ) , true ) ;
2021-08-02 17:31:51 +00:00
viewport - > set_as_audio_listener_3d ( true ) ;
2014-10-03 03:10:51 +00:00
}
2021-08-14 07:24:02 +00:00
view_type = VIEW_TYPE_USER ;
2015-03-21 20:47:21 +00:00
_update_name ( ) ;
2020-03-26 21:49:16 +00:00
EditorSettings : : get_singleton ( ) - > connect ( " settings_changed " , callable_mp ( this , & Node3DEditorViewport : : update_transform_gizmo_view ) ) ;
2014-02-10 01:10:30 +00:00
}
2021-01-04 09:06:46 +00:00
Node3DEditorViewport : : ~ Node3DEditorViewport ( ) {
memdelete ( frame_time_gradient ) ;
}
2017-06-11 14:29:27 +00:00
//////////////////////////////////////////////////////////////
2021-08-22 15:37:22 +00:00
void Node3DEditorViewportContainer : : gui_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 06:52:21 +00:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2017-06-11 14:29:27 +00:00
Ref < InputEventMouseButton > mb = p_event ;
2021-08-13 21:31:57 +00:00
if ( mb . is_valid ( ) & & mb - > get_button_index ( ) = = MouseButton : : LEFT ) {
2018-08-25 06:47:04 +00:00
if ( mb - > is_pressed ( ) ) {
Vector2 size = get_size ( ) ;
2017-06-11 14:29:27 +00:00
2021-07-17 21:22:52 +00:00
int h_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " HSplitContainer " ) ) ;
int v_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " VSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00: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 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
drag_begin_pos = mb - > get_position ( ) ;
drag_begin_ratio . x = ratio_h ;
drag_begin_ratio . y = ratio_v ;
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
dragging_h = false ;
dragging_v = false ;
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
} break ;
case VIEW_USE_2_VIEWPORTS : {
dragging_h = false ;
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
} break ;
case VIEW_USE_2_VIEWPORTS_ALT : {
2017-06-11 14:29:27 +00:00
dragging_v = false ;
2018-08-25 06:47:04 +00:00
} break ;
case VIEW_USE_3_VIEWPORTS :
case VIEW_USE_3_VIEWPORTS_ALT :
case VIEW_USE_4_VIEWPORTS : {
// Do nothing.
2017-06-11 14:29:27 +00:00
2018-08-25 06:47:04 +00:00
} break ;
}
} else {
dragging_h = false ;
dragging_v = false ;
2017-06-11 14:29:27 +00:00
}
}
Ref < InputEventMouseMotion > mm = p_event ;
2018-08-25 06:47:04 +00: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 ( ) ;
2021-07-17 21:22:52 +00:00
int h_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " HSplitContainer " ) ) ;
int v_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " VSplitContainer " ) ) ;
2018-08-25 06:47:04 +00: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 14:29:27 +00:00
if ( dragging_h ) {
2021-06-21 03:30:19 +00:00
real_t new_ratio = drag_begin_ratio . x + ( mm - > get_position ( ) . x - drag_begin_pos . x ) / get_size ( ) . width ;
2017-06-11 14:29:27 +00:00
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 ) {
2021-06-21 03:30:19 +00:00
real_t new_ratio = drag_begin_ratio . y + ( mm - > get_position ( ) . y - drag_begin_pos . y ) / get_size ( ) . height ;
2017-06-11 14:29:27 +00:00
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 21:49:16 +00:00
void Node3DEditorViewportContainer : : _notification ( int p_what ) {
2022-02-16 02:44:22 +00:00
switch ( p_what ) {
case NOTIFICATION_MOUSE_ENTER :
case NOTIFICATION_MOUSE_EXIT : {
mouseover = ( p_what = = NOTIFICATION_MOUSE_ENTER ) ;
update ( ) ;
} break ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_DRAW : {
if ( mouseover ) {
Ref < Texture2D > h_grabber = get_theme_icon ( SNAME ( " grabber " ) , SNAME ( " HSplitContainer " ) ) ;
Ref < Texture2D > v_grabber = get_theme_icon ( SNAME ( " grabber " ) , SNAME ( " VSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
Ref < Texture2D > hdiag_grabber = get_theme_icon ( SNAME ( " GuiViewportHdiagsplitter " ) , SNAME ( " EditorIcons " ) ) ;
Ref < Texture2D > vdiag_grabber = get_theme_icon ( SNAME ( " GuiViewportVdiagsplitter " ) , SNAME ( " EditorIcons " ) ) ;
Ref < Texture2D > vh_grabber = get_theme_icon ( SNAME ( " GuiViewportVhsplitter " ) , SNAME ( " EditorIcons " ) ) ;
2018-08-25 06:47:04 +00:00
2022-02-16 02:44:22 +00:00
Vector2 size = get_size ( ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int h_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " HSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int v_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " VSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int size_left = mid_w - h_sep / 2 ;
int size_bottom = size . height - mid_h - v_sep / 2 ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
// Nothing to show.
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00: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 ) ) ;
set_default_cursor_shape ( CURSOR_VSPLIT ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00: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 ) ) ;
set_default_cursor_shape ( CURSOR_HSPLIT ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_3_VIEWPORTS : {
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 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_3_VIEWPORTS_ALT : {
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 ) ;
}
2018-08-25 06:47:04 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_4_VIEWPORTS : {
Vector2 half ( mid_w , mid_h ) ;
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 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
}
}
} break ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
case NOTIFICATION_SORT_CHILDREN : {
Node3DEditorViewport * viewports [ 4 ] ;
int vc = 0 ;
for ( int i = 0 ; i < get_child_count ( ) ; i + + ) {
viewports [ vc ] = Object : : cast_to < Node3DEditorViewport > ( get_child ( i ) ) ;
if ( viewports [ vc ] ) {
vc + + ;
}
2017-06-11 14:29:27 +00:00
}
2022-02-16 02:44:22 +00:00
ERR_FAIL_COND ( vc ! = 4 ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
Size2 size = get_size ( ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
if ( size . x < 10 | | size . y < 10 ) {
for ( int i = 0 ; i < 4 ; i + + ) {
viewports [ i ] - > hide ( ) ;
}
return ;
2017-06-11 14:29:27 +00:00
}
2022-02-16 02:44:22 +00:00
int h_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " HSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int v_sep = get_theme_constant ( SNAME ( " separation " ) , SNAME ( " VSplitContainer " ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int mid_w = size . width * ratio_h ;
int mid_h = size . height * ratio_v ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int size_left = mid_w - h_sep / 2 ;
int size_right = size . width - mid_w - h_sep / 2 ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
int size_top = mid_h - v_sep / 2 ;
int size_bottom = size . height - mid_h - v_sep / 2 ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
switch ( view ) {
case VIEW_USE_1_VIEWPORT : {
viewports [ 0 ] - > show ( ) ;
for ( int i = 1 ; i < 4 ; i + + ) {
viewports [ i ] - > hide ( ) ;
}
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
fit_child_in_rect ( viewports [ 0 ] , Rect2 ( Vector2 ( ) , size ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_2_VIEWPORTS : {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i = = 1 | | i = = 3 ) {
viewports [ i ] - > hide ( ) ;
} else {
viewports [ i ] - > show ( ) ;
}
2020-05-14 14:41:43 +00:00
}
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00: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 ) ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_2_VIEWPORTS_ALT : {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i = = 1 | | i = = 3 ) {
viewports [ i ] - > hide ( ) ;
} else {
viewports [ i ] - > show ( ) ;
}
2020-05-14 14:41:43 +00:00
}
2022-02-16 02:44:22 +00: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 ) ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_3_VIEWPORTS : {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i = = 1 ) {
viewports [ i ] - > hide ( ) ;
} else {
viewports [ i ] - > show ( ) ;
}
2020-05-14 14:41:43 +00:00
}
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00: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 ) ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_3_VIEWPORTS_ALT : {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( i = = 1 ) {
viewports [ i ] - > hide ( ) ;
} else {
viewports [ i ] - > show ( ) ;
}
2020-05-14 14:41:43 +00:00
}
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00: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 ) ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
case VIEW_USE_4_VIEWPORTS : {
for ( int i = 0 ; i < 4 ; i + + ) {
viewports [ i ] - > show ( ) ;
}
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
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 ) ) ) ;
2017-06-11 14:29:27 +00:00
2022-02-16 02:44:22 +00:00
} break ;
}
} break ;
2017-06-11 14:29:27 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditorViewportContainer : : set_view ( View p_view ) {
2017-06-11 14:29:27 +00:00
view = p_view ;
queue_sort ( ) ;
}
2020-03-26 21:49:16 +00:00
Node3DEditorViewportContainer : : View Node3DEditorViewportContainer : : get_view ( ) {
2017-06-11 14:29:27 +00:00
return view ;
}
2020-03-26 21:49:16 +00:00
Node3DEditorViewportContainer : : Node3DEditorViewportContainer ( ) {
2018-08-25 06:47:04 +00:00
set_clip_contents ( true ) ;
2017-06-11 14:29:27 +00:00
view = VIEW_USE_1_VIEWPORT ;
mouseover = false ;
ratio_h = 0.5 ;
ratio_v = 0.5 ;
2018-08-25 06:47:04 +00:00
hovering_v = false ;
hovering_h = false ;
2017-06-11 14:29:27 +00:00
dragging_v = false ;
dragging_h = false ;
}
///////////////////////////////////////////////////////////////////
2020-04-01 23:20:12 +00:00
Node3DEditor * Node3DEditor : : singleton = nullptr ;
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem : : ~ Node3DEditorSelectedItem ( ) {
2020-05-14 14:41:43 +00:00
if ( sbox_instance . is_valid ( ) ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( sbox_instance ) ;
2020-05-14 14:41:43 +00:00
}
2021-08-09 14:51:30 +00:00
if ( sbox_instance_offset . is_valid ( ) ) {
RenderingServer : : get_singleton ( ) - > free ( sbox_instance_offset ) ;
}
2020-07-03 22:11:56 +00:00
if ( sbox_instance_xray . is_valid ( ) ) {
RenderingServer : : get_singleton ( ) - > free ( sbox_instance_xray ) ;
}
2021-08-09 14:51:30 +00:00
if ( sbox_instance_xray_offset . is_valid ( ) ) {
RenderingServer : : get_singleton ( ) - > free ( sbox_instance_xray_offset ) ;
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : select_gizmo_highlight_axis ( int p_axis ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2019-08-01 12:23:29 +00: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 16:22:51 +00:00
rotate_gizmo [ i ] - > surface_set_material ( 0 , ( i + 3 ) = = p_axis ? rotate_gizmo_color_hl [ i ] : rotate_gizmo_color [ i ] ) ;
2019-08-01 12:23:29 +00: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 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : update_transform_gizmo ( ) {
2021-06-23 14:49:50 +00:00
int count = 0 ;
bool local_gizmo_coords = are_local_coords_enabled ( ) ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
Vector3 gizmo_center ;
2017-01-11 03:52:51 +00:00
Basis gizmo_basis ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( se & & se - > gizmo . is_valid ( ) ) {
2021-08-09 20:13:42 +00:00
for ( const KeyValue < int , Transform3D > & E : se - > subgizmos ) {
Transform3D xf = se - > sp - > get_global_transform ( ) * se - > gizmo - > get_subgizmo_transform ( E . key ) ;
2021-06-23 14:49:50 +00:00
gizmo_center + = xf . origin ;
if ( count = = 0 & & local_gizmo_coords ) {
gizmo_basis = xf . basis ;
}
count + + ;
2020-05-14 14:41:43 +00:00
}
2021-06-23 14:49:50 +00:00
} else {
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Node3D * sp = Object : : cast_to < Node3D > ( E - > get ( ) ) ;
if ( ! sp ) {
continue ;
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
if ( sp - > has_meta ( " _edit_lock_ " ) ) {
continue ;
}
Node3DEditorSelectedItem * sel_item = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( ! sel_item ) {
continue ;
}
2017-10-03 16:49:32 +00:00
2021-06-23 14:49:50 +00:00
Transform3D xf = sel_item - > sp - > get_global_transform ( ) ;
gizmo_center + = xf . origin ;
if ( count = = 0 & & local_gizmo_coords ) {
2017-03-05 15:44:50 +00:00
gizmo_basis = xf . basis ;
2014-02-10 01:10:30 +00:00
}
2021-06-23 14:49:50 +00:00
count + + ;
2014-02-10 01:10:30 +00:00
}
}
2021-06-23 14:49:50 +00:00
gizmo . visible = count > 0 ;
gizmo . transform . origin = ( count > 0 ) ? gizmo_center / count : Vector3 ( ) ;
gizmo . transform . basis = ( count = = 1 ) ? gizmo_basis : Basis ( ) ;
2014-02-10 01:10:30 +00:00
2017-08-31 21:30:35 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-05-05 01:50:23 +00:00
viewports [ i ] - > update_transform_gizmo_view ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2017-11-22 21:29:27 +00:00
void _update_all_gizmos ( Node * p_node ) {
for ( int i = p_node - > get_child_count ( ) - 1 ; 0 < = i ; - - i ) {
2020-03-26 21:49:16 +00:00
Node3D * spatial_node = Object : : cast_to < Node3D > ( p_node - > get_child ( i ) ) ;
2017-11-22 21:29:27 +00:00
if ( spatial_node ) {
2021-06-23 14:49:50 +00:00
spatial_node - > update_gizmos ( ) ;
2017-11-22 21:29:27 +00:00
}
_update_all_gizmos ( p_node - > get_child ( i ) ) ;
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : update_all_gizmos ( Node * p_node ) {
2021-09-20 11:10:19 +00:00
if ( ! p_node & & is_inside_tree ( ) ) {
2021-07-27 15:43:12 +00:00
p_node = get_tree ( ) - > get_edited_scene_root ( ) ;
}
2019-09-03 10:42:34 +00:00
if ( ! p_node ) {
2021-07-27 15:43:12 +00:00
// No edited scene, so nothing to update.
return ;
2019-09-03 10:42:34 +00:00
}
2018-09-02 20:31:03 +00:00
_update_all_gizmos ( p_node ) ;
2017-11-22 21:29:27 +00:00
}
2020-03-26 21:49:16 +00:00
Object * Node3DEditor : : _get_editor_data ( Object * p_what ) {
Node3D * sp = Object : : cast_to < Node3D > ( p_what ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2020-04-01 23:20:12 +00:00
return nullptr ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * si = memnew ( Node3DEditorSelectedItem ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
si - > sp = sp ;
2020-07-03 22:11:56 +00:00
si - > sbox_instance = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
2021-08-09 14:51:30 +00:00
si - > sbox_instance_offset = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-07-03 22:11:56 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance_offset ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2021-05-10 17:20:54 +00:00
// Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
// It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance , 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance_offset , 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_offset , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_offset , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2020-07-03 22:11:56 +00:00
si - > sbox_instance_xray = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box_xray - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
2021-08-09 14:51:30 +00:00
si - > sbox_instance_xray_offset = RenderingServer : : get_singleton ( ) - > instance_create2 (
selection_box_xray - > get_rid ( ) ,
sp - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-07-03 22:11:56 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance_xray ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting (
si - > sbox_instance_xray_offset ,
RS : : SHADOW_CASTING_SETTING_OFF ) ;
2021-05-10 17:20:54 +00:00
// Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
// It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance_xray , 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( si - > sbox_instance_xray_offset , 1 < < Node3DEditorViewport : : GIZMO_EDIT_LAYER ) ;
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_xray , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_xray , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2021-08-09 14:51:30 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_xray_offset , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( si - > sbox_instance_xray_offset , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2014-02-10 01:10:30 +00:00
return si ;
}
2020-07-03 22:11:56 +00:00
void Node3DEditor : : _generate_selection_boxes ( ) {
// Use two AABBs to create the illusion of a slightly thicker line.
2017-11-17 02:09:00 +00:00
AABB aabb ( Vector3 ( ) , Vector3 ( 1 , 1 , 1 ) ) ;
2020-07-03 22:11:56 +00:00
// 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 15:44:50 +00:00
Ref < SurfaceTool > st = memnew ( SurfaceTool ) ;
2020-07-03 22:11:56 +00:00
Ref < SurfaceTool > st_xray = memnew ( SurfaceTool ) ;
2016-03-08 23:00:52 +00:00
2014-02-10 01:10:30 +00:00
st - > begin ( Mesh : : PRIMITIVE_LINES ) ;
2020-07-03 22:11:56 +00:00
st_xray - > begin ( Mesh : : PRIMITIVE_LINES ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 12 ; i + + ) {
Vector3 a , b ;
aabb . get_edge ( i , a , b ) ;
2016-03-08 23:00:52 +00:00
2014-02-10 01:10:30 +00:00
st - > add_vertex ( a ) ;
2020-07-03 22:11:56 +00:00
st - > add_vertex ( b ) ;
st_xray - > add_vertex ( a ) ;
st_xray - > add_vertex ( b ) ;
}
2014-02-10 01:10:30 +00:00
2019-09-15 04:01:52 +00:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2020-12-29 06:35:59 +00:00
const Color selection_box_color = EDITOR_GET ( " editors/3d/selection_box_color " ) ;
mat - > set_albedo ( selection_box_color ) ;
2019-09-15 04:01:52 +00:00
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2014-02-10 01:10:30 +00:00
st - > set_material ( mat ) ;
selection_box = st - > commit ( ) ;
2020-07-03 22:11:56 +00: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 06:35:59 +00:00
mat_xray - > set_albedo ( selection_box_color * Color ( 1 , 1 , 1 , 0.15 ) ) ;
2020-07-03 22:11:56 +00:00
mat_xray - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
st_xray - > set_material ( mat_xray ) ;
selection_box_xray = st_xray - > commit ( ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Dictionary Node3DEditor : : get_state ( ) const {
2014-02-10 01:10:30 +00:00
Dictionary d ;
2017-03-05 15:44:50 +00: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 18:51:37 +00:00
d [ " local_coords " ] = tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > is_pressed ( ) ;
2017-03-05 15:44:50 +00:00
int vc = 0 ;
2020-05-14 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) ) ) {
2017-03-05 15:44:50 +00:00
vc = 1 ;
2020-05-14 14:41:43 +00: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 15:44:50 +00:00
vc = 2 ;
2020-05-14 14:41:43 +00: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 15:44:50 +00:00
vc = 3 ;
2020-05-14 14:41:43 +00: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 15:44:50 +00:00
vc = 4 ;
2020-05-14 14:41:43 +00: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 15:44:50 +00:00
vc = 5 ;
2020-05-14 14:41:43 +00: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 15:44:50 +00:00
vc = 6 ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
d [ " viewport_mode " ] = vc ;
2014-02-10 01:10:30 +00:00
Array vpdata ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
vpdata . push_back ( viewports [ i ] - > get_state ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
d [ " viewports " ] = vpdata ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
2018-07-24 22:08:49 +00:00
Dictionary gizmos_status ;
2019-03-11 23:30:50 +00:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 10:56:01 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2018-08-11 21:07:00 +00:00
int state = gizmos_menu - > get_item_state ( gizmos_menu - > get_item_index ( i ) ) ;
2021-03-01 01:52:53 +00:00
String name = gizmo_plugins_by_name [ i ] - > get_gizmo_name ( ) ;
2018-08-11 21:07:00 +00:00
gizmos_status [ name ] = state ;
2018-07-24 22:08:49 +00:00
}
d [ " gizmos_status " ] = gizmos_status ;
2021-02-22 13:54:12 +00:00
{
Dictionary pd ;
pd [ " sun_rotation " ] = sun_rotation ;
pd [ " environ_sky_color " ] = environ_sky_color - > get_pick_color ( ) ;
pd [ " environ_ground_color " ] = environ_ground_color - > get_pick_color ( ) ;
pd [ " environ_energy " ] = environ_energy - > get_value ( ) ;
pd [ " environ_glow_enabled " ] = environ_glow_button - > is_pressed ( ) ;
pd [ " environ_tonemap_enabled " ] = environ_tonemap_button - > is_pressed ( ) ;
pd [ " environ_ao_enabled " ] = environ_ao_button - > is_pressed ( ) ;
pd [ " environ_gi_enabled " ] = environ_gi_button - > is_pressed ( ) ;
pd [ " sun_max_distance " ] = sun_max_distance - > get_value ( ) ;
pd [ " sun_color " ] = sun_color - > get_pick_color ( ) ;
pd [ " sun_energy " ] = sun_energy - > get_value ( ) ;
pd [ " sun_disabled " ] = sun_button - > is_pressed ( ) ;
pd [ " environ_disabled " ] = environ_button - > is_pressed ( ) ;
d [ " preview_sun_env " ] = pd ;
}
2018-07-24 22:08:49 +00:00
2014-02-10 01:10:30 +00:00
return d ;
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditor : : set_state ( const Dictionary & p_state ) {
2014-02-10 01:10:30 +00:00
Dictionary d = p_state ;
2016-01-10 20:59:12 +00:00
if ( d . has ( " snap_enabled " ) ) {
2017-03-05 15:44:50 +00:00
snap_enabled = d [ " snap_enabled " ] ;
2018-01-10 20:22:49 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_pressed ( d [ " snap_enabled " ] ) ;
2016-01-10 20:59:12 +00:00
}
2020-05-14 14:41:43 +00:00
if ( d . has ( " translate_snap " ) ) {
2020-03-08 19:31:11 +00:00
snap_translate_value = d [ " translate_snap " ] ;
2020-05-14 14:41:43 +00:00
}
2016-01-10 20:59:12 +00:00
2020-05-14 14:41:43 +00:00
if ( d . has ( " rotate_snap " ) ) {
2020-03-08 19:31:11 +00:00
snap_rotate_value = d [ " rotate_snap " ] ;
2020-05-14 14:41:43 +00:00
}
2016-01-10 20:59:12 +00:00
2020-05-14 14:41:43 +00:00
if ( d . has ( " scale_snap " ) ) {
2020-03-08 19:31:11 +00:00
snap_scale_value = d [ " scale_snap " ] ;
2020-05-14 14:41:43 +00:00
}
2020-03-08 19:31:11 +00:00
_snap_update ( ) ;
2016-01-10 20:59:12 +00:00
if ( d . has ( " local_coords " ) ) {
2017-11-18 18:51:37 +00:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_pressed ( d [ " local_coords " ] ) ;
2016-01-10 20:59:12 +00:00
update_transform_gizmo ( ) ;
}
2016-01-11 13:35:11 +00:00
if ( d . has ( " viewport_mode " ) ) {
int vc = d [ " viewport_mode " ] ;
2020-05-14 14:41:43 +00:00
if ( vc = = 1 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2020-05-14 14:41:43 +00:00
} else if ( vc = = 2 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS ) ;
2020-05-14 14:41:43 +00:00
} else if ( vc = = 3 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS ) ;
2020-05-14 14:41:43 +00:00
} else if ( vc = = 4 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_4_VIEWPORTS ) ;
2020-05-14 14:41:43 +00:00
} else if ( vc = = 5 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
2020-05-14 14:41:43 +00:00
} else if ( vc = = 6 ) {
2016-01-11 13:35:11 +00:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
2020-05-14 14:41:43 +00:00
}
2016-01-11 13:35:11 +00:00
}
2014-02-10 01:10:30 +00:00
2016-01-11 13:35:11 +00:00
if ( d . has ( " viewports " ) ) {
Array vp = d [ " viewports " ] ;
2019-03-12 02:17:30 +00:00
uint32_t vp_size = static_cast < uint32_t > ( vp . size ( ) ) ;
if ( vp_size > VIEWPORTS_COUNT ) {
2019-06-11 12:49:34 +00:00
WARN_PRINT ( " Ignoring superfluous viewport settings from spatial editor state. " ) ;
2019-03-12 02:17:30 +00:00
vp_size = VIEWPORTS_COUNT ;
}
2014-02-10 01:10:30 +00:00
2019-03-12 02:17:30 +00:00
for ( uint32_t i = 0 ; i < vp_size ; i + + ) {
2016-01-11 13:35:11 +00:00
viewports [ i ] - > set_state ( vp [ i ] ) ;
}
2014-02-10 01:10:30 +00:00
}
2020-05-14 14:41:43 +00:00
if ( d . has ( " zfar " ) ) {
2021-06-21 03:30:19 +00:00
settings_zfar - > set_value ( double ( d [ " zfar " ] ) ) ;
2020-05-14 14:41:43 +00:00
}
if ( d . has ( " znear " ) ) {
2021-06-21 03:30:19 +00:00
settings_znear - > set_value ( double ( d [ " znear " ] ) ) ;
2020-05-14 14:41:43 +00:00
}
if ( d . has ( " fov " ) ) {
2021-06-21 03:30:19 +00:00
settings_fov - > set_value ( double ( d [ " fov " ] ) ) ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
if ( d . has ( " show_grid " ) ) {
bool use = d [ " show_grid " ] ;
2017-03-05 15:44:50 +00:00
if ( use ! = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_GRID ) ) ) {
2014-07-15 07:06:55 +00:00
_menu_item_pressed ( MENU_VIEW_GRID ) ;
2014-02-10 01:10:30 +00:00
}
}
if ( d . has ( " show_origin " ) ) {
bool use = d [ " show_origin " ] ;
2017-03-05 15:44:50 +00: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 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , use ) ;
2014-02-10 01:10:30 +00:00
}
}
2018-07-24 22:08:49 +00:00
if ( d . has ( " gizmos_status " ) ) {
Dictionary gizmos_status = d [ " gizmos_status " ] ;
List < Variant > keys ;
gizmos_status . get_key_list ( & keys ) ;
2019-03-11 23:30:50 +00:00
for ( int j = 0 ; j < gizmo_plugins_by_name . size ( ) ; + + j ) {
2020-05-14 14:41:43 +00:00
if ( ! gizmo_plugins_by_name [ j ] - > can_be_hidden ( ) ) {
2020-05-10 10:56:01 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2020-03-26 21:49:16 +00:00
int state = EditorNode3DGizmoPlugin : : VISIBLE ;
2018-09-26 15:38:02 +00:00
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
2021-03-01 01:52:53 +00:00
if ( gizmo_plugins_by_name . write [ j ] - > get_gizmo_name ( ) = = String ( keys [ i ] ) ) {
2018-08-11 21:07:00 +00:00
state = gizmos_status [ keys [ i ] ] ;
2019-03-11 23:30:50 +00:00
break ;
2018-07-24 22:08:49 +00:00
}
}
2018-08-11 21:07:00 +00:00
2019-03-11 23:30:50 +00:00
gizmo_plugins_by_name . write [ j ] - > set_state ( state ) ;
2018-07-24 22:08:49 +00:00
}
2019-03-11 23:30:50 +00:00
_update_gizmos_menu ( ) ;
2018-07-24 22:08:49 +00:00
}
2021-02-22 13:54:12 +00:00
if ( d . has ( " preview_sun_env " ) ) {
sun_environ_updating = true ;
Dictionary pd = d [ " preview_sun_env " ] ;
sun_rotation = pd [ " sun_rotation " ] ;
environ_sky_color - > set_pick_color ( pd [ " environ_sky_color " ] ) ;
environ_ground_color - > set_pick_color ( pd [ " environ_ground_color " ] ) ;
environ_energy - > set_value ( pd [ " environ_energy " ] ) ;
environ_glow_button - > set_pressed ( pd [ " environ_glow_enabled " ] ) ;
environ_tonemap_button - > set_pressed ( pd [ " environ_tonemap_enabled " ] ) ;
environ_ao_button - > set_pressed ( pd [ " environ_ao_enabled " ] ) ;
environ_gi_button - > set_pressed ( pd [ " environ_gi_enabled " ] ) ;
sun_max_distance - > set_value ( pd [ " sun_max_distance " ] ) ;
sun_color - > set_pick_color ( pd [ " sun_color " ] ) ;
sun_energy - > set_value ( pd [ " sun_energy " ] ) ;
sun_button - > set_pressed ( pd [ " sun_disabled " ] ) ;
environ_button - > set_pressed ( pd [ " environ_disabled " ] ) ;
sun_environ_updating = false ;
_preview_settings_changed ( ) ;
_update_preview_environment ( ) ;
} else {
_load_default_preview_settings ( ) ;
sun_button - > set_pressed ( false ) ;
environ_button - > set_pressed ( false ) ;
_preview_settings_changed ( ) ;
_update_preview_environment ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : edit ( Node3D * p_spatial ) {
2017-03-05 15:44:50 +00:00
if ( p_spatial ! = selected ) {
2014-05-05 01:50:23 +00:00
if ( selected ) {
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = selected - > get_gizmos ( ) ;
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
}
2014-05-05 01:50:23 +00:00
seg - > set_selected ( false ) ;
}
2021-06-23 14:49:50 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) ;
if ( se ) {
se - > gizmo . unref ( ) ;
se - > subgizmos . clear ( ) ;
}
selected - > update_gizmos ( ) ;
2014-05-05 01:50:23 +00:00
}
2017-03-05 15:44:50 +00:00
selected = p_spatial ;
2021-06-23 14:49:50 +00:00
current_hover_gizmo = Ref < EditorNode3DGizmo > ( ) ;
current_hover_gizmo_handle = - 1 ;
2022-01-11 11:33:37 +00:00
current_hover_gizmo_handle_secondary = false ;
2014-05-05 01:50:23 +00:00
if ( selected ) {
2021-06-23 14:49:50 +00:00
Vector < Ref < Node3DGizmo > > gizmos = selected - > get_gizmos ( ) ;
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
}
2014-05-05 01:50:23 +00:00
seg - > set_selected ( true ) ;
}
2021-06-23 14:49:50 +00:00
selected - > update_gizmos ( ) ;
2014-05-05 01:50:23 +00:00
}
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _snap_changed ( ) {
2020-07-24 18:07:57 +00: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 19:31:11 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _snap_update ( ) {
2020-03-08 19:31:11 +00: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 21:49:16 +00:00
void Node3DEditor : : _xform_dialog_action ( ) {
2020-10-17 05:08:21 +00:00
Transform3D t ;
2014-02-10 01:10:30 +00:00
//translation
Vector3 scale ;
Vector3 rotate ;
Vector3 translate ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-07-24 18:07:57 +00: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 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
2017-01-05 17:31:39 +00:00
t . basis . scale ( scale ) ;
t . basis . rotate ( rotate ) ;
2017-03-05 15:44:50 +00:00
t . origin = translate ;
2014-02-10 01:10:30 +00:00
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " XForm Dialog " ) ) ;
2014-02-10 01:10:30 +00:00
2022-04-07 10:23:40 +00:00
const List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2014-02-10 01:10:30 +00:00
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
2020-05-14 14:41:43 +00:00
if ( ! se ) {
2014-02-10 01:10:30 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
bool post = xform_type - > get_selected ( ) > 0 ;
2014-02-10 01:10:30 +00:00
2020-10-17 05:08:21 +00:00
Transform3D tr = sp - > get_global_gizmo_transform ( ) ;
2020-05-14 14:41:43 +00:00
if ( post ) {
2014-02-10 01:10:30 +00:00
tr = tr * t ;
2020-05-14 14:41:43 +00:00
} else {
2014-02-10 01:10:30 +00:00
tr . basis = t . basis * tr . basis ;
2017-03-05 15:44:50 +00:00
tr . origin + = t . origin ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( sp , " set_global_transform " , tr ) ;
2017-10-03 16:49:32 +00:00
undo_redo - > add_undo_method ( sp , " set_global_transform " , sp - > get_global_gizmo_transform ( ) ) ;
2014-02-10 01:10:30 +00:00
}
undo_redo - > commit_action ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _menu_item_toggled ( bool pressed , int p_option ) {
2017-11-18 18:51:37 +00: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 20:55:01 +00:00
case MENU_TOOL_OVERRIDE_CAMERA : {
2020-02-07 01:52:05 +00:00
EditorDebuggerNode * const debugger = EditorDebuggerNode : : get_singleton ( ) ;
2019-04-06 20:55:01 +00:00
2020-02-24 05:21:15 +00:00
using Override = EditorDebuggerNode : : CameraOverride ;
2019-04-06 20:55:01 +00:00
if ( pressed ) {
debugger - > set_camera_override ( ( Override ) ( Override : : OVERRIDE_3D_1 + camera_override_viewport_id ) ) ;
} else {
2020-02-24 05:21:15 +00:00
debugger - > set_camera_override ( Override : : OVERRIDE_NONE ) ;
2019-04-06 20:55:01 +00:00
}
} break ;
2017-11-18 18:51:37 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _menu_gizmo_toggled ( int p_option ) {
2018-08-11 21:07:00 +00: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 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( SNAME ( " visibility_visible " ) ) ) ;
2018-08-11 21:07:00 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( SNAME ( " visibility_xray " ) ) ) ;
2018-08-11 21:07:00 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , view_menu - > get_popup ( ) - > get_theme_icon ( SNAME ( " visibility_hidden " ) ) ) ;
2018-08-11 21:07:00 +00:00
break ;
}
2019-03-11 23:30:50 +00:00
gizmo_plugins_by_name . write [ p_option ] - > set_state ( state ) ;
2018-07-24 22:08:49 +00:00
2018-08-11 21:07:00 +00:00
update_all_gizmos ( ) ;
2018-07-24 22:08:49 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _update_camera_override_button ( bool p_game_running ) {
2019-04-06 20:55:01 +00:00
Button * const button = tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] ;
if ( p_game_running ) {
button - > set_disabled ( false ) ;
2021-06-12 17:39:34 +00:00
button - > set_tooltip ( TTR ( " Project Camera Override \n Overrides the running project's camera with the editor viewport camera. " ) ) ;
2019-04-06 20:55:01 +00:00
} else {
button - > set_disabled ( true ) ;
button - > set_pressed ( false ) ;
2021-06-12 17:39:34 +00:00
button - > set_tooltip ( TTR ( " Project Camera Override \n No project instance running. Run the project from the editor to use this feature. " ) ) ;
2019-04-06 20:55:01 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _update_camera_override_viewport ( Object * p_viewport ) {
Node3DEditorViewport * current_viewport = Object : : cast_to < Node3DEditorViewport > ( p_viewport ) ;
2019-04-06 20:55:01 +00:00
2020-05-14 14:41:43 +00:00
if ( ! current_viewport ) {
2019-04-06 20:55:01 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2019-04-06 20:55:01 +00:00
2020-02-07 01:52:05 +00:00
EditorDebuggerNode * const debugger = EditorDebuggerNode : : get_singleton ( ) ;
2019-04-06 20:55:01 +00:00
camera_override_viewport_id = current_viewport - > index ;
2020-02-24 05:21:15 +00:00
if ( debugger - > get_camera_override ( ) > = EditorDebuggerNode : : OVERRIDE_3D_1 ) {
using Override = EditorDebuggerNode : : CameraOverride ;
2019-04-06 20:55:01 +00:00
debugger - > set_camera_override ( ( Override ) ( Override : : OVERRIDE_3D_1 + camera_override_viewport_id ) ) ;
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _menu_item_pressed ( int p_option ) {
2017-03-05 15:44:50 +00:00
switch ( p_option ) {
2014-02-10 01:10:30 +00:00
case MENU_TOOL_SELECT :
case MENU_TOOL_MOVE :
case MENU_TOOL_ROTATE :
2015-12-13 20:16:13 +00:00
case MENU_TOOL_SCALE :
case MENU_TOOL_LIST_SELECT : {
2020-05-14 14:41:43 +00:00
for ( int i = 0 ; i < TOOL_MAX ; i + + ) {
2017-03-05 15:44:50 +00:00
tool_button [ i ] - > set_pressed ( i = = p_option ) ;
2020-05-14 14:41:43 +00:00
}
2017-03-05 15:44:50 +00:00
tool_mode = ( ToolMode ) p_option ;
2014-02-10 01:10:30 +00:00
update_transform_gizmo ( ) ;
} break ;
case MENU_TRANSFORM_CONFIGURE_SNAP : {
2017-03-05 15:44:50 +00:00
snap_dialog - > popup_centered ( Size2 ( 200 , 180 ) ) ;
2014-02-10 01:10:30 +00:00
} break ;
case MENU_TRANSFORM_DIALOG : {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2014-02-10 01:10:30 +00:00
xform_translate [ i ] - > set_text ( " 0 " ) ;
xform_rotate [ i ] - > set_text ( " 0 " ) ;
xform_scale [ i ] - > set_text ( " 1 " ) ;
}
2017-07-31 13:00:02 +00:00
xform_dialog - > popup_centered ( Size2 ( 320 , 240 ) * EDSCALE ) ;
2014-02-10 01:10:30 +00:00
} break ;
case MENU_VIEW_USE_1_VIEWPORT : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_1_VIEWPORT ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
} break ;
case MENU_VIEW_USE_2_VIEWPORTS : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_2_VIEWPORTS ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 03:06:51 +00:00
} break ;
case MENU_VIEW_USE_2_VIEWPORTS_ALT : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_2_VIEWPORTS_ALT ) ;
2014-10-09 03:06:51 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
} break ;
case MENU_VIEW_USE_3_VIEWPORTS : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_3_VIEWPORTS ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 03:06:51 +00:00
} break ;
case MENU_VIEW_USE_3_VIEWPORTS_ALT : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_3_VIEWPORTS_ALT ) ;
2014-10-09 03:06:51 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
} break ;
case MENU_VIEW_USE_4_VIEWPORTS : {
2020-03-26 21:49:16 +00:00
viewport_base - > set_view ( Node3DEditorViewportContainer : : VIEW_USE_4_VIEWPORTS ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
} break ;
case MENU_VIEW_ORIGIN : {
2017-03-05 15:44:50 +00:00
bool is_checked = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) ) ;
2014-02-10 01:10:30 +00:00
2018-08-17 21:21:08 +00:00
origin_enabled = ! is_checked ;
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , origin_enabled ) ;
2018-08-17 21:21:08 +00:00
// Update the grid since its appearance depends on whether the origin is enabled
_finish_grid ( ) ;
_init_grid ( ) ;
2014-02-10 01:10:30 +00:00
2018-08-17 21:21:08 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) , origin_enabled ) ;
2014-02-10 01:10:30 +00:00
} break ;
case MENU_VIEW_GRID : {
2017-03-05 15:44:50 +00:00
bool is_checked = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
grid_enabled = ! is_checked ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; + + i ) {
2014-07-15 05:29:03 +00:00
if ( grid_enable [ i ] ) {
2017-03-05 15:44:50 +00:00
grid_visible [ i ] = grid_enabled ;
2014-07-15 05:29:03 +00:00
}
}
2020-11-19 10:29:37 +00:00
_finish_grid ( ) ;
_init_grid ( ) ;
2014-07-15 05:29:03 +00:00
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( p_option ) , grid_enabled ) ;
2022-02-09 08:39:28 +00:00
2014-02-10 01:10:30 +00:00
} break ;
case MENU_VIEW_CAMERA_SETTINGS : {
2017-03-05 15:44:50 +00:00
settings_dialog - > popup_centered ( settings_vbc - > get_combined_minimum_size ( ) + Size2 ( 50 , 50 ) ) ;
2014-02-10 01:10:30 +00:00
} break ;
2018-07-26 06:34:40 +00:00
case MENU_SNAP_TO_FLOOR : {
snap_selected_nodes_to_floor ( ) ;
} break ;
2017-10-23 19:21:15 +00:00
case MENU_LOCK_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Lock Selected " ) ) ;
2017-10-23 19:21:15 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * spatial = Object : : cast_to < Node3D > ( E ) ;
2020-06-24 15:09:53 +00:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2017-10-23 19:21:15 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-10-23 19:21:15 +00:00
2020-05-14 14:41:43 +00:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2017-10-23 19:21:15 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-10-23 19:21:15 +00:00
2019-04-26 17:23:50 +00: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 19:21:15 +00:00
}
2020-06-24 15:09:53 +00:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 17:23:50 +00:00
undo_redo - > commit_action ( ) ;
2017-10-23 19:21:15 +00:00
} break ;
case MENU_UNLOCK_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Unlock Selected " ) ) ;
2017-10-23 19:21:15 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * spatial = Object : : cast_to < Node3D > ( E ) ;
2020-06-24 15:09:53 +00:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2017-10-23 19:21:15 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-10-23 19:21:15 +00:00
2020-05-14 14:41:43 +00:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2017-10-23 19:21:15 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2017-10-23 19:21:15 +00:00
2019-04-26 17:23:50 +00: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 19:21:15 +00:00
}
2020-06-24 15:09:53 +00:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 17:23:50 +00:00
undo_redo - > commit_action ( ) ;
2019-04-17 16:24:28 +00:00
} break ;
case MENU_GROUP_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Group Selected " ) ) ;
2019-04-17 16:24:28 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * spatial = Object : : cast_to < Node3D > ( E ) ;
2020-06-24 15:09:53 +00:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2019-04-17 16:24:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-04-17 16:24:28 +00:00
2020-05-14 14:41:43 +00:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2019-04-17 16:24:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-04-17 16:24:28 +00:00
2019-04-26 17:23:50 +00: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 16:24:28 +00:00
}
2020-06-24 15:09:53 +00:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 17:23:50 +00:00
undo_redo - > commit_action ( ) ;
2019-04-17 16:24:28 +00:00
} break ;
case MENU_UNGROUP_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Ungroup Selected " ) ) ;
2019-04-17 16:24:28 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * spatial = Object : : cast_to < Node3D > ( E ) ;
2020-06-24 15:09:53 +00:00
if ( ! spatial | | ! spatial - > is_inside_tree ( ) ) {
2019-04-17 16:24:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-04-17 16:24:28 +00:00
2020-05-14 14:41:43 +00:00
if ( spatial - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2019-04-17 16:24:28 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-04-17 16:24:28 +00:00
2019-04-26 17:23:50 +00: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 16:24:28 +00:00
}
2020-06-24 15:09:53 +00:00
undo_redo - > add_do_method ( this , " _refresh_menu_icons " ) ;
undo_redo - > add_undo_method ( this , " _refresh_menu_icons " ) ;
2019-04-26 17:23:50 +00:00
undo_redo - > commit_action ( ) ;
2017-10-23 19:21:15 +00:00
} break ;
2014-02-10 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _init_indicators ( ) {
2014-02-10 01:10:30 +00:00
{
2018-09-20 11:27:32 +00:00
origin_enabled = true ;
grid_enabled = true ;
2014-02-10 01:10:30 +00:00
2021-06-17 22:03:09 +00:00
indicator_mat . instantiate ( ) ;
2019-09-15 04:01:52 +00: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 10:15:45 +00:00
indicator_mat - > set_transparency ( StandardMaterial3D : : Transparency : : TRANSPARENCY_ALPHA_DEPTH_PRE_PASS ) ;
2016-10-29 23:48:09 +00:00
2014-02-10 01:10:30 +00:00
Vector < Color > origin_colors ;
Vector < Vector3 > origin_points ;
2021-08-08 15:08:37 +00:00
const int count_of_elements = 3 * 6 ;
origin_colors . resize ( count_of_elements ) ;
origin_points . resize ( count_of_elements ) ;
int x = 0 ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2014-02-10 01:10:30 +00:00
Vector3 axis ;
2017-03-05 15:44:50 +00:00
axis [ i ] = 1 ;
2019-08-23 16:14:47 +00:00
Color origin_color ;
switch ( i ) {
case 0 :
2021-07-17 21:22:52 +00:00
origin_color = get_theme_color ( SNAME ( " axis_x_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
case 1 :
2021-07-17 21:22:52 +00:00
origin_color = get_theme_color ( SNAME ( " axis_y_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
case 2 :
2021-07-17 21:22:52 +00:00
origin_color = get_theme_color ( SNAME ( " axis_z_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
default :
origin_color = Color ( ) ;
break ;
}
2017-12-08 22:45:33 +00:00
grid_enable [ i ] = false ;
grid_visible [ i ] = false ;
2014-02-10 01:10:30 +00:00
2021-08-08 15:08:37 +00:00
origin_colors . set ( x , origin_color ) ;
origin_colors . set ( x + 1 , origin_color ) ;
origin_colors . set ( x + 2 , origin_color ) ;
origin_colors . set ( x + 3 , origin_color ) ;
origin_colors . set ( x + 4 , origin_color ) ;
origin_colors . set ( x + 5 , origin_color ) ;
2019-04-21 10:15:45 +00:00
// 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.
2021-08-08 15:08:37 +00:00
origin_points . set ( x , axis * 1048576 ) ;
origin_points . set ( x + 1 , axis * 1024 ) ;
origin_points . set ( x + 2 , axis * 1024 ) ;
origin_points . set ( x + 3 , axis * - 1024 ) ;
origin_points . set ( x + 4 , axis * - 1024 ) ;
origin_points . set ( x + 5 , axis * - 1048576 ) ;
x + = 6 ;
2019-04-21 10:15:45 +00:00
}
2021-01-29 15:12:50 +00:00
Ref < Shader > grid_shader = memnew ( Shader ) ;
2021-07-19 06:06:51 +00:00
grid_shader - > set_code ( R " (
2021-08-18 01:09:22 +00:00
// 3D editor grid shader.
2021-07-19 06:06:51 +00:00
shader_type spatial ;
render_mode unshaded ;
uniform bool orthogonal ;
uniform float grid_size ;
void vertex ( ) {
// From FLAG_SRGB_VERTEX_COLOR.
if ( ! OUTPUT_IS_SRGB ) {
COLOR . rgb = mix ( pow ( ( COLOR . rgb + vec3 ( 0.055 ) ) * ( 1.0 / ( 1.0 + 0.055 ) ) , vec3 ( 2.4 ) ) , COLOR . rgb * ( 1.0 / 12.92 ) , lessThan ( COLOR . rgb , vec3 ( 0.04045 ) ) ) ;
}
}
void fragment ( ) {
ALBEDO = COLOR . rgb ;
vec3 dir = orthogonal ? - vec3 ( 0 , 0 , 1 ) : VIEW ;
float angle_fade = abs ( dot ( dir , NORMAL ) ) ;
angle_fade = smoothstep ( 0.05 , 0.2 , angle_fade ) ;
2022-03-18 09:10:55 +00:00
vec3 world_pos = ( INV_VIEW_MATRIX * vec4 ( VERTEX , 1.0 ) ) . xyz ;
vec3 world_normal = ( INV_VIEW_MATRIX * vec4 ( NORMAL , 0.0 ) ) . xyz ;
vec3 camera_world_pos = INV_VIEW_MATRIX [ 3 ] . xyz ;
2021-07-19 06:06:51 +00:00
vec3 camera_world_pos_on_plane = camera_world_pos * ( 1.0 - world_normal ) ;
float dist_fade = 1.0 - ( distance ( world_pos , camera_world_pos_on_plane ) / grid_size ) ;
dist_fade = smoothstep ( 0.02 , 0.3 , dist_fade ) ;
ALPHA = COLOR . a * dist_fade * angle_fade ;
}
) " );
2021-01-29 15:12:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2021-06-17 22:03:09 +00:00
grid_mat [ i ] . instantiate ( ) ;
2021-01-29 15:12:50 +00:00
grid_mat [ i ] - > set_shader ( grid_shader ) ;
}
2019-04-21 10:15:45 +00:00
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 15:44:50 +00:00
2017-12-08 22:45:33 +00:00
_init_grid ( ) ;
2014-02-10 01:10:30 +00:00
2020-03-27 18:21:27 +00:00
origin = RenderingServer : : get_singleton ( ) - > mesh_create ( ) ;
2014-02-10 01:10:30 +00:00
Array d ;
2020-03-27 18:21:27 +00:00
d . resize ( RS : : ARRAY_MAX ) ;
d [ RenderingServer : : ARRAY_VERTEX ] = origin_points ;
d [ RenderingServer : : ARRAY_COLOR ] = origin_colors ;
2014-02-10 01:10:30 +00:00
2020-03-27 18:21:27 +00: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 01:10:30 +00:00
2020-04-18 09:00:51 +00:00
origin_instance = RenderingServer : : get_singleton ( ) - > instance_create2 ( origin , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2020-03-27 18:21:27 +00:00
RS : : get_singleton ( ) - > instance_set_layer_mask ( origin_instance , 1 < < Node3DEditorViewport : : GIZMO_GRID_LAYER ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( origin_instance , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( origin_instance , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2014-10-16 03:06:34 +00:00
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > instance_geometry_set_cast_shadows_setting ( origin_instance , RS : : SHADOW_CASTING_SETTING_OFF ) ;
2014-02-10 01:10:30 +00:00
}
{
//move gizmo
2021-10-09 10:24:26 +00:00
// Inverted zxy.
Vector3 ivec = Vector3 ( 0 , 0 , - 1 ) ;
Vector3 nivec = Vector3 ( - 1 , - 1 , 0 ) ;
Vector3 ivec2 = Vector3 ( - 1 , 0 , 0 ) ;
Vector3 ivec3 = Vector3 ( 0 , - 1 , 0 ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2019-08-23 16:14:47 +00:00
Color col ;
switch ( i ) {
case 0 :
2021-07-17 21:22:52 +00:00
col = get_theme_color ( SNAME ( " axis_x_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
case 1 :
2021-07-17 21:22:52 +00:00
col = get_theme_color ( SNAME ( " axis_y_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
case 2 :
2021-07-17 21:22:52 +00:00
col = get_theme_color ( SNAME ( " axis_z_color " ) , SNAME ( " Editor " ) ) ;
2019-08-23 16:14:47 +00:00
break ;
default :
col = Color ( ) ;
break ;
}
2019-08-01 12:23:29 +00:00
col . a = EditorSettings : : get_singleton ( ) - > get ( " editors/3d/manipulator_gizmo_opacity " ) ;
2017-06-07 21:18:55 +00:00
move_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-08-29 01:39:45 +00:00
move_plane_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-06-07 21:18:55 +00:00
rotate_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-09-21 21:11:56 +00:00
scale_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2017-11-14 22:50:19 +00:00
scale_plane_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2020-07-18 19:03:08 +00:00
axis_gizmo [ i ] = Ref < ArrayMesh > ( memnew ( ArrayMesh ) ) ;
2014-02-10 01:10:30 +00:00
2019-09-15 04:01:52 +00:00
Ref < StandardMaterial3D > mat = memnew ( StandardMaterial3D ) ;
mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-09-01 15:56:52 +00:00
mat - > set_on_top_of_alpha ( ) ;
2019-09-15 04:01:52 +00:00
mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
2016-10-27 14:50:26 +00:00
mat - > set_albedo ( col ) ;
2017-03-05 15:44:50 +00:00
gizmo_color [ i ] = mat ;
2014-02-10 01:10:30 +00:00
2019-09-15 04:01:52 +00:00
Ref < StandardMaterial3D > mat_hl = mat - > duplicate ( ) ;
2021-07-18 22:09:59 +00:00
const Color albedo = col . from_hsv ( col . get_h ( ) , 0.25 , 1.0 , 1 ) ;
2020-12-18 15:28:12 +00:00
mat_hl - > set_albedo ( albedo ) ;
2019-08-01 12:23:29 +00:00
gizmo_color_hl [ i ] = mat_hl ;
2017-09-21 21:11:56 +00:00
//translate
2014-02-10 01:10:30 +00:00
{
2017-03-05 15:44:50 +00:00
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
2014-02-10 01:10:30 +00:00
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2017-09-21 21:11:56 +00:00
// Arrow profile
2017-03-05 15:44:50 +00:00
const int arrow_points = 5 ;
Vector3 arrow [ 5 ] = {
nivec * 0.0 + ivec * 0.0 ,
nivec * 0.01 + ivec * 0.0 ,
2017-09-21 21:11:56 +00: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 01:10:30 +00:00
} ;
2018-08-09 14:34:18 +00:00
int arrow_sides = 16 ;
2014-02-10 01:10:30 +00:00
2020-04-03 09:50:40 +00:00
const real_t arrow_sides_step = Math_TAU / arrow_sides ;
2018-08-09 14:34:18 +00:00
for ( int k = 0 ; k < arrow_sides ; k + + ) {
2020-04-03 09:50:40 +00:00
Basis ma ( ivec , k * arrow_sides_step ) ;
Basis mb ( ivec , ( k + 1 ) * arrow_sides_step ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int j = 0 ; j < arrow_points - 1 ; j + + ) {
Vector3 points [ 4 ] = {
2014-02-10 01:10:30 +00:00
ma . xform ( arrow [ j ] ) ,
mb . xform ( arrow [ j ] ) ,
2017-03-05 15:44:50 +00:00
mb . xform ( arrow [ j + 1 ] ) ,
ma . xform ( arrow [ j + 1 ] ) ,
2014-02-10 01:10:30 +00: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 21:11:56 +00:00
// Plane Translation
2017-08-29 01:39:45 +00: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 04:01:52 +00:00
Ref < StandardMaterial3D > plane_mat = memnew ( StandardMaterial3D ) ;
plane_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-09-01 15:56:52 +00:00
plane_mat - > set_on_top_of_alpha ( ) ;
2019-09-15 04:01:52 +00:00
plane_mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
plane_mat - > set_cull_mode ( StandardMaterial3D : : CULL_DISABLED ) ;
2019-08-01 12:23:29 +00:00
plane_mat - > set_albedo ( col ) ;
2017-08-29 01:39:45 +00: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 12:23:29 +00:00
2019-09-15 04:01:52 +00:00
Ref < StandardMaterial3D > plane_mat_hl = plane_mat - > duplicate ( ) ;
2020-12-18 15:28:12 +00:00
plane_mat_hl - > set_albedo ( albedo ) ;
2019-08-01 12:23:29 +00:00
plane_gizmo_color_hl [ i ] = plane_mat_hl ; // needed, so we can draw planes from both sides
2017-08-29 01:39:45 +00:00
}
2017-09-21 21:11:56 +00:00
// Rotate
2014-02-10 01:10:30 +00:00
{
2017-03-05 15:44:50 +00:00
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
2014-02-10 01:10:30 +00:00
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2020-09-13 16:22:51 +00:00
int n = 128 ; // number of circle segments
2021-07-18 22:09:59 +00:00
int m = 3 ; // number of thickness segments
2014-02-10 01:10:30 +00:00
2020-04-03 09:50:40 +00:00
real_t step = Math_TAU / n ;
2020-09-13 16:22:51 +00:00
for ( int j = 0 ; j < n ; + + j ) {
2020-04-03 09:50:40 +00:00
Basis basis = Basis ( ivec , j * step ) ;
2014-02-10 01:10:30 +00:00
2020-09-13 16:22:51 +00:00
Vector3 vertex = basis . xform ( ivec2 * GIZMO_CIRCLE_SIZE ) ;
2014-02-10 01:10:30 +00:00
2020-09-13 16:22:51 +00:00
for ( int k = 0 ; k < m ; + + k ) {
2020-04-03 09:50:40 +00:00
Vector2 ofs = Vector2 ( Math : : cos ( ( Math_TAU * k ) / m ) , Math : : sin ( ( Math_TAU * k ) / m ) ) ;
2020-09-13 16:22:51 +00:00
Vector3 normal = ivec * ofs . x + ivec2 * ofs . y ;
2020-12-02 01:40:47 +00:00
surftool - > set_normal ( basis . xform ( normal ) ) ;
2020-09-13 16:22:51 +00:00
surftool - > add_vertex ( vertex ) ;
2014-02-10 01:10:30 +00:00
}
}
2020-09-13 16:22:51 +00: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 ) ;
2021-07-19 06:06:51 +00:00
rotate_shader - > set_code ( R " (
2021-08-18 01:09:22 +00:00
// 3D editor rotation manipulator gizmo shader.
2021-07-19 06:06:51 +00:00
shader_type spatial ;
render_mode unshaded , depth_test_disabled ;
uniform vec4 albedo ;
mat3 orthonormalize ( mat3 m ) {
vec3 x = normalize ( m [ 0 ] ) ;
vec3 y = normalize ( m [ 1 ] - x * dot ( x , m [ 1 ] ) ) ;
vec3 z = m [ 2 ] - x * dot ( x , m [ 2 ] ) ;
z = normalize ( z - y * ( dot ( y , m [ 2 ] ) ) ) ;
return mat3 ( x , y , z ) ;
}
void vertex ( ) {
mat3 mv = orthonormalize ( mat3 ( MODELVIEW_MATRIX ) ) ;
vec3 n = mv * VERTEX ;
float orientation = dot ( vec3 ( 0 , 0 , - 1 ) , n ) ;
if ( orientation < = 0.005 ) {
VERTEX + = NORMAL * 0.02 ;
}
}
void fragment ( ) {
ALBEDO = albedo . rgb ;
ALPHA = albedo . a ;
}
) " );
2020-09-13 16:22:51 +00:00
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 15:28:12 +00:00
rotate_mat_hl - > set_shader_param ( " albedo " , albedo ) ;
2020-09-13 16:22:51 +00: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 ) ;
2021-07-19 06:06:51 +00:00
border_shader - > set_code ( R " (
2021-08-18 01:09:22 +00:00
// 3D editor rotation manipulator gizmo shader (white outline).
2021-07-19 06:06:51 +00:00
shader_type spatial ;
render_mode unshaded , depth_test_disabled ;
uniform vec4 albedo ;
mat3 orthonormalize ( mat3 m ) {
vec3 x = normalize ( m [ 0 ] ) ;
vec3 y = normalize ( m [ 1 ] - x * dot ( x , m [ 1 ] ) ) ;
vec3 z = m [ 2 ] - x * dot ( x , m [ 2 ] ) ;
z = normalize ( z - y * ( dot ( y , m [ 2 ] ) ) ) ;
return mat3 ( x , y , z ) ;
}
void vertex ( ) {
mat3 mv = orthonormalize ( mat3 ( MODELVIEW_MATRIX ) ) ;
mv = inverse ( mv ) ;
VERTEX + = NORMAL * 0.008 ;
vec3 camera_dir_local = mv * vec3 ( 0 , 0 , 1 ) ;
vec3 camera_up_local = mv * vec3 ( 0 , 1 , 0 ) ;
mat3 rotation_matrix = mat3 ( cross ( camera_dir_local , camera_up_local ) , camera_up_local , camera_dir_local ) ;
VERTEX = rotation_matrix * VERTEX ;
}
void fragment ( ) {
ALBEDO = albedo . rgb ;
ALPHA = albedo . a ;
}
) " );
2020-09-13 16:22:51 +00:00
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 01:10:30 +00:00
}
2017-09-21 21:11:56 +00:00
// Scale
{
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
surftool - > begin ( Mesh : : PRIMITIVE_TRIANGLES ) ;
2014-05-05 01:50:23 +00:00
2017-09-21 21:11:56 +00: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 01:10:30 +00:00
2017-09-21 21:11:56 +00:00
int arrow_sides = 4 ;
2020-04-03 09:50:40 +00:00
const real_t arrow_sides_step = Math_TAU / arrow_sides ;
2017-09-21 21:11:56 +00:00
for ( int k = 0 ; k < 4 ; k + + ) {
2020-04-03 09:50:40 +00:00
Basis ma ( ivec , k * arrow_sides_step ) ;
Basis mb ( ivec , ( k + 1 ) * arrow_sides_step ) ;
2014-02-10 01:10:30 +00:00
2017-09-21 21:11:56 +00: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 22:50:19 +00: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 04:01:52 +00:00
Ref < StandardMaterial3D > plane_mat = memnew ( StandardMaterial3D ) ;
plane_mat - > set_shading_mode ( StandardMaterial3D : : SHADING_MODE_UNSHADED ) ;
2017-11-14 22:50:19 +00:00
plane_mat - > set_on_top_of_alpha ( ) ;
2019-09-15 04:01:52 +00:00
plane_mat - > set_transparency ( StandardMaterial3D : : TRANSPARENCY_ALPHA ) ;
plane_mat - > set_cull_mode ( StandardMaterial3D : : CULL_DISABLED ) ;
2019-08-01 12:23:29 +00:00
plane_mat - > set_albedo ( col ) ;
2017-11-14 22:50:19 +00: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 12:23:29 +00:00
2019-09-15 04:01:52 +00:00
Ref < StandardMaterial3D > plane_mat_hl = plane_mat - > duplicate ( ) ;
2021-07-18 22:09:59 +00:00
plane_mat_hl - > set_albedo ( col . from_hsv ( col . get_h ( ) , 0.25 , 1.0 , 1 ) ) ;
2019-08-01 12:23:29 +00:00
plane_gizmo_color_hl [ i ] = plane_mat_hl ; // needed, so we can draw planes from both sides
2017-11-14 22:50:19 +00:00
}
2020-07-18 19:03:08 +00:00
// Lines to visualize transforms locked to an axis/plane
{
Ref < SurfaceTool > surftool = memnew ( SurfaceTool ) ;
2022-02-11 21:59:32 +00:00
surftool - > begin ( Mesh : : PRIMITIVE_LINE_STRIP ) ;
2020-07-18 19:03:08 +00:00
Vector3 vec ;
vec [ i ] = 1 ;
// line extending through infinity(ish)
2022-02-11 21:59:32 +00:00
surftool - > add_vertex ( vec * - 1048576 ) ;
surftool - > add_vertex ( Vector3 ( ) ) ;
surftool - > add_vertex ( vec * 1048576 ) ;
2020-07-18 19:03:08 +00:00
surftool - > set_material ( mat_hl ) ;
surftool - > commit ( axis_gizmo [ i ] ) ;
}
2017-09-21 21:11:56 +00:00
}
}
2020-07-03 22:11:56 +00:00
_generate_selection_boxes ( ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _update_gizmos_menu ( ) {
2018-10-29 10:30:28 +00:00
gizmos_menu - > clear ( ) ;
2018-07-24 22:08:49 +00:00
2019-03-11 23:30:50 +00:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; + + i ) {
2020-05-14 14:41:43 +00:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 10:56:01 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2021-03-01 01:52:53 +00:00
String plugin_name = gizmo_plugins_by_name [ i ] - > get_gizmo_name ( ) ;
2019-03-11 23:30:50 +00:00
const int plugin_state = gizmo_plugins_by_name [ i ] - > get_state ( ) ;
2020-07-24 13:14:56 +00:00
gizmos_menu - > add_multistate_item ( plugin_name , 3 , plugin_state , i ) ;
2019-03-11 23:30:50 +00:00
const int idx = gizmos_menu - > get_item_index ( i ) ;
2020-06-07 13:34:01 +00: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-11 23:30:50 +00:00
switch ( plugin_state ) {
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_visible " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_xray " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_hidden " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
}
2018-07-24 22:08:49 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _update_gizmos_menu_theme ( ) {
2019-03-11 23:30:50 +00:00
for ( int i = 0 ; i < gizmo_plugins_by_name . size ( ) ; + + i ) {
2020-05-14 14:41:43 +00:00
if ( ! gizmo_plugins_by_name [ i ] - > can_be_hidden ( ) ) {
2020-05-10 10:56:01 +00:00
continue ;
2020-05-14 14:41:43 +00:00
}
2019-03-11 23:30:50 +00: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 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : VISIBLE :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_visible " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : ON_TOP :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_xray " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
2020-03-26 21:49:16 +00:00
case EditorNode3DGizmoPlugin : : HIDDEN :
2021-07-17 21:22:52 +00:00
gizmos_menu - > set_item_icon ( idx , gizmos_menu - > get_theme_icon ( SNAME ( " visibility_hidden " ) ) ) ;
2019-03-11 23:30:50 +00:00
break ;
}
2019-02-15 17:32:38 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _init_grid ( ) {
2019-04-21 10:15:45 +00:00
if ( ! grid_enabled ) {
return ;
}
Camera3D * camera = get_editor_viewport ( 0 ) - > camera ;
2020-12-08 17:35:30 +00:00
Vector3 camera_position = camera - > get_position ( ) ;
2019-04-21 10:15:45 +00:00
if ( camera_position = = Vector3 ( ) ) {
return ; // Camera3D is invalid, don't draw the grid.
}
2021-01-29 15:12:50 +00:00
bool orthogonal = camera - > get_projection ( ) = = Camera3D : : PROJECTION_ORTHOGONAL ;
2020-02-17 21:06:54 +00:00
Vector < Color > grid_colors [ 3 ] ;
Vector < Vector3 > grid_points [ 3 ] ;
2021-01-29 15:12:50 +00:00
Vector < Vector3 > grid_normals [ 3 ] ;
2017-12-08 22:45:33 +00:00
2018-04-29 23:43:20 +00: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 22:45:33 +00:00
2019-04-21 10:15:45 +00: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 " ) ;
2021-03-18 00:20:08 +00:00
// Default largest grid size is 8^2 when primary_grid_steps is 8 (64m apart, so primary grid lines are 512m apart).
2019-04-21 10:15:45 +00:00
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 ;
2021-01-29 15:12:50 +00:00
Vector3 normal ;
normal [ c ] = 1.0 ;
real_t camera_distance = Math : : abs ( camera_position [ c ] ) ;
if ( orthogonal ) {
camera_distance = camera - > get_size ( ) / 2.0 ;
2022-05-03 12:50:35 +00:00
Vector3 camera_direction = - camera - > get_global_transform ( ) . get_basis ( ) . get_column ( 2 ) ;
2021-04-08 14:26:14 +00:00
Plane grid_plane = Plane ( normal ) ;
2021-01-29 15:12:50 +00:00
Vector3 intersection ;
if ( grid_plane . intersects_ray ( camera_position , camera_direction , & intersection ) ) {
camera_position = intersection ;
}
}
real_t division_level = Math : : log ( Math : : abs ( camera_distance ) ) / Math : : log ( ( double ) primary_grid_steps ) + division_level_bias ;
real_t clamped_division_level = CLAMP ( division_level , division_level_min , division_level_max ) ;
real_t division_level_floored = Math : : floor ( clamped_division_level ) ;
real_t division_level_decimals = clamped_division_level - division_level_floored ;
2019-04-21 10:15:45 +00:00
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 ;
2021-01-29 15:12:50 +00:00
real_t fade_size = Math : : pow ( primary_grid_steps , division_level - 1.0 ) ;
real_t min_fade_size = Math : : pow ( primary_grid_steps , float ( division_level_min ) ) ;
real_t max_fade_size = Math : : pow ( primary_grid_steps , float ( division_level_max ) ) ;
fade_size = CLAMP ( fade_size , min_fade_size , max_fade_size ) ;
real_t grid_fade_size = ( grid_size - primary_grid_steps ) * fade_size ;
grid_mat [ c ] - > set_shader_param ( " grid_size " , grid_fade_size ) ;
grid_mat [ c ] - > set_shader_param ( " orthogonal " , orthogonal ) ;
2021-08-08 15:08:37 +00:00
// Cache these so we don't have to re-access memory.
Vector < Vector3 > & ref_grid = grid_points [ c ] ;
Vector < Vector3 > & ref_grid_normals = grid_normals [ c ] ;
Vector < Color > & ref_grid_colors = grid_colors [ c ] ;
// Count our elements same as code below it.
int expected_size = 0 ;
for ( int i = - grid_size ; i < = grid_size ; i + + ) {
const real_t position_a = center_a + i * small_step_size ;
const 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 ) ) ) {
expected_size + = 2 ;
}
if ( ! ( origin_enabled & & Math : : is_zero_approx ( position_b ) ) ) {
expected_size + = 2 ;
}
}
int idx = 0 ;
ref_grid . resize ( expected_size ) ;
ref_grid_normals . resize ( expected_size ) ;
ref_grid_colors . resize ( expected_size ) ;
2019-04-21 10:15:45 +00:00
// 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 ) ;
}
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 ;
2021-08-08 15:08:37 +00:00
ref_grid . set ( idx , line_bgn ) ;
ref_grid . set ( idx + 1 , line_end ) ;
ref_grid_colors . set ( idx , line_color ) ;
ref_grid_colors . set ( idx + 1 , line_color ) ;
ref_grid_normals . set ( idx , normal ) ;
ref_grid_normals . set ( idx + 1 , normal ) ;
idx + = 2 ;
2017-12-08 22:45:33 +00:00
}
2019-04-21 10:15:45 +00: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 ;
2021-08-08 15:08:37 +00:00
ref_grid . set ( idx , line_bgn ) ;
ref_grid . set ( idx + 1 , line_end ) ;
ref_grid_colors . set ( idx , line_color ) ;
ref_grid_colors . set ( idx + 1 , line_color ) ;
ref_grid_normals . set ( idx , normal ) ;
ref_grid_normals . set ( idx + 1 , normal ) ;
idx + = 2 ;
2019-04-21 10:15:45 +00:00
}
2017-12-08 22:45:33 +00:00
}
2019-04-21 10:15:45 +00:00
// Create a mesh from the pushed vector points and colors.
grid [ c ] = RenderingServer : : get_singleton ( ) - > mesh_create ( ) ;
2017-12-08 22:45:33 +00:00
Array d ;
2020-03-27 18:21:27 +00:00
d . resize ( RS : : ARRAY_MAX ) ;
2019-04-21 10:15:45 +00:00
d [ RenderingServer : : ARRAY_VERTEX ] = grid_points [ c ] ;
d [ RenderingServer : : ARRAY_COLOR ] = grid_colors [ c ] ;
2021-01-29 15:12:50 +00:00
d [ RenderingServer : : ARRAY_NORMAL ] = grid_normals [ c ] ;
2019-04-21 10:15:45 +00:00
RenderingServer : : get_singleton ( ) - > mesh_add_surface_from_arrays ( grid [ c ] , RenderingServer : : PRIMITIVE_LINES , d ) ;
2021-01-29 15:12:50 +00:00
RenderingServer : : get_singleton ( ) - > mesh_surface_set_material ( grid [ c ] , 0 , grid_mat [ c ] - > get_rid ( ) ) ;
2019-04-21 10:15:45 +00:00
grid_instance [ c ] = RenderingServer : : get_singleton ( ) - > instance_create2 ( grid [ c ] , get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_scenario ( ) ) ;
2017-12-08 22:45:33 +00:00
2019-04-21 10:15:45 +00: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 ) ;
2021-04-20 16:40:24 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( grid_instance [ c ] , RS : : INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING , true ) ;
2022-07-02 20:58:44 +00:00
RS : : get_singleton ( ) - > instance_geometry_set_flag ( grid_instance [ c ] , RS : : INSTANCE_FLAG_USE_BAKED_LIGHT , false ) ;
2017-12-08 22:45:33 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _finish_indicators ( ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( origin_instance ) ;
RenderingServer : : get_singleton ( ) - > free ( origin ) ;
2017-12-08 22:45:33 +00:00
_finish_grid ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _finish_grid ( ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > free ( grid_instance [ i ] ) ;
RenderingServer : : get_singleton ( ) - > free ( grid [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
}
2019-04-21 10:15:45 +00:00
void Node3DEditor : : update_grid ( ) {
2021-08-08 15:08:37 +00:00
const Camera3D : : Projection current_projection = viewports [ 0 ] - > camera - > get_projection ( ) ;
if ( current_projection ! = grid_camera_last_update_perspective ) {
grid_init_draw = false ; // redraw
grid_camera_last_update_perspective = current_projection ;
}
// Gets a orthogonal or perspective position correctly (for the grid comparison)
const Vector3 camera_position = get_editor_viewport ( 0 ) - > camera - > get_position ( ) ;
2021-09-29 03:51:34 +00:00
if ( ! grid_init_draw | | grid_camera_last_update_position . distance_squared_to ( camera_position ) > = 100.0f ) {
2021-08-08 15:08:37 +00:00
_finish_grid ( ) ;
_init_grid ( ) ;
grid_init_draw = true ;
grid_camera_last_update_position = camera_position ;
}
2019-04-21 10:15:45 +00:00
}
2021-06-23 14:49:50 +00:00
void Node3DEditor : : _selection_changed ( ) {
_refresh_menu_icons ( ) ;
if ( selected & & editor_selection - > get_selected_node_list ( ) . size ( ) ! = 1 ) {
Vector < Ref < Node3DGizmo > > gizmos = selected - > get_gizmos ( ) ;
for ( int i = 0 ; i < gizmos . size ( ) ; i + + ) {
Ref < EditorNode3DGizmo > seg = gizmos [ i ] ;
if ( ! seg . is_valid ( ) ) {
continue ;
}
seg - > set_selected ( false ) ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) ;
if ( se ) {
se - > gizmo . unref ( ) ;
se - > subgizmos . clear ( ) ;
2020-05-14 14:41:43 +00:00
}
2021-06-23 14:49:50 +00:00
selected - > update_gizmos ( ) ;
selected = nullptr ;
2017-05-07 20:59:05 +00:00
}
2021-06-23 14:49:50 +00:00
update_transform_gizmo ( ) ;
2017-05-07 20:59:05 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _refresh_menu_icons ( ) {
2017-10-23 19:21:15 +00:00
bool all_locked = true ;
2019-04-17 16:24:28 +00:00
bool all_grouped = true ;
2017-10-23 19:21:15 +00:00
List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2020-12-15 12:04:21 +00:00
if ( selection . is_empty ( ) ) {
2017-10-23 19:21:15 +00:00
all_locked = false ;
2019-04-17 16:24:28 +00:00
all_grouped = false ;
2017-10-23 19:21:15 +00:00
} else {
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
if ( Object : : cast_to < Node3D > ( E ) & & ! Object : : cast_to < Node3D > ( E ) - > has_meta ( " _edit_lock_ " ) ) {
2017-10-23 19:21:15 +00:00
all_locked = false ;
break ;
}
}
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
if ( Object : : cast_to < Node3D > ( E ) & & ! Object : : cast_to < Node3D > ( E ) - > has_meta ( " _edit_group_ " ) ) {
2019-04-17 16:24:28 +00:00
all_grouped = false ;
break ;
}
}
2017-10-23 19:21:15 +00:00
}
tool_button [ TOOL_LOCK_SELECTED ] - > set_visible ( ! all_locked ) ;
2020-12-15 12:04:21 +00:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_disabled ( selection . is_empty ( ) ) ;
2017-10-23 19:21:15 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_visible ( all_locked ) ;
2019-04-17 16:24:28 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_visible ( ! all_grouped ) ;
2020-12-15 12:04:21 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_disabled ( selection . is_empty ( ) ) ;
2019-04-17 16:24:28 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_visible ( all_grouped ) ;
2017-10-23 19:21:15 +00:00
}
2018-07-26 06:34:40 +00:00
template < typename T >
2022-05-19 15:00:06 +00:00
HashSet < T * > _get_child_nodes ( Node * parent_node ) {
HashSet < T * > nodes = HashSet < T * > ( ) ;
2018-07-26 06:34:40 +00:00
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 ) ;
2022-05-19 15:00:06 +00:00
HashSet < T * > child_nodes = _get_child_nodes < T > ( child_node ) ;
for ( T * I : child_nodes ) {
nodes . insert ( I ) ;
2018-07-26 06:34:40 +00:00
}
}
return nodes ;
}
2022-05-19 15:00:06 +00:00
HashSet < RID > _get_physics_bodies_rid ( Node * node ) {
HashSet < RID > rids = HashSet < RID > ( ) ;
2020-03-26 21:49:16 +00:00
PhysicsBody3D * pb = Node : : cast_to < PhysicsBody3D > ( node ) ;
2018-07-26 06:34:40 +00:00
if ( pb ) {
rids . insert ( pb - > get_rid ( ) ) ;
}
2022-05-19 15:00:06 +00:00
HashSet < PhysicsBody3D * > child_nodes = _get_child_nodes < PhysicsBody3D > ( node ) ;
2022-05-18 23:43:40 +00:00
for ( const PhysicsBody3D * I : child_nodes ) {
rids . insert ( I - > get_rid ( ) ) ;
2018-07-26 06:34:40 +00:00
}
return rids ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : snap_selected_nodes_to_floor ( ) {
2022-04-07 10:23:40 +00:00
const List < Node * > & selection = editor_selection - > get_selected_node_list ( ) ;
2018-07-26 06:34:40 +00:00
Dictionary snap_data ;
2021-07-16 03:45:57 +00:00
for ( Node * E : selection ) {
Node3D * sp = Object : : cast_to < Node3D > ( E ) ;
2018-07-26 06:34:40 +00:00
if ( sp ) {
Vector3 from = Vector3 ( ) ;
Vector3 position_offset = Vector3 ( ) ;
// Priorities for snapping to floor are CollisionShapes, VisualInstances and then origin
2022-05-19 15:00:06 +00:00
HashSet < VisualInstance3D * > vi = _get_child_nodes < VisualInstance3D > ( sp ) ;
HashSet < CollisionShape3D * > cs = _get_child_nodes < CollisionShape3D > ( sp ) ;
2020-12-10 20:44:09 +00:00
bool found_valid_shape = false ;
2018-07-26 06:34:40 +00:00
if ( cs . size ( ) ) {
2020-12-09 17:40:30 +00:00
AABB aabb ;
2022-05-19 15:00:06 +00:00
HashSet < CollisionShape3D * > : : Iterator I = cs . begin ( ) ;
if ( ( * I ) - > get_shape ( ) . is_valid ( ) ) {
CollisionShape3D * collision_shape = * cs . begin ( ) ;
2020-12-10 20:44:09 +00:00
aabb = collision_shape - > get_global_transform ( ) . xform ( collision_shape - > get_shape ( ) - > get_debug_mesh ( ) - > get_aabb ( ) ) ;
2020-12-09 17:40:30 +00:00
found_valid_shape = true ;
}
2022-05-19 15:00:06 +00:00
for ( + + I ; I ; + + I ) {
CollisionShape3D * col_shape = * I ;
2020-12-10 20:44:09 +00:00
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 17:40:30 +00: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 06:34:40 +00:00
}
2020-12-10 20:44:09 +00:00
}
if ( ! found_valid_shape & & vi . size ( ) ) {
2022-05-19 15:00:06 +00:00
AABB aabb = ( * vi . begin ( ) ) - > get_transformed_aabb ( ) ;
2022-05-18 23:43:40 +00:00
for ( const VisualInstance3D * I : vi ) {
aabb . merge_with ( I - > get_transformed_aabb ( ) ) ;
2018-07-26 06:34:40 +00:00
}
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 20:44:09 +00:00
} else if ( ! found_valid_shape ) {
2018-07-26 06:34:40 +00: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
2021-10-12 14:38:33 +00:00
from = from + Vector3 ( 0.0 , 1 , 0.0 ) ;
2018-07-26 06:34:40 +00:00
Dictionary d ;
d [ " from " ] = from ;
d [ " position_offset " ] = position_offset ;
snap_data [ sp ] = d ;
}
}
2020-04-18 09:00:51 +00:00
PhysicsDirectSpaceState3D * ss = get_tree ( ) - > get_root ( ) - > get_world_3d ( ) - > get_direct_space_state ( ) ;
2020-03-27 18:21:27 +00:00
PhysicsDirectSpaceState3D : : RayResult result ;
2018-07-26 06:34:40 +00:00
Array keys = snap_data . keys ( ) ;
2019-08-17 23:42:42 +00:00
// The maximum height an object can travel to be snapped
2021-10-12 14:38:33 +00:00
const float max_snap_height = 500.0 ;
2019-08-17 23:42:42 +00:00
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 18:36:39 +00:00
// Will be set to `true` if at least one node from the selection was successfully snapped
2019-08-17 23:42:42 +00:00
bool snapped_to_floor = false ;
2018-07-26 06:34:40 +00:00
2019-08-17 23:42:42 +00: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 06:34:40 +00:00
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
2022-01-25 15:37:41 +00:00
Node * node = Object : : cast_to < Node > ( keys [ i ] ) ;
2020-03-26 21:49:16 +00:00
Node3D * sp = Object : : cast_to < Node3D > ( node ) ;
2018-07-26 06:34:40 +00:00
Dictionary d = snap_data [ node ] ;
Vector3 from = d [ " from " ] ;
2019-08-17 23:42:42 +00:00
Vector3 to = from - Vector3 ( 0.0 , max_snap_height , 0.0 ) ;
2022-05-19 15:00:06 +00:00
HashSet < RID > excluded = _get_physics_bodies_rid ( sp ) ;
2018-07-26 06:34:40 +00:00
2021-11-02 01:00:58 +00:00
PhysicsDirectSpaceState3D : : RayParameters ray_params ;
ray_params . from = from ;
ray_params . to = to ;
ray_params . exclude = excluded ;
if ( ss - > intersect_ray ( ray_params , result ) ) {
2019-08-17 23:42:42 +00:00
snapped_to_floor = true ;
2018-07-26 06:34:40 +00:00
}
}
2019-08-17 23:42:42 +00:00
if ( snapped_to_floor ) {
2021-07-13 13:25:56 +00:00
undo_redo - > create_action ( TTR ( " Snap Nodes to Floor " ) ) ;
2019-08-17 23:42:42 +00:00
// Perform snapping if at least one node can be snapped
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
2022-01-25 15:37:41 +00:00
Node * node = Object : : cast_to < Node > ( keys [ i ] ) ;
2020-03-26 21:49:16 +00:00
Node3D * sp = Object : : cast_to < Node3D > ( node ) ;
2019-08-17 23:42:42 +00:00
Dictionary d = snap_data [ node ] ;
Vector3 from = d [ " from " ] ;
Vector3 to = from - Vector3 ( 0.0 , max_snap_height , 0.0 ) ;
2022-05-19 15:00:06 +00:00
HashSet < RID > excluded = _get_physics_bodies_rid ( sp ) ;
2019-08-17 23:42:42 +00:00
2021-11-02 01:00:58 +00:00
PhysicsDirectSpaceState3D : : RayParameters ray_params ;
ray_params . from = from ;
ray_params . to = to ;
ray_params . exclude = excluded ;
if ( ss - > intersect_ray ( ray_params , result ) ) {
2019-08-17 23:42:42 +00:00
Vector3 position_offset = d [ " position_offset " ] ;
2020-10-17 05:08:21 +00:00
Transform3D new_transform = sp - > get_global_transform ( ) ;
2019-08-17 23:42:42 +00:00
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 06:34:40 +00:00
}
}
2022-01-11 13:59:52 +00:00
void Node3DEditor : : shortcut_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 06:52:21 +00:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2020-05-14 14:41:43 +00:00
if ( ! is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-08-13 21:31:57 +00:00
snap_key_enabled = Input : : get_singleton ( ) - > is_key_pressed ( Key : : CTRL ) ;
2014-02-10 01:10:30 +00:00
}
2020-05-14 12:29:06 +00:00
2021-02-22 13:54:12 +00:00
void Node3DEditor : : _sun_environ_settings_pressed ( ) {
Vector2 pos = sun_environ_settings - > get_screen_position ( ) + sun_environ_settings - > get_size ( ) ;
sun_environ_popup - > set_position ( pos - Vector2 ( sun_environ_popup - > get_contents_minimum_size ( ) . width / 2 , 0 ) ) ;
2021-08-31 15:43:35 +00:00
sun_environ_popup - > reset_size ( ) ;
2021-02-22 13:54:12 +00:00
sun_environ_popup - > popup ( ) ;
}
2021-07-06 22:41:37 +00:00
void Node3DEditor : : _add_sun_to_scene ( bool p_already_added_environment ) {
2021-02-22 13:54:12 +00:00
sun_environ_popup - > hide ( ) ;
2021-08-13 21:31:57 +00:00
if ( ! p_already_added_environment & & world_env_count = = 0 & & Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2021-07-06 22:41:37 +00:00
// Prevent infinite feedback loop between the sun and environment methods.
_add_environment_to_scene ( true ) ;
}
2021-02-22 13:54:12 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( ! base ) {
2021-07-06 23:59:46 +00:00
// Create a root node so we can add child nodes to it.
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > add_root_node ( memnew ( Node3D ) ) ;
2021-07-06 23:59:46 +00:00
base = get_tree ( ) - > get_edited_scene_root ( ) ;
2021-02-22 13:54:12 +00:00
}
ERR_FAIL_COND ( ! base ) ;
Node * new_sun = preview_sun - > duplicate ( ) ;
2021-07-19 19:10:05 +00:00
undo_redo - > create_action ( TTR ( " Add Preview Sun to Scene " ) ) ;
2021-11-06 23:40:15 +00:00
undo_redo - > add_do_method ( base , " add_child " , new_sun , true ) ;
2021-07-12 10:08:58 +00:00
// Move to the beginning of the scene tree since more "global" nodes
// generally look better when placed at the top.
undo_redo - > add_do_method ( base , " move_child " , new_sun , 0 ) ;
2021-02-22 13:54:12 +00:00
undo_redo - > add_do_method ( new_sun , " set_owner " , base ) ;
undo_redo - > add_undo_method ( base , " remove_child " , new_sun ) ;
undo_redo - > add_do_reference ( new_sun ) ;
undo_redo - > commit_action ( ) ;
}
2021-07-06 22:41:37 +00:00
void Node3DEditor : : _add_environment_to_scene ( bool p_already_added_sun ) {
2021-02-22 13:54:12 +00:00
sun_environ_popup - > hide ( ) ;
2021-08-13 21:31:57 +00:00
if ( ! p_already_added_sun & & directional_light_count = = 0 & & Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2021-07-06 22:41:37 +00:00
// Prevent infinite feedback loop between the sun and environment methods.
_add_sun_to_scene ( true ) ;
}
2021-02-22 13:54:12 +00:00
Node * base = get_tree ( ) - > get_edited_scene_root ( ) ;
if ( ! base ) {
2021-07-06 23:59:46 +00:00
// Create a root node so we can add child nodes to it.
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > add_root_node ( memnew ( Node3D ) ) ;
2021-07-06 23:59:46 +00:00
base = get_tree ( ) - > get_edited_scene_root ( ) ;
2021-02-22 13:54:12 +00:00
}
ERR_FAIL_COND ( ! base ) ;
WorldEnvironment * new_env = memnew ( WorldEnvironment ) ;
new_env - > set_environment ( preview_environment - > get_environment ( ) - > duplicate ( true ) ) ;
2021-07-19 19:10:05 +00:00
undo_redo - > create_action ( TTR ( " Add Preview Environment to Scene " ) ) ;
2021-11-06 23:40:15 +00:00
undo_redo - > add_do_method ( base , " add_child " , new_env , true ) ;
2021-07-12 10:08:58 +00:00
// Move to the beginning of the scene tree since more "global" nodes
// generally look better when placed at the top.
undo_redo - > add_do_method ( base , " move_child " , new_env , 0 ) ;
2021-02-22 13:54:12 +00:00
undo_redo - > add_do_method ( new_env , " set_owner " , base ) ;
undo_redo - > add_undo_method ( base , " remove_child " , new_env ) ;
undo_redo - > add_do_reference ( new_env ) ;
undo_redo - > commit_action ( ) ;
}
2021-07-26 19:18:01 +00:00
void Node3DEditor : : _update_theme ( ) {
2022-03-05 20:22:38 +00:00
tool_button [ TOOL_MODE_SELECT ] - > set_icon ( get_theme_icon ( SNAME ( " ToolSelect " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_MODE_MOVE ] - > set_icon ( get_theme_icon ( SNAME ( " ToolMove " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_MODE_ROTATE ] - > set_icon ( get_theme_icon ( SNAME ( " ToolRotate " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_MODE_SCALE ] - > set_icon ( get_theme_icon ( SNAME ( " ToolScale " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_icon ( get_theme_icon ( SNAME ( " ListSelect " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_LOCK_SELECTED ] - > set_icon ( get_theme_icon ( SNAME ( " Lock " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_icon ( get_theme_icon ( SNAME ( " Unlock " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_GROUP_SELECTED ] - > set_icon ( get_theme_icon ( SNAME ( " Group " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_icon ( get_theme_icon ( SNAME ( " Ungroup " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_icon ( get_theme_icon ( SNAME ( " Object " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_icon ( get_theme_icon ( SNAME ( " Snap " ) , SNAME ( " EditorIcons " ) ) ) ;
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_icon ( get_theme_icon ( SNAME ( " Camera3D " ) , SNAME ( " EditorIcons " ) ) ) ;
2021-07-26 19:18:01 +00:00
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) , get_theme_icon ( SNAME ( " Panels1 " ) , SNAME ( " EditorIcons " ) ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS ) , get_theme_icon ( SNAME ( " Panels2 " ) , SNAME ( " EditorIcons " ) ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) , get_theme_icon ( SNAME ( " Panels2Alt " ) , SNAME ( " EditorIcons " ) ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS ) , get_theme_icon ( SNAME ( " Panels3 " ) , SNAME ( " EditorIcons " ) ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) , get_theme_icon ( SNAME ( " Panels3Alt " ) , SNAME ( " EditorIcons " ) ) ) ;
view_menu - > get_popup ( ) - > set_item_icon ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_4_VIEWPORTS ) , get_theme_icon ( SNAME ( " Panels4 " ) , SNAME ( " EditorIcons " ) ) ) ;
sun_button - > set_icon ( get_theme_icon ( SNAME ( " DirectionalLight3D " ) , SNAME ( " EditorIcons " ) ) ) ;
environ_button - > set_icon ( get_theme_icon ( SNAME ( " WorldEnvironment " ) , SNAME ( " EditorIcons " ) ) ) ;
sun_environ_settings - > set_icon ( get_theme_icon ( SNAME ( " GuiTabMenuHl " ) , SNAME ( " EditorIcons " ) ) ) ;
2022-02-08 09:14:58 +00:00
sun_title - > add_theme_font_override ( " font " , get_theme_font ( SNAME ( " title_font " ) , SNAME ( " Window " ) ) ) ;
environ_title - > add_theme_font_override ( " font " , get_theme_font ( SNAME ( " title_font " ) , SNAME ( " Window " ) ) ) ;
2022-05-17 20:44:15 +00:00
sun_color - > set_custom_minimum_size ( Size2 ( 0 , get_theme_constant ( SNAME ( " color_picker_button_height " ) , SNAME ( " Editor " ) ) ) ) ;
environ_sky_color - > set_custom_minimum_size ( Size2 ( 0 , get_theme_constant ( SNAME ( " color_picker_button_height " ) , SNAME ( " Editor " ) ) ) ) ;
environ_ground_color - > set_custom_minimum_size ( Size2 ( 0 , get_theme_constant ( SNAME ( " color_picker_button_height " ) , SNAME ( " Editor " ) ) ) ) ;
2022-04-01 04:43:46 +00:00
2022-07-20 01:00:25 +00:00
context_menu_panel - > add_theme_style_override ( " panel " , get_theme_stylebox ( SNAME ( " ContextualToolbar " ) , SNAME ( " EditorStyles " ) ) ) ;
2021-07-26 19:18:01 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _notification ( int p_what ) {
2021-07-26 19:18:01 +00:00
switch ( p_what ) {
case NOTIFICATION_READY : {
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2021-02-22 13:54:12 +00:00
2021-07-26 19:18:01 +00:00
_refresh_menu_icons ( ) ;
2021-02-22 13:54:12 +00:00
2021-07-26 19:18:01 +00:00
get_tree ( ) - > connect ( " node_removed " , callable_mp ( this , & Node3DEditor : : _node_removed ) ) ;
get_tree ( ) - > connect ( " node_added " , callable_mp ( this , & Node3DEditor : : _node_added ) ) ;
2021-11-17 20:08:55 +00:00
SceneTreeDock : : get_singleton ( ) - > get_tree_editor ( ) - > connect ( " node_changed " , callable_mp ( this , & Node3DEditor : : _refresh_menu_icons ) ) ;
2021-07-26 19:18:01 +00:00
editor_selection - > connect ( " selection_changed " , callable_mp ( this , & Node3DEditor : : _selection_changed ) ) ;
2019-04-06 20:55:01 +00:00
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > connect ( " stop_pressed " , callable_mp ( this , & Node3DEditor : : _update_camera_override_button ) , make_binds ( false ) ) ;
EditorNode : : get_singleton ( ) - > connect ( " play_pressed " , callable_mp ( this , & Node3DEditor : : _update_camera_override_button ) , make_binds ( true ) ) ;
2021-07-26 19:18:01 +00:00
_update_preview_environment ( ) ;
sun_state - > set_custom_minimum_size ( sun_vb - > get_combined_minimum_size ( ) ) ;
environ_state - > set_custom_minimum_size ( environ_vb - > get_combined_minimum_size ( ) ) ;
} break ;
2022-02-16 02:44:22 +00:00
2021-07-26 19:18:01 +00:00
case NOTIFICATION_ENTER_TREE : {
_update_theme ( ) ;
_register_all_gizmos ( ) ;
_update_gizmos_menu ( ) ;
_init_indicators ( ) ;
2021-07-27 15:43:12 +00:00
update_all_gizmos ( ) ;
2021-07-26 19:18:01 +00:00
} break ;
2022-02-16 02:44:22 +00:00
2021-07-26 19:18:01 +00:00
case NOTIFICATION_EXIT_TREE : {
_finish_indicators ( ) ;
} break ;
2022-02-16 02:44:22 +00:00
2021-07-26 19:18:01 +00:00
case NOTIFICATION_THEME_CHANGED : {
_update_theme ( ) ;
_update_gizmos_menu_theme ( ) ;
2022-02-08 09:14:58 +00:00
sun_title - > add_theme_font_override ( " font " , get_theme_font ( SNAME ( " title_font " ) , SNAME ( " Window " ) ) ) ;
environ_title - > add_theme_font_override ( " font " , get_theme_font ( SNAME ( " title_font " ) , SNAME ( " Window " ) ) ) ;
2021-07-26 19:18:01 +00:00
} break ;
2022-02-16 02:44:22 +00:00
2021-07-26 19:18:01 +00:00
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
// Update grid color by rebuilding grid.
_finish_grid ( ) ;
_init_grid ( ) ;
} break ;
2022-02-16 02:44:22 +00:00
2021-07-26 19:18:01 +00:00
case NOTIFICATION_VISIBILITY_CHANGED : {
if ( ! is_visible ( ) & & tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > is_pressed ( ) ) {
EditorDebuggerNode * debugger = EditorDebuggerNode : : get_singleton ( ) ;
debugger - > set_camera_override ( EditorDebuggerNode : : OVERRIDE_NONE ) ;
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > set_pressed ( false ) ;
}
} break ;
2017-08-29 23:03:13 +00:00
}
2014-02-10 01:10:30 +00:00
}
2021-06-23 14:49:50 +00:00
bool Node3DEditor : : is_subgizmo_selected ( int p_id ) {
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
if ( se ) {
return se - > subgizmos . has ( p_id ) ;
}
return false ;
}
bool Node3DEditor : : is_current_selected_gizmo ( const EditorNode3DGizmo * p_gizmo ) {
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
if ( se ) {
return se - > gizmo = = p_gizmo ;
}
return false ;
}
Vector < int > Node3DEditor : : get_subgizmo_selection ( ) {
Node3DEditorSelectedItem * se = selected ? editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) : nullptr ;
Vector < int > ret ;
if ( se ) {
2021-08-09 20:13:42 +00:00
for ( const KeyValue < int , Transform3D > & E : se - > subgizmos ) {
ret . push_back ( E . key ) ;
2021-06-23 14:49:50 +00:00
}
}
return ret ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : add_control_to_menu_panel ( Control * p_control ) {
2022-07-20 01:00:25 +00:00
context_menu_hbox - > add_child ( p_control ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : remove_control_from_menu_panel ( Control * p_control ) {
2022-07-20 01:00:25 +00:00
context_menu_hbox - > remove_child ( p_control ) ;
2018-02-13 21:21:19 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : set_can_preview ( Camera3D * p_preview ) {
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
2014-02-10 01:10:30 +00:00
viewports [ i ] - > set_can_preview ( p_preview ) ;
}
}
2020-03-26 21:49:16 +00:00
VSplitContainer * Node3DEditor : : get_shader_split ( ) {
2014-02-10 01:10:30 +00:00
return shader_split ;
}
2022-01-08 12:31:22 +00:00
void Node3DEditor : : add_control_to_left_panel ( Control * p_control ) {
left_panel_split - > add_child ( p_control ) ;
left_panel_split - > move_child ( p_control , 0 ) ;
}
void Node3DEditor : : add_control_to_right_panel ( Control * p_control ) {
right_panel_split - > add_child ( p_control ) ;
right_panel_split - > move_child ( p_control , 1 ) ;
}
void Node3DEditor : : remove_control_from_left_panel ( Control * p_control ) {
left_panel_split - > remove_child ( p_control ) ;
}
void Node3DEditor : : remove_control_from_right_panel ( Control * p_control ) {
right_panel_split - > remove_child ( p_control ) ;
}
void Node3DEditor : : move_control_to_left_panel ( Control * p_control ) {
ERR_FAIL_NULL ( p_control ) ;
if ( p_control - > get_parent ( ) = = left_panel_split ) {
return ;
}
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = right_panel_split ) ;
right_panel_split - > remove_child ( p_control ) ;
add_control_to_left_panel ( p_control ) ;
}
void Node3DEditor : : move_control_to_right_panel ( Control * p_control ) {
ERR_FAIL_NULL ( p_control ) ;
if ( p_control - > get_parent ( ) = = right_panel_split ) {
return ;
}
ERR_FAIL_COND ( p_control - > get_parent ( ) ! = left_panel_split ) ;
left_panel_split - > remove_child ( p_control ) ;
add_control_to_right_panel ( p_control ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _request_gizmo ( Object * p_obj ) {
Node3D * sp = Object : : cast_to < Node3D > ( p_obj ) ;
2020-05-14 14:41:43 +00:00
if ( ! sp ) {
2014-02-10 01:10:30 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-02-10 01:10:30 +00:00
2021-06-23 14:49:50 +00:00
bool is_selected = ( sp = = selected ) ;
2022-01-27 09:36:51 +00:00
Node * edited_scene = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
if ( edited_scene & & ( sp = = edited_scene | | ( sp - > get_owner ( ) & & edited_scene - > is_ancestor_of ( sp ) ) ) ) {
2019-03-11 23:30:50 +00:00
for ( int i = 0 ; i < gizmo_plugins_by_priority . size ( ) ; + + i ) {
2021-06-23 14:49:50 +00:00
Ref < EditorNode3DGizmo > seg = gizmo_plugins_by_priority . write [ i ] - > get_gizmo ( sp ) ;
2014-02-10 01:10:30 +00:00
2018-07-24 22:08:49 +00:00
if ( seg . is_valid ( ) ) {
2021-06-23 14:49:50 +00:00
sp - > add_gizmo ( seg ) ;
2014-05-05 01:50:23 +00:00
2021-06-23 14:49:50 +00:00
if ( is_selected ! = seg - > is_selected ( ) ) {
seg - > set_selected ( is_selected ) ;
2018-07-24 22:08:49 +00:00
}
}
2014-05-05 01:50:23 +00:00
}
2022-04-13 03:10:44 +00:00
if ( ! sp - > get_gizmos ( ) . is_empty ( ) ) {
sp - > update_gizmos ( ) ;
}
2021-06-23 14:49:50 +00:00
}
}
2021-02-04 08:20:26 +00:00
void Node3DEditor : : _set_subgizmo_selection ( Object * p_obj , Ref < Node3DGizmo > p_gizmo , int p_id , Transform3D p_transform ) {
if ( p_id = = - 1 ) {
_clear_subgizmo_selection ( p_obj ) ;
return ;
}
Node3D * sp = nullptr ;
if ( p_obj ) {
sp = Object : : cast_to < Node3D > ( p_obj ) ;
} else {
sp = selected ;
}
if ( ! sp ) {
return ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( se ) {
se - > subgizmos . clear ( ) ;
se - > subgizmos . insert ( p_id , p_transform ) ;
se - > gizmo = p_gizmo ;
sp - > update_gizmos ( ) ;
update_transform_gizmo ( ) ;
}
}
2021-06-23 14:49:50 +00:00
void Node3DEditor : : _clear_subgizmo_selection ( Object * p_obj ) {
Node3D * sp = nullptr ;
if ( p_obj ) {
sp = Object : : cast_to < Node3D > ( p_obj ) ;
} else {
sp = selected ;
}
if ( ! sp ) {
return ;
}
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( sp ) ;
if ( se ) {
se - > subgizmos . clear ( ) ;
se - > gizmo . unref ( ) ;
sp - > update_gizmos ( ) ;
update_transform_gizmo ( ) ;
2014-02-10 01:10:30 +00:00
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _toggle_maximize_view ( Object * p_viewport ) {
2020-05-14 14:41:43 +00:00
if ( ! p_viewport ) {
2020-05-10 10:56:01 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2020-03-26 21:49:16 +00:00
Node3DEditorViewport * current_viewport = Object : : cast_to < Node3DEditorViewport > ( p_viewport ) ;
2020-05-14 14:41:43 +00:00
if ( ! current_viewport ) {
2020-05-10 10:56:01 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
2017-03-05 15:44:50 +00:00
int index = - 1 ;
2014-04-01 10:45:48 +00:00
bool maximized = false ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( viewports [ i ] = = current_viewport ) {
index = i ;
2020-05-14 14:41:43 +00:00
if ( current_viewport - > get_global_rect ( ) = = viewport_base - > get_global_rect ( ) ) {
2017-03-05 15:44:50 +00:00
maximized = true ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
break ;
}
}
2020-05-14 14:41:43 +00:00
if ( index = = - 1 ) {
2020-05-10 10:56:01 +00:00
return ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
if ( ! maximized ) {
2017-08-31 21:30:35 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2020-05-14 14:41:43 +00:00
if ( i = = ( uint32_t ) index ) {
2022-03-19 00:02:57 +00:00
viewports [ i ] - > set_anchors_and_offsets_preset ( Control : : PRESET_FULL_RECT ) ;
2020-05-14 14:41:43 +00:00
} else {
2014-04-01 10:45:48 +00:00
viewports [ i ] - > hide ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
}
} else {
2020-05-14 14:41:43 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-04-01 10:45:48 +00:00
viewports [ i ] - > show ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
2020-05-14 14:41:43 +00:00
if ( view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_USE_1_VIEWPORT ) ) ) {
2014-04-01 10:45:48 +00:00
_menu_item_pressed ( MENU_VIEW_USE_1_VIEWPORT ) ;
2020-05-14 14:41:43 +00: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 10:45:48 +00:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS ) ;
2020-05-14 14:41:43 +00: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 03:06:51 +00:00
_menu_item_pressed ( MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
2020-05-14 14:41:43 +00: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 10:45:48 +00:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS ) ;
2020-05-14 14:41:43 +00: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 03:06:51 +00:00
_menu_item_pressed ( MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
2020-05-14 14:41:43 +00: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 10:45:48 +00:00
_menu_item_pressed ( MENU_VIEW_USE_4_VIEWPORTS ) ;
2020-05-14 14:41:43 +00:00
}
2014-04-01 10:45:48 +00:00
}
}
2021-02-22 13:54:12 +00:00
void Node3DEditor : : _node_added ( Node * p_node ) {
2021-06-18 22:02:50 +00:00
if ( EditorNode : : get_singleton ( ) - > get_scene_root ( ) - > is_ancestor_of ( p_node ) ) {
2021-02-22 13:54:12 +00:00
if ( Object : : cast_to < WorldEnvironment > ( p_node ) ) {
world_env_count + + ;
if ( world_env_count = = 1 ) {
_update_preview_environment ( ) ;
}
} else if ( Object : : cast_to < DirectionalLight3D > ( p_node ) ) {
directional_light_count + + ;
if ( directional_light_count = = 1 ) {
_update_preview_environment ( ) ;
}
}
}
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _node_removed ( Node * p_node ) {
2021-06-18 22:02:50 +00:00
if ( EditorNode : : get_singleton ( ) - > get_scene_root ( ) - > is_ancestor_of ( p_node ) ) {
2021-02-22 13:54:12 +00:00
if ( Object : : cast_to < WorldEnvironment > ( p_node ) ) {
world_env_count - - ;
if ( world_env_count = = 0 ) {
_update_preview_environment ( ) ;
}
} else if ( Object : : cast_to < DirectionalLight3D > ( p_node ) ) {
directional_light_count - - ;
if ( directional_light_count = = 0 ) {
_update_preview_environment ( ) ;
}
}
}
2020-05-14 14:41:43 +00:00
if ( p_node = = selected ) {
2021-06-23 14:49:50 +00:00
Node3DEditorSelectedItem * se = editor_selection - > get_node_editor_data < Node3DEditorSelectedItem > ( selected ) ;
if ( se ) {
se - > gizmo . unref ( ) ;
se - > subgizmos . clear ( ) ;
}
2020-04-01 23:20:12 +00:00
selected = nullptr ;
2021-06-23 14:49:50 +00:00
update_transform_gizmo ( ) ;
2020-05-14 14:41:43 +00:00
}
2014-05-05 01:50:23 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _register_all_gizmos ( ) {
2020-04-06 10:40:52 +00:00
add_gizmo_plugin ( Ref < Camera3DGizmoPlugin > ( memnew ( Camera3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < Light3DGizmoPlugin > ( memnew ( Light3DGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < AudioStreamPlayer3DGizmoPlugin > ( memnew ( AudioStreamPlayer3DGizmoPlugin ) ) ) ;
2021-09-16 19:28:20 +00:00
add_gizmo_plugin ( Ref < AudioListener3DGizmoPlugin > ( memnew ( AudioListener3DGizmoPlugin ) ) ) ;
2020-04-06 10:40:52 +00:00
add_gizmo_plugin ( Ref < MeshInstance3DGizmoPlugin > ( memnew ( MeshInstance3DGizmoPlugin ) ) ) ;
2021-04-20 16:40:24 +00:00
add_gizmo_plugin ( Ref < OccluderInstance3DGizmoPlugin > ( memnew ( OccluderInstance3DGizmoPlugin ) ) ) ;
2021-09-14 18:44:30 +00:00
add_gizmo_plugin ( Ref < SoftDynamicBody3DGizmoPlugin > ( memnew ( SoftDynamicBody3DGizmoPlugin ) ) ) ;
2020-04-06 10:40:52 +00:00
add_gizmo_plugin ( Ref < Sprite3DGizmoPlugin > ( memnew ( Sprite3DGizmoPlugin ) ) ) ;
2022-04-19 10:27:18 +00:00
add_gizmo_plugin ( Ref < Label3DGizmoPlugin > ( memnew ( Label3DGizmoPlugin ) ) ) ;
2020-04-06 10:40:52 +00:00
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 ) ) ) ;
2021-06-17 00:52:30 +00:00
add_gizmo_plugin ( Ref < VisibleOnScreenNotifier3DGizmoPlugin > ( memnew ( VisibleOnScreenNotifier3DGizmoPlugin ) ) ) ;
2020-03-30 16:22:57 +00:00
add_gizmo_plugin ( Ref < GPUParticles3DGizmoPlugin > ( memnew ( GPUParticles3DGizmoPlugin ) ) ) ;
2020-10-08 00:29:49 +00:00
add_gizmo_plugin ( Ref < GPUParticlesCollision3DGizmoPlugin > ( memnew ( GPUParticlesCollision3DGizmoPlugin ) ) ) ;
2020-03-30 16:22:57 +00:00
add_gizmo_plugin ( Ref < CPUParticles3DGizmoPlugin > ( memnew ( CPUParticles3DGizmoPlugin ) ) ) ;
2018-10-29 10:30:28 +00:00
add_gizmo_plugin ( Ref < ReflectionProbeGizmoPlugin > ( memnew ( ReflectionProbeGizmoPlugin ) ) ) ;
2020-04-14 03:05:21 +00:00
add_gizmo_plugin ( Ref < DecalGizmoPlugin > ( memnew ( DecalGizmoPlugin ) ) ) ;
2021-06-04 22:47:26 +00:00
add_gizmo_plugin ( Ref < VoxelGIGizmoPlugin > ( memnew ( VoxelGIGizmoPlugin ) ) ) ;
add_gizmo_plugin ( Ref < LightmapGIGizmoPlugin > ( memnew ( LightmapGIGizmoPlugin ) ) ) ;
2020-05-01 12:34:23 +00:00
add_gizmo_plugin ( Ref < LightmapProbeGizmoPlugin > ( memnew ( LightmapProbeGizmoPlugin ) ) ) ;
2021-02-06 22:21:04 +00:00
add_gizmo_plugin ( Ref < CollisionObject3DGizmoPlugin > ( memnew ( CollisionObject3DGizmoPlugin ) ) ) ;
2020-04-06 10:40:52 +00: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 ) ) ) ;
2021-10-03 11:28:55 +00:00
add_gizmo_plugin ( Ref < FogVolumeGizmoPlugin > ( memnew ( FogVolumeGizmoPlugin ) ) ) ;
2018-07-24 22:08:49 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : _bind_methods ( ) {
ClassDB : : bind_method ( " _get_editor_data " , & Node3DEditor : : _get_editor_data ) ;
ClassDB : : bind_method ( " _request_gizmo " , & Node3DEditor : : _request_gizmo ) ;
2021-02-04 08:20:26 +00:00
ClassDB : : bind_method ( " _set_subgizmo_selection " , & Node3DEditor : : _set_subgizmo_selection ) ;
2021-06-23 14:49:50 +00:00
ClassDB : : bind_method ( " _clear_subgizmo_selection " , & Node3DEditor : : _clear_subgizmo_selection ) ;
2020-06-24 15:09:53 +00:00
ClassDB : : bind_method ( " _refresh_menu_icons " , & Node3DEditor : : _refresh_menu_icons ) ;
2014-04-01 10:45:48 +00:00
2017-03-05 15:44:50 +00:00
ADD_SIGNAL ( MethodInfo ( " transform_key_request " ) ) ;
2017-10-23 19:21:15 +00:00
ADD_SIGNAL ( MethodInfo ( " item_lock_status_changed " ) ) ;
2019-04-17 16:24:28 +00:00
ADD_SIGNAL ( MethodInfo ( " item_group_status_changed " ) ) ;
2014-09-19 21:39:50 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : clear ( ) {
2019-10-31 13:32:46 +00: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 21:39:50 +00:00
2017-08-31 21:30:35 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2014-09-19 21:39:50 +00:00
viewports [ i ] - > reset ( ) ;
}
2020-03-27 18:21:27 +00:00
RenderingServer : : get_singleton ( ) - > instance_set_visible ( origin_instance , true ) ;
2017-03-05 15:44:50 +00: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 21:39:50 +00:00
if ( grid_enable [ i ] ) {
2017-03-05 15:44:50 +00:00
grid_visible [ i ] = true ;
2014-09-19 21:39:50 +00:00
}
}
2017-08-31 21:30:35 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2020-03-26 21:49:16 +00:00
viewports [ i ] - > view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( Node3DEditorViewport : : VIEW_AUDIO_LISTENER ) , i = = 0 ) ;
2021-08-02 17:31:51 +00:00
viewports [ i ] - > viewport - > set_as_audio_listener_3d ( i = = 0 ) ;
2014-10-03 03:10:51 +00:00
}
2014-10-12 05:13:22 +00:00
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( MENU_VIEW_GRID ) , true ) ;
2014-02-10 01:10:30 +00:00
}
2021-02-22 13:54:12 +00:00
void Node3DEditor : : _sun_direction_draw ( ) {
sun_direction - > draw_rect ( Rect2 ( Vector2 ( ) , sun_direction - > get_size ( ) ) , Color ( 1 , 1 , 1 , 1 ) ) ;
2022-05-03 12:50:35 +00:00
Vector3 z_axis = preview_sun - > get_transform ( ) . basis . get_column ( Vector3 : : AXIS_Z ) ;
2021-02-22 21:20:44 +00:00
z_axis = get_editor_viewport ( 0 ) - > camera - > get_camera_transform ( ) . basis . xform_inv ( z_axis ) ;
sun_direction_material - > set_shader_param ( " sun_direction " , Vector3 ( z_axis . x , - z_axis . y , z_axis . z ) ) ;
Color color = sun_color - > get_pick_color ( ) * sun_energy - > get_value ( ) ;
sun_direction_material - > set_shader_param ( " sun_color " , Vector3 ( color . r , color . g , color . b ) ) ;
2021-02-22 13:54:12 +00:00
}
void Node3DEditor : : _preview_settings_changed ( ) {
if ( sun_environ_updating ) {
return ;
}
{ // preview sun
2020-10-17 05:08:21 +00:00
Transform3D t ;
2021-02-22 21:20:44 +00:00
t . basis = Basis ( Vector3 ( sun_rotation . x , sun_rotation . y , 0 ) ) ;
2021-02-22 13:54:12 +00:00
preview_sun - > set_transform ( t ) ;
sun_direction - > update ( ) ;
preview_sun - > set_param ( Light3D : : PARAM_ENERGY , sun_energy - > get_value ( ) ) ;
preview_sun - > set_param ( Light3D : : PARAM_SHADOW_MAX_DISTANCE , sun_max_distance - > get_value ( ) ) ;
preview_sun - > set_color ( sun_color - > get_pick_color ( ) ) ;
}
{ //preview env
sky_material - > set_sky_energy ( environ_energy - > get_value ( ) ) ;
Color hz_color = environ_sky_color - > get_pick_color ( ) . lerp ( environ_ground_color - > get_pick_color ( ) , 0.5 ) . lerp ( Color ( 1 , 1 , 1 ) , 0.5 ) ;
sky_material - > set_sky_top_color ( environ_sky_color - > get_pick_color ( ) ) ;
sky_material - > set_sky_horizon_color ( hz_color ) ;
sky_material - > set_ground_bottom_color ( environ_ground_color - > get_pick_color ( ) ) ;
sky_material - > set_ground_horizon_color ( hz_color ) ;
environment - > set_ssao_enabled ( environ_ao_button - > is_pressed ( ) ) ;
environment - > set_glow_enabled ( environ_glow_button - > is_pressed ( ) ) ;
environment - > set_sdfgi_enabled ( environ_gi_button - > is_pressed ( ) ) ;
environment - > set_tonemapper ( environ_tonemap_button - > is_pressed ( ) ? Environment : : TONE_MAPPER_FILMIC : Environment : : TONE_MAPPER_LINEAR ) ;
}
}
2021-02-22 21:20:44 +00:00
2021-02-22 13:54:12 +00:00
void Node3DEditor : : _load_default_preview_settings ( ) {
sun_environ_updating = true ;
2021-02-22 21:20:44 +00:00
// These default rotations place the preview sun at an angular altitude
// of 60 degrees (must be negative) and an azimuth of 30 degrees clockwise
// from north (or 150 CCW from south), from north east, facing south west.
// On any not-tidally-locked planet, a sun would have an angular altitude
// of 60 degrees as the average of all points on the sphere at noon.
// The azimuth choice is arbitrary, but ideally shouldn't be on an axis.
sun_rotation = Vector2 ( - Math : : deg2rad ( 60.0 ) , Math : : deg2rad ( 150.0 ) ) ;
2021-02-22 13:54:12 +00:00
2021-02-22 21:20:44 +00:00
sun_angle_altitude - > set_value ( - Math : : rad2deg ( sun_rotation . x ) ) ;
sun_angle_azimuth - > set_value ( 180.0 - Math : : rad2deg ( sun_rotation . y ) ) ;
2021-02-22 13:54:12 +00:00
sun_direction - > update ( ) ;
2022-02-11 21:59:35 +00:00
environ_sky_color - > set_pick_color ( Color ( 0.385 , 0.454 , 0.55 ) ) ;
environ_ground_color - > set_pick_color ( Color ( 0.2 , 0.169 , 0.133 ) ) ;
2021-02-22 13:54:12 +00:00
environ_energy - > set_value ( 1.0 ) ;
environ_glow_button - > set_pressed ( true ) ;
environ_tonemap_button - > set_pressed ( true ) ;
environ_ao_button - > set_pressed ( false ) ;
environ_gi_button - > set_pressed ( false ) ;
sun_max_distance - > set_value ( 250 ) ;
sun_color - > set_pick_color ( Color ( 1 , 1 , 1 ) ) ;
sun_energy - > set_value ( 1.0 ) ;
sun_environ_updating = false ;
}
void Node3DEditor : : _update_preview_environment ( ) {
bool disable_light = directional_light_count > 0 | | sun_button - > is_pressed ( ) ;
sun_button - > set_disabled ( directional_light_count > 0 ) ;
if ( disable_light ) {
if ( preview_sun - > get_parent ( ) ) {
preview_sun - > get_parent ( ) - > remove_child ( preview_sun ) ;
sun_state - > show ( ) ;
sun_vb - > hide ( ) ;
}
if ( directional_light_count > 0 ) {
2021-02-23 11:55:29 +00:00
sun_state - > set_text ( TTR ( " Scene contains \n DirectionalLight3D. \n Preview disabled. " ) ) ;
2021-02-22 13:54:12 +00:00
} else {
2021-02-23 11:55:29 +00:00
sun_state - > set_text ( TTR ( " Preview disabled. " ) ) ;
2021-02-22 13:54:12 +00:00
}
} else {
if ( ! preview_sun - > get_parent ( ) ) {
2021-11-06 23:40:15 +00:00
add_child ( preview_sun , true ) ;
2021-02-22 13:54:12 +00:00
sun_state - > hide ( ) ;
sun_vb - > show ( ) ;
}
}
2021-02-22 21:20:44 +00:00
sun_angle_altitude - > set_value ( - Math : : rad2deg ( sun_rotation . x ) ) ;
sun_angle_azimuth - > set_value ( 180.0 - Math : : rad2deg ( sun_rotation . y ) ) ;
2021-02-22 13:54:12 +00:00
bool disable_env = world_env_count > 0 | | environ_button - > is_pressed ( ) ;
environ_button - > set_disabled ( world_env_count > 0 ) ;
if ( disable_env ) {
if ( preview_environment - > get_parent ( ) ) {
preview_environment - > get_parent ( ) - > remove_child ( preview_environment ) ;
environ_state - > show ( ) ;
environ_vb - > hide ( ) ;
}
if ( world_env_count > 0 ) {
2021-02-23 11:55:29 +00:00
environ_state - > set_text ( TTR ( " Scene contains \n WorldEnvironment. \n Preview disabled. " ) ) ;
2021-02-22 13:54:12 +00:00
} else {
2021-02-23 11:55:29 +00:00
environ_state - > set_text ( TTR ( " Preview disabled. " ) ) ;
2021-02-22 13:54:12 +00:00
}
} else {
if ( ! preview_environment - > get_parent ( ) ) {
add_child ( preview_environment ) ;
environ_state - > hide ( ) ;
environ_vb - > show ( ) ;
}
}
}
void Node3DEditor : : _sun_direction_input ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseMotion > mm = p_event ;
2021-08-13 21:31:57 +00:00
if ( mm . is_valid ( ) & & ( mm - > get_button_mask ( ) & MouseButton : : MASK_LEFT ) ! = MouseButton : : NONE ) {
2021-02-22 21:20:44 +00:00
sun_rotation . x + = mm - > get_relative ( ) . y * ( 0.02 * EDSCALE ) ;
sun_rotation . y - = mm - > get_relative ( ) . x * ( 0.02 * EDSCALE ) ;
sun_rotation . x = CLAMP ( sun_rotation . x , - Math_TAU / 4 , Math_TAU / 4 ) ;
sun_angle_altitude - > set_value ( - Math : : rad2deg ( sun_rotation . x ) ) ;
sun_angle_azimuth - > set_value ( 180.0 - Math : : rad2deg ( sun_rotation . y ) ) ;
2021-02-22 13:54:12 +00:00
_preview_settings_changed ( ) ;
}
}
2021-02-22 21:20:44 +00:00
void Node3DEditor : : _sun_direction_angle_set ( ) {
sun_rotation . x = Math : : deg2rad ( - sun_angle_altitude - > get_value ( ) ) ;
sun_rotation . y = Math : : deg2rad ( 180.0 - sun_angle_azimuth - > get_value ( ) ) ;
_preview_settings_changed ( ) ;
}
2022-01-27 09:36:51 +00:00
Node3DEditor : : Node3DEditor ( ) {
2017-03-05 15:44:50 +00:00
gizmo . visible = true ;
gizmo . scale = 1.0 ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
viewport_environment = Ref < Environment > ( memnew ( Environment ) ) ;
2022-01-27 09:36:51 +00:00
undo_redo = EditorNode : : get_singleton ( ) - > get_undo_redo ( ) ;
2014-02-10 01:10:30 +00:00
VBoxContainer * vbc = this ;
2020-04-01 23:20:12 +00:00
custom_camera = nullptr ;
2017-03-05 15:44:50 +00:00
singleton = this ;
2022-01-27 09:36:51 +00:00
editor_selection = EditorNode : : get_singleton ( ) - > get_editor_selection ( ) ;
2014-02-10 01:10:30 +00:00
editor_selection - > add_editor_plugin ( this ) ;
2017-03-05 15:44:50 +00:00
snap_enabled = false ;
2018-02-21 14:14:26 +00:00
snap_key_enabled = false ;
2014-02-10 01:10:30 +00:00
tool_mode = TOOL_MODE_SELECT ;
2019-04-06 20:55:01 +00:00
camera_override_viewport_id = 0 ;
2022-07-20 01:00:25 +00:00
// A fluid container for all toolbars.
HFlowContainer * main_flow = memnew ( HFlowContainer ) ;
vbc - > add_child ( main_flow ) ;
// Main toolbars.
HBoxContainer * main_menu_hbox = memnew ( HBoxContainer ) ;
main_flow - > add_child ( main_menu_hbox ) ;
2014-02-10 01:10:30 +00:00
Vector < Variant > button_binds ;
button_binds . resize ( 1 ) ;
2017-11-18 18:51:37 +00:00
String sct ;
2014-02-10 01:10:30 +00:00
2019-03-23 00:57:28 +00:00
// Add some margin to the left for better aesthetics.
// This prevents the first button's hover/pressed effect from "touching" the panel's border,
// which looks ugly.
Control * margin_left = memnew ( Control ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( margin_left ) ;
2019-03-23 00:57:28 +00:00
margin_left - > set_custom_minimum_size ( Size2 ( 2 , 0 ) * EDSCALE ) ;
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_MODE_SELECT ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_MODE_SELECT ] ) ;
2014-02-10 01:10:30 +00: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 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_SELECT ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_MODE_SELECT ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_MODE_SELECT ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_select " , TTR ( " Select Mode " ) , Key : : Q ) ) ;
2020-09-17 01:40:00 +00:00
tool_button [ TOOL_MODE_SELECT ] - > set_shortcut_context ( this ) ;
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_MODE_SELECT ] - > set_tooltip ( keycode_get_string ( ( Key ) KeyModifierMask : : CMD ) + TTR ( " Drag: Rotate selected node around pivot. " ) + " \n " + TTR ( " Alt+RMB: Show list of all nodes at position clicked, including locked. " ) ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2018-09-15 15:44:26 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_MODE_MOVE ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_MODE_MOVE ] ) ;
2014-02-10 01:10:30 +00:00
tool_button [ TOOL_MODE_MOVE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_MOVE ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_MOVE ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_MODE_MOVE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_MODE_MOVE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_move " , TTR ( " Move Mode " ) , Key : : W ) ) ;
2020-09-17 01:40:00 +00:00
tool_button [ TOOL_MODE_MOVE ] - > set_shortcut_context ( this ) ;
2014-02-10 01:10:30 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_MODE_ROTATE ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_MODE_ROTATE ] ) ;
2014-02-10 01:10:30 +00:00
tool_button [ TOOL_MODE_ROTATE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_ROTATE ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_ROTATE ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_MODE_ROTATE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_MODE_ROTATE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_rotate " , TTR ( " Rotate Mode " ) , Key : : E ) ) ;
2020-09-17 01:40:00 +00:00
tool_button [ TOOL_MODE_ROTATE ] - > set_shortcut_context ( this ) ;
2014-02-10 01:10:30 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_MODE_SCALE ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_MODE_SCALE ] ) ;
2014-02-10 01:10:30 +00:00
tool_button [ TOOL_MODE_SCALE ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_SCALE ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_SCALE ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_MODE_SCALE ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_MODE_SCALE ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/tool_scale " , TTR ( " Scale Mode " ) , Key : : R ) ) ;
2020-09-17 01:40:00 +00:00
tool_button [ TOOL_MODE_SCALE ] - > set_shortcut_context ( this ) ;
2014-02-10 01:10:30 +00:00
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2018-09-15 15:44:26 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_MODE_LIST_SELECT ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_MODE_LIST_SELECT ] ) ;
2015-12-13 20:16:13 +00:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_toggle_mode ( true ) ;
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_LIST_SELECT ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-06-04 13:31:28 +00:00
tool_button [ TOOL_MODE_LIST_SELECT ] - > set_tooltip ( TTR ( " Show list of selectable nodes at position clicked. " ) ) ;
2015-12-13 20:16:13 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_LOCK_SELECTED ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_LOCK_SELECTED ] ) ;
2020-06-24 15:09:53 +00:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_LOCK_SELECTED ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_LOCK_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-06-04 13:31:28 +00:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_tooltip ( TTR ( " Lock selected node, preventing selection and movement. " ) ) ;
2021-06-30 21:09:26 +00:00
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_LOCK_SELECTED ] - > set_shortcut ( ED_SHORTCUT ( " editor/lock_selected_nodes " , TTR ( " Lock Selected Node(s) " ) , KeyModifierMask : : CMD | Key : : L ) ) ;
2017-10-23 19:21:15 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_UNLOCK_SELECTED ] ) ;
2020-06-24 15:09:53 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_UNLOCK_SELECTED ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2021-06-04 13:31:28 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_tooltip ( TTR ( " Unlock selected node, allowing selection and movement. " ) ) ;
2021-06-30 21:09:26 +00:00
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_UNLOCK_SELECTED ] - > set_shortcut ( ED_SHORTCUT ( " editor/unlock_selected_nodes " , TTR ( " Unlock Selected Node(s) " ) , KeyModifierMask : : CMD | KeyModifierMask : : SHIFT | Key : : L ) ) ;
2017-10-23 19:21:15 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_GROUP_SELECTED ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_GROUP_SELECTED ] ) ;
2020-06-24 15:09:53 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_flat ( true ) ;
2019-04-17 16:24:28 +00:00
button_binds . write [ 0 ] = MENU_GROUP_SELECTED ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-04-17 16:24:28 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_tooltip ( TTR ( " Makes sure the object's children are not selectable. " ) ) ;
2021-06-30 21:09:26 +00:00
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_GROUP_SELECTED ] - > set_shortcut ( ED_SHORTCUT ( " editor/group_selected_nodes " , TTR ( " Group Selected Node(s) " ) , KeyModifierMask : : CMD | Key : : G ) ) ;
2019-04-17 16:24:28 +00:00
2020-06-19 18:49:04 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_button [ TOOL_UNGROUP_SELECTED ] ) ;
2020-06-24 15:09:53 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_flat ( true ) ;
2019-04-17 16:24:28 +00:00
button_binds . write [ 0 ] = MENU_UNGROUP_SELECTED ;
2020-03-26 21:49:16 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) , button_binds ) ;
2019-04-17 16:24:28 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_tooltip ( TTR ( " Restores the object's children's ability to be selected. " ) ) ;
2021-06-30 21:09:26 +00:00
// Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused.
2021-08-13 21:31:57 +00:00
tool_button [ TOOL_UNGROUP_SELECTED ] - > set_shortcut ( ED_SHORTCUT ( " editor/ungroup_selected_nodes " , TTR ( " Ungroup Selected Node(s) " ) , KeyModifierMask : : CMD | KeyModifierMask : : SHIFT | Key : : G ) ) ;
2019-04-17 16:24:28 +00:00
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2017-11-18 18:51:37 +00:00
2020-06-19 18:49:04 +00:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_option_button [ TOOL_OPT_LOCAL_COORDS ] ) ;
2017-11-18 18:51:37 +00:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_toggle_mode ( true ) ;
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_LOCAL_COORDS ;
2020-03-26 21:49:16 +00:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2021-08-13 21:31:57 +00: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 01:40:00 +00:00
tool_option_button [ TOOL_OPT_LOCAL_COORDS ] - > set_shortcut_context ( this ) ;
2017-11-18 18:51:37 +00:00
2020-06-19 18:49:04 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_option_button [ TOOL_OPT_USE_SNAP ] ) ;
2017-11-18 18:51:37 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_toggle_mode ( true ) ;
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_flat ( true ) ;
2018-07-25 01:11:03 +00:00
button_binds . write [ 0 ] = MENU_TOOL_USE_SNAP ;
2020-03-26 21:49:16 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2021-08-13 21:31:57 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_shortcut ( ED_SHORTCUT ( " spatial_editor/snap " , TTR ( " Use Snap " ) , Key : : Y ) ) ;
2020-09-17 01:40:00 +00:00
tool_option_button [ TOOL_OPT_USE_SNAP ] - > set_shortcut_context ( this ) ;
2017-11-18 18:51:37 +00:00
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2015-12-13 20:16:13 +00:00
2020-06-19 18:49:04 +00:00
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] = memnew ( Button ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] ) ;
2019-04-06 20:55:01 +00:00
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 21:49:16 +00:00
tool_option_button [ TOOL_OPT_OVERRIDE_CAMERA ] - > connect ( " toggled " , callable_mp ( this , & Node3DEditor : : _menu_item_toggled ) , button_binds ) ;
2019-04-06 20:55:01 +00:00
_update_camera_override_button ( false ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2021-02-22 13:54:12 +00:00
sun_button = memnew ( Button ) ;
sun_button - > set_tooltip ( TTR ( " Toggle preview sunlight. \n If a DirectionalLight3D node is added to the scene, preview sunlight is disabled. " ) ) ;
sun_button - > set_toggle_mode ( true ) ;
sun_button - > set_flat ( true ) ;
sun_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _update_preview_environment ) , varray ( ) , CONNECT_DEFERRED ) ;
sun_button - > set_disabled ( true ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( sun_button ) ;
2021-02-22 13:54:12 +00:00
environ_button = memnew ( Button ) ;
environ_button - > set_tooltip ( TTR ( " Toggle preview environment. \n If a WorldEnvironment node is added to the scene, preview environment is disabled. " ) ) ;
environ_button - > set_toggle_mode ( true ) ;
environ_button - > set_flat ( true ) ;
environ_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _update_preview_environment ) , varray ( ) , CONNECT_DEFERRED ) ;
environ_button - > set_disabled ( true ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( environ_button ) ;
2021-02-22 13:54:12 +00:00
sun_environ_settings = memnew ( Button ) ;
sun_environ_settings - > set_tooltip ( TTR ( " Edit Sun and Environment settings. " ) ) ;
sun_environ_settings - > set_flat ( true ) ;
sun_environ_settings - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _sun_environ_settings_pressed ) ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( sun_environ_settings ) ;
2021-02-22 13:54:12 +00:00
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2019-04-06 20:55:01 +00:00
2017-09-02 19:47:16 +00:00
// Drag and drop support;
2020-03-26 21:49:16 +00:00
preview_node = memnew ( Node3D ) ;
2017-11-17 02:09:00 +00:00
preview_bounds = AABB ( ) ;
2017-09-02 19:47:16 +00:00
2021-08-13 21:31:57 +00:00
ED_SHORTCUT ( " spatial_editor/bottom_view " , TTR ( " Bottom View " ) , KeyModifierMask : : ALT + Key : : KP_7 ) ;
ED_SHORTCUT ( " spatial_editor/top_view " , TTR ( " Top View " ) , Key : : KP_7 ) ;
ED_SHORTCUT ( " spatial_editor/rear_view " , TTR ( " Rear View " ) , KeyModifierMask : : ALT + Key : : KP_1 ) ;
ED_SHORTCUT ( " spatial_editor/front_view " , TTR ( " Front View " ) , Key : : KP_1 ) ;
ED_SHORTCUT ( " spatial_editor/left_view " , TTR ( " Left View " ) , KeyModifierMask : : ALT + Key : : KP_3 ) ;
ED_SHORTCUT ( " spatial_editor/right_view " , TTR ( " Right View " ) , Key : : KP_3 ) ;
ED_SHORTCUT ( " spatial_editor/orbit_view_down " , TTR ( " Orbit View Down " ) , Key : : KP_2 ) ;
ED_SHORTCUT ( " spatial_editor/orbit_view_left " , TTR ( " Orbit View Left " ) , Key : : KP_4 ) ;
ED_SHORTCUT ( " spatial_editor/orbit_view_right " , TTR ( " Orbit View Right " ) , Key : : KP_6 ) ;
ED_SHORTCUT ( " spatial_editor/orbit_view_up " , TTR ( " Orbit View Up " ) , Key : : KP_8 ) ;
ED_SHORTCUT ( " spatial_editor/orbit_view_180 " , TTR ( " Orbit View 180 " ) , Key : : KP_9 ) ;
ED_SHORTCUT ( " spatial_editor/switch_perspective_orthogonal " , TTR ( " Switch Perspective/Orthogonal View " ) , Key : : KP_5 ) ;
ED_SHORTCUT ( " spatial_editor/insert_anim_key " , TTR ( " Insert Animation Key " ) , Key : : K ) ;
ED_SHORTCUT ( " spatial_editor/focus_origin " , TTR ( " Focus Origin " ) , Key : : O ) ;
ED_SHORTCUT ( " spatial_editor/focus_selection " , TTR ( " Focus Selection " ) , Key : : F ) ;
ED_SHORTCUT ( " spatial_editor/align_transform_with_view " , TTR ( " Align Transform with View " ) , KeyModifierMask : : ALT + KeyModifierMask : : CMD + Key : : M ) ;
ED_SHORTCUT ( " spatial_editor/align_rotation_with_view " , TTR ( " Align Rotation with View " ) , KeyModifierMask : : ALT + KeyModifierMask : : CMD + Key : : F ) ;
ED_SHORTCUT ( " spatial_editor/freelook_toggle " , TTR ( " Toggle Freelook " ) , KeyModifierMask : : SHIFT + Key : : F ) ;
ED_SHORTCUT ( " spatial_editor/decrease_fov " , TTR ( " Decrease Field of View " ) , KeyModifierMask : : CMD + Key : : EQUAL ) ; // Usually direct access key for `KEY_PLUS`.
ED_SHORTCUT ( " spatial_editor/increase_fov " , TTR ( " Increase Field of View " ) , KeyModifierMask : : CMD + Key : : MINUS ) ;
ED_SHORTCUT ( " spatial_editor/reset_fov " , TTR ( " Reset Field of View to Default " ) , KeyModifierMask : : CMD + Key : : KEY_0 ) ;
2017-10-30 00:22:48 +00:00
2014-02-10 01:10:30 +00:00
PopupMenu * p ;
2017-03-05 15:44:50 +00:00
transform_menu = memnew ( MenuButton ) ;
2016-05-30 18:47:53 +00:00
transform_menu - > set_text ( TTR ( " Transform " ) ) ;
2018-07-29 22:26:43 +00:00
transform_menu - > set_switch_on_hover ( true ) ;
2020-09-17 01:40:00 +00:00
transform_menu - > set_shortcut_context ( this ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( transform_menu ) ;
2014-02-10 01:10:30 +00:00
p = transform_menu - > get_popup ( ) ;
2021-08-13 21:31:57 +00: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 17:36:01 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/transform_dialog " , TTR ( " Transform Dialog... " ) ) , MENU_TRANSFORM_DIALOG ) ;
2014-02-10 01:10:30 +00:00
2019-08-12 20:23:00 +00:00
p - > add_separator ( ) ;
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/configure_snap " , TTR ( " Configure Snap... " ) ) , MENU_TRANSFORM_CONFIGURE_SNAP ) ;
2020-03-26 21:49:16 +00:00
p - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
view_menu = memnew ( MenuButton ) ;
2022-06-08 09:42:51 +00:00
// TRANSLATORS: Noun, name of the 2D/3D View menus.
2016-05-04 01:25:37 +00:00
view_menu - > set_text ( TTR ( " View " ) ) ;
2018-07-29 22:26:43 +00:00
view_menu - > set_switch_on_hover ( true ) ;
2020-09-17 01:40:00 +00:00
view_menu - > set_shortcut_context ( this ) ;
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( view_menu ) ;
2020-02-03 19:07:21 +00:00
2022-07-20 01:00:25 +00:00
main_menu_hbox - > add_child ( memnew ( VSeparator ) ) ;
2020-02-03 19:07:21 +00:00
2022-07-20 01:00:25 +00:00
context_menu_panel = memnew ( PanelContainer ) ;
context_menu_hbox = memnew ( HBoxContainer ) ;
context_menu_panel - > add_child ( context_menu_hbox ) ;
main_flow - > add_child ( context_menu_panel ) ;
2014-02-10 01:10:30 +00:00
2021-07-31 20:33:38 +00:00
// Get the view menu popup and have it stay open when a checkable item is selected
2014-02-10 01:10:30 +00:00
p = view_menu - > get_popup ( ) ;
2021-07-31 20:33:38 +00:00
p - > set_hide_on_checkable_item_selection ( false ) ;
2014-02-10 01:10:30 +00:00
2017-09-02 19:47:16 +00:00
accept = memnew ( AcceptDialog ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > add_child ( accept ) ;
2017-09-02 19:47:16 +00:00
2021-08-13 21:31:57 +00:00
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/1_viewport " , TTR ( " 1 Viewport " ) , KeyModifierMask : : CMD + Key : : KEY_1 ) , MENU_VIEW_USE_1_VIEWPORT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/2_viewports " , TTR ( " 2 Viewports " ) , KeyModifierMask : : CMD + Key : : KEY_2 ) , MENU_VIEW_USE_2_VIEWPORTS ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/2_viewports_alt " , TTR ( " 2 Viewports (Alt) " ) , KeyModifierMask : : ALT + KeyModifierMask : : CMD + Key : : KEY_2 ) , MENU_VIEW_USE_2_VIEWPORTS_ALT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/3_viewports " , TTR ( " 3 Viewports " ) , KeyModifierMask : : CMD + Key : : KEY_3 ) , MENU_VIEW_USE_3_VIEWPORTS ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/3_viewports_alt " , TTR ( " 3 Viewports (Alt) " ) , KeyModifierMask : : ALT + KeyModifierMask : : CMD + Key : : KEY_3 ) , MENU_VIEW_USE_3_VIEWPORTS_ALT ) ;
p - > add_radio_check_shortcut ( ED_SHORTCUT ( " spatial_editor/4_viewports " , TTR ( " 4 Viewports " ) , KeyModifierMask : : CMD + Key : : KEY_4 ) , MENU_VIEW_USE_4_VIEWPORTS ) ;
2014-02-10 01:10:30 +00:00
p - > add_separator ( ) ;
2018-08-11 21:07:00 +00:00
p - > add_submenu_item ( TTR ( " Gizmos " ) , " GizmosMenu " ) ;
2018-08-12 13:20:20 +00:00
p - > add_separator ( ) ;
2016-06-30 20:54:34 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_origin " , TTR ( " View Origin " ) ) , MENU_VIEW_ORIGIN ) ;
2021-08-13 21:31:57 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " spatial_editor/view_grid " , TTR ( " View Grid " ) , Key : : NUMBERSIGN ) , MENU_VIEW_GRID ) ;
2019-08-12 20:23:00 +00:00
2014-02-10 01:10:30 +00:00
p - > add_separator ( ) ;
2019-08-12 20:23:00 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " spatial_editor/settings " , TTR ( " Settings... " ) ) , MENU_VIEW_CAMERA_SETTINGS ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00: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 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
p - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_item_pressed ) ) ;
2014-02-10 01:10:30 +00:00
2018-08-11 21:07:00 +00: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 21:49:16 +00:00
gizmos_menu - > connect ( " id_pressed " , callable_mp ( this , & Node3DEditor : : _menu_gizmo_toggled ) ) ;
2018-07-24 22:08:49 +00:00
2014-02-10 01:10:30 +00:00
/* REST OF MENU */
2022-01-08 12:31:22 +00:00
left_panel_split = memnew ( HSplitContainer ) ;
left_panel_split - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
vbc - > add_child ( left_panel_split ) ;
right_panel_split = memnew ( HSplitContainer ) ;
right_panel_split - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
left_panel_split - > add_child ( right_panel_split ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
shader_split = memnew ( VSplitContainer ) ;
2014-02-10 01:10:30 +00:00
shader_split - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2022-01-08 12:31:22 +00:00
right_panel_split - > add_child ( shader_split ) ;
2020-03-26 21:49:16 +00:00
viewport_base = memnew ( Node3DEditorViewportContainer ) ;
2014-02-10 01:10:30 +00:00
shader_split - > add_child ( viewport_base ) ;
viewport_base - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2017-08-31 21:30:35 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; i + + ) {
2022-01-27 09:36:51 +00:00
viewports [ i ] = memnew ( Node3DEditorViewport ( this , i ) ) ;
2020-03-26 21:49:16 +00:00
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 19:47:16 +00:00
viewports [ i ] - > assign_pending_data_pointers ( preview_node , & preview_bounds , accept ) ;
2014-02-10 01:10:30 +00:00
viewport_base - > add_child ( viewports [ i ] ) ;
}
/* SNAP DIALOG */
2020-03-08 19:31:11 +00:00
snap_translate_value = 1 ;
snap_rotate_value = 15 ;
snap_scale_value = 10 ;
2017-03-05 15:44:50 +00:00
snap_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 01:25:37 +00:00
snap_dialog - > set_title ( TTR ( " Snap Settings " ) ) ;
2014-02-10 01:10:30 +00:00
add_child ( snap_dialog ) ;
2020-03-26 21:49:16 +00:00
snap_dialog - > connect ( " confirmed " , callable_mp ( this , & Node3DEditor : : _snap_changed ) ) ;
2020-12-14 18:37:30 +00:00
snap_dialog - > get_cancel_button ( ) - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _snap_update ) ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
VBoxContainer * snap_dialog_vbc = memnew ( VBoxContainer ) ;
2015-10-18 16:31:44 +00:00
snap_dialog - > add_child ( snap_dialog_vbc ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
snap_translate = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Translate Snap: " ) , snap_translate ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
snap_rotate = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Rotate Snap (deg.): " ) , snap_rotate ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
snap_scale = memnew ( LineEdit ) ;
snap_dialog_vbc - > add_margin_child ( TTR ( " Scale Snap (%): " ) , snap_scale ) ;
2014-02-10 01:10:30 +00:00
2020-03-08 19:31:11 +00:00
_snap_update ( ) ;
2015-10-18 16:31:44 +00:00
/* SETTINGS DIALOG */
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
settings_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 01:25:37 +00:00
settings_dialog - > set_title ( TTR ( " Viewport Settings " ) ) ;
2014-02-10 01:10:30 +00:00
add_child ( settings_dialog ) ;
2017-03-05 15:44:50 +00:00
settings_vbc = memnew ( VBoxContainer ) ;
2017-08-04 11:23:10 +00:00
settings_vbc - > set_custom_minimum_size ( Size2 ( 200 , 0 ) * EDSCALE ) ;
2014-10-12 05:13:22 +00:00
settings_dialog - > add_child ( settings_vbc ) ;
2017-03-05 15:44:50 +00:00
settings_fov = memnew ( SpinBox ) ;
2017-08-04 11:23:10 +00:00
settings_fov - > set_max ( MAX_FOV ) ;
settings_fov - > set_min ( MIN_FOV ) ;
2019-10-31 13:32:46 +00:00
settings_fov - > set_step ( 0.1 ) ;
settings_fov - > set_value ( EDITOR_GET ( " editors/3d/default_fov " ) ) ;
2017-03-05 15:44:50 +00:00
settings_vbc - > add_margin_child ( TTR ( " Perspective FOV (deg.): " ) , settings_fov ) ;
2014-10-12 05:13:22 +00:00
2017-03-05 15:44:50 +00:00
settings_znear = memnew ( SpinBox ) ;
2017-08-04 11:23:10 +00:00
settings_znear - > set_max ( MAX_Z ) ;
settings_znear - > set_min ( MIN_Z ) ;
2014-10-12 05:13:22 +00:00
settings_znear - > set_step ( 0.01 ) ;
2019-10-31 13:32:46 +00:00
settings_znear - > set_value ( EDITOR_GET ( " editors/3d/default_z_near " ) ) ;
2017-03-05 15:44:50 +00:00
settings_vbc - > add_margin_child ( TTR ( " View Z-Near: " ) , settings_znear ) ;
2014-10-12 05:13:22 +00:00
2017-03-05 15:44:50 +00:00
settings_zfar = memnew ( SpinBox ) ;
2017-08-04 11:23:10 +00:00
settings_zfar - > set_max ( MAX_Z ) ;
settings_zfar - > set_min ( MIN_Z ) ;
2019-10-31 13:32:46 +00:00
settings_zfar - > set_step ( 0.1 ) ;
settings_zfar - > set_value ( EDITOR_GET ( " editors/3d/default_z_far " ) ) ;
2017-03-05 15:44:50 +00:00
settings_vbc - > add_margin_child ( TTR ( " View Z-Far: " ) , settings_zfar ) ;
2014-02-10 01:10:30 +00:00
2020-03-10 16:56:46 +00:00
for ( uint32_t i = 0 ; i < VIEWPORTS_COUNT ; + + i ) {
2021-10-14 22:00:27 +00:00
settings_dialog - > connect ( " confirmed " , callable_mp ( viewports [ i ] , & Node3DEditorViewport : : _view_settings_confirmed ) , varray ( 0.0 ) ) ;
2020-03-10 16:56:46 +00:00
}
2014-02-10 01:10:30 +00:00
/* XFORM DIALOG */
2017-03-05 15:44:50 +00:00
xform_dialog = memnew ( ConfirmationDialog ) ;
2016-05-04 01:25:37 +00:00
xform_dialog - > set_title ( TTR ( " Transform Change " ) ) ;
2014-02-10 01:10:30 +00:00
add_child ( xform_dialog ) ;
2017-07-31 13:00:02 +00:00
VBoxContainer * xform_vbc = memnew ( VBoxContainer ) ;
xform_dialog - > add_child ( xform_vbc ) ;
2015-10-18 16:31:44 +00:00
Label * l = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
l - > set_text ( TTR ( " Translate: " ) ) ;
2017-07-31 13:00:02 +00:00
xform_vbc - > add_child ( l ) ;
HBoxContainer * xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_translate [ i ] = memnew ( LineEdit ) ;
2017-07-31 13:00:02 +00:00
xform_translate [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_translate [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
l = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
l - > set_text ( TTR ( " Rotate (deg.): " ) ) ;
2017-07-31 13:00:02 +00:00
xform_vbc - > add_child ( l ) ;
xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_rotate [ i ] = memnew ( LineEdit ) ;
2017-07-31 13:00:02 +00:00
xform_rotate [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_rotate [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
l = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
l - > set_text ( TTR ( " Scale (ratio): " ) ) ;
2017-07-31 13:00:02 +00:00
xform_vbc - > add_child ( l ) ;
xform_hbc = memnew ( HBoxContainer ) ;
xform_vbc - > add_child ( xform_hbc ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
xform_scale [ i ] = memnew ( LineEdit ) ;
2017-07-31 13:00:02 +00:00
xform_scale [ i ] - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
xform_hbc - > add_child ( xform_scale [ i ] ) ;
2014-02-10 01:10:30 +00:00
}
l = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
l - > set_text ( TTR ( " Transform Type " ) ) ;
2017-07-31 13:00:02 +00:00
xform_vbc - > add_child ( l ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
xform_type = memnew ( OptionButton ) ;
2017-07-31 13:00:02 +00:00
xform_type - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2016-05-04 01:25:37 +00:00
xform_type - > add_item ( TTR ( " Pre " ) ) ;
xform_type - > add_item ( TTR ( " Post " ) ) ;
2017-07-31 13:00:02 +00:00
xform_vbc - > add_child ( xform_type ) ;
2014-02-10 01:10:30 +00:00
2020-03-26 21:49:16 +00:00
xform_dialog - > connect ( " confirmed " , callable_mp ( this , & Node3DEditor : : _xform_dialog_action ) ) ;
2014-02-10 01:10:30 +00:00
2020-04-01 23:20:12 +00:00
selected = nullptr ;
2014-02-10 01:10:30 +00:00
2022-01-11 13:59:52 +00:00
set_process_shortcut_input ( true ) ;
2014-02-10 01:10:30 +00:00
add_to_group ( " _spatial_editor_group " ) ;
2014-05-05 01:50:23 +00:00
2017-03-05 15:44:50 +00:00
EDITOR_DEF ( " editors/3d/manipulator_gizmo_size " , 80 ) ;
2020-12-14 22:33:47 +00: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 18:20:53 +00: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 09:46:26 +00:00
EDITOR_DEF ( " editors/3d/navigation/show_viewport_rotation_gizmo " , true ) ;
2014-05-05 01:50:23 +00:00
2021-06-23 14:49:50 +00:00
current_hover_gizmo_handle = - 1 ;
2022-01-11 11:33:37 +00:00
current_hover_gizmo_handle_secondary = false ;
2021-02-22 13:54:12 +00:00
{
//sun popup
sun_environ_popup = memnew ( PopupPanel ) ;
add_child ( sun_environ_popup ) ;
HBoxContainer * sun_environ_hb = memnew ( HBoxContainer ) ;
sun_environ_popup - > add_child ( sun_environ_hb ) ;
sun_vb = memnew ( VBoxContainer ) ;
sun_environ_hb - > add_child ( sun_vb ) ;
sun_vb - > set_custom_minimum_size ( Size2 ( 200 * EDSCALE , 0 ) ) ;
sun_vb - > hide ( ) ;
sun_title = memnew ( Label ) ;
2021-07-08 13:29:15 +00:00
sun_title - > set_theme_type_variation ( " HeaderSmall " ) ;
2021-02-22 13:54:12 +00:00
sun_vb - > add_child ( sun_title ) ;
sun_title - > set_text ( TTR ( " Preview Sun " ) ) ;
2021-11-25 02:58:47 +00:00
sun_title - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2021-02-22 13:54:12 +00:00
CenterContainer * sun_direction_center = memnew ( CenterContainer ) ;
sun_direction = memnew ( Control ) ;
sun_direction - > set_custom_minimum_size ( Size2i ( 128 , 128 ) * EDSCALE ) ;
sun_direction_center - > add_child ( sun_direction ) ;
sun_vb - > add_margin_child ( TTR ( " Sun Direction " ) , sun_direction_center ) ;
sun_direction - > connect ( " gui_input " , callable_mp ( this , & Node3DEditor : : _sun_direction_input ) ) ;
sun_direction - > connect ( " draw " , callable_mp ( this , & Node3DEditor : : _sun_direction_draw ) ) ;
sun_direction - > set_default_cursor_shape ( CURSOR_MOVE ) ;
2021-06-17 22:03:09 +00:00
sun_direction_shader . instantiate ( ) ;
2021-07-19 06:06:51 +00:00
sun_direction_shader - > set_code ( R " (
2021-08-18 01:09:22 +00:00
// 3D editor Preview Sun direction shader.
2021-07-19 06:06:51 +00:00
shader_type canvas_item ;
uniform vec3 sun_direction ;
uniform vec3 sun_color ;
void fragment ( ) {
vec3 n ;
n . xy = UV * 2.0 - 1.0 ;
n . z = sqrt ( max ( 0.0 , 1.0 - dot ( n . xy , n . xy ) ) ) ;
COLOR . rgb = dot ( n , sun_direction ) * sun_color ;
COLOR . a = 1.0 - smoothstep ( 0.99 , 1.0 , length ( n . xy ) ) ;
}
) " );
2021-06-17 22:03:09 +00:00
sun_direction_material . instantiate ( ) ;
2021-02-22 13:54:12 +00:00
sun_direction_material - > set_shader ( sun_direction_shader ) ;
sun_direction_material - > set_shader_param ( " sun_direction " , Vector3 ( 0 , 0 , 1 ) ) ;
sun_direction_material - > set_shader_param ( " sun_color " , Vector3 ( 1 , 1 , 1 ) ) ;
sun_direction - > set_material ( sun_direction_material ) ;
2021-02-22 21:20:44 +00:00
HBoxContainer * sun_angle_hbox = memnew ( HBoxContainer ) ;
VBoxContainer * sun_angle_altitude_vbox = memnew ( VBoxContainer ) ;
Label * sun_angle_altitude_label = memnew ( Label ) ;
sun_angle_altitude_label - > set_text ( TTR ( " Angular Altitude " ) ) ;
sun_angle_altitude_vbox - > add_child ( sun_angle_altitude_label ) ;
sun_angle_altitude = memnew ( EditorSpinSlider ) ;
sun_angle_altitude - > set_max ( 90 ) ;
sun_angle_altitude - > set_min ( - 90 ) ;
sun_angle_altitude - > set_step ( 0.1 ) ;
sun_angle_altitude - > connect ( " value_changed " , callable_mp ( this , & Node3DEditor : : _sun_direction_angle_set ) . unbind ( 1 ) ) ;
sun_angle_altitude_vbox - > add_child ( sun_angle_altitude ) ;
sun_angle_hbox - > add_child ( sun_angle_altitude_vbox ) ;
VBoxContainer * sun_angle_azimuth_vbox = memnew ( VBoxContainer ) ;
sun_angle_azimuth_vbox - > set_custom_minimum_size ( Vector2 ( 100 , 0 ) ) ;
Label * sun_angle_azimuth_label = memnew ( Label ) ;
sun_angle_azimuth_label - > set_text ( TTR ( " Azimuth " ) ) ;
sun_angle_azimuth_vbox - > add_child ( sun_angle_azimuth_label ) ;
sun_angle_azimuth = memnew ( EditorSpinSlider ) ;
sun_angle_azimuth - > set_max ( 180 ) ;
sun_angle_azimuth - > set_min ( - 180 ) ;
sun_angle_azimuth - > set_step ( 0.1 ) ;
sun_angle_azimuth - > set_allow_greater ( true ) ;
sun_angle_azimuth - > set_allow_lesser ( true ) ;
sun_angle_azimuth - > connect ( " value_changed " , callable_mp ( this , & Node3DEditor : : _sun_direction_angle_set ) . unbind ( 1 ) ) ;
sun_angle_azimuth_vbox - > add_child ( sun_angle_azimuth ) ;
sun_angle_hbox - > add_child ( sun_angle_azimuth_vbox ) ;
2022-02-08 09:14:58 +00:00
sun_angle_hbox - > add_theme_constant_override ( " separation " , 10 ) ;
2021-02-22 21:20:44 +00:00
sun_vb - > add_child ( sun_angle_hbox ) ;
2021-02-22 13:54:12 +00:00
sun_color = memnew ( ColorPickerButton ) ;
sun_color - > set_edit_alpha ( false ) ;
sun_vb - > add_margin_child ( TTR ( " Sun Color " ) , sun_color ) ;
sun_color - > connect ( " color_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
2022-07-01 03:43:46 +00:00
sun_color - > get_popup ( ) - > connect ( " about_to_popup " , callable_mp ( EditorNode : : get_singleton ( ) , & EditorNode : : setup_color_picker ) , varray ( sun_color - > get_picker ( ) ) ) ;
2021-02-22 13:54:12 +00:00
sun_energy = memnew ( EditorSpinSlider ) ;
sun_vb - > add_margin_child ( TTR ( " Sun Energy " ) , sun_energy ) ;
sun_energy - > connect ( " value_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
sun_energy - > set_max ( 64.0 ) ;
sun_max_distance = memnew ( EditorSpinSlider ) ;
sun_vb - > add_margin_child ( TTR ( " Shadow Max Distance " ) , sun_max_distance ) ;
sun_max_distance - > connect ( " value_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
sun_max_distance - > set_min ( 1 ) ;
sun_max_distance - > set_max ( 4096 ) ;
sun_add_to_scene = memnew ( Button ) ;
sun_add_to_scene - > set_text ( TTR ( " Add Sun to Scene " ) ) ;
2021-07-06 22:41:37 +00:00
sun_add_to_scene - > set_tooltip ( TTR ( " Adds a DirectionalLight3D node matching the preview sun settings to the current scene. \n Hold Shift while clicking to also add the preview environment to the current scene. " ) ) ;
sun_add_to_scene - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _add_sun_to_scene ) , varray ( false ) ) ;
2021-02-22 13:54:12 +00:00
sun_vb - > add_spacer ( ) ;
sun_vb - > add_child ( sun_add_to_scene ) ;
2021-02-23 11:55:29 +00:00
sun_state = memnew ( Label ) ;
sun_environ_hb - > add_child ( sun_state ) ;
2021-11-25 02:58:47 +00:00
sun_state - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
sun_state - > set_vertical_alignment ( VERTICAL_ALIGNMENT_CENTER ) ;
2021-02-23 11:55:29 +00:00
sun_state - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2021-02-22 13:54:12 +00:00
VSeparator * sc = memnew ( VSeparator ) ;
sc - > set_custom_minimum_size ( Size2 ( 50 * EDSCALE , 0 ) ) ;
sc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
sun_environ_hb - > add_child ( sc ) ;
environ_vb = memnew ( VBoxContainer ) ;
sun_environ_hb - > add_child ( environ_vb ) ;
environ_vb - > set_custom_minimum_size ( Size2 ( 200 * EDSCALE , 0 ) ) ;
2021-02-23 11:55:29 +00:00
environ_vb - > hide ( ) ;
2021-02-22 13:54:12 +00:00
environ_title = memnew ( Label ) ;
2021-07-08 13:29:15 +00:00
environ_title - > set_theme_type_variation ( " HeaderSmall " ) ;
2021-02-22 13:54:12 +00:00
environ_vb - > add_child ( environ_title ) ;
environ_title - > set_text ( TTR ( " Preview Environment " ) ) ;
2021-11-25 02:58:47 +00:00
environ_title - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
2021-02-22 13:54:12 +00:00
environ_sky_color = memnew ( ColorPickerButton ) ;
environ_sky_color - > set_edit_alpha ( false ) ;
environ_sky_color - > connect ( " color_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
2022-07-01 03:43:46 +00:00
environ_sky_color - > get_popup ( ) - > connect ( " about_to_popup " , callable_mp ( EditorNode : : get_singleton ( ) , & EditorNode : : setup_color_picker ) , varray ( environ_sky_color - > get_picker ( ) ) ) ;
2021-02-22 13:54:12 +00:00
environ_vb - > add_margin_child ( TTR ( " Sky Color " ) , environ_sky_color ) ;
environ_ground_color = memnew ( ColorPickerButton ) ;
environ_ground_color - > connect ( " color_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
environ_ground_color - > set_edit_alpha ( false ) ;
2022-07-01 03:43:46 +00:00
environ_ground_color - > get_popup ( ) - > connect ( " about_to_popup " , callable_mp ( EditorNode : : get_singleton ( ) , & EditorNode : : setup_color_picker ) , varray ( environ_ground_color - > get_picker ( ) ) ) ;
2021-02-22 13:54:12 +00:00
environ_vb - > add_margin_child ( TTR ( " Ground Color " ) , environ_ground_color ) ;
environ_energy = memnew ( EditorSpinSlider ) ;
environ_energy - > connect ( " value_changed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) . unbind ( 1 ) ) ;
environ_energy - > set_max ( 8.0 ) ;
environ_vb - > add_margin_child ( TTR ( " Sky Energy " ) , environ_energy ) ;
HBoxContainer * fx_vb = memnew ( HBoxContainer ) ;
fx_vb - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
environ_ao_button = memnew ( Button ) ;
environ_ao_button - > set_text ( TTR ( " AO " ) ) ;
environ_ao_button - > set_toggle_mode ( true ) ;
environ_ao_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) , varray ( ) , CONNECT_DEFERRED ) ;
fx_vb - > add_child ( environ_ao_button ) ;
environ_glow_button = memnew ( Button ) ;
environ_glow_button - > set_text ( TTR ( " Glow " ) ) ;
environ_glow_button - > set_toggle_mode ( true ) ;
environ_glow_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) , varray ( ) , CONNECT_DEFERRED ) ;
fx_vb - > add_child ( environ_glow_button ) ;
environ_tonemap_button = memnew ( Button ) ;
environ_tonemap_button - > set_text ( TTR ( " Tonemap " ) ) ;
environ_tonemap_button - > set_toggle_mode ( true ) ;
environ_tonemap_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) , varray ( ) , CONNECT_DEFERRED ) ;
fx_vb - > add_child ( environ_tonemap_button ) ;
environ_gi_button = memnew ( Button ) ;
environ_gi_button - > set_text ( TTR ( " GI " ) ) ;
environ_gi_button - > set_toggle_mode ( true ) ;
environ_gi_button - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _preview_settings_changed ) , varray ( ) , CONNECT_DEFERRED ) ;
fx_vb - > add_child ( environ_gi_button ) ;
environ_vb - > add_margin_child ( TTR ( " Post Process " ) , fx_vb ) ;
environ_add_to_scene = memnew ( Button ) ;
environ_add_to_scene - > set_text ( TTR ( " Add Environment to Scene " ) ) ;
2021-07-06 22:41:37 +00:00
environ_add_to_scene - > set_tooltip ( TTR ( " Adds a WorldEnvironment node matching the preview environment settings to the current scene. \n Hold Shift while clicking to also add the preview sun to the current scene. " ) ) ;
environ_add_to_scene - > connect ( " pressed " , callable_mp ( this , & Node3DEditor : : _add_environment_to_scene ) , varray ( false ) ) ;
2021-02-22 13:54:12 +00:00
environ_vb - > add_spacer ( ) ;
environ_vb - > add_child ( environ_add_to_scene ) ;
2021-02-23 11:55:29 +00:00
environ_state = memnew ( Label ) ;
sun_environ_hb - > add_child ( environ_state ) ;
2021-11-25 02:58:47 +00:00
environ_state - > set_horizontal_alignment ( HORIZONTAL_ALIGNMENT_CENTER ) ;
environ_state - > set_vertical_alignment ( VERTICAL_ALIGNMENT_CENTER ) ;
2021-02-23 11:55:29 +00:00
environ_state - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2021-02-22 13:54:12 +00:00
preview_sun = memnew ( DirectionalLight3D ) ;
preview_sun - > set_shadow ( true ) ;
preview_sun - > set_shadow_mode ( DirectionalLight3D : : SHADOW_PARALLEL_4_SPLITS ) ;
preview_environment = memnew ( WorldEnvironment ) ;
2021-06-17 22:03:09 +00:00
environment . instantiate ( ) ;
2021-02-22 13:54:12 +00:00
preview_environment - > set_environment ( environment ) ;
Ref < Sky > sky ;
2021-06-17 22:03:09 +00:00
sky . instantiate ( ) ;
sky_material . instantiate ( ) ;
2021-02-22 13:54:12 +00:00
sky - > set_material ( sky_material ) ;
environment - > set_sky ( sky ) ;
environment - > set_background ( Environment : : BG_SKY ) ;
_load_default_preview_settings ( ) ;
_preview_settings_changed ( ) ;
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Node3DEditor : : ~ Node3DEditor ( ) {
2017-09-02 19:47:16 +00:00
memdelete ( preview_node ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
void Node3DEditorPlugin : : make_visible ( bool p_visible ) {
2014-02-10 01:10:30 +00:00
if ( p_visible ) {
spatial_editor - > show ( ) ;
spatial_editor - > set_process ( true ) ;
} else {
spatial_editor - > hide ( ) ;
spatial_editor - > set_process ( false ) ;
}
}
2020-05-14 12:29:06 +00:00
2020-03-26 21:49:16 +00:00
void Node3DEditorPlugin : : edit ( Object * p_object ) {
spatial_editor - > edit ( Object : : cast_to < Node3D > ( p_object ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
bool Node3DEditorPlugin : : handles ( Object * p_object ) const {
2022-05-22 19:28:47 +00:00
if ( p_object - > is_class ( " Node3D " ) ) {
return true ;
} else {
// This ensures that gizmos are cleared when selecting a non-Node3D node.
const_cast < Node3DEditorPlugin * > ( this ) - > edit ( ( Object * ) nullptr ) ;
return false ;
}
2014-02-10 01:10:30 +00:00
}
2020-03-26 21:49:16 +00:00
Dictionary Node3DEditorPlugin : : get_state ( ) const {
2014-02-10 01:10:30 +00:00
return spatial_editor - > get_state ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditorPlugin : : set_state ( const Dictionary & p_state ) {
2014-02-10 01:10:30 +00:00
spatial_editor - > set_state ( p_state ) ;
}
2020-03-26 21:49:16 +00:00
Vector3 Node3DEditor : : snap_point ( Vector3 p_target , Vector3 p_start ) const {
2017-09-18 21:44:04 +00: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 ;
}
2021-02-04 08:20:26 +00:00
bool Node3DEditor : : is_gizmo_visible ( ) const {
if ( selected ) {
return gizmo . visible & & selected - > is_transform_gizmo_visible ( ) ;
}
return gizmo . visible ;
}
2021-06-21 03:30:19 +00:00
double Node3DEditor : : get_translate_snap ( ) const {
double snap_value ;
2021-08-13 21:31:57 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2020-07-24 18:07:57 +00:00
snap_value = snap_translate - > get_text ( ) . to_float ( ) / 10.0 ;
2019-04-09 15:55:44 +00:00
} else {
2020-07-24 18:07:57 +00:00
snap_value = snap_translate - > get_text ( ) . to_float ( ) ;
2019-04-09 15:55:44 +00:00
}
return snap_value ;
}
2021-06-21 03:30:19 +00:00
double Node3DEditor : : get_rotate_snap ( ) const {
double snap_value ;
2021-08-13 21:31:57 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2020-07-24 18:07:57 +00:00
snap_value = snap_rotate - > get_text ( ) . to_float ( ) / 3.0 ;
2019-04-09 15:55:44 +00:00
} else {
2020-07-24 18:07:57 +00:00
snap_value = snap_rotate - > get_text ( ) . to_float ( ) ;
2019-04-09 15:55:44 +00:00
}
return snap_value ;
}
2021-06-21 03:30:19 +00:00
double Node3DEditor : : get_scale_snap ( ) const {
double snap_value ;
2021-08-13 21:31:57 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( Key : : SHIFT ) ) {
2020-07-24 18:07:57 +00:00
snap_value = snap_scale - > get_text ( ) . to_float ( ) / 2.0 ;
2019-04-09 15:55:44 +00:00
} else {
2020-07-24 18:07:57 +00:00
snap_value = snap_scale - > get_text ( ) . to_float ( ) ;
2019-04-09 15:55:44 +00:00
}
return snap_value ;
}
2019-03-11 23:30:50 +00:00
struct _GizmoPluginPriorityComparator {
2020-03-26 21:49:16 +00:00
bool operator ( ) ( const Ref < EditorNode3DGizmoPlugin > & p_a , const Ref < EditorNode3DGizmoPlugin > & p_b ) const {
2019-03-11 23:30:50 +00:00
if ( p_a - > get_priority ( ) = = p_b - > get_priority ( ) ) {
2021-03-01 01:52:53 +00:00
return p_a - > get_gizmo_name ( ) < p_b - > get_gizmo_name ( ) ;
2019-03-11 23:30:50 +00:00
}
return p_a - > get_priority ( ) > p_b - > get_priority ( ) ;
}
} ;
struct _GizmoPluginNameComparator {
2020-03-26 21:49:16 +00:00
bool operator ( ) ( const Ref < EditorNode3DGizmoPlugin > & p_a , const Ref < EditorNode3DGizmoPlugin > & p_b ) const {
2021-03-01 01:52:53 +00:00
return p_a - > get_gizmo_name ( ) < p_b - > get_gizmo_name ( ) ;
2019-03-11 23:30:50 +00:00
}
} ;
2020-03-26 21:49:16 +00:00
void Node3DEditor : : add_gizmo_plugin ( Ref < EditorNode3DGizmoPlugin > p_plugin ) {
2019-01-25 11:57:32 +00:00
ERR_FAIL_NULL ( p_plugin . ptr ( ) ) ;
2019-03-11 23:30:50 +00: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 10:30:28 +00:00
_update_gizmos_menu ( ) ;
}
2020-03-26 21:49:16 +00:00
void Node3DEditor : : remove_gizmo_plugin ( Ref < EditorNode3DGizmoPlugin > p_plugin ) {
2019-03-11 23:30:50 +00:00
gizmo_plugins_by_priority . erase ( p_plugin ) ;
gizmo_plugins_by_name . erase ( p_plugin ) ;
2018-10-29 10:30:28 +00:00
_update_gizmos_menu ( ) ;
2018-07-24 22:08:49 +00:00
}
2022-01-27 09:36:51 +00:00
Node3DEditorPlugin : : Node3DEditorPlugin ( ) {
spatial_editor = memnew ( Node3DEditor ) ;
2016-02-08 16:01:54 +00:00
spatial_editor - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2022-01-27 09:36:51 +00:00
EditorNode : : get_singleton ( ) - > get_main_control ( ) - > add_child ( spatial_editor ) ;
2016-02-08 16:01:54 +00:00
2014-02-10 01:10:30 +00:00
spatial_editor - > hide ( ) ;
}
2020-03-26 21:49:16 +00:00
Node3DEditorPlugin : : ~ Node3DEditorPlugin ( ) {
2014-02-10 01:10:30 +00:00
}