1 /*************************************************************************/
2 /*  canvas_item_editor_plugin.cpp                                        */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "canvas_item_editor_plugin.h"
32 
33 #include "core/os/input.h"
34 #include "core/os/keyboard.h"
35 #include "core/print_string.h"
36 #include "core/project_settings.h"
37 #include "editor/editor_node.h"
38 #include "editor/editor_scale.h"
39 #include "editor/editor_settings.h"
40 #include "editor/plugins/animation_player_editor_plugin.h"
41 #include "editor/plugins/script_editor_plugin.h"
42 #include "editor/script_editor_debugger.h"
43 #include "scene/2d/light_2d.h"
44 #include "scene/2d/particles_2d.h"
45 #include "scene/2d/polygon_2d.h"
46 #include "scene/2d/skeleton_2d.h"
47 #include "scene/2d/sprite.h"
48 #include "scene/2d/touch_screen_button.h"
49 #include "scene/gui/grid_container.h"
50 #include "scene/gui/nine_patch_rect.h"
51 #include "scene/gui/viewport_container.h"
52 #include "scene/main/canvas_layer.h"
53 #include "scene/main/viewport.h"
54 #include "scene/resources/packed_scene.h"
55 
56 // Min and Max are power of two in order to play nicely with successive increment.
57 // That way, we can naturally reach a 100% zoom from boundaries.
58 #define MIN_ZOOM 1. / 128
59 #define MAX_ZOOM 128
60 
61 #define RULER_WIDTH (15 * EDSCALE)
62 #define SCALE_HANDLE_DISTANCE 25
63 
64 class SnapDialog : public ConfirmationDialog {
65 
66 	GDCLASS(SnapDialog, ConfirmationDialog);
67 
68 	friend class CanvasItemEditor;
69 
70 	SpinBox *grid_offset_x;
71 	SpinBox *grid_offset_y;
72 	SpinBox *grid_step_x;
73 	SpinBox *grid_step_y;
74 	SpinBox *primary_grid_steps;
75 	SpinBox *rotation_offset;
76 	SpinBox *rotation_step;
77 	SpinBox *scale_step;
78 
79 public:
SnapDialog()80 	SnapDialog() {
81 		const int SPIN_BOX_GRID_RANGE = 16384;
82 		const int SPIN_BOX_ROTATION_RANGE = 360;
83 		const float SPIN_BOX_SCALE_MIN = 0.01f;
84 		const float SPIN_BOX_SCALE_MAX = 100;
85 
86 		Label *label;
87 		VBoxContainer *container;
88 		GridContainer *child_container;
89 
90 		set_title(TTR("Configure Snap"));
91 
92 		container = memnew(VBoxContainer);
93 		add_child(container);
94 
95 		child_container = memnew(GridContainer);
96 		child_container->set_columns(3);
97 		container->add_child(child_container);
98 
99 		label = memnew(Label);
100 		label->set_text(TTR("Grid Offset:"));
101 		child_container->add_child(label);
102 		label->set_h_size_flags(SIZE_EXPAND_FILL);
103 
104 		grid_offset_x = memnew(SpinBox);
105 		grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
106 		grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
107 		grid_offset_x->set_allow_lesser(true);
108 		grid_offset_x->set_allow_greater(true);
109 		grid_offset_x->set_suffix("px");
110 		grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL);
111 		child_container->add_child(grid_offset_x);
112 
113 		grid_offset_y = memnew(SpinBox);
114 		grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
115 		grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
116 		grid_offset_y->set_allow_lesser(true);
117 		grid_offset_y->set_allow_greater(true);
118 		grid_offset_y->set_suffix("px");
119 		grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL);
120 		child_container->add_child(grid_offset_y);
121 
122 		label = memnew(Label);
123 		label->set_text(TTR("Grid Step:"));
124 		child_container->add_child(label);
125 		label->set_h_size_flags(SIZE_EXPAND_FILL);
126 
127 		grid_step_x = memnew(SpinBox);
128 		grid_step_x->set_min(0.01);
129 		grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
130 		grid_step_x->set_allow_greater(true);
131 		grid_step_x->set_suffix("px");
132 		grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL);
133 		child_container->add_child(grid_step_x);
134 
135 		grid_step_y = memnew(SpinBox);
136 		grid_step_y->set_min(0.01);
137 		grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
138 		grid_step_y->set_allow_greater(true);
139 		grid_step_y->set_suffix("px");
140 		grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL);
141 		child_container->add_child(grid_step_y);
142 
143 		child_container = memnew(GridContainer);
144 		child_container->set_columns(2);
145 		container->add_child(child_container);
146 
147 		label = memnew(Label);
148 		label->set_text(TTR("Primary Line Every:"));
149 		label->set_h_size_flags(SIZE_EXPAND_FILL);
150 		child_container->add_child(label);
151 
152 		primary_grid_steps = memnew(SpinBox);
153 		primary_grid_steps->set_min(0);
154 		primary_grid_steps->set_step(1);
155 		primary_grid_steps->set_max(100);
156 		primary_grid_steps->set_allow_greater(true);
157 		primary_grid_steps->set_suffix(TTR("steps"));
158 		primary_grid_steps->set_h_size_flags(SIZE_EXPAND_FILL);
159 		child_container->add_child(primary_grid_steps);
160 
161 		container->add_child(memnew(HSeparator));
162 
163 		// We need to create another GridContainer with the same column count,
164 		// so we can put an HSeparator above
165 		child_container = memnew(GridContainer);
166 		child_container->set_columns(2);
167 		container->add_child(child_container);
168 
169 		label = memnew(Label);
170 		label->set_text(TTR("Rotation Offset:"));
171 		child_container->add_child(label);
172 		label->set_h_size_flags(SIZE_EXPAND_FILL);
173 
174 		rotation_offset = memnew(SpinBox);
175 		rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
176 		rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
177 		rotation_offset->set_suffix("deg");
178 		rotation_offset->set_h_size_flags(SIZE_EXPAND_FILL);
179 		child_container->add_child(rotation_offset);
180 
181 		label = memnew(Label);
182 		label->set_text(TTR("Rotation Step:"));
183 		child_container->add_child(label);
184 		label->set_h_size_flags(SIZE_EXPAND_FILL);
185 
186 		rotation_step = memnew(SpinBox);
187 		rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
188 		rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
189 		rotation_step->set_suffix("deg");
190 		rotation_step->set_h_size_flags(SIZE_EXPAND_FILL);
191 		child_container->add_child(rotation_step);
192 
193 		container->add_child(memnew(HSeparator));
194 
195 		child_container = memnew(GridContainer);
196 		child_container->set_columns(2);
197 		container->add_child(child_container);
198 		label = memnew(Label);
199 		label->set_text(TTR("Scale Step:"));
200 		child_container->add_child(label);
201 		label->set_h_size_flags(SIZE_EXPAND_FILL);
202 
203 		scale_step = memnew(SpinBox);
204 		scale_step->set_min(SPIN_BOX_SCALE_MIN);
205 		scale_step->set_max(SPIN_BOX_SCALE_MAX);
206 		scale_step->set_allow_greater(true);
207 		scale_step->set_h_size_flags(SIZE_EXPAND_FILL);
208 		scale_step->set_step(0.01f);
209 		child_container->add_child(scale_step);
210 	}
211 
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)212 	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) {
213 		grid_offset_x->set_value(p_grid_offset.x);
214 		grid_offset_y->set_value(p_grid_offset.y);
215 		grid_step_x->set_value(p_grid_step.x);
216 		grid_step_y->set_value(p_grid_step.y);
217 		primary_grid_steps->set_value(p_primary_grid_steps);
218 		rotation_offset->set_value(p_rotation_offset * (180 / Math_PI));
219 		rotation_step->set_value(p_rotation_step * (180 / Math_PI));
220 		scale_step->set_value(p_scale_step);
221 	}
222 
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)223 	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) {
224 		p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value());
225 		p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value());
226 		p_primary_grid_steps = int(primary_grid_steps->get_value());
227 		p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI);
228 		p_rotation_step = rotation_step->get_value() / (180 / Math_PI);
229 		p_scale_step = scale_step->get_value();
230 	}
231 };
232 
_is_node_locked(const Node * p_node)233 bool CanvasItemEditor::_is_node_locked(const Node *p_node) {
234 	return p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_");
235 }
236 
_is_node_movable(const Node * p_node,bool p_popup_warning)237 bool CanvasItemEditor::_is_node_movable(const Node *p_node, bool p_popup_warning) {
238 	if (_is_node_locked(p_node)) {
239 		return false;
240 	}
241 	if (Object::cast_to<Control>(p_node) && Object::cast_to<Container>(p_node->get_parent())) {
242 		if (p_popup_warning) {
243 			_popup_warning_temporarily(warning_child_of_container, 3.0);
244 		}
245 		return false;
246 	}
247 	return true;
248 }
249 
_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)250 void CanvasItemEditor::_snap_if_closer_float(
251 		float p_value,
252 		float &r_current_snap, SnapTarget &r_current_snap_target,
253 		float p_target_value, SnapTarget p_snap_target,
254 		float p_radius) {
255 
256 	float radius = p_radius / zoom;
257 	float dist = Math::abs(p_value - p_target_value);
258 	if ((p_radius < 0 || dist < radius) && (r_current_snap_target == SNAP_TARGET_NONE || dist < Math::abs(r_current_snap - p_value))) {
259 		r_current_snap = p_target_value;
260 		r_current_snap_target = p_snap_target;
261 	}
262 }
263 
_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)264 void CanvasItemEditor::_snap_if_closer_point(
265 		Point2 p_value,
266 		Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
267 		Point2 p_target_value, SnapTarget p_snap_target,
268 		real_t rotation,
269 		float p_radius) {
270 
271 	Transform2D rot_trans = Transform2D(rotation, Point2());
272 	p_value = rot_trans.inverse().xform(p_value);
273 	p_target_value = rot_trans.inverse().xform(p_target_value);
274 	r_current_snap = rot_trans.inverse().xform(r_current_snap);
275 
276 	_snap_if_closer_float(
277 			p_value.x,
278 			r_current_snap.x,
279 			r_current_snap_target[0],
280 			p_target_value.x,
281 			p_snap_target,
282 			p_radius);
283 
284 	_snap_if_closer_float(
285 			p_value.y,
286 			r_current_snap.y,
287 			r_current_snap_target[1],
288 			p_target_value.y,
289 			p_snap_target,
290 			p_radius);
291 
292 	r_current_snap = rot_trans.xform(r_current_snap);
293 }
294 
_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)295 void CanvasItemEditor::_snap_other_nodes(
296 		const Point2 p_value,
297 		const Transform2D p_transform_to_snap,
298 		Point2 &r_current_snap, SnapTarget (&r_current_snap_target)[2],
299 		const SnapTarget p_snap_target, List<const CanvasItem *> p_exceptions,
300 		const Node *p_current) {
301 	const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
302 
303 	// Check if the element is in the exception
304 	bool exception = false;
305 	for (List<const CanvasItem *>::Element *E = p_exceptions.front(); E; E = E->next()) {
306 		if (E->get() == p_current) {
307 			exception = true;
308 			break;
309 		}
310 	};
311 
312 	if (canvas_item && !exception) {
313 		Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
314 		if (fmod(ci_transform.get_rotation() - p_transform_to_snap.get_rotation(), (real_t)360.0) == 0.0) {
315 			if (canvas_item->_edit_use_rect()) {
316 				Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
317 				Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
318 
319 				_snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, begin, p_snap_target, ci_transform.get_rotation());
320 				_snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, end, p_snap_target, ci_transform.get_rotation());
321 			} else {
322 				Point2 position = ci_transform.xform(Point2());
323 				_snap_if_closer_point(p_value, r_current_snap, r_current_snap_target, position, p_snap_target, ci_transform.get_rotation());
324 			}
325 		}
326 	}
327 	for (int i = 0; i < p_current->get_child_count(); i++) {
328 		_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));
329 	}
330 }
331 
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)332 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) {
333 
334 	snap_target[0] = SNAP_TARGET_NONE;
335 	snap_target[1] = SNAP_TARGET_NONE;
336 
337 	bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
338 
339 	// Smart snap using the canvas position
340 	Vector2 output = p_target;
341 	real_t rotation = 0.0;
342 
343 	if (p_self_canvas_item) {
344 		rotation = p_self_canvas_item->get_global_transform_with_canvas().get_rotation();
345 
346 		// Parent sides and center
347 		if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
348 			if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
349 				Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
350 				Point2 end = p_self_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
351 				_snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
352 				_snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
353 				_snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
354 			} else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_self_canvas_item->get_parent())) {
355 				if (parent_ci->_edit_use_rect()) {
356 					Point2 begin = p_self_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
357 					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());
358 					_snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_PARENT, rotation);
359 					_snap_if_closer_point(p_target, output, snap_target, (begin + end) / 2.0, SNAP_TARGET_PARENT, rotation);
360 					_snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_PARENT, rotation);
361 				} else {
362 					Point2 position = p_self_canvas_item->get_transform().affine_inverse().xform(Point2());
363 					_snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_PARENT, rotation);
364 				}
365 			}
366 		}
367 
368 		// Self anchors
369 		if ((is_snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
370 			if (const Control *c = Object::cast_to<Control>(p_self_canvas_item)) {
371 				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))));
372 				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))));
373 				_snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF_ANCHORS, rotation);
374 				_snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF_ANCHORS, rotation);
375 			}
376 		}
377 
378 		// Self sides
379 		if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
380 			if (p_self_canvas_item->_edit_use_rect()) {
381 				Point2 begin = p_self_canvas_item->get_global_transform_with_canvas().xform(p_self_canvas_item->_edit_get_rect().get_position());
382 				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());
383 				_snap_if_closer_point(p_target, output, snap_target, begin, SNAP_TARGET_SELF, rotation);
384 				_snap_if_closer_point(p_target, output, snap_target, end, SNAP_TARGET_SELF, rotation);
385 			}
386 		}
387 
388 		// Self center
389 		if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) {
390 			if (p_self_canvas_item->_edit_use_rect()) {
391 				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);
392 				_snap_if_closer_point(p_target, output, snap_target, center, SNAP_TARGET_SELF, rotation);
393 			} else {
394 				Point2 position = p_self_canvas_item->get_global_transform_with_canvas().xform(Point2());
395 				_snap_if_closer_point(p_target, output, snap_target, position, SNAP_TARGET_SELF, rotation);
396 			}
397 		}
398 	}
399 
400 	// Other nodes sides
401 	if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
402 		Transform2D to_snap_transform = Transform2D();
403 		List<const CanvasItem *> exceptions = List<const CanvasItem *>();
404 		for (List<CanvasItem *>::Element *E = p_other_nodes_exceptions.front(); E; E = E->next()) {
405 			exceptions.push_back(E->get());
406 		}
407 		if (p_self_canvas_item) {
408 			exceptions.push_back(p_self_canvas_item);
409 			to_snap_transform = p_self_canvas_item->get_global_transform_with_canvas();
410 		}
411 
412 		_snap_other_nodes(
413 				p_target, to_snap_transform,
414 				output, snap_target,
415 				SNAP_TARGET_OTHER_NODE,
416 				exceptions,
417 				get_tree()->get_edited_scene_root());
418 	}
419 
420 	if (((is_snap_active && snap_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, (real_t)360.0) == 0.0) {
421 		// Guides
422 		if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
423 			Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
424 			for (int i = 0; i < vguides.size(); i++) {
425 				_snap_if_closer_float(p_target.x, output.x, snap_target[0], vguides[i], SNAP_TARGET_GUIDE);
426 			}
427 		}
428 
429 		if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
430 			Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
431 			for (int i = 0; i < hguides.size(); i++) {
432 				_snap_if_closer_float(p_target.y, output.y, snap_target[1], hguides[i], SNAP_TARGET_GUIDE);
433 			}
434 		}
435 	}
436 
437 	if (((grid_snap_active && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, (real_t)360.0) == 0.0) {
438 		// Grid
439 		Point2 offset = grid_offset;
440 		if (snap_relative) {
441 			List<CanvasItem *> selection = _get_edited_canvas_items();
442 			if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
443 				offset = Object::cast_to<Node2D>(selection[0])->get_global_position();
444 			} else if (selection.size() > 0) {
445 				offset = _get_encompassing_rect_from_list(selection).position;
446 			}
447 		}
448 		Point2 grid_output;
449 		grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
450 		grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
451 		_snap_if_closer_point(p_target, output, snap_target, grid_output, SNAP_TARGET_GRID, 0.0, -1.0);
452 	}
453 
454 	if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
455 		// Pixel
456 		output = output.snapped(Size2(1, 1));
457 	}
458 
459 	snap_transform = Transform2D(rotation, output);
460 
461 	return output;
462 }
463 
snap_angle(float p_target,float p_start) const464 float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
465 	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;
466 }
467 
_unhandled_key_input(const Ref<InputEvent> & p_ev)468 void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
469 
470 	Ref<InputEventKey> k = p_ev;
471 
472 	if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
473 		return;
474 
475 	if (k->get_scancode() == KEY_CONTROL || k->get_scancode() == KEY_ALT || k->get_scancode() == KEY_SHIFT) {
476 		viewport->update();
477 	}
478 
479 	if (k->is_pressed() && !k->get_control() && !k->is_echo()) {
480 		if ((grid_snap_active || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
481 			// Multiply the grid size
482 			grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
483 			viewport->update();
484 		} else if ((grid_snap_active || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
485 			// Divide the grid size
486 			Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
487 			if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0)
488 				grid_step_multiplier--;
489 			viewport->update();
490 		}
491 	}
492 }
493 
_get_editor_data(Object * p_what)494 Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
495 
496 	CanvasItem *ci = Object::cast_to<CanvasItem>(p_what);
497 	if (!ci)
498 		return NULL;
499 
500 	return memnew(CanvasItemEditorSelectedItem);
501 }
502 
_keying_changed()503 void CanvasItemEditor::_keying_changed() {
504 
505 	if (AnimationPlayerEditor::singleton->get_track_editor()->is_visible_in_tree())
506 		animation_hb->show();
507 	else
508 		animation_hb->hide();
509 }
510 
_get_encompassing_rect_from_list(List<CanvasItem * > p_list)511 Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_list) {
512 	ERR_FAIL_COND_V(p_list.empty(), Rect2());
513 
514 	// Handles the first element
515 	CanvasItem *canvas_item = p_list.front()->get();
516 	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());
517 
518 	// Expand with the other ones
519 	for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) {
520 		CanvasItem *canvas_item2 = E->get();
521 		Transform2D xform = canvas_item2->get_global_transform_with_canvas();
522 
523 		Rect2 current_rect = canvas_item2->_edit_get_rect();
524 		rect.expand_to(xform.xform(current_rect.position));
525 		rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0)));
526 		rect.expand_to(xform.xform(current_rect.position + current_rect.size));
527 		rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y)));
528 	}
529 
530 	return rect;
531 }
532 
_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)533 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) {
534 	if (!p_node)
535 		return;
536 	if (Object::cast_to<Viewport>(p_node))
537 		return;
538 
539 	const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
540 
541 	for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
542 		if (canvas_item && !canvas_item->is_set_as_toplevel()) {
543 			_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
544 		} else {
545 			const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
546 			_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
547 		}
548 	}
549 
550 	if (canvas_item && canvas_item->is_visible_in_tree() && (include_locked_nodes || !_is_node_locked(canvas_item))) {
551 		Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
552 		Rect2 rect = canvas_item->_edit_get_rect();
553 		if (r_first) {
554 			r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2());
555 			r_first = false;
556 		}
557 		r_rect.expand_to(xform.xform(rect.position));
558 		r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
559 		r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
560 		r_rect.expand_to(xform.xform(rect.position + rect.size));
561 	}
562 }
563 
_get_encompassing_rect(const Node * p_node)564 Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) {
565 	Rect2 rect;
566 	bool first = true;
567 	_expand_encompassing_rect_using_children(rect, p_node, first);
568 
569 	return rect;
570 }
571 
_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)572 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) {
573 	if (!p_node)
574 		return;
575 	if (Object::cast_to<Viewport>(p_node))
576 		return;
577 
578 	const real_t grab_distance = EDITOR_GET("editors/poly_editor/point_grab_radius");
579 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
580 
581 	for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
582 		if (canvas_item) {
583 			if (!canvas_item->is_set_as_toplevel()) {
584 				_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
585 			} else {
586 				_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
587 			}
588 		} else {
589 			CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
590 			_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
591 		}
592 	}
593 
594 	if (canvas_item && canvas_item->is_visible_in_tree()) {
595 		Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse();
596 		const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length() / zoom;
597 		if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) {
598 			Node2D *node = Object::cast_to<Node2D>(canvas_item);
599 
600 			_SelectResult res;
601 			res.item = canvas_item;
602 			res.z_index = node ? node->get_z_index() : 0;
603 			res.has_z = node;
604 			r_items.push_back(res);
605 		}
606 	}
607 }
608 
_get_canvas_items_at_pos(const Point2 & p_pos,Vector<_SelectResult> & r_items)609 void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
610 
611 	Node *scene = editor->get_edited_scene();
612 
613 	_find_canvas_items_at_pos(p_pos, scene, r_items);
614 
615 	//Remove invalid results
616 	for (int i = 0; i < r_items.size(); i++) {
617 		Node *node = r_items[i].item;
618 
619 		// Make sure the selected node is in the current scene, or editable
620 		while (node && node != get_tree()->get_edited_scene_root() && node->get_owner() != scene && !scene->is_editable_instance(node->get_owner())) {
621 			node = node->get_parent();
622 		};
623 
624 		// Replace the node by the group if grouped
625 		CanvasItem *canvas_item = Object::cast_to<CanvasItem>(node);
626 		while (node && node != scene->get_parent()) {
627 			CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node);
628 			if (canvas_item_tmp && node->has_meta("_edit_group_")) {
629 				canvas_item = canvas_item_tmp;
630 			}
631 			node = node->get_parent();
632 		}
633 
634 		// Check if the canvas item is already in the list (for groups or scenes)
635 		bool duplicate = false;
636 		for (int j = 0; j < i; j++) {
637 			if (r_items[j].item == canvas_item) {
638 				duplicate = true;
639 				break;
640 			}
641 		}
642 
643 		//Remove the item if invalid
644 		if (!canvas_item || duplicate || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || _is_node_locked(canvas_item)) {
645 			r_items.remove(i);
646 			i--;
647 		} else {
648 			r_items.write[i].item = canvas_item;
649 		}
650 	}
651 }
652 
_get_bones_at_pos(const Point2 & p_pos,Vector<_SelectResult> & r_items)653 void CanvasItemEditor::_get_bones_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items) {
654 	Point2 screen_pos = transform.xform(p_pos);
655 
656 	for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
657 		Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
658 
659 		Vector<Vector2> bone_shape;
660 		if (!_get_bone_shape(&bone_shape, NULL, E))
661 			continue;
662 
663 		// Check if the point is inside the Polygon2D
664 		if (Geometry::is_point_in_polygon(screen_pos, bone_shape)) {
665 			// Check if the item is already in the list
666 			bool duplicate = false;
667 			for (int i = 0; i < r_items.size(); i++) {
668 				if (r_items[i].item == from_node) {
669 					duplicate = true;
670 					break;
671 				}
672 			}
673 			if (duplicate)
674 				continue;
675 
676 			// Else, add it
677 			_SelectResult res;
678 			res.item = from_node;
679 			res.z_index = from_node ? from_node->get_z_index() : 0;
680 			res.has_z = from_node;
681 			r_items.push_back(res);
682 		}
683 	}
684 }
685 
_get_bone_shape(Vector<Vector2> * shape,Vector<Vector2> * outline_shape,Map<BoneKey,BoneList>::Element * bone)686 bool CanvasItemEditor::_get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *outline_shape, Map<BoneKey, BoneList>::Element *bone) {
687 	int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
688 	int bone_outline_width = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
689 
690 	Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().from));
691 	Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().to));
692 
693 	if (!from_node)
694 		return false;
695 	if (!from_node->is_inside_tree())
696 		return false; //may have been removed
697 
698 	if (!to_node && bone->get().length == 0)
699 		return false;
700 
701 	Vector2 from = transform.xform(from_node->get_global_position());
702 	Vector2 to;
703 
704 	if (to_node)
705 		to = transform.xform(to_node->get_global_position());
706 	else
707 		to = transform.xform(from_node->get_global_transform().xform(Vector2(bone->get().length, 0)));
708 
709 	Vector2 rel = to - from;
710 	Vector2 relt = rel.tangent().normalized() * bone_width;
711 	Vector2 reln = rel.normalized();
712 	Vector2 reltn = relt.normalized();
713 
714 	if (shape) {
715 		shape->clear();
716 		shape->push_back(from);
717 		shape->push_back(from + rel * 0.2 + relt);
718 		shape->push_back(to);
719 		shape->push_back(from + rel * 0.2 - relt);
720 	}
721 
722 	if (outline_shape) {
723 		outline_shape->clear();
724 		outline_shape->push_back(from + (-reln - reltn) * bone_outline_width);
725 		outline_shape->push_back(from + (-reln + reltn) * bone_outline_width);
726 		outline_shape->push_back(from + rel * 0.2 + relt + reltn * bone_outline_width);
727 		outline_shape->push_back(to + (reln + reltn) * bone_outline_width);
728 		outline_shape->push_back(to + (reln - reltn) * bone_outline_width);
729 		outline_shape->push_back(from + rel * 0.2 - relt - reltn * bone_outline_width);
730 	}
731 	return true;
732 }
733 
_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)734 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) {
735 	if (!p_node)
736 		return;
737 	if (Object::cast_to<Viewport>(p_node))
738 		return;
739 
740 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
741 	Node *scene = editor->get_edited_scene();
742 
743 	bool editable = p_node == scene || p_node->get_owner() == scene || scene->is_editable_instance(p_node->get_owner());
744 	bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
745 	bool locked = _is_node_locked(p_node);
746 
747 	if (!lock_children || !editable) {
748 		for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
749 			if (canvas_item) {
750 				if (!canvas_item->is_set_as_toplevel()) {
751 					_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
752 				} else {
753 					_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, canvas_item->get_transform(), p_canvas_xform);
754 				}
755 			} else {
756 				CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
757 				_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
758 			}
759 		}
760 	}
761 
762 	if (canvas_item && canvas_item->is_visible_in_tree() && !locked && editable) {
763 		Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
764 
765 		if (canvas_item->_edit_use_rect()) {
766 			Rect2 rect = canvas_item->_edit_get_rect();
767 			if (p_rect.has_point(xform.xform(rect.position)) &&
768 					p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) &&
769 					p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) &&
770 					p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) {
771 
772 				r_items->push_back(canvas_item);
773 			}
774 		} else {
775 			if (p_rect.has_point(xform.xform(Point2()))) {
776 				r_items->push_back(canvas_item);
777 			}
778 		}
779 	}
780 }
781 
_select_click_on_item(CanvasItem * item,Point2 p_click_pos,bool p_append)782 bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append) {
783 	bool still_selected = true;
784 	if (p_append) {
785 		if (editor_selection->is_selected(item)) {
786 			// Already in the selection, remove it from the selected nodes
787 			editor_selection->remove_node(item);
788 			still_selected = false;
789 		} else {
790 			// Add the item to the selection
791 			editor_selection->add_node(item);
792 		}
793 	} else {
794 		if (!editor_selection->is_selected(item)) {
795 			// Select a new one and clear previous selection
796 			editor_selection->clear();
797 			editor_selection->add_node(item);
798 			// Reselect
799 			if (Engine::get_singleton()->is_editor_hint()) {
800 				selected_from_canvas = true;
801 				editor->call("edit_node", item);
802 			}
803 		}
804 	}
805 	viewport->update();
806 	return still_selected;
807 }
808 
_get_edited_canvas_items(bool retreive_locked,bool remove_canvas_item_if_parent_in_selection)809 List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_locked, bool remove_canvas_item_if_parent_in_selection) {
810 	List<CanvasItem *> selection;
811 	for (Map<Node *, Object *>::Element *E = editor_selection->get_selection().front(); E; E = E->next()) {
812 		CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
813 		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))) {
814 			CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
815 			if (se) {
816 				selection.push_back(canvas_item);
817 			}
818 		}
819 	}
820 
821 	if (remove_canvas_item_if_parent_in_selection) {
822 		List<CanvasItem *> filtered_selection;
823 		for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
824 			if (!selection.find(E->get()->get_parent())) {
825 				filtered_selection.push_back(E->get());
826 			}
827 		}
828 		return filtered_selection;
829 	} else {
830 		return selection;
831 	}
832 }
833 
_anchor_to_position(const Control * p_control,Vector2 anchor)834 Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) {
835 	ERR_FAIL_COND_V(!p_control, Vector2());
836 
837 	Transform2D parent_transform = p_control->get_transform().affine_inverse();
838 	Rect2 parent_rect = p_control->get_parent_anchorable_rect();
839 
840 	return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y));
841 }
842 
_position_to_anchor(const Control * p_control,Vector2 position)843 Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) {
844 	ERR_FAIL_COND_V(!p_control, Vector2());
845 
846 	Rect2 parent_rect = p_control->get_parent_anchorable_rect();
847 	ERR_FAIL_COND_V(parent_rect.size.x == 0, Vector2());
848 	ERR_FAIL_COND_V(parent_rect.size.y == 0, Vector2());
849 
850 	return (p_control->get_transform().xform(position) - parent_rect.position) / parent_rect.size;
851 }
852 
_save_canvas_item_ik_chain(const CanvasItem * p_canvas_item,List<float> * p_bones_length,List<Dictionary> * p_bones_state)853 void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) {
854 	if (p_bones_length)
855 		*p_bones_length = List<float>();
856 	if (p_bones_state)
857 		*p_bones_state = List<Dictionary>();
858 
859 	const Node2D *bone = Object::cast_to<Node2D>(p_canvas_item);
860 	if (bone && bone->has_meta("_edit_bone_")) {
861 		// Check if we have an IK chain
862 		List<const Node2D *> bone_ik_list;
863 		bool ik_found = false;
864 		bone = Object::cast_to<Node2D>(bone->get_parent());
865 		while (bone) {
866 			bone_ik_list.push_back(bone);
867 			if (bone->has_meta("_edit_ik_")) {
868 				ik_found = true;
869 				break;
870 			} else if (!bone->has_meta("_edit_bone_")) {
871 				break;
872 			}
873 			bone = Object::cast_to<Node2D>(bone->get_parent());
874 		}
875 
876 		//Save the bone state and length if we have an IK chain
877 		if (ik_found) {
878 			bone = Object::cast_to<Node2D>(p_canvas_item);
879 			Transform2D bone_xform = bone->get_global_transform();
880 			for (List<const Node2D *>::Element *bone_E = bone_ik_list.front(); bone_E; bone_E = bone_E->next()) {
881 				bone_xform = bone_xform * bone->get_transform().affine_inverse();
882 				const Node2D *parent_bone = bone_E->get();
883 				if (p_bones_length)
884 					p_bones_length->push_back(parent_bone->get_global_transform().get_origin().distance_to(bone->get_global_position()));
885 				if (p_bones_state)
886 					p_bones_state->push_back(parent_bone->_edit_get_state());
887 				bone = parent_bone;
888 			}
889 		}
890 	}
891 }
892 
_save_canvas_item_state(List<CanvasItem * > p_canvas_items,bool save_bones)893 void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
894 	for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
895 		CanvasItem *canvas_item = E->get();
896 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
897 		if (se) {
898 			se->undo_state = canvas_item->_edit_get_state();
899 			se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
900 			if (canvas_item->_edit_use_rect()) {
901 				se->pre_drag_rect = canvas_item->_edit_get_rect();
902 			} else {
903 				se->pre_drag_rect = Rect2();
904 			}
905 
906 			// If we have a bone, save the state of all nodes in the IK chain
907 			_save_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_length), &(se->pre_drag_bones_undo_state));
908 		}
909 	}
910 }
911 
_restore_canvas_item_ik_chain(CanvasItem * p_canvas_item,const List<Dictionary> * p_bones_state)912 void CanvasItemEditor::_restore_canvas_item_ik_chain(CanvasItem *p_canvas_item, const List<Dictionary> *p_bones_state) {
913 	CanvasItem *canvas_item = p_canvas_item;
914 	for (const List<Dictionary>::Element *E = p_bones_state->front(); E; E = E->next()) {
915 		canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
916 		canvas_item->_edit_set_state(E->get());
917 	}
918 }
919 
_restore_canvas_item_state(List<CanvasItem * > p_canvas_items,bool restore_bones)920 void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) {
921 	for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
922 		CanvasItem *canvas_item = E->get();
923 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
924 		canvas_item->_edit_set_state(se->undo_state);
925 		if (restore_bones) {
926 			_restore_canvas_item_ik_chain(canvas_item, &(se->pre_drag_bones_undo_state));
927 		}
928 	}
929 }
930 
_commit_canvas_item_state(List<CanvasItem * > p_canvas_items,String action_name,bool commit_bones)931 void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) {
932 	undo_redo->create_action(action_name);
933 	for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
934 		CanvasItem *canvas_item = E->get();
935 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
936 		undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
937 		undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
938 		if (commit_bones) {
939 			for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
940 				canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
941 				undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
942 				undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
943 			}
944 		}
945 	}
946 	undo_redo->add_do_method(viewport, "update");
947 	undo_redo->add_undo_method(viewport, "update");
948 	undo_redo->commit_action();
949 }
950 
_snap_changed()951 void CanvasItemEditor::_snap_changed() {
952 	((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step, snap_scale_step);
953 	grid_step_multiplier = 0;
954 	viewport->update();
955 }
956 
_selection_result_pressed(int p_result)957 void CanvasItemEditor::_selection_result_pressed(int p_result) {
958 
959 	if (selection_results.size() <= p_result)
960 		return;
961 
962 	CanvasItem *item = selection_results[p_result].item;
963 
964 	if (item)
965 		_select_click_on_item(item, Point2(), selection_menu_additive_selection);
966 }
967 
_selection_menu_hide()968 void CanvasItemEditor::_selection_menu_hide() {
969 
970 	selection_results.clear();
971 	selection_menu->clear();
972 	selection_menu->set_size(Vector2(0, 0));
973 }
974 
_gui_input_rulers_and_guides(const Ref<InputEvent> & p_event)975 bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_event) {
976 	Ref<InputEventMouseButton> b = p_event;
977 	Ref<InputEventMouseMotion> m = p_event;
978 
979 	if (drag_type == DRAG_NONE) {
980 		if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) {
981 			Transform2D xform = viewport_scrollable->get_transform() * transform;
982 			// Retrieve the guide lists
983 			Array vguides;
984 			if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
985 				vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
986 			}
987 			Array hguides;
988 			if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
989 				hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
990 			}
991 
992 			// Hover over guides
993 			float minimum = 1e20;
994 			is_hovering_h_guide = false;
995 			is_hovering_v_guide = false;
996 
997 			if (m.is_valid() && m->get_position().x < RULER_WIDTH) {
998 				// Check if we are hovering an existing horizontal guide
999 				for (int i = 0; i < hguides.size(); i++) {
1000 					if (ABS(xform.xform(Point2(0, hguides[i])).y - m->get_position().y) < MIN(minimum, 8)) {
1001 						is_hovering_h_guide = true;
1002 						is_hovering_v_guide = false;
1003 						break;
1004 					}
1005 				}
1006 
1007 			} else if (m.is_valid() && m->get_position().y < RULER_WIDTH) {
1008 				// Check if we are hovering an existing vertical guide
1009 				for (int i = 0; i < vguides.size(); i++) {
1010 					if (ABS(xform.xform(Point2(vguides[i], 0)).x - m->get_position().x) < MIN(minimum, 8)) {
1011 						is_hovering_v_guide = true;
1012 						is_hovering_h_guide = false;
1013 						break;
1014 					}
1015 				}
1016 			}
1017 
1018 			// Start dragging a guide
1019 			if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
1020 
1021 				// Press button
1022 				if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) {
1023 					// Drag a new double guide
1024 					drag_type = DRAG_DOUBLE_GUIDE;
1025 					dragged_guide_index = -1;
1026 					return true;
1027 				} else if (b->get_position().x < RULER_WIDTH) {
1028 					// Check if we drag an existing horizontal guide
1029 					dragged_guide_index = -1;
1030 					for (int i = 0; i < hguides.size(); i++) {
1031 						if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) {
1032 							dragged_guide_index = i;
1033 						}
1034 					}
1035 
1036 					if (dragged_guide_index >= 0) {
1037 						// Drag an existing horizontal guide
1038 						drag_type = DRAG_H_GUIDE;
1039 					} else {
1040 						// Drag a new vertical guide
1041 						drag_type = DRAG_V_GUIDE;
1042 					}
1043 					return true;
1044 				} else if (b->get_position().y < RULER_WIDTH) {
1045 					// Check if we drag an existing vertical guide
1046 					dragged_guide_index = -1;
1047 					for (int i = 0; i < vguides.size(); i++) {
1048 						if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) {
1049 							dragged_guide_index = i;
1050 						}
1051 					}
1052 
1053 					if (dragged_guide_index >= 0) {
1054 						// Drag an existing vertical guide
1055 						drag_type = DRAG_V_GUIDE;
1056 					} else {
1057 						// Drag a new vertical guide
1058 						drag_type = DRAG_H_GUIDE;
1059 					}
1060 					drag_from = xform.affine_inverse().xform(b->get_position());
1061 					return true;
1062 				}
1063 			}
1064 		}
1065 	}
1066 
1067 	if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE || drag_type == DRAG_H_GUIDE) {
1068 		// Move the guide
1069 		if (m.is_valid()) {
1070 			Transform2D xform = viewport_scrollable->get_transform() * transform;
1071 			drag_to = xform.affine_inverse().xform(m->get_position());
1072 
1073 			dragged_guide_pos = xform.xform(snap_point(drag_to, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES));
1074 			viewport->update();
1075 			return true;
1076 		}
1077 
1078 		// Release confirms the guide move
1079 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
1080 			if (show_guides && EditorNode::get_singleton()->get_edited_scene()) {
1081 				Transform2D xform = viewport_scrollable->get_transform() * transform;
1082 
1083 				// Retrieve the guide lists
1084 				Array vguides;
1085 				if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
1086 					vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
1087 				}
1088 				Array hguides;
1089 				if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
1090 					hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
1091 				}
1092 
1093 				Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES);
1094 				if (drag_type == DRAG_V_GUIDE) {
1095 					Array prev_vguides = vguides.duplicate();
1096 					if (b->get_position().x > RULER_WIDTH) {
1097 						// Adds a new vertical guide
1098 						if (dragged_guide_index >= 0) {
1099 							vguides[dragged_guide_index] = edited.x;
1100 							undo_redo->create_action(TTR("Move Vertical Guide"));
1101 							undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
1102 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
1103 							undo_redo->add_undo_method(viewport, "update");
1104 							undo_redo->commit_action();
1105 						} else {
1106 							vguides.push_back(edited.x);
1107 							undo_redo->create_action(TTR("Create Vertical Guide"));
1108 							undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
1109 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
1110 							undo_redo->add_undo_method(viewport, "update");
1111 							undo_redo->commit_action();
1112 						}
1113 					} else {
1114 						if (dragged_guide_index >= 0) {
1115 							vguides.remove(dragged_guide_index);
1116 							undo_redo->create_action(TTR("Remove Vertical Guide"));
1117 							if (vguides.empty()) {
1118 								undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_vertical_guides_");
1119 							} else {
1120 								undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
1121 							}
1122 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
1123 							undo_redo->add_undo_method(viewport, "update");
1124 							undo_redo->commit_action();
1125 						}
1126 					}
1127 				} else if (drag_type == DRAG_H_GUIDE) {
1128 					Array prev_hguides = hguides.duplicate();
1129 					if (b->get_position().y > RULER_WIDTH) {
1130 						// Adds a new horizontal guide
1131 						if (dragged_guide_index >= 0) {
1132 							hguides[dragged_guide_index] = edited.y;
1133 							undo_redo->create_action(TTR("Move Horizontal Guide"));
1134 							undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
1135 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
1136 							undo_redo->add_undo_method(viewport, "update");
1137 							undo_redo->commit_action();
1138 						} else {
1139 							hguides.push_back(edited.y);
1140 							undo_redo->create_action(TTR("Create Horizontal Guide"));
1141 							undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
1142 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
1143 							undo_redo->add_undo_method(viewport, "update");
1144 							undo_redo->commit_action();
1145 						}
1146 					} else {
1147 						if (dragged_guide_index >= 0) {
1148 							hguides.remove(dragged_guide_index);
1149 							undo_redo->create_action(TTR("Remove Horizontal Guide"));
1150 							if (hguides.empty()) {
1151 								undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "remove_meta", "_edit_horizontal_guides_");
1152 							} else {
1153 								undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
1154 							}
1155 							undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
1156 							undo_redo->add_undo_method(viewport, "update");
1157 							undo_redo->commit_action();
1158 						}
1159 					}
1160 				} else if (drag_type == DRAG_DOUBLE_GUIDE) {
1161 					Array prev_hguides = hguides.duplicate();
1162 					Array prev_vguides = vguides.duplicate();
1163 					if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) {
1164 						// Adds a new horizontal guide a new vertical guide
1165 						vguides.push_back(edited.x);
1166 						hguides.push_back(edited.y);
1167 						undo_redo->create_action(TTR("Create Horizontal and Vertical Guides"));
1168 						undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides);
1169 						undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides);
1170 						undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides);
1171 						undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides);
1172 						undo_redo->add_undo_method(viewport, "update");
1173 						undo_redo->commit_action();
1174 					}
1175 				}
1176 			}
1177 			drag_type = DRAG_NONE;
1178 			viewport->update();
1179 			return true;
1180 		}
1181 	}
1182 	return false;
1183 }
1184 
_gui_input_zoom_or_pan(const Ref<InputEvent> & p_event,bool p_already_accepted)1185 bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) {
1186 	Ref<InputEventMouseButton> b = p_event;
1187 	if (b.is_valid() && !p_already_accepted) {
1188 		const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control();
1189 
1190 		if (pan_on_scroll) {
1191 			// Perform horizontal scrolling first so we can check for Shift being held.
1192 			if (b->is_pressed() &&
1193 					(b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) {
1194 				// Pan left
1195 				view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
1196 				update_viewport();
1197 				return true;
1198 			}
1199 
1200 			if (b->is_pressed() &&
1201 					(b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) {
1202 				// Pan right
1203 				view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
1204 				update_viewport();
1205 				return true;
1206 			}
1207 		}
1208 
1209 		if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) {
1210 			// Scroll or pan down
1211 			if (pan_on_scroll) {
1212 				view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
1213 				update_viewport();
1214 			} else {
1215 				float new_zoom = _get_next_zoom_value(-1);
1216 				if (b->get_factor() != 1.f) {
1217 					new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f);
1218 				}
1219 				_zoom_on_position(new_zoom, b->get_position());
1220 			}
1221 			return true;
1222 		}
1223 
1224 		if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_UP) {
1225 			// Scroll or pan up
1226 			if (pan_on_scroll) {
1227 				view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
1228 				update_viewport();
1229 			} else {
1230 				float new_zoom = _get_next_zoom_value(1);
1231 				if (b->get_factor() != 1.f) {
1232 					new_zoom = zoom * ((new_zoom / zoom - 1.f) * b->get_factor() + 1.f);
1233 				}
1234 				_zoom_on_position(new_zoom, b->get_position());
1235 			}
1236 			return true;
1237 		}
1238 
1239 		if (!panning) {
1240 			if (b->is_pressed() &&
1241 					(b->get_button_index() == BUTTON_MIDDLE ||
1242 							b->get_button_index() == BUTTON_RIGHT ||
1243 							(b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) ||
1244 							(b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_panning") && pan_pressed))) {
1245 				// Pan the viewport
1246 				panning = true;
1247 			}
1248 		}
1249 
1250 		if (panning) {
1251 			if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != BUTTON_WHEEL_DOWN && b->get_button_index() != BUTTON_WHEEL_UP))) {
1252 				// Stop panning the viewport (for any mouse button press except zooming)
1253 				panning = false;
1254 			}
1255 		}
1256 	}
1257 
1258 	Ref<InputEventKey> k = p_event;
1259 	if (k.is_valid()) {
1260 		bool is_pan_key = pan_view_shortcut.is_valid() && pan_view_shortcut->is_shortcut(p_event);
1261 
1262 		if (is_pan_key && (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || drag_type != DRAG_NONE)) {
1263 			if (!panning) {
1264 				if (k->is_pressed() && !k->is_echo()) {
1265 					//Pan the viewport
1266 					panning = true;
1267 				}
1268 			} else {
1269 				if (!k->is_pressed()) {
1270 					// Stop panning the viewport (for any mouse button press)
1271 					panning = false;
1272 				}
1273 			}
1274 		}
1275 
1276 		if (is_pan_key)
1277 			pan_pressed = k->is_pressed();
1278 	}
1279 
1280 	Ref<InputEventMouseMotion> m = p_event;
1281 	if (m.is_valid()) {
1282 		if (panning) {
1283 			// Pan the viewport
1284 			Point2i relative;
1285 			if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
1286 				relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
1287 			} else {
1288 				relative = m->get_relative();
1289 			}
1290 			view_offset.x -= relative.x / zoom;
1291 			view_offset.y -= relative.y / zoom;
1292 			update_viewport();
1293 			return true;
1294 		}
1295 	}
1296 
1297 	Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
1298 	if (magnify_gesture.is_valid() && !p_already_accepted) {
1299 		// Zoom gesture
1300 		_zoom_on_position(zoom * magnify_gesture->get_factor(), magnify_gesture->get_position());
1301 		return true;
1302 	}
1303 
1304 	Ref<InputEventPanGesture> pan_gesture = p_event;
1305 	if (pan_gesture.is_valid() && !p_already_accepted) {
1306 		// If control key pressed, then zoom instead of pan
1307 		if (pan_gesture->get_control()) {
1308 			const float factor = pan_gesture->get_delta().y;
1309 			float new_zoom = _get_next_zoom_value(-1);
1310 
1311 			if (factor != 1.f) {
1312 				new_zoom = zoom * ((new_zoom / zoom - 1.f) * factor + 1.f);
1313 			}
1314 			_zoom_on_position(new_zoom, pan_gesture->get_position());
1315 			return true;
1316 		}
1317 
1318 		// Pan gesture
1319 		const Vector2 delta = (int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom) * pan_gesture->get_delta();
1320 		view_offset.x += delta.x;
1321 		view_offset.y += delta.y;
1322 		update_viewport();
1323 		return true;
1324 	}
1325 
1326 	return false;
1327 }
1328 
_gui_input_pivot(const Ref<InputEvent> & p_event)1329 bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
1330 	Ref<InputEventMouseMotion> m = p_event;
1331 	Ref<InputEventMouseButton> b = p_event;
1332 	Ref<InputEventKey> k = p_event;
1333 
1334 	// Drag the pivot (in pivot mode / with V key)
1335 	if (drag_type == DRAG_NONE) {
1336 		if ((b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
1337 				(k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V)) {
1338 			List<CanvasItem *> selection = _get_edited_canvas_items();
1339 
1340 			// Filters the selection with nodes that allow setting the pivot
1341 			drag_selection = List<CanvasItem *>();
1342 			for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
1343 				CanvasItem *canvas_item = E->get();
1344 				if (canvas_item->_edit_use_pivot()) {
1345 					drag_selection.push_back(canvas_item);
1346 				}
1347 			}
1348 
1349 			// Start dragging if we still have nodes
1350 			if (drag_selection.size() > 0) {
1351 				_save_canvas_item_state(drag_selection);
1352 				drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position());
1353 				Vector2 new_pos;
1354 				if (drag_selection.size() == 1) {
1355 					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]);
1356 				} else {
1357 					new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, NULL, drag_selection);
1358 				}
1359 				for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
1360 					CanvasItem *canvas_item = E->get();
1361 					canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
1362 				}
1363 
1364 				drag_type = DRAG_PIVOT;
1365 			}
1366 			return true;
1367 		}
1368 	}
1369 
1370 	if (drag_type == DRAG_PIVOT) {
1371 		// Move the pivot
1372 		if (m.is_valid()) {
1373 			drag_to = transform.affine_inverse().xform(m->get_position());
1374 			_restore_canvas_item_state(drag_selection);
1375 			Vector2 new_pos;
1376 			if (drag_selection.size() == 1)
1377 				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]);
1378 			else
1379 				new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
1380 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
1381 				CanvasItem *canvas_item = E->get();
1382 				canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
1383 			}
1384 			return true;
1385 		}
1386 
1387 		// Confirm the pivot move
1388 		if ((b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) ||
1389 				(k.is_valid() && !k->is_pressed() && k->get_scancode() == KEY_V)) {
1390 			_commit_canvas_item_state(drag_selection, TTR("Move pivot"));
1391 			drag_type = DRAG_NONE;
1392 			return true;
1393 		}
1394 
1395 		// Cancel a drag
1396 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
1397 			_restore_canvas_item_state(drag_selection);
1398 			drag_type = DRAG_NONE;
1399 			viewport->update();
1400 			return true;
1401 		}
1402 	}
1403 	return false;
1404 }
1405 
_solve_IK(Node2D * leaf_node,Point2 target_position)1406 void CanvasItemEditor::_solve_IK(Node2D *leaf_node, Point2 target_position) {
1407 	CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(leaf_node);
1408 	if (se) {
1409 		int nb_bones = se->pre_drag_bones_undo_state.size();
1410 		if (nb_bones > 0) {
1411 
1412 			// Build the node list
1413 			Point2 leaf_pos = target_position;
1414 
1415 			List<Node2D *> joints_list;
1416 			List<Point2> joints_pos;
1417 			Node2D *joint = leaf_node;
1418 			Transform2D joint_transform = leaf_node->get_global_transform_with_canvas();
1419 			for (int i = 0; i < nb_bones + 1; i++) {
1420 				joints_list.push_back(joint);
1421 				joints_pos.push_back(joint_transform.get_origin());
1422 				joint_transform = joint_transform * joint->get_transform().affine_inverse();
1423 				joint = Object::cast_to<Node2D>(joint->get_parent());
1424 			}
1425 			Point2 root_pos = joints_list.back()->get()->get_global_transform_with_canvas().get_origin();
1426 
1427 			// Restraints the node to a maximum distance is necessary
1428 			float total_len = 0;
1429 			for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
1430 				total_len += E->get();
1431 			}
1432 			if ((root_pos.distance_to(leaf_pos)) > total_len) {
1433 				Vector2 rel = leaf_pos - root_pos;
1434 				rel = rel.normalized() * total_len;
1435 				leaf_pos = root_pos + rel;
1436 			}
1437 			joints_pos[0] = leaf_pos;
1438 
1439 			// Run the solver
1440 			int solver_iterations = 64;
1441 			float solver_k = 0.3;
1442 
1443 			// Build the position list
1444 			for (int i = 0; i < solver_iterations; i++) {
1445 				// Handle the leaf joint
1446 				int node_id = 0;
1447 				for (List<float>::Element *E = se->pre_drag_bones_length.front(); E; E = E->next()) {
1448 					Vector2 direction = (joints_pos[node_id + 1] - joints_pos[node_id]).normalized();
1449 					int len = E->get();
1450 					if (E == se->pre_drag_bones_length.front()) {
1451 						joints_pos[1] = joints_pos[1].linear_interpolate(joints_pos[0] + len * direction, solver_k);
1452 					} else if (E == se->pre_drag_bones_length.back()) {
1453 						joints_pos[node_id] = joints_pos[node_id].linear_interpolate(joints_pos[node_id + 1] - len * direction, solver_k);
1454 					} else {
1455 						Vector2 center = (joints_pos[node_id + 1] + joints_pos[node_id]) / 2.0;
1456 						joints_pos[node_id] = joints_pos[node_id].linear_interpolate(center - (direction * len) / 2.0, solver_k);
1457 						joints_pos[node_id + 1] = joints_pos[node_id + 1].linear_interpolate(center + (direction * len) / 2.0, solver_k);
1458 					}
1459 					node_id++;
1460 				}
1461 			}
1462 
1463 			// Set the position
1464 			for (int node_id = joints_list.size() - 1; node_id > 0; node_id--) {
1465 				Point2 current = (joints_list[node_id - 1]->get_global_position() - joints_list[node_id]->get_global_position()).normalized();
1466 				Point2 target = (joints_pos[node_id - 1] - joints_list[node_id]->get_global_position()).normalized();
1467 				float rot = current.angle_to(target);
1468 				if (joints_list[node_id]->get_global_transform().basis_determinant() < 0) {
1469 					rot = -rot;
1470 				}
1471 				joints_list[node_id]->rotate(rot);
1472 			}
1473 		}
1474 	}
1475 }
1476 
_gui_input_rotate(const Ref<InputEvent> & p_event)1477 bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
1478 	Ref<InputEventMouseButton> b = p_event;
1479 	Ref<InputEventMouseMotion> m = p_event;
1480 
1481 	// Start rotation
1482 	if (drag_type == DRAG_NONE) {
1483 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
1484 			if ((b->get_control() && !b->get_alt() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
1485 				List<CanvasItem *> selection = _get_edited_canvas_items();
1486 
1487 				// Remove not movable nodes
1488 				for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
1489 					if (!_is_node_movable(E->get(), true))
1490 						selection.erase(E);
1491 				}
1492 
1493 				drag_selection = selection;
1494 				if (drag_selection.size() > 0) {
1495 					drag_type = DRAG_ROTATE;
1496 					drag_from = transform.affine_inverse().xform(b->get_position());
1497 					CanvasItem *canvas_item = drag_selection[0];
1498 					if (canvas_item->_edit_use_pivot()) {
1499 						drag_rotation_center = canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_pivot());
1500 					} else {
1501 						drag_rotation_center = canvas_item->get_global_transform_with_canvas().get_origin();
1502 					}
1503 					_save_canvas_item_state(drag_selection);
1504 					return true;
1505 				}
1506 			}
1507 		}
1508 	}
1509 
1510 	if (drag_type == DRAG_ROTATE) {
1511 		// Rotate the node
1512 		if (m.is_valid()) {
1513 			_restore_canvas_item_state(drag_selection);
1514 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
1515 				CanvasItem *canvas_item = E->get();
1516 				drag_to = transform.affine_inverse().xform(m->get_position());
1517 				//Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements
1518 				bool opposite = (canvas_item->get_global_transform().get_scale().sign().dot(canvas_item->get_transform().get_scale().sign()) == 0);
1519 				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()));
1520 				viewport->update();
1521 			}
1522 			return true;
1523 		}
1524 
1525 		// Confirms the node rotation
1526 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
1527 			_commit_canvas_item_state(drag_selection, TTR("Rotate CanvasItem"));
1528 			if (key_auto_insert_button->is_pressed()) {
1529 				_insert_animation_keys(false, true, false, true);
1530 			}
1531 
1532 			drag_type = DRAG_NONE;
1533 			return true;
1534 		}
1535 
1536 		// Cancel a drag
1537 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
1538 			_restore_canvas_item_state(drag_selection);
1539 			drag_type = DRAG_NONE;
1540 			viewport->update();
1541 			return true;
1542 		}
1543 	}
1544 	return false;
1545 }
1546 
_gui_input_open_scene_on_double_click(const Ref<InputEvent> & p_event)1547 bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEvent> &p_event) {
1548 	Ref<InputEventMouseButton> b = p_event;
1549 
1550 	// Open a sub-scene on double-click
1551 	if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && b->is_doubleclick() && tool == TOOL_SELECT) {
1552 		List<CanvasItem *> selection = _get_edited_canvas_items();
1553 		if (selection.size() == 1) {
1554 			CanvasItem *canvas_item = selection[0];
1555 			if (canvas_item->get_filename() != "" && canvas_item != editor->get_edited_scene()) {
1556 				editor->open_request(canvas_item->get_filename());
1557 				return true;
1558 			}
1559 		}
1560 	}
1561 	return false;
1562 }
1563 
_gui_input_anchors(const Ref<InputEvent> & p_event)1564 bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
1565 	Ref<InputEventMouseButton> b = p_event;
1566 	Ref<InputEventMouseMotion> m = p_event;
1567 
1568 	// Starts anchor dragging if needed
1569 	if (drag_type == DRAG_NONE) {
1570 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
1571 			List<CanvasItem *> selection = _get_edited_canvas_items();
1572 			if (selection.size() == 1) {
1573 				Control *control = Object::cast_to<Control>(selection[0]);
1574 				if (control && _is_node_movable(control)) {
1575 					Vector2 anchor_pos[4];
1576 					anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
1577 					anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
1578 					anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
1579 					anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
1580 
1581 					Rect2 anchor_rects[4];
1582 					for (int i = 0; i < 4; i++) {
1583 						anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
1584 						anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
1585 						anchor_rects[i].position -= anchor_handle->get_size() * Vector2(float(i == 0 || i == 3), float(i <= 1));
1586 					}
1587 
1588 					DragType dragger[] = {
1589 						DRAG_ANCHOR_TOP_LEFT,
1590 						DRAG_ANCHOR_TOP_RIGHT,
1591 						DRAG_ANCHOR_BOTTOM_RIGHT,
1592 						DRAG_ANCHOR_BOTTOM_LEFT,
1593 					};
1594 
1595 					for (int i = 0; i < 4; i++) {
1596 						if (anchor_rects[i].has_point(b->get_position())) {
1597 							if ((anchor_pos[0] == anchor_pos[2]) && (anchor_pos[0].distance_to(b->get_position()) < anchor_handle->get_size().length() / 3.0)) {
1598 								drag_type = DRAG_ANCHOR_ALL;
1599 							} else {
1600 								drag_type = dragger[i];
1601 							}
1602 							drag_from = transform.affine_inverse().xform(b->get_position());
1603 							drag_selection = List<CanvasItem *>();
1604 							drag_selection.push_back(control);
1605 							_save_canvas_item_state(drag_selection);
1606 							return true;
1607 						}
1608 					}
1609 				}
1610 			}
1611 		}
1612 	}
1613 
1614 	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) {
1615 		// Drag the anchor
1616 		if (m.is_valid()) {
1617 			_restore_canvas_item_state(drag_selection);
1618 			Control *control = Object::cast_to<Control>(drag_selection[0]);
1619 
1620 			drag_to = transform.affine_inverse().xform(m->get_position());
1621 
1622 			Transform2D xform = control->get_global_transform_with_canvas().affine_inverse();
1623 
1624 			Point2 previous_anchor;
1625 			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);
1626 			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);
1627 			previous_anchor = xform.affine_inverse().xform(_anchor_to_position(control, previous_anchor));
1628 
1629 			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));
1630 			new_anchor = _position_to_anchor(control, new_anchor).snapped(Vector2(0.001, 0.001));
1631 
1632 			bool use_single_axis = m->get_shift();
1633 			Vector2 drag_vector = xform.xform(drag_to) - xform.xform(drag_from);
1634 			bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
1635 
1636 			switch (drag_type) {
1637 				case DRAG_ANCHOR_TOP_LEFT:
1638 					if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
1639 					if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
1640 					break;
1641 				case DRAG_ANCHOR_TOP_RIGHT:
1642 					if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
1643 					if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, false);
1644 					break;
1645 				case DRAG_ANCHOR_BOTTOM_RIGHT:
1646 					if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, false);
1647 					if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
1648 					break;
1649 				case DRAG_ANCHOR_BOTTOM_LEFT:
1650 					if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, false);
1651 					if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
1652 					break;
1653 				case DRAG_ANCHOR_ALL:
1654 					if (!use_single_axis || !use_y) {
1655 						control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
1656 						control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
1657 					}
1658 					if (!use_single_axis || use_y) {
1659 						control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
1660 						control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
1661 					}
1662 					break;
1663 				default:
1664 					break;
1665 			}
1666 			return true;
1667 		}
1668 
1669 		// Confirms new anchor position
1670 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
1671 			_commit_canvas_item_state(drag_selection, TTR("Move anchor"));
1672 			drag_type = DRAG_NONE;
1673 			return true;
1674 		}
1675 
1676 		// Cancel a drag
1677 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
1678 			_restore_canvas_item_state(drag_selection);
1679 			drag_type = DRAG_NONE;
1680 			viewport->update();
1681 			return true;
1682 		}
1683 	}
1684 	return false;
1685 }
1686 
_gui_input_resize(const Ref<InputEvent> & p_event)1687 bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
1688 	Ref<InputEventMouseButton> b = p_event;
1689 	Ref<InputEventMouseMotion> m = p_event;
1690 
1691 	// Drag resize handles
1692 	if (drag_type == DRAG_NONE) {
1693 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
1694 			List<CanvasItem *> selection = _get_edited_canvas_items();
1695 			if (selection.size() == 1) {
1696 				CanvasItem *canvas_item = selection[0];
1697 				if (canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) {
1698 					Rect2 rect = canvas_item->_edit_get_rect();
1699 					Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
1700 
1701 					Vector2 endpoints[4] = {
1702 						xform.xform(rect.position),
1703 						xform.xform(rect.position + Vector2(rect.size.x, 0)),
1704 						xform.xform(rect.position + rect.size),
1705 						xform.xform(rect.position + Vector2(0, rect.size.y))
1706 					};
1707 
1708 					DragType dragger[] = {
1709 						DRAG_TOP_LEFT,
1710 						DRAG_TOP,
1711 						DRAG_TOP_RIGHT,
1712 						DRAG_RIGHT,
1713 						DRAG_BOTTOM_RIGHT,
1714 						DRAG_BOTTOM,
1715 						DRAG_BOTTOM_LEFT,
1716 						DRAG_LEFT
1717 					};
1718 
1719 					DragType resize_drag = DRAG_NONE;
1720 					float radius = (select_handle->get_size().width / 2) * 1.5;
1721 
1722 					for (int i = 0; i < 4; i++) {
1723 						int prev = (i + 3) % 4;
1724 						int next = (i + 1) % 4;
1725 
1726 						Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
1727 						ofs *= (select_handle->get_size().width / 2);
1728 						ofs += endpoints[i];
1729 						if (ofs.distance_to(b->get_position()) < radius)
1730 							resize_drag = dragger[i * 2];
1731 
1732 						ofs = (endpoints[i] + endpoints[next]) / 2;
1733 						ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
1734 						if (ofs.distance_to(b->get_position()) < radius)
1735 							resize_drag = dragger[i * 2 + 1];
1736 					}
1737 
1738 					if (resize_drag != DRAG_NONE) {
1739 						drag_type = resize_drag;
1740 						drag_from = transform.affine_inverse().xform(b->get_position());
1741 						drag_selection = List<CanvasItem *>();
1742 						drag_selection.push_back(canvas_item);
1743 						_save_canvas_item_state(drag_selection);
1744 						return true;
1745 					}
1746 				}
1747 			}
1748 		}
1749 	}
1750 
1751 	if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
1752 			drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
1753 		// Resize the node
1754 		if (m.is_valid()) {
1755 			CanvasItem *canvas_item = drag_selection[0];
1756 			CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
1757 			//Reset state
1758 			canvas_item->_edit_set_state(se->undo_state);
1759 
1760 			bool uniform = m->get_shift();
1761 			bool symmetric = m->get_alt();
1762 
1763 			Rect2 local_rect = canvas_item->_edit_get_rect();
1764 			float aspect = local_rect.get_size().y / local_rect.get_size().x;
1765 			Point2 current_begin = local_rect.get_position();
1766 			Point2 current_end = local_rect.get_position() + local_rect.get_size();
1767 			Point2 max_begin = (symmetric) ? (current_begin + current_end - canvas_item->_edit_get_minimum_size()) / 2.0 : current_end - canvas_item->_edit_get_minimum_size();
1768 			Point2 min_end = (symmetric) ? (current_begin + current_end + canvas_item->_edit_get_minimum_size()) / 2.0 : current_begin + canvas_item->_edit_get_minimum_size();
1769 			Point2 center = (current_begin + current_end) / 2.0;
1770 
1771 			drag_to = transform.affine_inverse().xform(m->get_position());
1772 
1773 			Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse();
1774 
1775 			Point2 drag_to_snapped_begin;
1776 			Point2 drag_to_snapped_end;
1777 
1778 			// last call decides which snapping lines are drawn
1779 			if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT) {
1780 				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);
1781 				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);
1782 			} else {
1783 				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);
1784 				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);
1785 			}
1786 
1787 			Point2 drag_begin = xform.xform(drag_to_snapped_begin);
1788 			Point2 drag_end = xform.xform(drag_to_snapped_end);
1789 
1790 			// Horizontal resize
1791 			if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
1792 				current_begin.x = MIN(drag_begin.x, max_begin.x);
1793 			} else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
1794 				current_end.x = MAX(drag_end.x, min_end.x);
1795 			}
1796 
1797 			// Vertical resize
1798 			if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
1799 				current_begin.y = MIN(drag_begin.y, max_begin.y);
1800 			} else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
1801 				current_end.y = MAX(drag_end.y, min_end.y);
1802 			}
1803 
1804 			// Uniform resize
1805 			if (uniform) {
1806 				if (drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT) {
1807 					current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
1808 				} else if (drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM) {
1809 					current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
1810 				} else {
1811 					if (aspect >= 1.0) {
1812 						if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
1813 							current_begin.y = current_end.y - aspect * (current_end.x - current_begin.x);
1814 						} else {
1815 							current_end.y = current_begin.y + aspect * (current_end.x - current_begin.x);
1816 						}
1817 					} else {
1818 						if (drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
1819 							current_begin.x = current_end.x - (current_end.y - current_begin.y) / aspect;
1820 						} else {
1821 							current_end.x = current_begin.x + (current_end.y - current_begin.y) / aspect;
1822 						}
1823 					}
1824 				}
1825 			}
1826 
1827 			// Symmetric resize
1828 			if (symmetric) {
1829 				if (drag_type == DRAG_LEFT || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_BOTTOM_LEFT) {
1830 					current_end.x = 2.0 * center.x - current_begin.x;
1831 				} else if (drag_type == DRAG_RIGHT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_RIGHT) {
1832 					current_begin.x = 2.0 * center.x - current_end.x;
1833 				}
1834 				if (drag_type == DRAG_TOP || drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT) {
1835 					current_end.y = 2.0 * center.y - current_begin.y;
1836 				} else if (drag_type == DRAG_BOTTOM || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT) {
1837 					current_begin.y = 2.0 * center.y - current_end.y;
1838 				}
1839 			}
1840 			canvas_item->_edit_set_rect(Rect2(current_begin, current_end - current_begin));
1841 			return true;
1842 		}
1843 
1844 		// Confirm resize
1845 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
1846 			_commit_canvas_item_state(drag_selection, TTR("Resize CanvasItem"));
1847 			if (key_auto_insert_button->is_pressed()) {
1848 				_insert_animation_keys(false, false, true, true);
1849 			}
1850 
1851 			snap_target[0] = SNAP_TARGET_NONE;
1852 			snap_target[1] = SNAP_TARGET_NONE;
1853 			drag_type = DRAG_NONE;
1854 			viewport->update();
1855 			return true;
1856 		}
1857 
1858 		// Cancel a drag
1859 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
1860 			_restore_canvas_item_state(drag_selection);
1861 			snap_target[0] = SNAP_TARGET_NONE;
1862 			snap_target[1] = SNAP_TARGET_NONE;
1863 			drag_type = DRAG_NONE;
1864 			viewport->update();
1865 			return true;
1866 		}
1867 	}
1868 	return false;
1869 }
1870 
_gui_input_scale(const Ref<InputEvent> & p_event)1871 bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
1872 
1873 	Ref<InputEventMouseButton> b = p_event;
1874 	Ref<InputEventMouseMotion> m = p_event;
1875 
1876 	// Drag resize handles
1877 	if (drag_type == DRAG_NONE) {
1878 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && ((b->get_alt() && b->get_control()) || tool == TOOL_SCALE)) {
1879 			List<CanvasItem *> selection = _get_edited_canvas_items();
1880 			if (selection.size() == 1) {
1881 				CanvasItem *canvas_item = selection[0];
1882 
1883 				if (_is_node_movable(canvas_item)) {
1884 
1885 					Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
1886 					Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
1887 					Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
1888 
1889 					drag_type = DRAG_SCALE_BOTH;
1890 
1891 					Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
1892 					Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
1893 					if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) {
1894 						drag_type = DRAG_SCALE_X;
1895 					}
1896 					Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
1897 					if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) {
1898 						drag_type = DRAG_SCALE_Y;
1899 					}
1900 
1901 					drag_from = transform.affine_inverse().xform(b->get_position());
1902 					drag_selection = List<CanvasItem *>();
1903 					drag_selection.push_back(canvas_item);
1904 					_save_canvas_item_state(drag_selection);
1905 					return true;
1906 				}
1907 			}
1908 		}
1909 	}
1910 
1911 	if (drag_type == DRAG_SCALE_BOTH || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) {
1912 		// Resize the node
1913 		if (m.is_valid()) {
1914 			_restore_canvas_item_state(drag_selection);
1915 			CanvasItem *canvas_item = drag_selection[0];
1916 
1917 			drag_to = transform.affine_inverse().xform(m->get_position());
1918 
1919 			Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse();
1920 			Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized();
1921 			Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform;
1922 
1923 			bool uniform = m->get_shift();
1924 			bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
1925 
1926 			Point2 drag_from_local = simple_xform.xform(drag_from);
1927 			Point2 drag_to_local = simple_xform.xform(drag_to);
1928 			Point2 offset = drag_to_local - drag_from_local;
1929 
1930 			Size2 scale = canvas_item->call("get_scale");
1931 			float ratio = scale.y / scale.x;
1932 			if (drag_type == DRAG_SCALE_BOTH) {
1933 				Size2 scale_factor = drag_to_local / drag_from_local;
1934 				if (uniform) {
1935 					scale *= (scale_factor.x + scale_factor.y) / 2.0;
1936 				} else {
1937 					scale *= scale_factor;
1938 				}
1939 			} else {
1940 				Size2 scale_factor = Vector2(offset.x, -offset.y) / SCALE_HANDLE_DISTANCE;
1941 				Size2 parent_scale = parent_xform.get_scale();
1942 				scale_factor *= Vector2(1.0 / parent_scale.x, 1.0 / parent_scale.y);
1943 				if (drag_type == DRAG_SCALE_X) {
1944 					scale.x += scale_factor.x;
1945 					if (uniform) {
1946 						scale.y = scale.x * ratio;
1947 					}
1948 				} else if (drag_type == DRAG_SCALE_Y) {
1949 					scale.y += scale_factor.y;
1950 					if (uniform) {
1951 						scale.x = scale.y / ratio;
1952 					}
1953 				}
1954 			}
1955 
1956 			if (snap_scale && !is_ctrl) {
1957 				scale.x = roundf(scale.x / snap_scale_step) * snap_scale_step;
1958 				scale.y = roundf(scale.y / snap_scale_step) * snap_scale_step;
1959 			}
1960 
1961 			canvas_item->call("set_scale", scale);
1962 			return true;
1963 		}
1964 
1965 		// Confirm resize
1966 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) {
1967 			_commit_canvas_item_state(drag_selection, TTR("Scale CanvasItem"));
1968 			if (key_auto_insert_button->is_pressed()) {
1969 				_insert_animation_keys(false, false, true, true);
1970 			}
1971 
1972 			drag_type = DRAG_NONE;
1973 			viewport->update();
1974 			return true;
1975 		}
1976 
1977 		// Cancel a drag
1978 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
1979 			_restore_canvas_item_state(drag_selection);
1980 			drag_type = DRAG_NONE;
1981 			viewport->update();
1982 			return true;
1983 		}
1984 	}
1985 	return false;
1986 }
1987 
_gui_input_move(const Ref<InputEvent> & p_event)1988 bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
1989 	Ref<InputEventMouseButton> b = p_event;
1990 	Ref<InputEventMouseMotion> m = p_event;
1991 	Ref<InputEventKey> k = p_event;
1992 
1993 	if (drag_type == DRAG_NONE) {
1994 		//Start moving the nodes
1995 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed()) {
1996 			if ((b->get_alt() && !b->get_control()) || tool == TOOL_MOVE) {
1997 				List<CanvasItem *> selection = _get_edited_canvas_items();
1998 
1999 				drag_selection.clear();
2000 				for (int i = 0; i < selection.size(); i++) {
2001 					if (_is_node_movable(selection[i], true)) {
2002 						drag_selection.push_back(selection[i]);
2003 					}
2004 				}
2005 
2006 				if (selection.size() > 0) {
2007 					drag_type = DRAG_MOVE;
2008 					drag_from = transform.affine_inverse().xform(b->get_position());
2009 					_save_canvas_item_state(drag_selection);
2010 				}
2011 				return true;
2012 			}
2013 		}
2014 	}
2015 
2016 	if (drag_type == DRAG_MOVE) {
2017 		// Move the nodes
2018 		if (m.is_valid()) {
2019 
2020 			// Save the ik chain for reapplying before IK solve
2021 			Vector<List<Dictionary> > all_bones_ik_states;
2022 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
2023 				List<Dictionary> bones_ik_states;
2024 				_save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states);
2025 				all_bones_ik_states.push_back(bones_ik_states);
2026 			}
2027 
2028 			_restore_canvas_item_state(drag_selection, true);
2029 
2030 			drag_to = transform.affine_inverse().xform(m->get_position());
2031 			Point2 previous_pos;
2032 			if (drag_selection.size() == 1) {
2033 				Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
2034 				previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
2035 			} else {
2036 				previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
2037 			}
2038 			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, NULL, drag_selection);
2039 			bool single_axis = m->get_shift();
2040 			if (single_axis) {
2041 				if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) {
2042 					new_pos.y = previous_pos.y;
2043 				} else {
2044 					new_pos.x = previous_pos.x;
2045 				}
2046 			}
2047 
2048 			bool force_no_IK = m->get_alt();
2049 			int index = 0;
2050 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
2051 				CanvasItem *canvas_item = E->get();
2052 				CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
2053 				Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
2054 
2055 				Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
2056 				if (node2d && se->pre_drag_bones_undo_state.size() > 0 && !force_no_IK) {
2057 					real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
2058 					_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
2059 					real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
2060 					node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
2061 					_solve_IK(node2d, new_pos);
2062 				} else {
2063 					canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
2064 				}
2065 				index++;
2066 			}
2067 			return true;
2068 		}
2069 
2070 		// Confirm the move (only if it was moved)
2071 		if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
2072 			if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
2073 				_commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
2074 			}
2075 
2076 			if (key_auto_insert_button->is_pressed()) {
2077 				_insert_animation_keys(true, false, false, true);
2078 			}
2079 
2080 			//Make sure smart snapping lines disappear.
2081 			snap_target[0] = SNAP_TARGET_NONE;
2082 			snap_target[1] = SNAP_TARGET_NONE;
2083 
2084 			drag_type = DRAG_NONE;
2085 			viewport->update();
2086 			return true;
2087 		}
2088 
2089 		// Cancel a drag
2090 		if (b.is_valid() && b->get_button_index() == BUTTON_RIGHT && b->is_pressed()) {
2091 			_restore_canvas_item_state(drag_selection, true);
2092 			snap_target[0] = SNAP_TARGET_NONE;
2093 			snap_target[1] = SNAP_TARGET_NONE;
2094 			drag_type = DRAG_NONE;
2095 			viewport->update();
2096 			return true;
2097 		}
2098 	}
2099 
2100 	// Move the canvas items with the arrow keys
2101 	if (k.is_valid() && k->is_pressed() && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
2102 			(k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
2103 		if (!k->is_echo()) {
2104 			// Start moving the canvas items with the keyboard
2105 			drag_selection = _get_edited_canvas_items();
2106 			drag_type = DRAG_KEY_MOVE;
2107 			drag_from = Vector2();
2108 			drag_to = Vector2();
2109 			_save_canvas_item_state(drag_selection, true);
2110 		}
2111 
2112 		if (drag_selection.size() > 0) {
2113 
2114 			// Save the ik chain for reapplying before IK solve
2115 			Vector<List<Dictionary> > all_bones_ik_states;
2116 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
2117 				List<Dictionary> bones_ik_states;
2118 				_save_canvas_item_ik_chain(E->get(), NULL, &bones_ik_states);
2119 				all_bones_ik_states.push_back(bones_ik_states);
2120 			}
2121 
2122 			_restore_canvas_item_state(drag_selection, true);
2123 
2124 			bool move_local_base = k->get_alt();
2125 			bool move_local_base_rotated = k->get_control() || k->get_metakey();
2126 
2127 			Vector2 dir;
2128 			if (k->get_scancode() == KEY_UP)
2129 				dir += Vector2(0, -1);
2130 			else if (k->get_scancode() == KEY_DOWN)
2131 				dir += Vector2(0, 1);
2132 			else if (k->get_scancode() == KEY_LEFT)
2133 				dir += Vector2(-1, 0);
2134 			else if (k->get_scancode() == KEY_RIGHT)
2135 				dir += Vector2(1, 0);
2136 			if (k->get_shift())
2137 				dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
2138 
2139 			drag_to += dir;
2140 			if (k->get_shift())
2141 				drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
2142 
2143 			Point2 previous_pos;
2144 			if (drag_selection.size() == 1) {
2145 				Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
2146 				previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
2147 			} else {
2148 				previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
2149 			}
2150 
2151 			Point2 new_pos;
2152 			if (drag_selection.size() == 1) {
2153 				Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]);
2154 				if (node_2d && move_local_base_rotated) {
2155 					Transform2D m2;
2156 					m2.rotate(node_2d->get_rotation());
2157 					new_pos += m2.xform(drag_to);
2158 				} else if (move_local_base) {
2159 					new_pos += drag_to;
2160 				} else {
2161 					new_pos = previous_pos + (drag_to - drag_from);
2162 				}
2163 			} else {
2164 				new_pos = previous_pos + (drag_to - drag_from);
2165 			}
2166 
2167 			int index = 0;
2168 			for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
2169 				CanvasItem *canvas_item = E->get();
2170 				CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
2171 				Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
2172 
2173 				Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
2174 				if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
2175 					real_t initial_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
2176 					_restore_canvas_item_ik_chain(node2d, &(all_bones_ik_states[index]));
2177 					real_t final_leaf_node_rotation = node2d->get_global_transform_with_canvas().get_rotation();
2178 					node2d->rotate(initial_leaf_node_rotation - final_leaf_node_rotation);
2179 					_solve_IK(node2d, new_pos);
2180 				} else {
2181 					canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
2182 				}
2183 				index++;
2184 			}
2185 		}
2186 		return true;
2187 	}
2188 
2189 	if (k.is_valid() && !k->is_pressed() && drag_type == DRAG_KEY_MOVE && (tool == TOOL_SELECT || tool == TOOL_MOVE) &&
2190 			(k->get_scancode() == KEY_UP || k->get_scancode() == KEY_DOWN || k->get_scancode() == KEY_LEFT || k->get_scancode() == KEY_RIGHT)) {
2191 		// Confirm canvas items move by arrow keys
2192 		if ((!Input::get_singleton()->is_key_pressed(KEY_UP)) &&
2193 				(!Input::get_singleton()->is_key_pressed(KEY_DOWN)) &&
2194 				(!Input::get_singleton()->is_key_pressed(KEY_LEFT)) &&
2195 				(!Input::get_singleton()->is_key_pressed(KEY_RIGHT))) {
2196 			_commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
2197 			drag_type = DRAG_NONE;
2198 		}
2199 		viewport->update();
2200 		return true;
2201 	}
2202 
2203 	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
2204 }
2205 
_gui_input_select(const Ref<InputEvent> & p_event)2206 bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
2207 	Ref<InputEventMouseButton> b = p_event;
2208 	Ref<InputEventMouseMotion> m = p_event;
2209 	Ref<InputEventKey> k = p_event;
2210 
2211 	if (drag_type == DRAG_NONE) {
2212 		if (b.is_valid() &&
2213 				((b->get_button_index() == BUTTON_RIGHT && b->get_alt() && tool == TOOL_SELECT) ||
2214 						(b->get_button_index() == BUTTON_LEFT && tool == TOOL_LIST_SELECT))) {
2215 			// Popup the selection menu list
2216 			Point2 click = transform.affine_inverse().xform(b->get_position());
2217 
2218 			_get_canvas_items_at_pos(click, selection_results);
2219 
2220 			if (selection_results.size() == 1) {
2221 				CanvasItem *item = selection_results[0].item;
2222 				selection_results.clear();
2223 
2224 				_select_click_on_item(item, click, b->get_shift());
2225 
2226 				return true;
2227 			} else if (!selection_results.empty()) {
2228 				// Sorts items according the their z-index
2229 				selection_results.sort();
2230 
2231 				NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
2232 				StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
2233 
2234 				for (int i = 0; i < selection_results.size(); i++) {
2235 					CanvasItem *item = selection_results[i].item;
2236 
2237 					Ref<Texture> icon = EditorNode::get_singleton()->get_object_icon(item, "Node");
2238 					String node_path = "/" + root_name + "/" + root_path.rel_path_to(item->get_path());
2239 
2240 					selection_menu->add_item(item->get_name());
2241 					selection_menu->set_item_icon(i, icon);
2242 					selection_menu->set_item_metadata(i, node_path);
2243 					selection_menu->set_item_tooltip(i, String(item->get_name()) + "\nType: " + item->get_class() + "\nPath: " + node_path);
2244 				}
2245 
2246 				selection_menu_additive_selection = b->get_shift();
2247 				selection_menu->set_global_position(b->get_global_position());
2248 				selection_menu->popup();
2249 				return true;
2250 			}
2251 		}
2252 
2253 		if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
2254 			// Single item selection
2255 			Point2 click = transform.affine_inverse().xform(b->get_position());
2256 
2257 			Node *scene = editor->get_edited_scene();
2258 			if (!scene)
2259 				return true;
2260 
2261 			// Find the item to select
2262 			CanvasItem *canvas_item = NULL;
2263 
2264 			// Retrieve the bones
2265 			Vector<_SelectResult> selection = Vector<_SelectResult>();
2266 			_get_bones_at_pos(click, selection);
2267 			if (!selection.empty()) {
2268 				canvas_item = selection[0].item;
2269 			} else {
2270 				// Retrieve the canvas items
2271 				selection = Vector<_SelectResult>();
2272 				_get_canvas_items_at_pos(click, selection);
2273 				if (!selection.empty()) {
2274 					canvas_item = selection[0].item;
2275 				}
2276 			}
2277 
2278 			if (!canvas_item) {
2279 				// Start a box selection
2280 				if (!b->get_shift()) {
2281 					// Clear the selection if not additive
2282 					editor_selection->clear();
2283 					viewport->update();
2284 					selected_from_canvas = true;
2285 				};
2286 
2287 				drag_from = click;
2288 				drag_type = DRAG_BOX_SELECTION;
2289 				box_selecting_to = drag_from;
2290 				return true;
2291 			} else {
2292 				bool still_selected = _select_click_on_item(canvas_item, click, b->get_shift());
2293 				// Start dragging
2294 				if (still_selected) {
2295 					// Drag the node(s) if requested
2296 					List<CanvasItem *> selection2 = _get_edited_canvas_items();
2297 
2298 					drag_selection.clear();
2299 					for (int i = 0; i < selection2.size(); i++) {
2300 						if (_is_node_movable(selection2[i], true)) {
2301 							drag_selection.push_back(selection2[i]);
2302 						}
2303 					}
2304 
2305 					if (selection2.size() > 0) {
2306 						drag_type = DRAG_MOVE;
2307 						drag_from = click;
2308 						_save_canvas_item_state(drag_selection);
2309 					}
2310 				}
2311 				// Select the item
2312 				return true;
2313 			}
2314 		}
2315 	}
2316 
2317 	if (drag_type == DRAG_BOX_SELECTION) {
2318 		if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
2319 			// Confirms box selection
2320 			Node *scene = editor->get_edited_scene();
2321 			if (scene) {
2322 				List<CanvasItem *> selitems;
2323 
2324 				Point2 bsfrom = drag_from;
2325 				Point2 bsto = box_selecting_to;
2326 				if (bsfrom.x > bsto.x)
2327 					SWAP(bsfrom.x, bsto.x);
2328 				if (bsfrom.y > bsto.y)
2329 					SWAP(bsfrom.y, bsto.y);
2330 
2331 				_find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems);
2332 				for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
2333 					editor_selection->add_node(E->get());
2334 				}
2335 			}
2336 
2337 			drag_type = DRAG_NONE;
2338 			viewport->update();
2339 			return true;
2340 		}
2341 
2342 		if (b.is_valid() && b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
2343 			// Cancel box selection
2344 			drag_type = DRAG_NONE;
2345 			viewport->update();
2346 			return true;
2347 		}
2348 
2349 		if (m.is_valid()) {
2350 			// Update box selection
2351 			box_selecting_to = transform.affine_inverse().xform(m->get_position());
2352 			viewport->update();
2353 			return true;
2354 		}
2355 	}
2356 
2357 	if (k.is_valid() && k->is_pressed() && k->get_scancode() == KEY_ESCAPE && drag_type == DRAG_NONE && tool == TOOL_SELECT) {
2358 		// Unselect everything
2359 		editor_selection->clear();
2360 		viewport->update();
2361 	}
2362 	return false;
2363 }
2364 
_gui_input_ruler_tool(const Ref<InputEvent> & p_event)2365 bool CanvasItemEditor::_gui_input_ruler_tool(const Ref<InputEvent> &p_event) {
2366 
2367 	if (tool != TOOL_RULER)
2368 		return false;
2369 
2370 	Ref<InputEventMouseButton> b = p_event;
2371 	Ref<InputEventMouseMotion> m = p_event;
2372 
2373 	Point2 previous_origin = ruler_tool_origin;
2374 	if (!ruler_tool_active)
2375 		ruler_tool_origin = snap_point(viewport->get_local_mouse_position() / zoom + view_offset);
2376 
2377 	if (b.is_valid() && b->get_button_index() == BUTTON_LEFT) {
2378 		if (b->is_pressed()) {
2379 			ruler_tool_active = true;
2380 		} else {
2381 			ruler_tool_active = false;
2382 		}
2383 
2384 		viewport->update();
2385 		return true;
2386 	}
2387 
2388 	if (m.is_valid() && (ruler_tool_active || (grid_snap_active && previous_origin != ruler_tool_origin))) {
2389 
2390 		viewport->update();
2391 		return true;
2392 	}
2393 
2394 	return false;
2395 }
2396 
_gui_input_hover(const Ref<InputEvent> & p_event)2397 bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) {
2398 
2399 	Ref<InputEventMouseMotion> m = p_event;
2400 	if (m.is_valid()) {
2401 		Point2 click = transform.affine_inverse().xform(m->get_position());
2402 
2403 		// Checks if the hovered items changed, update the viewport if so
2404 		Vector<_SelectResult> hovering_results_items;
2405 		_get_canvas_items_at_pos(click, hovering_results_items);
2406 		hovering_results_items.sort();
2407 
2408 		// Compute the nodes names and icon position
2409 		Vector<_HoverResult> hovering_results_tmp;
2410 		for (int i = 0; i < hovering_results_items.size(); i++) {
2411 			CanvasItem *canvas_item = hovering_results_items[i].item;
2412 
2413 			if (canvas_item->_edit_use_rect())
2414 				continue;
2415 
2416 			_HoverResult hover_result;
2417 			hover_result.position = canvas_item->get_global_transform_with_canvas().get_origin();
2418 			hover_result.icon = EditorNode::get_singleton()->get_object_icon(canvas_item);
2419 			hover_result.name = canvas_item->get_name();
2420 
2421 			hovering_results_tmp.push_back(hover_result);
2422 		}
2423 
2424 		// Check if changed, if so, update.
2425 		bool changed = false;
2426 		if (hovering_results_tmp.size() == hovering_results.size()) {
2427 			for (int i = 0; i < hovering_results_tmp.size(); i++) {
2428 				_HoverResult a = hovering_results_tmp[i];
2429 				_HoverResult b = hovering_results[i];
2430 				if (a.icon != b.icon || a.name != b.name || a.position != b.position) {
2431 					changed = true;
2432 					break;
2433 				}
2434 			}
2435 		} else {
2436 			changed = true;
2437 		}
2438 
2439 		if (changed) {
2440 			hovering_results = hovering_results_tmp;
2441 			viewport->update();
2442 		}
2443 
2444 		return true;
2445 	}
2446 
2447 	return false;
2448 }
2449 
_gui_input_viewport(const Ref<InputEvent> & p_event)2450 void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
2451 	bool accepted = false;
2452 
2453 	if (EditorSettings::get_singleton()->get("editors/2d/simple_panning") || !pan_pressed) {
2454 		if ((accepted = _gui_input_rulers_and_guides(p_event))) {
2455 			//printf("Rulers and guides\n");
2456 		} else if ((accepted = editor->get_editor_plugins_over()->forward_gui_input(p_event))) {
2457 			//printf("Plugin\n");
2458 		} else if ((accepted = _gui_input_open_scene_on_double_click(p_event))) {
2459 			//printf("Open scene on double click\n");
2460 		} else if ((accepted = _gui_input_scale(p_event))) {
2461 			//printf("Set scale\n");
2462 		} else if ((accepted = _gui_input_pivot(p_event))) {
2463 			//printf("Set pivot\n");
2464 		} else if ((accepted = _gui_input_resize(p_event))) {
2465 			//printf("Resize\n");
2466 		} else if ((accepted = _gui_input_rotate(p_event))) {
2467 			//printf("Rotate\n");
2468 		} else if ((accepted = _gui_input_move(p_event))) {
2469 			//printf("Move\n");
2470 		} else if ((accepted = _gui_input_anchors(p_event))) {
2471 			//printf("Anchors\n");
2472 		} else if ((accepted = _gui_input_select(p_event))) {
2473 			//printf("Selection\n");
2474 		} else if ((accepted = _gui_input_ruler_tool(p_event))) {
2475 			//printf("Measure\n");
2476 		} else {
2477 			//printf("Not accepted\n");
2478 		}
2479 	}
2480 
2481 	accepted = (_gui_input_zoom_or_pan(p_event, accepted) || accepted);
2482 
2483 	if (accepted)
2484 		accept_event();
2485 
2486 	// Handles the mouse hovering
2487 	_gui_input_hover(p_event);
2488 
2489 	// Change the cursor
2490 	CursorShape c = CURSOR_ARROW;
2491 	switch (drag_type) {
2492 		case DRAG_NONE:
2493 			switch (tool) {
2494 				case TOOL_MOVE:
2495 					c = CURSOR_MOVE;
2496 					break;
2497 				case TOOL_EDIT_PIVOT:
2498 					c = CURSOR_CROSS;
2499 					break;
2500 				case TOOL_PAN:
2501 					c = CURSOR_DRAG;
2502 					break;
2503 				case TOOL_RULER:
2504 					c = CURSOR_CROSS;
2505 					break;
2506 				default:
2507 					break;
2508 			}
2509 			break;
2510 		case DRAG_LEFT:
2511 		case DRAG_RIGHT:
2512 		case DRAG_V_GUIDE:
2513 			c = CURSOR_HSIZE;
2514 			break;
2515 		case DRAG_TOP:
2516 		case DRAG_BOTTOM:
2517 		case DRAG_H_GUIDE:
2518 			c = CURSOR_VSIZE;
2519 			break;
2520 		case DRAG_TOP_LEFT:
2521 		case DRAG_BOTTOM_RIGHT:
2522 		case DRAG_DOUBLE_GUIDE:
2523 			c = CURSOR_FDIAGSIZE;
2524 			break;
2525 		case DRAG_TOP_RIGHT:
2526 		case DRAG_BOTTOM_LEFT:
2527 			c = CURSOR_BDIAGSIZE;
2528 			break;
2529 		case DRAG_MOVE:
2530 			c = CURSOR_MOVE;
2531 			break;
2532 		default:
2533 			break;
2534 	}
2535 
2536 	if (is_hovering_h_guide)
2537 		c = CURSOR_VSIZE;
2538 	else if (is_hovering_v_guide)
2539 		c = CURSOR_HSIZE;
2540 
2541 	viewport->set_default_cursor_shape(c);
2542 
2543 	// Grab focus
2544 	if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
2545 		viewport->call_deferred("grab_focus");
2546 	}
2547 }
2548 
_draw_text_at_position(Point2 p_position,String p_string,Margin p_side)2549 void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
2550 	Color color = get_color("font_color", "Editor");
2551 	color.a = 0.8;
2552 	Ref<Font> font = get_font("font", "Label");
2553 	Size2 text_size = font->get_string_size(p_string);
2554 	switch (p_side) {
2555 		case MARGIN_LEFT:
2556 			p_position += Vector2(-text_size.x - 5, text_size.y / 2);
2557 			break;
2558 		case MARGIN_TOP:
2559 			p_position += Vector2(-text_size.x / 2, -5);
2560 			break;
2561 		case MARGIN_RIGHT:
2562 			p_position += Vector2(5, text_size.y / 2);
2563 			break;
2564 		case MARGIN_BOTTOM:
2565 			p_position += Vector2(-text_size.x / 2, text_size.y + 5);
2566 			break;
2567 	}
2568 	viewport->draw_string(font, p_position, p_string, color);
2569 }
2570 
_draw_margin_at_position(int p_value,Point2 p_position,Margin p_side)2571 void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
2572 	String str = vformat("%d px", p_value);
2573 	if (p_value != 0) {
2574 		_draw_text_at_position(p_position, str, p_side);
2575 	}
2576 }
2577 
_draw_percentage_at_position(float p_value,Point2 p_position,Margin p_side)2578 void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
2579 	String str = vformat("%.1f %%", p_value * 100.0);
2580 	if (p_value != 0) {
2581 		_draw_text_at_position(p_position, str, p_side);
2582 	}
2583 }
2584 
_draw_focus()2585 void CanvasItemEditor::_draw_focus() {
2586 	// Draw the focus around the base viewport
2587 	if (viewport->has_focus()) {
2588 		get_stylebox("Focus", "EditorStyles")->draw(viewport->get_canvas_item(), Rect2(Point2(), viewport->get_size()));
2589 	}
2590 }
2591 
_draw_guides()2592 void CanvasItemEditor::_draw_guides() {
2593 
2594 	Color guide_color = EditorSettings::get_singleton()->get("editors/2d/guides_color");
2595 	Transform2D xform = viewport_scrollable->get_transform() * transform;
2596 
2597 	// Guides already there
2598 	if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) {
2599 		Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_");
2600 		for (int i = 0; i < vguides.size(); i++) {
2601 			if (drag_type == DRAG_V_GUIDE && i == dragged_guide_index)
2602 				continue;
2603 			float x = xform.xform(Point2(vguides[i], 0)).x;
2604 			viewport->draw_line(Point2(x, 0), Point2(x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
2605 		}
2606 	}
2607 
2608 	if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) {
2609 		Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_");
2610 		for (int i = 0; i < hguides.size(); i++) {
2611 			if (drag_type == DRAG_H_GUIDE && i == dragged_guide_index)
2612 				continue;
2613 			float y = xform.xform(Point2(0, hguides[i])).y;
2614 			viewport->draw_line(Point2(0, y), Point2(viewport->get_size().x, y), guide_color, Math::round(EDSCALE));
2615 		}
2616 	}
2617 
2618 	// Dragged guide
2619 	Color text_color = get_color("font_color", "Editor");
2620 	text_color.a = 0.5;
2621 	if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
2622 		String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x));
2623 		Ref<Font> font = get_font("font", "Label");
2624 		Size2 text_size = font->get_string_size(str);
2625 		viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
2626 		viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
2627 	}
2628 	if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
2629 		String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y));
2630 		Ref<Font> font = get_font("font", "Label");
2631 		Size2 text_size = font->get_string_size(str);
2632 		viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color);
2633 		viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE));
2634 	}
2635 }
2636 
_draw_smart_snapping()2637 void CanvasItemEditor::_draw_smart_snapping() {
2638 	Color line_color = EditorSettings::get_singleton()->get("editors/2d/smart_snapping_line_color");
2639 	if (snap_target[0] != SNAP_TARGET_NONE && snap_target[0] != SNAP_TARGET_GRID) {
2640 		viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
2641 		viewport->draw_line(Point2(0, -1.0e+10F), Point2(0, 1.0e+10F), line_color);
2642 		viewport->draw_set_transform_matrix(viewport->get_transform());
2643 	}
2644 	if (snap_target[1] != SNAP_TARGET_NONE && snap_target[1] != SNAP_TARGET_GRID) {
2645 		viewport->draw_set_transform_matrix(viewport->get_transform() * transform * snap_transform);
2646 		viewport->draw_line(Point2(-1.0e+10F, 0), Point2(1.0e+10F, 0), line_color);
2647 		viewport->draw_set_transform_matrix(viewport->get_transform());
2648 	}
2649 }
2650 
_draw_rulers()2651 void CanvasItemEditor::_draw_rulers() {
2652 	Color bg_color = get_color("dark_color_2", "Editor");
2653 	Color graduation_color = get_color("font_color", "Editor").linear_interpolate(bg_color, 0.5);
2654 	Color font_color = get_color("font_color", "Editor");
2655 	font_color.a = 0.8;
2656 	Ref<Font> font = get_font("rulers", "EditorFonts");
2657 
2658 	// The rule transform
2659 	Transform2D ruler_transform = Transform2D();
2660 	if (show_grid || grid_snap_active) {
2661 		List<CanvasItem *> selection = _get_edited_canvas_items();
2662 		if (snap_relative && selection.size() > 0) {
2663 			ruler_transform.translate(_get_encompassing_rect_from_list(selection).position);
2664 			ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
2665 		} else {
2666 			ruler_transform.translate(grid_offset);
2667 			ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
2668 		}
2669 		while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
2670 			ruler_transform.scale_basis(Point2(2, 2));
2671 		}
2672 	} else {
2673 		float basic_rule = 100;
2674 		for (int i = 0; basic_rule * zoom > 100; i++) {
2675 			basic_rule /= (i % 2) ? 5.0 : 2.0;
2676 		}
2677 		for (int i = 0; basic_rule * zoom < 100; i++) {
2678 			basic_rule *= (i % 2) ? 2.0 : 5.0;
2679 		}
2680 		ruler_transform.scale(Size2(basic_rule, basic_rule));
2681 	}
2682 
2683 	// Subdivisions
2684 	int major_subdivision = 2;
2685 	Transform2D major_subdivide = Transform2D();
2686 	major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
2687 
2688 	int minor_subdivision = 5;
2689 	Transform2D minor_subdivide = Transform2D();
2690 	minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
2691 
2692 	// First and last graduations to draw (in the ruler space)
2693 	Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2(RULER_WIDTH, RULER_WIDTH));
2694 	Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size());
2695 
2696 	// Draw top ruler
2697 	viewport->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
2698 	for (int i = Math::ceil(first.x); i < last.x; i++) {
2699 		Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0));
2700 		if (i % (major_subdivision * minor_subdivision) == 0) {
2701 			viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
2702 			float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
2703 			viewport->draw_string(font, Point2(position.x + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
2704 		} else {
2705 			if (i % minor_subdivision == 0) {
2706 				viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
2707 			} else {
2708 				viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.75), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
2709 			}
2710 		}
2711 	}
2712 
2713 	// Draw left ruler
2714 	viewport->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
2715 	for (int i = Math::ceil(first.y); i < last.y; i++) {
2716 		Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i));
2717 		if (i % (major_subdivision * minor_subdivision) == 0) {
2718 			viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
2719 			float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
2720 
2721 			Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(), position.y - 2));
2722 			viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform);
2723 			viewport->draw_string(font, Point2(), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
2724 			viewport->draw_set_transform_matrix(viewport->get_transform());
2725 
2726 		} else {
2727 			if (i % minor_subdivision == 0) {
2728 				viewport->draw_line(Point2(RULER_WIDTH * 0.33, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
2729 			} else {
2730 				viewport->draw_line(Point2(RULER_WIDTH * 0.75, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
2731 			}
2732 		}
2733 	}
2734 
2735 	// Draw the top left corner
2736 	viewport->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
2737 }
2738 
_draw_grid()2739 void CanvasItemEditor::_draw_grid() {
2740 
2741 	if (show_grid || grid_snap_active) {
2742 		// Draw the grid
2743 		Vector2 real_grid_offset;
2744 		const List<CanvasItem *> selection = _get_edited_canvas_items();
2745 
2746 		if (snap_relative && selection.size() > 0) {
2747 			const Vector2 topleft = _get_encompassing_rect_from_list(selection).position;
2748 			real_grid_offset.x = fmod(topleft.x, grid_step.x * (real_t)Math::pow(2.0, grid_step_multiplier));
2749 			real_grid_offset.y = fmod(topleft.y, grid_step.y * (real_t)Math::pow(2.0, grid_step_multiplier));
2750 		} else {
2751 			real_grid_offset = grid_offset;
2752 		}
2753 
2754 		// Draw a "primary" line every several lines to make measurements easier.
2755 		// The step is configurable in the Configure Snap dialog.
2756 		const Color secondary_grid_color = EditorSettings::get_singleton()->get("editors/2d/grid_color");
2757 		const Color primary_grid_color =
2758 				Color(secondary_grid_color.r, secondary_grid_color.g, secondary_grid_color.b, secondary_grid_color.a * 2.5);
2759 
2760 		const Size2 viewport_size = viewport->get_size();
2761 		const Transform2D xform = transform.affine_inverse();
2762 		int last_cell = 0;
2763 
2764 		if (grid_step.x != 0) {
2765 			for (int i = 0; i < viewport_size.width; i++) {
2766 				const int cell =
2767 						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))));
2768 
2769 				if (i == 0) {
2770 					last_cell = cell;
2771 				}
2772 
2773 				if (last_cell != cell) {
2774 					Color grid_color;
2775 					if (primary_grid_steps == 0) {
2776 						grid_color = secondary_grid_color;
2777 					} else {
2778 						grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
2779 					}
2780 
2781 					viewport->draw_line(Point2(i, 0), Point2(i, viewport_size.height), grid_color, Math::round(EDSCALE));
2782 				}
2783 				last_cell = cell;
2784 			}
2785 		}
2786 
2787 		if (grid_step.y != 0) {
2788 			for (int i = 0; i < viewport_size.height; i++) {
2789 				const int cell =
2790 						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))));
2791 
2792 				if (i == 0) {
2793 					last_cell = cell;
2794 				}
2795 
2796 				if (last_cell != cell) {
2797 					Color grid_color;
2798 					if (primary_grid_steps == 0) {
2799 						grid_color = secondary_grid_color;
2800 					} else {
2801 						grid_color = cell % primary_grid_steps == 0 ? primary_grid_color : secondary_grid_color;
2802 					}
2803 
2804 					viewport->draw_line(Point2(0, i), Point2(viewport_size.width, i), grid_color, Math::round(EDSCALE));
2805 				}
2806 				last_cell = cell;
2807 			}
2808 		}
2809 	}
2810 }
2811 
_draw_ruler_tool()2812 void CanvasItemEditor::_draw_ruler_tool() {
2813 
2814 	if (tool != TOOL_RULER)
2815 		return;
2816 
2817 	if (ruler_tool_active) {
2818 		Color ruler_primary_color = get_color("accent_color", "Editor");
2819 		Color ruler_secondary_color = ruler_primary_color;
2820 		ruler_secondary_color.a = 0.5;
2821 
2822 		Point2 begin = (ruler_tool_origin - view_offset) * zoom;
2823 		Point2 end = snap_point(viewport->get_local_mouse_position() / zoom + view_offset) * zoom - view_offset * zoom;
2824 		Point2 corner = Point2(begin.x, end.y);
2825 		Vector2 length_vector = (begin - end).abs() / zoom;
2826 
2827 		bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x));
2828 
2829 		viewport->draw_line(begin, end, ruler_primary_color, Math::round(EDSCALE * 3), true);
2830 		if (draw_secondary_lines) {
2831 			viewport->draw_line(begin, corner, ruler_secondary_color, Math::round(EDSCALE));
2832 			viewport->draw_line(corner, end, ruler_secondary_color, Math::round(EDSCALE));
2833 		}
2834 
2835 		Ref<Font> font = get_font("bold", "EditorFonts");
2836 		Color font_color = get_color("font_color", "Editor");
2837 		Color font_secondary_color = font_color;
2838 		font_secondary_color.a = 0.5;
2839 		float text_height = font->get_height();
2840 		const float text_width = 76;
2841 		const float angle_text_width = 54;
2842 
2843 		Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
2844 		text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
2845 		text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
2846 		viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color);
2847 
2848 		if (draw_secondary_lines) {
2849 			const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x);
2850 			const float vertical_angle_rad = Math_PI / 2.0 - horizontal_angle_rad;
2851 			const int horizontal_angle = round(180 * horizontal_angle_rad / Math_PI);
2852 			const int vertical_angle = round(180 * vertical_angle_rad / Math_PI);
2853 
2854 			Point2 text_pos2 = text_pos;
2855 			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);
2856 			viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.y), font_secondary_color);
2857 
2858 			Point2 v_angle_text_pos = Point2();
2859 			v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
2860 			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);
2861 			viewport->draw_string(font, v_angle_text_pos, vformat("%d deg", vertical_angle), font_secondary_color);
2862 
2863 			text_pos2 = text_pos;
2864 			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);
2865 			viewport->draw_string(font, text_pos2, vformat("%.2f px", length_vector.x), font_secondary_color);
2866 
2867 			Point2 h_angle_text_pos = Point2();
2868 			h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
2869 			if (begin.y < end.y) {
2870 				h_angle_text_pos.y = end.y + text_height * 1.5;
2871 				if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
2872 					int height_multiplier = 1.5 + (int)grid_snap_active;
2873 					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));
2874 				}
2875 			} else {
2876 				h_angle_text_pos.y = end.y - text_height * 0.5;
2877 				if (ABS(text_pos2.x - h_angle_text_pos.x) < text_width) {
2878 					int height_multiplier = 1 + (int)grid_snap_active;
2879 					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));
2880 				}
2881 			}
2882 			viewport->draw_string(font, h_angle_text_pos, vformat("%d deg", horizontal_angle), font_secondary_color);
2883 
2884 			// Angle arcs
2885 			int arc_point_count = 8;
2886 			float arc_radius_max_length_percent = 0.1;
2887 			float ruler_length = length_vector.length() * zoom;
2888 			float arc_max_radius = 50.0;
2889 			float arc_line_width = 2.0;
2890 
2891 			const Vector2 end_to_begin = (end - begin);
2892 
2893 			float arc_1_start_angle =
2894 					end_to_begin.x < 0 ?
2895 							(end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 - vertical_angle_rad : Math_PI / 2.0) :
2896 							(end_to_begin.y < 0 ? 3.0 * Math_PI / 2.0 : Math_PI / 2.0 - vertical_angle_rad);
2897 			float arc_1_end_angle = arc_1_start_angle + vertical_angle_rad;
2898 			// Constrain arc to triangle height & max size
2899 			float arc_1_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.y)), arc_max_radius);
2900 
2901 			float arc_2_start_angle =
2902 					end_to_begin.x < 0 ?
2903 							(end_to_begin.y < 0 ? 0.0 : -horizontal_angle_rad) :
2904 							(end_to_begin.y < 0 ? Math_PI - horizontal_angle_rad : Math_PI);
2905 			float arc_2_end_angle = arc_2_start_angle + horizontal_angle_rad;
2906 			// Constrain arc to triangle width & max size
2907 			float arc_2_radius = MIN(MIN(arc_radius_max_length_percent * ruler_length, ABS(end_to_begin.x)), arc_max_radius);
2908 
2909 			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));
2910 			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));
2911 		}
2912 
2913 		if (grid_snap_active) {
2914 
2915 			text_pos = (begin + end) / 2 + Vector2(-text_width / 2, text_height / 2);
2916 			text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
2917 			text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2);
2918 
2919 			if (draw_secondary_lines) {
2920 				viewport->draw_string(font, text_pos, vformat("%.2f units", (length_vector / grid_step).length()), font_color);
2921 
2922 				Point2 text_pos2 = text_pos;
2923 				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);
2924 				viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.y / grid_step.y)), font_secondary_color);
2925 
2926 				text_pos2 = text_pos;
2927 				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);
2928 				viewport->draw_string(font, text_pos2, vformat("%d units", roundf(length_vector.x / grid_step.x)), font_secondary_color);
2929 			} else {
2930 				viewport->draw_string(font, text_pos, vformat("%d units", roundf((length_vector / grid_step).length())), font_color);
2931 			}
2932 		}
2933 	} else {
2934 
2935 		if (grid_snap_active) {
2936 			Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
2937 			viewport->draw_texture(get_icon("EditorPosition", "EditorIcons"), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2);
2938 		}
2939 	}
2940 }
2941 
_draw_control_anchors(Control * control)2942 void CanvasItemEditor::_draw_control_anchors(Control *control) {
2943 	Transform2D xform = transform * control->get_global_transform_with_canvas();
2944 	RID ci = viewport->get_canvas_item();
2945 	if (tool == TOOL_SELECT && !Object::cast_to<Container>(control->get_parent())) {
2946 
2947 		// Compute the anchors
2948 		float anchors_values[4];
2949 		anchors_values[0] = control->get_anchor(MARGIN_LEFT);
2950 		anchors_values[1] = control->get_anchor(MARGIN_TOP);
2951 		anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
2952 		anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
2953 
2954 		Vector2 anchors_pos[4];
2955 		for (int i = 0; i < 4; i++) {
2956 			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]);
2957 			anchors_pos[i] = xform.xform(_anchor_to_position(control, value));
2958 		}
2959 
2960 		// Draw the anchors handles
2961 		Rect2 anchor_rects[4];
2962 		anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
2963 		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));
2964 		anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
2965 		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));
2966 
2967 		for (int i = 0; i < 4; i++) {
2968 			anchor_handle->draw_rect(ci, anchor_rects[i]);
2969 		}
2970 	}
2971 }
2972 
_draw_control_helpers(Control * control)2973 void CanvasItemEditor::_draw_control_helpers(Control *control) {
2974 	Transform2D xform = transform * control->get_global_transform_with_canvas();
2975 	if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
2976 		// Draw the helpers
2977 		Color color_base = Color(0.8, 0.8, 0.8, 0.5);
2978 
2979 		// Compute the anchors
2980 		float anchors_values[4];
2981 		anchors_values[0] = control->get_anchor(MARGIN_LEFT);
2982 		anchors_values[1] = control->get_anchor(MARGIN_TOP);
2983 		anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
2984 		anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
2985 
2986 		Vector2 anchors[4];
2987 		Vector2 anchors_pos[4];
2988 		for (int i = 0; i < 4; i++) {
2989 			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]);
2990 			anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i]));
2991 		}
2992 
2993 		// Get which anchor is dragged
2994 		int dragged_anchor = -1;
2995 		switch (drag_type) {
2996 			case DRAG_ANCHOR_ALL:
2997 			case DRAG_ANCHOR_TOP_LEFT:
2998 				dragged_anchor = 0;
2999 				break;
3000 			case DRAG_ANCHOR_TOP_RIGHT:
3001 				dragged_anchor = 1;
3002 				break;
3003 			case DRAG_ANCHOR_BOTTOM_RIGHT:
3004 				dragged_anchor = 2;
3005 				break;
3006 			case DRAG_ANCHOR_BOTTOM_LEFT:
3007 				dragged_anchor = 3;
3008 				break;
3009 			default:
3010 				break;
3011 		}
3012 
3013 		if (dragged_anchor >= 0) {
3014 			// Draw the 4 lines when dragged
3015 			bool anchor_snapped;
3016 			Color color_snapped = Color(0.64, 0.93, 0.67, 0.5);
3017 
3018 			Vector2 corners_pos[4];
3019 			for (int i = 0; i < 4; i++) {
3020 				corners_pos[i] = xform.xform(_anchor_to_position(control, Vector2((i == 0 || i == 3) ? ANCHOR_BEGIN : ANCHOR_END, (i <= 1) ? ANCHOR_BEGIN : ANCHOR_END)));
3021 			}
3022 
3023 			Vector2 line_starts[4];
3024 			Vector2 line_ends[4];
3025 			for (int i = 0; i < 4; i++) {
3026 				float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i];
3027 				line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val);
3028 				line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val);
3029 				anchor_snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
3030 				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);
3031 			}
3032 
3033 			// Display the percentages next to the lines
3034 			float percent_val;
3035 			percent_val = anchors_values[(dragged_anchor + 2) % 4] - anchors_values[dragged_anchor];
3036 			percent_val = (dragged_anchor >= 2) ? -percent_val : percent_val;
3037 			_draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 1) % 4]) / 2, (Margin)((dragged_anchor + 1) % 4));
3038 
3039 			percent_val = anchors_values[(dragged_anchor + 3) % 4] - anchors_values[(dragged_anchor + 1) % 4];
3040 			percent_val = ((dragged_anchor + 1) % 4 >= 2) ? -percent_val : percent_val;
3041 			_draw_percentage_at_position(percent_val, (anchors_pos[dragged_anchor] + anchors_pos[(dragged_anchor + 3) % 4]) / 2, (Margin)(dragged_anchor));
3042 
3043 			percent_val = anchors_values[(dragged_anchor + 1) % 4];
3044 			percent_val = ((dragged_anchor + 1) % 4 >= 2) ? ANCHOR_END - percent_val : percent_val;
3045 			_draw_percentage_at_position(percent_val, (line_starts[dragged_anchor] + anchors_pos[dragged_anchor]) / 2, (Margin)(dragged_anchor));
3046 
3047 			percent_val = anchors_values[dragged_anchor];
3048 			percent_val = (dragged_anchor >= 2) ? ANCHOR_END - percent_val : percent_val;
3049 			_draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4));
3050 		}
3051 
3052 		// Draw the margin values and the node width/height when dragging control side
3053 		float ratio = 0.33;
3054 		Transform2D parent_transform = xform * control->get_transform().affine_inverse();
3055 		float node_pos_in_parent[4];
3056 
3057 		Rect2 parent_rect = control->get_parent_anchorable_rect();
3058 
3059 		node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * parent_rect.size.width + control->get_margin(MARGIN_LEFT) + parent_rect.position.x;
3060 		node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * parent_rect.size.height + control->get_margin(MARGIN_TOP) + parent_rect.position.y;
3061 		node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * parent_rect.size.width + control->get_margin(MARGIN_RIGHT) + parent_rect.position.x;
3062 		node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * parent_rect.size.height + control->get_margin(MARGIN_BOTTOM) + parent_rect.position.y;
3063 
3064 		Point2 start, end;
3065 		switch (drag_type) {
3066 			case DRAG_LEFT:
3067 			case DRAG_TOP_LEFT:
3068 			case DRAG_BOTTOM_LEFT:
3069 				_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);
3070 				FALLTHROUGH;
3071 			case DRAG_MOVE:
3072 				start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
3073 				end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
3074 				_draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP);
3075 				viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
3076 				break;
3077 			default:
3078 				break;
3079 		}
3080 		switch (drag_type) {
3081 			case DRAG_RIGHT:
3082 			case DRAG_TOP_RIGHT:
3083 			case DRAG_BOTTOM_RIGHT:
3084 				_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);
3085 				FALLTHROUGH;
3086 			case DRAG_MOVE:
3087 				start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
3088 				end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
3089 				_draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM);
3090 				viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
3091 				break;
3092 			default:
3093 				break;
3094 		}
3095 		switch (drag_type) {
3096 			case DRAG_TOP:
3097 			case DRAG_TOP_LEFT:
3098 			case DRAG_TOP_RIGHT:
3099 				_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);
3100 				FALLTHROUGH;
3101 			case DRAG_MOVE:
3102 				start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
3103 				end = start - Vector2(0, control->get_margin(MARGIN_TOP));
3104 				_draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT);
3105 				viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
3106 				break;
3107 			default:
3108 				break;
3109 		}
3110 		switch (drag_type) {
3111 			case DRAG_BOTTOM:
3112 			case DRAG_BOTTOM_LEFT:
3113 			case DRAG_BOTTOM_RIGHT:
3114 				_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);
3115 				FALLTHROUGH;
3116 			case DRAG_MOVE:
3117 				start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
3118 				end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
3119 				_draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT);
3120 				viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, Math::round(EDSCALE));
3121 				break;
3122 			default:
3123 				break;
3124 		}
3125 
3126 		switch (drag_type) {
3127 			//Draw the ghost rect if the node if rotated/scaled
3128 			case DRAG_LEFT:
3129 			case DRAG_TOP_LEFT:
3130 			case DRAG_TOP:
3131 			case DRAG_TOP_RIGHT:
3132 			case DRAG_RIGHT:
3133 			case DRAG_BOTTOM_RIGHT:
3134 			case DRAG_BOTTOM:
3135 			case DRAG_BOTTOM_LEFT:
3136 			case DRAG_MOVE:
3137 				if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) {
3138 					Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size());
3139 					viewport->draw_rect(parent_transform.xform(rect), color_base, false, Math::round(EDSCALE));
3140 				}
3141 				break;
3142 			default:
3143 				break;
3144 		}
3145 	}
3146 }
3147 
_draw_selection()3148 void CanvasItemEditor::_draw_selection() {
3149 	Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons");
3150 	Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
3151 	Ref<Texture> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons");
3152 
3153 	RID ci = viewport->get_canvas_item();
3154 
3155 	List<CanvasItem *> selection = _get_edited_canvas_items(true, false);
3156 
3157 	bool single = selection.size() == 1;
3158 	for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
3159 		CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
3160 		CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
3161 
3162 		bool item_locked = canvas_item->has_meta("_edit_lock_");
3163 
3164 		// Draw the previous position if we are dragging the node
3165 		if (show_helpers &&
3166 				(drag_type == DRAG_MOVE || drag_type == DRAG_ROTATE ||
3167 						drag_type == DRAG_LEFT || drag_type == DRAG_RIGHT || drag_type == DRAG_TOP || drag_type == DRAG_BOTTOM ||
3168 						drag_type == DRAG_TOP_LEFT || drag_type == DRAG_TOP_RIGHT || drag_type == DRAG_BOTTOM_LEFT || drag_type == DRAG_BOTTOM_RIGHT)) {
3169 			const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
3170 			const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7);
3171 
3172 			if (canvas_item->_edit_use_rect()) {
3173 				Vector2 pre_drag_endpoints[4] = {
3174 
3175 					pre_drag_xform.xform(se->pre_drag_rect.position),
3176 					pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)),
3177 					pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size),
3178 					pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y))
3179 				};
3180 
3181 				for (int i = 0; i < 4; i++) {
3182 					viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, Math::round(2 * EDSCALE), true);
3183 				}
3184 			} else {
3185 				viewport->draw_texture(previous_position_icon, (pre_drag_xform.xform(Point2()) - (previous_position_icon->get_size() / 2)).floor());
3186 			}
3187 		}
3188 
3189 		Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
3190 
3191 		// Draw the selected items position / surrounding boxes
3192 		if (canvas_item->_edit_use_rect()) {
3193 			Rect2 rect = canvas_item->_edit_get_rect();
3194 			Vector2 endpoints[4] = {
3195 				xform.xform(rect.position),
3196 				xform.xform(rect.position + Vector2(rect.size.x, 0)),
3197 				xform.xform(rect.position + rect.size),
3198 				xform.xform(rect.position + Vector2(0, rect.size.y))
3199 			};
3200 
3201 			Color c = Color(1, 0.6, 0.4, 0.7);
3202 
3203 			if (item_locked) {
3204 				c = Color(0.7, 0.7, 0.7, 0.7);
3205 			}
3206 
3207 			for (int i = 0; i < 4; i++) {
3208 				viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, Math::round(2 * EDSCALE), true);
3209 			}
3210 		} else {
3211 
3212 			Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
3213 			Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
3214 			viewport->draw_set_transform_matrix(simple_xform);
3215 			viewport->draw_texture(position_icon, -(position_icon->get_size() / 2));
3216 			viewport->draw_set_transform_matrix(viewport->get_transform());
3217 		}
3218 
3219 		if (single && !item_locked && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_SCALE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
3220 			// Draw the pivot
3221 			if (canvas_item->_edit_use_pivot()) {
3222 
3223 				// Draw the node's pivot
3224 				Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
3225 				Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
3226 
3227 				viewport->draw_set_transform_matrix(simple_xform);
3228 				viewport->draw_texture(pivot_icon, -(pivot_icon->get_size() / 2).floor());
3229 				viewport->draw_set_transform_matrix(viewport->get_transform());
3230 			}
3231 
3232 			// Draw control-related helpers
3233 			Control *control = Object::cast_to<Control>(canvas_item);
3234 			if (control && _is_node_movable(control)) {
3235 				_draw_control_anchors(control);
3236 				_draw_control_helpers(control);
3237 			}
3238 
3239 			// Draw the resize handles
3240 			if (tool == TOOL_SELECT && canvas_item->_edit_use_rect() && _is_node_movable(canvas_item)) {
3241 				Rect2 rect = canvas_item->_edit_get_rect();
3242 				Vector2 endpoints[4] = {
3243 					xform.xform(rect.position),
3244 					xform.xform(rect.position + Vector2(rect.size.x, 0)),
3245 					xform.xform(rect.position + rect.size),
3246 					xform.xform(rect.position + Vector2(0, rect.size.y))
3247 				};
3248 				for (int i = 0; i < 4; i++) {
3249 					int prev = (i + 3) % 4;
3250 					int next = (i + 1) % 4;
3251 
3252 					Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
3253 					ofs *= Math_SQRT2 * (select_handle->get_size().width / 2);
3254 
3255 					select_handle->draw(ci, (endpoints[i] + ofs - (select_handle->get_size() / 2)).floor());
3256 
3257 					ofs = (endpoints[i] + endpoints[next]) / 2;
3258 					ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
3259 
3260 					select_handle->draw(ci, (ofs - (select_handle->get_size() / 2)).floor());
3261 				}
3262 			}
3263 
3264 			// Draw the rescale handles
3265 			bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
3266 			bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
3267 			if ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) {
3268 				if (_is_node_movable(canvas_item)) {
3269 					Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
3270 					Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
3271 
3272 					Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
3273 					bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
3274 					Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom;
3275 
3276 					if (drag_type == DRAG_SCALE_X) {
3277 						scale_factor.x += offset.x;
3278 						if (uniform) {
3279 							scale_factor.y += offset.x;
3280 						}
3281 					} else if (drag_type == DRAG_SCALE_Y) {
3282 						scale_factor.y -= offset.y;
3283 						if (uniform) {
3284 							scale_factor.x -= offset.y;
3285 						}
3286 					}
3287 
3288 					viewport->draw_set_transform_matrix(simple_xform);
3289 					Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
3290 					viewport->draw_rect(x_handle_rect, get_color("axis_x_color", "Editor"));
3291 					viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE), true);
3292 
3293 					Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE);
3294 					viewport->draw_rect(y_handle_rect, get_color("axis_y_color", "Editor"));
3295 					viewport->draw_line(Point2(), Point2(0, -scale_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE), true);
3296 
3297 					viewport->draw_set_transform_matrix(viewport->get_transform());
3298 				}
3299 			}
3300 		}
3301 	}
3302 
3303 	if (drag_type == DRAG_BOX_SELECTION) {
3304 		// Draw the dragging box
3305 		Point2 bsfrom = transform.xform(drag_from);
3306 		Point2 bsto = transform.xform(box_selecting_to);
3307 
3308 		viewport->draw_rect(
3309 				Rect2(bsfrom, bsto - bsfrom),
3310 				get_color("box_selection_fill_color", "Editor"));
3311 
3312 		viewport->draw_rect(
3313 				Rect2(bsfrom, bsto - bsfrom),
3314 				get_color("box_selection_stroke_color", "Editor"),
3315 				false,
3316 				Math::round(EDSCALE));
3317 	}
3318 
3319 	if (drag_type == DRAG_ROTATE) {
3320 		// Draw the line when rotating a node
3321 		viewport->draw_line(
3322 				transform.xform(drag_rotation_center),
3323 				transform.xform(drag_to),
3324 				get_color("accent_color", "Editor") * Color(1, 1, 1, 0.6),
3325 				Math::round(2 * EDSCALE),
3326 				true);
3327 	}
3328 }
3329 
_draw_straight_line(Point2 p_from,Point2 p_to,Color p_color)3330 void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_color) {
3331 	// Draw a line going through the whole screen from a vector
3332 	RID ci = viewport->get_canvas_item();
3333 	Vector<Point2> points;
3334 	Point2 from = transform.xform(p_from);
3335 	Point2 to = transform.xform(p_to);
3336 	Size2 viewport_size = viewport->get_size();
3337 
3338 	if (to.x == from.x) {
3339 		// Vertical line
3340 		points.push_back(Point2(to.x, 0));
3341 		points.push_back(Point2(to.x, viewport_size.y));
3342 	} else if (to.y == from.y) {
3343 		// Horizontal line
3344 		points.push_back(Point2(0, to.y));
3345 		points.push_back(Point2(viewport_size.x, to.y));
3346 	} else {
3347 		float y_for_zero_x = (to.y * from.x - from.y * to.x) / (from.x - to.x);
3348 		float x_for_zero_y = (to.x * from.y - from.x * to.y) / (from.y - to.y);
3349 		float y_for_viewport_x = ((to.y - from.y) * (viewport_size.x - from.x)) / (to.x - from.x) + from.y;
3350 		float x_for_viewport_y = ((to.x - from.x) * (viewport_size.y - from.y)) / (to.y - from.y) + from.x; // faux
3351 
3352 		//bool start_set = false;
3353 		if (y_for_zero_x >= 0 && y_for_zero_x <= viewport_size.y) {
3354 			points.push_back(Point2(0, y_for_zero_x));
3355 		}
3356 		if (x_for_zero_y >= 0 && x_for_zero_y <= viewport_size.x) {
3357 			points.push_back(Point2(x_for_zero_y, 0));
3358 		}
3359 		if (y_for_viewport_x >= 0 && y_for_viewport_x <= viewport_size.y) {
3360 			points.push_back(Point2(viewport_size.x, y_for_viewport_x));
3361 		}
3362 		if (x_for_viewport_y >= 0 && x_for_viewport_y <= viewport_size.x) {
3363 			points.push_back(Point2(x_for_viewport_y, viewport_size.y));
3364 		}
3365 	}
3366 	if (points.size() >= 2) {
3367 		VisualServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color);
3368 	}
3369 }
3370 
_draw_axis()3371 void CanvasItemEditor::_draw_axis() {
3372 
3373 	if (show_origin) {
3374 
3375 		_draw_straight_line(Point2(), Point2(1, 0), get_color("axis_x_color", "Editor") * Color(1, 1, 1, 0.75));
3376 		_draw_straight_line(Point2(), Point2(0, 1), get_color("axis_y_color", "Editor") * Color(1, 1, 1, 0.75));
3377 	}
3378 
3379 	if (show_viewport) {
3380 
3381 		RID ci = viewport->get_canvas_item();
3382 
3383 		Color area_axis_color = EditorSettings::get_singleton()->get("editors/2d/viewport_border_color");
3384 
3385 		Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
3386 
3387 		Vector2 screen_endpoints[4] = {
3388 			transform.xform(Vector2(0, 0)),
3389 			transform.xform(Vector2(screen_size.width, 0)),
3390 			transform.xform(Vector2(screen_size.width, screen_size.height)),
3391 			transform.xform(Vector2(0, screen_size.height))
3392 		};
3393 
3394 		for (int i = 0; i < 4; i++) {
3395 			VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color);
3396 		}
3397 	}
3398 }
3399 
_draw_bones()3400 void CanvasItemEditor::_draw_bones() {
3401 	RID ci = viewport->get_canvas_item();
3402 
3403 	if (skeleton_show_bones) {
3404 		Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
3405 		Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
3406 		Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
3407 		Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
3408 		Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
3409 
3410 		for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
3411 
3412 			Vector<Vector2> bone_shape;
3413 			Vector<Vector2> bone_shape_outline;
3414 			if (!_get_bone_shape(&bone_shape, &bone_shape_outline, E))
3415 				continue;
3416 
3417 			Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
3418 			if (!from_node->is_visible_in_tree())
3419 				continue;
3420 
3421 			Vector<Color> colors;
3422 			if (from_node->has_meta("_edit_ik_")) {
3423 				colors.push_back(bone_ik_color);
3424 				colors.push_back(bone_ik_color);
3425 				colors.push_back(bone_ik_color);
3426 				colors.push_back(bone_ik_color);
3427 			} else {
3428 				colors.push_back(bone_color1);
3429 				colors.push_back(bone_color2);
3430 				colors.push_back(bone_color1);
3431 				colors.push_back(bone_color2);
3432 			}
3433 
3434 			Vector<Color> outline_colors;
3435 
3436 			if (editor_selection->is_selected(from_node)) {
3437 				outline_colors.push_back(bone_selected_color);
3438 				outline_colors.push_back(bone_selected_color);
3439 				outline_colors.push_back(bone_selected_color);
3440 				outline_colors.push_back(bone_selected_color);
3441 				outline_colors.push_back(bone_selected_color);
3442 				outline_colors.push_back(bone_selected_color);
3443 			} else {
3444 				outline_colors.push_back(bone_outline_color);
3445 				outline_colors.push_back(bone_outline_color);
3446 				outline_colors.push_back(bone_outline_color);
3447 				outline_colors.push_back(bone_outline_color);
3448 				outline_colors.push_back(bone_outline_color);
3449 				outline_colors.push_back(bone_outline_color);
3450 			}
3451 
3452 			VisualServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors);
3453 			VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID());
3454 		}
3455 	}
3456 }
3457 
_draw_invisible_nodes_positions(Node * p_node,const Transform2D & p_parent_xform,const Transform2D & p_canvas_xform)3458 void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
3459 	ERR_FAIL_COND(!p_node);
3460 
3461 	Node *scene = editor->get_edited_scene();
3462 	if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner()))
3463 		return;
3464 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
3465 	if (canvas_item && !canvas_item->is_visible())
3466 		return;
3467 
3468 	Transform2D parent_xform = p_parent_xform;
3469 	Transform2D canvas_xform = p_canvas_xform;
3470 
3471 	if (canvas_item && !canvas_item->is_set_as_toplevel()) {
3472 		parent_xform = parent_xform * canvas_item->get_transform();
3473 	} else {
3474 		CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
3475 		parent_xform = Transform2D();
3476 		canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
3477 	}
3478 
3479 	for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
3480 		_draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform);
3481 	}
3482 
3483 	if (canvas_item && !canvas_item->_edit_use_rect() && (!editor_selection->is_selected(canvas_item) || _is_node_locked(canvas_item))) {
3484 		Transform2D xform = transform * canvas_xform * parent_xform;
3485 
3486 		// Draw the node's position
3487 		Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons");
3488 		Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
3489 		Transform2D simple_xform = viewport->get_transform() * unscaled_transform;
3490 		viewport->draw_set_transform_matrix(simple_xform);
3491 		viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5));
3492 		viewport->draw_set_transform_matrix(viewport->get_transform());
3493 	}
3494 }
3495 
_draw_hover()3496 void CanvasItemEditor::_draw_hover() {
3497 	List<Rect2> previous_rects;
3498 
3499 	for (int i = 0; i < hovering_results.size(); i++) {
3500 
3501 		Ref<Texture> node_icon = hovering_results[i].icon;
3502 		String node_name = hovering_results[i].name;
3503 
3504 		Ref<Font> font = get_font("font", "Label");
3505 		Size2 node_name_size = font->get_string_size(node_name);
3506 		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));
3507 
3508 		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);
3509 		// Rectify the position to avoid overlapping items
3510 		for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) {
3511 			if (E->get().intersects(Rect2(pos, item_size))) {
3512 				pos.y = E->get().get_position().y - item_size.y;
3513 			}
3514 		}
3515 
3516 		previous_rects.push_back(Rect2(pos, item_size));
3517 
3518 		// Draw icon
3519 		viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5));
3520 
3521 		// Draw name
3522 		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));
3523 	}
3524 }
3525 
_draw_locks_and_groups(Node * p_node,const Transform2D & p_parent_xform,const Transform2D & p_canvas_xform)3526 void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
3527 	ERR_FAIL_COND(!p_node);
3528 
3529 	Node *scene = editor->get_edited_scene();
3530 	if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner()))
3531 		return;
3532 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
3533 	if (canvas_item && !canvas_item->is_visible())
3534 		return;
3535 
3536 	Transform2D parent_xform = p_parent_xform;
3537 	Transform2D canvas_xform = p_canvas_xform;
3538 
3539 	if (canvas_item && !canvas_item->is_set_as_toplevel()) {
3540 		parent_xform = parent_xform * canvas_item->get_transform();
3541 	} else {
3542 		CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
3543 		parent_xform = Transform2D();
3544 		canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
3545 	}
3546 
3547 	for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
3548 		_draw_locks_and_groups(p_node->get_child(i), parent_xform, canvas_xform);
3549 	}
3550 
3551 	RID viewport_canvas_item = viewport->get_canvas_item();
3552 	if (canvas_item) {
3553 		float offset = 0;
3554 
3555 		Ref<Texture> lock = get_icon("LockViewport", "EditorIcons");
3556 		if (p_node->has_meta("_edit_lock_") && show_edit_locks) {
3557 			lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
3558 			offset += lock->get_size().x;
3559 		}
3560 
3561 		Ref<Texture> group = get_icon("GroupViewport", "EditorIcons");
3562 		if (canvas_item->has_meta("_edit_group_") && show_edit_locks) {
3563 			group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
3564 			//offset += group->get_size().x;
3565 		}
3566 	}
3567 }
3568 
_build_bones_list(Node * p_node)3569 bool CanvasItemEditor::_build_bones_list(Node *p_node) {
3570 	ERR_FAIL_COND_V(!p_node, false);
3571 
3572 	bool has_child_bones = false;
3573 
3574 	for (int i = 0; i < p_node->get_child_count(); i++) {
3575 		if (_build_bones_list(p_node->get_child(i))) {
3576 			has_child_bones = true;
3577 		}
3578 	}
3579 
3580 	CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
3581 	Node *scene = editor->get_edited_scene();
3582 	if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner()))) {
3583 		return false;
3584 	}
3585 
3586 	Node *parent = canvas_item->get_parent();
3587 
3588 	if (Object::cast_to<Bone2D>(canvas_item)) {
3589 		if (Object::cast_to<Bone2D>(parent)) {
3590 			// Add as bone->parent relationship
3591 			BoneKey bk;
3592 			bk.from = parent->get_instance_id();
3593 			bk.to = canvas_item->get_instance_id();
3594 			if (!bone_list.has(bk)) {
3595 				BoneList b;
3596 				b.length = 0;
3597 				bone_list[bk] = b;
3598 			}
3599 
3600 			bone_list[bk].last_pass = bone_last_frame;
3601 		}
3602 
3603 		if (!has_child_bones) {
3604 			// Add a last bone if the Bone2D has no Bone2D child
3605 			BoneKey bk;
3606 			bk.from = canvas_item->get_instance_id();
3607 			bk.to = 0;
3608 			if (!bone_list.has(bk)) {
3609 				BoneList b;
3610 				b.length = 0;
3611 				bone_list[bk] = b;
3612 			}
3613 			bone_list[bk].last_pass = bone_last_frame;
3614 		}
3615 
3616 		return true;
3617 	}
3618 
3619 	if (canvas_item->has_meta("_edit_bone_")) {
3620 		// Add a "custom bone"
3621 		BoneKey bk;
3622 		bk.from = parent->get_instance_id();
3623 		bk.to = canvas_item->get_instance_id();
3624 		if (!bone_list.has(bk)) {
3625 			BoneList b;
3626 			b.length = 0;
3627 			bone_list[bk] = b;
3628 		}
3629 		bone_list[bk].last_pass = bone_last_frame;
3630 	}
3631 
3632 	return false;
3633 }
3634 
_draw_viewport()3635 void CanvasItemEditor::_draw_viewport() {
3636 
3637 	// Update the transform
3638 	transform = Transform2D();
3639 	transform.scale_basis(Size2(zoom, zoom));
3640 	transform.elements[2] = -view_offset * zoom;
3641 	editor->get_scene_root()->set_global_canvas_transform(transform);
3642 
3643 	// hide/show buttons depending on the selection
3644 	bool all_locked = true;
3645 	bool all_group = true;
3646 	List<Node *> selection = editor_selection->get_selected_node_list();
3647 	if (selection.empty()) {
3648 		all_locked = false;
3649 		all_group = false;
3650 	} else {
3651 		for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
3652 			if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_lock_")) {
3653 				all_locked = false;
3654 				break;
3655 			}
3656 		}
3657 		for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
3658 			if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_group_")) {
3659 				all_group = false;
3660 				break;
3661 			}
3662 		}
3663 	}
3664 
3665 	lock_button->set_visible(!all_locked);
3666 	lock_button->set_disabled(selection.empty());
3667 	unlock_button->set_visible(all_locked);
3668 	group_button->set_visible(!all_group);
3669 	group_button->set_disabled(selection.empty());
3670 	ungroup_button->set_visible(all_group);
3671 
3672 	info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
3673 
3674 	_draw_grid();
3675 	_draw_ruler_tool();
3676 	_draw_selection();
3677 	_draw_axis();
3678 	if (editor->get_edited_scene()) {
3679 		_draw_locks_and_groups(editor->get_edited_scene());
3680 		_draw_invisible_nodes_positions(editor->get_edited_scene());
3681 	}
3682 
3683 	RID ci = viewport->get_canvas_item();
3684 	VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
3685 
3686 	EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
3687 	if (!over_plugin_list->empty()) {
3688 		over_plugin_list->forward_canvas_draw_over_viewport(viewport);
3689 	}
3690 	EditorPluginList *force_over_plugin_list = editor->get_editor_plugins_force_over();
3691 	if (!force_over_plugin_list->empty()) {
3692 		force_over_plugin_list->forward_canvas_force_draw_over_viewport(viewport);
3693 	}
3694 
3695 	_draw_bones();
3696 	if (show_rulers)
3697 		_draw_rulers();
3698 	if (show_guides)
3699 		_draw_guides();
3700 	_draw_smart_snapping();
3701 	_draw_focus();
3702 	_draw_hover();
3703 }
3704 
update_viewport()3705 void CanvasItemEditor::update_viewport() {
3706 	_update_scrollbars();
3707 	viewport->update();
3708 }
3709 
set_current_tool(Tool p_tool)3710 void CanvasItemEditor::set_current_tool(Tool p_tool) {
3711 	_button_tool_select(p_tool);
3712 }
3713 
_notification(int p_what)3714 void CanvasItemEditor::_notification(int p_what) {
3715 
3716 	if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
3717 		EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
3718 
3719 		bool has_container_parents = false;
3720 		int nb_control = 0;
3721 		int nb_having_pivot = 0;
3722 
3723 		// Update the viewport if the canvas_item changes
3724 		List<CanvasItem *> selection = _get_edited_canvas_items(true);
3725 		for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
3726 			CanvasItem *canvas_item = E->get();
3727 			CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
3728 
3729 			Rect2 rect;
3730 			if (canvas_item->_edit_use_rect()) {
3731 				rect = canvas_item->_edit_get_rect();
3732 			} else {
3733 				rect = Rect2();
3734 			}
3735 			Transform2D xform = canvas_item->get_transform();
3736 
3737 			if (rect != se->prev_rect || xform != se->prev_xform) {
3738 				viewport->update();
3739 				se->prev_rect = rect;
3740 				se->prev_xform = xform;
3741 			}
3742 
3743 			Control *control = Object::cast_to<Control>(canvas_item);
3744 			if (control) {
3745 				float anchors[4];
3746 				Vector2 pivot;
3747 
3748 				pivot = control->get_pivot_offset();
3749 				anchors[MARGIN_LEFT] = control->get_anchor(MARGIN_LEFT);
3750 				anchors[MARGIN_RIGHT] = control->get_anchor(MARGIN_RIGHT);
3751 				anchors[MARGIN_TOP] = control->get_anchor(MARGIN_TOP);
3752 				anchors[MARGIN_BOTTOM] = control->get_anchor(MARGIN_BOTTOM);
3753 
3754 				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]) {
3755 					se->prev_pivot = pivot;
3756 					se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT];
3757 					se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT];
3758 					se->prev_anchors[MARGIN_TOP] = anchors[MARGIN_TOP];
3759 					se->prev_anchors[MARGIN_BOTTOM] = anchors[MARGIN_BOTTOM];
3760 					viewport->update();
3761 				}
3762 				nb_control++;
3763 
3764 				if (Object::cast_to<Container>(control->get_parent())) {
3765 					has_container_parents = true;
3766 				}
3767 			}
3768 
3769 			if (canvas_item->_edit_use_pivot()) {
3770 				nb_having_pivot++;
3771 			}
3772 		}
3773 
3774 		// Activate / Deactivate the pivot tool
3775 		pivot_button->set_disabled(nb_having_pivot == 0);
3776 
3777 		// Show / Hide the layout and anchors mode buttons
3778 		if (nb_control > 0 && nb_control == selection.size()) {
3779 			presets_menu->set_visible(true);
3780 			anchor_mode_button->set_visible(true);
3781 
3782 			// Disable if the selected node is child of a container
3783 			if (has_container_parents) {
3784 				presets_menu->set_disabled(true);
3785 				presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
3786 				anchor_mode_button->set_disabled(true);
3787 				anchor_mode_button->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
3788 			} else {
3789 				presets_menu->set_disabled(false);
3790 				presets_menu->set_tooltip(TTR("Presets for the anchors and margins values of a Control node."));
3791 				anchor_mode_button->set_disabled(false);
3792 				anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their margins."));
3793 			}
3794 		} else {
3795 			presets_menu->set_visible(false);
3796 			anchor_mode_button->set_visible(false);
3797 		}
3798 
3799 		// Update the viewport if bones changes
3800 		for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
3801 
3802 			Object *b = ObjectDB::get_instance(E->key().from);
3803 			if (!b) {
3804 
3805 				viewport->update();
3806 				break;
3807 			}
3808 
3809 			Node2D *b2 = Object::cast_to<Node2D>(b);
3810 			if (!b2 || !b2->is_inside_tree()) {
3811 				continue;
3812 			}
3813 
3814 			Transform2D global_xform = b2->get_global_transform();
3815 
3816 			if (global_xform != E->get().xform) {
3817 
3818 				E->get().xform = global_xform;
3819 				viewport->update();
3820 			}
3821 
3822 			Bone2D *bone = Object::cast_to<Bone2D>(b);
3823 			if (bone && bone->get_default_length() != E->get().length) {
3824 
3825 				E->get().length = bone->get_default_length();
3826 				viewport->update();
3827 			}
3828 		}
3829 	}
3830 
3831 	if (p_what == NOTIFICATION_ENTER_TREE) {
3832 
3833 		select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
3834 		for (int i = 0; i < 4; i++) {
3835 			select_sb->set_margin_size(Margin(i), 4);
3836 			select_sb->set_default_margin(Margin(i), 4);
3837 		}
3838 
3839 		AnimationPlayerEditor::singleton->get_track_editor()->connect("visibility_changed", this, "_keying_changed");
3840 		_keying_changed();
3841 		get_tree()->connect("node_added", this, "_tree_changed", varray());
3842 		get_tree()->connect("node_removed", this, "_tree_changed", varray());
3843 
3844 	} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
3845 
3846 		select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
3847 	}
3848 
3849 	if (p_what == NOTIFICATION_EXIT_TREE) {
3850 		get_tree()->disconnect("node_added", this, "_tree_changed");
3851 		get_tree()->disconnect("node_removed", this, "_tree_changed");
3852 	}
3853 
3854 	if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
3855 		select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
3856 		list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
3857 		move_button->set_icon(get_icon("ToolMove", "EditorIcons"));
3858 		scale_button->set_icon(get_icon("ToolScale", "EditorIcons"));
3859 		rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons"));
3860 		smart_snap_button->set_icon(get_icon("Snap", "EditorIcons"));
3861 		grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons"));
3862 		snap_config_menu->set_icon(get_icon("GuiTabMenuHl", "EditorIcons"));
3863 		skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
3864 		override_camera_button->set_icon(get_icon("Camera2D", "EditorIcons"));
3865 		pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
3866 		ruler_button->set_icon(get_icon("Ruler", "EditorIcons"));
3867 		pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
3868 		select_handle = get_icon("EditorHandle", "EditorIcons");
3869 		anchor_handle = get_icon("EditorControlAnchor", "EditorIcons");
3870 		lock_button->set_icon(get_icon("Lock", "EditorIcons"));
3871 		unlock_button->set_icon(get_icon("Unlock", "EditorIcons"));
3872 		group_button->set_icon(get_icon("Group", "EditorIcons"));
3873 		ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
3874 		key_loc_button->set_icon(get_icon("KeyPosition", "EditorIcons"));
3875 		key_rot_button->set_icon(get_icon("KeyRotation", "EditorIcons"));
3876 		key_scale_button->set_icon(get_icon("KeyScale", "EditorIcons"));
3877 		key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
3878 		key_auto_insert_button->set_icon(get_icon("AutoKey", "EditorIcons"));
3879 		animation_menu->set_icon(get_icon("GuiTabMenuHl", "EditorIcons"));
3880 
3881 		zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
3882 		zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
3883 
3884 		presets_menu->set_icon(get_icon("ControlLayout", "EditorIcons"));
3885 		PopupMenu *p = presets_menu->get_popup();
3886 
3887 		p->clear();
3888 		p->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_AND_MARGINS_PRESET_TOP_LEFT);
3889 		p->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT);
3890 		p->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT);
3891 		p->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT);
3892 		p->add_separator();
3893 		p->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT);
3894 		p->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_AND_MARGINS_PRESET_CENTER_TOP);
3895 		p->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT);
3896 		p->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM);
3897 		p->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_AND_MARGINS_PRESET_CENTER);
3898 		p->add_separator();
3899 		p->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE);
3900 		p->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_AND_MARGINS_PRESET_TOP_WIDE);
3901 		p->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE);
3902 		p->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE);
3903 		p->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE);
3904 		p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE);
3905 		p->add_separator();
3906 		p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_AND_MARGINS_PRESET_WIDE);
3907 		p->add_icon_item(get_icon("Anchor", "EditorIcons"), TTR("Keep Ratio"), ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO);
3908 		p->add_separator();
3909 		p->add_submenu_item(TTR("Anchors only"), "Anchors");
3910 		p->set_item_icon(21, get_icon("Anchor", "EditorIcons"));
3911 
3912 		anchors_popup->clear();
3913 		anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), TTR("Top Left"), ANCHORS_PRESET_TOP_LEFT);
3914 		anchors_popup->add_icon_item(get_icon("ControlAlignTopRight", "EditorIcons"), TTR("Top Right"), ANCHORS_PRESET_TOP_RIGHT);
3915 		anchors_popup->add_icon_item(get_icon("ControlAlignBottomRight", "EditorIcons"), TTR("Bottom Right"), ANCHORS_PRESET_BOTTOM_RIGHT);
3916 		anchors_popup->add_icon_item(get_icon("ControlAlignBottomLeft", "EditorIcons"), TTR("Bottom Left"), ANCHORS_PRESET_BOTTOM_LEFT);
3917 		anchors_popup->add_separator();
3918 		anchors_popup->add_icon_item(get_icon("ControlAlignLeftCenter", "EditorIcons"), TTR("Center Left"), ANCHORS_PRESET_CENTER_LEFT);
3919 		anchors_popup->add_icon_item(get_icon("ControlAlignTopCenter", "EditorIcons"), TTR("Center Top"), ANCHORS_PRESET_CENTER_TOP);
3920 		anchors_popup->add_icon_item(get_icon("ControlAlignRightCenter", "EditorIcons"), TTR("Center Right"), ANCHORS_PRESET_CENTER_RIGHT);
3921 		anchors_popup->add_icon_item(get_icon("ControlAlignBottomCenter", "EditorIcons"), TTR("Center Bottom"), ANCHORS_PRESET_CENTER_BOTTOM);
3922 		anchors_popup->add_icon_item(get_icon("ControlAlignCenter", "EditorIcons"), TTR("Center"), ANCHORS_PRESET_CENTER);
3923 		anchors_popup->add_separator();
3924 		anchors_popup->add_icon_item(get_icon("ControlAlignLeftWide", "EditorIcons"), TTR("Left Wide"), ANCHORS_PRESET_LEFT_WIDE);
3925 		anchors_popup->add_icon_item(get_icon("ControlAlignTopWide", "EditorIcons"), TTR("Top Wide"), ANCHORS_PRESET_TOP_WIDE);
3926 		anchors_popup->add_icon_item(get_icon("ControlAlignRightWide", "EditorIcons"), TTR("Right Wide"), ANCHORS_PRESET_RIGHT_WIDE);
3927 		anchors_popup->add_icon_item(get_icon("ControlAlignBottomWide", "EditorIcons"), TTR("Bottom Wide"), ANCHORS_PRESET_BOTTOM_WIDE);
3928 		anchors_popup->add_icon_item(get_icon("ControlVcenterWide", "EditorIcons"), TTR("VCenter Wide"), ANCHORS_PRESET_VCENTER_WIDE);
3929 		anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), TTR("HCenter Wide"), ANCHORS_PRESET_HCENTER_WIDE);
3930 		anchors_popup->add_separator();
3931 		anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), TTR("Full Rect"), ANCHORS_PRESET_WIDE);
3932 
3933 		anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons"));
3934 	}
3935 
3936 	if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
3937 		if (!is_visible() && override_camera_button->is_pressed()) {
3938 			ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
3939 
3940 			debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
3941 			override_camera_button->set_pressed(false);
3942 		}
3943 	}
3944 }
3945 
_selection_changed()3946 void CanvasItemEditor::_selection_changed() {
3947 	// Update the anchors_mode
3948 	int nbValidControls = 0;
3949 	int nbAnchorsMode = 0;
3950 	List<Node *> selection = editor_selection->get_selected_node_list();
3951 	for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
3952 		Control *control = Object::cast_to<Control>(E->get());
3953 		if (!control)
3954 			continue;
3955 		if (Object::cast_to<Container>(control->get_parent()))
3956 			continue;
3957 
3958 		nbValidControls++;
3959 		if (control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_")) {
3960 			nbAnchorsMode++;
3961 		}
3962 	}
3963 	anchors_mode = (nbValidControls == nbAnchorsMode);
3964 	anchor_mode_button->set_pressed(anchors_mode);
3965 
3966 	if (!selected_from_canvas) {
3967 		drag_type = DRAG_NONE;
3968 	}
3969 	selected_from_canvas = false;
3970 }
3971 
edit(CanvasItem * p_canvas_item)3972 void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
3973 
3974 	Array selection = editor_selection->get_selected_nodes();
3975 	if (selection.size() != 1 || (Node *)selection[0] != p_canvas_item) {
3976 		drag_type = DRAG_NONE;
3977 
3978 		// Clear the selection
3979 		editor_selection->clear(); //_clear_canvas_items();
3980 		editor_selection->add_node(p_canvas_item);
3981 	}
3982 }
3983 
_queue_update_bone_list()3984 void CanvasItemEditor::_queue_update_bone_list() {
3985 
3986 	if (bone_list_dirty)
3987 		return;
3988 
3989 	call_deferred("_update_bone_list");
3990 	bone_list_dirty = true;
3991 }
3992 
_update_bone_list()3993 void CanvasItemEditor::_update_bone_list() {
3994 
3995 	bone_last_frame++;
3996 
3997 	if (editor->get_edited_scene()) {
3998 		_build_bones_list(editor->get_edited_scene());
3999 	}
4000 
4001 	List<Map<BoneKey, BoneList>::Element *> bone_to_erase;
4002 	for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
4003 		if (E->get().last_pass != bone_last_frame) {
4004 			bone_to_erase.push_back(E);
4005 			continue;
4006 		}
4007 
4008 		Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E->key().from));
4009 		if (!node || !node->is_inside_tree() || (node != get_tree()->get_edited_scene_root() && !get_tree()->get_edited_scene_root()->is_a_parent_of(node))) {
4010 			bone_to_erase.push_back(E);
4011 			continue;
4012 		}
4013 	}
4014 	while (bone_to_erase.size()) {
4015 		bone_list.erase(bone_to_erase.front()->get());
4016 		bone_to_erase.pop_front();
4017 	}
4018 	bone_list_dirty = false;
4019 }
4020 
_tree_changed(Node *)4021 void CanvasItemEditor::_tree_changed(Node *) {
4022 	_queue_update_bone_list();
4023 }
4024 
_update_scrollbars()4025 void CanvasItemEditor::_update_scrollbars() {
4026 
4027 	updating_scroll = true;
4028 
4029 	// Move the zoom buttons.
4030 	Point2 controls_vb_begin = Point2(5, 5);
4031 	controls_vb_begin += (show_rulers) ? Point2(RULER_WIDTH, RULER_WIDTH) : Point2();
4032 	controls_vb->set_begin(controls_vb_begin);
4033 
4034 	Size2 hmin = h_scroll->get_minimum_size();
4035 	Size2 vmin = v_scroll->get_minimum_size();
4036 
4037 	// Get the visible frame.
4038 	Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
4039 	Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
4040 
4041 	_queue_update_bone_list();
4042 
4043 	// Calculate scrollable area.
4044 	Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
4045 	if (editor->get_edited_scene()) {
4046 		Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
4047 		canvas_item_rect.expand_to(content_rect.position);
4048 		canvas_item_rect.expand_to(content_rect.position + content_rect.size);
4049 	}
4050 	canvas_item_rect.size += screen_rect * 2;
4051 	canvas_item_rect.position -= screen_rect;
4052 
4053 	// Constraints the view offset and updates the scrollbars.
4054 	Size2 size = viewport->get_size();
4055 	Point2 begin = canvas_item_rect.position;
4056 	Point2 end = canvas_item_rect.position + canvas_item_rect.size - local_rect.size / zoom;
4057 	bool constrain_editor_view = bool(EditorSettings::get_singleton()->get("editors/2d/constrain_editor_view"));
4058 
4059 	if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) {
4060 		float centered = -(size.y / 2) / zoom + screen_rect.y / 2;
4061 		if (constrain_editor_view && ABS(centered - previous_update_view_offset.y) < ABS(centered - view_offset.y)) {
4062 			view_offset.y = previous_update_view_offset.y;
4063 		}
4064 
4065 		v_scroll->hide();
4066 	} else {
4067 		if (constrain_editor_view && view_offset.y > end.y && view_offset.y > previous_update_view_offset.y) {
4068 			view_offset.y = MAX(end.y, previous_update_view_offset.y);
4069 		}
4070 		if (constrain_editor_view && view_offset.y < begin.y && view_offset.y < previous_update_view_offset.y) {
4071 			view_offset.y = MIN(begin.y, previous_update_view_offset.y);
4072 		}
4073 
4074 		v_scroll->show();
4075 		v_scroll->set_min(MIN(view_offset.y, begin.y));
4076 		v_scroll->set_max(MAX(view_offset.y, end.y) + screen_rect.y);
4077 		v_scroll->set_page(screen_rect.y);
4078 	}
4079 
4080 	if (canvas_item_rect.size.width <= (local_rect.size.x / zoom)) {
4081 		float centered = -(size.x / 2) / zoom + screen_rect.x / 2;
4082 		if (constrain_editor_view && ABS(centered - previous_update_view_offset.x) < ABS(centered - view_offset.x)) {
4083 			view_offset.x = previous_update_view_offset.x;
4084 		}
4085 
4086 		h_scroll->hide();
4087 	} else {
4088 		if (constrain_editor_view && view_offset.x > end.x && view_offset.x > previous_update_view_offset.x) {
4089 			view_offset.x = MAX(end.x, previous_update_view_offset.x);
4090 		}
4091 		if (constrain_editor_view && view_offset.x < begin.x && view_offset.x < previous_update_view_offset.x) {
4092 			view_offset.x = MIN(begin.x, previous_update_view_offset.x);
4093 		}
4094 
4095 		h_scroll->show();
4096 		h_scroll->set_min(MIN(view_offset.x, begin.x));
4097 		h_scroll->set_max(MAX(view_offset.x, end.x) + screen_rect.x);
4098 		h_scroll->set_page(screen_rect.x);
4099 	}
4100 
4101 	// Move and resize the scrollbars, avoiding overlap.
4102 	v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
4103 	v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
4104 	h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
4105 	h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height));
4106 
4107 	// Calculate scrollable area.
4108 	v_scroll->set_value(view_offset.y);
4109 	h_scroll->set_value(view_offset.x);
4110 
4111 	previous_update_view_offset = view_offset;
4112 	updating_scroll = false;
4113 }
4114 
_popup_warning_depop(Control * p_control)4115 void CanvasItemEditor::_popup_warning_depop(Control *p_control) {
4116 	ERR_FAIL_COND(!popup_temporarily_timers.has(p_control));
4117 
4118 	Timer *timer = popup_temporarily_timers[p_control];
4119 	timer->queue_delete();
4120 	p_control->hide();
4121 	popup_temporarily_timers.erase(p_control);
4122 	info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
4123 }
4124 
_popup_warning_temporarily(Control * p_control,const float p_duration)4125 void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) {
4126 	Timer *timer;
4127 	if (!popup_temporarily_timers.has(p_control)) {
4128 		timer = memnew(Timer);
4129 		timer->connect("timeout", this, "_popup_warning_depop", varray(p_control));
4130 		timer->set_one_shot(true);
4131 		add_child(timer);
4132 
4133 		popup_temporarily_timers[p_control] = timer;
4134 	} else {
4135 		timer = popup_temporarily_timers[p_control];
4136 	}
4137 
4138 	timer->start(p_duration);
4139 	p_control->show();
4140 	info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
4141 }
4142 
_update_scroll(float)4143 void CanvasItemEditor::_update_scroll(float) {
4144 
4145 	if (updating_scroll)
4146 		return;
4147 
4148 	view_offset.x = h_scroll->get_value();
4149 	view_offset.y = v_scroll->get_value();
4150 	viewport->update();
4151 }
4152 
_set_anchors_and_margins_preset(Control::LayoutPreset p_preset)4153 void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_preset) {
4154 	List<Node *> selection = editor_selection->get_selected_node_list();
4155 
4156 	undo_redo->create_action(TTR("Change Anchors and Margins"));
4157 
4158 	for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4159 
4160 		Control *control = Object::cast_to<Control>(E->get());
4161 		if (control) {
4162 			undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
4163 			switch (p_preset) {
4164 				case PRESET_TOP_LEFT:
4165 				case PRESET_TOP_RIGHT:
4166 				case PRESET_BOTTOM_LEFT:
4167 				case PRESET_BOTTOM_RIGHT:
4168 				case PRESET_CENTER_LEFT:
4169 				case PRESET_CENTER_TOP:
4170 				case PRESET_CENTER_RIGHT:
4171 				case PRESET_CENTER_BOTTOM:
4172 				case PRESET_CENTER:
4173 					undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_KEEP_SIZE);
4174 					break;
4175 				case PRESET_LEFT_WIDE:
4176 				case PRESET_TOP_WIDE:
4177 				case PRESET_RIGHT_WIDE:
4178 				case PRESET_BOTTOM_WIDE:
4179 				case PRESET_VCENTER_WIDE:
4180 				case PRESET_HCENTER_WIDE:
4181 				case PRESET_WIDE:
4182 					undo_redo->add_do_method(control, "set_margins_preset", p_preset, Control::PRESET_MODE_MINSIZE);
4183 					break;
4184 			}
4185 			undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
4186 		}
4187 	}
4188 
4189 	undo_redo->commit_action();
4190 
4191 	anchors_mode = false;
4192 	anchor_mode_button->set_pressed(anchors_mode);
4193 }
4194 
_set_anchors_and_margins_to_keep_ratio()4195 void CanvasItemEditor::_set_anchors_and_margins_to_keep_ratio() {
4196 	List<Node *> selection = editor_selection->get_selected_node_list();
4197 
4198 	undo_redo->create_action(TTR("Change Anchors and Margins"));
4199 
4200 	for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4201 
4202 		Control *control = Object::cast_to<Control>(E->get());
4203 		if (control) {
4204 			Point2 top_left_anchor = _position_to_anchor(control, Point2());
4205 			Point2 bottom_right_anchor = _position_to_anchor(control, control->get_size());
4206 			undo_redo->add_do_method(control, "set_anchor", MARGIN_LEFT, top_left_anchor.x, false, true);
4207 			undo_redo->add_do_method(control, "set_anchor", MARGIN_RIGHT, bottom_right_anchor.x, false, true);
4208 			undo_redo->add_do_method(control, "set_anchor", MARGIN_TOP, top_left_anchor.y, false, true);
4209 			undo_redo->add_do_method(control, "set_anchor", MARGIN_BOTTOM, bottom_right_anchor.y, false, true);
4210 			undo_redo->add_do_method(control, "set_meta", "_edit_use_anchors_", true);
4211 
4212 			bool use_anchors = control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_");
4213 			undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
4214 			undo_redo->add_undo_method(control, "set_meta", "_edit_use_anchors_", use_anchors);
4215 
4216 			anchors_mode = true;
4217 			anchor_mode_button->set_pressed(anchors_mode);
4218 		}
4219 	}
4220 
4221 	undo_redo->commit_action();
4222 }
4223 
_set_anchors_preset(Control::LayoutPreset p_preset)4224 void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
4225 	List<Node *> selection = editor_selection->get_selected_node_list();
4226 
4227 	undo_redo->create_action(TTR("Change Anchors"));
4228 	for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4229 
4230 		Control *control = Object::cast_to<Control>(E->get());
4231 		if (control) {
4232 			undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
4233 			undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
4234 		}
4235 	}
4236 
4237 	undo_redo->commit_action();
4238 }
4239 
_get_next_zoom_value(int p_increment_count) const4240 float CanvasItemEditor::_get_next_zoom_value(int p_increment_count) const {
4241 	// Base increment factor defined as the twelveth root of two.
4242 	// This allow a smooth geometric evolution of the zoom, with the advantage of
4243 	// visiting all integer power of two scale factors.
4244 	// note: this is analogous to the 'semitones' interval in the music world
4245 	// In order to avoid numerical imprecisions, we compute and edit a zoom index
4246 	// with the following relation: zoom = 2 ^ (index / 12)
4247 
4248 	if (zoom < CMP_EPSILON || p_increment_count == 0) {
4249 		return 1.f;
4250 	}
4251 
4252 	// Remove Editor scale from the index computation
4253 	float zoom_noscale = zoom / MAX(1, EDSCALE);
4254 
4255 	// zoom = 2**(index/12) => log2(zoom) = index/12
4256 	float closest_zoom_index = Math::round(Math::log(zoom_noscale) * 12.f / Math::log(2.f));
4257 
4258 	float new_zoom_index = closest_zoom_index + p_increment_count;
4259 	float new_zoom = Math::pow(2.f, new_zoom_index / 12.f);
4260 
4261 	// Restore Editor scale transformation
4262 	new_zoom *= MAX(1, EDSCALE);
4263 
4264 	return new_zoom;
4265 }
4266 
_zoom_on_position(float p_zoom,Point2 p_position)4267 void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
4268 	p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM);
4269 
4270 	if (p_zoom == zoom)
4271 		return;
4272 
4273 	float prev_zoom = zoom;
4274 	zoom = p_zoom;
4275 
4276 	view_offset += p_position / prev_zoom - p_position / zoom;
4277 
4278 	// We want to align in-scene pixels to screen pixels, this prevents blurry rendering
4279 	// in small details (texts, lines).
4280 	// This correction adds a jitter movement when zooming, so we correct only when the
4281 	// zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway)
4282 	float closest_zoom_factor = Math::round(zoom);
4283 	if (Math::is_zero_approx(zoom - closest_zoom_factor)) {
4284 		// make sure scene pixel at view_offset is aligned on a screen pixel
4285 		Vector2 view_offset_int = view_offset.floor();
4286 		Vector2 view_offset_frac = view_offset - view_offset_int;
4287 		view_offset = view_offset_int + (view_offset_frac * closest_zoom_factor).round() / closest_zoom_factor;
4288 	}
4289 
4290 	_update_zoom_label();
4291 	update_viewport();
4292 }
4293 
_update_zoom_label()4294 void CanvasItemEditor::_update_zoom_label() {
4295 	String zoom_text;
4296 	// The zoom level displayed is relative to the editor scale
4297 	// (like in most image editors). Its lower bound is clamped to 1 as some people
4298 	// lower the editor scale to increase the available real estate,
4299 	// even if their display doesn't have a particularly low DPI.
4300 	if (zoom >= 10) {
4301 		// Don't show a decimal when the zoom level is higher than 1000 %.
4302 		zoom_text = rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)) + " %";
4303 	} else {
4304 		zoom_text = rtos(Math::stepify((zoom / MAX(1, EDSCALE)) * 100, 0.1)) + " %";
4305 	}
4306 
4307 	zoom_reset->set_text(zoom_text);
4308 }
4309 
_button_zoom_minus()4310 void CanvasItemEditor::_button_zoom_minus() {
4311 	_zoom_on_position(_get_next_zoom_value(-6), viewport_scrollable->get_size() / 2.0);
4312 }
4313 
_button_zoom_reset()4314 void CanvasItemEditor::_button_zoom_reset() {
4315 	_zoom_on_position(1.0 * MAX(1, EDSCALE), viewport_scrollable->get_size() / 2.0);
4316 }
4317 
_button_zoom_plus()4318 void CanvasItemEditor::_button_zoom_plus() {
4319 	_zoom_on_position(_get_next_zoom_value(6), viewport_scrollable->get_size() / 2.0);
4320 }
4321 
_button_toggle_smart_snap(bool p_status)4322 void CanvasItemEditor::_button_toggle_smart_snap(bool p_status) {
4323 	smart_snap_active = p_status;
4324 	viewport->update();
4325 }
4326 
_button_toggle_grid_snap(bool p_status)4327 void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) {
4328 	grid_snap_active = p_status;
4329 	viewport->update();
4330 }
_button_override_camera(bool p_pressed)4331 void CanvasItemEditor::_button_override_camera(bool p_pressed) {
4332 	ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger();
4333 
4334 	if (p_pressed) {
4335 		debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_2D);
4336 	} else {
4337 		debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE);
4338 	}
4339 }
4340 
_button_tool_select(int p_index)4341 void CanvasItemEditor::_button_tool_select(int p_index) {
4342 
4343 	ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button };
4344 	for (int i = 0; i < TOOL_MAX; i++) {
4345 		tb[i]->set_pressed(i == p_index);
4346 	}
4347 
4348 	tool = (Tool)p_index;
4349 	viewport->update();
4350 }
4351 
_insert_animation_keys(bool p_location,bool p_rotation,bool p_scale,bool p_on_existing)4352 void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, bool p_scale, bool p_on_existing) {
4353 
4354 	Map<Node *, Object *> &selection = editor_selection->get_selection();
4355 
4356 	for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4357 
4358 		CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
4359 		if (!canvas_item || !canvas_item->is_visible_in_tree())
4360 			continue;
4361 
4362 		if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4363 			continue;
4364 
4365 		if (Object::cast_to<Node2D>(canvas_item)) {
4366 			Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
4367 
4368 			if (key_pos && p_location)
4369 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "position", n2d->get_position(), p_on_existing);
4370 			if (key_rot && p_rotation)
4371 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "rotation_degrees", Math::rad2deg(n2d->get_rotation()), p_on_existing);
4372 			if (key_scale && p_scale)
4373 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(n2d, "scale", n2d->get_scale(), p_on_existing);
4374 
4375 			if (n2d->has_meta("_edit_bone_") && n2d->get_parent_item()) {
4376 				//look for an IK chain
4377 				List<Node2D *> ik_chain;
4378 
4379 				Node2D *n = Object::cast_to<Node2D>(n2d->get_parent_item());
4380 				bool has_chain = false;
4381 
4382 				while (n) {
4383 
4384 					ik_chain.push_back(n);
4385 					if (n->has_meta("_edit_ik_")) {
4386 						has_chain = true;
4387 						break;
4388 					}
4389 
4390 					if (!n->get_parent_item())
4391 						break;
4392 					n = Object::cast_to<Node2D>(n->get_parent_item());
4393 				}
4394 
4395 				if (has_chain && ik_chain.size()) {
4396 
4397 					for (List<Node2D *>::Element *F = ik_chain.front(); F; F = F->next()) {
4398 
4399 						if (key_pos)
4400 							AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), p_on_existing);
4401 						if (key_rot)
4402 							AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation_degrees", Math::rad2deg(F->get()->get_rotation()), p_on_existing);
4403 						if (key_scale)
4404 							AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), p_on_existing);
4405 					}
4406 				}
4407 			}
4408 
4409 		} else if (Object::cast_to<Control>(canvas_item)) {
4410 
4411 			Control *ctrl = Object::cast_to<Control>(canvas_item);
4412 
4413 			if (key_pos)
4414 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
4415 			if (key_rot)
4416 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation_degrees(), p_on_existing);
4417 			if (key_scale)
4418 				AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
4419 		}
4420 	}
4421 }
4422 
_button_toggle_anchor_mode(bool p_status)4423 void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
4424 	List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
4425 	for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
4426 		Control *control = Object::cast_to<Control>(E->get());
4427 		if (!control || Object::cast_to<Container>(control->get_parent()))
4428 			continue;
4429 
4430 		control->set_meta("_edit_use_anchors_", p_status);
4431 	}
4432 
4433 	anchors_mode = p_status;
4434 	viewport->update();
4435 }
4436 
_update_override_camera_button(bool p_game_running)4437 void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
4438 	if (p_game_running) {
4439 		override_camera_button->set_disabled(false);
4440 		override_camera_button->set_tooltip(TTR("Game Camera Override\nOverrides game camera with editor viewport camera."));
4441 	} else {
4442 		override_camera_button->set_disabled(true);
4443 		override_camera_button->set_pressed(false);
4444 		override_camera_button->set_tooltip(TTR("Game Camera Override\nNo game instance running."));
4445 	}
4446 }
4447 
_popup_callback(int p_op)4448 void CanvasItemEditor::_popup_callback(int p_op) {
4449 
4450 	last_option = MenuOption(p_op);
4451 	switch (p_op) {
4452 
4453 		case SHOW_GRID: {
4454 			show_grid = !show_grid;
4455 			int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
4456 			view_menu->get_popup()->set_item_checked(idx, show_grid);
4457 			viewport->update();
4458 		} break;
4459 		case SHOW_ORIGIN: {
4460 			show_origin = !show_origin;
4461 			int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN);
4462 			view_menu->get_popup()->set_item_checked(idx, show_origin);
4463 			viewport->update();
4464 		} break;
4465 		case SHOW_VIEWPORT: {
4466 			show_viewport = !show_viewport;
4467 			int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT);
4468 			view_menu->get_popup()->set_item_checked(idx, show_viewport);
4469 			viewport->update();
4470 		} break;
4471 		case SHOW_EDIT_LOCKS: {
4472 			show_edit_locks = !show_edit_locks;
4473 			int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
4474 			view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
4475 			viewport->update();
4476 		} break;
4477 		case SNAP_USE_NODE_PARENT: {
4478 			snap_node_parent = !snap_node_parent;
4479 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
4480 			smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
4481 		} break;
4482 		case SNAP_USE_NODE_ANCHORS: {
4483 			snap_node_anchors = !snap_node_anchors;
4484 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
4485 			smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
4486 		} break;
4487 		case SNAP_USE_NODE_SIDES: {
4488 			snap_node_sides = !snap_node_sides;
4489 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
4490 			smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
4491 		} break;
4492 		case SNAP_USE_NODE_CENTER: {
4493 			snap_node_center = !snap_node_center;
4494 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
4495 			smartsnap_config_popup->set_item_checked(idx, snap_node_center);
4496 		} break;
4497 		case SNAP_USE_OTHER_NODES: {
4498 			snap_other_nodes = !snap_other_nodes;
4499 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
4500 			smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
4501 		} break;
4502 		case SNAP_USE_GUIDES: {
4503 			snap_guides = !snap_guides;
4504 			int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
4505 			smartsnap_config_popup->set_item_checked(idx, snap_guides);
4506 		} break;
4507 		case SNAP_USE_ROTATION: {
4508 			snap_rotation = !snap_rotation;
4509 			int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
4510 			snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
4511 		} break;
4512 		case SNAP_USE_SCALE: {
4513 			snap_scale = !snap_scale;
4514 			int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_SCALE);
4515 			snap_config_menu->get_popup()->set_item_checked(idx, snap_scale);
4516 		} break;
4517 		case SNAP_RELATIVE: {
4518 			snap_relative = !snap_relative;
4519 			int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
4520 			snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
4521 			viewport->update();
4522 		} break;
4523 		case SNAP_USE_PIXEL: {
4524 			snap_pixel = !snap_pixel;
4525 			int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
4526 			snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
4527 		} break;
4528 		case SNAP_CONFIGURE: {
4529 			((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, primary_grid_steps, snap_rotation_offset, snap_rotation_step, snap_scale_step);
4530 			snap_dialog->popup_centered(Size2(220, 160) * EDSCALE);
4531 		} break;
4532 		case SKELETON_SHOW_BONES: {
4533 			skeleton_show_bones = !skeleton_show_bones;
4534 			int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
4535 			skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
4536 			viewport->update();
4537 		} break;
4538 		case SHOW_HELPERS: {
4539 			show_helpers = !show_helpers;
4540 			int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
4541 			view_menu->get_popup()->set_item_checked(idx, show_helpers);
4542 			viewport->update();
4543 		} break;
4544 		case SHOW_RULERS: {
4545 			show_rulers = !show_rulers;
4546 			int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
4547 			view_menu->get_popup()->set_item_checked(idx, show_rulers);
4548 			_update_scrollbars();
4549 			viewport->update();
4550 		} break;
4551 		case SHOW_GUIDES: {
4552 			show_guides = !show_guides;
4553 			int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
4554 			view_menu->get_popup()->set_item_checked(idx, show_guides);
4555 			viewport->update();
4556 		} break;
4557 		case LOCK_SELECTED: {
4558 			undo_redo->create_action(TTR("Lock Selected"));
4559 
4560 			List<Node *> selection = editor_selection->get_selected_node_list();
4561 			for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4562 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
4563 				if (!canvas_item || !canvas_item->is_inside_tree())
4564 					continue;
4565 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4566 					continue;
4567 
4568 				undo_redo->add_do_method(canvas_item, "set_meta", "_edit_lock_", true);
4569 				undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_lock_");
4570 				undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed");
4571 				undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed");
4572 			}
4573 			undo_redo->add_do_method(viewport, "update", Variant());
4574 			undo_redo->add_undo_method(viewport, "update", Variant());
4575 			undo_redo->commit_action();
4576 		} break;
4577 		case UNLOCK_SELECTED: {
4578 			undo_redo->create_action(TTR("Unlock Selected"));
4579 
4580 			List<Node *> selection = editor_selection->get_selected_node_list();
4581 			for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4582 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
4583 				if (!canvas_item || !canvas_item->is_inside_tree())
4584 					continue;
4585 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4586 					continue;
4587 
4588 				undo_redo->add_do_method(canvas_item, "remove_meta", "_edit_lock_");
4589 				undo_redo->add_undo_method(canvas_item, "set_meta", "_edit_lock_", true);
4590 				undo_redo->add_do_method(this, "emit_signal", "item_lock_status_changed");
4591 				undo_redo->add_undo_method(this, "emit_signal", "item_lock_status_changed");
4592 			}
4593 			undo_redo->add_do_method(viewport, "update", Variant());
4594 			undo_redo->add_undo_method(viewport, "update", Variant());
4595 			undo_redo->commit_action();
4596 		} break;
4597 		case GROUP_SELECTED: {
4598 			undo_redo->create_action(TTR("Group Selected"));
4599 
4600 			List<Node *> selection = editor_selection->get_selected_node_list();
4601 			for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4602 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
4603 				if (!canvas_item || !canvas_item->is_inside_tree())
4604 					continue;
4605 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4606 					continue;
4607 
4608 				undo_redo->add_do_method(canvas_item, "set_meta", "_edit_group_", true);
4609 				undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_group_");
4610 				undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed");
4611 				undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed");
4612 			}
4613 			undo_redo->add_do_method(viewport, "update", Variant());
4614 			undo_redo->add_undo_method(viewport, "update", Variant());
4615 			undo_redo->commit_action();
4616 		} break;
4617 		case UNGROUP_SELECTED: {
4618 			undo_redo->create_action(TTR("Ungroup Selected"));
4619 
4620 			List<Node *> selection = editor_selection->get_selected_node_list();
4621 			for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4622 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
4623 				if (!canvas_item || !canvas_item->is_inside_tree())
4624 					continue;
4625 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4626 					continue;
4627 
4628 				undo_redo->add_do_method(canvas_item, "remove_meta", "_edit_group_");
4629 				undo_redo->add_undo_method(canvas_item, "set_meta", "_edit_group_", true);
4630 				undo_redo->add_do_method(this, "emit_signal", "item_group_status_changed");
4631 				undo_redo->add_undo_method(this, "emit_signal", "item_group_status_changed");
4632 			}
4633 			undo_redo->add_do_method(viewport, "update", Variant());
4634 			undo_redo->add_undo_method(viewport, "update", Variant());
4635 			undo_redo->commit_action();
4636 		} break;
4637 		case ANCHORS_AND_MARGINS_PRESET_TOP_LEFT: {
4638 			_set_anchors_and_margins_preset(PRESET_TOP_LEFT);
4639 		} break;
4640 		case ANCHORS_AND_MARGINS_PRESET_TOP_RIGHT: {
4641 			_set_anchors_and_margins_preset(PRESET_TOP_RIGHT);
4642 		} break;
4643 		case ANCHORS_AND_MARGINS_PRESET_BOTTOM_LEFT: {
4644 			_set_anchors_and_margins_preset(PRESET_BOTTOM_LEFT);
4645 		} break;
4646 		case ANCHORS_AND_MARGINS_PRESET_BOTTOM_RIGHT: {
4647 			_set_anchors_and_margins_preset(PRESET_BOTTOM_RIGHT);
4648 		} break;
4649 		case ANCHORS_AND_MARGINS_PRESET_CENTER_LEFT: {
4650 			_set_anchors_and_margins_preset(PRESET_CENTER_LEFT);
4651 		} break;
4652 		case ANCHORS_AND_MARGINS_PRESET_CENTER_RIGHT: {
4653 			_set_anchors_and_margins_preset(PRESET_CENTER_RIGHT);
4654 		} break;
4655 		case ANCHORS_AND_MARGINS_PRESET_CENTER_TOP: {
4656 			_set_anchors_and_margins_preset(PRESET_CENTER_TOP);
4657 		} break;
4658 		case ANCHORS_AND_MARGINS_PRESET_CENTER_BOTTOM: {
4659 			_set_anchors_and_margins_preset(PRESET_CENTER_BOTTOM);
4660 		} break;
4661 		case ANCHORS_AND_MARGINS_PRESET_CENTER: {
4662 			_set_anchors_and_margins_preset(PRESET_CENTER);
4663 		} break;
4664 		case ANCHORS_AND_MARGINS_PRESET_TOP_WIDE: {
4665 			_set_anchors_and_margins_preset(PRESET_TOP_WIDE);
4666 		} break;
4667 		case ANCHORS_AND_MARGINS_PRESET_LEFT_WIDE: {
4668 			_set_anchors_and_margins_preset(PRESET_LEFT_WIDE);
4669 		} break;
4670 		case ANCHORS_AND_MARGINS_PRESET_RIGHT_WIDE: {
4671 			_set_anchors_and_margins_preset(PRESET_RIGHT_WIDE);
4672 		} break;
4673 		case ANCHORS_AND_MARGINS_PRESET_BOTTOM_WIDE: {
4674 			_set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE);
4675 		} break;
4676 		case ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE: {
4677 			_set_anchors_and_margins_preset(PRESET_VCENTER_WIDE);
4678 		} break;
4679 		case ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE: {
4680 			_set_anchors_and_margins_preset(PRESET_HCENTER_WIDE);
4681 		} break;
4682 		case ANCHORS_AND_MARGINS_PRESET_WIDE: {
4683 			_set_anchors_and_margins_preset(Control::PRESET_WIDE);
4684 		} break;
4685 		case ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO: {
4686 			_set_anchors_and_margins_to_keep_ratio();
4687 		} break;
4688 
4689 		case ANCHORS_PRESET_TOP_LEFT: {
4690 			_set_anchors_preset(PRESET_TOP_LEFT);
4691 		} break;
4692 		case ANCHORS_PRESET_TOP_RIGHT: {
4693 			_set_anchors_preset(PRESET_TOP_RIGHT);
4694 		} break;
4695 		case ANCHORS_PRESET_BOTTOM_LEFT: {
4696 			_set_anchors_preset(PRESET_BOTTOM_LEFT);
4697 		} break;
4698 		case ANCHORS_PRESET_BOTTOM_RIGHT: {
4699 			_set_anchors_preset(PRESET_BOTTOM_RIGHT);
4700 		} break;
4701 		case ANCHORS_PRESET_CENTER_LEFT: {
4702 			_set_anchors_preset(PRESET_CENTER_LEFT);
4703 		} break;
4704 		case ANCHORS_PRESET_CENTER_RIGHT: {
4705 			_set_anchors_preset(PRESET_CENTER_RIGHT);
4706 		} break;
4707 		case ANCHORS_PRESET_CENTER_TOP: {
4708 			_set_anchors_preset(PRESET_CENTER_TOP);
4709 		} break;
4710 		case ANCHORS_PRESET_CENTER_BOTTOM: {
4711 			_set_anchors_preset(PRESET_CENTER_BOTTOM);
4712 		} break;
4713 		case ANCHORS_PRESET_CENTER: {
4714 			_set_anchors_preset(PRESET_CENTER);
4715 		} break;
4716 		case ANCHORS_PRESET_TOP_WIDE: {
4717 			_set_anchors_preset(PRESET_TOP_WIDE);
4718 		} break;
4719 		case ANCHORS_PRESET_LEFT_WIDE: {
4720 			_set_anchors_preset(PRESET_LEFT_WIDE);
4721 		} break;
4722 		case ANCHORS_PRESET_RIGHT_WIDE: {
4723 			_set_anchors_preset(PRESET_RIGHT_WIDE);
4724 		} break;
4725 		case ANCHORS_PRESET_BOTTOM_WIDE: {
4726 			_set_anchors_preset(PRESET_BOTTOM_WIDE);
4727 		} break;
4728 		case ANCHORS_PRESET_VCENTER_WIDE: {
4729 			_set_anchors_preset(PRESET_VCENTER_WIDE);
4730 		} break;
4731 		case ANCHORS_PRESET_HCENTER_WIDE: {
4732 			_set_anchors_preset(PRESET_HCENTER_WIDE);
4733 		} break;
4734 		case ANCHORS_PRESET_WIDE: {
4735 			_set_anchors_preset(Control::PRESET_WIDE);
4736 		} break;
4737 
4738 		case ANIM_INSERT_KEY:
4739 		case ANIM_INSERT_KEY_EXISTING: {
4740 
4741 			bool existing = p_op == ANIM_INSERT_KEY_EXISTING;
4742 
4743 			_insert_animation_keys(true, true, true, existing);
4744 
4745 		} break;
4746 		case ANIM_INSERT_POS: {
4747 
4748 			key_pos = key_loc_button->is_pressed();
4749 		} break;
4750 		case ANIM_INSERT_ROT: {
4751 
4752 			key_rot = key_rot_button->is_pressed();
4753 		} break;
4754 		case ANIM_INSERT_SCALE: {
4755 
4756 			key_scale = key_scale_button->is_pressed();
4757 		} break;
4758 		case ANIM_COPY_POSE: {
4759 
4760 			pose_clipboard.clear();
4761 
4762 			Map<Node *, Object *> &selection = editor_selection->get_selection();
4763 
4764 			for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4765 
4766 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
4767 				if (!canvas_item || !canvas_item->is_visible_in_tree())
4768 					continue;
4769 
4770 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4771 					continue;
4772 
4773 				if (Object::cast_to<Node2D>(canvas_item)) {
4774 
4775 					Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
4776 					PoseClipboard pc;
4777 					pc.pos = n2d->get_position();
4778 					pc.rot = n2d->get_rotation();
4779 					pc.scale = n2d->get_scale();
4780 					pc.id = n2d->get_instance_id();
4781 					pose_clipboard.push_back(pc);
4782 				}
4783 			}
4784 
4785 		} break;
4786 		case ANIM_PASTE_POSE: {
4787 
4788 			if (!pose_clipboard.size())
4789 				break;
4790 
4791 			undo_redo->create_action(TTR("Paste Pose"));
4792 			for (List<PoseClipboard>::Element *E = pose_clipboard.front(); E; E = E->next()) {
4793 
4794 				Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->get().id));
4795 				if (!n2d)
4796 					continue;
4797 				undo_redo->add_do_method(n2d, "set_position", E->get().pos);
4798 				undo_redo->add_do_method(n2d, "set_rotation", E->get().rot);
4799 				undo_redo->add_do_method(n2d, "set_scale", E->get().scale);
4800 				undo_redo->add_undo_method(n2d, "set_position", n2d->get_position());
4801 				undo_redo->add_undo_method(n2d, "set_rotation", n2d->get_rotation());
4802 				undo_redo->add_undo_method(n2d, "set_scale", n2d->get_scale());
4803 			}
4804 			undo_redo->commit_action();
4805 
4806 		} break;
4807 		case ANIM_CLEAR_POSE: {
4808 
4809 			Map<Node *, Object *> &selection = editor_selection->get_selection();
4810 
4811 			for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4812 
4813 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
4814 				if (!canvas_item || !canvas_item->is_visible_in_tree())
4815 					continue;
4816 
4817 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4818 					continue;
4819 
4820 				if (Object::cast_to<Node2D>(canvas_item)) {
4821 					Node2D *n2d = Object::cast_to<Node2D>(canvas_item);
4822 
4823 					if (key_pos)
4824 						n2d->set_position(Vector2());
4825 					if (key_rot)
4826 						n2d->set_rotation(0);
4827 					if (key_scale)
4828 						n2d->set_scale(Vector2(1, 1));
4829 				} else if (Object::cast_to<Control>(canvas_item)) {
4830 
4831 					Control *ctrl = Object::cast_to<Control>(canvas_item);
4832 
4833 					if (key_pos)
4834 						ctrl->set_position(Point2());
4835 					/*
4836                                    if (key_scale)
4837 				   AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
4838                                    */
4839 				}
4840 			}
4841 
4842 		} break;
4843 		case CLEAR_GUIDES: {
4844 
4845 			Node *const root = EditorNode::get_singleton()->get_edited_scene();
4846 
4847 			if (root && (root->has_meta("_edit_horizontal_guides_") || root->has_meta("_edit_vertical_guides_"))) {
4848 				undo_redo->create_action(TTR("Clear Guides"));
4849 				if (root->has_meta("_edit_horizontal_guides_")) {
4850 					Array hguides = root->get_meta("_edit_horizontal_guides_");
4851 
4852 					undo_redo->add_do_method(root, "remove_meta", "_edit_horizontal_guides_");
4853 					undo_redo->add_undo_method(root, "set_meta", "_edit_horizontal_guides_", hguides);
4854 				}
4855 				if (root->has_meta("_edit_vertical_guides_")) {
4856 					Array vguides = root->get_meta("_edit_vertical_guides_");
4857 
4858 					undo_redo->add_do_method(root, "remove_meta", "_edit_vertical_guides_");
4859 					undo_redo->add_undo_method(root, "set_meta", "_edit_vertical_guides_", vguides);
4860 				}
4861 				undo_redo->add_undo_method(viewport, "update");
4862 				undo_redo->commit_action();
4863 			}
4864 
4865 		} break;
4866 		case VIEW_CENTER_TO_SELECTION:
4867 		case VIEW_FRAME_TO_SELECTION: {
4868 
4869 			_focus_selection(p_op);
4870 
4871 		} break;
4872 		case PREVIEW_CANVAS_SCALE: {
4873 
4874 			bool preview = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE));
4875 			preview = !preview;
4876 			VS::get_singleton()->canvas_set_disable_scale(!preview);
4877 			view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE), preview);
4878 
4879 		} break;
4880 		case SKELETON_MAKE_BONES: {
4881 
4882 			Map<Node *, Object *> &selection = editor_selection->get_selection();
4883 
4884 			undo_redo->create_action(TTR("Create Custom Bone(s) from Node(s)"));
4885 			for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4886 
4887 				Node2D *n2d = Object::cast_to<Node2D>(E->key());
4888 				if (!n2d)
4889 					continue;
4890 				if (!n2d->is_visible_in_tree())
4891 					continue;
4892 				if (!n2d->get_parent_item())
4893 					continue;
4894 				if (n2d->has_meta("_edit_bone_") && n2d->get_meta("_edit_bone_"))
4895 					continue;
4896 
4897 				undo_redo->add_do_method(n2d, "set_meta", "_edit_bone_", true);
4898 				undo_redo->add_undo_method(n2d, "remove_meta", "_edit_bone_");
4899 			}
4900 			undo_redo->add_do_method(this, "_queue_update_bone_list");
4901 			undo_redo->add_undo_method(this, "_queue_update_bone_list");
4902 			undo_redo->add_do_method(viewport, "update");
4903 			undo_redo->add_undo_method(viewport, "update");
4904 			undo_redo->commit_action();
4905 
4906 		} break;
4907 		case SKELETON_CLEAR_BONES: {
4908 
4909 			Map<Node *, Object *> &selection = editor_selection->get_selection();
4910 
4911 			undo_redo->create_action(TTR("Clear Bones"));
4912 			for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4913 
4914 				Node2D *n2d = Object::cast_to<Node2D>(E->key());
4915 				if (!n2d)
4916 					continue;
4917 				if (!n2d->is_visible_in_tree())
4918 					continue;
4919 				if (!n2d->has_meta("_edit_bone_"))
4920 					continue;
4921 
4922 				undo_redo->add_do_method(n2d, "remove_meta", "_edit_bone_");
4923 				undo_redo->add_undo_method(n2d, "set_meta", "_edit_bone_", n2d->get_meta("_edit_bone_"));
4924 			}
4925 			undo_redo->add_do_method(this, "_queue_update_bone_list");
4926 			undo_redo->add_undo_method(this, "_queue_update_bone_list");
4927 			undo_redo->add_do_method(viewport, "update");
4928 			undo_redo->add_undo_method(viewport, "update");
4929 			undo_redo->commit_action();
4930 
4931 		} break;
4932 		case SKELETON_SET_IK_CHAIN: {
4933 
4934 			List<Node *> selection = editor_selection->get_selected_node_list();
4935 
4936 			undo_redo->create_action(TTR("Make IK Chain"));
4937 			for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
4938 
4939 				CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
4940 				if (!canvas_item || !canvas_item->is_visible_in_tree())
4941 					continue;
4942 				if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4943 					continue;
4944 				if (canvas_item->has_meta("_edit_ik_") && canvas_item->get_meta("_edit_ik_"))
4945 					continue;
4946 
4947 				undo_redo->add_do_method(canvas_item, "set_meta", "_edit_ik_", true);
4948 				undo_redo->add_undo_method(canvas_item, "remove_meta", "_edit_ik_");
4949 			}
4950 			undo_redo->add_do_method(viewport, "update");
4951 			undo_redo->add_undo_method(viewport, "update");
4952 			undo_redo->commit_action();
4953 
4954 		} break;
4955 		case SKELETON_CLEAR_IK_CHAIN: {
4956 
4957 			Map<Node *, Object *> &selection = editor_selection->get_selection();
4958 
4959 			undo_redo->create_action(TTR("Clear IK Chain"));
4960 			for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4961 
4962 				CanvasItem *n2d = Object::cast_to<CanvasItem>(E->key());
4963 				if (!n2d)
4964 					continue;
4965 				if (!n2d->is_visible_in_tree())
4966 					continue;
4967 				if (!n2d->has_meta("_edit_ik_"))
4968 					continue;
4969 
4970 				undo_redo->add_do_method(n2d, "remove_meta", "_edit_ik_");
4971 				undo_redo->add_undo_method(n2d, "set_meta", "_edit_ik_", n2d->get_meta("_edit_ik_"));
4972 			}
4973 			undo_redo->add_do_method(viewport, "update");
4974 			undo_redo->add_undo_method(viewport, "update");
4975 			undo_redo->commit_action();
4976 
4977 		} break;
4978 	}
4979 }
4980 
_focus_selection(int p_op)4981 void CanvasItemEditor::_focus_selection(int p_op) {
4982 	Vector2 center(0.f, 0.f);
4983 	Rect2 rect;
4984 	int count = 0;
4985 
4986 	Map<Node *, Object *> &selection = editor_selection->get_selection();
4987 	for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
4988 		CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
4989 		if (!canvas_item) continue;
4990 		if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root())
4991 			continue;
4992 
4993 		// counting invisible items, for now
4994 		//if (!canvas_item->is_visible_in_tree()) continue;
4995 		++count;
4996 
4997 		Rect2 item_rect;
4998 		if (canvas_item->_edit_use_rect()) {
4999 			item_rect = canvas_item->_edit_get_rect();
5000 		} else {
5001 			item_rect = Rect2();
5002 		}
5003 
5004 		Vector2 pos = canvas_item->get_global_transform().get_origin();
5005 		Vector2 scale = canvas_item->get_global_transform().get_scale();
5006 		real_t angle = canvas_item->get_global_transform().get_rotation();
5007 
5008 		Transform2D t(angle, Vector2(0.f, 0.f));
5009 		item_rect = t.xform(item_rect);
5010 		Rect2 canvas_item_rect(pos + scale * item_rect.position, scale * item_rect.size);
5011 		if (count == 1) {
5012 			rect = canvas_item_rect;
5013 		} else {
5014 			rect = rect.merge(canvas_item_rect);
5015 		}
5016 	};
5017 	if (count == 0) return;
5018 
5019 	if (p_op == VIEW_CENTER_TO_SELECTION) {
5020 
5021 		center = rect.position + rect.size / 2;
5022 		Vector2 offset = viewport->get_size() / 2 - editor->get_scene_root()->get_global_canvas_transform().xform(center);
5023 		view_offset.x -= Math::round(offset.x / zoom);
5024 		view_offset.y -= Math::round(offset.y / zoom);
5025 		update_viewport();
5026 
5027 	} else { // VIEW_FRAME_TO_SELECTION
5028 
5029 		if (rect.size.x > CMP_EPSILON && rect.size.y > CMP_EPSILON) {
5030 			float scale_x = viewport->get_size().x / rect.size.x;
5031 			float scale_y = viewport->get_size().y / rect.size.y;
5032 			zoom = scale_x < scale_y ? scale_x : scale_y;
5033 			zoom *= 0.90;
5034 			viewport->update();
5035 			_update_zoom_label();
5036 			call_deferred("_popup_callback", VIEW_CENTER_TO_SELECTION);
5037 		}
5038 	}
5039 }
5040 
_bind_methods()5041 void CanvasItemEditor::_bind_methods() {
5042 
5043 	ClassDB::bind_method("_button_zoom_minus", &CanvasItemEditor::_button_zoom_minus);
5044 	ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset);
5045 	ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
5046 	ClassDB::bind_method("_button_toggle_smart_snap", &CanvasItemEditor::_button_toggle_smart_snap);
5047 	ClassDB::bind_method("_button_toggle_grid_snap", &CanvasItemEditor::_button_toggle_grid_snap);
5048 	ClassDB::bind_method(D_METHOD("_button_override_camera", "pressed"), &CanvasItemEditor::_button_override_camera);
5049 	ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button);
5050 	ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode);
5051 	ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
5052 	ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars);
5053 	ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
5054 	ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data);
5055 	ClassDB::bind_method("_button_tool_select", &CanvasItemEditor::_button_tool_select);
5056 	ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed);
5057 	ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input);
5058 	ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
5059 	ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
5060 	ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
5061 	ClassDB::bind_method("_queue_update_bone_list", &CanvasItemEditor::_update_bone_list);
5062 	ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
5063 	ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
5064 	ClassDB::bind_method("_selection_changed", &CanvasItemEditor::_selection_changed);
5065 	ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
5066 	ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
5067 	ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
5068 	ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
5069 	ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport);
5070 
5071 	ADD_SIGNAL(MethodInfo("item_lock_status_changed"));
5072 	ADD_SIGNAL(MethodInfo("item_group_status_changed"));
5073 }
5074 
get_state() const5075 Dictionary CanvasItemEditor::get_state() const {
5076 
5077 	Dictionary state;
5078 	// Take the editor scale into account.
5079 	state["zoom"] = zoom / MAX(1, EDSCALE);
5080 	state["ofs"] = view_offset;
5081 	state["grid_offset"] = grid_offset;
5082 	state["grid_step"] = grid_step;
5083 	state["primary_grid_steps"] = primary_grid_steps;
5084 	state["snap_rotation_offset"] = snap_rotation_offset;
5085 	state["snap_rotation_step"] = snap_rotation_step;
5086 	state["snap_scale_step"] = snap_scale_step;
5087 	state["smart_snap_active"] = smart_snap_active;
5088 	state["grid_snap_active"] = grid_snap_active;
5089 	state["snap_node_parent"] = snap_node_parent;
5090 	state["snap_node_anchors"] = snap_node_anchors;
5091 	state["snap_node_sides"] = snap_node_sides;
5092 	state["snap_node_center"] = snap_node_center;
5093 	state["snap_other_nodes"] = snap_other_nodes;
5094 	state["snap_guides"] = snap_guides;
5095 	state["show_grid"] = show_grid;
5096 	state["show_origin"] = show_origin;
5097 	state["show_viewport"] = show_viewport;
5098 	state["show_rulers"] = show_rulers;
5099 	state["show_guides"] = show_guides;
5100 	state["show_helpers"] = show_helpers;
5101 	state["show_zoom_control"] = zoom_hb->is_visible();
5102 	state["show_edit_locks"] = show_edit_locks;
5103 	state["snap_rotation"] = snap_rotation;
5104 	state["snap_scale"] = snap_scale;
5105 	state["snap_relative"] = snap_relative;
5106 	state["snap_pixel"] = snap_pixel;
5107 	state["skeleton_show_bones"] = skeleton_show_bones;
5108 	return state;
5109 }
5110 
set_state(const Dictionary & p_state)5111 void CanvasItemEditor::set_state(const Dictionary &p_state) {
5112 
5113 	bool update_scrollbars = false;
5114 	Dictionary state = p_state;
5115 	if (state.has("zoom")) {
5116 		// Compensate the editor scale, so that the editor scale can be changed
5117 		// and the zoom level will still be the same (relative to the editor scale).
5118 		zoom = float(p_state["zoom"]) * MAX(1, EDSCALE);
5119 		_update_zoom_label();
5120 	}
5121 
5122 	if (state.has("ofs")) {
5123 		view_offset = p_state["ofs"];
5124 		previous_update_view_offset = view_offset;
5125 		update_scrollbars = true;
5126 	}
5127 
5128 	if (state.has("grid_offset")) {
5129 		grid_offset = state["grid_offset"];
5130 	}
5131 
5132 	if (state.has("grid_step")) {
5133 		grid_step = state["grid_step"];
5134 	}
5135 
5136 	if (state.has("primary_grid_steps")) {
5137 		primary_grid_steps = state["primary_grid_steps"];
5138 	}
5139 
5140 	if (state.has("snap_rotation_step")) {
5141 		snap_rotation_step = state["snap_rotation_step"];
5142 	}
5143 
5144 	if (state.has("snap_rotation_offset")) {
5145 		snap_rotation_offset = state["snap_rotation_offset"];
5146 	}
5147 
5148 	if (state.has("snap_scale_step")) {
5149 		snap_scale_step = state["snap_scale_step"];
5150 	}
5151 
5152 	if (state.has("smart_snap_active")) {
5153 		smart_snap_active = state["smart_snap_active"];
5154 		smart_snap_button->set_pressed(smart_snap_active);
5155 	}
5156 
5157 	if (state.has("grid_snap_active")) {
5158 		grid_snap_active = state["grid_snap_active"];
5159 		grid_snap_button->set_pressed(grid_snap_active);
5160 	}
5161 
5162 	if (state.has("snap_node_parent")) {
5163 		snap_node_parent = state["snap_node_parent"];
5164 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
5165 		smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
5166 	}
5167 
5168 	if (state.has("snap_node_anchors")) {
5169 		snap_node_anchors = state["snap_node_anchors"];
5170 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
5171 		smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
5172 	}
5173 
5174 	if (state.has("snap_node_sides")) {
5175 		snap_node_sides = state["snap_node_sides"];
5176 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
5177 		smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
5178 	}
5179 
5180 	if (state.has("snap_node_center")) {
5181 		snap_node_center = state["snap_node_center"];
5182 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_CENTER);
5183 		smartsnap_config_popup->set_item_checked(idx, snap_node_center);
5184 	}
5185 
5186 	if (state.has("snap_other_nodes")) {
5187 		snap_other_nodes = state["snap_other_nodes"];
5188 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
5189 		smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
5190 	}
5191 
5192 	if (state.has("snap_guides")) {
5193 		snap_guides = state["snap_guides"];
5194 		int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES);
5195 		smartsnap_config_popup->set_item_checked(idx, snap_guides);
5196 	}
5197 
5198 	if (state.has("show_grid")) {
5199 		show_grid = state["show_grid"];
5200 		int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
5201 		view_menu->get_popup()->set_item_checked(idx, show_grid);
5202 	}
5203 
5204 	if (state.has("show_origin")) {
5205 		show_origin = state["show_origin"];
5206 		int idx = view_menu->get_popup()->get_item_index(SHOW_ORIGIN);
5207 		view_menu->get_popup()->set_item_checked(idx, show_origin);
5208 	}
5209 
5210 	if (state.has("show_viewport")) {
5211 		show_viewport = state["show_viewport"];
5212 		int idx = view_menu->get_popup()->get_item_index(SHOW_VIEWPORT);
5213 		view_menu->get_popup()->set_item_checked(idx, show_viewport);
5214 	}
5215 
5216 	if (state.has("show_rulers")) {
5217 		show_rulers = state["show_rulers"];
5218 		int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
5219 		view_menu->get_popup()->set_item_checked(idx, show_rulers);
5220 		update_scrollbars = true;
5221 	}
5222 
5223 	if (state.has("show_guides")) {
5224 		show_guides = state["show_guides"];
5225 		int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES);
5226 		view_menu->get_popup()->set_item_checked(idx, show_guides);
5227 	}
5228 
5229 	if (state.has("show_helpers")) {
5230 		show_helpers = state["show_helpers"];
5231 		int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
5232 		view_menu->get_popup()->set_item_checked(idx, show_helpers);
5233 	}
5234 
5235 	if (state.has("show_edit_locks")) {
5236 		show_edit_locks = state["show_edit_locks"];
5237 		int idx = view_menu->get_popup()->get_item_index(SHOW_EDIT_LOCKS);
5238 		view_menu->get_popup()->set_item_checked(idx, show_edit_locks);
5239 	}
5240 
5241 	if (state.has("show_zoom_control")) {
5242 		// This one is not user-controllable, but instrumentable
5243 		zoom_hb->set_visible(state["show_zoom_control"]);
5244 	}
5245 
5246 	if (state.has("snap_rotation")) {
5247 		snap_rotation = state["snap_rotation"];
5248 		int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
5249 		snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation);
5250 	}
5251 
5252 	if (state.has("snap_scale")) {
5253 		snap_scale = state["snap_scale"];
5254 		int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_SCALE);
5255 		snap_config_menu->get_popup()->set_item_checked(idx, snap_scale);
5256 	}
5257 
5258 	if (state.has("snap_relative")) {
5259 		snap_relative = state["snap_relative"];
5260 		int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
5261 		snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
5262 	}
5263 
5264 	if (state.has("snap_pixel")) {
5265 		snap_pixel = state["snap_pixel"];
5266 		int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
5267 		snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel);
5268 	}
5269 
5270 	if (state.has("skeleton_show_bones")) {
5271 		skeleton_show_bones = state["skeleton_show_bones"];
5272 		int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
5273 		skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
5274 	}
5275 
5276 	if (update_scrollbars) {
5277 		_update_scrollbars();
5278 	}
5279 	viewport->update();
5280 }
5281 
add_control_to_info_overlay(Control * p_control)5282 void CanvasItemEditor::add_control_to_info_overlay(Control *p_control) {
5283 	ERR_FAIL_COND(!p_control);
5284 
5285 	p_control->set_h_size_flags(p_control->get_h_size_flags() & ~Control::SIZE_EXPAND_FILL);
5286 	info_overlay->add_child(p_control);
5287 	info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
5288 }
5289 
remove_control_from_info_overlay(Control * p_control)5290 void CanvasItemEditor::remove_control_from_info_overlay(Control *p_control) {
5291 
5292 	info_overlay->remove_child(p_control);
5293 	info_overlay->set_margin(MARGIN_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
5294 }
5295 
add_control_to_menu_panel(Control * p_control)5296 void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
5297 	ERR_FAIL_COND(!p_control);
5298 
5299 	hb->add_child(p_control);
5300 }
5301 
remove_control_from_menu_panel(Control * p_control)5302 void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) {
5303 
5304 	hb->remove_child(p_control);
5305 }
5306 
get_palette_split()5307 HSplitContainer *CanvasItemEditor::get_palette_split() {
5308 
5309 	return palette_split;
5310 }
5311 
get_bottom_split()5312 VSplitContainer *CanvasItemEditor::get_bottom_split() {
5313 
5314 	return bottom_split;
5315 }
5316 
focus_selection()5317 void CanvasItemEditor::focus_selection() {
5318 	_focus_selection(VIEW_CENTER_TO_SELECTION);
5319 }
5320 
CanvasItemEditor(EditorNode * p_editor)5321 CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
5322 
5323 	key_pos = true;
5324 	key_rot = true;
5325 	key_scale = false;
5326 
5327 	show_grid = false;
5328 	show_origin = true;
5329 	show_viewport = true;
5330 	show_helpers = false;
5331 	show_rulers = true;
5332 	show_guides = true;
5333 	show_edit_locks = true;
5334 	zoom = 1.0 / MAX(1, EDSCALE);
5335 	view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH);
5336 	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
5337 	grid_offset = Point2();
5338 	grid_step = Point2(8, 8); // A power-of-two value works better as a default
5339 	primary_grid_steps = 8; // A power-of-two value works better as a default
5340 	grid_step_multiplier = 0;
5341 	snap_rotation_offset = 0;
5342 	snap_rotation_step = 15 / (180 / Math_PI);
5343 	snap_scale_step = 0.1f;
5344 	smart_snap_active = false;
5345 	grid_snap_active = false;
5346 	snap_node_parent = true;
5347 	snap_node_anchors = true;
5348 	snap_node_sides = true;
5349 	snap_node_center = true;
5350 	snap_other_nodes = true;
5351 	snap_guides = true;
5352 	snap_rotation = false;
5353 	snap_scale = false;
5354 	snap_relative = false;
5355 	snap_pixel = false;
5356 	snap_target[0] = SNAP_TARGET_NONE;
5357 	snap_target[1] = SNAP_TARGET_NONE;
5358 
5359 	selected_from_canvas = false;
5360 	anchors_mode = false;
5361 
5362 	skeleton_show_bones = true;
5363 
5364 	drag_type = DRAG_NONE;
5365 	drag_from = Vector2();
5366 	drag_to = Vector2();
5367 	dragged_guide_pos = Point2();
5368 	dragged_guide_index = -1;
5369 	is_hovering_h_guide = false;
5370 	is_hovering_v_guide = false;
5371 	panning = false;
5372 	pan_pressed = false;
5373 
5374 	ruler_tool_active = false;
5375 	ruler_tool_origin = Point2();
5376 
5377 	bone_last_frame = 0;
5378 
5379 	bone_list_dirty = false;
5380 	tool = TOOL_SELECT;
5381 	undo_redo = p_editor->get_undo_redo();
5382 	editor = p_editor;
5383 	editor_selection = p_editor->get_editor_selection();
5384 	editor_selection->add_editor_plugin(this);
5385 	editor_selection->connect("selection_changed", this, "update");
5386 	editor_selection->connect("selection_changed", this, "_selection_changed");
5387 
5388 	editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true));
5389 	editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false));
5390 
5391 	hb = memnew(HBoxContainer);
5392 	add_child(hb);
5393 	hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5394 
5395 	bottom_split = memnew(VSplitContainer);
5396 	add_child(bottom_split);
5397 	bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
5398 
5399 	palette_split = memnew(HSplitContainer);
5400 	bottom_split->add_child(palette_split);
5401 	palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
5402 
5403 	viewport_scrollable = memnew(Control);
5404 	palette_split->add_child(viewport_scrollable);
5405 	viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS);
5406 	viewport_scrollable->set_clip_contents(true);
5407 	viewport_scrollable->set_v_size_flags(SIZE_EXPAND_FILL);
5408 	viewport_scrollable->set_h_size_flags(SIZE_EXPAND_FILL);
5409 	viewport_scrollable->connect("draw", this, "_update_scrollbars");
5410 
5411 	ViewportContainer *scene_tree = memnew(ViewportContainer);
5412 	viewport_scrollable->add_child(scene_tree);
5413 	scene_tree->set_stretch(true);
5414 	scene_tree->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5415 	scene_tree->add_child(p_editor->get_scene_root());
5416 
5417 	controls_vb = memnew(VBoxContainer);
5418 	controls_vb->set_begin(Point2(5, 5));
5419 
5420 	zoom_hb = memnew(HBoxContainer);
5421 	// Bring the zoom percentage closer to the zoom buttons
5422 	zoom_hb->add_constant_override("separation", Math::round(-8 * EDSCALE));
5423 	controls_vb->add_child(zoom_hb);
5424 
5425 	viewport = memnew(CanvasItemEditorViewport(p_editor, this));
5426 	viewport_scrollable->add_child(viewport);
5427 	viewport->set_mouse_filter(MOUSE_FILTER_PASS);
5428 	viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5429 	viewport->set_clip_contents(true);
5430 	viewport->set_focus_mode(FOCUS_ALL);
5431 	viewport->connect("draw", this, "_draw_viewport");
5432 	viewport->connect("gui_input", this, "_gui_input_viewport");
5433 
5434 	info_overlay = memnew(VBoxContainer);
5435 	info_overlay->set_anchors_and_margins_preset(Control::PRESET_BOTTOM_LEFT);
5436 	info_overlay->set_margin(MARGIN_LEFT, 10);
5437 	info_overlay->set_margin(MARGIN_BOTTOM, -15);
5438 	info_overlay->set_v_grow_direction(Control::GROW_DIRECTION_BEGIN);
5439 	info_overlay->add_constant_override("separation", 10);
5440 	viewport_scrollable->add_child(info_overlay);
5441 
5442 	Theme *info_overlay_theme = memnew(Theme);
5443 	info_overlay_theme->copy_default_theme();
5444 	info_overlay->set_theme(info_overlay_theme);
5445 
5446 	StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat);
5447 	info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2));
5448 	info_overlay_label_stylebox->set_expand_margin_size_all(4);
5449 	info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox);
5450 
5451 	warning_child_of_container = memnew(Label);
5452 	warning_child_of_container->hide();
5453 	warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
5454 	warning_child_of_container->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"));
5455 	warning_child_of_container->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
5456 	add_control_to_info_overlay(warning_child_of_container);
5457 
5458 	h_scroll = memnew(HScrollBar);
5459 	viewport->add_child(h_scroll);
5460 	h_scroll->connect("value_changed", this, "_update_scroll");
5461 	h_scroll->hide();
5462 
5463 	v_scroll = memnew(VScrollBar);
5464 	viewport->add_child(v_scroll);
5465 	v_scroll->connect("value_changed", this, "_update_scroll");
5466 	v_scroll->hide();
5467 
5468 	viewport->add_child(controls_vb);
5469 
5470 	zoom_minus = memnew(ToolButton);
5471 	zoom_hb->add_child(zoom_minus);
5472 	zoom_minus->connect("pressed", this, "_button_zoom_minus");
5473 	zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS));
5474 	zoom_minus->set_focus_mode(FOCUS_NONE);
5475 
5476 	zoom_reset = memnew(ToolButton);
5477 	zoom_hb->add_child(zoom_reset);
5478 	zoom_reset->connect("pressed", this, "_button_zoom_reset");
5479 	zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0));
5480 	zoom_reset->set_focus_mode(FOCUS_NONE);
5481 	zoom_reset->set_text_align(Button::TextAlign::ALIGN_CENTER);
5482 	// Prevent the button's size from changing when the text size changes
5483 	zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
5484 
5485 	zoom_plus = memnew(ToolButton);
5486 	zoom_hb->add_child(zoom_plus);
5487 	zoom_plus->connect("pressed", this, "_button_zoom_plus");
5488 	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
5489 	zoom_plus->set_focus_mode(FOCUS_NONE);
5490 
5491 	updating_scroll = false;
5492 
5493 	select_button = memnew(ToolButton);
5494 	hb->add_child(select_button);
5495 	select_button->set_toggle_mode(true);
5496 	select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECT));
5497 	select_button->set_pressed(true);
5498 	select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q));
5499 	select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection"));
5500 
5501 	hb->add_child(memnew(VSeparator));
5502 
5503 	move_button = memnew(ToolButton);
5504 	hb->add_child(move_button);
5505 	move_button->set_toggle_mode(true);
5506 	move_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_MOVE));
5507 	move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W));
5508 	move_button->set_tooltip(TTR("Move Mode"));
5509 
5510 	rotate_button = memnew(ToolButton);
5511 	hb->add_child(rotate_button);
5512 	rotate_button->set_toggle_mode(true);
5513 	rotate_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_ROTATE));
5514 	rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E));
5515 	rotate_button->set_tooltip(TTR("Rotate Mode"));
5516 
5517 	scale_button = memnew(ToolButton);
5518 	hb->add_child(scale_button);
5519 	scale_button->set_toggle_mode(true);
5520 	scale_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SCALE));
5521 	scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), KEY_S));
5522 	scale_button->set_tooltip(TTR("Scale Mode"));
5523 
5524 	hb->add_child(memnew(VSeparator));
5525 
5526 	list_select_button = memnew(ToolButton);
5527 	hb->add_child(list_select_button);
5528 	list_select_button->set_toggle_mode(true);
5529 	list_select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_LIST_SELECT));
5530 	list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode)."));
5531 
5532 	pivot_button = memnew(ToolButton);
5533 	hb->add_child(pivot_button);
5534 	pivot_button->set_toggle_mode(true);
5535 	pivot_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_EDIT_PIVOT));
5536 	pivot_button->set_tooltip(TTR("Click to change object's rotation pivot."));
5537 
5538 	pan_button = memnew(ToolButton);
5539 	hb->add_child(pan_button);
5540 	pan_button->set_toggle_mode(true);
5541 	pan_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PAN));
5542 	pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G));
5543 	pan_button->set_tooltip(TTR("Pan Mode"));
5544 
5545 	ruler_button = memnew(ToolButton);
5546 	hb->add_child(ruler_button);
5547 	ruler_button->set_toggle_mode(true);
5548 	ruler_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_RULER));
5549 	ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), KEY_R));
5550 	ruler_button->set_tooltip(TTR("Ruler Mode"));
5551 
5552 	hb->add_child(memnew(VSeparator));
5553 
5554 	smart_snap_button = memnew(ToolButton);
5555 	hb->add_child(smart_snap_button);
5556 	smart_snap_button->set_toggle_mode(true);
5557 	smart_snap_button->connect("toggled", this, "_button_toggle_smart_snap");
5558 	smart_snap_button->set_tooltip(TTR("Toggle smart snapping."));
5559 	smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S));
5560 
5561 	grid_snap_button = memnew(ToolButton);
5562 	hb->add_child(grid_snap_button);
5563 	grid_snap_button->set_toggle_mode(true);
5564 	grid_snap_button->connect("toggled", this, "_button_toggle_grid_snap");
5565 	grid_snap_button->set_tooltip(TTR("Toggle grid snapping."));
5566 	grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KEY_MASK_SHIFT | KEY_G));
5567 
5568 	snap_config_menu = memnew(MenuButton);
5569 	hb->add_child(snap_config_menu);
5570 	snap_config_menu->set_h_size_flags(SIZE_SHRINK_END);
5571 	snap_config_menu->set_tooltip(TTR("Snapping Options"));
5572 	snap_config_menu->set_switch_on_hover(true);
5573 
5574 	PopupMenu *p = snap_config_menu->get_popup();
5575 	p->connect("id_pressed", this, "_popup_callback");
5576 	p->set_hide_on_checkable_item_selection(false);
5577 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
5578 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_scale_snap", TTR("Use Scale Snap")), SNAP_USE_SCALE);
5579 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
5580 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
5581 	p->add_submenu_item(TTR("Smart Snapping"), "SmartSnapping");
5582 
5583 	p->add_separator();
5584 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE);
5585 
5586 	smartsnap_config_popup = memnew(PopupMenu);
5587 	p->add_child(smartsnap_config_popup);
5588 	smartsnap_config_popup->set_name("SmartSnapping");
5589 	smartsnap_config_popup->connect("id_pressed", this, "_popup_callback");
5590 	smartsnap_config_popup->set_hide_on_checkable_item_selection(false);
5591 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to Parent")), SNAP_USE_NODE_PARENT);
5592 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to Node Anchor")), SNAP_USE_NODE_ANCHORS);
5593 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to Node Sides")), SNAP_USE_NODE_SIDES);
5594 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_center", TTR("Snap to Node Center")), SNAP_USE_NODE_CENTER);
5595 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to Other Nodes")), SNAP_USE_OTHER_NODES);
5596 	smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to Guides")), SNAP_USE_GUIDES);
5597 
5598 	hb->add_child(memnew(VSeparator));
5599 
5600 	lock_button = memnew(ToolButton);
5601 	hb->add_child(lock_button);
5602 
5603 	lock_button->connect("pressed", this, "_popup_callback", varray(LOCK_SELECTED));
5604 	lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved)."));
5605 
5606 	unlock_button = memnew(ToolButton);
5607 	hb->add_child(unlock_button);
5608 	unlock_button->connect("pressed", this, "_popup_callback", varray(UNLOCK_SELECTED));
5609 	unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved)."));
5610 
5611 	group_button = memnew(ToolButton);
5612 	hb->add_child(group_button);
5613 	group_button->connect("pressed", this, "_popup_callback", varray(GROUP_SELECTED));
5614 	group_button->set_tooltip(TTR("Makes sure the object's children are not selectable."));
5615 
5616 	ungroup_button = memnew(ToolButton);
5617 	hb->add_child(ungroup_button);
5618 	ungroup_button->connect("pressed", this, "_popup_callback", varray(UNGROUP_SELECTED));
5619 	ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected."));
5620 
5621 	hb->add_child(memnew(VSeparator));
5622 
5623 	skeleton_menu = memnew(MenuButton);
5624 	hb->add_child(skeleton_menu);
5625 	skeleton_menu->set_tooltip(TTR("Skeleton Options"));
5626 	skeleton_menu->set_switch_on_hover(true);
5627 
5628 	p = skeleton_menu->get_popup();
5629 	p->set_hide_on_checkable_item_selection(false);
5630 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
5631 	p->add_separator();
5632 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
5633 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
5634 	p->add_separator();
5635 	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);
5636 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES);
5637 	p->connect("id_pressed", this, "_popup_callback");
5638 
5639 	hb->add_child(memnew(VSeparator));
5640 
5641 	override_camera_button = memnew(ToolButton);
5642 	hb->add_child(override_camera_button);
5643 	override_camera_button->connect("toggled", this, "_button_override_camera");
5644 	override_camera_button->set_toggle_mode(true);
5645 	override_camera_button->set_disabled(true);
5646 	_update_override_camera_button(false);
5647 
5648 	hb->add_child(memnew(VSeparator));
5649 
5650 	view_menu = memnew(MenuButton);
5651 	view_menu->set_text(TTR("View"));
5652 	hb->add_child(view_menu);
5653 	view_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
5654 	view_menu->set_switch_on_hover(true);
5655 
5656 	p = view_menu->get_popup();
5657 	p->set_hide_on_checkable_item_selection(false);
5658 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Always Show Grid"), KEY_G), SHOW_GRID);
5659 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS);
5660 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers")), SHOW_RULERS);
5661 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES);
5662 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN);
5663 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT);
5664 	p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS);
5665 
5666 	p->add_separator();
5667 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION);
5668 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION);
5669 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/clear_guides", TTR("Clear Guides")), CLEAR_GUIDES);
5670 	p->add_separator();
5671 	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);
5672 
5673 	presets_menu = memnew(MenuButton);
5674 	presets_menu->set_text(TTR("Layout"));
5675 	hb->add_child(presets_menu);
5676 	presets_menu->hide();
5677 	presets_menu->set_switch_on_hover(true);
5678 
5679 	p = presets_menu->get_popup();
5680 	p->connect("id_pressed", this, "_popup_callback");
5681 
5682 	anchors_popup = memnew(PopupMenu);
5683 	p->add_child(anchors_popup);
5684 	anchors_popup->set_name("Anchors");
5685 	anchors_popup->connect("id_pressed", this, "_popup_callback");
5686 
5687 	anchor_mode_button = memnew(ToolButton);
5688 	hb->add_child(anchor_mode_button);
5689 	anchor_mode_button->set_toggle_mode(true);
5690 	anchor_mode_button->hide();
5691 	anchor_mode_button->connect("toggled", this, "_button_toggle_anchor_mode");
5692 
5693 	animation_hb = memnew(HBoxContainer);
5694 	hb->add_child(animation_hb);
5695 	animation_hb->add_child(memnew(VSeparator));
5696 	animation_hb->hide();
5697 
5698 	key_loc_button = memnew(Button);
5699 	key_loc_button->set_toggle_mode(true);
5700 	key_loc_button->set_flat(true);
5701 	key_loc_button->set_pressed(true);
5702 	key_loc_button->set_focus_mode(FOCUS_NONE);
5703 	key_loc_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_POS));
5704 	key_loc_button->set_tooltip(TTR("Translation mask for inserting keys."));
5705 	animation_hb->add_child(key_loc_button);
5706 	key_rot_button = memnew(Button);
5707 	key_rot_button->set_toggle_mode(true);
5708 	key_rot_button->set_flat(true);
5709 	key_rot_button->set_pressed(true);
5710 	key_rot_button->set_focus_mode(FOCUS_NONE);
5711 	key_rot_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_ROT));
5712 	key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys."));
5713 	animation_hb->add_child(key_rot_button);
5714 	key_scale_button = memnew(Button);
5715 	key_scale_button->set_toggle_mode(true);
5716 	key_scale_button->set_flat(true);
5717 	key_scale_button->set_focus_mode(FOCUS_NONE);
5718 	key_scale_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_SCALE));
5719 	key_scale_button->set_tooltip(TTR("Scale mask for inserting keys."));
5720 	animation_hb->add_child(key_scale_button);
5721 	key_insert_button = memnew(Button);
5722 	key_insert_button->set_flat(true);
5723 	key_insert_button->set_focus_mode(FOCUS_NONE);
5724 	key_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY));
5725 	key_insert_button->set_tooltip(TTR("Insert keys (based on mask)."));
5726 	key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), KEY_INSERT));
5727 	animation_hb->add_child(key_insert_button);
5728 	key_auto_insert_button = memnew(Button);
5729 	key_auto_insert_button->set_flat(true);
5730 	key_auto_insert_button->set_toggle_mode(true);
5731 	key_auto_insert_button->set_focus_mode(FOCUS_NONE);
5732 	//key_auto_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY));
5733 	key_auto_insert_button->set_tooltip(TTR("Auto insert keys when objects are translated, rotated or scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time."));
5734 	key_auto_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_auto_insert_key", TTR("Auto Insert Key")));
5735 	animation_hb->add_child(key_auto_insert_button);
5736 
5737 	animation_menu = memnew(MenuButton);
5738 	animation_menu->set_tooltip(TTR("Animation Key and Pose Options"));
5739 	animation_hb->add_child(animation_menu);
5740 	animation_menu->get_popup()->connect("id_pressed", this, "_popup_callback");
5741 	animation_menu->set_switch_on_hover(true);
5742 
5743 	p = animation_menu->get_popup();
5744 
5745 	p->add_shortcut(ED_GET_SHORTCUT("canvas_item_editor/anim_insert_key"), ANIM_INSERT_KEY);
5746 	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);
5747 	p->add_separator();
5748 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_copy_pose", TTR("Copy Pose")), ANIM_COPY_POSE);
5749 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_paste_pose", TTR("Paste Pose")), ANIM_PASTE_POSE);
5750 	p->add_shortcut(ED_SHORTCUT("canvas_item_editor/anim_clear_pose", TTR("Clear Pose"), KEY_MASK_SHIFT | KEY_K), ANIM_CLEAR_POSE);
5751 
5752 	snap_dialog = memnew(SnapDialog);
5753 	snap_dialog->connect("confirmed", this, "_snap_changed");
5754 	add_child(snap_dialog);
5755 
5756 	select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture));
5757 
5758 	selection_menu = memnew(PopupMenu);
5759 	add_child(selection_menu);
5760 	selection_menu->set_custom_minimum_size(Vector2(100, 0));
5761 	selection_menu->connect("id_pressed", this, "_selection_result_pressed");
5762 	selection_menu->connect("popup_hide", this, "_selection_menu_hide");
5763 
5764 	multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
5765 	divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
5766 	pan_view_shortcut = ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), KEY_SPACE);
5767 
5768 	skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
5769 	singleton = this;
5770 
5771 	set_process_unhandled_key_input(true);
5772 
5773 	// Update the menus' checkboxes
5774 	call_deferred("set_state", get_state());
5775 }
5776 
5777 CanvasItemEditor *CanvasItemEditor::singleton = NULL;
5778 
edit(Object * p_object)5779 void CanvasItemEditorPlugin::edit(Object *p_object) {
5780 
5781 	canvas_item_editor->set_undo_redo(&get_undo_redo());
5782 	canvas_item_editor->edit(Object::cast_to<CanvasItem>(p_object));
5783 }
5784 
handles(Object * p_object) const5785 bool CanvasItemEditorPlugin::handles(Object *p_object) const {
5786 
5787 	return p_object->is_class("CanvasItem");
5788 }
5789 
make_visible(bool p_visible)5790 void CanvasItemEditorPlugin::make_visible(bool p_visible) {
5791 
5792 	if (p_visible) {
5793 		canvas_item_editor->show();
5794 		canvas_item_editor->set_physics_process(true);
5795 		VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
5796 
5797 	} else {
5798 
5799 		canvas_item_editor->hide();
5800 		canvas_item_editor->set_physics_process(false);
5801 		VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true);
5802 	}
5803 }
5804 
get_state() const5805 Dictionary CanvasItemEditorPlugin::get_state() const {
5806 
5807 	return canvas_item_editor->get_state();
5808 }
set_state(const Dictionary & p_state)5809 void CanvasItemEditorPlugin::set_state(const Dictionary &p_state) {
5810 
5811 	canvas_item_editor->set_state(p_state);
5812 }
5813 
CanvasItemEditorPlugin(EditorNode * p_node)5814 CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *p_node) {
5815 
5816 	editor = p_node;
5817 	canvas_item_editor = memnew(CanvasItemEditor(editor));
5818 	canvas_item_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
5819 	editor->get_viewport()->add_child(canvas_item_editor);
5820 	canvas_item_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
5821 	canvas_item_editor->hide();
5822 }
5823 
~CanvasItemEditorPlugin()5824 CanvasItemEditorPlugin::~CanvasItemEditorPlugin() {
5825 }
5826 
_on_mouse_exit()5827 void CanvasItemEditorViewport::_on_mouse_exit() {
5828 	if (!selector->is_visible()) {
5829 		_remove_preview();
5830 	}
5831 }
5832 
_on_select_type(Object * selected)5833 void CanvasItemEditorViewport::_on_select_type(Object *selected) {
5834 	CheckBox *check = Object::cast_to<CheckBox>(selected);
5835 	String type = check->get_text();
5836 	selector->set_title(vformat(TTR("Add %s"), type));
5837 	label->set_text(vformat(TTR("Adding %s..."), type));
5838 }
5839 
_on_change_type_confirmed()5840 void CanvasItemEditorViewport::_on_change_type_confirmed() {
5841 	if (!button_group->get_pressed_button())
5842 		return;
5843 
5844 	CheckBox *check = Object::cast_to<CheckBox>(button_group->get_pressed_button());
5845 	default_type = check->get_text();
5846 	_perform_drop_data();
5847 	selector->hide();
5848 }
5849 
_on_change_type_closed()5850 void CanvasItemEditorViewport::_on_change_type_closed() {
5851 
5852 	_remove_preview();
5853 }
5854 
_create_preview(const Vector<String> & files) const5855 void CanvasItemEditorViewport::_create_preview(const Vector<String> &files) const {
5856 	bool add_preview = false;
5857 	for (int i = 0; i < files.size(); i++) {
5858 		String path = files[i];
5859 		RES res = ResourceLoader::load(path);
5860 		ERR_FAIL_COND(res.is_null());
5861 		Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
5862 		Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
5863 		if (texture != NULL || scene != NULL) {
5864 			if (texture != NULL) {
5865 				Sprite *sprite = memnew(Sprite);
5866 				sprite->set_texture(texture);
5867 				sprite->set_modulate(Color(1, 1, 1, 0.7f));
5868 				preview_node->add_child(sprite);
5869 				label->show();
5870 				label_desc->show();
5871 			} else {
5872 				if (scene.is_valid()) {
5873 					Node *instance = scene->instance();
5874 					if (instance) {
5875 						preview_node->add_child(instance);
5876 					}
5877 				}
5878 			}
5879 			add_preview = true;
5880 		}
5881 	}
5882 
5883 	if (add_preview)
5884 		editor->get_scene_root()->add_child(preview_node);
5885 }
5886 
_remove_preview()5887 void CanvasItemEditorViewport::_remove_preview() {
5888 	if (preview_node->get_parent()) {
5889 		for (int i = preview_node->get_child_count() - 1; i >= 0; i--) {
5890 			Node *node = preview_node->get_child(i);
5891 			node->queue_delete();
5892 			preview_node->remove_child(node);
5893 		}
5894 		editor->get_scene_root()->remove_child(preview_node);
5895 
5896 		label->hide();
5897 		label_desc->hide();
5898 	}
5899 }
5900 
_cyclical_dependency_exists(const String & p_target_scene_path,Node * p_desired_node)5901 bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node) {
5902 	if (p_desired_node->get_filename() == p_target_scene_path) {
5903 		return true;
5904 	}
5905 
5906 	int childCount = p_desired_node->get_child_count();
5907 	for (int i = 0; i < childCount; i++) {
5908 		Node *child = p_desired_node->get_child(i);
5909 		if (_cyclical_dependency_exists(p_target_scene_path, child)) {
5910 			return true;
5911 		}
5912 	}
5913 	return false;
5914 }
5915 
_create_nodes(Node * parent,Node * child,String & path,const Point2 & p_point)5916 void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point) {
5917 	child->set_name(path.get_file().get_basename());
5918 	Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(ResourceCache::get(path)));
5919 	Size2 texture_size = texture->get_size();
5920 
5921 	if (parent) {
5922 		editor_data->get_undo_redo().add_do_method(parent, "add_child", child);
5923 		editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
5924 		editor_data->get_undo_redo().add_do_reference(child);
5925 		editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child);
5926 	} else { // if we haven't parent, lets try to make a child as a parent.
5927 		editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child);
5928 		editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene());
5929 		editor_data->get_undo_redo().add_do_reference(child);
5930 		editor_data->get_undo_redo().add_undo_method(editor, "set_edited_scene", (Object *)NULL);
5931 	}
5932 
5933 	if (parent) {
5934 		String new_name = parent->validate_child_name(child);
5935 		ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
5936 		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);
5937 		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));
5938 	}
5939 
5940 	// handle with different property for texture
5941 	String property = "texture";
5942 	List<PropertyInfo> props;
5943 	child->get_property_list(&props);
5944 	for (const List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
5945 		if (E->get().name == "config/texture") { // Particles2D
5946 			property = "config/texture";
5947 			break;
5948 		} else if (E->get().name == "texture/texture") { // Polygon2D
5949 			property = "texture/texture";
5950 			break;
5951 		} else if (E->get().name == "normal") { // TouchScreenButton
5952 			property = "normal";
5953 			break;
5954 		}
5955 	}
5956 	editor_data->get_undo_redo().add_do_property(child, property, texture);
5957 
5958 	// make visible for certain node type
5959 	if (default_type == "NinePatchRect") {
5960 		editor_data->get_undo_redo().add_do_property(child, "rect/size", texture_size);
5961 	} else if (default_type == "Polygon2D") {
5962 		PoolVector<Vector2> list;
5963 		list.push_back(Vector2(0, 0));
5964 		list.push_back(Vector2(texture_size.width, 0));
5965 		list.push_back(Vector2(texture_size.width, texture_size.height));
5966 		list.push_back(Vector2(0, texture_size.height));
5967 		editor_data->get_undo_redo().add_do_property(child, "polygon", list);
5968 	}
5969 
5970 	// Compute the global position
5971 	Transform2D xform = canvas_item_editor->get_canvas_transform();
5972 	Point2 target_position = xform.affine_inverse().xform(p_point);
5973 
5974 	// there's nothing to be used as source position so snapping will work as absolute if enabled
5975 	target_position = canvas_item_editor->snap_point(target_position);
5976 	editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position);
5977 }
5978 
_create_instance(Node * parent,String & path,const Point2 & p_point)5979 bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
5980 	Ref<PackedScene> sdata = ResourceLoader::load(path);
5981 	if (!sdata.is_valid()) { // invalid scene
5982 		return false;
5983 	}
5984 
5985 	Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
5986 	if (!instanced_scene) { // error on instancing
5987 		return false;
5988 	}
5989 
5990 	if (editor->get_edited_scene()->get_filename() != "") { // cyclical instancing
5991 		if (_cyclical_dependency_exists(editor->get_edited_scene()->get_filename(), instanced_scene)) {
5992 			memdelete(instanced_scene);
5993 			return false;
5994 		}
5995 	}
5996 
5997 	instanced_scene->set_filename(ProjectSettings::get_singleton()->localize_path(path));
5998 
5999 	editor_data->get_undo_redo().add_do_method(parent, "add_child", instanced_scene);
6000 	editor_data->get_undo_redo().add_do_method(instanced_scene, "set_owner", editor->get_edited_scene());
6001 	editor_data->get_undo_redo().add_do_reference(instanced_scene);
6002 	editor_data->get_undo_redo().add_undo_method(parent, "remove_child", instanced_scene);
6003 
6004 	String new_name = parent->validate_child_name(instanced_scene);
6005 	ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
6006 	editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name);
6007 	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));
6008 
6009 	CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent);
6010 	if (parent_ci) {
6011 		Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point);
6012 		target_pos = canvas_item_editor->snap_point(target_pos);
6013 		target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos);
6014 		// Preserve instance position of the original scene.
6015 		CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instanced_scene);
6016 		if (instance_ci) {
6017 			target_pos += instance_ci->_edit_get_position();
6018 		}
6019 		editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
6020 	}
6021 
6022 	return true;
6023 }
6024 
_perform_drop_data()6025 void CanvasItemEditorViewport::_perform_drop_data() {
6026 	_remove_preview();
6027 
6028 	// Without root dropping multiple files is not allowed
6029 	if (!target_node && selected_files.size() > 1) {
6030 		accept->set_text(TTR("Cannot instantiate multiple nodes without root."));
6031 		accept->popup_centered_minsize();
6032 		return;
6033 	}
6034 
6035 	Vector<String> error_files;
6036 
6037 	editor_data->get_undo_redo().create_action(TTR("Create Node"));
6038 
6039 	for (int i = 0; i < selected_files.size(); i++) {
6040 		String path = selected_files[i];
6041 		RES res = ResourceLoader::load(path);
6042 		if (res.is_null()) {
6043 			continue;
6044 		}
6045 		Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
6046 		if (scene != NULL && scene.is_valid()) {
6047 			if (!target_node) {
6048 				// Without root node act the same as "Load Inherited Scene"
6049 				Error err = EditorNode::get_singleton()->load_scene(path, false, true);
6050 				if (err != OK) {
6051 					error_files.push_back(path);
6052 				}
6053 			} else {
6054 				bool success = _create_instance(target_node, path, drop_pos);
6055 				if (!success) {
6056 					error_files.push_back(path);
6057 				}
6058 			}
6059 		} else {
6060 			Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
6061 			if (texture != NULL && texture.is_valid()) {
6062 				Node *child;
6063 				if (default_type == "Light2D")
6064 					child = memnew(Light2D);
6065 				else if (default_type == "Particles2D")
6066 					child = memnew(Particles2D);
6067 				else if (default_type == "Polygon2D")
6068 					child = memnew(Polygon2D);
6069 				else if (default_type == "TouchScreenButton")
6070 					child = memnew(TouchScreenButton);
6071 				else if (default_type == "TextureRect")
6072 					child = memnew(TextureRect);
6073 				else if (default_type == "NinePatchRect")
6074 					child = memnew(NinePatchRect);
6075 				else
6076 					child = memnew(Sprite); // default
6077 
6078 				_create_nodes(target_node, child, path, drop_pos);
6079 			}
6080 		}
6081 	}
6082 
6083 	editor_data->get_undo_redo().commit_action();
6084 
6085 	if (error_files.size() > 0) {
6086 		String files_str;
6087 		for (int i = 0; i < error_files.size(); i++) {
6088 			files_str += error_files[i].get_file().get_basename() + ",";
6089 		}
6090 		files_str = files_str.substr(0, files_str.length() - 1);
6091 		accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str()));
6092 		accept->popup_centered_minsize();
6093 	}
6094 }
6095 
can_drop_data(const Point2 & p_point,const Variant & p_data) const6096 bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
6097 	Dictionary d = p_data;
6098 	if (d.has("type")) {
6099 		if (String(d["type"]) == "files") {
6100 			Vector<String> files = d["files"];
6101 			bool can_instance = false;
6102 			for (int i = 0; i < files.size(); i++) { // check if dragged files contain resource or scene can be created at least once
6103 				RES res = ResourceLoader::load(files[i]);
6104 				if (res.is_null()) {
6105 					continue;
6106 				}
6107 				String type = res->get_class();
6108 				if (type == "PackedScene") {
6109 					Ref<PackedScene> sdata = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
6110 					Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
6111 					if (!instanced_scene) {
6112 						continue;
6113 					}
6114 					memdelete(instanced_scene);
6115 				} else if (type == "Texture" ||
6116 						   type == "ImageTexture" ||
6117 						   type == "ViewportTexture" ||
6118 						   type == "CurveTexture" ||
6119 						   type == "GradientTexture" ||
6120 						   type == "StreamTexture" ||
6121 						   type == "AtlasTexture" ||
6122 						   type == "LargeTexture") {
6123 					Ref<Texture> texture = Ref<Texture>(Object::cast_to<Texture>(*res));
6124 					if (!texture.is_valid()) {
6125 						continue;
6126 					}
6127 				} else {
6128 					continue;
6129 				}
6130 				can_instance = true;
6131 				break;
6132 			}
6133 			if (can_instance) {
6134 				if (!preview_node->get_parent()) { // create preview only once
6135 					_create_preview(files);
6136 				}
6137 				Transform2D trans = canvas_item_editor->get_canvas_transform();
6138 				preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x);
6139 				label->set_text(vformat(TTR("Adding %s..."), default_type));
6140 			}
6141 			return can_instance;
6142 		}
6143 	}
6144 	label->hide();
6145 	return false;
6146 }
6147 
_show_resource_type_selector()6148 void CanvasItemEditorViewport::_show_resource_type_selector() {
6149 	_remove_preview();
6150 	List<BaseButton *> btn_list;
6151 	button_group->get_buttons(&btn_list);
6152 
6153 	for (int i = 0; i < btn_list.size(); i++) {
6154 		CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]);
6155 		check->set_pressed(check->get_text() == default_type);
6156 	}
6157 	selector->set_title(vformat(TTR("Add %s"), default_type));
6158 	selector->popup_centered_minsize();
6159 }
6160 
_only_packed_scenes_selected() const6161 bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
6162 
6163 	for (int i = 0; i < selected_files.size(); ++i) {
6164 		if (ResourceLoader::load(selected_files[i])->get_class() != "PackedScene") {
6165 			return false;
6166 		}
6167 	}
6168 
6169 	return true;
6170 }
6171 
drop_data(const Point2 & p_point,const Variant & p_data)6172 void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
6173 	bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
6174 	bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
6175 
6176 	selected_files.clear();
6177 	Dictionary d = p_data;
6178 	if (d.has("type") && String(d["type"]) == "files") {
6179 		selected_files = d["files"];
6180 	}
6181 	if (selected_files.size() == 0)
6182 		return;
6183 
6184 	List<Node *> list = editor->get_editor_selection()->get_selected_node_list();
6185 	if (list.size() == 0) {
6186 		Node *root_node = editor->get_edited_scene();
6187 		if (root_node) {
6188 			list.push_back(root_node);
6189 		} else {
6190 			drop_pos = p_point;
6191 			target_node = NULL;
6192 		}
6193 	}
6194 
6195 	if (list.size() > 0) {
6196 		target_node = list[0];
6197 		if (is_shift && target_node != editor->get_edited_scene()) {
6198 			target_node = target_node->get_parent();
6199 		}
6200 	}
6201 
6202 	drop_pos = p_point;
6203 
6204 	if (is_alt && !_only_packed_scenes_selected()) {
6205 		_show_resource_type_selector();
6206 	} else {
6207 		_perform_drop_data();
6208 	}
6209 }
6210 
_notification(int p_what)6211 void CanvasItemEditorViewport::_notification(int p_what) {
6212 	switch (p_what) {
6213 		case NOTIFICATION_ENTER_TREE: {
6214 			connect("mouse_exited", this, "_on_mouse_exit");
6215 			label->add_color_override("font_color", get_color("warning_color", "Editor"));
6216 		} break;
6217 		case NOTIFICATION_EXIT_TREE: {
6218 			disconnect("mouse_exited", this, "_on_mouse_exit");
6219 		} break;
6220 
6221 		default: break;
6222 	}
6223 }
6224 
_bind_methods()6225 void CanvasItemEditorViewport::_bind_methods() {
6226 	ClassDB::bind_method(D_METHOD("_on_select_type"), &CanvasItemEditorViewport::_on_select_type);
6227 	ClassDB::bind_method(D_METHOD("_on_change_type_confirmed"), &CanvasItemEditorViewport::_on_change_type_confirmed);
6228 	ClassDB::bind_method(D_METHOD("_on_change_type_closed"), &CanvasItemEditorViewport::_on_change_type_closed);
6229 	ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit);
6230 }
6231 
CanvasItemEditorViewport(EditorNode * p_node,CanvasItemEditor * p_canvas_item_editor)6232 CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) {
6233 	default_type = "Sprite";
6234 	// Node2D
6235 	types.push_back("Sprite");
6236 	types.push_back("Light2D");
6237 	types.push_back("Particles2D");
6238 	types.push_back("Polygon2D");
6239 	types.push_back("TouchScreenButton");
6240 	// Control
6241 	types.push_back("TextureRect");
6242 	types.push_back("NinePatchRect");
6243 
6244 	target_node = NULL;
6245 	editor = p_node;
6246 	editor_data = editor->get_scene_tree_dock()->get_editor_data();
6247 	canvas_item_editor = p_canvas_item_editor;
6248 	preview_node = memnew(Node2D);
6249 
6250 	accept = memnew(AcceptDialog);
6251 	editor->get_gui_base()->add_child(accept);
6252 
6253 	selector = memnew(AcceptDialog);
6254 	editor->get_gui_base()->add_child(selector);
6255 	selector->set_title(TTR("Change Default Type"));
6256 	selector->connect("confirmed", this, "_on_change_type_confirmed");
6257 	selector->connect("popup_hide", this, "_on_change_type_closed");
6258 
6259 	VBoxContainer *vbc = memnew(VBoxContainer);
6260 	selector->add_child(vbc);
6261 	vbc->set_h_size_flags(SIZE_EXPAND_FILL);
6262 	vbc->set_v_size_flags(SIZE_EXPAND_FILL);
6263 	vbc->set_custom_minimum_size(Size2(240, 260) * EDSCALE);
6264 
6265 	btn_group = memnew(VBoxContainer);
6266 	vbc->add_child(btn_group);
6267 	btn_group->set_h_size_flags(0);
6268 
6269 	button_group.instance();
6270 	for (int i = 0; i < types.size(); i++) {
6271 		CheckBox *check = memnew(CheckBox);
6272 		btn_group->add_child(check);
6273 		check->set_text(types[i]);
6274 		check->connect("button_down", this, "_on_select_type", varray(check));
6275 		check->set_button_group(button_group);
6276 	}
6277 
6278 	label = memnew(Label);
6279 	label->add_color_override("font_color_shadow", Color(0, 0, 0, 1));
6280 	label->add_constant_override("shadow_as_outline", 1 * EDSCALE);
6281 	label->hide();
6282 	canvas_item_editor->get_controls_container()->add_child(label);
6283 
6284 	label_desc = memnew(Label);
6285 	label_desc->set_text(TTR("Drag & drop + Shift : Add node as sibling\nDrag & drop + Alt : Change node type"));
6286 	label_desc->add_color_override("font_color", Color(0.6f, 0.6f, 0.6f, 1));
6287 	label_desc->add_color_override("font_color_shadow", Color(0.2f, 0.2f, 0.2f, 1));
6288 	label_desc->add_constant_override("shadow_as_outline", 1 * EDSCALE);
6289 	label_desc->add_constant_override("line_spacing", 0);
6290 	label_desc->hide();
6291 	canvas_item_editor->get_controls_container()->add_child(label_desc);
6292 
6293 	VS::get_singleton()->canvas_set_disable_scale(true);
6294 }
6295 
~CanvasItemEditorViewport()6296 CanvasItemEditorViewport::~CanvasItemEditorViewport() {
6297 	memdelete(preview_node);
6298 }
6299