1 /*************************************************************************/
2 /*  canvas_item_editor_plugin.h                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2019 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 #ifndef CONTROL_EDITOR_PLUGIN_H
31 #define CONTROL_EDITOR_PLUGIN_H
32 
33 #include "editor/editor_node.h"
34 #include "editor/editor_plugin.h"
35 #include "scene/2d/canvas_item.h"
36 #include "scene/gui/box_container.h"
37 #include "scene/gui/button_group.h"
38 #include "scene/gui/check_box.h"
39 #include "scene/gui/label.h"
40 #include "scene/gui/panel_container.h"
41 #include "scene/gui/spin_box.h"
42 /**
43 	@author Juan Linietsky <reduzio@gmail.com>
44 */
45 
46 class CanvasItemEditorViewport;
47 
48 class CanvasItemEditorSelectedItem : public Object {
49 
50 	OBJ_TYPE(CanvasItemEditorSelectedItem, Object);
51 
52 public:
53 	Variant undo_state;
54 	Vector2 undo_pivot;
55 
56 	Matrix32 prev_xform;
57 	float prev_rot;
58 	Rect2 prev_rect;
59 
CanvasItemEditorSelectedItem()60 	CanvasItemEditorSelectedItem() { prev_rot = 0; }
61 };
62 
63 class CanvasItemEditor : public VBoxContainer {
64 
65 	OBJ_TYPE(CanvasItemEditor, VBoxContainer);
66 
67 	EditorNode *editor;
68 
69 	enum Tool {
70 
71 		TOOL_SELECT,
72 		TOOL_LIST_SELECT,
73 		TOOL_MOVE,
74 		TOOL_ROTATE,
75 		TOOL_EDIT_PIVOT,
76 		TOOL_PAN,
77 		TOOL_MAX
78 	};
79 
80 	enum MenuOption {
81 		SNAP_USE,
82 		SNAP_SHOW_GRID,
83 		SNAP_USE_ROTATION,
84 		SNAP_RELATIVE,
85 		SNAP_CONFIGURE,
86 		SNAP_USE_PIXEL,
87 		ZOOM_IN,
88 		ZOOM_OUT,
89 		ZOOM_RESET,
90 		ZOOM_SET,
91 		LOCK_SELECTED,
92 		UNLOCK_SELECTED,
93 		GROUP_SELECTED,
94 		UNGROUP_SELECTED,
95 		ALIGN_HORIZONTAL,
96 		ALIGN_VERTICAL,
97 		ANCHOR_ALIGN_TOP_LEFT,
98 		ANCHOR_ALIGN_TOP_RIGHT,
99 		ANCHOR_ALIGN_BOTTOM_LEFT,
100 		ANCHOR_ALIGN_BOTTOM_RIGHT,
101 		ANCHOR_ALIGN_CENTER_LEFT,
102 		ANCHOR_ALIGN_CENTER_RIGHT,
103 		ANCHOR_ALIGN_CENTER_TOP,
104 		ANCHOR_ALIGN_CENTER_BOTTOM,
105 		ANCHOR_ALIGN_CENTER,
106 		ANCHOR_ALIGN_TOP_WIDE,
107 		ANCHOR_ALIGN_LEFT_WIDE,
108 		ANCHOR_ALIGN_RIGHT_WIDE,
109 		ANCHOR_ALIGN_BOTTOM_WIDE,
110 		ANCHOR_ALIGN_VCENTER_WIDE,
111 		ANCHOR_ALIGN_HCENTER_WIDE,
112 		ANCHOR_ALIGN_WIDE,
113 
114 		SPACE_HORIZONTAL,
115 		SPACE_VERTICAL,
116 		EXPAND_TO_PARENT,
117 		ANIM_INSERT_KEY,
118 		ANIM_INSERT_KEY_EXISTING,
119 		ANIM_INSERT_POS,
120 		ANIM_INSERT_ROT,
121 		ANIM_INSERT_SCALE,
122 		ANIM_COPY_POSE,
123 		ANIM_PASTE_POSE,
124 		ANIM_CLEAR_POSE,
125 		VIEW_CENTER_TO_SELECTION,
126 		VIEW_FRAME_TO_SELECTION,
127 		SKELETON_MAKE_BONES,
128 		SKELETON_CLEAR_BONES,
129 		SKELETON_SET_IK_CHAIN,
130 		SKELETON_CLEAR_IK_CHAIN
131 
132 	};
133 
134 	enum DragType {
135 		DRAG_NONE,
136 		DRAG_LEFT,
137 		DRAG_TOP_LEFT,
138 		DRAG_TOP,
139 		DRAG_TOP_RIGHT,
140 		DRAG_RIGHT,
141 		DRAG_BOTTOM_RIGHT,
142 		DRAG_BOTTOM,
143 		DRAG_BOTTOM_LEFT,
144 		DRAG_ALL,
145 		DRAG_ROTATE,
146 		DRAG_PIVOT,
147 		DRAG_NODE_2D,
148 
149 	};
150 
151 	enum KeyMoveMODE {
152 		MOVE_VIEW_BASE,
153 		MOVE_LOCAL_BASE,
154 		MOVE_LOCAL_WITH_ROT
155 	};
156 
157 	EditorSelection *editor_selection;
158 	bool additive_selection;
159 
160 	Tool tool;
161 	bool first_update;
162 	Control *viewport;
163 
164 	bool can_move_pivot;
165 
166 	HScrollBar *h_scroll;
167 	VScrollBar *v_scroll;
168 	HBoxContainer *hb;
169 
170 	Matrix32 transform;
171 	float zoom;
172 	Vector2 snap_offset;
173 	Vector2 snap_step;
174 	float snap_rotation_step;
175 	float snap_rotation_offset;
176 	bool snap_grid;
177 	bool snap_show_grid;
178 	bool snap_rotation;
179 	bool snap_relative;
180 	bool snap_pixel;
181 	bool box_selecting;
182 	Point2 box_selecting_to;
183 	bool key_pos;
184 	bool key_rot;
185 	bool key_scale;
186 
187 	void _tool_select(int p_index);
188 
189 	MenuOption last_option;
190 
191 	struct _SelectResult {
192 
193 		CanvasItem *item;
194 		float z;
195 		bool has_z;
196 		_FORCE_INLINE_ bool operator<(const _SelectResult &p_rr) const {
197 			return has_z && p_rr.has_z ? p_rr.z < z : p_rr.has_z;
198 		}
199 	};
200 
201 	Vector<_SelectResult> selection_results;
202 
203 	struct LockList {
204 		Point2 pos;
205 		bool lock;
206 		bool group;
LockListLockList207 		LockList() {
208 			lock = false;
209 			group = false;
210 		}
211 	};
212 
213 	List<LockList> lock_list;
214 
215 	struct BoneList {
216 
217 		Matrix32 xform;
218 		Vector2 from;
219 		Vector2 to;
220 		ObjectID bone;
221 		uint64_t last_pass;
222 	};
223 
224 	uint64_t bone_last_frame;
225 	Map<ObjectID, BoneList> bone_list;
226 
227 	Matrix32 bone_orig_xform;
228 
229 	struct BoneIK {
230 
231 		Variant orig_state;
232 		Vector2 pos;
233 		float len;
234 		Node2D *node;
235 	};
236 
237 	List<BoneIK> bone_ik_list;
238 
239 	struct PoseClipboard {
240 
241 		Vector2 pos;
242 		Vector2 scale;
243 		float rot;
244 		ObjectID id;
245 	};
246 
247 	List<PoseClipboard> pose_clipboard;
248 
249 	ToolButton *select_button;
250 	ToolButton *list_select_button;
251 	ToolButton *move_button;
252 	ToolButton *rotate_button;
253 
254 	ToolButton *pivot_button;
255 	ToolButton *pan_button;
256 
257 	ToolButton *lock_button;
258 	ToolButton *unlock_button;
259 
260 	ToolButton *group_button;
261 	ToolButton *ungroup_button;
262 
263 	MenuButton *edit_menu;
264 	MenuButton *view_menu;
265 	HBoxContainer *animation_hb;
266 	MenuButton *animation_menu;
267 	MenuButton *anchor_menu;
268 
269 	Button *key_loc_button;
270 	Button *key_rot_button;
271 	Button *key_scale_button;
272 	Button *key_insert_button;
273 
274 	PopupMenu *selection_menu;
275 
276 	//PopupMenu *popup;
277 	DragType drag;
278 	Point2 drag_from;
279 	Point2 drag_point_from;
280 	bool updating_value_dialog;
281 	Point2 display_rotate_from;
282 	Point2 display_rotate_to;
283 #if 0
284 	struct EditInfo {
285 
286 		Variant undo_state;
287 
288 		Matrix32 prev_xform;
289 		float prev_rot;
290 		Rect2 prev_rect;
291 		EditInfo() { prev_rot=0; }
292 	};
293 
294 	typedef Map<CanvasItem*,EditInfo> CanvasItemMap;
295 	CanvasItemMap canvas_items;
296 #endif
297 	Ref<StyleBoxTexture> select_sb;
298 	Ref<Texture> select_handle;
299 
300 	int handle_len;
301 	bool _is_part_of_subscene(CanvasItem *p_item);
302 	CanvasItem *_select_canvas_item_at_pos(const Point2 &p_pos, Node *p_node, const Matrix32 &p_parent_xform, const Matrix32 &p_canvas_xform);
303 	void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Matrix32 &p_parent_xform, const Matrix32 &p_canvas_xform, Vector<_SelectResult> &r_items);
304 	void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, const Matrix32 &p_parent_xform, const Matrix32 &p_canvas_xform, List<CanvasItem *> *r_items);
305 
306 	bool _select(CanvasItem *item, Point2 p_click_pos, bool p_append, bool p_drag = true);
307 
308 	ConfirmationDialog *snap_dialog;
309 
310 	AcceptDialog *value_dialog;
311 	Label *dialog_label;
312 	SpinBox *dialog_val;
313 
314 	CanvasItem *ref_item;
315 
316 	void _edit_set_pivot(const Vector2 &mouse_pos);
317 	void _add_canvas_item(CanvasItem *p_canvas_item);
318 	void _remove_canvas_item(CanvasItem *p_canvas_item);
319 	void _clear_canvas_items();
320 	void _visibility_changed(ObjectID p_canvas_item);
321 	void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode);
322 	void _list_select(const InputEventMouseButton &b);
323 
324 	DragType _find_drag_type(const Matrix32 &p_xform, const Rect2 &p_local_rect, const Point2 &p_click, Vector2 &r_point);
325 	void _prepare_drag(const Point2 &p_click_pos);
326 
327 	void _popup_callback(int p_op);
328 	bool updating_scroll;
329 	void _update_scroll(float);
330 	void _update_scrollbars();
331 	void incbeg(float &beg, float &end, float inc, float minsize, bool p_symmetric);
332 	void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric);
333 
334 	void _append_canvas_item(CanvasItem *p_item);
335 	void _dialog_value_changed(double);
336 	void _snap_changed();
337 	void _selection_result_pressed(int);
338 	void _selection_menu_hide();
339 
340 	UndoRedo *undo_redo;
341 
342 	Point2 _find_topleftmost_point();
343 
344 	void _find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Matrix32 &p_xform);
345 
346 	Object *_get_editor_data(Object *p_what);
347 
348 	CanvasItem *get_single_item();
349 	int get_item_count();
350 	void _keying_changed();
351 
352 	void _unhandled_key_input(const InputEvent &p_ev);
353 
354 	void _viewport_input_event(const InputEvent &p_event);
355 	void _viewport_draw();
356 
357 	void _set_anchor(Control::AnchorType p_left, Control::AnchorType p_top, Control::AnchorType p_right, Control::AnchorType p_bottom);
358 
359 	HSplitContainer *palette_split;
360 	VSplitContainer *bottom_split;
361 
362 	friend class CanvasItemEditorPlugin;
363 
364 protected:
365 	void _notification(int p_what);
366 
367 	void _node_removed(Node *p_node);
368 	static void _bind_methods();
369 	void end_drag();
370 	void box_selection_start(Point2 &click);
371 	bool box_selection_end();
372 
get_panel_hb()373 	HBoxContainer *get_panel_hb() { return hb; }
374 
375 	struct compare_items_x {
operatorcompare_items_x376 		bool operator()(const CanvasItem *a, const CanvasItem *b) const {
377 			return a->get_global_transform().elements[2].x < b->get_global_transform().elements[2].x;
378 		}
379 	};
380 
381 	struct compare_items_y {
operatorcompare_items_y382 		bool operator()(const CanvasItem *a, const CanvasItem *b) const {
383 			return a->get_global_transform().elements[2].y < b->get_global_transform().elements[2].y;
384 		}
385 	};
386 
387 	struct proj_vector2_x {
getproj_vector2_x388 		float get(const Vector2 &v) { return v.x; }
setproj_vector2_x389 		void set(Vector2 &v, float f) { v.x = f; }
390 	};
391 
392 	struct proj_vector2_y {
getproj_vector2_y393 		float get(const Vector2 &v) { return v.y; }
setproj_vector2_y394 		void set(Vector2 &v, float f) { v.y = f; }
395 	};
396 
397 	template <class P, class C>
398 	void space_selected_items();
399 
400 	static CanvasItemEditor *singleton;
401 
402 public:
403 	Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
404 	float snap_angle(float p_target, float p_start = 0) const;
405 
get_canvas_transform()406 	Matrix32 get_canvas_transform() const { return transform; }
407 
get_singleton()408 	static CanvasItemEditor *get_singleton() { return singleton; }
409 	Dictionary get_state() const;
410 	void set_state(const Dictionary &p_state);
411 
412 	void add_control_to_menu_panel(Control *p_control);
413 
414 	HSplitContainer *get_palette_split();
415 	VSplitContainer *get_bottom_split();
416 
get_viewport_control()417 	Control *get_viewport_control() { return viewport; }
418 
419 	bool get_remove_list(List<Node *> *p_list);
set_undo_redo(UndoRedo * p_undo_redo)420 	void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; }
421 	void edit(CanvasItem *p_canvas_item);
422 	CanvasItemEditor(EditorNode *p_editor);
423 };
424 
425 class CanvasItemEditorPlugin : public EditorPlugin {
426 
427 	OBJ_TYPE(CanvasItemEditorPlugin, EditorPlugin);
428 
429 	CanvasItemEditor *canvas_item_editor;
430 	EditorNode *editor;
431 
432 public:
get_name()433 	virtual String get_name() const { return "2D"; }
has_main_screen()434 	bool has_main_screen() const { return true; }
435 	virtual void edit(Object *p_object);
436 	virtual bool handles(Object *p_object) const;
437 	virtual void make_visible(bool p_visible);
get_remove_list(List<Node * > * p_list)438 	virtual bool get_remove_list(List<Node *> *p_list) { return canvas_item_editor->get_remove_list(p_list); }
439 	virtual Dictionary get_state() const;
440 	virtual void set_state(const Dictionary &p_state);
441 
get_canvas_item_editor()442 	CanvasItemEditor *get_canvas_item_editor() { return canvas_item_editor; }
443 
444 	CanvasItemEditorPlugin(EditorNode *p_node);
445 	~CanvasItemEditorPlugin();
446 };
447 
448 class CanvasItemEditorViewport : public Control {
449 	OBJ_TYPE(CanvasItemEditorViewport, Control);
450 
451 	String default_type;
452 	Vector<String> types;
453 
454 	Vector<String> selected_files;
455 	Node *target_node;
456 	Point2 drop_pos;
457 
458 	EditorNode *editor;
459 	EditorData *editor_data;
460 	CanvasItemEditor *canvas;
461 	Node2D *preview;
462 	AcceptDialog *accept;
463 	WindowDialog *selector;
464 	Label *selector_label;
465 	Label *label;
466 	Label *label_desc;
467 	ButtonGroup *btn_group;
468 
469 	void _on_mouse_exit();
470 	void _on_select_type(Object *selected);
471 	void _on_change_type();
472 
473 	void _create_preview(const Vector<String> &files) const;
474 	void _remove_preview();
475 
476 	bool _cyclical_dependency_exists(const String &p_target_scene_path, Node *p_desired_node);
477 	void _create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point);
478 	bool _create_instance(Node *parent, String &path, const Point2 &p_point);
479 	void _perform_drop_data();
480 
481 	static void _bind_methods();
482 
483 protected:
484 	void _notification(int p_what);
485 
486 public:
487 	virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
488 	virtual void drop_data(const Point2 &p_point, const Variant &p_data);
489 
490 	CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas);
491 };
492 
493 #endif
494