2014-02-10 01:10:30 +00:00
/*************************************************************************/
/* canvas_item_editor_plugin.cpp */
/*************************************************************************/
/* 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
/*************************************************************************/
2021-01-01 19:13:46 +00:00
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 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
2014-02-10 01:10:30 +00:00
# include "canvas_item_editor_plugin.h"
2017-01-16 07:04:19 +00:00
2018-09-11 16:13:45 +00:00
# include "core/os/input.h"
# include "core/os/keyboard.h"
# include "core/print_string.h"
# include "core/project_settings.h"
2017-03-05 13:21:25 +00:00
# include "editor/editor_node.h"
2019-12-24 07:17:23 +00:00
# include "editor/editor_scale.h"
2017-03-05 15:44:50 +00:00
# include "editor/editor_settings.h"
# include "editor/plugins/animation_player_editor_plugin.h"
# include "editor/plugins/script_editor_plugin.h"
# include "editor/script_editor_debugger.h"
2016-10-25 19:27:24 +00:00
# include "scene/2d/light_2d.h"
# include "scene/2d/particles_2d.h"
# include "scene/2d/polygon_2d.h"
2018-05-04 19:46:32 +00:00
# include "scene/2d/skeleton_2d.h"
2017-03-05 15:44:50 +00:00
# include "scene/2d/sprite.h"
2019-02-12 16:18:13 +00:00
# include "scene/2d/touch_screen_button.h"
2015-02-15 08:00:55 +00:00
# include "scene/gui/grid_container.h"
2017-10-24 05:59:04 +00:00
# include "scene/gui/nine_patch_rect.h"
2019-12-24 07:17:23 +00:00
# include "scene/gui/viewport_container.h"
2017-03-05 15:44:50 +00:00
# include "scene/main/canvas_layer.h"
# include "scene/main/viewport.h"
2021-06-03 09:32:06 +00:00
# include "scene/resources/dynamic_font.h"
2016-04-07 10:59:50 +00:00
# include "scene/resources/packed_scene.h"
2015-02-15 08:00:55 +00:00
2020-10-14 07:32:05 +00:00
# include <stdlib.h>
2020-03-15 18:13:07 +00:00
// Min and Max are power of two in order to play nicely with successive increment.
// That way, we can naturally reach a 100% zoom from boundaries.
# define MIN_ZOOM 1. / 128
# define MAX_ZOOM 128
2016-07-21 13:06:38 +00:00
2019-12-10 04:13:02 +00:00
# define RULER_WIDTH (15 * EDSCALE)
2018-09-10 12:39:46 +00:00
# define SCALE_HANDLE_DISTANCE 25
2017-08-29 19:50:18 +00:00
2015-02-15 08:00:55 +00:00
class SnapDialog : public ConfirmationDialog {
2017-03-05 15:44:50 +00:00
GDCLASS ( SnapDialog , ConfirmationDialog ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
friend class CanvasItemEditor ;
2015-10-18 16:31:44 +00:00
2015-02-15 08:00:55 +00:00
SpinBox * grid_offset_x ;
SpinBox * grid_offset_y ;
SpinBox * grid_step_x ;
2016-03-08 23:00:52 +00:00
SpinBox * grid_step_y ;
2019-10-15 08:23:38 +00:00
SpinBox * primary_grid_steps ;
2016-03-08 23:00:52 +00:00
SpinBox * rotation_offset ;
2015-02-15 08:00:55 +00:00
SpinBox * rotation_step ;
2019-10-30 14:18:57 +00:00
SpinBox * scale_step ;
2016-03-08 23:00:52 +00:00
2015-02-15 08:00:55 +00:00
public :
2019-06-26 13:08:25 +00:00
SnapDialog ( ) {
2019-10-07 20:59:51 +00:00
const int SPIN_BOX_GRID_RANGE = 16384 ;
2015-02-15 08:00:55 +00:00
const int SPIN_BOX_ROTATION_RANGE = 360 ;
2019-10-30 14:18:57 +00:00
const float SPIN_BOX_SCALE_MIN = 0.01f ;
const float SPIN_BOX_SCALE_MAX = 100 ;
2015-02-15 08:00:55 +00:00
Label * label ;
VBoxContainer * container ;
GridContainer * child_container ;
2015-10-18 16:31:44 +00:00
2016-05-04 01:25:37 +00:00
set_title ( TTR ( " Configure Snap " ) ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
container = memnew ( VBoxContainer ) ;
2015-02-15 08:00:55 +00:00
add_child ( container ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
child_container = memnew ( GridContainer ) ;
2015-02-15 08:00:55 +00:00
child_container - > set_columns ( 3 ) ;
container - > add_child ( child_container ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
label = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
label - > set_text ( TTR ( " Grid Offset: " ) ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( label ) ;
2015-10-18 16:31:44 +00:00
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-05 15:44:50 +00:00
grid_offset_x = memnew ( SpinBox ) ;
2015-02-15 08:00:55 +00:00
grid_offset_x - > set_min ( - SPIN_BOX_GRID_RANGE ) ;
grid_offset_x - > set_max ( SPIN_BOX_GRID_RANGE ) ;
2019-10-07 20:59:51 +00:00
grid_offset_x - > set_allow_lesser ( true ) ;
grid_offset_x - > set_allow_greater ( true ) ;
2015-02-15 08:00:55 +00:00
grid_offset_x - > set_suffix ( " px " ) ;
2019-04-21 22:51:48 +00:00
grid_offset_x - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( grid_offset_x ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
grid_offset_y = memnew ( SpinBox ) ;
2015-02-15 08:00:55 +00:00
grid_offset_y - > set_min ( - SPIN_BOX_GRID_RANGE ) ;
grid_offset_y - > set_max ( SPIN_BOX_GRID_RANGE ) ;
2019-10-07 20:59:51 +00:00
grid_offset_y - > set_allow_lesser ( true ) ;
grid_offset_y - > set_allow_greater ( true ) ;
2015-02-15 08:00:55 +00:00
grid_offset_y - > set_suffix ( " px " ) ;
2019-04-21 22:51:48 +00:00
grid_offset_y - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( grid_offset_y ) ;
2017-03-05 15:44:50 +00:00
label = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
label - > set_text ( TTR ( " Grid Step: " ) ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( label ) ;
2015-10-18 16:31:44 +00:00
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-05 15:44:50 +00:00
grid_step_x = memnew ( SpinBox ) ;
2017-09-03 19:13:59 +00:00
grid_step_x - > set_min ( 0.01 ) ;
2015-02-15 08:00:55 +00:00
grid_step_x - > set_max ( SPIN_BOX_GRID_RANGE ) ;
2019-10-07 20:59:51 +00:00
grid_step_x - > set_allow_greater ( true ) ;
2015-02-15 08:00:55 +00:00
grid_step_x - > set_suffix ( " px " ) ;
2019-04-21 22:51:48 +00:00
grid_step_x - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( grid_step_x ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
grid_step_y = memnew ( SpinBox ) ;
2017-09-03 19:13:59 +00:00
grid_step_y - > set_min ( 0.01 ) ;
2015-02-15 08:00:55 +00:00
grid_step_y - > set_max ( SPIN_BOX_GRID_RANGE ) ;
2019-10-07 20:59:51 +00:00
grid_step_y - > set_allow_greater ( true ) ;
2015-02-15 08:00:55 +00:00
grid_step_y - > set_suffix ( " px " ) ;
2019-04-21 22:51:48 +00:00
grid_step_y - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( grid_step_y ) ;
2019-10-30 21:02:37 +00:00
child_container = memnew ( GridContainer ) ;
child_container - > set_columns ( 2 ) ;
container - > add_child ( child_container ) ;
2019-10-15 08:23:38 +00:00
label = memnew ( Label ) ;
2019-10-30 21:02:37 +00:00
label - > set_text ( TTR ( " Primary Line Every: " ) ) ;
2019-10-15 08:23:38 +00:00
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
child_container - > add_child ( label ) ;
primary_grid_steps = memnew ( SpinBox ) ;
primary_grid_steps - > set_min ( 0 ) ;
primary_grid_steps - > set_step ( 1 ) ;
primary_grid_steps - > set_max ( 100 ) ;
primary_grid_steps - > set_allow_greater ( true ) ;
2019-10-30 21:02:37 +00:00
primary_grid_steps - > set_suffix ( TTR ( " steps " ) ) ;
2019-10-15 08:23:38 +00:00
primary_grid_steps - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
child_container - > add_child ( primary_grid_steps ) ;
2017-03-05 15:44:50 +00:00
container - > add_child ( memnew ( HSeparator ) ) ;
2015-10-18 16:31:44 +00:00
2019-10-30 21:02:37 +00:00
// We need to create another GridContainer with the same column count,
// so we can put an HSeparator above
2017-03-05 15:44:50 +00:00
child_container = memnew ( GridContainer ) ;
2015-02-15 08:00:55 +00:00
child_container - > set_columns ( 2 ) ;
container - > add_child ( child_container ) ;
2017-03-05 15:44:50 +00:00
label = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
label - > set_text ( TTR ( " Rotation Offset: " ) ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( label ) ;
2015-10-18 16:31:44 +00:00
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-05 15:44:50 +00:00
rotation_offset = memnew ( SpinBox ) ;
2015-02-15 08:00:55 +00:00
rotation_offset - > set_min ( - SPIN_BOX_ROTATION_RANGE ) ;
rotation_offset - > set_max ( SPIN_BOX_ROTATION_RANGE ) ;
rotation_offset - > set_suffix ( " deg " ) ;
2019-04-21 22:51:48 +00:00
rotation_offset - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( rotation_offset ) ;
2015-10-18 16:31:44 +00:00
2017-03-05 15:44:50 +00:00
label = memnew ( Label ) ;
2016-05-04 01:25:37 +00:00
label - > set_text ( TTR ( " Rotation Step: " ) ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( label ) ;
2015-10-18 16:31:44 +00:00
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2017-03-05 15:44:50 +00:00
rotation_step = memnew ( SpinBox ) ;
2015-02-15 08:00:55 +00:00
rotation_step - > set_min ( - SPIN_BOX_ROTATION_RANGE ) ;
rotation_step - > set_max ( SPIN_BOX_ROTATION_RANGE ) ;
rotation_step - > set_suffix ( " deg " ) ;
2019-04-21 22:51:48 +00:00
rotation_step - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2015-02-15 08:00:55 +00:00
child_container - > add_child ( rotation_step ) ;
2019-10-30 14:18:57 +00:00
container - > add_child ( memnew ( HSeparator ) ) ;
child_container = memnew ( GridContainer ) ;
child_container - > set_columns ( 2 ) ;
container - > add_child ( child_container ) ;
label = memnew ( Label ) ;
label - > set_text ( TTR ( " Scale Step: " ) ) ;
child_container - > add_child ( label ) ;
label - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
scale_step = memnew ( SpinBox ) ;
scale_step - > set_min ( SPIN_BOX_SCALE_MIN ) ;
scale_step - > set_max ( SPIN_BOX_SCALE_MAX ) ;
scale_step - > set_allow_greater ( true ) ;
scale_step - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
scale_step - > set_step ( 0.01f ) ;
child_container - > add_child ( scale_step ) ;
2015-02-15 08:00:55 +00:00
}
2016-03-08 23:00:52 +00:00
2019-10-30 14:18:57 +00:00
void set_fields ( const Point2 p_grid_offset , const Point2 p_grid_step , const int p_primary_grid_steps , const float p_rotation_offset , const float p_rotation_step , const float p_scale_step ) {
2017-01-04 04:16:14 +00:00
grid_offset_x - > set_value ( p_grid_offset . x ) ;
grid_offset_y - > set_value ( p_grid_offset . y ) ;
grid_step_x - > set_value ( p_grid_step . x ) ;
grid_step_y - > set_value ( p_grid_step . y ) ;
2019-10-15 08:23:38 +00:00
primary_grid_steps - > set_value ( p_primary_grid_steps ) ;
2017-01-04 04:16:14 +00:00
rotation_offset - > set_value ( p_rotation_offset * ( 180 / Math_PI ) ) ;
rotation_step - > set_value ( p_rotation_step * ( 180 / Math_PI ) ) ;
2019-10-30 14:18:57 +00:00
scale_step - > set_value ( p_scale_step ) ;
2015-02-15 08:00:55 +00:00
}
2016-03-08 23:00:52 +00:00
2019-10-30 14:18:57 +00:00
void get_fields ( Point2 & p_grid_offset , Point2 & p_grid_step , int & p_primary_grid_steps , float & p_rotation_offset , float & p_rotation_step , float & p_scale_step ) {
2017-08-29 19:50:18 +00:00
p_grid_offset = Point2 ( grid_offset_x - > get_value ( ) , grid_offset_y - > get_value ( ) ) ;
p_grid_step = Point2 ( grid_step_x - > get_value ( ) , grid_step_y - > get_value ( ) ) ;
2019-10-15 08:23:38 +00:00
p_primary_grid_steps = int ( primary_grid_steps - > get_value ( ) ) ;
2017-01-04 04:16:14 +00:00
p_rotation_offset = rotation_offset - > get_value ( ) / ( 180 / Math_PI ) ;
p_rotation_step = rotation_step - > get_value ( ) / ( 180 / Math_PI ) ;
2019-10-30 14:18:57 +00:00
p_scale_step = scale_step - > get_value ( ) ;
2015-02-15 08:00:55 +00:00
}
} ;
2018-10-16 18:35:51 +00:00
bool CanvasItemEditor : : _is_node_locked ( const Node * p_node ) {
return p_node - > has_meta ( " _edit_lock_ " ) & & p_node - > get_meta ( " _edit_lock_ " ) ;
}
2018-10-25 17:08:32 +00:00
bool CanvasItemEditor : : _is_node_movable ( const Node * p_node , bool p_popup_warning ) {
2018-10-16 18:35:51 +00:00
if ( _is_node_locked ( p_node ) ) {
return false ;
}
if ( Object : : cast_to < Control > ( p_node ) & & Object : : cast_to < Container > ( p_node - > get_parent ( ) ) ) {
2018-10-25 17:08:32 +00:00
if ( p_popup_warning ) {
_popup_warning_temporarily ( warning_child_of_container , 3.0 ) ;
}
2018-10-16 18:35:51 +00:00
return false ;
}
return true ;
2018-09-21 23:30:49 +00:00
}
2019-04-05 08:18:21 +00:00
void CanvasItemEditor : : _snap_if_closer_float (
float p_value ,
float & r_current_snap , SnapTarget & r_current_snap_target ,
float p_target_value , SnapTarget p_snap_target ,
float p_radius ) {
float radius = p_radius / zoom ;
float dist = Math : : abs ( p_value - p_target_value ) ;
if ( ( p_radius < 0 | | dist < radius ) & & ( r_current_snap_target = = SNAP_TARGET_NONE | | dist < Math : : abs ( r_current_snap - p_value ) ) ) {
r_current_snap = p_target_value ;
r_current_snap_target = p_snap_target ;
}
}
void CanvasItemEditor : : _snap_if_closer_point (
Point2 p_value ,
Point2 & r_current_snap , SnapTarget ( & r_current_snap_target ) [ 2 ] ,
Point2 p_target_value , SnapTarget p_snap_target ,
real_t rotation ,
float p_radius ) {
2017-09-07 21:30:54 +00:00
Transform2D rot_trans = Transform2D ( rotation , Point2 ( ) ) ;
p_value = rot_trans . inverse ( ) . xform ( p_value ) ;
2019-04-05 08:18:21 +00:00
p_target_value = rot_trans . inverse ( ) . xform ( p_target_value ) ;
2017-09-07 21:30:54 +00:00
r_current_snap = rot_trans . inverse ( ) . xform ( r_current_snap ) ;
2019-04-05 08:18:21 +00:00
_snap_if_closer_float (
p_value . x ,
r_current_snap . x ,
r_current_snap_target [ 0 ] ,
p_target_value . x ,
p_snap_target ,
p_radius ) ;
_snap_if_closer_float (
p_value . y ,
r_current_snap . y ,
r_current_snap_target [ 1 ] ,
p_target_value . y ,
p_snap_target ,
p_radius ) ;
2017-09-07 21:30:54 +00:00
r_current_snap = rot_trans . xform ( r_current_snap ) ;
}
2019-04-05 08:18:21 +00:00
void CanvasItemEditor : : _snap_other_nodes (
const Point2 p_value ,
const Transform2D p_transform_to_snap ,
Point2 & r_current_snap , SnapTarget ( & r_current_snap_target ) [ 2 ] ,
const SnapTarget p_snap_target , List < const CanvasItem * > p_exceptions ,
const Node * p_current ) {
2017-09-07 21:30:54 +00:00
const CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_current ) ;
2019-04-05 08:18:21 +00:00
// Check if the element is in the exception
bool exception = false ;
for ( List < const CanvasItem * > : : Element * E = p_exceptions . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) = = p_current ) {
exception = true ;
break ;
}
} ;
if ( canvas_item & & ! exception ) {
2017-09-07 21:30:54 +00:00
Transform2D ci_transform = canvas_item - > get_global_transform_with_canvas ( ) ;
2019-04-05 08:18:21 +00:00
if ( fmod ( ci_transform . get_rotation ( ) - p_transform_to_snap . get_rotation ( ) , ( real_t ) 360.0 ) = = 0.0 ) {
2018-03-08 20:35:41 +00:00
if ( canvas_item - > _edit_use_rect ( ) ) {
Point2 begin = ci_transform . xform ( canvas_item - > _edit_get_rect ( ) . get_position ( ) ) ;
Point2 end = ci_transform . xform ( canvas_item - > _edit_get_rect ( ) . get_position ( ) + canvas_item - > _edit_get_rect ( ) . get_size ( ) ) ;
2019-04-05 08:18:21 +00:00
_snap_if_closer_point ( p_value , r_current_snap , r_current_snap_target , begin , p_snap_target , ci_transform . get_rotation ( ) ) ;
_snap_if_closer_point ( p_value , r_current_snap , r_current_snap_target , end , p_snap_target , ci_transform . get_rotation ( ) ) ;
2018-03-08 20:35:41 +00:00
} else {
Point2 position = ci_transform . xform ( Point2 ( ) ) ;
2019-04-05 08:18:21 +00:00
_snap_if_closer_point ( p_value , r_current_snap , r_current_snap_target , position , p_snap_target , ci_transform . get_rotation ( ) ) ;
2018-03-08 20:35:41 +00:00
}
2017-09-07 21:30:54 +00:00
}
}
for ( int i = 0 ; i < p_current - > get_child_count ( ) ; i + + ) {
2019-04-05 08:18:21 +00:00
_snap_other_nodes ( p_value , p_transform_to_snap , r_current_snap , r_current_snap_target , p_snap_target , p_exceptions , p_current - > get_child ( i ) ) ;
2017-09-07 21:30:54 +00:00
}
}
2019-04-05 08:18:21 +00:00
Point2 CanvasItemEditor : : snap_point ( Point2 p_target , unsigned int p_modes , unsigned int p_forced_modes , const CanvasItem * p_self_canvas_item , List < CanvasItem * > p_other_nodes_exceptions ) {
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2019-10-10 17:41:45 +00:00
bool is_snap_active = smart_snap_active ^ Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ;
2017-09-07 21:30:54 +00:00
// Smart snap using the canvas position
Vector2 output = p_target ;
real_t rotation = 0.0 ;
2019-04-05 08:18:21 +00:00
if ( p_self_canvas_item ) {
rotation = p_self_canvas_item - > get_global_transform_with_canvas ( ) . get_rotation ( ) ;
2017-09-07 21:30:54 +00:00
2017-11-07 07:58:35 +00:00
// Parent sides and center
2018-03-27 15:30:39 +00:00
if ( ( is_snap_active & & snap_node_parent & & ( p_modes & SNAP_NODE_PARENT ) ) | | ( p_forced_modes & SNAP_NODE_PARENT ) ) {
2019-04-05 08:18:21 +00:00
if ( const Control * c = Object : : cast_to < Control > ( p_self_canvas_item ) ) {
Point2 begin = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( _anchor_to_position ( c , Point2 ( 0 , 0 ) ) ) ;
Point2 end = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( _anchor_to_position ( c , Point2 ( 1 , 1 ) ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , begin , SNAP_TARGET_PARENT , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , ( begin + end ) / 2.0 , SNAP_TARGET_PARENT , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , end , SNAP_TARGET_PARENT , rotation ) ;
} else if ( const CanvasItem * parent_ci = Object : : cast_to < CanvasItem > ( p_self_canvas_item - > get_parent ( ) ) ) {
2018-03-08 20:35:41 +00:00
if ( parent_ci - > _edit_use_rect ( ) ) {
2019-04-05 08:18:21 +00:00
Point2 begin = p_self_canvas_item - > get_transform ( ) . affine_inverse ( ) . xform ( parent_ci - > _edit_get_rect ( ) . get_position ( ) ) ;
Point2 end = p_self_canvas_item - > get_transform ( ) . affine_inverse ( ) . xform ( parent_ci - > _edit_get_rect ( ) . get_position ( ) + parent_ci - > _edit_get_rect ( ) . get_size ( ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , begin , SNAP_TARGET_PARENT , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , ( begin + end ) / 2.0 , SNAP_TARGET_PARENT , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , end , SNAP_TARGET_PARENT , rotation ) ;
2018-03-08 20:35:41 +00:00
} else {
2019-04-05 08:18:21 +00:00
Point2 position = p_self_canvas_item - > get_transform ( ) . affine_inverse ( ) . xform ( Point2 ( ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , position , SNAP_TARGET_PARENT , rotation ) ;
2018-03-08 20:35:41 +00:00
}
2017-09-07 21:30:54 +00:00
}
}
2017-11-07 07:58:35 +00:00
// Self anchors
2018-03-27 15:30:39 +00:00
if ( ( is_snap_active & & snap_node_anchors & & ( p_modes & SNAP_NODE_ANCHORS ) ) | | ( p_forced_modes & SNAP_NODE_ANCHORS ) ) {
2019-04-05 08:18:21 +00:00
if ( const Control * c = Object : : cast_to < Control > ( p_self_canvas_item ) ) {
Point2 begin = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( _anchor_to_position ( c , Point2 ( c - > get_anchor ( MARGIN_LEFT ) , c - > get_anchor ( MARGIN_TOP ) ) ) ) ;
Point2 end = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( _anchor_to_position ( c , Point2 ( c - > get_anchor ( MARGIN_RIGHT ) , c - > get_anchor ( MARGIN_BOTTOM ) ) ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , begin , SNAP_TARGET_SELF_ANCHORS , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , end , SNAP_TARGET_SELF_ANCHORS , rotation ) ;
2017-09-07 21:30:54 +00:00
}
}
2017-11-07 07:58:35 +00:00
// Self sides
2018-03-27 15:30:39 +00:00
if ( ( is_snap_active & & snap_node_sides & & ( p_modes & SNAP_NODE_SIDES ) ) | | ( p_forced_modes & SNAP_NODE_SIDES ) ) {
2019-04-05 08:18:21 +00:00
if ( p_self_canvas_item - > _edit_use_rect ( ) ) {
Point2 begin = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( p_self_canvas_item - > _edit_get_rect ( ) . get_position ( ) ) ;
Point2 end = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( p_self_canvas_item - > _edit_get_rect ( ) . get_position ( ) + p_self_canvas_item - > _edit_get_rect ( ) . get_size ( ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , begin , SNAP_TARGET_SELF , rotation ) ;
_snap_if_closer_point ( p_target , output , snap_target , end , SNAP_TARGET_SELF , rotation ) ;
2018-03-08 20:35:41 +00:00
}
2017-10-18 21:55:02 +00:00
}
2017-11-07 07:58:35 +00:00
// Self center
2018-03-27 15:30:39 +00:00
if ( ( is_snap_active & & snap_node_center & & ( p_modes & SNAP_NODE_CENTER ) ) | | ( p_forced_modes & SNAP_NODE_CENTER ) ) {
2019-04-05 08:18:21 +00:00
if ( p_self_canvas_item - > _edit_use_rect ( ) ) {
Point2 center = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( p_self_canvas_item - > _edit_get_rect ( ) . get_position ( ) + p_self_canvas_item - > _edit_get_rect ( ) . get_size ( ) / 2.0 ) ;
_snap_if_closer_point ( p_target , output , snap_target , center , SNAP_TARGET_SELF , rotation ) ;
2018-03-08 20:35:41 +00:00
} else {
2019-04-05 08:18:21 +00:00
Point2 position = p_self_canvas_item - > get_global_transform_with_canvas ( ) . xform ( Point2 ( ) ) ;
_snap_if_closer_point ( p_target , output , snap_target , position , SNAP_TARGET_SELF , rotation ) ;
2018-03-08 20:35:41 +00:00
}
2017-11-07 07:58:35 +00:00
}
2017-10-18 21:55:02 +00:00
}
// Other nodes sides
2018-03-27 15:30:39 +00:00
if ( ( is_snap_active & & snap_other_nodes & & ( p_modes & SNAP_OTHER_NODES ) ) | | ( p_forced_modes & SNAP_OTHER_NODES ) ) {
2019-04-05 08:18:21 +00:00
Transform2D to_snap_transform = Transform2D ( ) ;
List < const CanvasItem * > exceptions = List < const CanvasItem * > ( ) ;
for ( List < CanvasItem * > : : Element * E = p_other_nodes_exceptions . front ( ) ; E ; E = E - > next ( ) ) {
exceptions . push_back ( E - > get ( ) ) ;
}
if ( p_self_canvas_item ) {
exceptions . push_back ( p_self_canvas_item ) ;
to_snap_transform = p_self_canvas_item - > get_global_transform_with_canvas ( ) ;
}
_snap_other_nodes (
p_target , to_snap_transform ,
output , snap_target ,
SNAP_TARGET_OTHER_NODE ,
exceptions ,
get_tree ( ) - > get_edited_scene_root ( ) ) ;
2017-10-18 21:55:02 +00:00
}
2018-03-27 15:30:39 +00:00
if ( ( ( is_snap_active & & snap_guides & & ( p_modes & SNAP_GUIDES ) ) | | ( p_forced_modes & SNAP_GUIDES ) ) & & fmod ( rotation , ( real_t ) 360.0 ) = = 0.0 ) {
2017-10-18 21:55:02 +00:00
// Guides
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_vertical_guides_ " ) ) {
Array vguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_vertical_guides_ " ) ;
for ( int i = 0 ; i < vguides . size ( ) ; i + + ) {
2019-04-05 08:18:21 +00:00
_snap_if_closer_float ( p_target . x , output . x , snap_target [ 0 ] , vguides [ i ] , SNAP_TARGET_GUIDE ) ;
2017-10-18 21:55:02 +00:00
}
2017-09-07 21:30:54 +00:00
}
2017-10-18 21:55:02 +00:00
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_horizontal_guides_ " ) ) {
Array hguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_horizontal_guides_ " ) ;
for ( int i = 0 ; i < hguides . size ( ) ; i + + ) {
2019-04-05 08:18:21 +00:00
_snap_if_closer_float ( p_target . y , output . y , snap_target [ 1 ] , hguides [ i ] , SNAP_TARGET_GUIDE ) ;
2017-10-18 21:55:02 +00:00
}
2017-09-07 21:30:54 +00:00
}
}
2019-10-10 17:41:45 +00:00
if ( ( ( grid_snap_active & & ( p_modes & SNAP_GRID ) ) | | ( p_forced_modes & SNAP_GRID ) ) & & fmod ( rotation , ( real_t ) 360.0 ) = = 0.0 ) {
2017-09-07 21:30:54 +00:00
// Grid
Point2 offset = grid_offset ;
if ( snap_relative ) {
2017-11-07 07:58:35 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
2017-09-07 21:30:54 +00:00
if ( selection . size ( ) = = 1 & & Object : : cast_to < Node2D > ( selection [ 0 ] ) ) {
offset = Object : : cast_to < Node2D > ( selection [ 0 ] ) - > get_global_position ( ) ;
2017-11-07 07:58:35 +00:00
} else if ( selection . size ( ) > 0 ) {
offset = _get_encompassing_rect_from_list ( selection ) . position ;
2017-09-07 21:30:54 +00:00
}
}
Point2 grid_output ;
grid_output . x = Math : : stepify ( p_target . x - offset . x , grid_step . x * Math : : pow ( 2.0 , grid_step_multiplier ) ) + offset . x ;
grid_output . y = Math : : stepify ( p_target . y - offset . y , grid_step . y * Math : : pow ( 2.0 , grid_step_multiplier ) ) + offset . y ;
2019-04-05 08:18:21 +00:00
_snap_if_closer_point ( p_target , output , snap_target , grid_output , SNAP_TARGET_GRID , 0.0 , - 1.0 ) ;
2017-09-17 20:52:41 +00:00
}
if ( ( ( snap_pixel & & ( p_modes & SNAP_PIXEL ) ) | | ( p_forced_modes & SNAP_PIXEL ) ) & & rotation = = 0.0 ) {
2017-09-07 21:30:54 +00:00
// Pixel
2017-09-17 20:52:41 +00:00
output = output . snapped ( Size2 ( 1 , 1 ) ) ;
2017-09-07 21:30:54 +00:00
}
2019-04-05 08:18:21 +00:00
snap_transform = Transform2D ( rotation , output ) ;
2017-09-07 21:30:54 +00:00
return output ;
}
float CanvasItemEditor : : snap_angle ( float p_target , float p_start ) const {
2019-10-10 17:41:45 +00:00
return ( ( ( smart_snap_active | | snap_rotation ) ^ Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ) & & snap_rotation_step ! = 0 ) ? Math : : stepify ( p_target - snap_rotation_offset , snap_rotation_step ) + snap_rotation_offset : p_target ;
2017-09-07 21:30:54 +00:00
}
2017-05-20 15:38:03 +00:00
void CanvasItemEditor : : _unhandled_key_input ( const Ref < InputEvent > & p_ev ) {
2021-04-27 14:51:29 +00:00
ERR_FAIL_COND ( p_ev . is_null ( ) ) ;
2017-05-20 15:38:03 +00:00
Ref < InputEventKey > k = p_ev ;
2014-02-10 01:10:30 +00:00
2021-05-05 10:44:11 +00:00
if ( ! is_visible_in_tree ( ) | | get_viewport ( ) - > gui_has_modal_stack ( ) ) {
2014-02-10 01:10:30 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2016-07-15 19:22:01 +00:00
2018-09-10 12:39:46 +00:00
if ( k - > get_scancode ( ) = = KEY_CONTROL | | k - > get_scancode ( ) = = KEY_ALT | | k - > get_scancode ( ) = = KEY_SHIFT ) {
viewport - > update ( ) ;
}
2016-07-15 19:22:01 +00:00
2018-09-10 12:39:46 +00:00
if ( k - > is_pressed ( ) & & ! k - > get_control ( ) & & ! k - > is_echo ( ) ) {
2019-10-10 17:41:45 +00:00
if ( ( grid_snap_active | | show_grid ) & & multiply_grid_step_shortcut . is_valid ( ) & & multiply_grid_step_shortcut - > is_shortcut ( p_ev ) ) {
2017-08-31 19:54:42 +00:00
// Multiply the grid size
grid_step_multiplier = MIN ( grid_step_multiplier + 1 , 12 ) ;
viewport - > update ( ) ;
2019-10-10 17:41:45 +00:00
} else if ( ( grid_snap_active | | show_grid ) & & divide_grid_step_shortcut . is_valid ( ) & & divide_grid_step_shortcut - > is_shortcut ( p_ev ) ) {
2017-08-31 19:54:42 +00:00
// Divide the grid size
Point2 new_grid_step = grid_step * Math : : pow ( 2.0 , grid_step_multiplier - 1 ) ;
2021-05-05 10:44:11 +00:00
if ( new_grid_step . x > = 1.0 & & new_grid_step . y > = 1.0 ) {
2017-08-31 19:54:42 +00:00
grid_step_multiplier - - ;
2021-05-05 10:44:11 +00:00
}
2017-08-31 19:54:42 +00:00
viewport - > update ( ) ;
2015-06-12 16:53:18 +00:00
}
}
2014-02-10 01:10:30 +00:00
}
Object * CanvasItemEditor : : _get_editor_data ( Object * p_what ) {
2017-08-24 20:58:51 +00:00
CanvasItem * ci = Object : : cast_to < CanvasItem > ( p_what ) ;
2021-05-05 10:44:11 +00:00
if ( ! ci ) {
2021-05-04 14:00:45 +00:00
return nullptr ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
return memnew ( CanvasItemEditorSelectedItem ) ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _keying_changed ( ) {
2021-05-05 10:44:11 +00:00
if ( AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > is_visible_in_tree ( ) ) {
2017-11-07 07:58:35 +00:00
animation_hb - > show ( ) ;
2021-05-05 10:44:11 +00:00
} else {
2017-11-07 07:58:35 +00:00
animation_hb - > hide ( ) ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-10-18 21:55:02 +00:00
2017-11-07 07:58:35 +00:00
Rect2 CanvasItemEditor : : _get_encompassing_rect_from_list ( List < CanvasItem * > p_list ) {
ERR_FAIL_COND_V ( p_list . empty ( ) , Rect2 ( ) ) ;
2015-02-15 08:00:55 +00:00
2017-11-07 07:58:35 +00:00
// Handles the first element
CanvasItem * canvas_item = p_list . front ( ) - > get ( ) ;
2018-07-29 21:09:59 +00:00
Rect2 rect = Rect2 ( canvas_item - > get_global_transform_with_canvas ( ) . xform ( canvas_item - > _edit_get_rect ( ) . position + canvas_item - > _edit_get_rect ( ) . size / 2 ) , Size2 ( ) ) ;
2015-02-15 08:00:55 +00:00
2018-03-08 20:35:41 +00:00
// Expand with the other ones
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = p_list . front ( ) ; E ; E = E - > next ( ) ) {
2019-02-12 20:10:08 +00:00
CanvasItem * canvas_item2 = E - > get ( ) ;
Transform2D xform = canvas_item2 - > get_global_transform_with_canvas ( ) ;
2018-03-08 20:35:41 +00:00
2019-02-12 20:10:08 +00:00
Rect2 current_rect = canvas_item2 - > _edit_get_rect ( ) ;
2018-07-29 21:09:59 +00:00
rect . expand_to ( xform . xform ( current_rect . position ) ) ;
rect . expand_to ( xform . xform ( current_rect . position + Vector2 ( current_rect . size . x , 0 ) ) ) ;
rect . expand_to ( xform . xform ( current_rect . position + current_rect . size ) ) ;
rect . expand_to ( xform . xform ( current_rect . position + Vector2 ( 0 , current_rect . size . y ) ) ) ;
2017-08-29 19:50:18 +00:00
}
2017-11-07 07:58:35 +00:00
return rect ;
}
2017-10-18 21:55:02 +00:00
2018-07-29 21:09:59 +00:00
void CanvasItemEditor : : _expand_encompassing_rect_using_children ( Rect2 & r_rect , const Node * p_node , bool & r_first , const Transform2D & p_parent_xform , const Transform2D & p_canvas_xform , bool include_locked_nodes ) {
2021-05-05 10:44:11 +00:00
if ( ! p_node ) {
2017-11-07 07:58:35 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
if ( Object : : cast_to < Viewport > ( p_node ) ) {
2017-11-07 07:58:35 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2017-08-19 16:29:37 +00:00
2018-03-08 20:35:41 +00:00
const CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
2014-04-24 01:43:02 +00:00
2018-03-08 20:35:41 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
if ( canvas_item & & ! canvas_item - > is_set_as_toplevel ( ) ) {
_expand_encompassing_rect_using_children ( r_rect , p_node - > get_child ( i ) , r_first , p_parent_xform * canvas_item - > get_transform ( ) , p_canvas_xform ) ;
} else {
const CanvasLayer * canvas_layer = Object : : cast_to < CanvasLayer > ( p_node ) ;
_expand_encompassing_rect_using_children ( r_rect , p_node - > get_child ( i ) , r_first , Transform2D ( ) , canvas_layer ? canvas_layer - > get_transform ( ) : p_canvas_xform ) ;
2017-11-07 07:58:35 +00:00
}
2014-02-10 01:10:30 +00:00
}
2016-09-07 09:10:00 +00:00
2018-10-16 18:35:51 +00:00
if ( canvas_item & & canvas_item - > is_visible_in_tree ( ) & & ( include_locked_nodes | | ! _is_node_locked ( canvas_item ) ) ) {
2017-11-07 07:58:35 +00:00
Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item - > get_transform ( ) ;
2018-07-29 21:09:59 +00:00
Rect2 rect = canvas_item - > _edit_get_rect ( ) ;
if ( r_first ) {
r_rect = Rect2 ( xform . xform ( rect . position + rect . size / 2 ) , Size2 ( ) ) ;
r_first = false ;
2017-11-07 07:58:35 +00:00
}
2018-07-29 21:09:59 +00:00
r_rect . expand_to ( xform . xform ( rect . position ) ) ;
r_rect . expand_to ( xform . xform ( rect . position + Point2 ( rect . size . x , 0 ) ) ) ;
r_rect . expand_to ( xform . xform ( rect . position + Point2 ( 0 , rect . size . y ) ) ) ;
r_rect . expand_to ( xform . xform ( rect . position + rect . size ) ) ;
2016-09-07 09:10:00 +00:00
}
2014-02-10 01:10:30 +00:00
}
2018-03-08 20:35:41 +00:00
Rect2 CanvasItemEditor : : _get_encompassing_rect ( const Node * p_node ) {
2017-11-07 07:58:35 +00:00
Rect2 rect ;
bool first = true ;
2018-03-08 20:35:41 +00:00
_expand_encompassing_rect_using_children ( rect , p_node , first ) ;
2017-11-07 07:58:35 +00:00
return rect ;
2016-04-07 10:59:50 +00:00
}
2018-10-16 18:35:51 +00:00
void CanvasItemEditor : : _find_canvas_items_at_pos ( const Point2 & p_pos , Node * p_node , Vector < _SelectResult > & r_items , const Transform2D & p_parent_xform , const Transform2D & p_canvas_xform ) {
2021-05-05 10:44:11 +00:00
if ( ! p_node ) {
2015-11-04 21:39:07 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
if ( Object : : cast_to < Viewport > ( p_node ) ) {
2015-11-04 21:39:07 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2015-11-04 21:39:07 +00:00
2018-12-01 20:45:54 +00:00
const real_t grab_distance = EDITOR_GET ( " editors/poly_editor/point_grab_radius " ) ;
2017-11-07 07:58:35 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
2015-11-04 21:39:07 +00:00
2018-05-03 22:27:37 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2018-09-19 09:05:24 +00:00
if ( canvas_item ) {
if ( ! canvas_item - > is_set_as_toplevel ( ) ) {
2018-10-16 18:35:51 +00:00
_find_canvas_items_at_pos ( p_pos , p_node - > get_child ( i ) , r_items , p_parent_xform * canvas_item - > get_transform ( ) , p_canvas_xform ) ;
2018-09-19 09:05:24 +00:00
} else {
2018-10-16 18:35:51 +00:00
_find_canvas_items_at_pos ( p_pos , p_node - > get_child ( i ) , r_items , canvas_item - > get_transform ( ) , p_canvas_xform ) ;
2018-09-19 09:05:24 +00:00
}
2018-05-03 22:27:37 +00:00
} else {
CanvasLayer * cl = Object : : cast_to < CanvasLayer > ( p_node ) ;
2018-10-16 18:35:51 +00:00
_find_canvas_items_at_pos ( p_pos , p_node - > get_child ( i ) , r_items , Transform2D ( ) , cl ? cl - > get_transform ( ) : p_canvas_xform ) ;
2015-11-04 21:39:07 +00:00
}
2018-05-03 22:27:37 +00:00
}
2015-11-04 21:39:07 +00:00
2018-05-03 22:27:37 +00:00
if ( canvas_item & & canvas_item - > is_visible_in_tree ( ) ) {
Transform2D xform = ( p_parent_xform * p_canvas_xform * canvas_item - > get_transform ( ) ) . affine_inverse ( ) ;
2019-01-24 19:43:11 +00:00
const real_t local_grab_distance = xform . basis_xform ( Vector2 ( grab_distance , 0 ) ) . length ( ) / zoom ;
2018-05-03 22:27:37 +00:00
if ( canvas_item - > _edit_is_selected_on_click ( xform . xform ( p_pos ) , local_grab_distance ) ) {
Node2D * node = Object : : cast_to < Node2D > ( canvas_item ) ;
2015-11-04 21:39:07 +00:00
2018-05-03 22:27:37 +00:00
_SelectResult res ;
res . item = canvas_item ;
res . z_index = node ? node - > get_z_index ( ) : 0 ;
res . has_z = node ;
r_items . push_back ( res ) ;
2015-11-04 21:39:07 +00:00
}
}
}
2014-02-10 01:10:30 +00:00
2021-08-18 11:27:33 +00:00
void CanvasItemEditor : : _get_canvas_items_at_pos ( const Point2 & p_pos , Vector < _SelectResult > & r_items , bool p_allow_locked ) {
2018-04-24 19:55:28 +00:00
Node * scene = editor - > get_edited_scene ( ) ;
2018-10-16 18:35:51 +00:00
_find_canvas_items_at_pos ( p_pos , scene , r_items ) ;
2018-04-24 19:55:28 +00:00
//Remove invalid results
for ( int i = 0 ; i < r_items . size ( ) ; i + + ) {
Node * node = r_items [ i ] . item ;
2018-05-03 22:27:37 +00:00
// Make sure the selected node is in the current scene, or editable
2021-02-20 09:27:03 +00:00
if ( node & & node ! = get_tree ( ) - > get_edited_scene_root ( ) ) {
node = scene - > get_deepest_editable_node ( node ) ;
}
2018-04-24 19:55:28 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( node ) ;
2021-08-18 11:27:33 +00:00
if ( ! p_allow_locked ) {
// Replace the node by the group if grouped.
while ( node & & node ! = scene - > get_parent ( ) ) {
CanvasItem * canvas_item_tmp = Object : : cast_to < CanvasItem > ( node ) ;
if ( canvas_item_tmp & & node - > has_meta ( " _edit_group_ " ) ) {
canvas_item = canvas_item_tmp ;
}
node = node - > get_parent ( ) ;
2018-04-24 19:55:28 +00:00
}
}
2018-05-15 07:37:23 +00:00
// Check if the canvas item is already in the list (for groups or scenes)
bool duplicate = false ;
for ( int j = 0 ; j < i ; j + + ) {
if ( r_items [ j ] . item = = canvas_item ) {
duplicate = true ;
break ;
}
}
2018-04-24 19:55:28 +00:00
//Remove the item if invalid
2021-08-18 11:27:33 +00:00
if ( ! canvas_item | | duplicate | | ( canvas_item ! = scene & & canvas_item - > get_owner ( ) ! = scene & & ! scene - > is_editable_instance ( canvas_item - > get_owner ( ) ) ) | | ( ! p_allow_locked & & _is_node_locked ( canvas_item ) ) ) {
2018-04-24 19:55:28 +00:00
r_items . remove ( i ) ;
i - - ;
} else {
2018-07-25 01:11:03 +00:00
r_items . write [ i ] . item = canvas_item ;
2018-04-24 19:55:28 +00:00
}
}
}
2018-05-15 13:18:46 +00:00
void CanvasItemEditor : : _get_bones_at_pos ( const Point2 & p_pos , Vector < _SelectResult > & r_items ) {
Point2 screen_pos = transform . xform ( p_pos ) ;
for ( Map < BoneKey , BoneList > : : Element * E = bone_list . front ( ) ; E ; E = E - > next ( ) ) {
Node2D * from_node = Object : : cast_to < Node2D > ( ObjectDB : : get_instance ( E - > key ( ) . from ) ) ;
Vector < Vector2 > bone_shape ;
2021-05-05 10:44:11 +00:00
if ( ! _get_bone_shape ( & bone_shape , nullptr , E ) ) {
2018-05-15 13:18:46 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2018-05-15 13:18:46 +00:00
// Check if the point is inside the Polygon2D
if ( Geometry : : is_point_in_polygon ( screen_pos , bone_shape ) ) {
// Check if the item is already in the list
bool duplicate = false ;
for ( int i = 0 ; i < r_items . size ( ) ; i + + ) {
if ( r_items [ i ] . item = = from_node ) {
duplicate = true ;
break ;
}
}
2021-05-05 10:44:11 +00:00
if ( duplicate ) {
2018-05-15 13:18:46 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2018-05-15 13:18:46 +00:00
// Else, add it
_SelectResult res ;
res . item = from_node ;
res . z_index = from_node ? from_node - > get_z_index ( ) : 0 ;
res . has_z = from_node ;
r_items . push_back ( res ) ;
}
}
}
bool CanvasItemEditor : : _get_bone_shape ( Vector < Vector2 > * shape , Vector < Vector2 > * outline_shape , Map < BoneKey , BoneList > : : Element * bone ) {
int bone_width = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_width " ) ;
int bone_outline_width = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_outline_size " ) ;
Node2D * from_node = Object : : cast_to < Node2D > ( ObjectDB : : get_instance ( bone - > key ( ) . from ) ) ;
Node2D * to_node = Object : : cast_to < Node2D > ( ObjectDB : : get_instance ( bone - > key ( ) . to ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! from_node ) {
2018-05-15 13:18:46 +00:00
return false ;
2021-05-05 10:44:11 +00:00
}
if ( ! from_node - > is_inside_tree ( ) ) {
2019-01-16 06:11:11 +00:00
return false ; //may have been removed
2021-05-05 10:44:11 +00:00
}
2018-05-15 13:18:46 +00:00
2021-05-05 10:44:11 +00:00
if ( ! to_node & & bone - > get ( ) . length = = 0 ) {
2018-05-15 13:18:46 +00:00
return false ;
2021-05-05 10:44:11 +00:00
}
2018-05-15 13:18:46 +00:00
Vector2 from = transform . xform ( from_node - > get_global_position ( ) ) ;
Vector2 to ;
2021-05-05 10:44:11 +00:00
if ( to_node ) {
2018-05-15 13:18:46 +00:00
to = transform . xform ( to_node - > get_global_position ( ) ) ;
2021-05-05 10:44:11 +00:00
} else {
2018-05-15 13:18:46 +00:00
to = transform . xform ( from_node - > get_global_transform ( ) . xform ( Vector2 ( bone - > get ( ) . length , 0 ) ) ) ;
2021-05-05 10:44:11 +00:00
}
2018-05-15 13:18:46 +00:00
Vector2 rel = to - from ;
Vector2 relt = rel . tangent ( ) . normalized ( ) * bone_width ;
Vector2 reln = rel . normalized ( ) ;
Vector2 reltn = relt . normalized ( ) ;
if ( shape ) {
shape - > clear ( ) ;
shape - > push_back ( from ) ;
shape - > push_back ( from + rel * 0.2 + relt ) ;
shape - > push_back ( to ) ;
shape - > push_back ( from + rel * 0.2 - relt ) ;
}
if ( outline_shape ) {
outline_shape - > clear ( ) ;
outline_shape - > push_back ( from + ( - reln - reltn ) * bone_outline_width ) ;
outline_shape - > push_back ( from + ( - reln + reltn ) * bone_outline_width ) ;
outline_shape - > push_back ( from + rel * 0.2 + relt + reltn * bone_outline_width ) ;
outline_shape - > push_back ( to + ( reln + reltn ) * bone_outline_width ) ;
outline_shape - > push_back ( to + ( reln - reltn ) * bone_outline_width ) ;
outline_shape - > push_back ( from + rel * 0.2 - relt - reltn * bone_outline_width ) ;
}
return true ;
}
2018-03-08 20:35:41 +00:00
void CanvasItemEditor : : _find_canvas_items_in_rect ( const Rect2 & p_rect , Node * p_node , List < CanvasItem * > * r_items , const Transform2D & p_parent_xform , const Transform2D & p_canvas_xform ) {
2021-05-05 10:44:11 +00:00
if ( ! p_node ) {
2014-02-10 01:10:30 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
if ( Object : : cast_to < Viewport > ( p_node ) ) {
2014-02-10 01:10:30 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
2018-05-03 22:27:37 +00:00
Node * scene = editor - > get_edited_scene ( ) ;
2014-02-10 01:10:30 +00:00
2021-02-20 09:27:03 +00:00
bool editable = p_node = = scene | | p_node - > get_owner ( ) = = scene | | p_node = = scene - > get_deepest_editable_node ( p_node ) ;
2017-03-05 15:44:50 +00:00
bool lock_children = p_node - > has_meta ( " _edit_group_ " ) & & p_node - > get_meta ( " _edit_group_ " ) ;
2018-10-16 18:35:51 +00:00
bool locked = _is_node_locked ( p_node ) ;
2017-11-07 07:58:35 +00:00
2018-05-03 22:27:37 +00:00
if ( ! lock_children | | ! editable ) {
2017-03-05 15:44:50 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2018-09-19 09:05:24 +00:00
if ( canvas_item ) {
if ( ! canvas_item - > is_set_as_toplevel ( ) ) {
_find_canvas_items_in_rect ( p_rect , p_node - > get_child ( i ) , r_items , p_parent_xform * canvas_item - > get_transform ( ) , p_canvas_xform ) ;
} else {
_find_canvas_items_in_rect ( p_rect , p_node - > get_child ( i ) , r_items , canvas_item - > get_transform ( ) , p_canvas_xform ) ;
}
2017-11-07 07:58:35 +00:00
} else {
CanvasLayer * canvas_layer = Object : : cast_to < CanvasLayer > ( p_node ) ;
2018-03-08 20:35:41 +00:00
_find_canvas_items_in_rect ( p_rect , p_node - > get_child ( i ) , r_items , Transform2D ( ) , canvas_layer ? canvas_layer - > get_transform ( ) : p_canvas_xform ) ;
2016-11-12 13:43:31 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
2018-05-03 22:27:37 +00:00
if ( canvas_item & & canvas_item - > is_visible_in_tree ( ) & & ! locked & & editable ) {
2017-11-07 07:58:35 +00:00
Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item - > get_transform ( ) ;
2014-02-10 01:10:30 +00:00
2018-03-08 20:35:41 +00:00
if ( canvas_item - > _edit_use_rect ( ) ) {
Rect2 rect = canvas_item - > _edit_get_rect ( ) ;
if ( p_rect . has_point ( xform . xform ( rect . position ) ) & &
p_rect . has_point ( xform . xform ( rect . position + Vector2 ( rect . size . x , 0 ) ) ) & &
p_rect . has_point ( xform . xform ( rect . position + Vector2 ( rect . size . x , rect . size . y ) ) ) & &
p_rect . has_point ( xform . xform ( rect . position + Vector2 ( 0 , rect . size . y ) ) ) ) {
r_items - > push_back ( canvas_item ) ;
}
} else {
if ( p_rect . has_point ( xform . xform ( Point2 ( ) ) ) ) {
r_items - > push_back ( canvas_item ) ;
}
2014-02-10 01:10:30 +00:00
}
}
}
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _select_click_on_item ( CanvasItem * item , Point2 p_click_pos , bool p_append ) {
2017-07-18 18:17:55 +00:00
bool still_selected = true ;
2021-04-13 10:09:53 +00:00
if ( p_append & & ! editor_selection - > get_selected_node_list ( ) . empty ( ) ) {
2015-11-04 21:39:07 +00:00
if ( editor_selection - > is_selected ( item ) ) {
2017-07-18 18:17:55 +00:00
// Already in the selection, remove it from the selected nodes
2015-11-04 21:39:07 +00:00
editor_selection - > remove_node ( item ) ;
2017-07-18 18:17:55 +00:00
still_selected = false ;
2021-04-13 10:09:53 +00:00
if ( editor_selection - > get_selected_node_list ( ) . size ( ) = = 1 ) {
editor - > push_item ( editor_selection - > get_selected_node_list ( ) [ 0 ] ) ;
}
2017-07-18 18:17:55 +00:00
} else {
// Add the item to the selection
2017-11-07 07:58:35 +00:00
editor_selection - > add_node ( item ) ;
2015-11-04 21:39:07 +00:00
}
} else {
if ( ! editor_selection - > is_selected ( item ) ) {
2017-07-18 18:17:55 +00:00
// Select a new one and clear previous selection
2015-11-04 21:39:07 +00:00
editor_selection - > clear ( ) ;
editor_selection - > add_node ( item ) ;
2017-07-18 18:17:55 +00:00
// Reselect
2017-08-18 23:02:56 +00:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2019-11-19 15:02:04 +00:00
selected_from_canvas = true ;
2017-03-05 15:44:50 +00:00
editor - > call ( " edit_node " , item ) ;
2015-11-04 21:39:07 +00:00
}
}
2017-07-18 18:17:55 +00:00
}
viewport - > update ( ) ;
return still_selected ;
2015-11-04 21:39:07 +00:00
}
2017-11-07 07:58:35 +00:00
List < CanvasItem * > CanvasItemEditor : : _get_edited_canvas_items ( bool retreive_locked , bool remove_canvas_item_if_parent_in_selection ) {
List < CanvasItem * > selection ;
for ( Map < Node * , Object * > : : Element * E = editor_selection - > get_selection ( ) . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2018-10-16 18:35:51 +00:00
if ( canvas_item & & canvas_item - > is_visible_in_tree ( ) & & canvas_item - > get_viewport ( ) = = EditorNode : : get_singleton ( ) - > get_scene_root ( ) & & ( retreive_locked | | ! _is_node_locked ( canvas_item ) ) ) {
2017-11-07 07:58:35 +00:00
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
if ( se ) {
selection . push_back ( canvas_item ) ;
}
}
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
if ( remove_canvas_item_if_parent_in_selection ) {
List < CanvasItem * > filtered_selection ;
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
if ( ! selection . find ( E - > get ( ) - > get_parent ( ) ) ) {
filtered_selection . push_back ( E - > get ( ) ) ;
}
}
return filtered_selection ;
} else {
return selection ;
}
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
Vector2 CanvasItemEditor : : _anchor_to_position ( const Control * p_control , Vector2 anchor ) {
ERR_FAIL_COND_V ( ! p_control , Vector2 ( ) ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
Transform2D parent_transform = p_control - > get_transform ( ) . affine_inverse ( ) ;
2018-05-05 14:59:00 +00:00
Rect2 parent_rect = p_control - > get_parent_anchorable_rect ( ) ;
2014-02-10 01:10:30 +00:00
2018-05-05 14:59:00 +00:00
return parent_transform . xform ( parent_rect . position + Vector2 ( parent_rect . size . x * anchor . x , parent_rect . size . y * anchor . y ) ) ;
2017-11-07 07:58:35 +00:00
}
2017-07-10 22:14:22 +00:00
2017-09-07 21:30:54 +00:00
Vector2 CanvasItemEditor : : _position_to_anchor ( const Control * p_control , Vector2 position ) {
2017-07-29 14:57:32 +00:00
ERR_FAIL_COND_V ( ! p_control , Vector2 ( ) ) ;
2018-05-05 14:59:00 +00:00
Rect2 parent_rect = p_control - > get_parent_anchorable_rect ( ) ;
2020-09-27 15:44:06 +00:00
Vector2 output = Vector2 ( ) ;
output . x = ( parent_rect . size . x = = 0 ) ? 0.0 : ( p_control - > get_transform ( ) . xform ( position ) . x - parent_rect . position . x ) / parent_rect . size . x ;
output . y = ( parent_rect . size . y = = 0 ) ? 0.0 : ( p_control - > get_transform ( ) . xform ( position ) . y - parent_rect . position . y ) / parent_rect . size . y ;
return output ;
2017-07-29 14:57:32 +00:00
}
2018-09-20 20:33:49 +00:00
void CanvasItemEditor : : _save_canvas_item_ik_chain ( const CanvasItem * p_canvas_item , List < float > * p_bones_length , List < Dictionary > * p_bones_state ) {
2021-05-05 10:44:11 +00:00
if ( p_bones_length ) {
2018-09-20 20:33:49 +00:00
* p_bones_length = List < float > ( ) ;
2021-05-05 10:44:11 +00:00
}
if ( p_bones_state ) {
2018-09-20 20:33:49 +00:00
* p_bones_state = List < Dictionary > ( ) ;
2021-05-05 10:44:11 +00:00
}
2018-09-20 20:33:49 +00:00
const Node2D * bone = Object : : cast_to < Node2D > ( p_canvas_item ) ;
if ( bone & & bone - > has_meta ( " _edit_bone_ " ) ) {
// Check if we have an IK chain
List < const Node2D * > bone_ik_list ;
bool ik_found = false ;
bone = Object : : cast_to < Node2D > ( bone - > get_parent ( ) ) ;
while ( bone ) {
bone_ik_list . push_back ( bone ) ;
if ( bone - > has_meta ( " _edit_ik_ " ) ) {
ik_found = true ;
break ;
} else if ( ! bone - > has_meta ( " _edit_bone_ " ) ) {
break ;
}
bone = Object : : cast_to < Node2D > ( bone - > get_parent ( ) ) ;
}
//Save the bone state and length if we have an IK chain
if ( ik_found ) {
bone = Object : : cast_to < Node2D > ( p_canvas_item ) ;
Transform2D bone_xform = bone - > get_global_transform ( ) ;
for ( List < const Node2D * > : : Element * bone_E = bone_ik_list . front ( ) ; bone_E ; bone_E = bone_E - > next ( ) ) {
bone_xform = bone_xform * bone - > get_transform ( ) . affine_inverse ( ) ;
const Node2D * parent_bone = bone_E - > get ( ) ;
2021-05-05 10:44:11 +00:00
if ( p_bones_length ) {
2018-09-20 20:33:49 +00:00
p_bones_length - > push_back ( parent_bone - > get_global_transform ( ) . get_origin ( ) . distance_to ( bone - > get_global_position ( ) ) ) ;
2021-05-05 10:44:11 +00:00
}
if ( p_bones_state ) {
2018-09-20 20:33:49 +00:00
p_bones_state - > push_back ( parent_bone - > _edit_get_state ( ) ) ;
2021-05-05 10:44:11 +00:00
}
2018-09-20 20:33:49 +00:00
bone = parent_bone ;
}
}
}
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _save_canvas_item_state ( List < CanvasItem * > p_canvas_items , bool save_bones ) {
for ( List < CanvasItem * > : : Element * E = p_canvas_items . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
if ( se ) {
se - > undo_state = canvas_item - > _edit_get_state ( ) ;
se - > pre_drag_xform = canvas_item - > get_global_transform_with_canvas ( ) ;
2018-03-08 20:35:41 +00:00
if ( canvas_item - > _edit_use_rect ( ) ) {
se - > pre_drag_rect = canvas_item - > _edit_get_rect ( ) ;
} else {
se - > pre_drag_rect = Rect2 ( ) ;
}
2017-11-07 07:58:35 +00:00
// If we have a bone, save the state of all nodes in the IK chain
2018-09-20 20:33:49 +00:00
_save_canvas_item_ik_chain ( canvas_item , & ( se - > pre_drag_bones_length ) , & ( se - > pre_drag_bones_undo_state ) ) ;
2017-07-29 14:57:32 +00:00
}
}
}
2018-09-20 20:33:49 +00:00
void CanvasItemEditor : : _restore_canvas_item_ik_chain ( CanvasItem * p_canvas_item , const List < Dictionary > * p_bones_state ) {
CanvasItem * canvas_item = p_canvas_item ;
for ( const List < Dictionary > : : Element * E = p_bones_state - > front ( ) ; E ; E = E - > next ( ) ) {
canvas_item = Object : : cast_to < CanvasItem > ( canvas_item - > get_parent ( ) ) ;
canvas_item - > _edit_set_state ( E - > get ( ) ) ;
}
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _restore_canvas_item_state ( List < CanvasItem * > p_canvas_items , bool restore_bones ) {
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
2017-03-22 23:47:51 +00:00
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2021-03-07 14:14:24 +00:00
if ( se ) {
canvas_item - > _edit_set_state ( se - > undo_state ) ;
if ( restore_bones ) {
_restore_canvas_item_ik_chain ( canvas_item , & ( se - > pre_drag_bones_undo_state ) ) ;
}
2014-02-10 01:10:30 +00:00
}
}
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _commit_canvas_item_state ( List < CanvasItem * > p_canvas_items , String action_name , bool commit_bones ) {
2021-01-03 16:24:10 +00:00
List < CanvasItem * > modified_canvas_items ;
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = p_canvas_items . front ( ) ; E ; E = E - > next ( ) ) {
2021-01-03 16:24:10 +00:00
CanvasItem * canvas_item = E - > get ( ) ;
Dictionary old_state = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) - > undo_state ;
Dictionary new_state = canvas_item - > _edit_get_state ( ) ;
if ( old_state . hash ( ) ! = new_state . hash ( ) ) {
modified_canvas_items . push_back ( canvas_item ) ;
}
}
if ( modified_canvas_items . empty ( ) ) {
return ;
}
undo_redo - > create_action ( action_name ) ;
for ( List < CanvasItem * > : : Element * E = modified_canvas_items . front ( ) ; E ; E = E - > next ( ) ) {
2017-11-07 07:58:35 +00:00
CanvasItem * canvas_item = E - > get ( ) ;
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2021-03-07 14:14:24 +00:00
if ( se ) {
undo_redo - > add_do_method ( canvas_item , " _edit_set_state " , canvas_item - > _edit_get_state ( ) ) ;
undo_redo - > add_undo_method ( canvas_item , " _edit_set_state " , se - > undo_state ) ;
if ( commit_bones ) {
for ( List < Dictionary > : : Element * F = se - > pre_drag_bones_undo_state . front ( ) ; F ; F = F - > next ( ) ) {
canvas_item = Object : : cast_to < CanvasItem > ( canvas_item - > get_parent ( ) ) ;
undo_redo - > add_do_method ( canvas_item , " _edit_set_state " , canvas_item - > _edit_get_state ( ) ) ;
undo_redo - > add_undo_method ( canvas_item , " _edit_set_state " , F - > get ( ) ) ;
}
2014-02-10 01:10:30 +00:00
}
}
}
2017-11-07 07:58:35 +00:00
undo_redo - > add_do_method ( viewport , " update " ) ;
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
}
2015-02-15 08:00:55 +00:00
void CanvasItemEditor : : _snap_changed ( ) {
2019-10-30 14:18:57 +00:00
( ( SnapDialog * ) snap_dialog ) - > get_fields ( grid_offset , grid_step , primary_grid_steps , snap_rotation_offset , snap_rotation_step , snap_scale_step ) ;
2017-08-31 19:54:42 +00:00
grid_step_multiplier = 0 ;
2015-02-15 08:00:55 +00:00
viewport - > update ( ) ;
}
2015-11-04 21:39:07 +00:00
void CanvasItemEditor : : _selection_result_pressed ( int p_result ) {
2021-05-05 10:44:11 +00:00
if ( selection_results . size ( ) < = p_result ) {
2015-11-04 21:39:07 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2015-11-04 21:39:07 +00:00
2017-03-05 15:44:50 +00:00
CanvasItem * item = selection_results [ p_result ] . item ;
2015-11-04 21:39:07 +00:00
2021-05-05 10:44:11 +00:00
if ( item ) {
2017-11-07 07:58:35 +00:00
_select_click_on_item ( item , Point2 ( ) , selection_menu_additive_selection ) ;
2021-05-05 10:44:11 +00:00
}
2015-11-04 21:39:07 +00:00
}
void CanvasItemEditor : : _selection_menu_hide ( ) {
selection_results . clear ( ) ;
selection_menu - > clear ( ) ;
selection_menu - > set_size ( Vector2 ( 0 , 0 ) ) ;
}
2021-07-07 11:19:59 +00:00
void CanvasItemEditor : : _add_node_pressed ( int p_result ) {
if ( p_result = = AddNodeOption : : ADD_NODE ) {
editor - > get_scene_tree_dock ( ) - > open_add_child_dialog ( ) ;
} else if ( p_result = = AddNodeOption : : ADD_INSTANCE ) {
editor - > get_scene_tree_dock ( ) - > open_instance_child_dialog ( ) ;
}
}
void CanvasItemEditor : : _node_created ( Node * p_node ) {
if ( node_create_position = = Point2 ( ) ) {
return ;
}
CanvasItem * c = Object : : cast_to < CanvasItem > ( p_node ) ;
if ( c ) {
Transform2D xform = c - > get_global_transform_with_canvas ( ) . affine_inverse ( ) * c - > get_transform ( ) ;
c - > _edit_set_position ( xform . xform ( node_create_position ) ) ;
}
call_deferred ( " _reset_create_position " ) ; // Defer the call in case more than one node is added.
}
void CanvasItemEditor : : _reset_create_position ( ) {
node_create_position = Point2 ( ) ;
}
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_rulers_and_guides ( const Ref < InputEvent > & p_event ) {
2017-10-18 21:55:02 +00:00
Ref < InputEventMouseButton > b = p_event ;
2017-11-07 07:58:35 +00:00
Ref < InputEventMouseMotion > m = p_event ;
if ( drag_type = = DRAG_NONE ) {
2019-07-13 15:16:32 +00:00
if ( show_guides & & show_rulers & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
Transform2D xform = viewport_scrollable - > get_transform ( ) * transform ;
// Retrieve the guide lists
Array vguides ;
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_vertical_guides_ " ) ) {
vguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_vertical_guides_ " ) ;
}
Array hguides ;
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_horizontal_guides_ " ) ) {
hguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_horizontal_guides_ " ) ;
}
// Hover over guides
float minimum = 1e20 ;
is_hovering_h_guide = false ;
is_hovering_v_guide = false ;
if ( m . is_valid ( ) & & m - > get_position ( ) . x < RULER_WIDTH ) {
// Check if we are hovering an existing horizontal guide
for ( int i = 0 ; i < hguides . size ( ) ; i + + ) {
if ( ABS ( xform . xform ( Point2 ( 0 , hguides [ i ] ) ) . y - m - > get_position ( ) . y ) < MIN ( minimum , 8 ) ) {
is_hovering_h_guide = true ;
is_hovering_v_guide = false ;
break ;
}
2017-10-18 21:55:02 +00:00
}
2019-07-13 15:16:32 +00:00
} else if ( m . is_valid ( ) & & m - > get_position ( ) . y < RULER_WIDTH ) {
// Check if we are hovering an existing vertical guide
for ( int i = 0 ; i < vguides . size ( ) ; i + + ) {
if ( ABS ( xform . xform ( Point2 ( vguides [ i ] , 0 ) ) . x - m - > get_position ( ) . x ) < MIN ( minimum , 8 ) ) {
is_hovering_v_guide = true ;
is_hovering_h_guide = false ;
break ;
}
2017-10-18 21:55:02 +00:00
}
2019-07-13 15:16:32 +00:00
}
// Start dragging a guide
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) ) {
2017-10-18 21:55:02 +00:00
// Press button
if ( b - > get_position ( ) . x < RULER_WIDTH & & b - > get_position ( ) . y < RULER_WIDTH ) {
// Drag a new double guide
2017-11-07 07:58:35 +00:00
drag_type = DRAG_DOUBLE_GUIDE ;
dragged_guide_index = - 1 ;
return true ;
2017-10-18 21:55:02 +00:00
} else if ( b - > get_position ( ) . x < RULER_WIDTH ) {
// Check if we drag an existing horizontal guide
2017-11-07 07:58:35 +00:00
dragged_guide_index = - 1 ;
2017-10-18 21:55:02 +00:00
for ( int i = 0 ; i < hguides . size ( ) ; i + + ) {
if ( ABS ( xform . xform ( Point2 ( 0 , hguides [ i ] ) ) . y - b - > get_position ( ) . y ) < MIN ( minimum , 8 ) ) {
2017-11-07 07:58:35 +00:00
dragged_guide_index = i ;
2017-10-18 21:55:02 +00:00
}
}
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
2017-10-18 21:55:02 +00:00
// Drag an existing horizontal guide
2017-11-07 07:58:35 +00:00
drag_type = DRAG_H_GUIDE ;
2017-10-18 21:55:02 +00:00
} else {
// Drag a new vertical guide
2017-11-07 07:58:35 +00:00
drag_type = DRAG_V_GUIDE ;
2017-10-18 21:55:02 +00:00
}
2017-11-07 07:58:35 +00:00
return true ;
2017-10-18 21:55:02 +00:00
} else if ( b - > get_position ( ) . y < RULER_WIDTH ) {
// Check if we drag an existing vertical guide
2017-11-07 07:58:35 +00:00
dragged_guide_index = - 1 ;
2017-10-18 21:55:02 +00:00
for ( int i = 0 ; i < vguides . size ( ) ; i + + ) {
if ( ABS ( xform . xform ( Point2 ( vguides [ i ] , 0 ) ) . x - b - > get_position ( ) . x ) < MIN ( minimum , 8 ) ) {
2017-11-07 07:58:35 +00:00
dragged_guide_index = i ;
2017-10-18 21:55:02 +00:00
}
}
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
2017-10-18 21:55:02 +00:00
// Drag an existing vertical guide
2017-11-07 07:58:35 +00:00
drag_type = DRAG_V_GUIDE ;
2017-10-18 21:55:02 +00:00
} else {
// Drag a new vertical guide
2017-11-07 07:58:35 +00:00
drag_type = DRAG_H_GUIDE ;
2017-10-18 21:55:02 +00:00
}
2017-11-07 07:58:35 +00:00
drag_from = xform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
return true ;
2017-10-18 21:55:02 +00:00
}
}
}
2017-11-07 07:58:35 +00:00
}
if ( drag_type = = DRAG_DOUBLE_GUIDE | | drag_type = = DRAG_V_GUIDE | | drag_type = = DRAG_H_GUIDE ) {
// Move the guide
if ( m . is_valid ( ) ) {
Transform2D xform = viewport_scrollable - > get_transform ( ) * transform ;
drag_to = xform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2017-10-18 21:55:02 +00:00
2017-11-07 07:58:35 +00:00
dragged_guide_pos = xform . xform ( snap_point ( drag_to , SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES ) ) ;
viewport - > update ( ) ;
return true ;
}
// Release confirms the guide move
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & ! b - > is_pressed ( ) ) {
2017-10-18 21:55:02 +00:00
if ( show_guides & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ) {
Transform2D xform = viewport_scrollable - > get_transform ( ) * transform ;
2018-01-18 20:37:17 +00:00
// Retrieve the guide lists
2017-10-18 21:55:02 +00:00
Array vguides ;
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_vertical_guides_ " ) ) {
vguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_vertical_guides_ " ) ;
}
Array hguides ;
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_horizontal_guides_ " ) ) {
hguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_horizontal_guides_ " ) ;
}
Point2 edited = snap_point ( xform . affine_inverse ( ) . xform ( b - > get_position ( ) ) , SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES ) ;
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_V_GUIDE ) {
2017-10-18 21:55:02 +00:00
Array prev_vguides = vguides . duplicate ( ) ;
if ( b - > get_position ( ) . x > RULER_WIDTH ) {
// Adds a new vertical guide
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
vguides [ dragged_guide_index ] = edited . x ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Move Vertical Guide " ) ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , vguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , prev_vguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
} else {
vguides . push_back ( edited . x ) ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Create Vertical Guide " ) ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , vguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , prev_vguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
}
} else {
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
vguides . remove ( dragged_guide_index ) ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Remove Vertical Guide " ) ) ;
2019-12-06 01:19:54 +00:00
if ( vguides . empty ( ) ) {
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " remove_meta " , " _edit_vertical_guides_ " ) ;
} else {
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , vguides ) ;
}
2017-10-18 21:55:02 +00:00
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , prev_vguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
}
}
2017-11-07 07:58:35 +00:00
} else if ( drag_type = = DRAG_H_GUIDE ) {
2017-10-18 21:55:02 +00:00
Array prev_hguides = hguides . duplicate ( ) ;
if ( b - > get_position ( ) . y > RULER_WIDTH ) {
// Adds a new horizontal guide
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
hguides [ dragged_guide_index ] = edited . y ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Move Horizontal Guide " ) ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , hguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , prev_hguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
} else {
hguides . push_back ( edited . y ) ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Create Horizontal Guide " ) ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , hguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , prev_hguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
}
} else {
2017-11-07 07:58:35 +00:00
if ( dragged_guide_index > = 0 ) {
hguides . remove ( dragged_guide_index ) ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Remove Horizontal Guide " ) ) ;
2019-12-06 01:19:54 +00:00
if ( hguides . empty ( ) ) {
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " remove_meta " , " _edit_horizontal_guides_ " ) ;
} else {
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , hguides ) ;
}
2017-10-18 21:55:02 +00:00
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , prev_hguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
}
}
2017-11-07 07:58:35 +00:00
} else if ( drag_type = = DRAG_DOUBLE_GUIDE ) {
2017-10-18 21:55:02 +00:00
Array prev_hguides = hguides . duplicate ( ) ;
Array prev_vguides = vguides . duplicate ( ) ;
if ( b - > get_position ( ) . x > RULER_WIDTH & & b - > get_position ( ) . y > RULER_WIDTH ) {
// Adds a new horizontal guide a new vertical guide
vguides . push_back ( edited . x ) ;
hguides . push_back ( edited . y ) ;
2019-07-13 15:16:32 +00:00
undo_redo - > create_action ( TTR ( " Create Horizontal and Vertical Guides " ) ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , vguides ) ;
undo_redo - > add_do_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , hguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_vertical_guides_ " , prev_vguides ) ;
undo_redo - > add_undo_method ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) , " set_meta " , " _edit_horizontal_guides_ " , prev_hguides ) ;
2017-11-07 07:58:35 +00:00
undo_redo - > add_undo_method ( viewport , " update " ) ;
2017-10-18 21:55:02 +00:00
undo_redo - > commit_action ( ) ;
}
}
}
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
2017-10-29 21:00:03 +00:00
}
}
2017-11-07 07:58:35 +00:00
return false ;
2017-10-15 20:33:25 +00:00
}
2019-07-28 14:00:05 +00:00
bool CanvasItemEditor : : _gui_input_zoom_or_pan ( const Ref < InputEvent > & p_event , bool p_already_accepted ) {
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseButton > b = p_event ;
2019-07-28 14:00:05 +00:00
if ( b . is_valid ( ) & & ! p_already_accepted ) {
2020-06-19 17:27:33 +00:00
const bool pan_on_scroll = bool ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/scroll_to_pan " ) ) & & ! b - > get_control ( ) ;
if ( pan_on_scroll ) {
// Perform horizontal scrolling first so we can check for Shift being held.
if ( b - > is_pressed ( ) & &
( b - > get_button_index ( ) = = BUTTON_WHEEL_LEFT | | ( b - > get_shift ( ) & & b - > get_button_index ( ) = = BUTTON_WHEEL_UP ) ) ) {
// Pan left
view_offset . x - = int ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/pan_speed " ) ) / zoom * b - > get_factor ( ) ;
update_viewport ( ) ;
return true ;
}
if ( b - > is_pressed ( ) & &
( b - > get_button_index ( ) = = BUTTON_WHEEL_RIGHT | | ( b - > get_shift ( ) & & b - > get_button_index ( ) = = BUTTON_WHEEL_DOWN ) ) ) {
// Pan right
view_offset . x + = int ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/pan_speed " ) ) / zoom * b - > get_factor ( ) ;
update_viewport ( ) ;
return true ;
}
}
2019-07-20 14:55:02 +00:00
2018-04-22 21:27:46 +00:00
if ( b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_WHEEL_DOWN ) {
2017-07-18 18:17:55 +00:00
// Scroll or pan down
2019-07-20 14:55:02 +00:00
if ( pan_on_scroll ) {
2018-03-15 14:12:16 +00:00
view_offset . y + = int ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/pan_speed " ) ) / zoom * b - > get_factor ( ) ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2017-06-05 23:33:38 +00:00
} else {
2021-04-27 22:54:59 +00:00
float new_zoom = _get_next_zoom_value ( - 1 , b - > get_alt ( ) ) ;
if ( ! Math : : is_equal_approx ( b - > get_factor ( ) , 1.0f ) ) {
// Handle high-precision (analog) scrolling.
2020-03-15 18:13:07 +00:00
new_zoom = zoom * ( ( new_zoom / zoom - 1.f ) * b - > get_factor ( ) + 1.f ) ;
}
_zoom_on_position ( new_zoom , b - > get_position ( ) ) ;
2014-05-24 04:35:47 +00:00
}
2017-11-07 07:58:35 +00:00
return true ;
2014-02-10 01:10:30 +00:00
}
2018-04-22 21:27:46 +00:00
if ( b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_WHEEL_UP ) {
2017-07-18 18:17:55 +00:00
// Scroll or pan up
2019-07-20 14:55:02 +00:00
if ( pan_on_scroll ) {
2018-03-15 14:12:16 +00:00
view_offset . y - = int ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/pan_speed " ) ) / zoom * b - > get_factor ( ) ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2017-06-05 23:33:38 +00:00
} else {
2021-04-27 22:54:59 +00:00
float new_zoom = _get_next_zoom_value ( 1 , b - > get_alt ( ) ) ;
if ( ! Math : : is_equal_approx ( b - > get_factor ( ) , 1.0f ) ) {
// Handle high-precision (analog) scrolling.
2020-03-15 18:13:07 +00:00
new_zoom = zoom * ( ( new_zoom / zoom - 1.f ) * b - > get_factor ( ) + 1.f ) ;
}
_zoom_on_position ( new_zoom , b - > get_position ( ) ) ;
2014-05-24 04:35:47 +00:00
}
2017-11-07 07:58:35 +00:00
return true ;
2014-02-10 01:10:30 +00:00
}
2019-04-07 14:43:21 +00:00
if ( ! panning ) {
2018-04-22 21:27:46 +00:00
if ( b - > is_pressed ( ) & &
( b - > get_button_index ( ) = = BUTTON_MIDDLE | |
2019-07-20 14:55:02 +00:00
b - > get_button_index ( ) = = BUTTON_RIGHT | |
2018-04-22 21:27:46 +00:00
( b - > get_button_index ( ) = = BUTTON_LEFT & & tool = = TOOL_PAN ) | |
2019-06-05 20:35:07 +00:00
( b - > get_button_index ( ) = = BUTTON_LEFT & & ! EditorSettings : : get_singleton ( ) - > get ( " editors/2d/simple_panning " ) & & pan_pressed ) ) ) {
2017-11-07 07:58:35 +00:00
// Pan the viewport
2019-04-07 14:43:21 +00:00
panning = true ;
2018-04-22 21:27:46 +00:00
}
}
2019-04-07 14:43:21 +00:00
if ( panning ) {
2019-11-04 11:33:24 +00:00
if ( ! b - > is_pressed ( ) & & ( pan_on_scroll | | ( b - > get_button_index ( ) ! = BUTTON_WHEEL_DOWN & & b - > get_button_index ( ) ! = BUTTON_WHEEL_UP ) ) ) {
// Stop panning the viewport (for any mouse button press except zooming)
2019-04-07 14:43:21 +00:00
panning = false ;
2018-04-22 21:27:46 +00:00
}
}
}
Ref < InputEventKey > k = p_event ;
if ( k . is_valid ( ) ) {
2021-04-27 22:54:59 +00:00
if ( k - > is_pressed ( ) ) {
2021-07-15 17:58:44 +00:00
if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_3.125_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 1.0 / 32.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_6.25_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 1.0 / 16.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_12.5_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 1.0 / 8.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_25_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 1.0 / 4.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_50_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 1.0 / 2.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_100_percent " ) - > is_shortcut ( p_event ) ) {
2021-04-27 22:54:59 +00:00
_shortcut_zoom_set ( 1.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_200_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 2.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_400_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 4.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_800_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 8.0 ) ;
} else if ( ED_GET_SHORTCUT ( " canvas_item_editor/zoom_1600_percent " ) - > is_shortcut ( p_event ) ) {
_shortcut_zoom_set ( 16.0 ) ;
}
}
2019-06-05 20:35:07 +00:00
bool is_pan_key = pan_view_shortcut . is_valid ( ) & & pan_view_shortcut - > is_shortcut ( p_event ) ;
if ( is_pan_key & & ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/simple_panning " ) | | drag_type ! = DRAG_NONE ) ) {
2019-04-07 14:43:21 +00:00
if ( ! panning ) {
2018-04-22 21:27:46 +00:00
if ( k - > is_pressed ( ) & & ! k - > is_echo ( ) ) {
//Pan the viewport
2019-04-07 14:43:21 +00:00
panning = true ;
2014-02-10 01:10:30 +00:00
}
2019-10-14 09:40:55 +00:00
} else {
2018-04-22 21:27:46 +00:00
if ( ! k - > is_pressed ( ) ) {
// Stop panning the viewport (for any mouse button press)
2019-04-07 14:43:21 +00:00
panning = false ;
2018-04-22 21:27:46 +00:00
}
}
}
2019-06-05 20:35:07 +00:00
2021-05-05 10:44:11 +00:00
if ( is_pan_key ) {
2019-06-05 20:35:07 +00:00
pan_pressed = k - > is_pressed ( ) ;
2021-05-05 10:44:11 +00:00
}
2018-04-22 21:27:46 +00:00
}
Ref < InputEventMouseMotion > m = p_event ;
if ( m . is_valid ( ) ) {
2019-04-07 14:43:21 +00:00
if ( panning ) {
2018-04-22 21:27:46 +00:00
// Pan the viewport
Point2i relative ;
if ( bool ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/warped_mouse_panning " ) ) ) {
relative = Input : : get_singleton ( ) - > warp_mouse_motion ( m , viewport - > get_global_rect ( ) ) ;
} else {
relative = m - > get_relative ( ) ;
2015-12-28 12:38:15 +00:00
}
2018-04-22 21:27:46 +00:00
view_offset . x - = relative . x / zoom ;
view_offset . y - = relative . y / zoom ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2018-04-22 21:27:46 +00:00
return true ;
2015-12-28 12:38:15 +00:00
}
2017-11-07 07:58:35 +00:00
}
2015-12-28 12:38:15 +00:00
2017-11-07 07:58:35 +00:00
Ref < InputEventMagnifyGesture > magnify_gesture = p_event ;
2019-07-28 14:00:05 +00:00
if ( magnify_gesture . is_valid ( ) & & ! p_already_accepted ) {
2017-11-07 07:58:35 +00:00
// Zoom gesture
_zoom_on_position ( zoom * magnify_gesture - > get_factor ( ) , magnify_gesture - > get_position ( ) ) ;
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
Ref < InputEventPanGesture > pan_gesture = p_event ;
2019-07-28 14:00:05 +00:00
if ( pan_gesture . is_valid ( ) & & ! p_already_accepted ) {
2020-06-08 16:23:30 +00:00
// If control key pressed, then zoom instead of pan
if ( pan_gesture - > get_control ( ) ) {
const float factor = pan_gesture - > get_delta ( ) . y ;
float new_zoom = _get_next_zoom_value ( - 1 ) ;
if ( factor ! = 1.f ) {
new_zoom = zoom * ( ( new_zoom / zoom - 1.f ) * factor + 1.f ) ;
}
_zoom_on_position ( new_zoom , pan_gesture - > get_position ( ) ) ;
return true ;
}
2017-11-07 07:58:35 +00:00
// Pan gesture
const Vector2 delta = ( int ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/pan_speed " ) ) / zoom ) * pan_gesture - > get_delta ( ) ;
2018-03-15 14:12:16 +00:00
view_offset . x + = delta . x ;
view_offset . y + = delta . y ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2017-11-07 07:58:35 +00:00
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
return false ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_pivot ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseMotion > m = p_event ;
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventKey > k = p_event ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Drag the pivot (in pivot mode / with V key)
if ( drag_type = = DRAG_NONE ) {
if ( ( b . is_valid ( ) & & b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & tool = = TOOL_EDIT_PIVOT ) | |
( k . is_valid ( ) & & k - > is_pressed ( ) & & ! k - > is_echo ( ) & & k - > get_scancode ( ) = = KEY_V ) ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
// Filters the selection with nodes that allow setting the pivot
drag_selection = List < CanvasItem * > ( ) ;
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
if ( canvas_item - > _edit_use_pivot ( ) ) {
drag_selection . push_back ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
}
}
2017-11-07 07:58:35 +00:00
// Start dragging if we still have nodes
if ( drag_selection . size ( ) > 0 ) {
2019-11-05 13:59:03 +00:00
_save_canvas_item_state ( drag_selection ) ;
2017-11-07 07:58:35 +00:00
drag_from = transform . affine_inverse ( ) . xform ( ( b . is_valid ( ) ) ? b - > get_position ( ) : viewport - > get_local_mouse_position ( ) ) ;
Vector2 new_pos ;
2019-04-05 08:18:21 +00:00
if ( drag_selection . size ( ) = = 1 ) {
new_pos = snap_point ( drag_from , SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , drag_selection [ 0 ] ) ;
} else {
2021-05-04 14:00:45 +00:00
new_pos = snap_point ( drag_from , SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , nullptr , drag_selection ) ;
2019-04-05 08:18:21 +00:00
}
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
canvas_item - > _edit_set_pivot ( canvas_item - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( new_pos ) ) ;
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
drag_type = DRAG_PIVOT ;
}
return true ;
}
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_PIVOT ) {
// Move the pivot
if ( m . is_valid ( ) ) {
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
_restore_canvas_item_state ( drag_selection ) ;
Vector2 new_pos ;
2021-05-05 10:44:11 +00:00
if ( drag_selection . size ( ) = = 1 ) {
2019-04-05 08:18:21 +00:00
new_pos = snap_point ( drag_to , SNAP_NODE_SIDES | SNAP_NODE_CENTER | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , drag_selection [ 0 ] ) ;
2021-05-05 10:44:11 +00:00
} else {
2017-11-07 07:58:35 +00:00
new_pos = snap_point ( drag_to , SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
canvas_item - > _edit_set_pivot ( canvas_item - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( new_pos ) ) ;
}
return true ;
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
// Confirm the pivot move
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) > = 1 & &
( ( b . is_valid ( ) & & ! b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & tool = = TOOL_EDIT_PIVOT ) | |
( k . is_valid ( ) & & ! k - > is_pressed ( ) & & k - > get_scancode ( ) = = KEY_V ) ) ) {
_commit_canvas_item_state (
drag_selection ,
vformat (
TTR ( " Set CanvasItem \" %s \" Pivot Offset to (%d, %d) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
drag_selection [ 0 ] - > _edit_get_pivot ( ) . x ,
drag_selection [ 0 ] - > _edit_get_pivot ( ) . y ) ) ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
return true ;
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
}
return false ;
}
void CanvasItemEditor : : _solve_IK ( Node2D * leaf_node , Point2 target_position ) {
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( leaf_node ) ;
2018-09-20 20:33:49 +00:00
if ( se ) {
int nb_bones = se - > pre_drag_bones_undo_state . size ( ) ;
if ( nb_bones > 0 ) {
// Build the node list
Point2 leaf_pos = target_position ;
List < Node2D * > joints_list ;
List < Point2 > joints_pos ;
Node2D * joint = leaf_node ;
Transform2D joint_transform = leaf_node - > get_global_transform_with_canvas ( ) ;
for ( int i = 0 ; i < nb_bones + 1 ; i + + ) {
joints_list . push_back ( joint ) ;
joints_pos . push_back ( joint_transform . get_origin ( ) ) ;
joint_transform = joint_transform * joint - > get_transform ( ) . affine_inverse ( ) ;
joint = Object : : cast_to < Node2D > ( joint - > get_parent ( ) ) ;
}
Point2 root_pos = joints_list . back ( ) - > get ( ) - > get_global_transform_with_canvas ( ) . get_origin ( ) ;
// Restraints the node to a maximum distance is necessary
float total_len = 0 ;
2017-11-07 07:58:35 +00:00
for ( List < float > : : Element * E = se - > pre_drag_bones_length . front ( ) ; E ; E = E - > next ( ) ) {
2018-09-20 20:33:49 +00:00
total_len + = E - > get ( ) ;
}
if ( ( root_pos . distance_to ( leaf_pos ) ) > total_len ) {
Vector2 rel = leaf_pos - root_pos ;
rel = rel . normalized ( ) * total_len ;
leaf_pos = root_pos + rel ;
}
joints_pos [ 0 ] = leaf_pos ;
// Run the solver
int solver_iterations = 64 ;
float solver_k = 0.3 ;
// Build the position list
for ( int i = 0 ; i < solver_iterations ; i + + ) {
// Handle the leaf joint
int node_id = 0 ;
for ( List < float > : : Element * E = se - > pre_drag_bones_length . front ( ) ; E ; E = E - > next ( ) ) {
Vector2 direction = ( joints_pos [ node_id + 1 ] - joints_pos [ node_id ] ) . normalized ( ) ;
int len = E - > get ( ) ;
if ( E = = se - > pre_drag_bones_length . front ( ) ) {
joints_pos [ 1 ] = joints_pos [ 1 ] . linear_interpolate ( joints_pos [ 0 ] + len * direction , solver_k ) ;
} else if ( E = = se - > pre_drag_bones_length . back ( ) ) {
joints_pos [ node_id ] = joints_pos [ node_id ] . linear_interpolate ( joints_pos [ node_id + 1 ] - len * direction , solver_k ) ;
} else {
Vector2 center = ( joints_pos [ node_id + 1 ] + joints_pos [ node_id ] ) / 2.0 ;
joints_pos [ node_id ] = joints_pos [ node_id ] . linear_interpolate ( center - ( direction * len ) / 2.0 , solver_k ) ;
joints_pos [ node_id + 1 ] = joints_pos [ node_id + 1 ] . linear_interpolate ( center + ( direction * len ) / 2.0 , solver_k ) ;
}
node_id + + ;
2014-02-10 01:10:30 +00:00
}
}
2018-09-20 20:33:49 +00:00
// Set the position
for ( int node_id = joints_list . size ( ) - 1 ; node_id > 0 ; node_id - - ) {
Point2 current = ( joints_list [ node_id - 1 ] - > get_global_position ( ) - joints_list [ node_id ] - > get_global_position ( ) ) . normalized ( ) ;
Point2 target = ( joints_pos [ node_id - 1 ] - joints_list [ node_id ] - > get_global_position ( ) ) . normalized ( ) ;
float rot = current . angle_to ( target ) ;
if ( joints_list [ node_id ] - > get_global_transform ( ) . basis_determinant ( ) < 0 ) {
rot = - rot ;
}
joints_list [ node_id ] - > rotate ( rot ) ;
2017-11-07 07:58:35 +00:00
}
}
}
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_rotate ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Start rotation
if ( drag_type = = DRAG_NONE ) {
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) ) {
2020-11-18 10:16:22 +00:00
if ( ( b - > get_command ( ) & & ! b - > get_alt ( ) & & tool = = TOOL_SELECT ) | | tool = = TOOL_ROTATE ) {
2018-10-25 17:08:32 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
2018-10-16 18:35:51 +00:00
2018-10-25 17:08:32 +00:00
// Remove not movable nodes
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2021-05-05 10:44:11 +00:00
if ( ! _is_node_movable ( E - > get ( ) , true ) ) {
2018-10-25 17:08:32 +00:00
selection . erase ( E ) ;
2021-05-05 10:44:11 +00:00
}
2018-10-25 17:08:32 +00:00
}
2018-10-16 18:35:51 +00:00
2018-10-25 17:08:32 +00:00
drag_selection = selection ;
if ( drag_selection . size ( ) > 0 ) {
drag_type = DRAG_ROTATE ;
drag_from = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
CanvasItem * canvas_item = drag_selection [ 0 ] ;
if ( canvas_item - > _edit_use_pivot ( ) ) {
drag_rotation_center = canvas_item - > get_global_transform_with_canvas ( ) . xform ( canvas_item - > _edit_get_pivot ( ) ) ;
} else {
drag_rotation_center = canvas_item - > get_global_transform_with_canvas ( ) . get_origin ( ) ;
}
_save_canvas_item_state ( drag_selection ) ;
return true ;
2014-07-06 14:49:27 +00:00
}
}
2017-11-07 07:58:35 +00:00
}
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_ROTATE ) {
// Rotate the node
if ( m . is_valid ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2020-01-07 02:43:22 +00:00
//Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements
bool opposite = ( canvas_item - > get_global_transform ( ) . get_scale ( ) . sign ( ) . dot ( canvas_item - > get_transform ( ) . get_scale ( ) . sign ( ) ) = = 0 ) ;
canvas_item - > _edit_set_rotation ( snap_angle ( canvas_item - > _edit_get_rotation ( ) + ( opposite ? - 1 : 1 ) * ( drag_from - drag_rotation_center ) . angle_to ( drag_to - drag_rotation_center ) , canvas_item - > _edit_get_rotation ( ) ) ) ;
2017-11-07 07:58:35 +00:00
viewport - > update ( ) ;
}
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Confirms the node rotation
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & ! b - > is_pressed ( ) ) {
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) ! = 1 ) {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Rotate %d CanvasItems " ) , drag_selection . size ( ) ) ,
true ) ;
} else {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Rotate CanvasItem \" %s \" to %d degrees " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
Math : : rad2deg ( drag_selection [ 0 ] - > _edit_get_rotation ( ) ) ) ,
true ) ;
}
2019-04-15 03:49:03 +00:00
if ( key_auto_insert_button - > is_pressed ( ) ) {
_insert_animation_keys ( false , true , false , true ) ;
}
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
}
return false ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_open_scene_on_double_click ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Open a sub-scene on double-click
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) & & b - > is_doubleclick ( ) & & tool = = TOOL_SELECT ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( selection . size ( ) = = 1 ) {
CanvasItem * canvas_item = selection [ 0 ] ;
if ( canvas_item - > get_filename ( ) ! = " " & & canvas_item ! = editor - > get_edited_scene ( ) ) {
editor - > open_request ( canvas_item - > get_filename ( ) ) ;
return true ;
}
}
}
return false ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_anchors ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Starts anchor dragging if needed
if ( drag_type = = DRAG_NONE ) {
2019-03-31 16:53:24 +00:00
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) & & tool = = TOOL_SELECT ) {
2017-11-07 07:58:35 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( selection . size ( ) = = 1 ) {
Control * control = Object : : cast_to < Control > ( selection [ 0 ] ) ;
2018-10-16 18:35:51 +00:00
if ( control & & _is_node_movable ( control ) ) {
2017-11-07 07:58:35 +00:00
Vector2 anchor_pos [ 4 ] ;
anchor_pos [ 0 ] = Vector2 ( control - > get_anchor ( MARGIN_LEFT ) , control - > get_anchor ( MARGIN_TOP ) ) ;
anchor_pos [ 1 ] = Vector2 ( control - > get_anchor ( MARGIN_RIGHT ) , control - > get_anchor ( MARGIN_TOP ) ) ;
anchor_pos [ 2 ] = Vector2 ( control - > get_anchor ( MARGIN_RIGHT ) , control - > get_anchor ( MARGIN_BOTTOM ) ) ;
anchor_pos [ 3 ] = Vector2 ( control - > get_anchor ( MARGIN_LEFT ) , control - > get_anchor ( MARGIN_BOTTOM ) ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
Rect2 anchor_rects [ 4 ] ;
for ( int i = 0 ; i < 4 ; i + + ) {
anchor_pos [ i ] = ( transform * control - > get_global_transform_with_canvas ( ) ) . xform ( _anchor_to_position ( control , anchor_pos [ i ] ) ) ;
anchor_rects [ i ] = Rect2 ( anchor_pos [ i ] , anchor_handle - > get_size ( ) ) ;
2019-07-20 06:09:57 +00:00
anchor_rects [ i ] . position - = anchor_handle - > get_size ( ) * Vector2 ( float ( i = = 0 | | i = = 3 ) , float ( i < = 1 ) ) ;
2017-11-07 07:58:35 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
DragType dragger [ ] = {
DRAG_ANCHOR_TOP_LEFT ,
DRAG_ANCHOR_TOP_RIGHT ,
DRAG_ANCHOR_BOTTOM_RIGHT ,
DRAG_ANCHOR_BOTTOM_LEFT ,
} ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
if ( anchor_rects [ i ] . has_point ( b - > get_position ( ) ) ) {
if ( ( anchor_pos [ 0 ] = = anchor_pos [ 2 ] ) & & ( anchor_pos [ 0 ] . distance_to ( b - > get_position ( ) ) < anchor_handle - > get_size ( ) . length ( ) / 3.0 ) ) {
drag_type = DRAG_ANCHOR_ALL ;
} else {
drag_type = dragger [ i ] ;
}
drag_from = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
drag_selection = List < CanvasItem * > ( ) ;
drag_selection . push_back ( control ) ;
_save_canvas_item_state ( drag_selection ) ;
return true ;
2014-07-06 14:49:27 +00:00
}
}
}
}
}
2017-11-07 07:58:35 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_ANCHOR_TOP_LEFT | | drag_type = = DRAG_ANCHOR_TOP_RIGHT | | drag_type = = DRAG_ANCHOR_BOTTOM_RIGHT | | drag_type = = DRAG_ANCHOR_BOTTOM_LEFT | | drag_type = = DRAG_ANCHOR_ALL ) {
// Drag the anchor
if ( m . is_valid ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
Control * control = Object : : cast_to < Control > ( drag_selection [ 0 ] ) ;
2017-07-29 14:57:32 +00:00
2017-11-07 07:58:35 +00:00
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
Transform2D xform = control - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
Point2 previous_anchor ;
previous_anchor . x = ( drag_type = = DRAG_ANCHOR_TOP_LEFT | | drag_type = = DRAG_ANCHOR_BOTTOM_LEFT ) ? control - > get_anchor ( MARGIN_LEFT ) : control - > get_anchor ( MARGIN_RIGHT ) ;
previous_anchor . y = ( drag_type = = DRAG_ANCHOR_TOP_LEFT | | drag_type = = DRAG_ANCHOR_TOP_RIGHT ) ? control - > get_anchor ( MARGIN_TOP ) : control - > get_anchor ( MARGIN_BOTTOM ) ;
previous_anchor = xform . affine_inverse ( ) . xform ( _anchor_to_position ( control , previous_anchor ) ) ;
2014-02-10 01:10:30 +00:00
2019-04-05 08:18:21 +00:00
Vector2 new_anchor = xform . xform ( snap_point ( previous_anchor + ( drag_to - drag_from ) , SNAP_GRID | SNAP_OTHER_NODES , SNAP_NODE_PARENT | SNAP_NODE_SIDES | SNAP_NODE_CENTER , control ) ) ;
2017-11-07 07:58:35 +00:00
new_anchor = _position_to_anchor ( control , new_anchor ) . snapped ( Vector2 ( 0.001 , 0.001 ) ) ;
2017-07-18 18:17:55 +00:00
2017-11-07 07:58:35 +00:00
bool use_single_axis = m - > get_shift ( ) ;
Vector2 drag_vector = xform . xform ( drag_to ) - xform . xform ( drag_from ) ;
bool use_y = Math : : abs ( drag_vector . y ) > Math : : abs ( drag_vector . x ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
switch ( drag_type ) {
case DRAG_ANCHOR_TOP_LEFT :
2021-05-05 10:44:11 +00:00
if ( ! use_single_axis | | ! use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_LEFT , new_anchor . x , false , false ) ;
2021-05-05 10:44:11 +00:00
}
if ( ! use_single_axis | | use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_TOP , new_anchor . y , false , false ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
break ;
case DRAG_ANCHOR_TOP_RIGHT :
2021-05-05 10:44:11 +00:00
if ( ! use_single_axis | | ! use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_RIGHT , new_anchor . x , false , false ) ;
2021-05-05 10:44:11 +00:00
}
if ( ! use_single_axis | | use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_TOP , new_anchor . y , false , false ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
break ;
case DRAG_ANCHOR_BOTTOM_RIGHT :
2021-05-05 10:44:11 +00:00
if ( ! use_single_axis | | ! use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_RIGHT , new_anchor . x , false , false ) ;
2021-05-05 10:44:11 +00:00
}
if ( ! use_single_axis | | use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_BOTTOM , new_anchor . y , false , false ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
break ;
case DRAG_ANCHOR_BOTTOM_LEFT :
2021-05-05 10:44:11 +00:00
if ( ! use_single_axis | | ! use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_LEFT , new_anchor . x , false , false ) ;
2021-05-05 10:44:11 +00:00
}
if ( ! use_single_axis | | use_y ) {
2021-05-04 12:28:27 +00:00
control - > set_anchor ( MARGIN_BOTTOM , new_anchor . y , false , false ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
break ;
case DRAG_ANCHOR_ALL :
2019-04-04 20:00:16 +00:00
if ( ! use_single_axis | | ! use_y ) {
control - > set_anchor ( MARGIN_LEFT , new_anchor . x , false , true ) ;
control - > set_anchor ( MARGIN_RIGHT , new_anchor . x , false , true ) ;
}
if ( ! use_single_axis | | use_y ) {
control - > set_anchor ( MARGIN_TOP , new_anchor . y , false , true ) ;
control - > set_anchor ( MARGIN_BOTTOM , new_anchor . y , false , true ) ;
}
2017-11-07 07:58:35 +00:00
break ;
default :
break ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
return true ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
// Confirms new anchor position
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) > = 1 & & b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & ! b - > is_pressed ( ) ) {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Move CanvasItem \" %s \" Anchor " ) , drag_selection [ 0 ] - > get_name ( ) ) ) ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
return true ;
2017-08-08 10:13:17 +00:00
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
2017-07-18 18:17:55 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
return false ;
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_resize ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
2017-05-20 15:38:03 +00:00
Ref < InputEventMouseMotion > m = p_event ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
// Drag resize handles
if ( drag_type = = DRAG_NONE ) {
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) & & tool = = TOOL_SELECT ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( selection . size ( ) = = 1 ) {
CanvasItem * canvas_item = selection [ 0 ] ;
2018-10-16 18:35:51 +00:00
if ( canvas_item - > _edit_use_rect ( ) & & _is_node_movable ( canvas_item ) ) {
2018-03-08 20:35:41 +00:00
Rect2 rect = canvas_item - > _edit_get_rect ( ) ;
Transform2D xform = transform * canvas_item - > get_global_transform_with_canvas ( ) ;
Vector2 endpoints [ 4 ] = {
xform . xform ( rect . position ) ,
xform . xform ( rect . position + Vector2 ( rect . size . x , 0 ) ) ,
xform . xform ( rect . position + rect . size ) ,
xform . xform ( rect . position + Vector2 ( 0 , rect . size . y ) )
} ;
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
DragType dragger [ ] = {
DRAG_TOP_LEFT ,
DRAG_TOP ,
DRAG_TOP_RIGHT ,
DRAG_RIGHT ,
DRAG_BOTTOM_RIGHT ,
DRAG_BOTTOM ,
DRAG_BOTTOM_LEFT ,
DRAG_LEFT
} ;
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
DragType resize_drag = DRAG_NONE ;
float radius = ( select_handle - > get_size ( ) . width / 2 ) * 1.5 ;
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
int prev = ( i + 3 ) % 4 ;
int next = ( i + 1 ) % 4 ;
Vector2 ofs = ( ( endpoints [ i ] - endpoints [ prev ] ) . normalized ( ) + ( ( endpoints [ i ] - endpoints [ next ] ) . normalized ( ) ) ) . normalized ( ) ;
ofs * = ( select_handle - > get_size ( ) . width / 2 ) ;
ofs + = endpoints [ i ] ;
2021-05-05 10:44:11 +00:00
if ( ofs . distance_to ( b - > get_position ( ) ) < radius ) {
2018-03-08 20:35:41 +00:00
resize_drag = dragger [ i * 2 ] ;
2021-05-05 10:44:11 +00:00
}
2018-03-08 20:35:41 +00:00
ofs = ( endpoints [ i ] + endpoints [ next ] ) / 2 ;
ofs + = ( endpoints [ next ] - endpoints [ i ] ) . tangent ( ) . normalized ( ) * ( select_handle - > get_size ( ) . width / 2 ) ;
2021-05-05 10:44:11 +00:00
if ( ofs . distance_to ( b - > get_position ( ) ) < radius ) {
2018-03-08 20:35:41 +00:00
resize_drag = dragger [ i * 2 + 1 ] ;
2021-05-05 10:44:11 +00:00
}
2018-03-08 20:35:41 +00:00
}
2017-03-22 20:18:47 +00:00
2018-03-08 20:35:41 +00:00
if ( resize_drag ! = DRAG_NONE ) {
drag_type = resize_drag ;
drag_from = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
drag_selection = List < CanvasItem * > ( ) ;
drag_selection . push_back ( canvas_item ) ;
_save_canvas_item_state ( drag_selection ) ;
return true ;
}
2017-11-07 07:58:35 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
2017-11-07 07:58:35 +00:00
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_LEFT | | drag_type = = DRAG_RIGHT | | drag_type = = DRAG_TOP | | drag_type = = DRAG_BOTTOM | |
drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_TOP_RIGHT | | drag_type = = DRAG_BOTTOM_LEFT | | drag_type = = DRAG_BOTTOM_RIGHT ) {
// Resize the node
if ( m . is_valid ( ) ) {
CanvasItem * canvas_item = drag_selection [ 0 ] ;
2017-03-05 15:44:50 +00:00
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2017-11-07 07:58:35 +00:00
//Reset state
canvas_item - > _edit_set_state ( se - > undo_state ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
bool uniform = m - > get_shift ( ) ;
bool symmetric = m - > get_alt ( ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
Rect2 local_rect = canvas_item - > _edit_get_rect ( ) ;
float aspect = local_rect . get_size ( ) . y / local_rect . get_size ( ) . x ;
Point2 current_begin = local_rect . get_position ( ) ;
Point2 current_end = local_rect . get_position ( ) + local_rect . get_size ( ) ;
Point2 max_begin = ( symmetric ) ? ( current_begin + current_end - canvas_item - > _edit_get_minimum_size ( ) ) / 2.0 : current_end - canvas_item - > _edit_get_minimum_size ( ) ;
Point2 min_end = ( symmetric ) ? ( current_begin + current_end + canvas_item - > _edit_get_minimum_size ( ) ) / 2.0 : current_begin + canvas_item - > _edit_get_minimum_size ( ) ;
Point2 center = ( current_begin + current_end ) / 2.0 ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2016-06-27 13:47:51 +00:00
2017-11-07 07:58:35 +00:00
Transform2D xform = canvas_item - > get_global_transform_with_canvas ( ) . affine_inverse ( ) ;
2016-06-27 13:47:51 +00:00
2020-01-20 06:49:18 +00:00
Point2 drag_to_snapped_begin ;
Point2 drag_to_snapped_end ;
// last call decides which snapping lines are drawn
if ( drag_type = = DRAG_LEFT | | drag_type = = DRAG_TOP | | drag_type = = DRAG_TOP_LEFT ) {
drag_to_snapped_end = snap_point ( xform . affine_inverse ( ) . xform ( current_end ) + ( drag_to - drag_from ) , SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , canvas_item ) ;
drag_to_snapped_begin = snap_point ( xform . affine_inverse ( ) . xform ( current_begin ) + ( drag_to - drag_from ) , SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , canvas_item ) ;
} else {
drag_to_snapped_begin = snap_point ( xform . affine_inverse ( ) . xform ( current_begin ) + ( drag_to - drag_from ) , SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , canvas_item ) ;
drag_to_snapped_end = snap_point ( xform . affine_inverse ( ) . xform ( current_end ) + ( drag_to - drag_from ) , SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL , 0 , canvas_item ) ;
}
2017-11-07 07:58:35 +00:00
Point2 drag_begin = xform . xform ( drag_to_snapped_begin ) ;
Point2 drag_end = xform . xform ( drag_to_snapped_end ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
// Horizontal resize
if ( drag_type = = DRAG_LEFT | | drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_BOTTOM_LEFT ) {
current_begin . x = MIN ( drag_begin . x , max_begin . x ) ;
} else if ( drag_type = = DRAG_RIGHT | | drag_type = = DRAG_TOP_RIGHT | | drag_type = = DRAG_BOTTOM_RIGHT ) {
current_end . x = MAX ( drag_end . x , min_end . x ) ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
// Vertical resize
if ( drag_type = = DRAG_TOP | | drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_TOP_RIGHT ) {
current_begin . y = MIN ( drag_begin . y , max_begin . y ) ;
} else if ( drag_type = = DRAG_BOTTOM | | drag_type = = DRAG_BOTTOM_LEFT | | drag_type = = DRAG_BOTTOM_RIGHT ) {
current_end . y = MAX ( drag_end . y , min_end . y ) ;
}
2017-08-31 21:27:05 +00:00
2017-11-07 07:58:35 +00:00
// Uniform resize
if ( uniform ) {
if ( drag_type = = DRAG_LEFT | | drag_type = = DRAG_RIGHT ) {
current_end . y = current_begin . y + aspect * ( current_end . x - current_begin . x ) ;
} else if ( drag_type = = DRAG_TOP | | drag_type = = DRAG_BOTTOM ) {
current_end . x = current_begin . x + ( current_end . y - current_begin . y ) / aspect ;
} else {
if ( aspect > = 1.0 ) {
if ( drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_TOP_RIGHT ) {
current_begin . y = current_end . y - aspect * ( current_end . x - current_begin . x ) ;
2017-08-31 21:27:05 +00:00
} else {
2017-11-07 07:58:35 +00:00
current_end . y = current_begin . y + aspect * ( current_end . x - current_begin . x ) ;
}
} else {
if ( drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_BOTTOM_LEFT ) {
current_begin . x = current_end . x - ( current_end . y - current_begin . y ) / aspect ;
} else {
current_end . x = current_begin . x + ( current_end . y - current_begin . y ) / aspect ;
2017-08-31 21:27:05 +00:00
}
}
2017-11-07 07:58:35 +00:00
}
2017-08-31 21:27:05 +00:00
}
2017-11-07 07:58:35 +00:00
// Symmetric resize
if ( symmetric ) {
if ( drag_type = = DRAG_LEFT | | drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_BOTTOM_LEFT ) {
current_end . x = 2.0 * center . x - current_begin . x ;
} else if ( drag_type = = DRAG_RIGHT | | drag_type = = DRAG_TOP_RIGHT | | drag_type = = DRAG_BOTTOM_RIGHT ) {
current_begin . x = 2.0 * center . x - current_end . x ;
}
if ( drag_type = = DRAG_TOP | | drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_TOP_RIGHT ) {
current_end . y = 2.0 * center . y - current_begin . y ;
} else if ( drag_type = = DRAG_BOTTOM | | drag_type = = DRAG_BOTTOM_LEFT | | drag_type = = DRAG_BOTTOM_RIGHT ) {
current_begin . y = 2.0 * center . y - current_end . y ;
}
}
canvas_item - > _edit_set_rect ( Rect2 ( current_begin , current_end - current_begin ) ) ;
return true ;
}
2017-09-07 21:30:54 +00:00
2017-11-07 07:58:35 +00:00
// Confirm resize
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) > = 1 & & b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & ! b - > is_pressed ( ) ) {
const Node2D * node2d = Object : : cast_to < Node2D > ( drag_selection [ 0 ] ) ;
if ( node2d ) {
// Extends from Node2D.
// Node2D doesn't have an actual stored rect size, unlike Controls.
_commit_canvas_item_state (
drag_selection ,
vformat (
TTR ( " Scale Node2D \" %s \" to (%s, %s) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
Math : : stepify ( drag_selection [ 0 ] - > _edit_get_scale ( ) . x , 0.01 ) ,
Math : : stepify ( drag_selection [ 0 ] - > _edit_get_scale ( ) . y , 0.01 ) ) ,
true ) ;
} else {
// Extends from Control.
_commit_canvas_item_state (
drag_selection ,
vformat (
TTR ( " Resize Control \" %s \" to (%d, %d) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
drag_selection [ 0 ] - > _edit_get_rect ( ) . size . x ,
drag_selection [ 0 ] - > _edit_get_rect ( ) . size . y ) ,
true ) ;
}
2019-04-15 03:49:03 +00:00
if ( key_auto_insert_button - > is_pressed ( ) ) {
_insert_animation_keys ( false , false , true , true ) ;
}
2019-09-25 14:56:44 +00:00
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
2017-09-07 21:30:54 +00:00
2017-11-07 07:58:35 +00:00
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
2019-09-25 14:56:44 +00:00
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
}
return false ;
}
2017-09-07 21:30:54 +00:00
2018-09-10 12:39:46 +00:00
bool CanvasItemEditor : : _gui_input_scale ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
// Drag resize handles
if ( drag_type = = DRAG_NONE ) {
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) & & ( ( b - > get_alt ( ) & & b - > get_control ( ) ) | | tool = = TOOL_SCALE ) ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( selection . size ( ) = = 1 ) {
CanvasItem * canvas_item = selection [ 0 ] ;
2018-10-16 18:35:51 +00:00
if ( _is_node_movable ( canvas_item ) ) {
Transform2D xform = transform * canvas_item - > get_global_transform_with_canvas ( ) ;
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( xform * canvas_item - > get_transform ( ) . affine_inverse ( ) * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2018-10-16 18:35:51 +00:00
Transform2D simple_xform = viewport - > get_transform ( ) * unscaled_transform ;
2018-09-20 13:22:35 +00:00
2018-10-16 18:35:51 +00:00
drag_type = DRAG_SCALE_BOTH ;
2018-09-20 13:22:35 +00:00
2018-10-16 18:35:51 +00:00
Size2 scale_factor = Size2 ( SCALE_HANDLE_DISTANCE , SCALE_HANDLE_DISTANCE ) ;
Rect2 x_handle_rect = Rect2 ( scale_factor . x * EDSCALE , - 5 * EDSCALE , 10 * EDSCALE , 10 * EDSCALE ) ;
if ( x_handle_rect . has_point ( simple_xform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ) ) {
drag_type = DRAG_SCALE_X ;
}
Rect2 y_handle_rect = Rect2 ( - 5 * EDSCALE , - ( scale_factor . y + 10 ) * EDSCALE , 10 * EDSCALE , 10 * EDSCALE ) ;
if ( y_handle_rect . has_point ( simple_xform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ) ) {
drag_type = DRAG_SCALE_Y ;
}
drag_from = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
drag_selection = List < CanvasItem * > ( ) ;
drag_selection . push_back ( canvas_item ) ;
_save_canvas_item_state ( drag_selection ) ;
return true ;
}
2018-09-10 12:39:46 +00:00
}
}
}
2018-09-20 13:22:35 +00:00
if ( drag_type = = DRAG_SCALE_BOTH | | drag_type = = DRAG_SCALE_X | | drag_type = = DRAG_SCALE_Y ) {
2018-09-10 12:39:46 +00:00
// Resize the node
if ( m . is_valid ( ) ) {
2018-09-20 20:33:49 +00:00
_restore_canvas_item_state ( drag_selection ) ;
2018-09-10 12:39:46 +00:00
CanvasItem * canvas_item = drag_selection [ 0 ] ;
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2018-09-20 13:22:35 +00:00
Transform2D parent_xform = canvas_item - > get_global_transform_with_canvas ( ) * canvas_item - > get_transform ( ) . affine_inverse ( ) ;
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( transform * parent_xform * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2018-09-20 13:22:35 +00:00
Transform2D simple_xform = ( viewport - > get_transform ( ) * unscaled_transform ) . affine_inverse ( ) * transform ;
2018-09-10 12:39:46 +00:00
bool uniform = m - > get_shift ( ) ;
2019-10-30 14:18:57 +00:00
bool is_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ;
2018-09-20 13:22:35 +00:00
Point2 drag_from_local = simple_xform . xform ( drag_from ) ;
Point2 drag_to_local = simple_xform . xform ( drag_to ) ;
Point2 offset = drag_to_local - drag_from_local ;
2018-09-10 12:39:46 +00:00
Size2 scale = canvas_item - > call ( " get_scale " ) ;
float ratio = scale . y / scale . x ;
2018-09-20 13:22:35 +00:00
if ( drag_type = = DRAG_SCALE_BOTH ) {
Size2 scale_factor = drag_to_local / drag_from_local ;
2018-09-10 12:39:46 +00:00
if ( uniform ) {
2018-11-06 20:51:48 +00:00
scale * = ( scale_factor . x + scale_factor . y ) / 2.0 ;
2018-09-20 13:22:35 +00:00
} else {
scale * = scale_factor ;
2018-09-10 12:39:46 +00:00
}
2018-09-20 13:22:35 +00:00
} else {
Size2 scale_factor = Vector2 ( offset . x , - offset . y ) / SCALE_HANDLE_DISTANCE ;
Size2 parent_scale = parent_xform . get_scale ( ) ;
scale_factor * = Vector2 ( 1.0 / parent_scale . x , 1.0 / parent_scale . y ) ;
if ( drag_type = = DRAG_SCALE_X ) {
scale . x + = scale_factor . x ;
if ( uniform ) {
scale . y = scale . x * ratio ;
}
} else if ( drag_type = = DRAG_SCALE_Y ) {
scale . y + = scale_factor . y ;
if ( uniform ) {
scale . x = scale . y / ratio ;
}
2018-09-10 12:39:46 +00:00
}
}
2019-10-30 14:18:57 +00:00
if ( snap_scale & & ! is_ctrl ) {
scale . x = roundf ( scale . x / snap_scale_step ) * snap_scale_step ;
scale . y = roundf ( scale . y / snap_scale_step ) * snap_scale_step ;
}
2018-09-20 13:22:35 +00:00
canvas_item - > call ( " set_scale " , scale ) ;
return true ;
2018-09-10 12:39:46 +00:00
}
// Confirm resize
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & ! b - > is_pressed ( ) ) {
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) ! = 1 ) {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Scale %d CanvasItems " ) , drag_selection . size ( ) ) ,
true ) ;
} else {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Scale CanvasItem \" %s \" to (%s, %s) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
Math : : stepify ( drag_selection [ 0 ] - > _edit_get_scale ( ) . x , 0.01 ) ,
Math : : stepify ( drag_selection [ 0 ] - > _edit_get_scale ( ) . y , 0.01 ) ) ,
true ) ;
}
2019-04-15 03:49:03 +00:00
if ( key_auto_insert_button - > is_pressed ( ) ) {
_insert_animation_keys ( false , false , true , true ) ;
}
2018-09-10 12:39:46 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection ) ;
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
}
return false ;
}
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_move ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
Ref < InputEventKey > k = p_event ;
2017-07-29 14:57:32 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_NONE ) {
//Start moving the nodes
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) ) {
2018-10-25 17:08:32 +00:00
if ( ( b - > get_alt ( ) & & ! b - > get_control ( ) ) | | tool = = TOOL_MOVE ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
2018-10-16 18:35:51 +00:00
2020-07-19 21:13:08 +00:00
drag_selection . clear ( ) ;
2018-10-25 17:08:32 +00:00
for ( int i = 0 ; i < selection . size ( ) ; i + + ) {
2020-07-19 21:13:08 +00:00
if ( _is_node_movable ( selection [ i ] , true ) ) {
drag_selection . push_back ( selection [ i ] ) ;
2018-10-25 17:08:32 +00:00
}
2018-10-16 18:35:51 +00:00
}
if ( selection . size ( ) > 0 ) {
drag_type = DRAG_MOVE ;
drag_from = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
_save_canvas_item_state ( drag_selection ) ;
}
2017-11-07 07:58:35 +00:00
return true ;
2017-07-29 14:57:32 +00:00
}
2017-11-07 07:58:35 +00:00
}
}
2017-07-29 14:57:32 +00:00
2018-09-09 20:17:47 +00:00
if ( drag_type = = DRAG_MOVE ) {
2017-11-07 07:58:35 +00:00
// Move the nodes
if ( m . is_valid ( ) ) {
2018-09-20 20:33:49 +00:00
// Save the ik chain for reapplying before IK solve
2021-05-04 12:20:36 +00:00
Vector < List < Dictionary > > all_bones_ik_states ;
2018-09-20 20:33:49 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
List < Dictionary > bones_ik_states ;
2021-05-04 14:00:45 +00:00
_save_canvas_item_ik_chain ( E - > get ( ) , nullptr , & bones_ik_states ) ;
2018-09-20 20:33:49 +00:00
all_bones_ik_states . push_back ( bones_ik_states ) ;
}
2017-11-07 07:58:35 +00:00
_restore_canvas_item_state ( drag_selection , true ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
drag_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
Point2 previous_pos ;
2021-08-01 09:55:53 +00:00
if ( ! drag_selection . empty ( ) ) {
if ( drag_selection . size ( ) = = 1 ) {
Transform2D xform = drag_selection [ 0 ] - > get_global_transform_with_canvas ( ) * drag_selection [ 0 ] - > get_transform ( ) . affine_inverse ( ) ;
previous_pos = xform . xform ( drag_selection [ 0 ] - > _edit_get_position ( ) ) ;
} else {
previous_pos = _get_encompassing_rect_from_list ( drag_selection ) . position ;
}
2017-11-07 07:58:35 +00:00
}
2021-05-04 14:00:45 +00:00
Point2 new_pos = snap_point ( previous_pos + ( drag_to - drag_from ) , SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES , 0 , nullptr , drag_selection ) ;
2017-11-07 07:58:35 +00:00
bool single_axis = m - > get_shift ( ) ;
if ( single_axis ) {
if ( ABS ( new_pos . x - previous_pos . x ) > ABS ( new_pos . y - previous_pos . y ) ) {
new_pos . y = previous_pos . y ;
} else {
new_pos . x = previous_pos . x ;
2016-01-05 23:13:07 +00:00
}
}
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
bool force_no_IK = m - > get_alt ( ) ;
2018-09-20 20:33:49 +00:00
int index = 0 ;
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2021-03-07 14:14:24 +00:00
if ( se ) {
Transform2D xform = canvas_item - > get_global_transform_with_canvas ( ) . affine_inverse ( ) * canvas_item - > get_transform ( ) ;
Node2D * node2d = Object : : cast_to < Node2D > ( canvas_item ) ;
if ( node2d & & se - > pre_drag_bones_undo_state . size ( ) > 0 & & ! force_no_IK ) {
real_t initial_leaf_node_rotation = node2d - > get_global_transform_with_canvas ( ) . get_rotation ( ) ;
_restore_canvas_item_ik_chain ( node2d , & ( all_bones_ik_states [ index ] ) ) ;
real_t final_leaf_node_rotation = node2d - > get_global_transform_with_canvas ( ) . get_rotation ( ) ;
node2d - > rotate ( initial_leaf_node_rotation - final_leaf_node_rotation ) ;
_solve_IK ( node2d , new_pos ) ;
} else {
canvas_item - > _edit_set_position ( canvas_item - > _edit_get_position ( ) + xform . xform ( new_pos ) - xform . xform ( previous_pos ) ) ;
}
2017-11-07 07:58:35 +00:00
}
2018-09-20 20:33:49 +00:00
index + + ;
2017-11-07 07:58:35 +00:00
}
return true ;
}
2017-03-22 23:47:51 +00:00
2017-11-07 07:58:35 +00:00
// Confirm the move (only if it was moved)
2019-04-08 09:03:37 +00:00
if ( b . is_valid ( ) & & ! b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT ) {
2017-11-07 07:58:35 +00:00
if ( transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ! = drag_from ) {
2020-09-21 20:49:30 +00:00
if ( drag_selection . size ( ) ! = 1 ) {
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Move %d CanvasItems " ) , drag_selection . size ( ) ) ,
true ) ;
} else {
_commit_canvas_item_state (
drag_selection ,
vformat (
TTR ( " Move CanvasItem \" %s \" to (%d, %d) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
drag_selection [ 0 ] - > _edit_get_position ( ) . x ,
drag_selection [ 0 ] - > _edit_get_position ( ) . y ) ,
true ) ;
}
2014-02-10 01:10:30 +00:00
}
2019-04-15 03:49:03 +00:00
if ( key_auto_insert_button - > is_pressed ( ) ) {
_insert_animation_keys ( true , false , false , true ) ;
}
2019-09-20 20:26:26 +00:00
//Make sure smart snapping lines disappear.
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
// Cancel a drag
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > is_pressed ( ) ) {
_restore_canvas_item_state ( drag_selection , true ) ;
2019-09-20 20:26:26 +00:00
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
}
// Move the canvas items with the arrow keys
2020-02-10 20:39:05 +00:00
if ( k . is_valid ( ) & & k - > is_pressed ( ) & & ( tool = = TOOL_SELECT | | tool = = TOOL_MOVE ) & &
2017-11-07 07:58:35 +00:00
( k - > get_scancode ( ) = = KEY_UP | | k - > get_scancode ( ) = = KEY_DOWN | | k - > get_scancode ( ) = = KEY_LEFT | | k - > get_scancode ( ) = = KEY_RIGHT ) ) {
if ( ! k - > is_echo ( ) ) {
// Start moving the canvas items with the keyboard
drag_selection = _get_edited_canvas_items ( ) ;
drag_type = DRAG_KEY_MOVE ;
drag_from = Vector2 ( ) ;
drag_to = Vector2 ( ) ;
_save_canvas_item_state ( drag_selection , true ) ;
}
2018-03-08 20:35:41 +00:00
if ( drag_selection . size ( ) > 0 ) {
2018-09-20 20:33:49 +00:00
// Save the ik chain for reapplying before IK solve
2021-05-04 12:20:36 +00:00
Vector < List < Dictionary > > all_bones_ik_states ;
2018-09-20 20:33:49 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
List < Dictionary > bones_ik_states ;
2021-05-04 14:00:45 +00:00
_save_canvas_item_ik_chain ( E - > get ( ) , nullptr , & bones_ik_states ) ;
2018-09-20 20:33:49 +00:00
all_bones_ik_states . push_back ( bones_ik_states ) ;
}
2018-03-08 20:35:41 +00:00
_restore_canvas_item_state ( drag_selection , true ) ;
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
bool move_local_base = k - > get_alt ( ) ;
bool move_local_base_rotated = k - > get_control ( ) | | k - > get_metakey ( ) ;
Vector2 dir ;
2021-05-05 10:44:11 +00:00
if ( k - > get_scancode ( ) = = KEY_UP ) {
2018-03-08 20:35:41 +00:00
dir + = Vector2 ( 0 , - 1 ) ;
2021-05-05 10:44:11 +00:00
} else if ( k - > get_scancode ( ) = = KEY_DOWN ) {
2018-03-08 20:35:41 +00:00
dir + = Vector2 ( 0 , 1 ) ;
2021-05-05 10:44:11 +00:00
} else if ( k - > get_scancode ( ) = = KEY_LEFT ) {
2018-03-08 20:35:41 +00:00
dir + = Vector2 ( - 1 , 0 ) ;
2021-05-05 10:44:11 +00:00
} else if ( k - > get_scancode ( ) = = KEY_RIGHT ) {
2018-03-08 20:35:41 +00:00
dir + = Vector2 ( 1 , 0 ) ;
2021-05-05 10:44:11 +00:00
}
if ( k - > get_shift ( ) ) {
2018-03-08 20:35:41 +00:00
dir * = grid_step * Math : : pow ( 2.0 , grid_step_multiplier ) ;
2021-05-05 10:44:11 +00:00
}
2018-03-08 20:35:41 +00:00
drag_to + = dir ;
2021-05-05 10:44:11 +00:00
if ( k - > get_shift ( ) ) {
2018-03-08 20:35:41 +00:00
drag_to = drag_to . snapped ( grid_step * Math : : pow ( 2.0 , grid_step_multiplier ) ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
Point2 previous_pos ;
if ( drag_selection . size ( ) = = 1 ) {
Transform2D xform = drag_selection [ 0 ] - > get_global_transform_with_canvas ( ) * drag_selection [ 0 ] - > get_transform ( ) . affine_inverse ( ) ;
previous_pos = xform . xform ( drag_selection [ 0 ] - > _edit_get_position ( ) ) ;
} else {
previous_pos = _get_encompassing_rect_from_list ( drag_selection ) . position ;
}
2017-11-07 07:58:35 +00:00
2018-03-08 20:35:41 +00:00
Point2 new_pos ;
if ( drag_selection . size ( ) = = 1 ) {
Node2D * node_2d = Object : : cast_to < Node2D > ( drag_selection [ 0 ] ) ;
if ( node_2d & & move_local_base_rotated ) {
2019-02-12 20:10:08 +00:00
Transform2D m2 ;
m2 . rotate ( node_2d - > get_rotation ( ) ) ;
new_pos + = m2 . xform ( drag_to ) ;
2018-03-08 20:35:41 +00:00
} else if ( move_local_base ) {
new_pos + = drag_to ;
} else {
new_pos = previous_pos + ( drag_to - drag_from ) ;
}
2017-11-07 07:58:35 +00:00
} else {
new_pos = previous_pos + ( drag_to - drag_from ) ;
}
2014-07-06 14:49:27 +00:00
2018-09-20 20:33:49 +00:00
int index = 0 ;
2018-03-08 20:35:41 +00:00
for ( List < CanvasItem * > : : Element * E = drag_selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2021-03-07 14:14:24 +00:00
if ( se ) {
Transform2D xform = canvas_item - > get_global_transform_with_canvas ( ) . affine_inverse ( ) * canvas_item - > get_transform ( ) ;
Node2D * node2d = Object : : cast_to < Node2D > ( canvas_item ) ;
if ( node2d & & se - > pre_drag_bones_undo_state . size ( ) > 0 ) {
real_t initial_leaf_node_rotation = node2d - > get_global_transform_with_canvas ( ) . get_rotation ( ) ;
_restore_canvas_item_ik_chain ( node2d , & ( all_bones_ik_states [ index ] ) ) ;
real_t final_leaf_node_rotation = node2d - > get_global_transform_with_canvas ( ) . get_rotation ( ) ;
node2d - > rotate ( initial_leaf_node_rotation - final_leaf_node_rotation ) ;
_solve_IK ( node2d , new_pos ) ;
} else {
canvas_item - > _edit_set_position ( canvas_item - > _edit_get_position ( ) + xform . xform ( new_pos ) - xform . xform ( previous_pos ) ) ;
}
2018-03-08 20:35:41 +00:00
}
2018-09-20 20:33:49 +00:00
index + + ;
2017-11-07 07:58:35 +00:00
}
}
return true ;
}
2020-05-21 12:50:35 +00:00
if ( k . is_valid ( ) & & ! k - > is_pressed ( ) & & drag_type = = DRAG_KEY_MOVE & & ( tool = = TOOL_SELECT | | tool = = TOOL_MOVE ) & &
2017-11-07 07:58:35 +00:00
( k - > get_scancode ( ) = = KEY_UP | | k - > get_scancode ( ) = = KEY_DOWN | | k - > get_scancode ( ) = = KEY_LEFT | | k - > get_scancode ( ) = = KEY_RIGHT ) ) {
// Confirm canvas items move by arrow keys
if ( ( ! Input : : get_singleton ( ) - > is_key_pressed ( KEY_UP ) ) & &
( ! Input : : get_singleton ( ) - > is_key_pressed ( KEY_DOWN ) ) & &
( ! Input : : get_singleton ( ) - > is_key_pressed ( KEY_LEFT ) ) & &
( ! Input : : get_singleton ( ) - > is_key_pressed ( KEY_RIGHT ) ) ) {
2020-12-10 00:47:12 +00:00
if ( drag_selection . size ( ) > 1 ) {
2020-09-21 20:49:30 +00:00
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Move %d CanvasItems " ) , drag_selection . size ( ) ) ,
true ) ;
2020-12-10 00:47:12 +00:00
} else if ( drag_selection . size ( ) = = 1 ) {
2020-09-21 20:49:30 +00:00
_commit_canvas_item_state (
drag_selection ,
vformat ( TTR ( " Move CanvasItem \" %s \" to (%d, %d) " ) ,
drag_selection [ 0 ] - > get_name ( ) ,
drag_selection [ 0 ] - > _edit_get_position ( ) . x ,
drag_selection [ 0 ] - > _edit_get_position ( ) . y ) ,
true ) ;
}
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
}
viewport - > update ( ) ;
return true ;
}
2014-07-06 14:49:27 +00:00
2019-06-26 13:08:25 +00:00
return ( k . is_valid ( ) & & ( k - > get_scancode ( ) = = KEY_UP | | k - > get_scancode ( ) = = KEY_DOWN | | k - > get_scancode ( ) = = KEY_LEFT | | k - > get_scancode ( ) = = KEY_RIGHT ) ) ; // Accept the key event in any case
2017-11-07 07:58:35 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
bool CanvasItemEditor : : _gui_input_select ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
Ref < InputEventKey > k = p_event ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_NONE ) {
if ( b . is_valid ( ) & &
2018-03-07 20:39:55 +00:00
( ( b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > get_alt ( ) & & tool = = TOOL_SELECT ) | |
2017-11-07 07:58:35 +00:00
( b - > get_button_index ( ) = = BUTTON_LEFT & & tool = = TOOL_LIST_SELECT ) ) ) {
// Popup the selection menu list
2018-03-07 20:39:55 +00:00
Point2 click = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
2017-11-07 07:58:35 +00:00
2021-08-18 11:27:33 +00:00
_get_canvas_items_at_pos ( click , selection_results , b - > get_alt ( ) & & tool ! = TOOL_LIST_SELECT ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( selection_results . size ( ) = = 1 ) {
CanvasItem * item = selection_results [ 0 ] . item ;
selection_results . clear ( ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
_select_click_on_item ( item , click , b - > get_shift ( ) ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
return true ;
} else if ( ! selection_results . empty ( ) ) {
2018-03-08 20:35:41 +00:00
// Sorts items according the their z-index
2017-11-07 07:58:35 +00:00
selection_results . sort ( ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
NodePath root_path = get_tree ( ) - > get_edited_scene_root ( ) - > get_path ( ) ;
StringName root_name = root_path . get_name ( root_path . get_name_count ( ) - 1 ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
for ( int i = 0 ; i < selection_results . size ( ) ; i + + ) {
CanvasItem * item = selection_results [ i ] . item ;
2014-07-06 14:49:27 +00:00
2018-09-02 21:40:51 +00:00
Ref < Texture > icon = EditorNode : : get_singleton ( ) - > get_object_icon ( item , " Node " ) ;
2017-11-07 07:58:35 +00:00
String node_path = " / " + root_name + " / " + root_path . rel_path_to ( item - > get_path ( ) ) ;
2014-07-06 14:49:27 +00:00
2021-08-18 11:27:33 +00:00
int locked = 0 ;
if ( _is_node_locked ( item ) ) {
locked = 1 ;
} else {
Node * scene = editor - > get_edited_scene ( ) ;
Node * node = item ;
while ( node & & node ! = scene - > get_parent ( ) ) {
CanvasItem * canvas_item_tmp = Object : : cast_to < CanvasItem > ( node ) ;
if ( canvas_item_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 ) item - > get_name ( ) + suffix ) ;
2017-11-07 07:58:35 +00:00
selection_menu - > set_item_icon ( i , icon ) ;
selection_menu - > set_item_metadata ( i , node_path ) ;
selection_menu - > set_item_tooltip ( i , String ( item - > get_name ( ) ) + " \n Type: " + item - > get_class ( ) + " \n Path: " + node_path ) ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
selection_menu_additive_selection = b - > get_shift ( ) ;
selection_menu - > set_global_position ( b - > get_global_position ( ) ) ;
selection_menu - > popup ( ) ;
return true ;
}
}
2014-07-06 14:49:27 +00:00
2021-07-07 11:19:59 +00:00
if ( b . is_valid ( ) & & b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT & & b - > get_control ( ) ) {
add_node_menu - > set_position ( get_global_transform ( ) . xform ( get_local_mouse_position ( ) ) ) ;
add_node_menu - > set_size ( Vector2 ( 1 , 1 ) ) ;
add_node_menu - > popup ( ) ;
node_create_position = transform . affine_inverse ( ) . xform ( ( get_local_mouse_position ( ) ) ) ;
return true ;
}
2017-11-07 07:58:35 +00:00
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT & & b - > is_pressed ( ) & & tool = = TOOL_SELECT ) {
// Single item selection
Point2 click = transform . affine_inverse ( ) . xform ( b - > get_position ( ) ) ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
Node * scene = editor - > get_edited_scene ( ) ;
2021-05-05 10:44:11 +00:00
if ( ! scene ) {
2017-11-07 07:58:35 +00:00
return true ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
// Find the item to select
2021-05-04 14:00:45 +00:00
CanvasItem * canvas_item = nullptr ;
2018-03-04 13:05:58 +00:00
2018-05-15 13:18:46 +00:00
// Retrieve the bones
2019-01-09 19:55:04 +00:00
Vector < _SelectResult > selection = Vector < _SelectResult > ( ) ;
2018-05-15 13:18:46 +00:00
_get_bones_at_pos ( click , selection ) ;
2018-09-11 18:58:01 +00:00
if ( ! selection . empty ( ) ) {
2017-11-07 07:58:35 +00:00
canvas_item = selection [ 0 ] . item ;
2019-01-09 19:55:04 +00:00
} else {
// Retrieve the canvas items
selection = Vector < _SelectResult > ( ) ;
_get_canvas_items_at_pos ( click , selection ) ;
if ( ! selection . empty ( ) ) {
canvas_item = selection [ 0 ] . item ;
}
2018-09-11 18:58:01 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( ! canvas_item ) {
// Start a box selection
if ( ! b - > get_shift ( ) ) {
// Clear the selection if not additive
editor_selection - > clear ( ) ;
viewport - > update ( ) ;
2019-11-27 20:07:35 +00:00
selected_from_canvas = true ;
2017-11-07 07:58:35 +00:00
} ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
drag_from = click ;
drag_type = DRAG_BOX_SELECTION ;
box_selecting_to = drag_from ;
return true ;
} else {
bool still_selected = _select_click_on_item ( canvas_item , click , b - > get_shift ( ) ) ;
// Start dragging
if ( still_selected ) {
// Drag the node(s) if requested
2021-07-16 04:03:09 +00:00
drag_start_origin = click ;
drag_type = DRAG_QUEUED ;
}
// Select the item
return true ;
}
}
}
2017-11-07 07:58:35 +00:00
2021-07-16 04:03:09 +00:00
if ( drag_type = = DRAG_QUEUED ) {
if ( b . is_valid ( ) & & ! b - > is_pressed ( ) ) {
drag_type = DRAG_NONE ;
return true ;
}
if ( m . is_valid ( ) ) {
Point2 click = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
// Scale movement threshold with zoom (which itself is set relative to the editor scale).
bool movement_threshold_passed = drag_start_origin . distance_to ( click ) > ( 8 * MAX ( 1 , EDSCALE ) ) / zoom ;
if ( m . is_valid ( ) & & movement_threshold_passed ) {
List < CanvasItem * > selection2 = _get_edited_canvas_items ( ) ;
2018-10-16 18:35:51 +00:00
2021-07-16 04:03:09 +00:00
drag_selection . clear ( ) ;
for ( int i = 0 ; i < selection2 . size ( ) ; i + + ) {
if ( _is_node_movable ( selection2 [ i ] , true ) ) {
drag_selection . push_back ( selection2 [ i ] ) ;
2018-10-16 18:35:51 +00:00
}
2017-11-07 07:58:35 +00:00
}
2021-07-16 04:03:09 +00:00
if ( selection2 . size ( ) > 0 ) {
drag_type = DRAG_MOVE ;
drag_from = click ;
_save_canvas_item_state ( drag_selection ) ;
}
2017-11-07 07:58:35 +00:00
return true ;
}
}
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_BOX_SELECTION ) {
if ( b . is_valid ( ) & & ! b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT ) {
// Confirms box selection
Node * scene = editor - > get_edited_scene ( ) ;
if ( scene ) {
List < CanvasItem * > selitems ;
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
Point2 bsfrom = drag_from ;
Point2 bsto = box_selecting_to ;
2021-05-05 10:44:11 +00:00
if ( bsfrom . x > bsto . x ) {
2017-11-07 07:58:35 +00:00
SWAP ( bsfrom . x , bsto . x ) ;
2021-05-05 10:44:11 +00:00
}
if ( bsfrom . y > bsto . y ) {
2017-11-07 07:58:35 +00:00
SWAP ( bsfrom . y , bsto . y ) ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2018-03-08 20:35:41 +00:00
_find_canvas_items_in_rect ( Rect2 ( bsfrom , bsto - bsfrom ) , scene , & selitems ) ;
2021-04-13 10:09:53 +00:00
if ( selitems . size ( ) = = 1 & & editor_selection - > get_selected_node_list ( ) . empty ( ) ) {
editor - > push_item ( selitems [ 0 ] ) ;
}
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = selitems . front ( ) ; E ; E = E - > next ( ) ) {
editor_selection - > add_node ( E - > get ( ) ) ;
2014-07-06 14:49:27 +00:00
}
2017-11-07 07:58:35 +00:00
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( b . is_valid ( ) & & b - > is_pressed ( ) & & b - > get_button_index ( ) = = BUTTON_RIGHT ) {
// Cancel box selection
drag_type = DRAG_NONE ;
viewport - > update ( ) ;
return true ;
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( m . is_valid ( ) ) {
// Update box selection
box_selecting_to = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
viewport - > update ( ) ;
return true ;
}
}
2014-07-06 14:49:27 +00:00
2017-11-07 07:58:35 +00:00
if ( k . is_valid ( ) & & k - > is_pressed ( ) & & k - > get_scancode ( ) = = KEY_ESCAPE & & drag_type = = DRAG_NONE & & tool = = TOOL_SELECT ) {
// Unselect everything
editor_selection - > clear ( ) ;
viewport - > update ( ) ;
}
return false ;
}
2014-07-06 14:49:27 +00:00
2019-08-30 20:49:47 +00:00
bool CanvasItemEditor : : _gui_input_ruler_tool ( const Ref < InputEvent > & p_event ) {
2020-03-15 09:35:53 +00:00
if ( tool ! = TOOL_RULER ) {
ruler_tool_active = false ;
2019-08-30 20:49:47 +00:00
return false ;
2020-03-15 09:35:53 +00:00
}
2019-08-30 20:49:47 +00:00
Ref < InputEventMouseButton > b = p_event ;
Ref < InputEventMouseMotion > m = p_event ;
Point2 previous_origin = ruler_tool_origin ;
2021-05-05 10:44:11 +00:00
if ( ! ruler_tool_active ) {
2019-10-24 19:19:11 +00:00
ruler_tool_origin = snap_point ( viewport - > get_local_mouse_position ( ) / zoom + view_offset ) ;
2021-05-05 10:44:11 +00:00
}
2019-08-30 20:49:47 +00:00
if ( b . is_valid ( ) & & b - > get_button_index ( ) = = BUTTON_LEFT ) {
if ( b - > is_pressed ( ) ) {
ruler_tool_active = true ;
} else {
ruler_tool_active = false ;
}
viewport - > update ( ) ;
return true ;
}
2019-10-24 20:31:19 +00:00
if ( m . is_valid ( ) & & ( ruler_tool_active | | ( grid_snap_active & & previous_origin ! = ruler_tool_origin ) ) ) {
2019-08-30 20:49:47 +00:00
viewport - > update ( ) ;
return true ;
}
return false ;
}
2018-03-12 22:32:25 +00:00
bool CanvasItemEditor : : _gui_input_hover ( const Ref < InputEvent > & p_event ) {
Ref < InputEventMouseMotion > m = p_event ;
if ( m . is_valid ( ) ) {
2018-06-12 09:01:24 +00:00
Point2 click = transform . affine_inverse ( ) . xform ( m - > get_position ( ) ) ;
2018-03-12 22:32:25 +00:00
2018-06-12 09:01:24 +00:00
// Checks if the hovered items changed, update the viewport if so
Vector < _SelectResult > hovering_results_items ;
_get_canvas_items_at_pos ( click , hovering_results_items ) ;
hovering_results_items . sort ( ) ;
// Compute the nodes names and icon position
Vector < _HoverResult > hovering_results_tmp ;
for ( int i = 0 ; i < hovering_results_items . size ( ) ; i + + ) {
CanvasItem * canvas_item = hovering_results_items [ i ] . item ;
2021-05-05 10:44:11 +00:00
if ( canvas_item - > _edit_use_rect ( ) ) {
2018-06-12 09:01:24 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2018-06-12 09:01:24 +00:00
_HoverResult hover_result ;
hover_result . position = canvas_item - > get_global_transform_with_canvas ( ) . get_origin ( ) ;
2018-09-02 21:40:51 +00:00
hover_result . icon = EditorNode : : get_singleton ( ) - > get_object_icon ( canvas_item ) ;
2018-06-12 09:01:24 +00:00
hover_result . name = canvas_item - > get_name ( ) ;
hovering_results_tmp . push_back ( hover_result ) ;
}
// Check if changed, if so, update.
bool changed = false ;
if ( hovering_results_tmp . size ( ) = = hovering_results . size ( ) ) {
for ( int i = 0 ; i < hovering_results_tmp . size ( ) ; i + + ) {
_HoverResult a = hovering_results_tmp [ i ] ;
_HoverResult b = hovering_results [ i ] ;
if ( a . icon ! = b . icon | | a . name ! = b . name | | a . position ! = b . position ) {
changed = true ;
break ;
}
2018-03-12 22:32:25 +00:00
}
2018-06-12 09:01:24 +00:00
} else {
changed = true ;
}
2018-03-12 22:32:25 +00:00
2018-06-12 09:01:24 +00:00
if ( changed ) {
hovering_results = hovering_results_tmp ;
viewport - > update ( ) ;
2018-03-12 22:32:25 +00:00
}
2018-06-12 09:01:24 +00:00
return true ;
2018-03-12 22:32:25 +00:00
}
return false ;
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _gui_input_viewport ( const Ref < InputEvent > & p_event ) {
bool accepted = false ;
2019-03-31 16:53:24 +00:00
2019-06-05 20:35:07 +00:00
if ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/simple_panning " ) | | ! pan_pressed ) {
2019-04-07 14:43:21 +00:00
if ( ( accepted = _gui_input_rulers_and_guides ( p_event ) ) ) {
//printf("Rulers and guides\n");
} else if ( ( accepted = editor - > get_editor_plugins_over ( ) - > forward_gui_input ( p_event ) ) ) {
//printf("Plugin\n");
} else if ( ( accepted = _gui_input_open_scene_on_double_click ( p_event ) ) ) {
//printf("Open scene on double click\n");
} else if ( ( accepted = _gui_input_scale ( p_event ) ) ) {
//printf("Set scale\n");
} else if ( ( accepted = _gui_input_pivot ( p_event ) ) ) {
//printf("Set pivot\n");
} else if ( ( accepted = _gui_input_resize ( p_event ) ) ) {
//printf("Resize\n");
} else if ( ( accepted = _gui_input_rotate ( p_event ) ) ) {
//printf("Rotate\n");
} else if ( ( accepted = _gui_input_move ( p_event ) ) ) {
//printf("Move\n");
2019-07-16 18:33:40 +00:00
} else if ( ( accepted = _gui_input_anchors ( p_event ) ) ) {
//printf("Anchors\n");
2019-04-07 14:43:21 +00:00
} else if ( ( accepted = _gui_input_select ( p_event ) ) ) {
//printf("Selection\n");
2019-08-30 20:49:47 +00:00
} else if ( ( accepted = _gui_input_ruler_tool ( p_event ) ) ) {
//printf("Measure\n");
2019-04-07 14:43:21 +00:00
} else {
//printf("Not accepted\n");
}
2017-11-07 07:58:35 +00:00
}
2019-07-28 14:00:05 +00:00
accepted = ( _gui_input_zoom_or_pan ( p_event , accepted ) | | accepted ) ;
2019-04-07 14:43:21 +00:00
2021-05-05 10:44:11 +00:00
if ( accepted ) {
2017-11-07 07:58:35 +00:00
accept_event ( ) ;
2021-05-05 10:44:11 +00:00
}
2017-11-07 07:58:35 +00:00
2018-03-12 22:32:25 +00:00
// Handles the mouse hovering
_gui_input_hover ( p_event ) ;
2020-10-01 10:19:45 +00:00
// Compute an eventual rotation of the cursor
CursorShape rotation_array [ 4 ] = { CURSOR_HSIZE , CURSOR_BDIAGSIZE , CURSOR_VSIZE , CURSOR_FDIAGSIZE } ;
int rotation_array_index = 0 ;
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( selection . size ( ) = = 1 ) {
float angle = Math : : fposmod ( ( double ) selection [ 0 ] - > get_global_transform_with_canvas ( ) . get_rotation ( ) , Math_PI ) ;
if ( angle > Math_PI * 7.0 / 8.0 ) {
rotation_array_index = 0 ;
} else if ( angle > Math_PI * 5.0 / 8.0 ) {
rotation_array_index = 1 ;
} else if ( angle > Math_PI * 3.0 / 8.0 ) {
rotation_array_index = 2 ;
} else if ( angle > Math_PI * 1.0 / 8.0 ) {
rotation_array_index = 3 ;
} else {
rotation_array_index = 0 ;
}
2020-08-06 16:56:56 +00:00
}
2020-10-01 10:19:45 +00:00
// Choose the correct cursor
CursorShape c = CURSOR_ARROW ;
2017-11-07 07:58:35 +00:00
switch ( drag_type ) {
case DRAG_NONE :
2018-04-22 21:27:46 +00:00
switch ( tool ) {
case TOOL_MOVE :
c = CURSOR_MOVE ;
break ;
case TOOL_EDIT_PIVOT :
c = CURSOR_CROSS ;
break ;
case TOOL_PAN :
c = CURSOR_DRAG ;
break ;
2019-08-30 20:49:47 +00:00
case TOOL_RULER :
c = CURSOR_CROSS ;
break ;
2018-04-22 21:27:46 +00:00
default :
break ;
2014-07-06 14:49:27 +00:00
}
2017-11-07 07:58:35 +00:00
break ;
case DRAG_LEFT :
case DRAG_RIGHT :
2020-10-01 10:19:45 +00:00
c = rotation_array [ rotation_array_index ] ;
break ;
2019-07-13 15:16:32 +00:00
case DRAG_V_GUIDE :
2020-10-01 10:19:45 +00:00
c = CURSOR_HSIZE ;
2017-11-07 07:58:35 +00:00
break ;
case DRAG_TOP :
case DRAG_BOTTOM :
2020-10-01 10:19:45 +00:00
c = rotation_array [ ( rotation_array_index + 2 ) % 4 ] ;
break ;
2019-07-13 15:16:32 +00:00
case DRAG_H_GUIDE :
2020-10-01 10:19:45 +00:00
c = CURSOR_VSIZE ;
2017-11-07 07:58:35 +00:00
break ;
case DRAG_TOP_LEFT :
case DRAG_BOTTOM_RIGHT :
2020-10-01 10:19:45 +00:00
c = rotation_array [ ( rotation_array_index + 3 ) % 4 ] ;
break ;
2019-07-13 15:16:32 +00:00
case DRAG_DOUBLE_GUIDE :
2020-10-01 10:19:45 +00:00
c = CURSOR_FDIAGSIZE ;
2017-11-07 07:58:35 +00:00
break ;
case DRAG_TOP_RIGHT :
case DRAG_BOTTOM_LEFT :
2020-10-01 10:19:45 +00:00
c = rotation_array [ ( rotation_array_index + 1 ) % 4 ] ;
2017-11-07 07:58:35 +00:00
break ;
2018-09-09 20:17:47 +00:00
case DRAG_MOVE :
2017-11-07 07:58:35 +00:00
c = CURSOR_MOVE ;
break ;
default :
break ;
}
2019-07-13 15:16:32 +00:00
2021-05-05 10:44:11 +00:00
if ( is_hovering_h_guide ) {
2019-07-13 15:16:32 +00:00
c = CURSOR_VSIZE ;
2021-05-05 10:44:11 +00:00
} else if ( is_hovering_v_guide ) {
2019-07-13 15:16:32 +00:00
c = CURSOR_HSIZE ;
2021-05-05 10:44:11 +00:00
}
2019-07-13 15:16:32 +00:00
2017-11-07 07:58:35 +00:00
viewport - > set_default_cursor_shape ( c ) ;
// Grab focus
if ( ! viewport - > has_focus ( ) & & ( ! get_focus_owner ( ) | | ! get_focus_owner ( ) - > is_text_field ( ) ) ) {
viewport - > call_deferred ( " grab_focus " ) ;
2014-02-10 01:10:30 +00:00
}
}
2017-08-17 22:42:49 +00:00
void CanvasItemEditor : : _draw_text_at_position ( Point2 p_position , String p_string , Margin p_side ) {
2017-09-21 00:29:52 +00:00
Color color = get_color ( " font_color " , " Editor " ) ;
color . a = 0.8 ;
2017-08-17 22:42:49 +00:00
Ref < Font > font = get_font ( " font " , " Label " ) ;
Size2 text_size = font - > get_string_size ( p_string ) ;
switch ( p_side ) {
case MARGIN_LEFT :
p_position + = Vector2 ( - text_size . x - 5 , text_size . y / 2 ) ;
break ;
case MARGIN_TOP :
p_position + = Vector2 ( - text_size . x / 2 , - 5 ) ;
break ;
case MARGIN_RIGHT :
p_position + = Vector2 ( 5 , text_size . y / 2 ) ;
break ;
case MARGIN_BOTTOM :
p_position + = Vector2 ( - text_size . x / 2 , text_size . y + 5 ) ;
break ;
}
viewport - > draw_string ( font , p_position , p_string , color ) ;
}
void CanvasItemEditor : : _draw_margin_at_position ( int p_value , Point2 p_position , Margin p_side ) {
String str = vformat ( " %d px " , p_value ) ;
if ( p_value ! = 0 ) {
_draw_text_at_position ( p_position , str , p_side ) ;
}
}
2017-08-02 16:33:06 +00:00
void CanvasItemEditor : : _draw_percentage_at_position ( float p_value , Point2 p_position , Margin p_side ) {
2017-08-17 22:42:49 +00:00
String str = vformat ( " %.1f %% " , p_value * 100.0 ) ;
2017-08-02 16:33:06 +00:00
if ( p_value ! = 0 ) {
2017-08-17 22:42:49 +00:00
_draw_text_at_position ( p_position , str , p_side ) ;
2017-08-02 16:33:06 +00:00
}
}
2017-10-18 21:55:02 +00:00
void CanvasItemEditor : : _draw_focus ( ) {
// Draw the focus around the base viewport
2017-11-07 07:58:35 +00:00
if ( viewport - > has_focus ( ) ) {
get_stylebox ( " Focus " , " EditorStyles " ) - > draw ( viewport - > get_canvas_item ( ) , Rect2 ( Point2 ( ) , viewport - > get_size ( ) ) ) ;
2017-10-18 21:55:02 +00:00
}
}
void CanvasItemEditor : : _draw_guides ( ) {
2017-12-05 20:42:33 +00:00
Color guide_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/guides_color " ) ;
2017-10-18 21:55:02 +00:00
Transform2D xform = viewport_scrollable - > get_transform ( ) * transform ;
// Guides already there
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_vertical_guides_ " ) ) {
Array vguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_vertical_guides_ " ) ;
for ( int i = 0 ; i < vguides . size ( ) ; i + + ) {
2021-05-05 10:44:11 +00:00
if ( drag_type = = DRAG_V_GUIDE & & i = = dragged_guide_index ) {
2017-10-18 21:55:02 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2017-10-18 21:55:02 +00:00
float x = xform . xform ( Point2 ( vguides [ i ] , 0 ) ) . x ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( x , 0 ) , Point2 ( x , viewport - > get_size ( ) . y ) , guide_color , Math : : round ( EDSCALE ) ) ;
2017-10-18 21:55:02 +00:00
}
}
if ( EditorNode : : get_singleton ( ) - > get_edited_scene ( ) & & EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > has_meta ( " _edit_horizontal_guides_ " ) ) {
Array hguides = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) - > get_meta ( " _edit_horizontal_guides_ " ) ;
for ( int i = 0 ; i < hguides . size ( ) ; i + + ) {
2021-05-05 10:44:11 +00:00
if ( drag_type = = DRAG_H_GUIDE & & i = = dragged_guide_index ) {
2017-10-18 21:55:02 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2017-10-18 21:55:02 +00:00
float y = xform . xform ( Point2 ( 0 , hguides [ i ] ) ) . y ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( 0 , y ) , Point2 ( viewport - > get_size ( ) . x , y ) , guide_color , Math : : round ( EDSCALE ) ) ;
2017-10-18 21:55:02 +00:00
}
}
// Dragged guide
Color text_color = get_color ( " font_color " , " Editor " ) ;
text_color . a = 0.5 ;
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_DOUBLE_GUIDE | | drag_type = = DRAG_V_GUIDE ) {
2020-01-24 15:33:01 +00:00
String str = vformat ( " %d px " , Math : : round ( xform . affine_inverse ( ) . xform ( dragged_guide_pos ) . x ) ) ;
2017-10-18 21:55:02 +00:00
Ref < Font > font = get_font ( " font " , " Label " ) ;
Size2 text_size = font - > get_string_size ( str ) ;
2017-11-07 07:58:35 +00:00
viewport - > draw_string ( font , Point2 ( dragged_guide_pos . x + 10 , RULER_WIDTH + text_size . y / 2 + 10 ) , str , text_color ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( dragged_guide_pos . x , 0 ) , Point2 ( dragged_guide_pos . x , viewport - > get_size ( ) . y ) , guide_color , Math : : round ( EDSCALE ) ) ;
2017-10-18 21:55:02 +00:00
}
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_DOUBLE_GUIDE | | drag_type = = DRAG_H_GUIDE ) {
2020-01-24 15:33:01 +00:00
String str = vformat ( " %d px " , Math : : round ( xform . affine_inverse ( ) . xform ( dragged_guide_pos ) . y ) ) ;
2017-10-18 21:55:02 +00:00
Ref < Font > font = get_font ( " font " , " Label " ) ;
Size2 text_size = font - > get_string_size ( str ) ;
2017-11-07 07:58:35 +00:00
viewport - > draw_string ( font , Point2 ( RULER_WIDTH + 10 , dragged_guide_pos . y + text_size . y / 2 + 10 ) , str , text_color ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( 0 , dragged_guide_pos . y ) , Point2 ( viewport - > get_size ( ) . x , dragged_guide_pos . y ) , guide_color , Math : : round ( EDSCALE ) ) ;
2017-10-18 21:55:02 +00:00
}
}
2019-04-05 08:18:21 +00:00
void CanvasItemEditor : : _draw_smart_snapping ( ) {
Color line_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/smart_snapping_line_color " ) ;
if ( snap_target [ 0 ] ! = SNAP_TARGET_NONE & & snap_target [ 0 ] ! = SNAP_TARGET_GRID ) {
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) * transform * snap_transform ) ;
viewport - > draw_line ( Point2 ( 0 , - 1.0e+10 F ) , Point2 ( 0 , 1.0e+10 F ) , line_color ) ;
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
}
if ( snap_target [ 1 ] ! = SNAP_TARGET_NONE & & snap_target [ 1 ] ! = SNAP_TARGET_GRID ) {
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) * transform * snap_transform ) ;
viewport - > draw_line ( Point2 ( - 1.0e+10 F , 0 ) , Point2 ( 1.0e+10 F , 0 ) , line_color ) ;
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
}
}
2017-08-29 19:50:18 +00:00
void CanvasItemEditor : : _draw_rulers ( ) {
Color bg_color = get_color ( " dark_color_2 " , " Editor " ) ;
2017-11-07 07:58:35 +00:00
Color graduation_color = get_color ( " font_color " , " Editor " ) . linear_interpolate ( bg_color , 0.5 ) ;
2017-09-21 00:29:52 +00:00
Color font_color = get_color ( " font_color " , " Editor " ) ;
font_color . a = 0.8 ;
2017-08-29 19:50:18 +00:00
Ref < Font > font = get_font ( " rulers " , " EditorFonts " ) ;
// The rule transform
2017-11-07 07:58:35 +00:00
Transform2D ruler_transform = Transform2D ( ) ;
2019-10-10 17:41:45 +00:00
if ( show_grid | | grid_snap_active ) {
2017-11-07 07:58:35 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
if ( snap_relative & & selection . size ( ) > 0 ) {
ruler_transform . translate ( _get_encompassing_rect_from_list ( selection ) . position ) ;
2017-08-31 19:54:42 +00:00
ruler_transform . scale_basis ( grid_step * Math : : pow ( 2.0 , grid_step_multiplier ) ) ;
2017-08-29 19:50:18 +00:00
} else {
ruler_transform . translate ( grid_offset ) ;
2017-08-31 19:54:42 +00:00
ruler_transform . scale_basis ( grid_step * Math : : pow ( 2.0 , grid_step_multiplier ) ) ;
2017-08-29 19:50:18 +00:00
}
while ( ( transform * ruler_transform ) . get_scale ( ) . x < 50 | | ( transform * ruler_transform ) . get_scale ( ) . y < 50 ) {
ruler_transform . scale_basis ( Point2 ( 2 , 2 ) ) ;
}
} else {
float basic_rule = 100 ;
for ( int i = 0 ; basic_rule * zoom > 100 ; i + + ) {
basic_rule / = ( i % 2 ) ? 5.0 : 2.0 ;
}
for ( int i = 0 ; basic_rule * zoom < 100 ; i + + ) {
basic_rule * = ( i % 2 ) ? 2.0 : 5.0 ;
}
ruler_transform . scale ( Size2 ( basic_rule , basic_rule ) ) ;
}
// Subdivisions
int major_subdivision = 2 ;
Transform2D major_subdivide = Transform2D ( ) ;
major_subdivide . scale ( Size2 ( 1.0 / major_subdivision , 1.0 / major_subdivision ) ) ;
int minor_subdivision = 5 ;
Transform2D minor_subdivide = Transform2D ( ) ;
minor_subdivide . scale ( Size2 ( 1.0 / minor_subdivision , 1.0 / minor_subdivision ) ) ;
// First and last graduations to draw (in the ruler space)
2017-11-07 07:58:35 +00:00
Point2 first = ( transform * ruler_transform * major_subdivide * minor_subdivide ) . affine_inverse ( ) . xform ( Point2 ( RULER_WIDTH , RULER_WIDTH ) ) ;
2017-08-29 19:50:18 +00:00
Point2 last = ( transform * ruler_transform * major_subdivide * minor_subdivide ) . affine_inverse ( ) . xform ( viewport - > get_size ( ) ) ;
// Draw top ruler
2017-11-07 07:58:35 +00:00
viewport - > draw_rect ( Rect2 ( Point2 ( RULER_WIDTH , 0 ) , Size2 ( viewport - > get_size ( ) . x , RULER_WIDTH ) ) , bg_color ) ;
2017-08-29 19:50:18 +00:00
for ( int i = Math : : ceil ( first . x ) ; i < last . x ; i + + ) {
Point2 position = ( transform * ruler_transform * major_subdivide * minor_subdivide ) . xform ( Point2 ( i , 0 ) ) ;
if ( i % ( major_subdivision * minor_subdivision ) = = 0 ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( position . x , 0 ) , Point2 ( position . x , RULER_WIDTH ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
float val = ( ruler_transform * major_subdivide * minor_subdivide ) . xform ( Point2 ( i , 0 ) ) . x ;
2017-11-07 07:58:35 +00:00
viewport - > draw_string ( font , Point2 ( position . x + 2 , font - > get_height ( ) ) , vformat ( ( ( int ) val = = val ) ? " %d " : " %.1f " , val ) , font_color ) ;
2017-08-29 19:50:18 +00:00
} else {
if ( i % minor_subdivision = = 0 ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( position . x , RULER_WIDTH * 0.33 ) , Point2 ( position . x , RULER_WIDTH ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
} else {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( position . x , RULER_WIDTH * 0.75 ) , Point2 ( position . x , RULER_WIDTH ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
}
}
}
// Draw left ruler
2017-11-07 07:58:35 +00:00
viewport - > draw_rect ( Rect2 ( Point2 ( 0 , RULER_WIDTH ) , Size2 ( RULER_WIDTH , viewport - > get_size ( ) . y ) ) , bg_color ) ;
2017-08-29 19:50:18 +00:00
for ( int i = Math : : ceil ( first . y ) ; i < last . y ; i + + ) {
Point2 position = ( transform * ruler_transform * major_subdivide * minor_subdivide ) . xform ( Point2 ( 0 , i ) ) ;
if ( i % ( major_subdivision * minor_subdivision ) = = 0 ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( 0 , position . y ) , Point2 ( RULER_WIDTH , position . y ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
float val = ( ruler_transform * major_subdivide * minor_subdivide ) . xform ( Point2 ( 0 , i ) ) . y ;
2018-09-27 14:50:40 +00:00
Transform2D text_xform = Transform2D ( - Math_PI / 2.0 , Point2 ( font - > get_height ( ) , position . y - 2 ) ) ;
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) * text_xform ) ;
viewport - > draw_string ( font , Point2 ( ) , vformat ( ( ( int ) val = = val ) ? " %d " : " %.1f " , val ) , font_color ) ;
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
2017-08-29 19:50:18 +00:00
} else {
if ( i % minor_subdivision = = 0 ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( RULER_WIDTH * 0.33 , position . y ) , Point2 ( RULER_WIDTH , position . y ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
} else {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( Point2 ( RULER_WIDTH * 0.75 , position . y ) , Point2 ( RULER_WIDTH , position . y ) , graduation_color , Math : : round ( EDSCALE ) ) ;
2017-08-29 19:50:18 +00:00
}
}
}
2019-04-05 08:18:21 +00:00
// Draw the top left corner
2017-11-07 07:58:35 +00:00
viewport - > draw_rect ( Rect2 ( Point2 ( ) , Size2 ( RULER_WIDTH , RULER_WIDTH ) ) , graduation_color ) ;
2017-08-29 19:50:18 +00:00
}
2017-08-28 19:51:56 +00:00
void CanvasItemEditor : : _draw_grid ( ) {
2019-10-15 08:23:38 +00:00
if ( show_grid | | grid_snap_active ) {
// Draw the grid
2017-08-29 19:50:18 +00:00
Vector2 real_grid_offset ;
2019-10-15 08:23:38 +00:00
const List < CanvasItem * > selection = _get_edited_canvas_items ( ) ;
2017-11-07 07:58:35 +00:00
if ( snap_relative & & selection . size ( ) > 0 ) {
2019-10-15 08:23:38 +00:00
const Vector2 topleft = _get_encompassing_rect_from_list ( selection ) . position ;
2017-10-19 16:41:36 +00:00
real_grid_offset . x = fmod ( topleft . x , grid_step . x * ( real_t ) Math : : pow ( 2.0 , grid_step_multiplier ) ) ;
real_grid_offset . y = fmod ( topleft . y , grid_step . y * ( real_t ) Math : : pow ( 2.0 , grid_step_multiplier ) ) ;
2017-07-25 19:09:32 +00:00
} else {
2017-08-29 19:50:18 +00:00
real_grid_offset = grid_offset ;
2017-07-25 19:09:32 +00:00
}
2019-10-15 08:23:38 +00:00
// Draw a "primary" line every several lines to make measurements easier.
// The step is configurable in the Configure Snap dialog.
const Color secondary_grid_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/grid_color " ) ;
const Color primary_grid_color =
Color ( secondary_grid_color . r , secondary_grid_color . g , secondary_grid_color . b , secondary_grid_color . a * 2.5 ) ;
const Size2 viewport_size = viewport - > get_size ( ) ;
const Transform2D xform = transform . affine_inverse ( ) ;
int last_cell = 0 ;
2017-08-29 19:50:18 +00:00
if ( grid_step . x ! = 0 ) {
2019-10-15 08:23:38 +00:00
for ( int i = 0 ; i < viewport_size . width ; i + + ) {
const int cell =
Math : : fast_ftoi ( Math : : floor ( ( xform . xform ( Vector2 ( i , 0 ) ) . x - real_grid_offset . x ) / ( grid_step . x * Math : : pow ( 2.0 , grid_step_multiplier ) ) ) ) ;
if ( i = = 0 ) {
2017-03-05 15:44:50 +00:00
last_cell = cell ;
2019-10-15 08:23:38 +00:00
}
if ( last_cell ! = cell ) {
Color grid_color ;
if ( primary_grid_steps = = 0 ) {
grid_color = secondary_grid_color ;
} else {
grid_color = cell % primary_grid_steps = = 0 ? primary_grid_color : secondary_grid_color ;
}
viewport - > draw_line ( Point2 ( i , 0 ) , Point2 ( i , viewport_size . height ) , grid_color , Math : : round ( EDSCALE ) ) ;
}
2017-03-05 15:44:50 +00:00
last_cell = cell ;
2015-02-15 08:00:55 +00:00
}
2014-02-10 01:10:30 +00:00
}
2017-08-29 19:50:18 +00:00
if ( grid_step . y ! = 0 ) {
2019-10-15 08:23:38 +00:00
for ( int i = 0 ; i < viewport_size . height ; i + + ) {
const int cell =
Math : : fast_ftoi ( Math : : floor ( ( xform . xform ( Vector2 ( 0 , i ) ) . y - real_grid_offset . y ) / ( grid_step . y * Math : : pow ( 2.0 , grid_step_multiplier ) ) ) ) ;
if ( i = = 0 ) {
2017-03-05 15:44:50 +00:00
last_cell = cell ;
2019-10-15 08:23:38 +00:00
}
if ( last_cell ! = cell ) {
Color grid_color ;
if ( primary_grid_steps = = 0 ) {
grid_color = secondary_grid_color ;
} else {
grid_color = cell % primary_grid_steps = = 0 ? primary_grid_color : secondary_grid_color ;
}
viewport - > draw_line ( Point2 ( 0 , i ) , Point2 ( viewport_size . width , i ) , grid_color , Math : : round ( EDSCALE ) ) ;
}
2017-03-05 15:44:50 +00:00
last_cell = cell ;
2015-02-15 08:00:55 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
2017-08-28 19:51:56 +00:00
}
2014-02-10 01:10:30 +00:00
2019-08-30 20:49:47 +00:00
void CanvasItemEditor : : _draw_ruler_tool ( ) {
2021-05-05 10:44:11 +00:00
if ( tool ! = TOOL_RULER ) {
2019-08-30 20:49:47 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2019-08-30 20:49:47 +00:00
if ( ruler_tool_active ) {
Color ruler_primary_color = get_color ( " accent_color " , " Editor " ) ;
Color ruler_secondary_color = ruler_primary_color ;
ruler_secondary_color . a = 0.5 ;
2019-10-24 19:19:11 +00:00
Point2 begin = ( ruler_tool_origin - view_offset ) * zoom ;
2019-08-30 20:49:47 +00:00
Point2 end = snap_point ( viewport - > get_local_mouse_position ( ) / zoom + view_offset ) * zoom - view_offset * zoom ;
Point2 corner = Point2 ( begin . x , end . y ) ;
Vector2 length_vector = ( begin - end ) . abs ( ) / zoom ;
2019-10-24 19:19:11 +00:00
bool draw_secondary_lines = ! ( Math : : is_equal_approx ( begin . y , corner . y ) | | Math : : is_equal_approx ( end . x , corner . x ) ) ;
2019-08-30 20:49:47 +00:00
viewport - > draw_line ( begin , end , ruler_primary_color , Math : : round ( EDSCALE * 3 ) , true ) ;
if ( draw_secondary_lines ) {
viewport - > draw_line ( begin , corner , ruler_secondary_color , Math : : round ( EDSCALE ) ) ;
viewport - > draw_line ( corner , end , ruler_secondary_color , Math : : round ( EDSCALE ) ) ;
}
Ref < Font > font = get_font ( " bold " , " EditorFonts " ) ;
Color font_color = get_color ( " font_color " , " Editor " ) ;
Color font_secondary_color = font_color ;
font_secondary_color . a = 0.5 ;
float text_height = font - > get_height ( ) ;
const float text_width = 76 ;
2019-10-06 14:19:13 +00:00
const float angle_text_width = 54 ;
2019-08-30 20:49:47 +00:00
Point2 text_pos = ( begin + end ) / 2 - Vector2 ( text_width / 2 , text_height / 2 ) ;
text_pos . x = CLAMP ( text_pos . x , text_width / 2 , viewport - > get_rect ( ) . size . x - text_width * 1.5 ) ;
text_pos . y = CLAMP ( text_pos . y , text_height * 1.5 , viewport - > get_rect ( ) . size . y - text_height * 1.5 ) ;
2021-07-18 08:51:03 +00:00
viewport - > draw_string ( font , text_pos , vformat ( " %.1f px " , length_vector . length ( ) ) , font_color ) ;
2019-08-30 20:49:47 +00:00
if ( draw_secondary_lines ) {
2019-10-15 15:47:58 +00:00
const float horizontal_angle_rad = atan2 ( length_vector . y , length_vector . x ) ;
const float vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad ;
const int horizontal_angle = round ( 180 * horizontal_angle_rad / Math_PI ) ;
const int vertical_angle = round ( 180 * vertical_angle_rad / Math_PI ) ;
2019-08-30 20:49:47 +00:00
Point2 text_pos2 = text_pos ;
text_pos2 . x = begin . x < text_pos . x ? MIN ( text_pos . x - text_width , begin . x - text_width / 2 ) : MAX ( text_pos . x + text_width , begin . x - text_width / 2 ) ;
2021-07-18 08:51:03 +00:00
viewport - > draw_string ( font , text_pos2 , vformat ( " %.1f px " , length_vector . y ) , font_secondary_color ) ;
2019-08-30 20:49:47 +00:00
2019-10-06 14:19:13 +00:00
Point2 v_angle_text_pos = Point2 ( ) ;
v_angle_text_pos . x = CLAMP ( begin . x - angle_text_width / 2 , angle_text_width / 2 , viewport - > get_rect ( ) . size . x - angle_text_width ) ;
v_angle_text_pos . y = begin . y < end . y ? MIN ( text_pos2 . y - 2 * text_height , begin . y - text_height * 0.5 ) : MAX ( text_pos2 . y + text_height * 3 , begin . y + text_height * 1.5 ) ;
2021-07-18 08:51:03 +00:00
viewport - > draw_string ( font , v_angle_text_pos , vformat ( String : : utf8 ( " %d° " ) , vertical_angle ) , font_secondary_color ) ;
2019-10-06 14:19:13 +00:00
2019-08-30 20:49:47 +00:00
text_pos2 = text_pos ;
text_pos2 . y = end . y < text_pos . y ? MIN ( text_pos . y - text_height * 2 , end . y - text_height / 2 ) : MAX ( text_pos . y + text_height * 2 , end . y - text_height / 2 ) ;
2021-07-18 08:51:03 +00:00
viewport - > draw_string ( font , text_pos2 , vformat ( " %.1f px " , length_vector . x ) , font_secondary_color ) ;
2019-10-06 14:19:13 +00:00
Point2 h_angle_text_pos = Point2 ( ) ;
h_angle_text_pos . x = CLAMP ( end . x - angle_text_width / 2 , angle_text_width / 2 , viewport - > get_rect ( ) . size . x - angle_text_width ) ;
if ( begin . y < end . y ) {
h_angle_text_pos . y = end . y + text_height * 1.5 ;
if ( ABS ( text_pos2 . x - h_angle_text_pos . x ) < text_width ) {
2019-10-24 20:31:19 +00:00
int height_multiplier = 1.5 + ( int ) grid_snap_active ;
2019-10-06 14:19:13 +00:00
h_angle_text_pos . y = MAX ( text_pos . y + height_multiplier * text_height , MAX ( end . y + text_height * 1.5 , text_pos2 . y + height_multiplier * text_height ) ) ;
}
} else {
h_angle_text_pos . y = end . y - text_height * 0.5 ;
if ( ABS ( text_pos2 . x - h_angle_text_pos . x ) < text_width ) {
2019-10-24 20:31:19 +00:00
int height_multiplier = 1 + ( int ) grid_snap_active ;
2019-10-06 14:19:13 +00:00
h_angle_text_pos . y = MIN ( text_pos . y - height_multiplier * text_height , MIN ( end . y - text_height * 0.5 , text_pos2 . y - height_multiplier * text_height ) ) ;
}
}
2021-07-18 08:51:03 +00:00
viewport - > draw_string ( font , h_angle_text_pos , vformat ( String : : utf8 ( " %d° " ) , horizontal_angle ) , font_secondary_color ) ;
2019-10-15 15:47:58 +00:00
// Angle arcs
int arc_point_count = 8 ;
float arc_radius_max_length_percent = 0.1 ;
float ruler_length = length_vector . length ( ) * zoom ;
float arc_max_radius = 50.0 ;
float arc_line_width = 2.0 ;
const Vector2 end_to_begin = ( end - begin ) ;
float arc_1_start_angle =
end_to_begin . x < 0 ?
2021-01-12 15:57:55 +00:00
( end_to_begin . y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0 ) :
( end_to_begin . y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad ) ;
2019-10-15 15:47:58 +00:00
float arc_1_end_angle = arc_1_start_angle + vertical_angle_rad ;
// Constrain arc to triangle height & max size
float arc_1_radius = MIN ( MIN ( arc_radius_max_length_percent * ruler_length , ABS ( end_to_begin . y ) ) , arc_max_radius ) ;
float arc_2_start_angle =
end_to_begin . x < 0 ?
2021-01-12 15:57:55 +00:00
( end_to_begin . y < 0 ? 0.0 : - horizontal_angle_rad ) :
( end_to_begin . y < 0 ? Math_PI - horizontal_angle_rad : Math_PI ) ;
2019-10-15 15:47:58 +00:00
float arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad ;
// Constrain arc to triangle width & max size
float arc_2_radius = MIN ( MIN ( arc_radius_max_length_percent * ruler_length , ABS ( end_to_begin . x ) ) , arc_max_radius ) ;
viewport - > draw_arc ( begin , arc_1_radius , arc_1_start_angle , arc_1_end_angle , arc_point_count , ruler_primary_color , Math : : round ( EDSCALE * arc_line_width ) ) ;
viewport - > draw_arc ( end , arc_2_radius , arc_2_start_angle , arc_2_end_angle , arc_point_count , ruler_primary_color , Math : : round ( EDSCALE * arc_line_width ) ) ;
2019-08-30 20:49:47 +00:00
}
2019-10-24 20:31:19 +00:00
if ( grid_snap_active ) {
2019-08-30 20:49:47 +00:00
text_pos = ( begin + end ) / 2 + Vector2 ( - text_width / 2 , text_height / 2 ) ;
text_pos . x = CLAMP ( text_pos . x , text_width / 2 , viewport - > get_rect ( ) . size . x - text_width * 1.5 ) ;
text_pos . y = CLAMP ( text_pos . y , text_height * 2.5 , viewport - > get_rect ( ) . size . y - text_height / 2 ) ;
if ( draw_secondary_lines ) {
viewport - > draw_string ( font , text_pos , vformat ( " %.2f units " , ( length_vector / grid_step ) . length ( ) ) , font_color ) ;
Point2 text_pos2 = text_pos ;
text_pos2 . x = begin . x < text_pos . x ? MIN ( text_pos . x - text_width , begin . x - text_width / 2 ) : MAX ( text_pos . x + text_width , begin . x - text_width / 2 ) ;
2019-10-24 19:19:11 +00:00
viewport - > draw_string ( font , text_pos2 , vformat ( " %d units " , roundf ( length_vector . y / grid_step . y ) ) , font_secondary_color ) ;
2019-08-30 20:49:47 +00:00
text_pos2 = text_pos ;
text_pos2 . y = end . y < text_pos . y ? MIN ( text_pos . y - text_height * 2 , end . y + text_height / 2 ) : MAX ( text_pos . y + text_height * 2 , end . y + text_height / 2 ) ;
2019-10-24 19:19:11 +00:00
viewport - > draw_string ( font , text_pos2 , vformat ( " %d units " , roundf ( length_vector . x / grid_step . x ) ) , font_secondary_color ) ;
2019-08-30 20:49:47 +00:00
} else {
viewport - > draw_string ( font , text_pos , vformat ( " %d units " , roundf ( ( length_vector / grid_step ) . length ( ) ) ) , font_color ) ;
}
}
} else {
2019-10-24 20:31:19 +00:00
if ( grid_snap_active ) {
2019-08-30 20:49:47 +00:00
Ref < Texture > position_icon = get_icon ( " EditorPosition " , " EditorIcons " ) ;
2019-10-24 19:19:11 +00:00
viewport - > draw_texture ( get_icon ( " EditorPosition " , " EditorIcons " ) , ( ruler_tool_origin - view_offset ) * zoom - position_icon - > get_size ( ) / 2 ) ;
2019-08-30 20:49:47 +00:00
}
}
}
2019-03-31 16:53:24 +00:00
void CanvasItemEditor : : _draw_control_anchors ( Control * control ) {
2018-09-10 12:39:46 +00:00
Transform2D xform = transform * control - > get_global_transform_with_canvas ( ) ;
RID ci = viewport - > get_canvas_item ( ) ;
2019-03-31 16:53:24 +00:00
if ( tool = = TOOL_SELECT & & ! Object : : cast_to < Container > ( control - > get_parent ( ) ) ) {
// Compute the anchors
float anchors_values [ 4 ] ;
anchors_values [ 0 ] = control - > get_anchor ( MARGIN_LEFT ) ;
anchors_values [ 1 ] = control - > get_anchor ( MARGIN_TOP ) ;
anchors_values [ 2 ] = control - > get_anchor ( MARGIN_RIGHT ) ;
anchors_values [ 3 ] = control - > get_anchor ( MARGIN_BOTTOM ) ;
Vector2 anchors_pos [ 4 ] ;
for ( int i = 0 ; i < 4 ; i + + ) {
Vector2 value = Vector2 ( ( i % 2 = = 0 ) ? anchors_values [ i ] : anchors_values [ ( i + 1 ) % 4 ] , ( i % 2 = = 1 ) ? anchors_values [ i ] : anchors_values [ ( i + 1 ) % 4 ] ) ;
anchors_pos [ i ] = xform . xform ( _anchor_to_position ( control , value ) ) ;
}
// Draw the anchors handles
Rect2 anchor_rects [ 4 ] ;
anchor_rects [ 0 ] = Rect2 ( anchors_pos [ 0 ] - anchor_handle - > get_size ( ) , anchor_handle - > get_size ( ) ) ;
anchor_rects [ 1 ] = Rect2 ( anchors_pos [ 1 ] - Vector2 ( 0.0 , anchor_handle - > get_size ( ) . y ) , Point2 ( - anchor_handle - > get_size ( ) . x , anchor_handle - > get_size ( ) . y ) ) ;
anchor_rects [ 2 ] = Rect2 ( anchors_pos [ 2 ] , - anchor_handle - > get_size ( ) ) ;
anchor_rects [ 3 ] = Rect2 ( anchors_pos [ 3 ] - Vector2 ( anchor_handle - > get_size ( ) . x , 0.0 ) , Point2 ( anchor_handle - > get_size ( ) . x , - anchor_handle - > get_size ( ) . y ) ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
anchor_handle - > draw_rect ( ci , anchor_rects [ i ] ) ;
}
}
}
void CanvasItemEditor : : _draw_control_helpers ( Control * control ) {
Transform2D xform = transform * control - > get_global_transform_with_canvas ( ) ;
2018-09-10 12:39:46 +00:00
if ( tool = = TOOL_SELECT & & show_helpers & & ! Object : : cast_to < Container > ( control - > get_parent ( ) ) ) {
// Draw the helpers
Color color_base = Color ( 0.8 , 0.8 , 0.8 , 0.5 ) ;
2019-03-31 16:53:24 +00:00
// Compute the anchors
2018-09-10 12:39:46 +00:00
float anchors_values [ 4 ] ;
anchors_values [ 0 ] = control - > get_anchor ( MARGIN_LEFT ) ;
anchors_values [ 1 ] = control - > get_anchor ( MARGIN_TOP ) ;
anchors_values [ 2 ] = control - > get_anchor ( MARGIN_RIGHT ) ;
anchors_values [ 3 ] = control - > get_anchor ( MARGIN_BOTTOM ) ;
Vector2 anchors [ 4 ] ;
Vector2 anchors_pos [ 4 ] ;
for ( int i = 0 ; i < 4 ; i + + ) {
anchors [ i ] = Vector2 ( ( i % 2 = = 0 ) ? anchors_values [ i ] : anchors_values [ ( i + 1 ) % 4 ] , ( i % 2 = = 1 ) ? anchors_values [ i ] : anchors_values [ ( i + 1 ) % 4 ] ) ;
anchors_pos [ i ] = xform . xform ( _anchor_to_position ( control , anchors [ i ] ) ) ;
}
// Get which anchor is dragged
int dragged_anchor = - 1 ;
switch ( drag_type ) {
case DRAG_ANCHOR_ALL :
case DRAG_ANCHOR_TOP_LEFT :
dragged_anchor = 0 ;
break ;
case DRAG_ANCHOR_TOP_RIGHT :
dragged_anchor = 1 ;
break ;
case DRAG_ANCHOR_BOTTOM_RIGHT :
dragged_anchor = 2 ;
break ;
case DRAG_ANCHOR_BOTTOM_LEFT :
dragged_anchor = 3 ;
break ;
default :
break ;
}
if ( dragged_anchor > = 0 ) {
// Draw the 4 lines when dragged
2019-04-05 08:18:21 +00:00
bool anchor_snapped ;
2018-09-10 12:39:46 +00:00
Color color_snapped = Color ( 0.64 , 0.93 , 0.67 , 0.5 ) ;
Vector2 corners_pos [ 4 ] ;
for ( int i = 0 ; i < 4 ; i + + ) {
corners_pos [ i ] = xform . xform ( _anchor_to_position ( control , Vector2 ( ( i = = 0 | | i = = 3 ) ? ANCHOR_BEGIN : ANCHOR_END , ( i < = 1 ) ? ANCHOR_BEGIN : ANCHOR_END ) ) ) ;
}
Vector2 line_starts [ 4 ] ;
Vector2 line_ends [ 4 ] ;
for ( int i = 0 ; i < 4 ; i + + ) {
float anchor_val = ( i > = 2 ) ? ANCHOR_END - anchors_values [ i ] : anchors_values [ i ] ;
line_starts [ i ] = Vector2 : : linear_interpolate ( corners_pos [ i ] , corners_pos [ ( i + 1 ) % 4 ] , anchor_val ) ;
line_ends [ i ] = Vector2 : : linear_interpolate ( corners_pos [ ( i + 3 ) % 4 ] , corners_pos [ ( i + 2 ) % 4 ] , anchor_val ) ;
2019-04-05 08:18:21 +00:00
anchor_snapped = anchors_values [ i ] = = 0.0 | | anchors_values [ i ] = = 0.5 | | anchors_values [ i ] = = 1.0 ;
viewport - > draw_line ( line_starts [ i ] , line_ends [ i ] , anchor_snapped ? color_snapped : color_base , ( i = = dragged_anchor | | ( i + 3 ) % 4 = = dragged_anchor ) ? 2 : 1 ) ;
2018-09-10 12:39:46 +00:00
}
// Display the percentages next to the lines
float percent_val ;
percent_val = anchors_values [ ( dragged_anchor + 2 ) % 4 ] - anchors_values [ dragged_anchor ] ;
percent_val = ( dragged_anchor > = 2 ) ? - percent_val : percent_val ;
_draw_percentage_at_position ( percent_val , ( anchors_pos [ dragged_anchor ] + anchors_pos [ ( dragged_anchor + 1 ) % 4 ] ) / 2 , ( Margin ) ( ( dragged_anchor + 1 ) % 4 ) ) ;
percent_val = anchors_values [ ( dragged_anchor + 3 ) % 4 ] - anchors_values [ ( dragged_anchor + 1 ) % 4 ] ;
percent_val = ( ( dragged_anchor + 1 ) % 4 > = 2 ) ? - percent_val : percent_val ;
_draw_percentage_at_position ( percent_val , ( anchors_pos [ dragged_anchor ] + anchors_pos [ ( dragged_anchor + 3 ) % 4 ] ) / 2 , ( Margin ) ( dragged_anchor ) ) ;
percent_val = anchors_values [ ( dragged_anchor + 1 ) % 4 ] ;
percent_val = ( ( dragged_anchor + 1 ) % 4 > = 2 ) ? ANCHOR_END - percent_val : percent_val ;
_draw_percentage_at_position ( percent_val , ( line_starts [ dragged_anchor ] + anchors_pos [ dragged_anchor ] ) / 2 , ( Margin ) ( dragged_anchor ) ) ;
percent_val = anchors_values [ dragged_anchor ] ;
percent_val = ( dragged_anchor > = 2 ) ? ANCHOR_END - percent_val : percent_val ;
_draw_percentage_at_position ( percent_val , ( line_ends [ ( dragged_anchor + 1 ) % 4 ] + anchors_pos [ dragged_anchor ] ) / 2 , ( Margin ) ( ( dragged_anchor + 1 ) % 4 ) ) ;
}
// Draw the margin values and the node width/height when dragging control side
float ratio = 0.33 ;
Transform2D parent_transform = xform * control - > get_transform ( ) . affine_inverse ( ) ;
float node_pos_in_parent [ 4 ] ;
Rect2 parent_rect = control - > get_parent_anchorable_rect ( ) ;
node_pos_in_parent [ 0 ] = control - > get_anchor ( MARGIN_LEFT ) * parent_rect . size . width + control - > get_margin ( MARGIN_LEFT ) + parent_rect . position . x ;
node_pos_in_parent [ 1 ] = control - > get_anchor ( MARGIN_TOP ) * parent_rect . size . height + control - > get_margin ( MARGIN_TOP ) + parent_rect . position . y ;
node_pos_in_parent [ 2 ] = control - > get_anchor ( MARGIN_RIGHT ) * parent_rect . size . width + control - > get_margin ( MARGIN_RIGHT ) + parent_rect . position . x ;
node_pos_in_parent [ 3 ] = control - > get_anchor ( MARGIN_BOTTOM ) * parent_rect . size . height + control - > get_margin ( MARGIN_BOTTOM ) + parent_rect . position . y ;
Point2 start , end ;
switch ( drag_type ) {
case DRAG_LEFT :
case DRAG_TOP_LEFT :
case DRAG_BOTTOM_LEFT :
_draw_margin_at_position ( control - > get_size ( ) . width , parent_transform . xform ( Vector2 ( ( node_pos_in_parent [ 0 ] + node_pos_in_parent [ 2 ] ) / 2 , node_pos_in_parent [ 3 ] ) ) + Vector2 ( 0 , 5 ) , MARGIN_BOTTOM ) ;
2019-04-05 12:06:16 +00:00
FALLTHROUGH ;
2018-09-10 12:39:46 +00:00
case DRAG_MOVE :
start = Vector2 ( node_pos_in_parent [ 0 ] , Math : : lerp ( node_pos_in_parent [ 1 ] , node_pos_in_parent [ 3 ] , ratio ) ) ;
end = start - Vector2 ( control - > get_margin ( MARGIN_LEFT ) , 0 ) ;
_draw_margin_at_position ( control - > get_margin ( MARGIN_LEFT ) , parent_transform . xform ( ( start + end ) / 2 ) , MARGIN_TOP ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( parent_transform . xform ( start ) , parent_transform . xform ( end ) , color_base , Math : : round ( EDSCALE ) ) ;
2018-09-10 12:39:46 +00:00
break ;
default :
break ;
}
switch ( drag_type ) {
case DRAG_RIGHT :
case DRAG_TOP_RIGHT :
case DRAG_BOTTOM_RIGHT :
_draw_margin_at_position ( control - > get_size ( ) . width , parent_transform . xform ( Vector2 ( ( node_pos_in_parent [ 0 ] + node_pos_in_parent [ 2 ] ) / 2 , node_pos_in_parent [ 3 ] ) ) + Vector2 ( 0 , 5 ) , MARGIN_BOTTOM ) ;
2019-04-05 12:06:16 +00:00
FALLTHROUGH ;
2018-09-10 12:39:46 +00:00
case DRAG_MOVE :
start = Vector2 ( node_pos_in_parent [ 2 ] , Math : : lerp ( node_pos_in_parent [ 3 ] , node_pos_in_parent [ 1 ] , ratio ) ) ;
end = start - Vector2 ( control - > get_margin ( MARGIN_RIGHT ) , 0 ) ;
_draw_margin_at_position ( control - > get_margin ( MARGIN_RIGHT ) , parent_transform . xform ( ( start + end ) / 2 ) , MARGIN_BOTTOM ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( parent_transform . xform ( start ) , parent_transform . xform ( end ) , color_base , Math : : round ( EDSCALE ) ) ;
2018-09-10 12:39:46 +00:00
break ;
default :
break ;
}
switch ( drag_type ) {
case DRAG_TOP :
case DRAG_TOP_LEFT :
case DRAG_TOP_RIGHT :
_draw_margin_at_position ( control - > get_size ( ) . height , parent_transform . xform ( Vector2 ( node_pos_in_parent [ 2 ] , ( node_pos_in_parent [ 1 ] + node_pos_in_parent [ 3 ] ) / 2 ) ) + Vector2 ( 5 , 0 ) , MARGIN_RIGHT ) ;
2019-04-05 12:06:16 +00:00
FALLTHROUGH ;
2018-09-10 12:39:46 +00:00
case DRAG_MOVE :
start = Vector2 ( Math : : lerp ( node_pos_in_parent [ 0 ] , node_pos_in_parent [ 2 ] , ratio ) , node_pos_in_parent [ 1 ] ) ;
end = start - Vector2 ( 0 , control - > get_margin ( MARGIN_TOP ) ) ;
_draw_margin_at_position ( control - > get_margin ( MARGIN_TOP ) , parent_transform . xform ( ( start + end ) / 2 ) , MARGIN_LEFT ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( parent_transform . xform ( start ) , parent_transform . xform ( end ) , color_base , Math : : round ( EDSCALE ) ) ;
2018-09-10 12:39:46 +00:00
break ;
default :
break ;
}
switch ( drag_type ) {
case DRAG_BOTTOM :
case DRAG_BOTTOM_LEFT :
case DRAG_BOTTOM_RIGHT :
_draw_margin_at_position ( control - > get_size ( ) . height , parent_transform . xform ( Vector2 ( node_pos_in_parent [ 2 ] , ( node_pos_in_parent [ 1 ] + node_pos_in_parent [ 3 ] ) / 2 ) + Vector2 ( 5 , 0 ) ) , MARGIN_RIGHT ) ;
2019-04-05 12:06:16 +00:00
FALLTHROUGH ;
2018-09-10 12:39:46 +00:00
case DRAG_MOVE :
start = Vector2 ( Math : : lerp ( node_pos_in_parent [ 2 ] , node_pos_in_parent [ 0 ] , ratio ) , node_pos_in_parent [ 3 ] ) ;
end = start - Vector2 ( 0 , control - > get_margin ( MARGIN_BOTTOM ) ) ;
_draw_margin_at_position ( control - > get_margin ( MARGIN_BOTTOM ) , parent_transform . xform ( ( start + end ) / 2 ) , MARGIN_RIGHT ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( parent_transform . xform ( start ) , parent_transform . xform ( end ) , color_base , Math : : round ( EDSCALE ) ) ;
2018-09-10 12:39:46 +00:00
break ;
default :
break ;
}
switch ( drag_type ) {
//Draw the ghost rect if the node if rotated/scaled
case DRAG_LEFT :
case DRAG_TOP_LEFT :
case DRAG_TOP :
case DRAG_TOP_RIGHT :
case DRAG_RIGHT :
case DRAG_BOTTOM_RIGHT :
case DRAG_BOTTOM :
case DRAG_BOTTOM_LEFT :
case DRAG_MOVE :
if ( control - > get_rotation ( ) ! = 0.0 | | control - > get_scale ( ) ! = Vector2 ( 1 , 1 ) ) {
Rect2 rect = Rect2 ( Vector2 ( node_pos_in_parent [ 0 ] , node_pos_in_parent [ 1 ] ) , control - > get_size ( ) ) ;
2019-07-08 23:49:43 +00:00
viewport - > draw_rect ( parent_transform . xform ( rect ) , color_base , false , Math : : round ( EDSCALE ) ) ;
2018-09-10 12:39:46 +00:00
}
break ;
default :
break ;
}
}
}
2017-08-28 19:51:56 +00:00
void CanvasItemEditor : : _draw_selection ( ) {
Ref < Texture > pivot_icon = get_icon ( " EditorPivot " , " EditorIcons " ) ;
2018-03-10 10:56:27 +00:00
Ref < Texture > position_icon = get_icon ( " EditorPosition " , " EditorIcons " ) ;
Ref < Texture > previous_position_icon = get_icon ( " EditorPositionPrevious " , " EditorIcons " ) ;
2017-08-28 19:51:56 +00:00
RID ci = viewport - > get_canvas_item ( ) ;
2014-02-10 01:10:30 +00:00
2020-04-15 12:03:12 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( true , false ) ;
2014-02-10 01:10:30 +00:00
2017-11-07 07:58:35 +00:00
bool single = selection . size ( ) = = 1 ;
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2017-03-05 15:44:50 +00:00
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
2020-04-15 12:03:12 +00:00
bool item_locked = canvas_item - > has_meta ( " _edit_lock_ " ) ;
2017-11-07 07:58:35 +00:00
// Draw the previous position if we are dragging the node
if ( show_helpers & &
2018-09-09 20:17:47 +00:00
( drag_type = = DRAG_MOVE | | drag_type = = DRAG_ROTATE | |
2017-11-07 07:58:35 +00:00
drag_type = = DRAG_LEFT | | drag_type = = DRAG_RIGHT | | drag_type = = DRAG_TOP | | drag_type = = DRAG_BOTTOM | |
drag_type = = DRAG_TOP_LEFT | | drag_type = = DRAG_TOP_RIGHT | | drag_type = = DRAG_BOTTOM_LEFT | | drag_type = = DRAG_BOTTOM_RIGHT ) ) {
2017-09-12 17:11:53 +00:00
const Transform2D pre_drag_xform = transform * se - > pre_drag_xform ;
const Color pre_drag_color = Color ( 0.4 , 0.6 , 1 , 0.7 ) ;
2018-03-08 20:35:41 +00:00
if ( canvas_item - > _edit_use_rect ( ) ) {
Vector2 pre_drag_endpoints [ 4 ] = {
2017-09-12 17:11:53 +00:00
2018-03-08 20:35:41 +00:00
pre_drag_xform . xform ( se - > pre_drag_rect . position ) ,
pre_drag_xform . xform ( se - > pre_drag_rect . position + Vector2 ( se - > pre_drag_rect . size . x , 0 ) ) ,
pre_drag_xform . xform ( se - > pre_drag_rect . position + se - > pre_drag_rect . size ) ,
pre_drag_xform . xform ( se - > pre_drag_rect . position + Vector2 ( 0 , se - > pre_drag_rect . size . y ) )
} ;
2017-09-12 17:11:53 +00:00
2018-03-08 20:35:41 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( pre_drag_endpoints [ i ] , pre_drag_endpoints [ ( i + 1 ) % 4 ] , pre_drag_color , Math : : round ( 2 * EDSCALE ) , true ) ;
2018-03-08 20:35:41 +00:00
}
} else {
2018-03-10 10:56:27 +00:00
viewport - > draw_texture ( previous_position_icon , ( pre_drag_xform . xform ( Point2 ( ) ) - ( previous_position_icon - > get_size ( ) / 2 ) ) . floor ( ) ) ;
2017-09-12 17:11:53 +00:00
}
}
2017-03-05 15:44:50 +00:00
Transform2D xform = transform * canvas_item - > get_global_transform_with_canvas ( ) ;
2014-02-10 01:10:30 +00:00
2018-03-08 20:35:41 +00:00
// Draw the selected items position / surrounding boxes
if ( canvas_item - > _edit_use_rect ( ) ) {
Rect2 rect = canvas_item - > _edit_get_rect ( ) ;
Vector2 endpoints [ 4 ] = {
xform . xform ( rect . position ) ,
xform . xform ( rect . position + Vector2 ( rect . size . x , 0 ) ) ,
xform . xform ( rect . position + rect . size ) ,
xform . xform ( rect . position + Vector2 ( 0 , rect . size . y ) )
} ;
2014-02-10 01:10:30 +00:00
2018-03-08 20:35:41 +00:00
Color c = Color ( 1 , 0.6 , 0.4 , 0.7 ) ;
2014-02-10 01:10:30 +00:00
2020-04-15 12:03:12 +00:00
if ( item_locked ) {
c = Color ( 0.7 , 0.7 , 0.7 , 0.7 ) ;
}
2018-03-08 20:35:41 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
2019-07-08 23:49:43 +00:00
viewport - > draw_line ( endpoints [ i ] , endpoints [ ( i + 1 ) % 4 ] , c , Math : : round ( 2 * EDSCALE ) , true ) ;
2018-03-08 20:35:41 +00:00
}
} else {
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( xform * canvas_item - > get_transform ( ) . affine_inverse ( ) * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2018-09-10 12:39:46 +00:00
Transform2D simple_xform = viewport - > get_transform ( ) * unscaled_transform ;
viewport - > draw_set_transform_matrix ( simple_xform ) ;
2018-03-08 20:35:41 +00:00
viewport - > draw_texture ( position_icon , - ( position_icon - > get_size ( ) / 2 ) ) ;
2018-09-10 12:39:46 +00:00
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2020-04-15 12:03:12 +00:00
if ( single & & ! item_locked & & ( tool = = TOOL_SELECT | | tool = = TOOL_MOVE | | tool = = TOOL_SCALE | | tool = = TOOL_ROTATE | | tool = = TOOL_EDIT_PIVOT ) ) { //kind of sucks
2017-11-07 07:58:35 +00:00
// Draw the pivot
2019-01-18 18:30:45 +00:00
if ( canvas_item - > _edit_use_pivot ( ) ) {
// Draw the node's pivot
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( xform * canvas_item - > get_transform ( ) . affine_inverse ( ) * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2019-01-18 18:30:45 +00:00
Transform2D simple_xform = viewport - > get_transform ( ) * unscaled_transform ;
2019-01-27 14:51:45 +00:00
2019-01-18 18:30:45 +00:00
viewport - > draw_set_transform_matrix ( simple_xform ) ;
2019-01-27 14:51:45 +00:00
viewport - > draw_texture ( pivot_icon , - ( pivot_icon - > get_size ( ) / 2 ) . floor ( ) ) ;
2019-01-18 18:30:45 +00:00
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-07-10 22:14:22 +00:00
2018-09-10 12:39:46 +00:00
// Draw control-related helpers
2017-08-24 20:58:51 +00:00
Control * control = Object : : cast_to < Control > ( canvas_item ) ;
2018-10-16 18:35:51 +00:00
if ( control & & _is_node_movable ( control ) ) {
2019-03-31 16:53:24 +00:00
_draw_control_anchors ( control ) ;
2018-09-10 12:39:46 +00:00
_draw_control_helpers ( control ) ;
2017-07-06 20:42:44 +00:00
}
2014-02-10 01:10:30 +00:00
2018-09-10 12:39:46 +00:00
// Draw the resize handles
2018-10-16 18:35:51 +00:00
if ( tool = = TOOL_SELECT & & canvas_item - > _edit_use_rect ( ) & & _is_node_movable ( canvas_item ) ) {
2018-03-08 20:35:41 +00:00
Rect2 rect = canvas_item - > _edit_get_rect ( ) ;
Vector2 endpoints [ 4 ] = {
xform . xform ( rect . position ) ,
xform . xform ( rect . position + Vector2 ( rect . size . x , 0 ) ) ,
xform . xform ( rect . position + rect . size ) ,
xform . xform ( rect . position + Vector2 ( 0 , rect . size . y ) )
} ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
int prev = ( i + 3 ) % 4 ;
int next = ( i + 1 ) % 4 ;
2014-02-10 01:10:30 +00:00
Vector2 ofs = ( ( endpoints [ i ] - endpoints [ prev ] ) . normalized ( ) + ( ( endpoints [ i ] - endpoints [ next ] ) . normalized ( ) ) ) . normalized ( ) ;
2019-12-10 04:13:02 +00:00
ofs * = Math_SQRT2 * ( select_handle - > get_size ( ) . width / 2 ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
select_handle - > draw ( ci , ( endpoints [ i ] + ofs - ( select_handle - > get_size ( ) / 2 ) ) . floor ( ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ofs = ( endpoints [ i ] + endpoints [ next ] ) / 2 ;
ofs + = ( endpoints [ next ] - endpoints [ i ] ) . tangent ( ) . normalized ( ) * ( select_handle - > get_size ( ) . width / 2 ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
select_handle - > draw ( ci , ( ofs - ( select_handle - > get_size ( ) / 2 ) ) . floor ( ) ) ;
2014-02-10 01:10:30 +00:00
}
}
2018-09-10 12:39:46 +00:00
// Draw the rescale handles
bool is_ctrl = Input : : get_singleton ( ) - > is_key_pressed ( KEY_CONTROL ) ;
bool is_alt = Input : : get_singleton ( ) - > is_key_pressed ( KEY_ALT ) ;
if ( ( is_alt & & is_ctrl ) | | tool = = TOOL_SCALE | | drag_type = = DRAG_SCALE_X | | drag_type = = DRAG_SCALE_Y ) {
2018-10-16 18:35:51 +00:00
if ( _is_node_movable ( canvas_item ) ) {
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( xform * canvas_item - > get_transform ( ) . affine_inverse ( ) * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2018-10-16 18:35:51 +00:00
Transform2D simple_xform = viewport - > get_transform ( ) * unscaled_transform ;
Size2 scale_factor = Size2 ( SCALE_HANDLE_DISTANCE , SCALE_HANDLE_DISTANCE ) ;
bool uniform = Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ;
Point2 offset = ( simple_xform . affine_inverse ( ) . xform ( drag_to ) - simple_xform . affine_inverse ( ) . xform ( drag_from ) ) * zoom ;
if ( drag_type = = DRAG_SCALE_X ) {
scale_factor . x + = offset . x ;
if ( uniform ) {
scale_factor . y + = offset . x ;
}
} else if ( drag_type = = DRAG_SCALE_Y ) {
scale_factor . y - = offset . y ;
if ( uniform ) {
scale_factor . x - = offset . y ;
}
2018-09-10 12:39:46 +00:00
}
2018-10-16 18:35:51 +00:00
viewport - > draw_set_transform_matrix ( simple_xform ) ;
Rect2 x_handle_rect = Rect2 ( scale_factor . x * EDSCALE , - 5 * EDSCALE , 10 * EDSCALE , 10 * EDSCALE ) ;
2019-08-23 16:14:47 +00:00
viewport - > draw_rect ( x_handle_rect , get_color ( " axis_x_color " , " Editor " ) ) ;
viewport - > draw_line ( Point2 ( ) , Point2 ( scale_factor . x * EDSCALE , 0 ) , get_color ( " axis_x_color " , " Editor " ) , Math : : round ( EDSCALE ) , true ) ;
2018-09-10 12:39:46 +00:00
2018-10-16 18:35:51 +00:00
Rect2 y_handle_rect = Rect2 ( - 5 * EDSCALE , - ( scale_factor . y + 10 ) * EDSCALE , 10 * EDSCALE , 10 * EDSCALE ) ;
2019-08-23 16:14:47 +00:00
viewport - > draw_rect ( y_handle_rect , get_color ( " axis_y_color " , " Editor " ) ) ;
viewport - > draw_line ( Point2 ( ) , Point2 ( 0 , - scale_factor . y * EDSCALE ) , get_color ( " axis_y_color " , " Editor " ) , Math : : round ( EDSCALE ) , true ) ;
2018-09-10 12:39:46 +00:00
2018-10-16 18:35:51 +00:00
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
}
2018-09-10 12:39:46 +00:00
}
2014-02-10 01:10:30 +00:00
}
}
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_BOX_SELECTION ) {
// Draw the dragging box
2014-02-10 01:10:30 +00:00
Point2 bsfrom = transform . xform ( drag_from ) ;
2017-03-05 15:44:50 +00:00
Point2 bsto = transform . xform ( box_selecting_to ) ;
2014-02-10 01:10:30 +00:00
2019-08-15 20:17:08 +00:00
viewport - > draw_rect (
2019-03-29 13:19:44 +00:00
Rect2 ( bsfrom , bsto - bsfrom ) ,
2019-08-15 20:17:08 +00:00
get_color ( " box_selection_fill_color " , " Editor " ) ) ;
viewport - > draw_rect (
Rect2 ( bsfrom , bsto - bsfrom ) ,
get_color ( " box_selection_stroke_color " , " Editor " ) ,
false ,
Math : : round ( EDSCALE ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
if ( drag_type = = DRAG_ROTATE ) {
// Draw the line when rotating a node
2019-03-29 13:19:44 +00:00
viewport - > draw_line (
transform . xform ( drag_rotation_center ) ,
transform . xform ( drag_to ) ,
get_color ( " accent_color " , " Editor " ) * Color ( 1 , 1 , 1 , 0.6 ) ,
Math : : round ( 2 * EDSCALE ) ,
true ) ;
2017-11-07 07:58:35 +00:00
}
}
void CanvasItemEditor : : _draw_straight_line ( Point2 p_from , Point2 p_to , Color p_color ) {
// Draw a line going through the whole screen from a vector
RID ci = viewport - > get_canvas_item ( ) ;
Vector < Point2 > points ;
Point2 from = transform . xform ( p_from ) ;
Point2 to = transform . xform ( p_to ) ;
Size2 viewport_size = viewport - > get_size ( ) ;
if ( to . x = = from . x ) {
// Vertical line
points . push_back ( Point2 ( to . x , 0 ) ) ;
points . push_back ( Point2 ( to . x , viewport_size . y ) ) ;
} else if ( to . y = = from . y ) {
// Horizontal line
points . push_back ( Point2 ( 0 , to . y ) ) ;
points . push_back ( Point2 ( viewport_size . x , to . y ) ) ;
} else {
float y_for_zero_x = ( to . y * from . x - from . y * to . x ) / ( from . x - to . x ) ;
float x_for_zero_y = ( to . x * from . y - from . x * to . y ) / ( from . y - to . y ) ;
float y_for_viewport_x = ( ( to . y - from . y ) * ( viewport_size . x - from . x ) ) / ( to . x - from . x ) + from . y ;
float x_for_viewport_y = ( ( to . x - from . x ) * ( viewport_size . y - from . y ) ) / ( to . y - from . y ) + from . x ; // faux
//bool start_set = false;
if ( y_for_zero_x > = 0 & & y_for_zero_x < = viewport_size . y ) {
points . push_back ( Point2 ( 0 , y_for_zero_x ) ) ;
}
if ( x_for_zero_y > = 0 & & x_for_zero_y < = viewport_size . x ) {
points . push_back ( Point2 ( x_for_zero_y , 0 ) ) ;
}
if ( y_for_viewport_x > = 0 & & y_for_viewport_x < = viewport_size . y ) {
points . push_back ( Point2 ( viewport_size . x , y_for_viewport_x ) ) ;
}
if ( x_for_viewport_y > = 0 & & x_for_viewport_y < = viewport_size . x ) {
points . push_back ( Point2 ( x_for_viewport_y , viewport_size . y ) ) ;
}
}
if ( points . size ( ) > = 2 ) {
VisualServer : : get_singleton ( ) - > canvas_item_add_line ( ci , points [ 0 ] , points [ 1 ] , p_color ) ;
2014-02-10 01:10:30 +00:00
}
2017-08-28 19:51:56 +00:00
}
void CanvasItemEditor : : _draw_axis ( ) {
2018-03-02 08:52:13 +00:00
if ( show_origin ) {
2019-08-23 16:14:47 +00:00
_draw_straight_line ( Point2 ( ) , Point2 ( 1 , 0 ) , get_color ( " axis_x_color " , " Editor " ) * Color ( 1 , 1 , 1 , 0.75 ) ) ;
_draw_straight_line ( Point2 ( ) , Point2 ( 0 , 1 ) , get_color ( " axis_y_color " , " Editor " ) * Color ( 1 , 1 , 1 , 0.75 ) ) ;
2018-03-02 08:52:13 +00:00
}
2014-02-10 01:10:30 +00:00
2018-03-02 08:52:13 +00:00
if ( show_viewport ) {
RID ci = viewport - > get_canvas_item ( ) ;
2018-09-24 13:16:40 +00:00
Color area_axis_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/viewport_border_color " ) ;
2014-02-10 01:10:30 +00:00
2018-03-02 08:52:13 +00:00
Size2 screen_size = Size2 ( ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/width " ) , ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/height " ) ) ;
Vector2 screen_endpoints [ 4 ] = {
transform . xform ( Vector2 ( 0 , 0 ) ) ,
transform . xform ( Vector2 ( screen_size . width , 0 ) ) ,
transform . xform ( Vector2 ( screen_size . width , screen_size . height ) ) ,
transform . xform ( Vector2 ( 0 , screen_size . height ) )
} ;
for ( int i = 0 ; i < 4 ; i + + ) {
VisualServer : : get_singleton ( ) - > canvas_item_add_line ( ci , screen_endpoints [ i ] , screen_endpoints [ ( i + 1 ) % 4 ] , area_axis_color ) ;
}
2014-02-10 01:10:30 +00:00
}
2017-08-28 19:51:56 +00:00
}
2014-02-10 01:10:30 +00:00
2017-08-28 19:51:56 +00:00
void CanvasItemEditor : : _draw_bones ( ) {
RID ci = viewport - > get_canvas_item ( ) ;
2016-09-10 19:44:03 +00:00
2016-09-07 09:10:00 +00:00
if ( skeleton_show_bones ) {
2017-01-15 01:20:05 +00:00
Color bone_color1 = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_color1 " ) ;
Color bone_color2 = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_color2 " ) ;
Color bone_ik_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_ik_color " ) ;
2018-05-04 14:54:04 +00:00
Color bone_outline_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_outline_color " ) ;
2017-01-15 01:20:05 +00:00
Color bone_selected_color = EditorSettings : : get_singleton ( ) - > get ( " editors/2d/bone_selected_color " ) ;
2014-07-06 14:49:27 +00:00
2018-05-04 19:46:32 +00:00
for ( Map < BoneKey , BoneList > : : Element * E = bone_list . front ( ) ; E ; E = E - > next ( ) ) {
2016-09-07 09:10:00 +00:00
Vector < Vector2 > bone_shape ;
2018-05-04 14:54:04 +00:00
Vector < Vector2 > bone_shape_outline ;
2021-05-05 10:44:11 +00:00
if ( ! _get_bone_shape ( & bone_shape , & bone_shape_outline , E ) ) {
2018-05-15 13:18:46 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2018-05-04 14:54:04 +00:00
2018-05-15 13:18:46 +00:00
Node2D * from_node = Object : : cast_to < Node2D > ( ObjectDB : : get_instance ( E - > key ( ) . from ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! from_node - > is_visible_in_tree ( ) ) {
2018-05-25 04:01:15 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2018-05-25 04:01:15 +00:00
2016-09-07 09:10:00 +00:00
Vector < Color > colors ;
2018-05-04 19:46:32 +00:00
if ( from_node - > has_meta ( " _edit_ik_ " ) ) {
2016-09-07 09:10:00 +00:00
colors . push_back ( bone_ik_color ) ;
colors . push_back ( bone_ik_color ) ;
colors . push_back ( bone_ik_color ) ;
colors . push_back ( bone_ik_color ) ;
} else {
colors . push_back ( bone_color1 ) ;
colors . push_back ( bone_color2 ) ;
colors . push_back ( bone_color1 ) ;
colors . push_back ( bone_color2 ) ;
}
2014-07-06 14:49:27 +00:00
2018-05-04 14:54:04 +00:00
Vector < Color > outline_colors ;
2018-05-04 19:46:32 +00:00
if ( editor_selection - > is_selected ( from_node ) ) {
2018-05-04 14:54:04 +00:00
outline_colors . push_back ( bone_selected_color ) ;
outline_colors . push_back ( bone_selected_color ) ;
outline_colors . push_back ( bone_selected_color ) ;
outline_colors . push_back ( bone_selected_color ) ;
outline_colors . push_back ( bone_selected_color ) ;
outline_colors . push_back ( bone_selected_color ) ;
} else {
outline_colors . push_back ( bone_outline_color ) ;
outline_colors . push_back ( bone_outline_color ) ;
outline_colors . push_back ( bone_outline_color ) ;
outline_colors . push_back ( bone_outline_color ) ;
outline_colors . push_back ( bone_outline_color ) ;
outline_colors . push_back ( bone_outline_color ) ;
2014-07-06 14:49:27 +00:00
}
2018-05-04 14:54:04 +00:00
VisualServer : : get_singleton ( ) - > canvas_item_add_polygon ( ci , bone_shape_outline , outline_colors ) ;
VisualServer : : get_singleton ( ) - > canvas_item_add_primitive ( ci , bone_shape , colors , Vector < Vector2 > ( ) , RID ( ) ) ;
2016-09-07 09:10:00 +00:00
}
2014-07-06 14:49:27 +00:00
}
2014-02-10 01:10:30 +00:00
}
2018-03-10 10:56:27 +00:00
void CanvasItemEditor : : _draw_invisible_nodes_positions ( Node * p_node , const Transform2D & p_parent_xform , const Transform2D & p_canvas_xform ) {
2017-09-20 19:28:16 +00:00
ERR_FAIL_COND ( ! p_node ) ;
2018-03-10 10:56:27 +00:00
Node * scene = editor - > get_edited_scene ( ) ;
2021-05-05 10:44:11 +00:00
if ( p_node ! = scene & & p_node - > get_owner ( ) ! = scene & & ! scene - > is_editable_instance ( p_node - > get_owner ( ) ) ) {
2018-03-10 10:56:27 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2021-02-20 09:27:03 +00:00
2018-03-10 10:56:27 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
2021-05-05 10:44:11 +00:00
if ( canvas_item & & ! canvas_item - > is_visible ( ) ) {
2018-03-10 10:56:27 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2017-08-28 19:51:56 +00:00
2018-03-10 10:56:27 +00:00
Transform2D parent_xform = p_parent_xform ;
Transform2D canvas_xform = p_canvas_xform ;
if ( canvas_item & & ! canvas_item - > is_set_as_toplevel ( ) ) {
parent_xform = parent_xform * canvas_item - > get_transform ( ) ;
} else {
CanvasLayer * cl = Object : : cast_to < CanvasLayer > ( p_node ) ;
parent_xform = Transform2D ( ) ;
canvas_xform = cl ? cl - > get_transform ( ) : p_canvas_xform ;
}
2017-08-28 19:51:56 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2018-03-10 10:56:27 +00:00
_draw_invisible_nodes_positions ( p_node - > get_child ( i ) , parent_xform , canvas_xform ) ;
}
2018-10-16 18:35:51 +00:00
if ( canvas_item & & ! canvas_item - > _edit_use_rect ( ) & & ( ! editor_selection - > is_selected ( canvas_item ) | | _is_node_locked ( canvas_item ) ) ) {
2018-03-10 10:56:27 +00:00
Transform2D xform = transform * canvas_xform * parent_xform ;
2018-03-12 22:32:25 +00:00
// Draw the node's position
Ref < Texture > position_icon = get_icon ( " EditorPositionUnselected " , " EditorIcons " ) ;
2019-10-20 10:11:06 +00:00
Transform2D unscaled_transform = ( xform * canvas_item - > get_transform ( ) . affine_inverse ( ) * canvas_item - > _edit_get_transform ( ) ) . orthonormalized ( ) ;
2018-09-10 12:39:46 +00:00
Transform2D simple_xform = viewport - > get_transform ( ) * unscaled_transform ;
viewport - > draw_set_transform_matrix ( simple_xform ) ;
2018-03-10 10:56:27 +00:00
viewport - > draw_texture ( position_icon , - position_icon - > get_size ( ) / 2 , Color ( 1.0 , 1.0 , 1.0 , 0.5 ) ) ;
2018-09-10 12:39:46 +00:00
viewport - > draw_set_transform_matrix ( viewport - > get_transform ( ) ) ;
2017-08-28 19:51:56 +00:00
}
2018-03-12 22:32:25 +00:00
}
void CanvasItemEditor : : _draw_hover ( ) {
List < Rect2 > previous_rects ;
for ( int i = 0 ; i < hovering_results . size ( ) ; i + + ) {
2018-06-12 09:01:24 +00:00
Ref < Texture > node_icon = hovering_results [ i ] . icon ;
String node_name = hovering_results [ i ] . name ;
2018-03-12 22:32:25 +00:00
2018-03-10 10:56:27 +00:00
Ref < Font > font = get_font ( " font " , " Label " ) ;
2018-03-12 22:32:25 +00:00
Size2 node_name_size = font - > get_string_size ( node_name ) ;
Size2 item_size = Size2 ( node_icon - > get_size ( ) . x + 4 + node_name_size . x , MAX ( node_icon - > get_size ( ) . y , node_name_size . y - 3 ) ) ;
2018-06-12 09:01:24 +00:00
Point2 pos = transform . xform ( hovering_results [ i ] . position ) - Point2 ( 0 , item_size . y ) + ( Point2 ( node_icon - > get_size ( ) . x , - node_icon - > get_size ( ) . y ) / 4 ) ;
2018-09-13 01:38:39 +00:00
// Rectify the position to avoid overlapping items
2018-03-12 22:32:25 +00:00
for ( List < Rect2 > : : Element * E = previous_rects . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . intersects ( Rect2 ( pos , item_size ) ) ) {
pos . y = E - > get ( ) . get_position ( ) . y - item_size . y ;
}
}
previous_rects . push_back ( Rect2 ( pos , item_size ) ) ;
2018-06-12 09:01:24 +00:00
// Draw icon
2018-03-12 22:32:25 +00:00
viewport - > draw_texture ( node_icon , pos , Color ( 1.0 , 1.0 , 1.0 , 0.5 ) ) ;
2018-06-12 09:01:24 +00:00
// Draw name
2018-03-12 22:32:25 +00:00
viewport - > draw_string ( font , pos + Point2 ( node_icon - > get_size ( ) . x + 4 , item_size . y - 3 ) , node_name , Color ( 1.0 , 1.0 , 1.0 , 0.5 ) ) ;
2018-03-10 10:56:27 +00:00
}
}
2018-03-08 20:12:49 +00:00
void CanvasItemEditor : : _draw_locks_and_groups ( Node * p_node , const Transform2D & p_parent_xform , const Transform2D & p_canvas_xform ) {
2017-09-20 19:28:16 +00:00
ERR_FAIL_COND ( ! p_node ) ;
2018-03-08 20:12:49 +00:00
Node * scene = editor - > get_edited_scene ( ) ;
2021-05-05 10:44:11 +00:00
if ( p_node ! = scene & & p_node - > get_owner ( ) ! = scene & & ! scene - > is_editable_instance ( p_node - > get_owner ( ) ) ) {
2018-03-08 20:12:49 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2018-03-08 20:12:49 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
2021-05-05 10:44:11 +00:00
if ( canvas_item & & ! canvas_item - > is_visible ( ) ) {
2018-03-08 20:12:49 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2017-08-28 19:51:56 +00:00
2018-03-08 20:12:49 +00:00
Transform2D parent_xform = p_parent_xform ;
Transform2D canvas_xform = p_canvas_xform ;
if ( canvas_item & & ! canvas_item - > is_set_as_toplevel ( ) ) {
parent_xform = parent_xform * canvas_item - > get_transform ( ) ;
} else {
CanvasLayer * cl = Object : : cast_to < CanvasLayer > ( p_node ) ;
parent_xform = Transform2D ( ) ;
canvas_xform = cl ? cl - > get_transform ( ) : p_canvas_xform ;
}
2017-08-28 19:51:56 +00:00
for ( int i = p_node - > get_child_count ( ) - 1 ; i > = 0 ; i - - ) {
2018-03-08 20:12:49 +00:00
_draw_locks_and_groups ( p_node - > get_child ( i ) , parent_xform , canvas_xform ) ;
2017-08-28 19:51:56 +00:00
}
2018-03-08 20:12:49 +00:00
RID viewport_canvas_item = viewport - > get_canvas_item ( ) ;
if ( canvas_item ) {
float offset = 0 ;
2017-08-28 19:51:56 +00:00
2017-09-21 20:55:07 +00:00
Ref < Texture > lock = get_icon ( " LockViewport " , " EditorIcons " ) ;
2018-09-20 00:41:19 +00:00
if ( p_node - > has_meta ( " _edit_lock_ " ) & & show_edit_locks ) {
2018-03-08 20:12:49 +00:00
lock - > draw ( viewport_canvas_item , ( transform * canvas_xform * parent_xform ) . xform ( Point2 ( 0 , 0 ) ) + Point2 ( offset , 0 ) ) ;
offset + = lock - > get_size ( ) . x ;
2017-08-28 19:51:56 +00:00
}
2017-09-21 20:55:07 +00:00
Ref < Texture > group = get_icon ( " GroupViewport " , " EditorIcons " ) ;
2018-09-20 00:41:19 +00:00
if ( canvas_item - > has_meta ( " _edit_group_ " ) & & show_edit_locks ) {
2018-03-08 20:12:49 +00:00
group - > draw ( viewport_canvas_item , ( transform * canvas_xform * parent_xform ) . xform ( Point2 ( 0 , 0 ) ) + Point2 ( offset , 0 ) ) ;
//offset += group->get_size().x;
2017-08-28 19:51:56 +00:00
}
}
}
2018-05-04 19:46:32 +00:00
bool CanvasItemEditor : : _build_bones_list ( Node * p_node ) {
ERR_FAIL_COND_V ( ! p_node , false ) ;
bool has_child_bones = false ;
2017-09-20 19:28:16 +00:00
2017-08-28 19:51:56 +00:00
for ( int i = 0 ; i < p_node - > get_child_count ( ) ; i + + ) {
2018-05-04 19:46:32 +00:00
if ( _build_bones_list ( p_node - > get_child ( i ) ) ) {
has_child_bones = true ;
}
2017-08-28 19:51:56 +00:00
}
2018-05-05 13:45:26 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( p_node ) ;
Node * scene = editor - > get_edited_scene ( ) ;
2021-02-20 09:27:03 +00:00
if ( ! canvas_item | | ! canvas_item - > is_visible ( ) | | ( canvas_item ! = scene & & canvas_item - > get_owner ( ) ! = scene & & canvas_item ! = scene - > get_deepest_editable_node ( canvas_item ) ) ) {
2018-05-04 19:46:32 +00:00
return false ;
2018-05-04 21:11:28 +00:00
}
2018-05-04 19:46:32 +00:00
2018-05-05 13:45:26 +00:00
Node * parent = canvas_item - > get_parent ( ) ;
2018-05-04 19:46:32 +00:00
2018-05-05 13:45:26 +00:00
if ( Object : : cast_to < Bone2D > ( canvas_item ) ) {
if ( Object : : cast_to < Bone2D > ( parent ) ) {
// Add as bone->parent relationship
2018-05-04 19:46:32 +00:00
BoneKey bk ;
2018-05-05 13:45:26 +00:00
bk . from = parent - > get_instance_id ( ) ;
bk . to = canvas_item - > get_instance_id ( ) ;
2018-05-04 19:46:32 +00:00
if ( ! bone_list . has ( bk ) ) {
BoneList b ;
b . length = 0 ;
bone_list [ bk ] = b ;
}
bone_list [ bk ] . last_pass = bone_last_frame ;
}
2017-08-28 19:51:56 +00:00
2018-05-04 19:46:32 +00:00
if ( ! has_child_bones ) {
2018-05-05 13:45:26 +00:00
// Add a last bone if the Bone2D has no Bone2D child
2018-05-04 19:46:32 +00:00
BoneKey bk ;
2018-05-05 13:45:26 +00:00
bk . from = canvas_item - > get_instance_id ( ) ;
2018-05-04 19:46:32 +00:00
bk . to = 0 ;
if ( ! bone_list . has ( bk ) ) {
BoneList b ;
b . length = 0 ;
bone_list [ bk ] = b ;
2017-08-28 19:51:56 +00:00
}
2018-05-04 19:46:32 +00:00
bone_list [ bk ] . last_pass = bone_last_frame ;
}
2017-08-28 19:51:56 +00:00
2018-05-04 19:46:32 +00:00
return true ;
}
2018-05-05 13:45:26 +00:00
if ( canvas_item - > has_meta ( " _edit_bone_ " ) ) {
// Add a "custom bone"
2018-05-04 19:46:32 +00:00
BoneKey bk ;
2018-05-05 13:45:26 +00:00
bk . from = parent - > get_instance_id ( ) ;
bk . to = canvas_item - > get_instance_id ( ) ;
2018-05-04 19:46:32 +00:00
if ( ! bone_list . has ( bk ) ) {
BoneList b ;
b . length = 0 ;
bone_list [ bk ] = b ;
2017-08-28 19:51:56 +00:00
}
2018-05-04 19:46:32 +00:00
bone_list [ bk ] . last_pass = bone_last_frame ;
2017-08-28 19:51:56 +00:00
}
2018-05-04 19:46:32 +00:00
return false ;
2017-08-28 19:51:56 +00:00
}
void CanvasItemEditor : : _draw_viewport ( ) {
2018-03-15 14:12:16 +00:00
// Update the transform
transform = Transform2D ( ) ;
transform . scale_basis ( Size2 ( zoom , zoom ) ) ;
transform . elements [ 2 ] = - view_offset * zoom ;
editor - > get_scene_root ( ) - > set_global_canvas_transform ( transform ) ;
2017-08-30 22:03:03 +00:00
// hide/show buttons depending on the selection
bool all_locked = true ;
bool all_group = true ;
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-08-30 22:03:03 +00:00
if ( selection . empty ( ) ) {
all_locked = false ;
all_group = false ;
} else {
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-09-30 13:30:51 +00:00
if ( Object : : cast_to < CanvasItem > ( E - > get ( ) ) & & ! Object : : cast_to < CanvasItem > ( E - > get ( ) ) - > has_meta ( " _edit_lock_ " ) ) {
2017-08-30 22:03:03 +00:00
all_locked = false ;
break ;
}
}
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-09-30 13:30:51 +00:00
if ( Object : : cast_to < CanvasItem > ( E - > get ( ) ) & & ! Object : : cast_to < CanvasItem > ( E - > get ( ) ) - > has_meta ( " _edit_group_ " ) ) {
2017-08-30 22:03:03 +00:00
all_group = false ;
break ;
}
}
}
lock_button - > set_visible ( ! all_locked ) ;
lock_button - > set_disabled ( selection . empty ( ) ) ;
unlock_button - > set_visible ( all_locked ) ;
group_button - > set_visible ( ! all_group ) ;
group_button - > set_disabled ( selection . empty ( ) ) ;
ungroup_button - > set_visible ( all_group ) ;
2018-10-25 17:08:32 +00:00
info_overlay - > set_margin ( MARGIN_LEFT , ( show_rulers ? RULER_WIDTH : 0 ) + 10 ) ;
2017-08-28 19:51:56 +00:00
_draw_grid ( ) ;
2019-08-30 20:49:47 +00:00
_draw_ruler_tool ( ) ;
2017-08-28 19:51:56 +00:00
_draw_axis ( ) ;
2018-03-10 10:56:27 +00:00
if ( editor - > get_edited_scene ( ) ) {
2018-03-08 20:12:49 +00:00
_draw_locks_and_groups ( editor - > get_edited_scene ( ) ) ;
2018-03-10 10:56:27 +00:00
_draw_invisible_nodes_positions ( editor - > get_edited_scene ( ) ) ;
}
2020-09-27 16:47:38 +00:00
_draw_selection ( ) ;
2017-08-28 19:51:56 +00:00
RID ci = viewport - > get_canvas_item ( ) ;
VisualServer : : get_singleton ( ) - > canvas_item_add_set_transform ( ci , Transform2D ( ) ) ;
EditorPluginList * over_plugin_list = editor - > get_editor_plugins_over ( ) ;
if ( ! over_plugin_list - > empty ( ) ) {
2018-09-18 18:00:07 +00:00
over_plugin_list - > forward_canvas_draw_over_viewport ( viewport ) ;
2017-08-28 19:51:56 +00:00
}
2017-10-29 19:32:09 +00:00
EditorPluginList * force_over_plugin_list = editor - > get_editor_plugins_force_over ( ) ;
if ( ! force_over_plugin_list - > empty ( ) ) {
2018-09-18 18:00:07 +00:00
force_over_plugin_list - > forward_canvas_force_draw_over_viewport ( viewport ) ;
2017-10-29 19:32:09 +00:00
}
2017-10-01 19:00:44 +00:00
_draw_bones ( ) ;
2021-05-05 10:44:11 +00:00
if ( show_rulers ) {
2017-11-07 07:58:35 +00:00
_draw_rulers ( ) ;
2021-05-05 10:44:11 +00:00
}
if ( show_guides ) {
2017-11-07 07:58:35 +00:00
_draw_guides ( ) ;
2021-05-05 10:44:11 +00:00
}
2019-04-05 08:18:21 +00:00
_draw_smart_snapping ( ) ;
2017-11-07 07:58:35 +00:00
_draw_focus ( ) ;
2018-03-12 22:32:25 +00:00
_draw_hover ( ) ;
2017-08-28 19:51:56 +00:00
}
2018-10-18 12:06:57 +00:00
void CanvasItemEditor : : update_viewport ( ) {
_update_scrollbars ( ) ;
viewport - > update ( ) ;
}
2019-08-21 13:34:06 +00:00
void CanvasItemEditor : : set_current_tool ( Tool p_tool ) {
_button_tool_select ( p_tool ) ;
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : _notification ( int p_what ) {
2017-09-30 14:19:07 +00:00
if ( p_what = = NOTIFICATION_PHYSICS_PROCESS ) {
2017-09-07 14:22:07 +00:00
EditorNode : : get_singleton ( ) - > get_scene_root ( ) - > set_snap_controls_to_pixels ( GLOBAL_GET ( " gui/common/snap_controls_to_pixels " ) ) ;
2019-05-30 15:20:27 +00:00
bool has_container_parents = false ;
2017-11-07 07:58:35 +00:00
int nb_control = 0 ;
int nb_having_pivot = 0 ;
2015-08-24 04:00:39 +00:00
2018-05-05 13:45:26 +00:00
// Update the viewport if the canvas_item changes
2019-11-18 20:08:14 +00:00
List < CanvasItem * > selection = _get_edited_canvas_items ( true ) ;
2017-11-07 07:58:35 +00:00
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = E - > get ( ) ;
2017-03-05 15:44:50 +00:00
CanvasItemEditorSelectedItem * se = editor_selection - > get_node_editor_data < CanvasItemEditorSelectedItem > ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
2018-03-08 20:35:41 +00:00
Rect2 rect ;
if ( canvas_item - > _edit_use_rect ( ) ) {
rect = canvas_item - > _edit_get_rect ( ) ;
} else {
rect = Rect2 ( ) ;
}
2017-01-11 03:52:51 +00:00
Transform2D xform = canvas_item - > get_transform ( ) ;
2014-02-10 01:10:30 +00:00
2018-03-08 20:35:41 +00:00
if ( rect ! = se - > prev_rect | | xform ! = se - > prev_xform ) {
2017-09-12 16:44:32 +00:00
viewport - > update ( ) ;
2018-03-08 20:35:41 +00:00
se - > prev_rect = rect ;
2017-09-12 16:44:32 +00:00
se - > prev_xform = xform ;
}
2017-11-07 07:58:35 +00:00
Control * control = Object : : cast_to < Control > ( canvas_item ) ;
if ( control ) {
2017-09-12 16:44:32 +00:00
float anchors [ 4 ] ;
Vector2 pivot ;
2017-11-07 07:58:35 +00:00
pivot = control - > get_pivot_offset ( ) ;
anchors [ MARGIN_LEFT ] = control - > get_anchor ( MARGIN_LEFT ) ;
anchors [ MARGIN_RIGHT ] = control - > get_anchor ( MARGIN_RIGHT ) ;
anchors [ MARGIN_TOP ] = control - > get_anchor ( MARGIN_TOP ) ;
anchors [ MARGIN_BOTTOM ] = control - > get_anchor ( MARGIN_BOTTOM ) ;
2017-07-06 20:42:44 +00:00
2017-09-12 16:44:32 +00:00
if ( pivot ! = se - > prev_pivot | | anchors [ MARGIN_LEFT ] ! = se - > prev_anchors [ MARGIN_LEFT ] | | anchors [ MARGIN_RIGHT ] ! = se - > prev_anchors [ MARGIN_RIGHT ] | | anchors [ MARGIN_TOP ] ! = se - > prev_anchors [ MARGIN_TOP ] | | anchors [ MARGIN_BOTTOM ] ! = se - > prev_anchors [ MARGIN_BOTTOM ] ) {
2017-09-01 20:33:39 +00:00
se - > prev_pivot = pivot ;
se - > prev_anchors [ MARGIN_LEFT ] = anchors [ MARGIN_LEFT ] ;
se - > prev_anchors [ MARGIN_RIGHT ] = anchors [ MARGIN_RIGHT ] ;
se - > prev_anchors [ MARGIN_TOP ] = anchors [ MARGIN_TOP ] ;
se - > prev_anchors [ MARGIN_BOTTOM ] = anchors [ MARGIN_BOTTOM ] ;
2017-11-07 07:58:35 +00:00
viewport - > update ( ) ;
2017-09-01 20:33:39 +00:00
}
2017-11-07 07:58:35 +00:00
nb_control + + ;
2019-05-30 15:20:27 +00:00
if ( Object : : cast_to < Container > ( control - > get_parent ( ) ) ) {
has_container_parents = true ;
}
2017-11-07 07:58:35 +00:00
}
if ( canvas_item - > _edit_use_pivot ( ) ) {
nb_having_pivot + + ;
2014-02-10 01:10:30 +00:00
}
}
2018-05-05 13:45:26 +00:00
2017-11-07 07:58:35 +00:00
// Activate / Deactivate the pivot tool
pivot_button - > set_disabled ( nb_having_pivot = = 0 ) ;
2014-02-10 01:10:30 +00:00
2019-03-31 16:53:24 +00:00
// Show / Hide the layout and anchors mode buttons
2019-01-27 15:36:10 +00:00
if ( nb_control > 0 & & nb_control = = selection . size ( ) ) {
presets_menu - > set_visible ( true ) ;
2019-03-31 16:53:24 +00:00
anchor_mode_button - > set_visible ( true ) ;
2019-01-27 15:36:10 +00:00
// Disable if the selected node is child of a container
2019-05-30 15:20:27 +00:00
if ( has_container_parents ) {
presets_menu - > set_disabled ( true ) ;
presets_menu - > set_tooltip ( TTR ( " Children of containers have their anchors and margins values overridden by their parent. " ) ) ;
anchor_mode_button - > set_disabled ( true ) ;
anchor_mode_button - > set_tooltip ( TTR ( " Children of containers have their anchors and margins values overridden by their parent. " ) ) ;
} else {
presets_menu - > set_disabled ( false ) ;
presets_menu - > set_tooltip ( TTR ( " Presets for the anchors and margins values of a Control node. " ) ) ;
anchor_mode_button - > set_disabled ( false ) ;
anchor_mode_button - > set_tooltip ( TTR ( " When active, moving Control nodes changes their anchors instead of their margins. " ) ) ;
2019-01-27 15:36:10 +00:00
}
} else {
presets_menu - > set_visible ( false ) ;
2019-03-31 16:53:24 +00:00
anchor_mode_button - > set_visible ( false ) ;
2019-01-27 15:36:10 +00:00
}
2015-04-20 22:38:02 +00:00
2018-05-05 13:45:26 +00:00
// Update the viewport if bones changes
2018-05-04 19:46:32 +00:00
for ( Map < BoneKey , BoneList > : : Element * E = bone_list . front ( ) ; E ; E = E - > next ( ) ) {
Object * b = ObjectDB : : get_instance ( E - > key ( ) . from ) ;
2014-07-07 20:44:21 +00:00
if ( ! b ) {
viewport - > update ( ) ;
break ;
}
2017-08-24 20:58:51 +00:00
Node2D * b2 = Object : : cast_to < Node2D > ( b ) ;
2018-05-05 13:45:26 +00:00
if ( ! b2 | | ! b2 - > is_inside_tree ( ) ) {
2014-07-07 20:44:21 +00:00
continue ;
}
2018-05-04 19:46:32 +00:00
Transform2D global_xform = b2 - > get_global_transform ( ) ;
if ( global_xform ! = E - > get ( ) . xform ) {
E - > get ( ) . xform = global_xform ;
viewport - > update ( ) ;
}
Bone2D * bone = Object : : cast_to < Bone2D > ( b ) ;
if ( bone & & bone - > get_default_length ( ) ! = E - > get ( ) . length ) {
E - > get ( ) . length = bone - > get_default_length ( ) ;
2014-07-07 20:44:21 +00:00
viewport - > update ( ) ;
}
}
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
if ( p_what = = NOTIFICATION_ENTER_TREE ) {
select_sb - > set_texture ( get_icon ( " EditorRect2D " , " EditorIcons " ) ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
select_sb - > set_margin_size ( Margin ( i ) , 4 ) ;
select_sb - > set_default_margin ( Margin ( i ) , 4 ) ;
2014-02-10 01:10:30 +00:00
}
2018-06-07 15:46:14 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > connect ( " visibility_changed " , this , " _keying_changed " ) ;
2016-02-09 19:09:29 +00:00
_keying_changed ( ) ;
2018-05-04 21:11:28 +00:00
get_tree ( ) - > connect ( " node_added " , this , " _tree_changed " , varray ( ) ) ;
get_tree ( ) - > connect ( " node_removed " , this , " _tree_changed " , varray ( ) ) ;
2017-10-03 22:47:40 +00:00
2017-08-29 23:03:13 +00:00
} else if ( p_what = = EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED ) {
select_sb - > set_texture ( get_icon ( " EditorRect2D " , " EditorIcons " ) ) ;
2017-10-03 22:47:40 +00:00
}
2017-08-29 23:03:13 +00:00
2018-05-04 21:11:28 +00:00
if ( p_what = = NOTIFICATION_EXIT_TREE ) {
get_tree ( ) - > disconnect ( " node_added " , this , " _tree_changed " ) ;
get_tree ( ) - > disconnect ( " node_removed " , this , " _tree_changed " ) ;
}
2017-10-03 22:47:40 +00:00
if ( p_what = = NOTIFICATION_ENTER_TREE | | p_what = = EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED ) {
2017-08-29 23:03:13 +00:00
select_button - > set_icon ( get_icon ( " ToolSelect " , " EditorIcons " ) ) ;
list_select_button - > set_icon ( get_icon ( " ListSelect " , " EditorIcons " ) ) ;
move_button - > set_icon ( get_icon ( " ToolMove " , " EditorIcons " ) ) ;
2018-09-10 12:39:46 +00:00
scale_button - > set_icon ( get_icon ( " ToolScale " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
rotate_button - > set_icon ( get_icon ( " ToolRotate " , " EditorIcons " ) ) ;
2019-10-10 17:41:45 +00:00
smart_snap_button - > set_icon ( get_icon ( " Snap " , " EditorIcons " ) ) ;
grid_snap_button - > set_icon ( get_icon ( " SnapGrid " , " EditorIcons " ) ) ;
2020-07-11 15:32:27 +00:00
snap_config_menu - > set_icon ( get_icon ( " GuiTabMenuHl " , " EditorIcons " ) ) ;
2017-09-17 20:52:41 +00:00
skeleton_menu - > set_icon ( get_icon ( " Bone " , " EditorIcons " ) ) ;
2019-04-06 20:55:01 +00:00
override_camera_button - > set_icon ( get_icon ( " Camera2D " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
pan_button - > set_icon ( get_icon ( " ToolPan " , " EditorIcons " ) ) ;
2019-09-02 14:45:03 +00:00
ruler_button - > set_icon ( get_icon ( " Ruler " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
pivot_button - > set_icon ( get_icon ( " EditPivot " , " EditorIcons " ) ) ;
select_handle = get_icon ( " EditorHandle " , " EditorIcons " ) ;
anchor_handle = get_icon ( " EditorControlAnchor " , " EditorIcons " ) ;
lock_button - > set_icon ( get_icon ( " Lock " , " EditorIcons " ) ) ;
unlock_button - > set_icon ( get_icon ( " Unlock " , " EditorIcons " ) ) ;
group_button - > set_icon ( get_icon ( " Group " , " EditorIcons " ) ) ;
ungroup_button - > set_icon ( get_icon ( " Ungroup " , " EditorIcons " ) ) ;
2017-10-12 18:59:25 +00:00
key_loc_button - > set_icon ( get_icon ( " KeyPosition " , " EditorIcons " ) ) ;
key_rot_button - > set_icon ( get_icon ( " KeyRotation " , " EditorIcons " ) ) ;
key_scale_button - > set_icon ( get_icon ( " KeyScale " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
key_insert_button - > set_icon ( get_icon ( " Key " , " EditorIcons " ) ) ;
2019-04-15 03:49:03 +00:00
key_auto_insert_button - > set_icon ( get_icon ( " AutoKey " , " EditorIcons " ) ) ;
2020-09-29 21:22:21 +00:00
// Use a different color for the active autokey icon to make them easier
// to distinguish from the other key icons at the top. On a light theme,
// the icon will be dark, so we need to lighten it before blending it
// with the red color.
const Color key_auto_color = EditorSettings : : get_singleton ( ) - > is_dark_theme ( ) ? Color ( 1 , 1 , 1 ) : Color ( 4.25 , 4.25 , 4.25 ) ;
key_auto_insert_button - > add_color_override ( " icon_color_pressed " , key_auto_color . linear_interpolate ( Color ( 1 , 0 , 0 ) , 0.55 ) ) ;
2020-07-11 15:32:27 +00:00
animation_menu - > set_icon ( get_icon ( " GuiTabMenuHl " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
2017-10-03 22:47:40 +00:00
zoom_minus - > set_icon ( get_icon ( " ZoomLess " , " EditorIcons " ) ) ;
zoom_plus - > set_icon ( get_icon ( " ZoomMore " , " EditorIcons " ) ) ;
2017-08-29 23:03:13 +00:00
2021-07-30 22:21:56 +00:00
_update_context_menu_stylebox ( ) ;
2017-10-13 21:39:17 +00:00
presets_menu - > set_icon ( get_icon ( " ControlLayout " , " EditorIcons " ) ) ;
2021-07-30 22:21:56 +00:00
2017-10-03 22:47:40 +00:00
PopupMenu * p = presets_menu - > get_popup ( ) ;
p - > clear ( ) ;
2019-12-16 05:18:44 +00:00
p - > add_icon_item ( get_icon ( " ControlAlignTopLeft " , " EditorIcons " ) , TTR ( " Top Left " ) , ANCHORS_AND_MARGINS_PRESET_TOP_LEFT ) ;
p - > add_icon_item ( get_icon ( " ControlAlignTopRight " , " EditorIcons " ) , TTR ( " Top Right " ) , ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT ) ;
p - > add_icon_item ( get_icon ( " ControlAlignBottomRight " , " EditorIcons " ) , TTR ( " Bottom Right " ) , ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT ) ;
p - > add_icon_item ( get_icon ( " ControlAlignBottomLeft " , " EditorIcons " ) , TTR ( " Bottom Left " ) , ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT ) ;
2017-08-29 23:03:13 +00:00
p - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
p - > add_icon_item ( get_icon ( " ControlAlignLeftCenter " , " EditorIcons " ) , TTR ( " Center Left " ) , ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT ) ;
p - > add_icon_item ( get_icon ( " ControlAlignTopCenter " , " EditorIcons " ) , TTR ( " Center Top " ) , ANCHORS_AND_MARGINS_PRESET_CENTER_TOP ) ;
p - > add_icon_item ( get_icon ( " ControlAlignRightCenter " , " EditorIcons " ) , TTR ( " Center Right " ) , ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT ) ;
p - > add_icon_item ( get_icon ( " ControlAlignBottomCenter " , " EditorIcons " ) , TTR ( " Center Bottom " ) , ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM ) ;
p - > add_icon_item ( get_icon ( " ControlAlignCenter " , " EditorIcons " ) , TTR ( " Center " ) , ANCHORS_AND_MARGINS_PRESET_CENTER ) ;
2017-08-29 23:03:13 +00:00
p - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
p - > add_icon_item ( get_icon ( " ControlAlignLeftWide " , " EditorIcons " ) , TTR ( " Left Wide " ) , ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE ) ;
p - > add_icon_item ( get_icon ( " ControlAlignTopWide " , " EditorIcons " ) , TTR ( " Top Wide " ) , ANCHORS_AND_MARGINS_PRESET_TOP_WIDE ) ;
p - > add_icon_item ( get_icon ( " ControlAlignRightWide " , " EditorIcons " ) , TTR ( " Right Wide " ) , ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE ) ;
p - > add_icon_item ( get_icon ( " ControlAlignBottomWide " , " EditorIcons " ) , TTR ( " Bottom Wide " ) , ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE ) ;
p - > add_icon_item ( get_icon ( " ControlVcenterWide " , " EditorIcons " ) , TTR ( " VCenter Wide " ) , ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE ) ;
p - > add_icon_item ( get_icon ( " ControlHcenterWide " , " EditorIcons " ) , TTR ( " HCenter Wide " ) , ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE ) ;
2017-08-29 23:03:13 +00:00
p - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
p - > add_icon_item ( get_icon ( " ControlAlignWide " , " EditorIcons " ) , TTR ( " Full Rect " ) , ANCHORS_AND_MARGINS_PRESET_WIDE ) ;
p - > add_icon_item ( get_icon ( " Anchor " , " EditorIcons " ) , TTR ( " Keep Ratio " ) , ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO ) ;
2017-10-03 22:47:40 +00:00
p - > add_separator ( ) ;
2019-03-31 16:53:24 +00:00
p - > add_submenu_item ( TTR ( " Anchors only " ) , " Anchors " ) ;
p - > set_item_icon ( 21 , get_icon ( " Anchor " , " EditorIcons " ) ) ;
2017-10-03 22:47:40 +00:00
anchors_popup - > clear ( ) ;
2019-12-16 05:18:44 +00:00
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignTopLeft " , " EditorIcons " ) , TTR ( " Top Left " ) , ANCHORS_PRESET_TOP_LEFT ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignTopRight " , " EditorIcons " ) , TTR ( " Top Right " ) , ANCHORS_PRESET_TOP_RIGHT ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignBottomRight " , " EditorIcons " ) , TTR ( " Bottom Right " ) , ANCHORS_PRESET_BOTTOM_RIGHT ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignBottomLeft " , " EditorIcons " ) , TTR ( " Bottom Left " ) , ANCHORS_PRESET_BOTTOM_LEFT ) ;
2017-10-03 22:47:40 +00:00
anchors_popup - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignLeftCenter " , " EditorIcons " ) , TTR ( " Center Left " ) , ANCHORS_PRESET_CENTER_LEFT ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignTopCenter " , " EditorIcons " ) , TTR ( " Center Top " ) , ANCHORS_PRESET_CENTER_TOP ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignRightCenter " , " EditorIcons " ) , TTR ( " Center Right " ) , ANCHORS_PRESET_CENTER_RIGHT ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignBottomCenter " , " EditorIcons " ) , TTR ( " Center Bottom " ) , ANCHORS_PRESET_CENTER_BOTTOM ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignCenter " , " EditorIcons " ) , TTR ( " Center " ) , ANCHORS_PRESET_CENTER ) ;
2017-10-03 22:47:40 +00:00
anchors_popup - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignLeftWide " , " EditorIcons " ) , TTR ( " Left Wide " ) , ANCHORS_PRESET_LEFT_WIDE ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignTopWide " , " EditorIcons " ) , TTR ( " Top Wide " ) , ANCHORS_PRESET_TOP_WIDE ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignRightWide " , " EditorIcons " ) , TTR ( " Right Wide " ) , ANCHORS_PRESET_RIGHT_WIDE ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignBottomWide " , " EditorIcons " ) , TTR ( " Bottom Wide " ) , ANCHORS_PRESET_BOTTOM_WIDE ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlVcenterWide " , " EditorIcons " ) , TTR ( " VCenter Wide " ) , ANCHORS_PRESET_VCENTER_WIDE ) ;
anchors_popup - > add_icon_item ( get_icon ( " ControlHcenterWide " , " EditorIcons " ) , TTR ( " HCenter Wide " ) , ANCHORS_PRESET_HCENTER_WIDE ) ;
2017-10-03 22:47:40 +00:00
anchors_popup - > add_separator ( ) ;
2019-12-16 05:18:44 +00:00
anchors_popup - > add_icon_item ( get_icon ( " ControlAlignWide " , " EditorIcons " ) , TTR ( " Full Rect " ) , ANCHORS_PRESET_WIDE ) ;
2019-03-31 16:53:24 +00:00
anchor_mode_button - > set_icon ( get_icon ( " Anchor " , " EditorIcons " ) ) ;
2021-06-03 09:32:06 +00:00
Ref < DynamicFont > font = zoom_reset - > get_font ( " font " ) - > duplicate ( false ) ;
font - > set_outline_size ( 1 ) ;
font - > set_outline_color ( Color ( 0 , 0 , 0 ) ) ;
zoom_reset - > add_font_override ( " font " , font ) ;
zoom_reset - > add_color_override ( " font_color " , Color ( 1 , 1 , 1 ) ) ;
2021-08-13 22:06:21 +00:00
info_overlay - > get_theme ( ) - > set_stylebox ( " normal " , " Label " , get_stylebox ( " CanvasItemInfoOverlay " , " EditorStyles " ) ) ;
warning_child_of_container - > add_color_override ( " font_color " , get_color ( " warning_color " , " Editor " ) ) ;
warning_child_of_container - > add_font_override ( " font " , get_font ( " main " , " EditorFonts " ) ) ;
2014-02-10 01:10:30 +00:00
}
2019-04-06 20:55:01 +00:00
if ( p_what = = NOTIFICATION_VISIBILITY_CHANGED ) {
if ( ! is_visible ( ) & & override_camera_button - > is_pressed ( ) ) {
ScriptEditorDebugger * debugger = ScriptEditor : : get_singleton ( ) - > get_debugger ( ) ;
debugger - > set_camera_override ( ScriptEditorDebugger : : OVERRIDE_NONE ) ;
override_camera_button - > set_pressed ( false ) ;
}
}
2014-02-10 01:10:30 +00:00
}
2019-03-31 16:53:24 +00:00
void CanvasItemEditor : : _selection_changed ( ) {
// Update the anchors_mode
int nbValidControls = 0 ;
int nbAnchorsMode = 0 ;
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Control * control = Object : : cast_to < Control > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! control ) {
2019-03-31 16:53:24 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( Object : : cast_to < Container > ( control - > get_parent ( ) ) ) {
2019-03-31 16:53:24 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2019-03-31 16:53:24 +00:00
nbValidControls + + ;
if ( control - > has_meta ( " _edit_use_anchors_ " ) & & control - > get_meta ( " _edit_use_anchors_ " ) ) {
nbAnchorsMode + + ;
}
}
anchors_mode = ( nbValidControls = = nbAnchorsMode ) ;
2019-06-04 19:58:21 +00:00
anchor_mode_button - > set_pressed ( anchors_mode ) ;
2019-11-19 15:02:04 +00:00
if ( ! selected_from_canvas ) {
drag_type = DRAG_NONE ;
}
selected_from_canvas = false ;
2019-03-31 16:53:24 +00:00
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : edit ( CanvasItem * p_canvas_item ) {
2018-10-16 18:35:51 +00:00
Array selection = editor_selection - > get_selected_nodes ( ) ;
if ( selection . size ( ) ! = 1 | | ( Node * ) selection [ 0 ] ! = p_canvas_item ) {
drag_type = DRAG_NONE ;
2014-02-10 01:10:30 +00:00
2018-10-16 18:35:51 +00:00
// Clear the selection
editor_selection - > clear ( ) ; //_clear_canvas_items();
editor_selection - > add_node ( p_canvas_item ) ;
}
2014-02-10 01:10:30 +00:00
}
2018-05-04 21:11:28 +00:00
void CanvasItemEditor : : _queue_update_bone_list ( ) {
2021-05-05 10:44:11 +00:00
if ( bone_list_dirty ) {
2018-05-04 21:11:28 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2018-05-04 21:11:28 +00:00
call_deferred ( " _update_bone_list " ) ;
bone_list_dirty = true ;
}
void CanvasItemEditor : : _update_bone_list ( ) {
bone_last_frame + + ;
if ( editor - > get_edited_scene ( ) ) {
_build_bones_list ( editor - > get_edited_scene ( ) ) ;
}
List < Map < BoneKey , BoneList > : : Element * > bone_to_erase ;
for ( Map < BoneKey , BoneList > : : Element * E = bone_list . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . last_pass ! = bone_last_frame ) {
bone_to_erase . push_back ( E ) ;
continue ;
}
Node * node = Object : : cast_to < Node > ( ObjectDB : : get_instance ( E - > key ( ) . from ) ) ;
if ( ! node | | ! node - > is_inside_tree ( ) | | ( node ! = get_tree ( ) - > get_edited_scene_root ( ) & & ! get_tree ( ) - > get_edited_scene_root ( ) - > is_a_parent_of ( node ) ) ) {
bone_to_erase . push_back ( E ) ;
continue ;
}
}
while ( bone_to_erase . size ( ) ) {
bone_list . erase ( bone_to_erase . front ( ) - > get ( ) ) ;
bone_to_erase . pop_front ( ) ;
}
bone_list_dirty = false ;
}
void CanvasItemEditor : : _tree_changed ( Node * ) {
_queue_update_bone_list ( ) ;
}
2021-07-30 22:21:56 +00:00
void CanvasItemEditor : : _update_context_menu_stylebox ( ) {
// This must be called when the theme changes to follow the new accent color.
Ref < StyleBoxFlat > context_menu_stylebox = memnew ( StyleBoxFlat ) ;
const Color accent_color = EditorNode : : get_singleton ( ) - > get_gui_base ( ) - > get_color ( " accent_color " , " Editor " ) ;
context_menu_stylebox - > set_bg_color ( accent_color * Color ( 1 , 1 , 1 , 0.1 ) ) ;
// Add an underline to the StyleBox, but prevent its minimum vertical size from changing.
context_menu_stylebox - > set_border_color ( accent_color ) ;
context_menu_stylebox - > set_border_width ( MARGIN_BOTTOM , Math : : round ( 2 * EDSCALE ) ) ;
context_menu_stylebox - > set_default_margin ( MARGIN_BOTTOM , 0 ) ;
context_menu_container - > add_style_override ( " panel " , context_menu_stylebox ) ;
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : _update_scrollbars ( ) {
2017-03-05 15:44:50 +00:00
updating_scroll = true ;
2014-02-10 01:10:30 +00:00
2020-01-14 01:49:17 +00:00
// Move the zoom buttons.
2019-11-18 09:49:37 +00:00
Point2 controls_vb_begin = Point2 ( 5 , 5 ) ;
controls_vb_begin + = ( show_rulers ) ? Point2 ( RULER_WIDTH , RULER_WIDTH ) : Point2 ( ) ;
controls_vb - > set_begin ( controls_vb_begin ) ;
2017-08-29 19:50:18 +00:00
2014-02-10 01:10:30 +00:00
Size2 hmin = h_scroll - > get_minimum_size ( ) ;
Size2 vmin = v_scroll - > get_minimum_size ( ) ;
2020-01-14 01:49:17 +00:00
// Get the visible frame.
2017-07-19 20:00:46 +00:00
Size2 screen_rect = Size2 ( ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/width " ) , ProjectSettings : : get_singleton ( ) - > get ( " display/window/size/height " ) ) ;
2017-03-05 15:44:50 +00:00
Rect2 local_rect = Rect2 ( Point2 ( ) , viewport - > get_size ( ) - Size2 ( vmin . width , hmin . height ) ) ;
2014-02-10 01:10:30 +00:00
2018-05-04 21:11:28 +00:00
_queue_update_bone_list ( ) ;
2014-02-10 01:10:30 +00:00
2020-01-14 01:49:17 +00:00
// Calculate scrollable area.
2017-11-07 07:58:35 +00:00
Rect2 canvas_item_rect = Rect2 ( Point2 ( ) , screen_rect ) ;
if ( editor - > get_edited_scene ( ) ) {
2018-03-08 20:35:41 +00:00
Rect2 content_rect = _get_encompassing_rect ( editor - > get_edited_scene ( ) ) ;
2017-11-07 07:58:35 +00:00
canvas_item_rect . expand_to ( content_rect . position ) ;
canvas_item_rect . expand_to ( content_rect . position + content_rect . size ) ;
}
2017-03-05 15:44:50 +00:00
canvas_item_rect . size + = screen_rect * 2 ;
2017-06-03 22:25:13 +00:00
canvas_item_rect . position - = screen_rect ;
2014-02-10 01:10:30 +00:00
2020-01-14 01:49:17 +00:00
// Constraints the view offset and updates the scrollbars.
Size2 size = viewport - > get_size ( ) ;
2018-03-15 14:12:16 +00:00
Point2 begin = canvas_item_rect . position ;
Point2 end = canvas_item_rect . position + canvas_item_rect . size - local_rect . size / zoom ;
2019-06-24 19:15:26 +00:00
bool constrain_editor_view = bool ( EditorSettings : : get_singleton ( ) - > get ( " editors/2d/constrain_editor_view " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
if ( canvas_item_rect . size . height < = ( local_rect . size . y / zoom ) ) {
2019-06-26 21:03:02 +00:00
float centered = - ( size . y / 2 ) / zoom + screen_rect . y / 2 ;
if ( constrain_editor_view & & ABS ( centered - previous_update_view_offset . y ) < ABS ( centered - view_offset . y ) ) {
2018-03-15 14:12:16 +00:00
view_offset . y = previous_update_view_offset . y ;
}
2014-02-10 01:10:30 +00:00
v_scroll - > hide ( ) ;
} else {
2019-06-24 19:15:26 +00:00
if ( constrain_editor_view & & view_offset . y > end . y & & view_offset . y > previous_update_view_offset . y ) {
2018-03-15 14:12:16 +00:00
view_offset . y = MAX ( end . y , previous_update_view_offset . y ) ;
}
2019-06-24 19:15:26 +00:00
if ( constrain_editor_view & & view_offset . y < begin . y & & view_offset . y < previous_update_view_offset . y ) {
2018-03-15 14:12:16 +00:00
view_offset . y = MIN ( begin . y , previous_update_view_offset . y ) ;
2014-02-10 01:10:30 +00:00
}
2018-03-15 14:12:16 +00:00
v_scroll - > show ( ) ;
v_scroll - > set_min ( MIN ( view_offset . y , begin . y ) ) ;
v_scroll - > set_max ( MAX ( view_offset . y , end . y ) + screen_rect . y ) ;
v_scroll - > set_page ( screen_rect . y ) ;
2014-02-10 01:10:30 +00:00
}
2017-03-05 15:44:50 +00:00
if ( canvas_item_rect . size . width < = ( local_rect . size . x / zoom ) ) {
2019-06-26 21:03:02 +00:00
float centered = - ( size . x / 2 ) / zoom + screen_rect . x / 2 ;
if ( constrain_editor_view & & ABS ( centered - previous_update_view_offset . x ) < ABS ( centered - view_offset . x ) ) {
2018-03-15 14:12:16 +00:00
view_offset . x = previous_update_view_offset . x ;
}
2014-02-10 01:10:30 +00:00
h_scroll - > hide ( ) ;
} else {
2019-06-24 19:15:26 +00:00
if ( constrain_editor_view & & view_offset . x > end . x & & view_offset . x > previous_update_view_offset . x ) {
2018-03-15 14:12:16 +00:00
view_offset . x = MAX ( end . x , previous_update_view_offset . x ) ;
}
2019-06-24 19:15:26 +00:00
if ( constrain_editor_view & & view_offset . x < begin . x & & view_offset . x < previous_update_view_offset . x ) {
2018-03-15 14:12:16 +00:00
view_offset . x = MIN ( begin . x , previous_update_view_offset . x ) ;
}
2014-02-10 01:10:30 +00:00
h_scroll - > show ( ) ;
2018-03-15 14:12:16 +00:00
h_scroll - > set_min ( MIN ( view_offset . x , begin . x ) ) ;
h_scroll - > set_max ( MAX ( view_offset . x , end . x ) + screen_rect . x ) ;
h_scroll - > set_page ( screen_rect . x ) ;
2014-02-10 01:10:30 +00:00
}
2020-01-14 01:49:17 +00:00
// Move and resize the scrollbars, avoiding overlap.
v_scroll - > set_begin ( Point2 ( size . width - vmin . width , ( show_rulers ) ? RULER_WIDTH : 0 ) ) ;
v_scroll - > set_end ( Point2 ( size . width , size . height - ( h_scroll - > is_visible ( ) ? hmin . height : 0 ) ) ) ;
h_scroll - > set_begin ( Point2 ( ( show_rulers ) ? RULER_WIDTH : 0 , size . height - hmin . height ) ) ;
h_scroll - > set_end ( Point2 ( size . width - ( v_scroll - > is_visible ( ) ? vmin . width : 0 ) , size . height ) ) ;
// Calculate scrollable area.
2018-03-15 14:12:16 +00:00
v_scroll - > set_value ( view_offset . y ) ;
h_scroll - > set_value ( view_offset . x ) ;
2014-02-10 01:10:30 +00:00
2018-03-15 14:12:16 +00:00
previous_update_view_offset = view_offset ;
2017-03-05 15:44:50 +00:00
updating_scroll = false ;
2014-02-10 01:10:30 +00:00
}
2018-10-25 17:08:32 +00:00
void CanvasItemEditor : : _popup_warning_depop ( Control * p_control ) {
ERR_FAIL_COND ( ! popup_temporarily_timers . has ( p_control ) ) ;
Timer * timer = popup_temporarily_timers [ p_control ] ;
2019-12-18 14:54:13 +00:00
timer - > queue_delete ( ) ;
2018-10-25 17:08:32 +00:00
p_control - > hide ( ) ;
popup_temporarily_timers . erase ( p_control ) ;
info_overlay - > set_margin ( MARGIN_LEFT , ( show_rulers ? RULER_WIDTH : 0 ) + 10 ) ;
}
void CanvasItemEditor : : _popup_warning_temporarily ( Control * p_control , const float p_duration ) {
Timer * timer ;
if ( ! popup_temporarily_timers . has ( p_control ) ) {
timer = memnew ( Timer ) ;
timer - > connect ( " timeout " , this , " _popup_warning_depop " , varray ( p_control ) ) ;
timer - > set_one_shot ( true ) ;
add_child ( timer ) ;
popup_temporarily_timers [ p_control ] = timer ;
} else {
timer = popup_temporarily_timers [ p_control ] ;
}
timer - > start ( p_duration ) ;
p_control - > show ( ) ;
info_overlay - > set_margin ( MARGIN_LEFT , ( show_rulers ? RULER_WIDTH : 0 ) + 10 ) ;
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : _update_scroll ( float ) {
2021-05-05 10:44:11 +00:00
if ( updating_scroll ) {
2014-02-10 01:10:30 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2018-03-15 14:12:16 +00:00
view_offset . x = h_scroll - > get_value ( ) ;
view_offset . y = v_scroll - > get_value ( ) ;
2014-02-10 01:10:30 +00:00
viewport - > update ( ) ;
}
2017-10-03 22:47:40 +00:00
void CanvasItemEditor : : _set_anchors_and_margins_preset ( Control : : LayoutPreset p_preset ) {
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2015-08-24 04:00:39 +00:00
2017-10-03 22:47:40 +00:00
undo_redo - > create_action ( TTR ( " Change Anchors and Margins " ) ) ;
2017-11-07 07:58:35 +00:00
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-11-07 07:58:35 +00:00
Control * control = Object : : cast_to < Control > ( E - > get ( ) ) ;
if ( control ) {
undo_redo - > add_do_method ( control , " set_anchors_preset " , p_preset ) ;
switch ( p_preset ) {
case PRESET_TOP_LEFT :
case PRESET_TOP_RIGHT :
case PRESET_BOTTOM_LEFT :
case PRESET_BOTTOM_RIGHT :
case PRESET_CENTER_LEFT :
case PRESET_CENTER_TOP :
case PRESET_CENTER_RIGHT :
case PRESET_CENTER_BOTTOM :
case PRESET_CENTER :
undo_redo - > add_do_method ( control , " set_margins_preset " , p_preset , Control : : PRESET_MODE_KEEP_SIZE ) ;
break ;
case PRESET_LEFT_WIDE :
case PRESET_TOP_WIDE :
case PRESET_RIGHT_WIDE :
case PRESET_BOTTOM_WIDE :
case PRESET_VCENTER_WIDE :
case PRESET_HCENTER_WIDE :
case PRESET_WIDE :
undo_redo - > add_do_method ( control , " set_margins_preset " , p_preset , Control : : PRESET_MODE_MINSIZE ) ;
break ;
}
undo_redo - > add_undo_method ( control , " _edit_set_state " , control - > _edit_get_state ( ) ) ;
2017-10-03 22:47:40 +00:00
}
2015-08-24 04:00:39 +00:00
}
undo_redo - > commit_action ( ) ;
2019-03-31 16:53:24 +00:00
anchors_mode = false ;
2019-06-04 19:58:21 +00:00
anchor_mode_button - > set_pressed ( anchors_mode ) ;
2019-03-31 16:53:24 +00:00
}
void CanvasItemEditor : : _set_anchors_and_margins_to_keep_ratio ( ) {
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
undo_redo - > create_action ( TTR ( " Change Anchors and Margins " ) ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Control * control = Object : : cast_to < Control > ( E - > get ( ) ) ;
if ( control ) {
Point2 top_left_anchor = _position_to_anchor ( control , Point2 ( ) ) ;
Point2 bottom_right_anchor = _position_to_anchor ( control , control - > get_size ( ) ) ;
undo_redo - > add_do_method ( control , " set_anchor " , MARGIN_LEFT , top_left_anchor . x , false , true ) ;
undo_redo - > add_do_method ( control , " set_anchor " , MARGIN_RIGHT , bottom_right_anchor . x , false , true ) ;
undo_redo - > add_do_method ( control , " set_anchor " , MARGIN_TOP , top_left_anchor . y , false , true ) ;
undo_redo - > add_do_method ( control , " set_anchor " , MARGIN_BOTTOM , bottom_right_anchor . y , false , true ) ;
undo_redo - > add_do_method ( control , " set_meta " , " _edit_use_anchors_ " , true ) ;
bool use_anchors = control - > has_meta ( " _edit_use_anchors_ " ) & & control - > get_meta ( " _edit_use_anchors_ " ) ;
undo_redo - > add_undo_method ( control , " _edit_set_state " , control - > _edit_get_state ( ) ) ;
undo_redo - > add_undo_method ( control , " set_meta " , " _edit_use_anchors_ " , use_anchors ) ;
anchors_mode = true ;
2019-06-04 19:58:21 +00:00
anchor_mode_button - > set_pressed ( anchors_mode ) ;
2019-03-31 16:53:24 +00:00
}
}
undo_redo - > commit_action ( ) ;
2015-08-24 04:00:39 +00:00
}
2014-02-10 01:10:30 +00:00
2017-10-03 22:47:40 +00:00
void CanvasItemEditor : : _set_anchors_preset ( Control : : LayoutPreset p_preset ) {
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-07-09 13:54:49 +00:00
undo_redo - > create_action ( TTR ( " Change Anchors " ) ) ;
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-11-07 07:58:35 +00:00
Control * control = Object : : cast_to < Control > ( E - > get ( ) ) ;
if ( control ) {
undo_redo - > add_do_method ( control , " set_anchors_preset " , p_preset ) ;
undo_redo - > add_undo_method ( control , " _edit_set_state " , control - > _edit_get_state ( ) ) ;
}
2017-07-09 13:54:49 +00:00
}
undo_redo - > commit_action ( ) ;
}
2021-04-27 22:54:59 +00:00
float CanvasItemEditor : : _get_next_zoom_value ( int p_increment_count , bool p_integer_only ) const {
// Remove editor scale from the index computation.
const float zoom_noscale = zoom / MAX ( 1 , EDSCALE ) ;
if ( p_integer_only ) {
// Only visit integer scaling factors above 100%, and fractions with an integer denominator below 100%
// (1/2 = 50%, 1/3 = 33.33%, 1/4 = 25%, …).
// This is useful when working on pixel art projects to avoid distortion.
// This algorithm is designed to handle fractional start zoom values correctly
// (e.g. 190% will zoom up to 200% and down to 100%).
if ( zoom_noscale + p_increment_count * 0.001 > = 1.0 - CMP_EPSILON ) {
// New zoom is certain to be above 100%.
if ( p_increment_count > = 1 ) {
// Zooming.
return Math : : floor ( zoom_noscale + p_increment_count ) * MAX ( 1 , EDSCALE ) ;
} else {
// Dezooming.
return Math : : ceil ( zoom_noscale + p_increment_count ) * MAX ( 1 , EDSCALE ) ;
}
} else {
if ( p_increment_count > = 1 ) {
// Zooming. Convert the current zoom into a denominator.
float new_zoom = 1.0 / Math : : ceil ( 1.0 / zoom_noscale - p_increment_count ) ;
if ( Math : : is_equal_approx ( zoom_noscale , new_zoom ) ) {
// New zoom is identical to the old zoom, so try again.
// This can happen due to floating-point precision issues.
new_zoom = 1.0 / Math : : ceil ( 1.0 / zoom_noscale - p_increment_count - 1 ) ;
}
return new_zoom * MAX ( 1 , EDSCALE ) ;
} else {
// Dezooming. Convert the current zoom into a denominator.
float new_zoom = 1.0 / Math : : floor ( 1.0 / zoom_noscale - p_increment_count ) ;
if ( Math : : is_equal_approx ( zoom_noscale , new_zoom ) ) {
// New zoom is identical to the old zoom, so try again.
// This can happen due to floating-point precision issues.
new_zoom = 1.0 / Math : : floor ( 1.0 / zoom_noscale - p_increment_count + 1 ) ;
}
return new_zoom * MAX ( 1 , EDSCALE ) ;
}
}
} else {
// Base increment factor defined as the twelveth root of two.
// This allow a smooth geometric evolution of the zoom, with the advantage of
// visiting all integer power of two scale factors.
// note: this is analogous to the 'semitones' interval in the music world
// In order to avoid numerical imprecisions, we compute and edit a zoom index
// with the following relation: zoom = 2 ^ (index / 12)
2020-03-15 18:13:07 +00:00
2021-04-27 22:54:59 +00:00
if ( zoom < CMP_EPSILON | | p_increment_count = = 0 ) {
return 1.f ;
}
2020-03-15 18:13:07 +00:00
2021-04-27 22:54:59 +00:00
// zoom = 2**(index/12) => log2(zoom) = index/12
float closest_zoom_index = Math : : round ( Math : : log ( zoom_noscale ) * 12.f / Math : : log ( 2.f ) ) ;
2020-03-15 18:13:07 +00:00
2021-04-27 22:54:59 +00:00
float new_zoom_index = closest_zoom_index + p_increment_count ;
float new_zoom = Math : : pow ( 2.f , new_zoom_index / 12.f ) ;
2020-03-15 18:13:07 +00:00
2021-04-27 22:54:59 +00:00
// Restore editor scale transformation.
new_zoom * = MAX ( 1 , EDSCALE ) ;
2020-03-15 18:13:07 +00:00
2021-04-27 22:54:59 +00:00
return new_zoom ;
}
2020-03-15 18:13:07 +00:00
}
2017-10-01 09:30:38 +00:00
void CanvasItemEditor : : _zoom_on_position ( float p_zoom , Point2 p_position ) {
2020-03-15 18:13:07 +00:00
p_zoom = CLAMP ( p_zoom , MIN_ZOOM , MAX_ZOOM ) ;
2021-05-05 10:44:11 +00:00
if ( p_zoom = = zoom ) {
2017-08-19 16:29:37 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2017-10-01 09:30:38 +00:00
float prev_zoom = zoom ;
zoom = p_zoom ;
2020-03-18 06:05:23 +00:00
view_offset + = p_position / prev_zoom - p_position / zoom ;
// We want to align in-scene pixels to screen pixels, this prevents blurry rendering
// in small details (texts, lines).
// This correction adds a jitter movement when zooming, so we correct only when the
// zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway)
float closest_zoom_factor = Math : : round ( zoom ) ;
if ( Math : : is_zero_approx ( zoom - closest_zoom_factor ) ) {
// make sure scene pixel at view_offset is aligned on a screen pixel
Vector2 view_offset_int = view_offset . floor ( ) ;
Vector2 view_offset_frac = view_offset - view_offset_int ;
view_offset = view_offset_int + ( view_offset_frac * closest_zoom_factor ) . round ( ) / closest_zoom_factor ;
}
2017-08-19 16:29:37 +00:00
2019-09-17 04:43:08 +00:00
_update_zoom_label ( ) ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2017-08-19 16:29:37 +00:00
}
2019-09-17 04:43:08 +00:00
void CanvasItemEditor : : _update_zoom_label ( ) {
String zoom_text ;
2020-01-04 17:43:52 +00:00
// The zoom level displayed is relative to the editor scale
2020-01-13 11:13:35 +00:00
// (like in most image editors). Its lower bound is clamped to 1 as some people
// lower the editor scale to increase the available real estate,
// even if their display doesn't have a particularly low DPI.
2019-09-17 04:43:08 +00:00
if ( zoom > = 10 ) {
2020-01-04 17:43:52 +00:00
// Don't show a decimal when the zoom level is higher than 1000 %.
2020-01-13 11:13:35 +00:00
zoom_text = rtos ( Math : : round ( ( zoom / MAX ( 1 , EDSCALE ) ) * 100 ) ) + " % " ;
2019-09-17 04:43:08 +00:00
} else {
2020-01-13 11:13:35 +00:00
zoom_text = rtos ( Math : : stepify ( ( zoom / MAX ( 1 , EDSCALE ) ) * 100 , 0.1 ) ) + " % " ;
2019-09-17 04:43:08 +00:00
}
zoom_reset - > set_text ( zoom_text ) ;
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _button_zoom_minus ( ) {
2021-04-27 22:54:59 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_ALT ) ) {
_zoom_on_position ( _get_next_zoom_value ( - 1 , true ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
} else {
_zoom_on_position ( _get_next_zoom_value ( - 6 ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
}
2017-10-01 09:30:38 +00:00
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _button_zoom_reset ( ) {
2020-01-18 21:07:27 +00:00
_zoom_on_position ( 1.0 * MAX ( 1 , EDSCALE ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
2017-08-19 16:29:37 +00:00
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _button_zoom_plus ( ) {
2021-04-27 22:54:59 +00:00
if ( Input : : get_singleton ( ) - > is_key_pressed ( KEY_ALT ) ) {
_zoom_on_position ( _get_next_zoom_value ( 1 , true ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
} else {
_zoom_on_position ( _get_next_zoom_value ( 6 ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
}
}
void CanvasItemEditor : : _shortcut_zoom_set ( float p_zoom ) {
_zoom_on_position ( p_zoom * MAX ( 1 , EDSCALE ) , viewport_scrollable - > get_size ( ) / 2.0 ) ;
2017-08-19 16:29:37 +00:00
}
2019-10-10 17:41:45 +00:00
void CanvasItemEditor : : _button_toggle_smart_snap ( bool p_status ) {
smart_snap_active = p_status ;
viewport - > update ( ) ;
}
void CanvasItemEditor : : _button_toggle_grid_snap ( bool p_status ) {
grid_snap_active = p_status ;
2017-09-17 20:52:41 +00:00
viewport - > update ( ) ;
2017-11-07 07:58:35 +00:00
}
2019-04-06 20:55:01 +00:00
void CanvasItemEditor : : _button_override_camera ( bool p_pressed ) {
ScriptEditorDebugger * debugger = ScriptEditor : : get_singleton ( ) - > get_debugger ( ) ;
if ( p_pressed ) {
debugger - > set_camera_override ( ScriptEditorDebugger : : OVERRIDE_2D ) ;
} else {
debugger - > set_camera_override ( ScriptEditorDebugger : : OVERRIDE_NONE ) ;
}
}
2017-11-07 07:58:35 +00:00
void CanvasItemEditor : : _button_tool_select ( int p_index ) {
2019-08-30 20:49:47 +00:00
ToolButton * tb [ TOOL_MAX ] = { select_button , list_select_button , move_button , scale_button , rotate_button , pivot_button , pan_button , ruler_button } ;
2017-11-07 07:58:35 +00:00
for ( int i = 0 ; i < TOOL_MAX ; i + + ) {
tb [ i ] - > set_pressed ( i = = p_index ) ;
}
tool = ( Tool ) p_index ;
2019-08-30 20:49:47 +00:00
viewport - > update ( ) ;
2017-09-17 20:52:41 +00:00
}
2019-04-15 03:49:03 +00:00
void CanvasItemEditor : : _insert_animation_keys ( bool p_location , bool p_rotation , bool p_scale , bool p_on_existing ) {
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_visible_in_tree ( ) ) {
2019-04-15 03:49:03 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
2021-05-05 10:44:11 +00:00
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2019-04-15 03:49:03 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
if ( Object : : cast_to < Node2D > ( canvas_item ) ) {
Node2D * n2d = Object : : cast_to < Node2D > ( canvas_item ) ;
2021-05-05 10:44:11 +00:00
if ( key_pos & & p_location ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( n2d , " position " , n2d - > get_position ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_rot & & p_rotation ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( n2d , " rotation_degrees " , Math : : rad2deg ( n2d - > get_rotation ( ) ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_scale & & p_scale ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( n2d , " scale " , n2d - > get_scale ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
if ( n2d - > has_meta ( " _edit_bone_ " ) & & n2d - > get_parent_item ( ) ) {
//look for an IK chain
List < Node2D * > ik_chain ;
Node2D * n = Object : : cast_to < Node2D > ( n2d - > get_parent_item ( ) ) ;
bool has_chain = false ;
while ( n ) {
ik_chain . push_back ( n ) ;
if ( n - > has_meta ( " _edit_ik_ " ) ) {
has_chain = true ;
break ;
}
2021-05-05 10:44:11 +00:00
if ( ! n - > get_parent_item ( ) ) {
2019-04-15 03:49:03 +00:00
break ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
n = Object : : cast_to < Node2D > ( n - > get_parent_item ( ) ) ;
}
if ( has_chain & & ik_chain . size ( ) ) {
for ( List < Node2D * > : : Element * F = ik_chain . front ( ) ; F ; F = F - > next ( ) ) {
2021-05-05 10:44:11 +00:00
if ( key_pos ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( F - > get ( ) , " position " , F - > get ( ) - > get_position ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_rot ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( F - > get ( ) , " rotation_degrees " , Math : : rad2deg ( F - > get ( ) - > get_rotation ( ) ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_scale ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( F - > get ( ) , " scale " , F - > get ( ) - > get_scale ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
}
}
}
} else if ( Object : : cast_to < Control > ( canvas_item ) ) {
Control * ctrl = Object : : cast_to < Control > ( canvas_item ) ;
2021-05-05 10:44:11 +00:00
if ( key_pos ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( ctrl , " rect_position " , ctrl - > get_position ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_rot ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( ctrl , " rect_rotation " , ctrl - > get_rotation_degrees ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_scale ) {
2019-04-15 03:49:03 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( ctrl , " rect_size " , ctrl - > get_size ( ) , p_on_existing ) ;
2021-05-05 10:44:11 +00:00
}
2019-04-15 03:49:03 +00:00
}
}
}
2019-03-31 16:53:24 +00:00
void CanvasItemEditor : : _button_toggle_anchor_mode ( bool p_status ) {
List < CanvasItem * > selection = _get_edited_canvas_items ( false , false ) ;
for ( List < CanvasItem * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
Control * control = Object : : cast_to < Control > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! control | | Object : : cast_to < Container > ( control - > get_parent ( ) ) ) {
2019-03-31 16:53:24 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2019-03-31 16:53:24 +00:00
control - > set_meta ( " _edit_use_anchors_ " , p_status ) ;
}
anchors_mode = p_status ;
viewport - > update ( ) ;
}
2019-04-06 20:55:01 +00:00
void CanvasItemEditor : : _update_override_camera_button ( bool p_game_running ) {
if ( p_game_running ) {
override_camera_button - > set_disabled ( false ) ;
2021-06-29 14:17:47 +00:00
override_camera_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 {
override_camera_button - > set_disabled ( true ) ;
override_camera_button - > set_pressed ( false ) ;
2021-06-29 14:17:47 +00:00
override_camera_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
}
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : _popup_callback ( int p_op ) {
2017-03-05 15:44:50 +00:00
last_option = MenuOption ( p_op ) ;
switch ( p_op ) {
2017-09-17 20:52:41 +00:00
case SHOW_GRID : {
show_grid = ! show_grid ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_GRID ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_grid ) ;
2017-07-25 19:09:32 +00:00
viewport - > update ( ) ;
2015-02-15 08:00:55 +00:00
} break ;
2018-03-02 08:52:13 +00:00
case SHOW_ORIGIN : {
show_origin = ! show_origin ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_ORIGIN ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_origin ) ;
viewport - > update ( ) ;
} break ;
case SHOW_VIEWPORT : {
show_viewport = ! show_viewport ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_VIEWPORT ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_viewport ) ;
viewport - > update ( ) ;
} break ;
2018-09-20 00:41:19 +00:00
case SHOW_EDIT_LOCKS : {
show_edit_locks = ! show_edit_locks ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_EDIT_LOCKS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_edit_locks ) ;
viewport - > update ( ) ;
} break ;
2017-09-17 20:52:41 +00:00
case SNAP_USE_NODE_PARENT : {
snap_node_parent = ! snap_node_parent ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_PARENT ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_parent ) ;
} break ;
case SNAP_USE_NODE_ANCHORS : {
snap_node_anchors = ! snap_node_anchors ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_ANCHORS ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_anchors ) ;
} break ;
case SNAP_USE_NODE_SIDES : {
snap_node_sides = ! snap_node_sides ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_SIDES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_sides ) ;
} break ;
2017-11-07 07:58:35 +00:00
case SNAP_USE_NODE_CENTER : {
snap_node_center = ! snap_node_center ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_CENTER ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_center ) ;
} break ;
2017-09-17 20:52:41 +00:00
case SNAP_USE_OTHER_NODES : {
snap_other_nodes = ! snap_other_nodes ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_OTHER_NODES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_other_nodes ) ;
} break ;
2017-10-18 21:55:02 +00:00
case SNAP_USE_GUIDES : {
snap_guides = ! snap_guides ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_GUIDES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_guides ) ;
} break ;
2015-02-15 08:00:55 +00:00
case SNAP_USE_ROTATION : {
snap_rotation = ! snap_rotation ;
2017-09-17 20:52:41 +00:00
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_ROTATION ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_rotation ) ;
2015-02-15 08:00:55 +00:00
} break ;
2019-10-30 14:18:57 +00:00
case SNAP_USE_SCALE : {
snap_scale = ! snap_scale ;
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_SCALE ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_scale ) ;
} break ;
2015-02-20 12:21:59 +00:00
case SNAP_RELATIVE : {
snap_relative = ! snap_relative ;
2017-09-17 20:52:41 +00:00
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_RELATIVE ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_relative ) ;
2017-07-25 19:09:32 +00:00
viewport - > update ( ) ;
2015-02-15 08:00:55 +00:00
} break ;
2014-02-10 01:10:30 +00:00
case SNAP_USE_PIXEL : {
2015-02-15 08:00:55 +00:00
snap_pixel = ! snap_pixel ;
2017-09-17 20:52:41 +00:00
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_PIXEL ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_pixel ) ;
2014-02-10 01:10:30 +00:00
} break ;
case SNAP_CONFIGURE : {
2019-10-30 14:18:57 +00:00
( ( SnapDialog * ) snap_dialog ) - > set_fields ( grid_offset , grid_step , primary_grid_steps , snap_rotation_offset , snap_rotation_step , snap_scale_step ) ;
2019-10-15 08:23:38 +00:00
snap_dialog - > popup_centered ( Size2 ( 220 , 160 ) * EDSCALE ) ;
2014-02-10 01:10:30 +00:00
} break ;
2016-09-07 09:10:00 +00:00
case SKELETON_SHOW_BONES : {
skeleton_show_bones = ! skeleton_show_bones ;
2017-09-17 20:52:41 +00:00
int idx = skeleton_menu - > get_popup ( ) - > get_item_index ( SKELETON_SHOW_BONES ) ;
skeleton_menu - > get_popup ( ) - > set_item_checked ( idx , skeleton_show_bones ) ;
2016-09-07 09:10:00 +00:00
viewport - > update ( ) ;
} break ;
2017-08-19 16:29:37 +00:00
case SHOW_HELPERS : {
show_helpers = ! show_helpers ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_HELPERS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_helpers ) ;
2014-02-10 01:10:30 +00:00
viewport - > update ( ) ;
} break ;
2017-08-29 19:50:18 +00:00
case SHOW_RULERS : {
show_rulers = ! show_rulers ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_RULERS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_rulers ) ;
2019-05-20 20:35:31 +00:00
_update_scrollbars ( ) ;
2017-08-29 19:50:18 +00:00
viewport - > update ( ) ;
} break ;
2017-10-18 21:55:02 +00:00
case SHOW_GUIDES : {
show_guides = ! show_guides ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_GUIDES ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_guides ) ;
viewport - > update ( ) ;
} break ;
2014-02-10 01:10:30 +00:00
case LOCK_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Lock Selected " ) ) ;
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_inside_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-01-24 19:41:50 +00:00
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( canvas_item , " set_meta " , " _edit_lock_ " , true ) ;
undo_redo - > add_undo_method ( canvas_item , " 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 " ) ;
2014-02-10 01:10:30 +00:00
}
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > add_undo_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case UNLOCK_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Unlock Selected " ) ) ;
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_inside_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-01-24 19:41:50 +00:00
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( canvas_item , " remove_meta " , " _edit_lock_ " ) ;
undo_redo - > add_undo_method ( canvas_item , " 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 " ) ;
2014-02-10 01:10:30 +00:00
}
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > add_undo_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case GROUP_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Group Selected " ) ) ;
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_inside_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-01-24 19:41:50 +00:00
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( canvas_item , " set_meta " , " _edit_group_ " , true ) ;
undo_redo - > add_undo_method ( canvas_item , " 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 " ) ;
2014-02-10 01:10:30 +00:00
}
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > add_undo_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
case UNGROUP_SELECTED : {
2019-04-26 17:23:50 +00:00
undo_redo - > create_action ( TTR ( " Ungroup Selected " ) ) ;
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_inside_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-01-24 19:41:50 +00:00
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( canvas_item , " remove_meta " , " _edit_group_ " ) ;
undo_redo - > add_undo_method ( canvas_item , " 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 " ) ;
2014-02-10 01:10:30 +00:00
}
2019-04-26 17:23:50 +00:00
undo_redo - > add_do_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > add_undo_method ( viewport , " update " , Variant ( ) ) ;
undo_redo - > commit_action ( ) ;
2014-02-10 01:10:30 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT : {
_set_anchors_and_margins_preset ( PRESET_TOP_LEFT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT : {
_set_anchors_and_margins_preset ( PRESET_TOP_RIGHT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT : {
_set_anchors_and_margins_preset ( PRESET_BOTTOM_LEFT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT : {
_set_anchors_and_margins_preset ( PRESET_BOTTOM_RIGHT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT : {
_set_anchors_and_margins_preset ( PRESET_CENTER_LEFT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT : {
_set_anchors_and_margins_preset ( PRESET_CENTER_RIGHT ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP : {
_set_anchors_and_margins_preset ( PRESET_CENTER_TOP ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM : {
_set_anchors_and_margins_preset ( PRESET_CENTER_BOTTOM ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_CENTER : {
_set_anchors_and_margins_preset ( PRESET_CENTER ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE : {
_set_anchors_and_margins_preset ( PRESET_TOP_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE : {
_set_anchors_and_margins_preset ( PRESET_LEFT_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE : {
_set_anchors_and_margins_preset ( PRESET_RIGHT_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE : {
_set_anchors_and_margins_preset ( PRESET_BOTTOM_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE : {
_set_anchors_and_margins_preset ( PRESET_VCENTER_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE : {
_set_anchors_and_margins_preset ( PRESET_HCENTER_WIDE ) ;
} break ;
case ANCHORS_AND_MARGINS_PRESET_WIDE : {
_set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
} break ;
2019-03-31 16:53:24 +00:00
case ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO : {
_set_anchors_and_margins_to_keep_ratio ( ) ;
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_TOP_LEFT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_TOP_LEFT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_TOP_RIGHT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_TOP_RIGHT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_BOTTOM_LEFT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_BOTTOM_LEFT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_BOTTOM_RIGHT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_BOTTOM_RIGHT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_CENTER_LEFT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_CENTER_LEFT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_CENTER_RIGHT : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_CENTER_RIGHT ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_CENTER_TOP : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_CENTER_TOP ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_CENTER_BOTTOM : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_CENTER_BOTTOM ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_CENTER : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_CENTER ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_TOP_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_TOP_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_LEFT_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_LEFT_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_RIGHT_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_RIGHT_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_BOTTOM_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_BOTTOM_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_VCENTER_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_VCENTER_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_HCENTER_WIDE : {
2017-08-11 16:16:28 +00:00
_set_anchors_preset ( PRESET_HCENTER_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2017-10-03 22:47:40 +00:00
case ANCHORS_PRESET_WIDE : {
2017-09-21 22:12:33 +00:00
_set_anchors_preset ( Control : : PRESET_WIDE ) ;
2015-08-24 04:00:39 +00:00
} break ;
2014-02-10 01:10:30 +00:00
case ANIM_INSERT_KEY :
case ANIM_INSERT_KEY_EXISTING : {
2017-03-05 15:44:50 +00:00
bool existing = p_op = = ANIM_INSERT_KEY_EXISTING ;
2014-02-10 01:10:30 +00:00
2019-04-15 03:49:03 +00:00
_insert_animation_keys ( true , true , true , existing ) ;
2014-02-10 01:10:30 +00:00
} break ;
2014-07-06 14:49:27 +00:00
case ANIM_INSERT_POS : {
key_pos = key_loc_button - > is_pressed ( ) ;
} break ;
case ANIM_INSERT_ROT : {
2015-01-02 20:31:43 +00:00
key_rot = key_rot_button - > is_pressed ( ) ;
2014-07-06 14:49:27 +00:00
} break ;
case ANIM_INSERT_SCALE : {
key_scale = key_scale_button - > is_pressed ( ) ;
} break ;
2014-02-10 01:10:30 +00:00
case ANIM_COPY_POSE : {
2017-01-14 17:03:38 +00:00
pose_clipboard . clear ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2021-05-05 10:44:11 +00:00
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2017-08-24 20:58:51 +00:00
if ( Object : : cast_to < Node2D > ( canvas_item ) ) {
Node2D * n2d = Object : : cast_to < Node2D > ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
PoseClipboard pc ;
2017-03-05 15:44:50 +00:00
pc . pos = n2d - > get_position ( ) ;
pc . rot = n2d - > get_rotation ( ) ;
pc . scale = n2d - > get_scale ( ) ;
2017-08-07 10:17:31 +00:00
pc . id = n2d - > get_instance_id ( ) ;
2014-02-10 01:10:30 +00:00
pose_clipboard . push_back ( pc ) ;
}
}
} break ;
case ANIM_PASTE_POSE : {
2021-05-05 10:44:11 +00:00
if ( ! pose_clipboard . size ( ) ) {
2014-02-10 01:10:30 +00:00
break ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2016-05-04 01:25:37 +00:00
undo_redo - > create_action ( TTR ( " Paste Pose " ) ) ;
2017-03-05 15:44:50 +00:00
for ( List < PoseClipboard > : : Element * E = pose_clipboard . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
Node2D * n2d = Object : : cast_to < Node2D > ( ObjectDB : : get_instance ( E - > get ( ) . id ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! n2d ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2017-03-29 15:29:38 +00:00
undo_redo - > add_do_method ( n2d , " set_position " , E - > get ( ) . pos ) ;
2017-06-24 09:39:57 +00:00
undo_redo - > add_do_method ( n2d , " set_rotation " , E - > get ( ) . rot ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_do_method ( n2d , " set_scale " , E - > get ( ) . scale ) ;
2017-03-29 15:29:38 +00:00
undo_redo - > add_undo_method ( n2d , " set_position " , n2d - > get_position ( ) ) ;
2017-06-24 09:39:57 +00:00
undo_redo - > add_undo_method ( n2d , " set_rotation " , n2d - > get_rotation ( ) ) ;
2017-03-05 15:44:50 +00:00
undo_redo - > add_undo_method ( n2d , " set_scale " , n2d - > get_scale ( ) ) ;
2014-02-10 01:10:30 +00:00
}
undo_redo - > commit_action ( ) ;
} break ;
case ANIM_CLEAR_POSE : {
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_visible_in_tree ( ) ) {
2014-02-10 01:10:30 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-02-10 01:10:30 +00:00
2021-05-05 10:44:11 +00:00
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-01-24 19:41:50 +00:00
2017-08-24 20:58:51 +00:00
if ( Object : : cast_to < Node2D > ( canvas_item ) ) {
Node2D * n2d = Object : : cast_to < Node2D > ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
2021-05-05 10:44:11 +00:00
if ( key_pos ) {
2017-01-04 04:16:14 +00:00
n2d - > set_position ( Vector2 ( ) ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_rot ) {
2017-01-04 04:16:14 +00:00
n2d - > set_rotation ( 0 ) ;
2021-05-05 10:44:11 +00:00
}
if ( key_scale ) {
2017-03-05 15:44:50 +00:00
n2d - > set_scale ( Vector2 ( 1 , 1 ) ) ;
2021-05-05 10:44:11 +00:00
}
2017-08-24 20:58:51 +00:00
} else if ( Object : : cast_to < Control > ( canvas_item ) ) {
Control * ctrl = Object : : cast_to < Control > ( canvas_item ) ;
2014-02-10 01:10:30 +00:00
2021-05-05 10:44:11 +00:00
if ( key_pos ) {
2017-03-29 15:29:38 +00:00
ctrl - > set_position ( Point2 ( ) ) ;
2021-05-05 10:44:11 +00:00
}
2017-01-14 11:26:56 +00:00
/*
2017-11-07 07:58:35 +00:00
if ( key_scale )
2018-06-07 15:46:14 +00:00
AnimationPlayerEditor : : singleton - > get_track_editor ( ) - > insert_node_value_key ( ctrl , " rect/size " , ctrl - > get_size ( ) ) ;
2017-11-07 07:58:35 +00:00
*/
2014-02-10 01:10:30 +00:00
}
}
2019-08-24 20:58:16 +00:00
} break ;
case CLEAR_GUIDES : {
2019-12-05 07:20:50 +00:00
Node * const root = EditorNode : : get_singleton ( ) - > get_edited_scene ( ) ;
if ( root & & ( root - > has_meta ( " _edit_horizontal_guides_ " ) | | root - > has_meta ( " _edit_vertical_guides_ " ) ) ) {
2019-08-24 20:58:16 +00:00
undo_redo - > create_action ( TTR ( " Clear Guides " ) ) ;
2019-12-05 07:20:50 +00:00
if ( root - > has_meta ( " _edit_horizontal_guides_ " ) ) {
Array hguides = root - > get_meta ( " _edit_horizontal_guides_ " ) ;
2019-08-24 20:58:16 +00:00
2019-12-04 21:16:22 +00:00
undo_redo - > add_do_method ( root , " remove_meta " , " _edit_horizontal_guides_ " ) ;
2019-12-05 07:20:50 +00:00
undo_redo - > add_undo_method ( root , " set_meta " , " _edit_horizontal_guides_ " , hguides ) ;
2019-08-24 20:58:16 +00:00
}
2019-12-05 07:20:50 +00:00
if ( root - > has_meta ( " _edit_vertical_guides_ " ) ) {
Array vguides = root - > get_meta ( " _edit_vertical_guides_ " ) ;
2019-08-24 20:58:16 +00:00
2019-12-04 21:16:22 +00:00
undo_redo - > add_do_method ( root , " remove_meta " , " _edit_vertical_guides_ " ) ;
2019-12-05 07:20:50 +00:00
undo_redo - > add_undo_method ( root , " set_meta " , " _edit_vertical_guides_ " , vguides ) ;
2019-08-24 20:58:16 +00:00
}
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
}
2014-02-10 01:10:30 +00:00
} break ;
2014-05-03 17:36:59 +00:00
case VIEW_CENTER_TO_SELECTION :
case VIEW_FRAME_TO_SELECTION : {
2016-07-28 19:37:52 +00:00
_focus_selection ( p_op ) ;
2014-05-03 17:36:59 +00:00
2019-04-05 13:24:54 +00:00
} break ;
case PREVIEW_CANVAS_SCALE : {
bool preview = view_menu - > get_popup ( ) - > is_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( PREVIEW_CANVAS_SCALE ) ) ;
preview = ! preview ;
VS : : get_singleton ( ) - > canvas_set_disable_scale ( ! preview ) ;
view_menu - > get_popup ( ) - > set_item_checked ( view_menu - > get_popup ( ) - > get_item_index ( PREVIEW_CANVAS_SCALE ) , preview ) ;
2014-05-03 17:36:59 +00:00
} break ;
2014-07-06 14:49:27 +00:00
case SKELETON_MAKE_BONES : {
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > create_action ( TTR ( " Create Custom Bone(s) from Node(s) " ) ) ;
2017-03-05 15:44:50 +00:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
Node2D * n2d = Object : : cast_to < Node2D > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! n2d ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > is_visible_in_tree ( ) ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > get_parent_item ( ) ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( n2d - > has_meta ( " _edit_bone_ " ) & & n2d - > get_meta ( " _edit_bone_ " ) ) {
2019-05-21 20:17:25 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( n2d , " set_meta " , " _edit_bone_ " , true ) ;
undo_redo - > add_undo_method ( n2d , " remove_meta " , " _edit_bone_ " ) ;
2014-07-06 14:49:27 +00:00
}
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( this , " _queue_update_bone_list " ) ;
undo_redo - > add_undo_method ( this , " _queue_update_bone_list " ) ;
undo_redo - > add_do_method ( viewport , " update " ) ;
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
2014-07-06 14:49:27 +00:00
} break ;
case SKELETON_CLEAR_BONES : {
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > create_action ( TTR ( " Clear Bones " ) ) ;
2017-03-05 15:44:50 +00:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
Node2D * n2d = Object : : cast_to < Node2D > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! n2d ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > is_visible_in_tree ( ) ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > has_meta ( " _edit_bone_ " ) ) {
2019-05-21 20:17:25 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( n2d , " remove_meta " , " _edit_bone_ " ) ;
undo_redo - > add_undo_method ( n2d , " set_meta " , " _edit_bone_ " , n2d - > get_meta ( " _edit_bone_ " ) ) ;
2014-07-06 14:49:27 +00:00
}
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( this , " _queue_update_bone_list " ) ;
undo_redo - > add_undo_method ( this , " _queue_update_bone_list " ) ;
undo_redo - > add_do_method ( viewport , " update " ) ;
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
2014-07-06 14:49:27 +00:00
} break ;
case SKELETON_SET_IK_CHAIN : {
2018-01-07 08:55:26 +00:00
List < Node * > selection = editor_selection - > get_selected_node_list ( ) ;
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > create_action ( TTR ( " Make IK Chain " ) ) ;
2017-03-05 15:44:50 +00:00
for ( List < Node * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > get ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item | | ! canvas_item - > is_visible_in_tree ( ) ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-01-24 19:41:50 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > has_meta ( " _edit_ik_ " ) & & canvas_item - > get_meta ( " _edit_ik_ " ) ) {
2019-05-21 20:17:25 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( canvas_item , " set_meta " , " _edit_ik_ " , true ) ;
undo_redo - > add_undo_method ( canvas_item , " remove_meta " , " _edit_ik_ " ) ;
2014-07-06 14:49:27 +00:00
}
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( viewport , " update " ) ;
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
2014-07-06 14:49:27 +00:00
} break ;
case SKELETON_CLEAR_IK_CHAIN : {
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > create_action ( TTR ( " Clear IK Chain " ) ) ;
2017-03-05 15:44:50 +00:00
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * n2d = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! n2d ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > is_visible_in_tree ( ) ) {
2014-07-06 14:49:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( ! n2d - > has_meta ( " _edit_ik_ " ) ) {
2019-05-21 20:17:25 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2014-07-06 14:49:27 +00:00
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( n2d , " remove_meta " , " _edit_ik_ " ) ;
undo_redo - > add_undo_method ( n2d , " set_meta " , " _edit_ik_ " , n2d - > get_meta ( " _edit_ik_ " ) ) ;
2014-07-06 14:49:27 +00:00
}
2019-05-21 20:17:25 +00:00
undo_redo - > add_do_method ( viewport , " update " ) ;
undo_redo - > add_undo_method ( viewport , " update " ) ;
undo_redo - > commit_action ( ) ;
2014-07-06 14:49:27 +00:00
} break ;
2014-02-10 01:10:30 +00:00
}
}
2016-07-28 19:37:52 +00:00
void CanvasItemEditor : : _focus_selection ( int p_op ) {
Vector2 center ( 0.f , 0.f ) ;
Rect2 rect ;
int count = 0 ;
2017-03-05 15:44:50 +00:00
Map < Node * , Object * > & selection = editor_selection - > get_selection ( ) ;
for ( Map < Node * , Object * > : : Element * E = selection . front ( ) ; E ; E = E - > next ( ) ) {
2017-08-24 20:58:51 +00:00
CanvasItem * canvas_item = Object : : cast_to < CanvasItem > ( E - > key ( ) ) ;
2021-05-05 10:44:11 +00:00
if ( ! canvas_item ) {
2021-05-04 12:28:27 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
if ( canvas_item - > get_viewport ( ) ! = EditorNode : : get_singleton ( ) - > get_scene_root ( ) ) {
2016-07-28 19:37:52 +00:00
continue ;
2021-05-05 10:44:11 +00:00
}
2016-07-28 19:37:52 +00:00
// counting invisible items, for now
2017-01-13 13:45:50 +00:00
//if (!canvas_item->is_visible_in_tree()) continue;
2016-07-28 19:37:52 +00:00
+ + count ;
2018-03-08 20:35:41 +00:00
Rect2 item_rect ;
if ( canvas_item - > _edit_use_rect ( ) ) {
item_rect = canvas_item - > _edit_get_rect ( ) ;
} else {
item_rect = Rect2 ( ) ;
}
2016-07-28 19:37:52 +00:00
Vector2 pos = canvas_item - > get_global_transform ( ) . get_origin ( ) ;
Vector2 scale = canvas_item - > get_global_transform ( ) . get_scale ( ) ;
real_t angle = canvas_item - > get_global_transform ( ) . get_rotation ( ) ;
2017-03-05 15:44:50 +00:00
Transform2D t ( angle , Vector2 ( 0.f , 0.f ) ) ;
2016-07-28 19:37:52 +00:00
item_rect = t . xform ( item_rect ) ;
2017-06-03 22:25:13 +00:00
Rect2 canvas_item_rect ( pos + scale * item_rect . position , scale * item_rect . size ) ;
2016-07-28 19:37:52 +00:00
if ( count = = 1 ) {
rect = canvas_item_rect ;
} else {
rect = rect . merge ( canvas_item_rect ) ;
}
} ;
if ( p_op = = VIEW_CENTER_TO_SELECTION ) {
2017-06-03 22:25:13 +00:00
center = rect . position + rect . size / 2 ;
2017-03-05 15:44:50 +00:00
Vector2 offset = viewport - > get_size ( ) / 2 - editor - > get_scene_root ( ) - > get_global_canvas_transform ( ) . xform ( center ) ;
2019-12-11 16:09:55 +00:00
view_offset . x - = Math : : round ( offset . x / zoom ) ;
view_offset . y - = Math : : round ( offset . y / zoom ) ;
2018-10-18 12:06:57 +00:00
update_viewport ( ) ;
2016-07-28 19:37:52 +00:00
} else { // VIEW_FRAME_TO_SELECTION
if ( rect . size . x > CMP_EPSILON & & rect . size . y > CMP_EPSILON ) {
2017-03-05 15:44:50 +00:00
float scale_x = viewport - > get_size ( ) . x / rect . size . x ;
float scale_y = viewport - > get_size ( ) . y / rect . size . y ;
zoom = scale_x < scale_y ? scale_x : scale_y ;
2016-07-28 19:37:52 +00:00
zoom * = 0.90 ;
2018-03-15 14:12:16 +00:00
viewport - > update ( ) ;
2020-02-08 17:29:28 +00:00
_update_zoom_label ( ) ;
2016-07-28 19:37:52 +00:00
call_deferred ( " _popup_callback " , VIEW_CENTER_TO_SELECTION ) ;
}
}
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : _bind_methods ( ) {
2017-11-07 07:58:35 +00:00
ClassDB : : bind_method ( " _button_zoom_minus " , & CanvasItemEditor : : _button_zoom_minus ) ;
ClassDB : : bind_method ( " _button_zoom_reset " , & CanvasItemEditor : : _button_zoom_reset ) ;
ClassDB : : bind_method ( " _button_zoom_plus " , & CanvasItemEditor : : _button_zoom_plus ) ;
2019-10-10 17:41:45 +00:00
ClassDB : : bind_method ( " _button_toggle_smart_snap " , & CanvasItemEditor : : _button_toggle_smart_snap ) ;
ClassDB : : bind_method ( " _button_toggle_grid_snap " , & CanvasItemEditor : : _button_toggle_grid_snap ) ;
2019-04-06 20:55:01 +00:00
ClassDB : : bind_method ( D_METHOD ( " _button_override_camera " , " pressed " ) , & CanvasItemEditor : : _button_override_camera ) ;
ClassDB : : bind_method ( D_METHOD ( " _update_override_camera_button " , " game_running " ) , & CanvasItemEditor : : _update_override_camera_button ) ;
2019-03-31 16:53:24 +00:00
ClassDB : : bind_method ( " _button_toggle_anchor_mode " , & CanvasItemEditor : : _button_toggle_anchor_mode ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( " _update_scroll " , & CanvasItemEditor : : _update_scroll ) ;
2018-03-15 14:12:16 +00:00
ClassDB : : bind_method ( " _update_scrollbars " , & CanvasItemEditor : : _update_scrollbars ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( " _popup_callback " , & CanvasItemEditor : : _popup_callback ) ;
ClassDB : : bind_method ( " _get_editor_data " , & CanvasItemEditor : : _get_editor_data ) ;
2017-11-07 07:58:35 +00:00
ClassDB : : bind_method ( " _button_tool_select " , & CanvasItemEditor : : _button_tool_select ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( " _keying_changed " , & CanvasItemEditor : : _keying_changed ) ;
ClassDB : : bind_method ( " _unhandled_key_input " , & CanvasItemEditor : : _unhandled_key_input ) ;
2017-08-28 19:51:56 +00:00
ClassDB : : bind_method ( " _draw_viewport " , & CanvasItemEditor : : _draw_viewport ) ;
2017-10-15 20:33:25 +00:00
ClassDB : : bind_method ( " _gui_input_viewport " , & CanvasItemEditor : : _gui_input_viewport ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( " _snap_changed " , & CanvasItemEditor : : _snap_changed ) ;
2019-05-21 20:17:25 +00:00
ClassDB : : bind_method ( " _queue_update_bone_list " , & CanvasItemEditor : : _update_bone_list ) ;
2018-05-04 21:11:28 +00:00
ClassDB : : bind_method ( " _update_bone_list " , & CanvasItemEditor : : _update_bone_list ) ;
ClassDB : : bind_method ( " _tree_changed " , & CanvasItemEditor : : _tree_changed ) ;
2019-03-31 16:53:24 +00:00
ClassDB : : bind_method ( " _selection_changed " , & CanvasItemEditor : : _selection_changed ) ;
2018-10-25 17:08:32 +00:00
ClassDB : : bind_method ( " _popup_warning_depop " , & CanvasItemEditor : : _popup_warning_depop ) ;
2021-07-07 11:19:59 +00:00
ClassDB : : bind_method ( " _add_node_pressed " , & CanvasItemEditor : : _add_node_pressed ) ;
ClassDB : : bind_method ( " _node_created " , & CanvasItemEditor : : _node_created ) ;
ClassDB : : bind_method ( " _reset_create_position " , & CanvasItemEditor : : _reset_create_position ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _selection_result_pressed " ) , & CanvasItemEditor : : _selection_result_pressed ) ;
ClassDB : : bind_method ( D_METHOD ( " _selection_menu_hide " ) , & CanvasItemEditor : : _selection_menu_hide ) ;
2021-05-28 18:34:30 +00:00
ClassDB : : bind_method ( D_METHOD ( " get_state " ) , & CanvasItemEditor : : get_state ) ;
2018-01-04 18:55:43 +00:00
ClassDB : : bind_method ( D_METHOD ( " set_state " ) , & CanvasItemEditor : : set_state ) ;
2018-10-18 12:06:57 +00:00
ClassDB : : bind_method ( D_METHOD ( " update_viewport " ) , & CanvasItemEditor : : update_viewport ) ;
2021-05-28 18:34:30 +00:00
ClassDB : : bind_method ( D_METHOD ( " _zoom_on_position " ) , & CanvasItemEditor : : _zoom_on_position ) ;
2017-03-05 15:44:50 +00:00
ADD_SIGNAL ( MethodInfo ( " item_lock_status_changed " ) ) ;
ADD_SIGNAL ( MethodInfo ( " item_group_status_changed " ) ) ;
2014-02-10 01:10:30 +00:00
}
2017-11-07 07:58:35 +00:00
Dictionary CanvasItemEditor : : get_state ( ) const {
Dictionary state ;
2020-01-04 17:43:52 +00:00
// Take the editor scale into account.
2020-01-13 11:13:35 +00:00
state [ " zoom " ] = zoom / MAX ( 1 , EDSCALE ) ;
2018-03-15 14:12:16 +00:00
state [ " ofs " ] = view_offset ;
2017-11-07 07:58:35 +00:00
state [ " grid_offset " ] = grid_offset ;
state [ " grid_step " ] = grid_step ;
2019-10-15 08:23:38 +00:00
state [ " primary_grid_steps " ] = primary_grid_steps ;
2017-11-07 07:58:35 +00:00
state [ " snap_rotation_offset " ] = snap_rotation_offset ;
state [ " snap_rotation_step " ] = snap_rotation_step ;
2019-10-30 14:18:57 +00:00
state [ " snap_scale_step " ] = snap_scale_step ;
2019-10-10 17:41:45 +00:00
state [ " smart_snap_active " ] = smart_snap_active ;
state [ " grid_snap_active " ] = grid_snap_active ;
2017-11-07 07:58:35 +00:00
state [ " snap_node_parent " ] = snap_node_parent ;
state [ " snap_node_anchors " ] = snap_node_anchors ;
state [ " snap_node_sides " ] = snap_node_sides ;
state [ " snap_node_center " ] = snap_node_center ;
state [ " snap_other_nodes " ] = snap_other_nodes ;
state [ " snap_guides " ] = snap_guides ;
state [ " show_grid " ] = show_grid ;
2018-03-02 08:52:13 +00:00
state [ " show_origin " ] = show_origin ;
state [ " show_viewport " ] = show_viewport ;
2017-11-07 07:58:35 +00:00
state [ " show_rulers " ] = show_rulers ;
state [ " show_guides " ] = show_guides ;
state [ " show_helpers " ] = show_helpers ;
2019-05-20 20:36:34 +00:00
state [ " show_zoom_control " ] = zoom_hb - > is_visible ( ) ;
2018-09-20 00:41:19 +00:00
state [ " show_edit_locks " ] = show_edit_locks ;
2017-11-07 07:58:35 +00:00
state [ " snap_rotation " ] = snap_rotation ;
2019-10-30 14:18:57 +00:00
state [ " snap_scale " ] = snap_scale ;
2017-11-07 07:58:35 +00:00
state [ " snap_relative " ] = snap_relative ;
state [ " snap_pixel " ] = snap_pixel ;
state [ " skeleton_show_bones " ] = skeleton_show_bones ;
return state ;
}
void CanvasItemEditor : : set_state ( const Dictionary & p_state ) {
2019-05-20 20:35:31 +00:00
bool update_scrollbars = false ;
2017-11-07 07:58:35 +00:00
Dictionary state = p_state ;
if ( state . has ( " zoom " ) ) {
2020-01-04 17:43:52 +00:00
// Compensate the editor scale, so that the editor scale can be changed
// and the zoom level will still be the same (relative to the editor scale).
2020-01-18 21:07:27 +00:00
zoom = float ( p_state [ " zoom " ] ) * MAX ( 1 , EDSCALE ) ;
2019-09-17 04:43:08 +00:00
_update_zoom_label ( ) ;
2017-11-07 07:58:35 +00:00
}
if ( state . has ( " ofs " ) ) {
2018-03-15 14:12:16 +00:00
view_offset = p_state [ " ofs " ] ;
previous_update_view_offset = view_offset ;
2019-05-20 20:35:31 +00:00
update_scrollbars = true ;
2017-11-07 07:58:35 +00:00
}
if ( state . has ( " grid_offset " ) ) {
grid_offset = state [ " grid_offset " ] ;
}
if ( state . has ( " grid_step " ) ) {
grid_step = state [ " grid_step " ] ;
}
2019-10-15 08:23:38 +00:00
if ( state . has ( " primary_grid_steps " ) ) {
primary_grid_steps = state [ " primary_grid_steps " ] ;
}
2017-11-07 07:58:35 +00:00
if ( state . has ( " snap_rotation_step " ) ) {
snap_rotation_step = state [ " snap_rotation_step " ] ;
}
if ( state . has ( " snap_rotation_offset " ) ) {
snap_rotation_offset = state [ " snap_rotation_offset " ] ;
}
2019-10-30 14:18:57 +00:00
if ( state . has ( " snap_scale_step " ) ) {
snap_scale_step = state [ " snap_scale_step " ] ;
}
2019-10-10 17:41:45 +00:00
if ( state . has ( " smart_snap_active " ) ) {
smart_snap_active = state [ " smart_snap_active " ] ;
smart_snap_button - > set_pressed ( smart_snap_active ) ;
}
if ( state . has ( " grid_snap_active " ) ) {
grid_snap_active = state [ " grid_snap_active " ] ;
2019-10-14 09:40:55 +00:00
grid_snap_button - > set_pressed ( grid_snap_active ) ;
2017-11-07 07:58:35 +00:00
}
if ( state . has ( " snap_node_parent " ) ) {
snap_node_parent = state [ " snap_node_parent " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_PARENT ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_parent ) ;
}
if ( state . has ( " snap_node_anchors " ) ) {
snap_node_anchors = state [ " snap_node_anchors " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_ANCHORS ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_anchors ) ;
}
if ( state . has ( " snap_node_sides " ) ) {
snap_node_sides = state [ " snap_node_sides " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_SIDES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_sides ) ;
}
if ( state . has ( " snap_node_center " ) ) {
snap_node_center = state [ " snap_node_center " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_NODE_CENTER ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_node_center ) ;
}
if ( state . has ( " snap_other_nodes " ) ) {
snap_other_nodes = state [ " snap_other_nodes " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_OTHER_NODES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_other_nodes ) ;
}
if ( state . has ( " snap_guides " ) ) {
snap_guides = state [ " snap_guides " ] ;
int idx = smartsnap_config_popup - > get_item_index ( SNAP_USE_GUIDES ) ;
smartsnap_config_popup - > set_item_checked ( idx , snap_guides ) ;
}
if ( state . has ( " show_grid " ) ) {
show_grid = state [ " show_grid " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_GRID ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_grid ) ;
}
2018-03-02 08:52:13 +00:00
if ( state . has ( " show_origin " ) ) {
show_origin = state [ " show_origin " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_ORIGIN ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_origin ) ;
}
if ( state . has ( " show_viewport " ) ) {
show_viewport = state [ " show_viewport " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_VIEWPORT ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_viewport ) ;
}
2017-11-07 07:58:35 +00:00
if ( state . has ( " show_rulers " ) ) {
show_rulers = state [ " show_rulers " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_RULERS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_rulers ) ;
2019-05-20 20:35:31 +00:00
update_scrollbars = true ;
2017-11-07 07:58:35 +00:00
}
if ( state . has ( " show_guides " ) ) {
show_guides = state [ " show_guides " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_GUIDES ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_guides ) ;
}
if ( state . has ( " show_helpers " ) ) {
show_helpers = state [ " show_helpers " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_HELPERS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_helpers ) ;
}
2018-09-20 00:41:19 +00:00
if ( state . has ( " show_edit_locks " ) ) {
show_edit_locks = state [ " show_edit_locks " ] ;
int idx = view_menu - > get_popup ( ) - > get_item_index ( SHOW_EDIT_LOCKS ) ;
view_menu - > get_popup ( ) - > set_item_checked ( idx , show_edit_locks ) ;
}
2019-05-20 20:36:34 +00:00
if ( state . has ( " show_zoom_control " ) ) {
// This one is not user-controllable, but instrumentable
zoom_hb - > set_visible ( state [ " show_zoom_control " ] ) ;
}
2017-11-07 07:58:35 +00:00
if ( state . has ( " snap_rotation " ) ) {
snap_rotation = state [ " snap_rotation " ] ;
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_ROTATION ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_rotation ) ;
}
2019-10-30 14:18:57 +00:00
if ( state . has ( " snap_scale " ) ) {
snap_scale = state [ " snap_scale " ] ;
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_SCALE ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_scale ) ;
}
2017-11-07 07:58:35 +00:00
if ( state . has ( " snap_relative " ) ) {
snap_relative = state [ " snap_relative " ] ;
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_RELATIVE ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_relative ) ;
}
if ( state . has ( " snap_pixel " ) ) {
snap_pixel = state [ " snap_pixel " ] ;
int idx = snap_config_menu - > get_popup ( ) - > get_item_index ( SNAP_USE_PIXEL ) ;
snap_config_menu - > get_popup ( ) - > set_item_checked ( idx , snap_pixel ) ;
}
if ( state . has ( " skeleton_show_bones " ) ) {
skeleton_show_bones = state [ " skeleton_show_bones " ] ;
int idx = skeleton_menu - > get_popup ( ) - > get_item_index ( SKELETON_SHOW_BONES ) ;
skeleton_menu - > get_popup ( ) - > set_item_checked ( idx , skeleton_show_bones ) ;
}
2019-05-20 20:35:31 +00:00
if ( update_scrollbars ) {
_update_scrollbars ( ) ;
}
2017-11-07 07:58:35 +00:00
viewport - > update ( ) ;
}
2018-10-25 17:08:32 +00:00
void CanvasItemEditor : : add_control_to_info_overlay ( Control * p_control ) {
ERR_FAIL_COND ( ! p_control ) ;
p_control - > set_h_size_flags ( p_control - > get_h_size_flags ( ) & ~ Control : : SIZE_EXPAND_FILL ) ;
info_overlay - > add_child ( p_control ) ;
info_overlay - > set_margin ( MARGIN_LEFT , ( show_rulers ? RULER_WIDTH : 0 ) + 10 ) ;
}
void CanvasItemEditor : : remove_control_from_info_overlay ( Control * p_control ) {
info_overlay - > remove_child ( p_control ) ;
info_overlay - > set_margin ( MARGIN_LEFT , ( show_rulers ? RULER_WIDTH : 0 ) + 10 ) ;
}
2014-02-10 01:10:30 +00:00
void CanvasItemEditor : : add_control_to_menu_panel ( Control * p_control ) {
2018-10-25 17:08:32 +00:00
ERR_FAIL_COND ( ! p_control ) ;
2014-02-10 01:10:30 +00:00
2021-07-30 22:21:56 +00:00
hbc_context_menu - > add_child ( p_control ) ;
2014-02-10 01:10:30 +00:00
}
2018-02-13 21:21:19 +00:00
void CanvasItemEditor : : remove_control_from_menu_panel ( Control * p_control ) {
2021-07-30 22:21:56 +00:00
hbc_context_menu - > remove_child ( p_control ) ;
2018-02-13 21:21:19 +00:00
}
2014-12-28 22:37:25 +00:00
HSplitContainer * CanvasItemEditor : : get_palette_split ( ) {
return palette_split ;
}
2015-01-11 23:52:42 +00:00
VSplitContainer * CanvasItemEditor : : get_bottom_split ( ) {
return bottom_split ;
}
2016-07-28 19:37:52 +00:00
void CanvasItemEditor : : focus_selection ( ) {
_focus_selection ( VIEW_CENTER_TO_SELECTION ) ;
}
2014-02-10 01:10:30 +00:00
CanvasItemEditor : : CanvasItemEditor ( EditorNode * p_editor ) {
2018-11-11 17:32:47 +00:00
key_pos = true ;
key_rot = true ;
key_scale = false ;
show_grid = false ;
show_origin = true ;
show_viewport = true ;
show_helpers = false ;
show_rulers = true ;
show_guides = true ;
show_edit_locks = true ;
2020-01-13 11:13:35 +00:00
zoom = 1.0 / MAX ( 1 , EDSCALE ) ;
2018-11-11 17:32:47 +00:00
view_offset = Point2 ( - 150 - RULER_WIDTH , - 95 - RULER_WIDTH ) ;
previous_update_view_offset = view_offset ; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen
grid_offset = Point2 ( ) ;
2020-01-04 01:23:49 +00:00
grid_step = Point2 ( 8 , 8 ) ; // A power-of-two value works better as a default
2019-10-15 08:23:38 +00:00
primary_grid_steps = 8 ; // A power-of-two value works better as a default
2018-11-11 17:32:47 +00:00
grid_step_multiplier = 0 ;
snap_rotation_offset = 0 ;
snap_rotation_step = 15 / ( 180 / Math_PI ) ;
2019-10-30 14:18:57 +00:00
snap_scale_step = 0.1f ;
2019-10-10 17:41:45 +00:00
smart_snap_active = false ;
grid_snap_active = false ;
2018-11-11 17:32:47 +00:00
snap_node_parent = true ;
snap_node_anchors = true ;
snap_node_sides = true ;
snap_node_center = true ;
snap_other_nodes = true ;
snap_guides = true ;
snap_rotation = false ;
2019-11-10 08:49:13 +00:00
snap_scale = false ;
2019-02-14 19:47:35 +00:00
snap_relative = false ;
2021-09-10 20:10:43 +00:00
// Enable pixel snapping even if pixel snap rendering is disabled in the Project Settings.
// This results in crisper visuals by preventing 2D nodes from being placed at subpixel coordinates.
snap_pixel = true ;
2019-09-20 20:26:26 +00:00
snap_target [ 0 ] = SNAP_TARGET_NONE ;
snap_target [ 1 ] = SNAP_TARGET_NONE ;
2018-11-11 17:32:47 +00:00
2019-11-19 15:02:04 +00:00
selected_from_canvas = false ;
2019-03-31 16:53:24 +00:00
anchors_mode = false ;
2018-11-11 17:32:47 +00:00
skeleton_show_bones = true ;
drag_type = DRAG_NONE ;
drag_from = Vector2 ( ) ;
drag_to = Vector2 ( ) ;
dragged_guide_pos = Point2 ( ) ;
dragged_guide_index = - 1 ;
2019-11-20 15:22:16 +00:00
is_hovering_h_guide = false ;
is_hovering_v_guide = false ;
2019-04-07 14:43:21 +00:00
panning = false ;
2019-06-05 20:35:07 +00:00
pan_pressed = false ;
2018-11-11 17:32:47 +00:00
2019-08-30 20:49:47 +00:00
ruler_tool_active = false ;
ruler_tool_origin = Point2 ( ) ;
2018-11-11 17:32:47 +00:00
bone_last_frame = 0 ;
2018-05-04 21:11:28 +00:00
bone_list_dirty = false ;
2014-02-10 01:10:30 +00:00
tool = TOOL_SELECT ;
2017-03-05 15:44:50 +00:00
undo_redo = p_editor - > get_undo_redo ( ) ;
editor = p_editor ;
editor_selection = p_editor - > 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
editor_selection - > connect ( " selection_changed " , this , " update " ) ;
2019-03-31 16:53:24 +00:00
editor_selection - > connect ( " selection_changed " , this , " _selection_changed " ) ;
2014-02-10 01:10:30 +00:00
2021-07-07 11:19:59 +00:00
editor - > get_scene_tree_dock ( ) - > connect ( " node_created " , this , " _node_created " ) ;
editor - > get_scene_tree_dock ( ) - > connect ( " add_node_used " , this , " _reset_create_position " ) ;
2019-04-06 20:55:01 +00:00
editor - > call_deferred ( " connect " , " play_pressed " , this , " _update_override_camera_button " , make_binds ( true ) ) ;
editor - > call_deferred ( " connect " , " stop_pressed " , this , " _update_override_camera_button " , make_binds ( false ) ) ;
2017-03-05 15:44:50 +00:00
hb = memnew ( HBoxContainer ) ;
add_child ( hb ) ;
2017-09-21 22:12:33 +00:00
hb - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
bottom_split = memnew ( VSplitContainer ) ;
2015-01-11 23:52:42 +00:00
add_child ( bottom_split ) ;
2017-08-19 16:29:37 +00:00
bottom_split - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2015-01-11 23:52:42 +00:00
2017-03-05 15:44:50 +00:00
palette_split = memnew ( HSplitContainer ) ;
2015-01-11 23:52:42 +00:00
bottom_split - > add_child ( palette_split ) ;
2017-08-19 16:29:37 +00:00
palette_split - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2014-12-28 22:37:25 +00:00
2017-08-29 19:50:18 +00:00
viewport_scrollable = memnew ( Control ) ;
2017-11-07 07:58:35 +00:00
palette_split - > add_child ( viewport_scrollable ) ;
2017-08-29 19:50:18 +00:00
viewport_scrollable - > set_mouse_filter ( MOUSE_FILTER_PASS ) ;
2017-11-07 07:58:35 +00:00
viewport_scrollable - > set_clip_contents ( true ) ;
viewport_scrollable - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
viewport_scrollable - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
2018-03-15 14:12:16 +00:00
viewport_scrollable - > connect ( " draw " , this , " _update_scrollbars " ) ;
2014-02-10 01:10:30 +00:00
2017-08-28 19:51:56 +00:00
ViewportContainer * scene_tree = memnew ( ViewportContainer ) ;
2017-08-29 19:50:18 +00:00
viewport_scrollable - > add_child ( scene_tree ) ;
2017-08-28 19:51:56 +00:00
scene_tree - > set_stretch ( true ) ;
2017-09-21 22:12:33 +00:00
scene_tree - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2017-08-28 19:51:56 +00:00
scene_tree - > add_child ( p_editor - > get_scene_root ( ) ) ;
2014-02-10 01:10:30 +00:00
2019-11-18 09:49:37 +00:00
controls_vb = memnew ( VBoxContainer ) ;
controls_vb - > set_begin ( Point2 ( 5 , 5 ) ) ;
zoom_hb = memnew ( HBoxContainer ) ;
// Bring the zoom percentage closer to the zoom buttons
zoom_hb - > add_constant_override ( " separation " , Math : : round ( - 8 * EDSCALE ) ) ;
controls_vb - > add_child ( zoom_hb ) ;
2017-03-05 15:44:50 +00:00
viewport = memnew ( CanvasItemEditorViewport ( p_editor , this ) ) ;
2017-08-29 19:50:18 +00:00
viewport_scrollable - > add_child ( viewport ) ;
viewport - > set_mouse_filter ( MOUSE_FILTER_PASS ) ;
2017-09-21 22:12:33 +00:00
viewport - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2017-01-09 18:50:08 +00:00
viewport - > set_clip_contents ( true ) ;
2017-11-07 07:58:35 +00:00
viewport - > set_focus_mode ( FOCUS_ALL ) ;
2017-08-28 19:51:56 +00:00
viewport - > connect ( " draw " , this , " _draw_viewport " ) ;
2017-10-15 20:33:25 +00:00
viewport - > connect ( " gui_input " , this , " _gui_input_viewport " ) ;
2017-08-29 19:50:18 +00:00
2018-10-25 17:08:32 +00:00
info_overlay = memnew ( VBoxContainer ) ;
info_overlay - > set_anchors_and_margins_preset ( Control : : PRESET_BOTTOM_LEFT ) ;
info_overlay - > set_margin ( MARGIN_LEFT , 10 ) ;
info_overlay - > set_margin ( MARGIN_BOTTOM , - 15 ) ;
info_overlay - > set_v_grow_direction ( Control : : GROW_DIRECTION_BEGIN ) ;
info_overlay - > add_constant_override ( " separation " , 10 ) ;
viewport_scrollable - > add_child ( info_overlay ) ;
2021-08-13 22:06:21 +00:00
// Make sure all labels inside of the container are styled the same.
2018-10-25 17:08:32 +00:00
Theme * info_overlay_theme = memnew ( Theme ) ;
info_overlay - > set_theme ( info_overlay_theme ) ;
warning_child_of_container = memnew ( Label ) ;
warning_child_of_container - > hide ( ) ;
2018-12-13 13:16:20 +00:00
warning_child_of_container - > set_text ( TTR ( " Warning: Children of a container get their position and size determined only by their parent. " ) ) ;
2018-10-25 17:08:32 +00:00
add_control_to_info_overlay ( warning_child_of_container ) ;
2017-08-19 16:29:37 +00:00
h_scroll = memnew ( HScrollBar ) ;
viewport - > add_child ( h_scroll ) ;
2018-03-15 14:12:16 +00:00
h_scroll - > connect ( " value_changed " , this , " _update_scroll " ) ;
2014-02-10 01:10:30 +00:00
h_scroll - > hide ( ) ;
2017-08-19 16:29:37 +00:00
v_scroll = memnew ( VScrollBar ) ;
viewport - > add_child ( v_scroll ) ;
2018-03-15 14:12:16 +00:00
v_scroll - > connect ( " value_changed " , this , " _update_scroll " ) ;
2014-02-10 01:10:30 +00:00
v_scroll - > hide ( ) ;
2017-08-19 16:29:37 +00:00
2019-11-18 09:49:37 +00:00
viewport - > add_child ( controls_vb ) ;
2017-08-19 16:29:37 +00:00
zoom_minus = memnew ( ToolButton ) ;
zoom_hb - > add_child ( zoom_minus ) ;
2017-11-07 07:58:35 +00:00
zoom_minus - > connect ( " pressed " , this , " _button_zoom_minus " ) ;
2018-11-24 04:38:26 +00:00
zoom_minus - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/zoom_minus " , TTR ( " Zoom Out " ) , KEY_MASK_CMD | KEY_MINUS ) ) ;
2017-08-19 16:29:37 +00:00
zoom_minus - > set_focus_mode ( FOCUS_NONE ) ;
zoom_reset = memnew ( ToolButton ) ;
zoom_hb - > add_child ( zoom_reset ) ;
2017-11-07 07:58:35 +00:00
zoom_reset - > connect ( " pressed " , this , " _button_zoom_reset " ) ;
2018-11-24 04:38:26 +00:00
zoom_reset - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/zoom_reset " , TTR ( " Zoom Reset " ) , KEY_MASK_CMD | KEY_0 ) ) ;
2017-08-19 16:29:37 +00:00
zoom_reset - > set_focus_mode ( FOCUS_NONE ) ;
2019-09-17 04:43:08 +00:00
zoom_reset - > set_text_align ( Button : : TextAlign : : ALIGN_CENTER ) ;
// Prevent the button's size from changing when the text size changes
zoom_reset - > set_custom_minimum_size ( Size2 ( 75 * EDSCALE , 0 ) ) ;
2017-08-19 16:29:37 +00:00
zoom_plus = memnew ( ToolButton ) ;
zoom_hb - > add_child ( zoom_plus ) ;
2017-11-07 07:58:35 +00:00
zoom_plus - > connect ( " pressed " , this , " _button_zoom_plus " ) ;
2018-11-24 04:38:26 +00:00
zoom_plus - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/zoom_plus " , TTR ( " Zoom In " ) , KEY_MASK_CMD | KEY_EQUAL ) ) ; // Usually direct access key for PLUS
2017-08-19 16:29:37 +00:00
zoom_plus - > set_focus_mode ( FOCUS_NONE ) ;
2017-03-05 15:44:50 +00:00
updating_scroll = false ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
select_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( select_button ) ;
2017-08-19 16:29:37 +00:00
select_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
select_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_SELECT ) ) ;
2014-02-10 01:10:30 +00:00
select_button - > set_pressed ( true ) ;
2017-03-05 15:44:50 +00:00
select_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/select_mode " , TTR ( " Select Mode " ) , KEY_Q ) ) ;
2021-07-23 20:30:58 +00:00
select_button - > set_tooltip ( keycode_get_string ( KEY_MASK_CMD ) + TTR ( " Drag: Rotate selected node around pivot. " ) + " \n " + TTR ( " Alt+Drag: Move selected node. " ) + " \n " + TTR ( " V: Set selected node's pivot position. " ) + " \n " + TTR ( " Alt+RMB: Show list of all nodes at position clicked, including locked. " ) + " \n " + keycode_get_string ( KEY_MASK_CMD ) + TTR ( " RMB: Add node at position clicked. " ) ) ;
2015-12-13 20:16:13 +00:00
2018-09-10 12:39:46 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2017-03-05 15:44:50 +00:00
move_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( move_button ) ;
2017-08-19 16:29:37 +00:00
move_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
move_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_MOVE ) ) ;
2017-03-05 15:44:50 +00:00
move_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/move_mode " , TTR ( " Move Mode " ) , KEY_W ) ) ;
2016-07-15 19:22:01 +00:00
move_button - > set_tooltip ( TTR ( " Move Mode " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
rotate_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( rotate_button ) ;
2017-08-19 16:29:37 +00:00
rotate_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
rotate_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_ROTATE ) ) ;
2017-03-05 15:44:50 +00:00
rotate_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/rotate_mode " , TTR ( " Rotate Mode " ) , KEY_E ) ) ;
2016-07-15 19:22:01 +00:00
rotate_button - > set_tooltip ( TTR ( " Rotate Mode " ) ) ;
2014-02-10 01:10:30 +00:00
2018-09-15 15:44:26 +00:00
scale_button = memnew ( ToolButton ) ;
hb - > add_child ( scale_button ) ;
scale_button - > set_toggle_mode ( true ) ;
scale_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_SCALE ) ) ;
scale_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/scale_mode " , TTR ( " Scale Mode " ) , KEY_S ) ) ;
scale_button - > set_tooltip ( TTR ( " Scale Mode " ) ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2017-03-05 15:44:50 +00:00
list_select_button = memnew ( ToolButton ) ;
2015-12-13 20:16:13 +00:00
hb - > add_child ( list_select_button ) ;
2017-08-19 16:29:37 +00:00
list_select_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
list_select_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_LIST_SELECT ) ) ;
2016-05-18 22:08:12 +00:00
list_select_button - > set_tooltip ( TTR ( " Show a list of all objects at the position clicked \n (same as Alt+RMB in select mode). " ) ) ;
2015-12-13 20:16:13 +00:00
2017-03-05 15:44:50 +00:00
pivot_button = memnew ( ToolButton ) ;
2015-12-28 12:38:15 +00:00
hb - > add_child ( pivot_button ) ;
2017-08-19 16:29:37 +00:00
pivot_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
pivot_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_EDIT_PIVOT ) ) ;
2016-05-18 22:08:12 +00:00
pivot_button - > set_tooltip ( TTR ( " Click to change object's rotation pivot. " ) ) ;
2015-12-28 12:38:15 +00:00
2017-03-05 15:44:50 +00:00
pan_button = memnew ( ToolButton ) ;
2014-05-02 11:39:12 +00:00
hb - > add_child ( pan_button ) ;
2017-08-19 16:29:37 +00:00
pan_button - > set_toggle_mode ( true ) ;
2017-11-07 07:58:35 +00:00
pan_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_PAN ) ) ;
2020-05-26 13:31:29 +00:00
pan_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/pan_mode " , TTR ( " Pan Mode " ) , KEY_G ) ) ;
2016-05-04 01:25:37 +00:00
pan_button - > set_tooltip ( TTR ( " Pan Mode " ) ) ;
2014-05-02 11:39:12 +00:00
2019-08-30 20:49:47 +00:00
ruler_button = memnew ( ToolButton ) ;
hb - > add_child ( ruler_button ) ;
ruler_button - > set_toggle_mode ( true ) ;
ruler_button - > connect ( " pressed " , this , " _button_tool_select " , make_binds ( TOOL_RULER ) ) ;
ruler_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/ruler_mode " , TTR ( " Ruler Mode " ) , KEY_R ) ) ;
ruler_button - > set_tooltip ( TTR ( " Ruler Mode " ) ) ;
2014-05-02 11:39:12 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2019-10-10 17:41:45 +00:00
smart_snap_button = memnew ( ToolButton ) ;
hb - > add_child ( smart_snap_button ) ;
smart_snap_button - > set_toggle_mode ( true ) ;
smart_snap_button - > connect ( " toggled " , this , " _button_toggle_smart_snap " ) ;
smart_snap_button - > set_tooltip ( TTR ( " Toggle smart snapping. " ) ) ;
smart_snap_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/use_smart_snap " , TTR ( " Use Smart Snap " ) , KEY_MASK_SHIFT | KEY_S ) ) ;
grid_snap_button = memnew ( ToolButton ) ;
hb - > add_child ( grid_snap_button ) ;
grid_snap_button - > set_toggle_mode ( true ) ;
grid_snap_button - > connect ( " toggled " , this , " _button_toggle_grid_snap " ) ;
grid_snap_button - > set_tooltip ( TTR ( " Toggle grid snapping. " ) ) ;
grid_snap_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/use_grid_snap " , TTR ( " Use Grid Snap " ) , KEY_MASK_SHIFT | KEY_G ) ) ;
2017-09-17 20:52:41 +00:00
snap_config_menu = memnew ( MenuButton ) ;
hb - > add_child ( snap_config_menu ) ;
snap_config_menu - > set_h_size_flags ( SIZE_SHRINK_END ) ;
2018-05-28 15:54:07 +00:00
snap_config_menu - > set_tooltip ( TTR ( " Snapping Options " ) ) ;
2019-04-20 18:52:01 +00:00
snap_config_menu - > set_switch_on_hover ( true ) ;
2017-09-17 20:52:41 +00:00
PopupMenu * p = snap_config_menu - > get_popup ( ) ;
p - > connect ( " id_pressed " , this , " _popup_callback " ) ;
p - > set_hide_on_checkable_item_selection ( false ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/use_rotation_snap " , TTR ( " Use Rotation Snap " ) ) , SNAP_USE_ROTATION ) ;
2019-10-30 14:18:57 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/use_scale_snap " , TTR ( " Use Scale Snap " ) ) , SNAP_USE_SCALE ) ;
2017-09-17 20:52:41 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_relative " , TTR ( " Snap Relative " ) ) , SNAP_RELATIVE ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/use_pixel_snap " , TTR ( " Use Pixel Snap " ) ) , SNAP_USE_PIXEL ) ;
2019-03-25 00:54:29 +00:00
p - > add_submenu_item ( TTR ( " Smart Snapping " ) , " SmartSnapping " ) ;
2017-09-17 20:52:41 +00:00
2019-08-12 20:23:00 +00:00
p - > add_separator ( ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/configure_snap " , TTR ( " Configure Snap... " ) ) , SNAP_CONFIGURE ) ;
2017-09-17 20:52:41 +00:00
smartsnap_config_popup = memnew ( PopupMenu ) ;
p - > add_child ( smartsnap_config_popup ) ;
smartsnap_config_popup - > set_name ( " SmartSnapping " ) ;
smartsnap_config_popup - > connect ( " id_pressed " , this , " _popup_callback " ) ;
smartsnap_config_popup - > set_hide_on_checkable_item_selection ( false ) ;
2019-03-25 00:54:29 +00:00
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_node_parent " , TTR ( " Snap to Parent " ) ) , SNAP_USE_NODE_PARENT ) ;
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_node_anchors " , TTR ( " Snap to Node Anchor " ) ) , SNAP_USE_NODE_ANCHORS ) ;
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_node_sides " , TTR ( " Snap to Node Sides " ) ) , SNAP_USE_NODE_SIDES ) ;
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_node_center " , TTR ( " Snap to Node Center " ) ) , SNAP_USE_NODE_CENTER ) ;
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_other_nodes " , TTR ( " Snap to Other Nodes " ) ) , SNAP_USE_OTHER_NODES ) ;
smartsnap_config_popup - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/snap_guides " , TTR ( " Snap to Guides " ) ) , SNAP_USE_GUIDES ) ;
2017-09-17 20:52:41 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2017-03-05 15:44:50 +00:00
lock_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( lock_button ) ;
2017-03-05 15:44:50 +00:00
lock_button - > connect ( " pressed " , this , " _popup_callback " , varray ( LOCK_SELECTED ) ) ;
2016-05-18 22:08:12 +00:00
lock_button - > set_tooltip ( TTR ( " Lock the selected object in place (can't be moved). " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
unlock_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( unlock_button ) ;
2017-03-05 15:44:50 +00:00
unlock_button - > connect ( " pressed " , this , " _popup_callback " , varray ( UNLOCK_SELECTED ) ) ;
2016-05-04 01:25:37 +00:00
unlock_button - > set_tooltip ( TTR ( " Unlock the selected object (can be moved). " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
group_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( group_button ) ;
2017-03-05 15:44:50 +00:00
group_button - > connect ( " pressed " , this , " _popup_callback " , varray ( GROUP_SELECTED ) ) ;
2016-05-18 22:08:12 +00:00
group_button - > set_tooltip ( TTR ( " Makes sure the object's children are not selectable. " ) ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
ungroup_button = memnew ( ToolButton ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( ungroup_button ) ;
2017-03-05 15:44:50 +00:00
ungroup_button - > connect ( " pressed " , this , " _popup_callback " , varray ( UNGROUP_SELECTED ) ) ;
2016-05-18 22:08:12 +00:00
ungroup_button - > set_tooltip ( TTR ( " Restores the object's children's ability to be selected. " ) ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
2017-09-17 20:52:41 +00:00
skeleton_menu = memnew ( MenuButton ) ;
hb - > add_child ( skeleton_menu ) ;
2018-10-17 07:53:29 +00:00
skeleton_menu - > set_tooltip ( TTR ( " Skeleton Options " ) ) ;
2019-04-20 18:52:01 +00:00
skeleton_menu - > set_switch_on_hover ( true ) ;
2014-02-10 01:10:30 +00:00
2017-09-17 20:52:41 +00:00
p = skeleton_menu - > get_popup ( ) ;
2017-04-14 11:49:50 +00:00
p - > set_hide_on_checkable_item_selection ( false ) ;
2017-09-17 20:52:41 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/skeleton_show_bones " , TTR ( " Show Bones " ) ) , SKELETON_SHOW_BONES ) ;
2014-02-10 01:10:30 +00:00
p - > add_separator ( ) ;
2017-09-17 20:52:41 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/skeleton_set_ik_chain " , TTR ( " Make IK Chain " ) ) , SKELETON_SET_IK_CHAIN ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/skeleton_clear_ik_chain " , TTR ( " Clear IK Chain " ) ) , SKELETON_CLEAR_IK_CHAIN ) ;
2018-05-04 19:46:32 +00:00
p - > add_separator ( ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/skeleton_make_bones " , TTR ( " Make Custom Bone(s) from Node(s) " ) , KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B ) , SKELETON_MAKE_BONES ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/skeleton_clear_bones " , TTR ( " Clear Custom Bones " ) ) , SKELETON_CLEAR_BONES ) ;
2017-09-17 20:52:41 +00:00
p - > connect ( " id_pressed " , this , " _popup_callback " ) ;
hb - > add_child ( memnew ( VSeparator ) ) ;
2014-02-10 01:10:30 +00:00
2019-04-06 20:55:01 +00:00
override_camera_button = memnew ( ToolButton ) ;
hb - > add_child ( override_camera_button ) ;
override_camera_button - > connect ( " toggled " , this , " _button_override_camera " ) ;
override_camera_button - > set_toggle_mode ( true ) ;
override_camera_button - > set_disabled ( true ) ;
_update_override_camera_button ( false ) ;
hb - > add_child ( memnew ( VSeparator ) ) ;
2017-03-05 15:44:50 +00:00
view_menu = memnew ( MenuButton ) ;
2016-05-04 01:25:37 +00:00
view_menu - > set_text ( TTR ( " View " ) ) ;
2014-02-10 01:10:30 +00:00
hb - > add_child ( view_menu ) ;
2017-03-05 15:44:50 +00:00
view_menu - > get_popup ( ) - > connect ( " id_pressed " , this , " _popup_callback " ) ;
2019-04-20 18:52:01 +00:00
view_menu - > set_switch_on_hover ( true ) ;
2014-02-10 01:10:30 +00:00
p = view_menu - > get_popup ( ) ;
2019-04-20 18:52:01 +00:00
p - > set_hide_on_checkable_item_selection ( false ) ;
2021-06-24 18:01:09 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_grid " , TTR ( " Always Show Grid " ) , KEY_MASK_CMD | KEY_G ) , SHOW_GRID ) ;
2018-02-02 19:27:57 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_helpers " , TTR ( " Show Helpers " ) , KEY_H ) , SHOW_HELPERS ) ;
2019-10-08 21:26:21 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_rulers " , TTR ( " Show Rulers " ) ) , SHOW_RULERS ) ;
2018-02-02 19:27:57 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_guides " , TTR ( " Show Guides " ) , KEY_Y ) , SHOW_GUIDES ) ;
2018-03-02 08:52:13 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_origin " , TTR ( " Show Origin " ) ) , SHOW_ORIGIN ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_viewport " , TTR ( " Show Viewport " ) ) , SHOW_VIEWPORT ) ;
2018-09-20 00:41:19 +00:00
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/show_edit_locks " , TTR ( " Show Group And Lock Icons " ) ) , SHOW_EDIT_LOCKS ) ;
2014-07-06 14:49:27 +00:00
p - > add_separator ( ) ;
2016-06-29 20:02:26 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/center_selection " , TTR ( " Center Selection " ) , KEY_F ) , VIEW_CENTER_TO_SELECTION ) ;
2016-07-15 19:38:43 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/frame_selection " , TTR ( " Frame Selection " ) , KEY_MASK_SHIFT | KEY_F ) , VIEW_FRAME_TO_SELECTION ) ;
2019-08-24 20:58:16 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/clear_guides " , TTR ( " Clear Guides " ) ) , CLEAR_GUIDES ) ;
2019-04-05 13:24:54 +00:00
p - > add_separator ( ) ;
p - > add_check_shortcut ( ED_SHORTCUT ( " canvas_item_editor/preview_canvas_scale " , TTR ( " Preview Canvas Scale " ) , KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_P ) , PREVIEW_CANVAS_SCALE ) ;
2014-02-10 01:10:30 +00:00
2021-07-30 22:21:56 +00:00
hb - > add_child ( memnew ( VSeparator ) ) ;
context_menu_container = memnew ( PanelContainer ) ;
hbc_context_menu = memnew ( HBoxContainer ) ;
context_menu_container - > add_child ( hbc_context_menu ) ;
// Use a custom stylebox to make contextual menu items stand out from the rest.
// This helps with editor usability as contextual menu items change when selecting nodes,
// even though it may not be immediately obvious at first.
hb - > add_child ( context_menu_container ) ;
_update_context_menu_stylebox ( ) ;
2017-10-03 22:47:40 +00:00
presets_menu = memnew ( MenuButton ) ;
presets_menu - > set_text ( TTR ( " Layout " ) ) ;
2021-07-30 22:21:56 +00:00
hbc_context_menu - > add_child ( presets_menu ) ;
2017-10-03 22:47:40 +00:00
presets_menu - > hide ( ) ;
2019-04-20 18:52:01 +00:00
presets_menu - > set_switch_on_hover ( true ) ;
2017-10-03 22:47:40 +00:00
p = presets_menu - > get_popup ( ) ;
p - > connect ( " id_pressed " , this , " _popup_callback " ) ;
2015-08-24 04:00:39 +00:00
2017-10-03 22:47:40 +00:00
anchors_popup = memnew ( PopupMenu ) ;
p - > add_child ( anchors_popup ) ;
anchors_popup - > set_name ( " Anchors " ) ;
anchors_popup - > connect ( " id_pressed " , this , " _popup_callback " ) ;
2015-08-24 04:00:39 +00:00
2019-03-31 16:53:24 +00:00
anchor_mode_button = memnew ( ToolButton ) ;
2021-07-30 22:21:56 +00:00
hbc_context_menu - > add_child ( anchor_mode_button ) ;
2019-03-31 16:53:24 +00:00
anchor_mode_button - > set_toggle_mode ( true ) ;
anchor_mode_button - > hide ( ) ;
anchor_mode_button - > connect ( " toggled " , this , " _button_toggle_anchor_mode " ) ;
2017-03-05 15:44:50 +00:00
animation_hb = memnew ( HBoxContainer ) ;
2021-07-30 22:21:56 +00:00
hbc_context_menu - > add_child ( animation_hb ) ;
2017-03-05 15:44:50 +00:00
animation_hb - > add_child ( memnew ( VSeparator ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > hide ( ) ;
2017-10-12 18:59:25 +00:00
key_loc_button = memnew ( Button ) ;
2014-07-06 14:49:27 +00:00
key_loc_button - > set_toggle_mode ( true ) ;
2017-07-18 16:03:06 +00:00
key_loc_button - > set_flat ( true ) ;
2014-07-06 14:49:27 +00:00
key_loc_button - > set_pressed ( true ) ;
key_loc_button - > set_focus_mode ( FOCUS_NONE ) ;
2017-03-05 15:44:50 +00:00
key_loc_button - > connect ( " pressed " , this , " _popup_callback " , varray ( ANIM_INSERT_POS ) ) ;
2019-04-15 03:49:03 +00:00
key_loc_button - > set_tooltip ( TTR ( " Translation mask for inserting keys. " ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > add_child ( key_loc_button ) ;
2017-10-12 18:59:25 +00:00
key_rot_button = memnew ( Button ) ;
2014-07-06 14:49:27 +00:00
key_rot_button - > set_toggle_mode ( true ) ;
2017-07-18 16:03:06 +00:00
key_rot_button - > set_flat ( true ) ;
2014-07-06 14:49:27 +00:00
key_rot_button - > set_pressed ( true ) ;
key_rot_button - > set_focus_mode ( FOCUS_NONE ) ;
2017-03-05 15:44:50 +00:00
key_rot_button - > connect ( " pressed " , this , " _popup_callback " , varray ( ANIM_INSERT_ROT ) ) ;
2019-04-15 03:49:03 +00:00
key_rot_button - > set_tooltip ( TTR ( " Rotation mask for inserting keys. " ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > add_child ( key_rot_button ) ;
2017-10-12 18:59:25 +00:00
key_scale_button = memnew ( Button ) ;
2014-07-06 14:49:27 +00:00
key_scale_button - > set_toggle_mode ( true ) ;
2017-07-18 16:03:06 +00:00
key_scale_button - > set_flat ( true ) ;
2014-07-06 14:49:27 +00:00
key_scale_button - > set_focus_mode ( FOCUS_NONE ) ;
2017-03-05 15:44:50 +00:00
key_scale_button - > connect ( " pressed " , this , " _popup_callback " , varray ( ANIM_INSERT_SCALE ) ) ;
2019-04-15 03:49:03 +00:00
key_scale_button - > set_tooltip ( TTR ( " Scale mask for inserting keys. " ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > add_child ( key_scale_button ) ;
2017-05-02 21:02:06 +00:00
key_insert_button = memnew ( Button ) ;
2017-07-18 16:03:06 +00:00
key_insert_button - > set_flat ( true ) ;
2014-07-06 14:49:27 +00:00
key_insert_button - > set_focus_mode ( FOCUS_NONE ) ;
2017-03-05 15:44:50 +00:00
key_insert_button - > connect ( " pressed " , this , " _popup_callback " , varray ( ANIM_INSERT_KEY ) ) ;
2019-04-15 03:49:03 +00:00
key_insert_button - > set_tooltip ( TTR ( " Insert keys (based on mask). " ) ) ;
2016-06-29 20:02:26 +00:00
key_insert_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_insert_key " , TTR ( " Insert Key " ) , KEY_INSERT ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > add_child ( key_insert_button ) ;
2019-04-15 03:49:03 +00:00
key_auto_insert_button = memnew ( Button ) ;
key_auto_insert_button - > set_flat ( true ) ;
key_auto_insert_button - > set_toggle_mode ( true ) ;
key_auto_insert_button - > set_focus_mode ( FOCUS_NONE ) ;
//key_auto_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY));
2019-11-08 22:31:29 +00:00
key_auto_insert_button - > set_tooltip ( TTR ( " Auto insert keys when objects are translated, rotated or scaled (based on mask). \n Keys are only added to existing tracks, no new tracks will be created. \n Keys must be inserted manually for the first time. " ) ) ;
2019-04-15 03:49:03 +00:00
key_auto_insert_button - > set_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_auto_insert_key " , TTR ( " Auto Insert Key " ) ) ) ;
animation_hb - > add_child ( key_auto_insert_button ) ;
2014-07-06 14:49:27 +00:00
2017-03-05 15:44:50 +00:00
animation_menu = memnew ( MenuButton ) ;
2020-01-21 21:58:11 +00:00
animation_menu - > set_tooltip ( TTR ( " Animation Key and Pose Options " ) ) ;
2014-07-06 14:49:27 +00:00
animation_hb - > add_child ( animation_menu ) ;
2017-03-05 15:44:50 +00:00
animation_menu - > get_popup ( ) - > connect ( " id_pressed " , this , " _popup_callback " ) ;
2019-04-20 18:52:01 +00:00
animation_menu - > set_switch_on_hover ( true ) ;
2014-02-10 01:10:30 +00:00
p = animation_menu - > get_popup ( ) ;
2016-06-29 20:02:26 +00:00
p - > add_shortcut ( ED_GET_SHORTCUT ( " canvas_item_editor/anim_insert_key " ) , ANIM_INSERT_KEY ) ;
2017-03-05 15:44:50 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_insert_key_existing_tracks " , TTR ( " Insert Key (Existing Tracks) " ) , KEY_MASK_CMD + KEY_INSERT ) , ANIM_INSERT_KEY_EXISTING ) ;
2014-02-10 01:10:30 +00:00
p - > add_separator ( ) ;
2016-06-29 20:02:26 +00:00
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_copy_pose " , TTR ( " Copy Pose " ) ) , ANIM_COPY_POSE ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_paste_pose " , TTR ( " Paste Pose " ) ) , ANIM_PASTE_POSE ) ;
p - > add_shortcut ( ED_SHORTCUT ( " canvas_item_editor/anim_clear_pose " , TTR ( " Clear Pose " ) , KEY_MASK_SHIFT | KEY_K ) , ANIM_CLEAR_POSE ) ;
2014-02-10 01:10:30 +00:00
2017-03-05 15:44:50 +00:00
snap_dialog = memnew ( SnapDialog ) ;
snap_dialog - > connect ( " confirmed " , this , " _snap_changed " ) ;
2015-02-15 08:00:55 +00:00
add_child ( snap_dialog ) ;
2017-03-05 15:44:50 +00:00
select_sb = Ref < StyleBoxTexture > ( memnew ( StyleBoxTexture ) ) ;
2014-02-10 01:10:30 +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 ) ;
selection_menu - > set_custom_minimum_size ( Vector2 ( 100 , 0 ) ) ;
2017-01-08 21:18:54 +00:00
selection_menu - > connect ( " id_pressed " , this , " _selection_result_pressed " ) ;
2015-11-04 21:39:07 +00:00
selection_menu - > connect ( " popup_hide " , this , " _selection_menu_hide " ) ;
2021-07-07 11:19:59 +00:00
add_node_menu = memnew ( PopupMenu ) ;
add_child ( add_node_menu ) ;
add_node_menu - > add_icon_item ( editor - > get_scene_tree_dock ( ) - > get_icon ( " Add " , " EditorIcons " ) , TTR ( " Add Node Here " ) ) ;
add_node_menu - > add_icon_item ( editor - > get_scene_tree_dock ( ) - > get_icon ( " Instance " , " EditorIcons " ) , TTR ( " Instance Scene Here " ) ) ;
add_node_menu - > connect ( " id_pressed " , this , " _add_node_pressed " ) ;
2017-08-31 19:54:42 +00:00
multiply_grid_step_shortcut = ED_SHORTCUT ( " canvas_item_editor/multiply_grid_step " , TTR ( " Multiply grid step by 2 " ) , KEY_KP_MULTIPLY ) ;
divide_grid_step_shortcut = ED_SHORTCUT ( " canvas_item_editor/divide_grid_step " , TTR ( " Divide grid step by 2 " ) , KEY_KP_DIVIDE ) ;
2019-06-05 20:35:07 +00:00
pan_view_shortcut = ED_SHORTCUT ( " canvas_item_editor/pan_view " , TTR ( " Pan View " ) , KEY_SPACE ) ;
2017-08-31 19:54:42 +00:00
2017-09-17 20:52:41 +00:00
skeleton_menu - > get_popup ( ) - > set_item_checked ( skeleton_menu - > get_popup ( ) - > get_item_index ( SKELETON_SHOW_BONES ) , true ) ;
2017-03-05 15:44:50 +00:00
singleton = this ;
2016-02-09 19:09:29 +00:00
2021-04-27 22:54:59 +00:00
// To ensure that scripts can parse the list of shortcuts correctly, we have to define
// those shortcuts one by one.
// Resetting zoom to 100% is a duplicate shortcut of `canvas_item_editor/reset_zoom`,
// but it ensures both 1 and Ctrl + 0 can be used to reset zoom.
2021-07-15 17:58:44 +00:00
ED_SHORTCUT ( " canvas_item_editor/zoom_3.125_percent " , TTR ( " Zoom to 3.125% " ) , KEY_MASK_SHIFT | KEY_5 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_6.25_percent " , TTR ( " Zoom to 6.25% " ) , KEY_MASK_SHIFT | KEY_4 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_12.5_percent " , TTR ( " Zoom to 12.5% " ) , KEY_MASK_SHIFT | KEY_3 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_25_percent " , TTR ( " Zoom to 25% " ) , KEY_MASK_SHIFT | KEY_2 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_50_percent " , TTR ( " Zoom to 50% " ) , KEY_MASK_SHIFT | KEY_1 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_100_percent " , TTR ( " Zoom to 100% " ) , KEY_1 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_200_percent " , TTR ( " Zoom to 200% " ) , KEY_2 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_400_percent " , TTR ( " Zoom to 400% " ) , KEY_3 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_800_percent " , TTR ( " Zoom to 800% " ) , KEY_4 ) ;
ED_SHORTCUT ( " canvas_item_editor/zoom_1600_percent " , TTR ( " Zoom to 1600% " ) , KEY_5 ) ;
2021-04-27 22:54:59 +00:00
2014-04-10 03:18:27 +00:00
set_process_unhandled_key_input ( true ) ;
2017-11-07 07:58:35 +00:00
// Update the menus' checkboxes
2018-01-04 18:55:43 +00:00
call_deferred ( " set_state " , get_state ( ) ) ;
2014-02-10 01:10:30 +00:00
}
2021-05-04 14:00:45 +00:00
CanvasItemEditor * CanvasItemEditor : : singleton = nullptr ;
2014-02-10 01:10:30 +00:00
void CanvasItemEditorPlugin : : edit ( Object * p_object ) {
canvas_item_editor - > set_undo_redo ( & get_undo_redo ( ) ) ;
2017-08-24 20:58:51 +00:00
canvas_item_editor - > edit ( Object : : cast_to < CanvasItem > ( p_object ) ) ;
2014-02-10 01:10:30 +00:00
}
bool CanvasItemEditorPlugin : : handles ( Object * p_object ) const {
2017-01-03 02:03:46 +00:00
return p_object - > is_class ( " CanvasItem " ) ;
2014-02-10 01:10:30 +00:00
}
void CanvasItemEditorPlugin : : make_visible ( bool p_visible ) {
if ( p_visible ) {
canvas_item_editor - > show ( ) ;
2017-09-30 14:19:07 +00:00
canvas_item_editor - > set_physics_process ( true ) ;
2017-03-05 15:44:50 +00:00
VisualServer : : get_singleton ( ) - > viewport_set_hide_canvas ( editor - > get_scene_root ( ) - > get_viewport_rid ( ) , false ) ;
2014-02-10 01:10:30 +00:00
} else {
canvas_item_editor - > hide ( ) ;
2017-09-30 14:19:07 +00:00
canvas_item_editor - > set_physics_process ( false ) ;
2017-03-05 15:44:50 +00:00
VisualServer : : get_singleton ( ) - > viewport_set_hide_canvas ( editor - > get_scene_root ( ) - > get_viewport_rid ( ) , true ) ;
2014-02-10 01:10:30 +00:00
}
}
Dictionary CanvasItemEditorPlugin : : get_state ( ) const {
return canvas_item_editor - > get_state ( ) ;
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorPlugin : : set_state ( const Dictionary & p_state ) {
2014-02-10 01:10:30 +00:00
canvas_item_editor - > set_state ( p_state ) ;
}
CanvasItemEditorPlugin : : CanvasItemEditorPlugin ( EditorNode * p_node ) {
2017-03-05 15:44:50 +00:00
editor = p_node ;
canvas_item_editor = memnew ( CanvasItemEditor ( editor ) ) ;
2016-02-08 16:01:54 +00:00
canvas_item_editor - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2014-02-10 01:10:30 +00:00
editor - > get_viewport ( ) - > add_child ( canvas_item_editor ) ;
2017-09-21 22:12:33 +00:00
canvas_item_editor - > set_anchors_and_margins_preset ( Control : : PRESET_WIDE ) ;
2014-02-10 01:10:30 +00:00
canvas_item_editor - > hide ( ) ;
}
2017-03-05 15:44:50 +00:00
CanvasItemEditorPlugin : : ~ CanvasItemEditorPlugin ( ) {
2014-02-10 01:10:30 +00:00
}
2016-10-25 19:27:24 +00:00
void CanvasItemEditorViewport : : _on_mouse_exit ( ) {
2017-03-05 15:44:50 +00:00
if ( ! selector - > is_visible ( ) ) {
2016-10-25 19:27:24 +00:00
_remove_preview ( ) ;
}
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorViewport : : _on_select_type ( Object * selected ) {
2017-08-24 20:58:51 +00:00
CheckBox * check = Object : : cast_to < CheckBox > ( selected ) ;
2016-10-25 19:27:24 +00:00
String type = check - > get_text ( ) ;
2017-11-11 17:57:54 +00:00
selector - > set_title ( vformat ( TTR ( " Add %s " ) , type ) ) ;
2017-03-05 15:44:50 +00:00
label - > set_text ( vformat ( TTR ( " Adding %s... " ) , type ) ) ;
2016-10-25 19:27:24 +00:00
}
2017-11-12 09:50:06 +00:00
void CanvasItemEditorViewport : : _on_change_type_confirmed ( ) {
2021-05-05 10:44:11 +00:00
if ( ! button_group - > get_pressed_button ( ) ) {
2017-01-10 04:04:31 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2017-01-10 04:04:31 +00:00
2017-08-24 20:58:51 +00:00
CheckBox * check = Object : : cast_to < CheckBox > ( button_group - > get_pressed_button ( ) ) ;
2017-03-05 15:44:50 +00:00
default_type = check - > get_text ( ) ;
2016-10-25 19:27:24 +00:00
_perform_drop_data ( ) ;
selector - > hide ( ) ;
}
2017-11-12 09:50:06 +00:00
void CanvasItemEditorViewport : : _on_change_type_closed ( ) {
_remove_preview ( ) ;
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorViewport : : _create_preview ( const Vector < String > & files ) const {
2018-01-09 06:05:15 +00:00
bool add_preview = false ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) {
String path = files [ i ] ;
RES res = ResourceLoader : : load ( path ) ;
2019-09-29 12:17:42 +00:00
ERR_FAIL_COND ( res . is_null ( ) ) ;
2017-08-24 20:58:51 +00:00
Ref < Texture > texture = Ref < Texture > ( Object : : cast_to < Texture > ( * res ) ) ;
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2021-05-04 14:00:45 +00:00
if ( texture ! = nullptr | | scene ! = nullptr ) {
if ( texture ! = nullptr ) {
2017-03-05 15:44:50 +00:00
Sprite * sprite = memnew ( Sprite ) ;
2016-10-25 19:27:24 +00:00
sprite - > set_texture ( texture ) ;
2017-03-05 15:44:50 +00:00
sprite - > set_modulate ( Color ( 1 , 1 , 1 , 0.7f ) ) ;
2017-09-02 19:47:16 +00:00
preview_node - > add_child ( sprite ) ;
2016-10-25 19:27:24 +00:00
label - > show ( ) ;
label_desc - > show ( ) ;
2017-03-13 10:35:27 +00:00
} else {
if ( scene . is_valid ( ) ) {
Node * instance = scene - > instance ( ) ;
2017-03-05 15:44:50 +00:00
if ( instance ) {
2017-09-02 19:47:16 +00:00
preview_node - > add_child ( instance ) ;
2016-10-25 19:27:24 +00:00
}
}
}
2018-01-09 06:05:15 +00:00
add_preview = true ;
2016-10-25 19:27:24 +00:00
}
}
2018-01-09 06:05:15 +00:00
2021-05-05 10:44:11 +00:00
if ( add_preview ) {
2018-01-09 06:05:15 +00:00
editor - > get_scene_root ( ) - > add_child ( preview_node ) ;
2021-05-05 10:44:11 +00:00
}
2016-10-25 19:27:24 +00:00
}
void CanvasItemEditorViewport : : _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 ) ;
2016-10-25 19:27:24 +00:00
}
2017-09-02 19:47:16 +00:00
editor - > get_scene_root ( ) - > remove_child ( preview_node ) ;
2016-10-25 19:27:24 +00:00
label - > hide ( ) ;
label_desc - > hide ( ) ;
}
}
2017-03-05 15:44:50 +00:00
bool CanvasItemEditorViewport : : _cyclical_dependency_exists ( const String & p_target_scene_path , Node * p_desired_node ) {
if ( p_desired_node - > get_filename ( ) = = p_target_scene_path ) {
2016-10-25 19:27:24 +00:00
return true ;
}
2017-03-05 15:44:50 +00:00
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 ) ) {
2016-10-25 19:27:24 +00:00
return true ;
}
}
return false ;
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorViewport : : _create_nodes ( Node * parent , Node * child , String & path , const Point2 & p_point ) {
2021-07-29 04:26:34 +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 ( ) ;
2021-08-15 13:54:19 +00:00
switch ( ProjectSettings : : get_singleton ( ) - > get ( " node/name_casing " ) . operator int ( ) ) {
2021-07-29 04:26:34 +00:00
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 ;
}
child - > set_name ( name ) ;
2017-08-25 15:14:33 +00:00
Ref < Texture > texture = Ref < Texture > ( Object : : cast_to < Texture > ( ResourceCache : : get ( path ) ) ) ;
2016-10-25 19:27:24 +00:00
Size2 texture_size = texture - > get_size ( ) ;
2017-11-22 02:28:02 +00:00
if ( parent ) {
editor_data - > get_undo_redo ( ) . add_do_method ( parent , " add_child " , child ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( child , " set_owner " , editor - > get_edited_scene ( ) ) ;
editor_data - > get_undo_redo ( ) . add_do_reference ( child ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( parent , " remove_child " , child ) ;
} else { // if we haven't parent, lets try to make a child as a parent.
editor_data - > get_undo_redo ( ) . add_do_method ( editor , " set_edited_scene " , child ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( child , " set_owner " , editor - > get_edited_scene ( ) ) ;
editor_data - > get_undo_redo ( ) . add_do_reference ( child ) ;
2021-05-04 14:00:45 +00:00
editor_data - > get_undo_redo ( ) . add_undo_method ( editor , " set_edited_scene " , ( Object * ) nullptr ) ;
2017-11-22 02:28:02 +00:00
}
2016-10-25 19:27:24 +00:00
2017-11-22 02:28:02 +00:00
if ( parent ) {
String new_name = parent - > validate_child_name ( child ) ;
ScriptEditorDebugger * sed = ScriptEditor : : get_singleton ( ) - > get_debugger ( ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( sed , " live_debug_create_node " , editor - > get_edited_scene ( ) - > get_path_to ( parent ) , child - > get_class ( ) , new_name ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( sed , " live_debug_remove_node " , NodePath ( String ( editor - > get_edited_scene ( ) - > get_path_to ( parent ) ) + " / " + new_name ) ) ;
}
2016-10-25 19:27:24 +00:00
// handle with different property for texture
String property = " texture " ;
List < PropertyInfo > props ;
child - > get_property_list ( & props ) ;
2017-03-05 15:44:50 +00:00
for ( const List < PropertyInfo > : : Element * E = props . front ( ) ; E ; E = E - > next ( ) ) {
if ( E - > get ( ) . name = = " config/texture " ) { // Particles2D
property = " config/texture " ;
2016-10-25 19:27:24 +00:00
break ;
2017-03-05 15:44:50 +00:00
} else if ( E - > get ( ) . name = = " texture/texture " ) { // Polygon2D
property = " texture/texture " ;
2016-10-25 19:27:24 +00:00
break ;
2017-03-05 15:44:50 +00:00
} else if ( E - > get ( ) . name = = " normal " ) { // TouchScreenButton
property = " normal " ;
2016-10-25 19:27:24 +00:00
break ;
}
}
2017-03-05 15:44:50 +00:00
editor_data - > get_undo_redo ( ) . add_do_property ( child , property , texture ) ;
2016-10-25 19:27:24 +00:00
// make visible for certain node type
2017-09-30 12:44:01 +00:00
if ( default_type = = " NinePatchRect " ) {
2017-03-05 15:44:50 +00:00
editor_data - > get_undo_redo ( ) . add_do_property ( child , " rect/size " , texture_size ) ;
} else if ( default_type = = " Polygon2D " ) {
2017-01-07 21:25:37 +00:00
PoolVector < Vector2 > list ;
2017-03-05 15:44:50 +00:00
list . push_back ( Vector2 ( 0 , 0 ) ) ;
list . push_back ( Vector2 ( texture_size . width , 0 ) ) ;
list . push_back ( Vector2 ( texture_size . width , texture_size . height ) ) ;
list . push_back ( Vector2 ( 0 , texture_size . height ) ) ;
editor_data - > get_undo_redo ( ) . add_do_property ( child , " polygon " , list ) ;
2016-10-25 19:27:24 +00:00
}
2018-11-16 15:55:28 +00:00
// Compute the global position
Transform2D xform = canvas_item_editor - > get_canvas_transform ( ) ;
Point2 target_position = xform . affine_inverse ( ) . xform ( p_point ) ;
2017-03-22 23:47:51 +00:00
// there's nothing to be used as source position so snapping will work as absolute if enabled
2018-11-16 15:55:28 +00:00
target_position = canvas_item_editor - > snap_point ( target_position ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( child , " set_global_position " , target_position ) ;
2016-10-25 19:27:24 +00:00
}
2017-03-05 15:44:50 +00:00
bool CanvasItemEditorViewport : : _create_instance ( Node * parent , String & path , const Point2 & p_point ) {
Ref < PackedScene > sdata = ResourceLoader : : load ( path ) ;
2016-10-25 19:27:24 +00:00
if ( ! sdata . is_valid ( ) ) { // invalid scene
return false ;
}
2017-03-05 15:44:50 +00:00
Node * instanced_scene = sdata - > instance ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
2016-10-25 19:27:24 +00:00
if ( ! instanced_scene ) { // error on instancing
return false ;
}
2017-03-05 15:44:50 +00:00
if ( editor - > get_edited_scene ( ) - > get_filename ( ) ! = " " ) { // cyclical instancing
2016-10-25 19:27:24 +00:00
if ( _cyclical_dependency_exists ( editor - > get_edited_scene ( ) - > get_filename ( ) , instanced_scene ) ) {
2016-10-31 02:50:34 +00:00
memdelete ( instanced_scene ) ;
2016-10-25 19:27:24 +00:00
return false ;
}
}
2017-07-19 20:00:46 +00:00
instanced_scene - > set_filename ( ProjectSettings : : get_singleton ( ) - > localize_path ( path ) ) ;
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( parent , " add_child " , instanced_scene ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( instanced_scene , " set_owner " , editor - > get_edited_scene ( ) ) ;
2016-10-25 19:27:24 +00:00
editor_data - > get_undo_redo ( ) . add_do_reference ( instanced_scene ) ;
2017-03-05 15:44:50 +00:00
editor_data - > get_undo_redo ( ) . add_undo_method ( parent , " remove_child " , instanced_scene ) ;
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
String new_name = parent - > validate_child_name ( instanced_scene ) ;
ScriptEditorDebugger * sed = ScriptEditor : : get_singleton ( ) - > get_debugger ( ) ;
editor_data - > get_undo_redo ( ) . add_do_method ( sed , " live_debug_instance_node " , editor - > get_edited_scene ( ) - > get_path_to ( parent ) , path , new_name ) ;
editor_data - > get_undo_redo ( ) . add_undo_method ( sed , " live_debug_remove_node " , NodePath ( String ( editor - > get_edited_scene ( ) - > get_path_to ( parent ) ) + " / " + new_name ) ) ;
2016-10-25 19:27:24 +00:00
2017-09-07 21:30:54 +00:00
CanvasItem * parent_ci = Object : : cast_to < CanvasItem > ( parent ) ;
if ( parent_ci ) {
2018-11-16 15:55:28 +00:00
Vector2 target_pos = canvas_item_editor - > get_canvas_transform ( ) . affine_inverse ( ) . xform ( p_point ) ;
target_pos = canvas_item_editor - > snap_point ( target_pos ) ;
2017-09-07 21:30:54 +00:00
target_pos = parent_ci - > get_global_transform_with_canvas ( ) . affine_inverse ( ) . xform ( target_pos ) ;
2020-06-22 12:16:59 +00:00
// Preserve instance position of the original scene.
CanvasItem * instance_ci = Object : : cast_to < CanvasItem > ( instanced_scene ) ;
if ( instance_ci ) {
target_pos + = instance_ci - > _edit_get_position ( ) ;
}
2017-09-07 21:30:54 +00:00
editor_data - > get_undo_redo ( ) . add_do_method ( instanced_scene , " set_position " , target_pos ) ;
2016-10-25 19:27:24 +00:00
}
return true ;
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorViewport : : _perform_drop_data ( ) {
2016-10-25 19:27:24 +00:00
_remove_preview ( ) ;
2018-01-09 06:05:15 +00:00
// Without root dropping multiple files is not allowed
if ( ! target_node & & selected_files . size ( ) > 1 ) {
accept - > set_text ( TTR ( " Cannot instantiate multiple nodes without root. " ) ) ;
accept - > popup_centered_minsize ( ) ;
return ;
}
2016-10-25 19:27:24 +00:00
Vector < String > error_files ;
editor_data - > get_undo_redo ( ) . create_action ( TTR ( " Create Node " ) ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < selected_files . size ( ) ; i + + ) {
String path = selected_files [ i ] ;
RES res = ResourceLoader : : load ( path ) ;
2016-10-25 19:27:24 +00:00
if ( res . is_null ( ) ) {
continue ;
}
2017-08-24 20:58:51 +00:00
Ref < PackedScene > scene = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2021-05-04 14:00:45 +00:00
if ( scene ! = nullptr & & scene . is_valid ( ) ) {
2018-01-09 06:05:15 +00:00
if ( ! target_node ) {
// Without root node act the same as "Load Inherited Scene"
Error err = EditorNode : : get_singleton ( ) - > load_scene ( path , false , true ) ;
if ( err ! = OK ) {
error_files . push_back ( path ) ;
}
} else {
bool success = _create_instance ( target_node , path , drop_pos ) ;
if ( ! success ) {
error_files . push_back ( path ) ;
}
}
} else {
Ref < Texture > texture = Ref < Texture > ( Object : : cast_to < Texture > ( * res ) ) ;
2021-05-04 14:00:45 +00:00
if ( texture ! = nullptr & & texture . is_valid ( ) ) {
2018-01-09 06:05:15 +00:00
Node * child ;
2021-05-05 10:44:11 +00:00
if ( default_type = = " Light2D " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( Light2D ) ;
2021-05-05 10:44:11 +00:00
} else if ( default_type = = " Particles2D " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( Particles2D ) ;
2021-05-05 10:44:11 +00:00
} else if ( default_type = = " Polygon2D " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( Polygon2D ) ;
2021-05-05 10:44:11 +00:00
} else if ( default_type = = " TouchScreenButton " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( TouchScreenButton ) ;
2021-05-05 10:44:11 +00:00
} else if ( default_type = = " TextureRect " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( TextureRect ) ;
2021-05-05 10:44:11 +00:00
} else if ( default_type = = " NinePatchRect " ) {
2018-01-09 06:05:15 +00:00
child = memnew ( NinePatchRect ) ;
2021-05-05 10:44:11 +00:00
} else {
2018-01-09 06:05:15 +00:00
child = memnew ( Sprite ) ; // default
2021-05-05 10:44:11 +00:00
}
2018-01-09 06:05:15 +00:00
_create_nodes ( target_node , child , path , drop_pos ) ;
2016-10-25 19:27:24 +00:00
}
}
}
editor_data - > get_undo_redo ( ) . commit_action ( ) ;
2017-03-05 15:44:50 +00:00
if ( error_files . size ( ) > 0 ) {
2016-10-25 19:27:24 +00:00
String files_str ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < error_files . size ( ) ; i + + ) {
2017-01-14 03:51:09 +00:00
files_str + = error_files [ i ] . get_file ( ) . get_basename ( ) + " , " ;
2016-10-25 19:27:24 +00:00
}
2017-03-05 15:44:50 +00:00
files_str = files_str . substr ( 0 , files_str . length ( ) - 1 ) ;
accept - > set_text ( vformat ( TTR ( " Error instancing scene from %s " ) , files_str . c_str ( ) ) ) ;
2016-10-25 19:27:24 +00:00
accept - > popup_centered_minsize ( ) ;
}
}
2017-03-05 15:44:50 +00:00
bool CanvasItemEditorViewport : : can_drop_data ( const Point2 & p_point , const Variant & p_data ) const {
Dictionary d = p_data ;
2016-10-25 19:27:24 +00:00
if ( d . has ( " type " ) ) {
2017-03-05 15:44:50 +00:00
if ( String ( d [ " type " ] ) = = " files " ) {
Vector < String > files = d [ " files " ] ;
bool can_instance = false ;
2018-01-09 06:05:15 +00:00
for ( int i = 0 ; i < files . size ( ) ; i + + ) { // check if dragged files contain resource or scene can be created at least once
2017-03-05 15:44:50 +00:00
RES res = ResourceLoader : : load ( files [ i ] ) ;
2016-10-25 19:27:24 +00:00
if ( res . is_null ( ) ) {
continue ;
}
2017-03-05 15:44:50 +00:00
String type = res - > get_class ( ) ;
if ( type = = " PackedScene " ) {
2018-01-09 06:05:15 +00:00
Ref < PackedScene > sdata = Ref < PackedScene > ( Object : : cast_to < PackedScene > ( * res ) ) ;
2017-03-05 15:44:50 +00:00
Node * instanced_scene = sdata - > instance ( PackedScene : : GEN_EDIT_STATE_INSTANCE ) ;
2016-10-25 19:27:24 +00:00
if ( ! instanced_scene ) {
continue ;
}
memdelete ( instanced_scene ) ;
2017-09-16 13:57:17 +00:00
} else if ( type = = " Texture " | |
type = = " ImageTexture " | |
type = = " ViewportTexture " | |
type = = " CurveTexture " | |
type = = " GradientTexture " | |
type = = " StreamTexture " | |
type = = " AtlasTexture " | |
type = = " LargeTexture " ) {
2018-01-09 06:05:15 +00:00
Ref < Texture > texture = Ref < Texture > ( Object : : cast_to < Texture > ( * res ) ) ;
2018-10-06 20:20:41 +00:00
if ( ! texture . is_valid ( ) ) {
2017-09-16 13:57:17 +00:00
continue ;
}
} else {
continue ;
2016-10-25 19:27:24 +00:00
}
2017-03-05 15:44:50 +00:00
can_instance = true ;
2016-10-25 19:27:24 +00:00
break ;
}
if ( can_instance ) {
2017-09-02 19:47:16 +00:00
if ( ! preview_node - > get_parent ( ) ) { // create preview only once
2016-10-25 19:27:24 +00:00
_create_preview ( files ) ;
}
2018-11-16 15:55:28 +00:00
Transform2D trans = canvas_item_editor - > get_canvas_transform ( ) ;
2017-09-02 19:47:16 +00:00
preview_node - > set_position ( ( p_point - trans . get_origin ( ) ) / trans . get_scale ( ) . x ) ;
2017-03-05 15:44:50 +00:00
label - > set_text ( vformat ( TTR ( " Adding %s... " ) , default_type ) ) ;
2016-10-25 19:27:24 +00:00
}
return can_instance ;
}
}
label - > hide ( ) ;
return false ;
}
2017-11-22 02:28:02 +00:00
void CanvasItemEditorViewport : : _show_resource_type_selector ( ) {
2018-01-09 06:05:15 +00:00
_remove_preview ( ) ;
2017-11-22 02:28:02 +00:00
List < BaseButton * > btn_list ;
button_group - > get_buttons ( & btn_list ) ;
for ( int i = 0 ; i < btn_list . size ( ) ; i + + ) {
CheckBox * check = Object : : cast_to < CheckBox > ( btn_list [ i ] ) ;
check - > set_pressed ( check - > get_text ( ) = = default_type ) ;
}
selector - > set_title ( vformat ( TTR ( " Add %s " ) , default_type ) ) ;
selector - > popup_centered_minsize ( ) ;
}
2018-01-09 06:05:15 +00:00
bool CanvasItemEditorViewport : : _only_packed_scenes_selected ( ) const {
for ( int i = 0 ; i < selected_files . size ( ) ; + + i ) {
if ( ResourceLoader : : load ( selected_files [ i ] ) - > get_class ( ) ! = " PackedScene " ) {
return false ;
}
}
return true ;
}
2017-03-05 15:44:50 +00:00
void CanvasItemEditorViewport : : drop_data ( const Point2 & p_point , const Variant & p_data ) {
bool is_shift = Input : : get_singleton ( ) - > is_key_pressed ( KEY_SHIFT ) ;
bool is_alt = Input : : get_singleton ( ) - > is_key_pressed ( KEY_ALT ) ;
2016-10-25 19:27:24 +00:00
selected_files . clear ( ) ;
2017-03-05 15:44:50 +00:00
Dictionary d = p_data ;
if ( d . has ( " type " ) & & String ( d [ " type " ] ) = = " files " ) {
selected_files = d [ " files " ] ;
2016-10-25 19:27:24 +00:00
}
2021-05-05 10:44:11 +00:00
if ( selected_files . size ( ) = = 0 ) {
2018-01-09 06:05:15 +00:00
return ;
2021-05-05 10:44:11 +00:00
}
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
List < Node * > list = editor - > get_editor_selection ( ) - > get_selected_node_list ( ) ;
if ( list . size ( ) = = 0 ) {
2017-09-02 19:47:16 +00:00
Node * root_node = editor - > get_edited_scene ( ) ;
if ( root_node ) {
list . push_back ( root_node ) ;
} else {
2017-11-22 02:28:02 +00:00
drop_pos = p_point ;
2021-05-04 14:00:45 +00:00
target_node = nullptr ;
2017-09-02 19:47:16 +00:00
}
2016-10-25 19:27:24 +00:00
}
2018-01-09 06:05:15 +00:00
if ( list . size ( ) > 0 ) {
target_node = list [ 0 ] ;
if ( is_shift & & target_node ! = editor - > get_edited_scene ( ) ) {
target_node = target_node - > get_parent ( ) ;
}
2016-10-25 19:27:24 +00:00
}
2018-01-09 06:05:15 +00:00
2017-03-05 15:44:50 +00:00
drop_pos = p_point ;
2016-10-25 19:27:24 +00:00
2018-01-09 06:05:15 +00:00
if ( is_alt & & ! _only_packed_scenes_selected ( ) ) {
2017-11-22 02:28:02 +00:00
_show_resource_type_selector ( ) ;
2016-10-25 19:27:24 +00:00
} else {
_perform_drop_data ( ) ;
}
}
void CanvasItemEditorViewport : : _notification ( int p_what ) {
2017-08-10 16:40:28 +00:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
connect ( " mouse_exited " , this , " _on_mouse_exit " ) ;
label - > add_color_override ( " font_color " , get_color ( " warning_color " , " Editor " ) ) ;
} break ;
case NOTIFICATION_EXIT_TREE : {
disconnect ( " mouse_exited " , this , " _on_mouse_exit " ) ;
} break ;
2021-05-04 12:35:44 +00:00
default :
break ;
2016-10-25 19:27:24 +00:00
}
}
void CanvasItemEditorViewport : : _bind_methods ( ) {
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _on_select_type " ) , & CanvasItemEditorViewport : : _on_select_type ) ;
2017-11-12 09:50:06 +00:00
ClassDB : : bind_method ( D_METHOD ( " _on_change_type_confirmed " ) , & CanvasItemEditorViewport : : _on_change_type_confirmed ) ;
ClassDB : : bind_method ( D_METHOD ( " _on_change_type_closed " ) , & CanvasItemEditorViewport : : _on_change_type_closed ) ;
2017-03-05 15:44:50 +00:00
ClassDB : : bind_method ( D_METHOD ( " _on_mouse_exit " ) , & CanvasItemEditorViewport : : _on_mouse_exit ) ;
2016-10-25 19:27:24 +00:00
}
2018-11-16 15:55:28 +00:00
CanvasItemEditorViewport : : CanvasItemEditorViewport ( EditorNode * p_node , CanvasItemEditor * p_canvas_item_editor ) {
2017-03-05 15:44:50 +00:00
default_type = " Sprite " ;
2016-10-25 19:27:24 +00:00
// Node2D
types . push_back ( " Sprite " ) ;
types . push_back ( " Light2D " ) ;
types . push_back ( " Particles2D " ) ;
types . push_back ( " Polygon2D " ) ;
types . push_back ( " TouchScreenButton " ) ;
// Control
2017-01-12 21:27:27 +00:00
types . push_back ( " TextureRect " ) ;
2017-09-30 12:44:01 +00:00
types . push_back ( " NinePatchRect " ) ;
2016-10-25 19:27:24 +00:00
2021-05-04 14:00:45 +00:00
target_node = nullptr ;
2017-03-05 15:44:50 +00:00
editor = p_node ;
editor_data = editor - > get_scene_tree_dock ( ) - > get_editor_data ( ) ;
2018-11-16 15:55:28 +00:00
canvas_item_editor = p_canvas_item_editor ;
2017-09-02 19:47:16 +00:00
preview_node = memnew ( Node2D ) ;
2017-08-19 16:29:37 +00:00
2017-03-05 15:44:50 +00:00
accept = memnew ( AcceptDialog ) ;
2016-10-25 19:27:24 +00:00
editor - > get_gui_base ( ) - > add_child ( accept ) ;
2017-08-10 16:40:28 +00:00
selector = memnew ( AcceptDialog ) ;
2017-08-19 16:29:37 +00:00
editor - > get_gui_base ( ) - > add_child ( selector ) ;
2019-03-25 00:54:29 +00:00
selector - > set_title ( TTR ( " Change Default Type " ) ) ;
2017-11-12 09:50:06 +00:00
selector - > connect ( " confirmed " , this , " _on_change_type_confirmed " ) ;
selector - > connect ( " popup_hide " , this , " _on_change_type_closed " ) ;
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
VBoxContainer * vbc = memnew ( VBoxContainer ) ;
2017-08-19 16:29:37 +00:00
selector - > add_child ( vbc ) ;
2017-08-10 16:40:28 +00:00
vbc - > set_h_size_flags ( SIZE_EXPAND_FILL ) ;
vbc - > set_v_size_flags ( SIZE_EXPAND_FILL ) ;
2020-07-11 19:21:45 +00:00
vbc - > set_custom_minimum_size ( Size2 ( 240 , 260 ) * EDSCALE ) ;
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
btn_group = memnew ( VBoxContainer ) ;
2017-08-19 16:29:37 +00:00
vbc - > add_child ( btn_group ) ;
2016-10-25 19:27:24 +00:00
btn_group - > set_h_size_flags ( 0 ) ;
2017-08-19 16:29:37 +00:00
button_group . instance ( ) ;
2017-03-05 15:44:50 +00:00
for ( int i = 0 ; i < types . size ( ) ; i + + ) {
CheckBox * check = memnew ( CheckBox ) ;
2017-08-19 16:29:37 +00:00
btn_group - > add_child ( check ) ;
2016-10-25 19:27:24 +00:00
check - > set_text ( types [ i ] ) ;
2017-04-10 04:00:08 +00:00
check - > connect ( " button_down " , this , " _on_select_type " , varray ( check ) ) ;
2017-01-10 04:04:31 +00:00
check - > set_button_group ( button_group ) ;
2016-10-25 19:27:24 +00:00
}
2017-03-05 15:44:50 +00:00
label = memnew ( Label ) ;
label - > add_color_override ( " font_color_shadow " , Color ( 0 , 0 , 0 , 1 ) ) ;
label - > add_constant_override ( " shadow_as_outline " , 1 * EDSCALE ) ;
2016-10-25 19:27:24 +00:00
label - > hide ( ) ;
2019-11-18 09:49:37 +00:00
canvas_item_editor - > get_controls_container ( ) - > add_child ( label ) ;
2016-10-25 19:27:24 +00:00
2017-03-05 15:44:50 +00:00
label_desc = memnew ( Label ) ;
2016-10-25 19:27:24 +00:00
label_desc - > set_text ( TTR ( " Drag & drop + Shift : Add node as sibling \n Drag & drop + Alt : Change node type " ) ) ;
2017-03-13 10:35:27 +00:00
label_desc - > add_color_override ( " font_color " , Color ( 0.6f , 0.6f , 0.6f , 1 ) ) ;
label_desc - > add_color_override ( " font_color_shadow " , Color ( 0.2f , 0.2f , 0.2f , 1 ) ) ;
2017-03-05 15:44:50 +00:00
label_desc - > add_constant_override ( " shadow_as_outline " , 1 * EDSCALE ) ;
2016-10-25 19:27:24 +00:00
label_desc - > add_constant_override ( " line_spacing " , 0 ) ;
label_desc - > hide ( ) ;
2019-11-18 09:49:37 +00:00
canvas_item_editor - > get_controls_container ( ) - > add_child ( label_desc ) ;
2019-04-05 13:24:54 +00:00
VS : : get_singleton ( ) - > canvas_set_disable_scale ( true ) ;
2016-10-25 19:27:24 +00:00
}
2017-08-24 16:51:28 +00:00
CanvasItemEditorViewport : : ~ CanvasItemEditorViewport ( ) {
2017-09-02 19:47:16 +00:00
memdelete ( preview_node ) ;
2017-08-24 16:51:28 +00:00
}