1 /*************************************************************************/
2 /*  canvas_item.cpp                                                      */
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 #include "canvas_item.h"
31 #include "message_queue.h"
32 #include "os/input.h"
33 #include "scene/main/canvas_layer.h"
34 #include "scene/main/viewport.h"
35 #include "scene/resources/font.h"
36 #include "scene/resources/style_box.h"
37 #include "scene/resources/texture.h"
38 #include "scene/scene_string_names.h"
39 #include "servers/visual_server.h"
40 
_set(const StringName & p_name,const Variant & p_value)41 bool CanvasItemMaterial::_set(const StringName &p_name, const Variant &p_value) {
42 
43 	if (p_name == SceneStringNames::get_singleton()->shader_shader) {
44 		set_shader(p_value);
45 		return true;
46 	} else if (p_name == SceneStringNames::get_singleton()->shading_mode) {
47 		set_shading_mode(ShadingMode(p_value.operator int()));
48 		return true;
49 	} else {
50 
51 		if (shader.is_valid()) {
52 
53 			StringName pr = shader->remap_param(p_name);
54 			if (!pr) {
55 				String n = p_name;
56 				if (n.find("param/") == 0) { //backwards compatibility
57 					pr = n.substr(6, n.length());
58 				}
59 			}
60 			if (pr) {
61 				VisualServer::get_singleton()->canvas_item_material_set_shader_param(material, pr, p_value);
62 				return true;
63 			}
64 		}
65 	}
66 
67 	return false;
68 }
69 
_get(const StringName & p_name,Variant & r_ret) const70 bool CanvasItemMaterial::_get(const StringName &p_name, Variant &r_ret) const {
71 
72 	if (p_name == SceneStringNames::get_singleton()->shader_shader) {
73 
74 		r_ret = get_shader();
75 		return true;
76 	} else if (p_name == SceneStringNames::get_singleton()->shading_mode) {
77 
78 		r_ret = shading_mode;
79 		return true;
80 	} else {
81 
82 		if (shader.is_valid()) {
83 
84 			StringName pr = shader->remap_param(p_name);
85 			if (pr) {
86 				r_ret = VisualServer::get_singleton()->canvas_item_material_get_shader_param(material, pr);
87 				return true;
88 			}
89 		}
90 	}
91 
92 	return false;
93 }
94 
_get_property_list(List<PropertyInfo> * p_list) const95 void CanvasItemMaterial::_get_property_list(List<PropertyInfo> *p_list) const {
96 
97 	p_list->push_back(PropertyInfo(Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"));
98 	p_list->push_back(PropertyInfo(Variant::INT, "shader/shading_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"));
99 
100 	if (!shader.is_null()) {
101 
102 		shader->get_param_list(p_list);
103 	}
104 }
105 
set_shader(const Ref<Shader> & p_shader)106 void CanvasItemMaterial::set_shader(const Ref<Shader> &p_shader) {
107 
108 	ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode() != Shader::MODE_CANVAS_ITEM);
109 
110 	shader = p_shader;
111 
112 	RID rid;
113 	if (shader.is_valid())
114 		rid = shader->get_rid();
115 
116 	VS::get_singleton()->canvas_item_material_set_shader(material, rid);
117 	_change_notify(); //properties for shader exposed
118 	emit_changed();
119 }
120 
get_shader() const121 Ref<Shader> CanvasItemMaterial::get_shader() const {
122 
123 	return shader;
124 }
125 
set_shader_param(const StringName & p_param,const Variant & p_value)126 void CanvasItemMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) {
127 
128 	VS::get_singleton()->canvas_item_material_set_shader_param(material, p_param, p_value);
129 }
130 
get_shader_param(const StringName & p_param) const131 Variant CanvasItemMaterial::get_shader_param(const StringName &p_param) const {
132 
133 	return VS::get_singleton()->canvas_item_material_get_shader_param(material, p_param);
134 }
135 
get_rid() const136 RID CanvasItemMaterial::get_rid() const {
137 
138 	return material;
139 }
140 
set_shading_mode(ShadingMode p_mode)141 void CanvasItemMaterial::set_shading_mode(ShadingMode p_mode) {
142 
143 	shading_mode = p_mode;
144 	VS::get_singleton()->canvas_item_material_set_shading_mode(material, VS::CanvasItemShadingMode(p_mode));
145 }
146 
get_shading_mode() const147 CanvasItemMaterial::ShadingMode CanvasItemMaterial::get_shading_mode() const {
148 	return shading_mode;
149 }
150 
_bind_methods()151 void CanvasItemMaterial::_bind_methods() {
152 
153 	ObjectTypeDB::bind_method(_MD("set_shader", "shader:Shader"), &CanvasItemMaterial::set_shader);
154 	ObjectTypeDB::bind_method(_MD("get_shader:Shader"), &CanvasItemMaterial::get_shader);
155 	ObjectTypeDB::bind_method(_MD("set_shader_param", "param", "value"), &CanvasItemMaterial::set_shader_param);
156 	ObjectTypeDB::bind_method(_MD("get_shader_param", "param"), &CanvasItemMaterial::get_shader_param);
157 	ObjectTypeDB::bind_method(_MD("set_shading_mode", "mode"), &CanvasItemMaterial::set_shading_mode);
158 	ObjectTypeDB::bind_method(_MD("get_shading_mode"), &CanvasItemMaterial::get_shading_mode);
159 
160 	BIND_CONSTANT(SHADING_NORMAL);
161 	BIND_CONSTANT(SHADING_UNSHADED);
162 	BIND_CONSTANT(SHADING_ONLY_LIGHT);
163 }
164 
get_argument_options(const StringName & p_function,int p_idx,List<String> * r_options) const165 void CanvasItemMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
166 
167 	String f = p_function.operator String();
168 	if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) {
169 
170 		if (shader.is_valid()) {
171 			List<PropertyInfo> pl;
172 			shader->get_param_list(&pl);
173 			for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) {
174 				r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\"");
175 			}
176 		}
177 	}
178 	Resource::get_argument_options(p_function, p_idx, r_options);
179 }
180 
CanvasItemMaterial()181 CanvasItemMaterial::CanvasItemMaterial() {
182 
183 	material = VS::get_singleton()->canvas_item_material_create();
184 	shading_mode = SHADING_NORMAL;
185 }
186 
~CanvasItemMaterial()187 CanvasItemMaterial::~CanvasItemMaterial() {
188 
189 	VS::get_singleton()->free(material);
190 }
191 
192 ///////////////////////////////////////////////////////////////////
193 
is_visible() const194 bool CanvasItem::is_visible() const {
195 
196 	if (!is_inside_tree())
197 		return false;
198 
199 	const CanvasItem *p = this;
200 
201 	while (p) {
202 		if (p->hidden)
203 			return false;
204 		p = p->get_parent_item();
205 	}
206 
207 	return true;
208 }
209 
is_hidden() const210 bool CanvasItem::is_hidden() const {
211 
212 	/*if (!is_inside_scene())
213 		return false;*/
214 
215 	return hidden;
216 }
217 
_propagate_visibility_changed(bool p_visible)218 void CanvasItem::_propagate_visibility_changed(bool p_visible) {
219 
220 	notification(NOTIFICATION_VISIBILITY_CHANGED);
221 
222 	if (p_visible)
223 		update(); //todo optimize
224 	else
225 		emit_signal(SceneStringNames::get_singleton()->hide);
226 	_block();
227 
228 	for (int i = 0; i < get_child_count(); i++) {
229 
230 		CanvasItem *c = get_child(i)->cast_to<CanvasItem>();
231 
232 		if (c && !c->hidden) //should the toplevels stop propagation? i think so but..
233 			c->_propagate_visibility_changed(p_visible);
234 	}
235 
236 	_unblock();
237 }
238 
show()239 void CanvasItem::show() {
240 
241 	if (!hidden)
242 		return;
243 
244 	hidden = false;
245 	VisualServer::get_singleton()->canvas_item_set_visible(canvas_item, true);
246 
247 	if (!is_inside_tree())
248 		return;
249 
250 	_propagate_visibility_changed(true);
251 	_change_notify("visibility/visible");
252 }
253 
hide()254 void CanvasItem::hide() {
255 
256 	if (hidden)
257 		return;
258 
259 	hidden = true;
260 	VisualServer::get_singleton()->canvas_item_set_visible(canvas_item, false);
261 
262 	if (!is_inside_tree())
263 		return;
264 
265 	_propagate_visibility_changed(false);
266 	_change_notify("visibility/visible");
267 }
268 
set_hidden(bool p_hidden)269 void CanvasItem::set_hidden(bool p_hidden) {
270 
271 	if (hidden == p_hidden) {
272 		return;
273 	}
274 
275 	_set_visible_(!p_hidden);
276 }
277 
edit_get_state() const278 Variant CanvasItem::edit_get_state() const {
279 
280 	return Variant();
281 }
edit_set_state(const Variant & p_state)282 void CanvasItem::edit_set_state(const Variant &p_state) {
283 }
284 
edit_set_rect(const Rect2 & p_edit_rect)285 void CanvasItem::edit_set_rect(const Rect2 &p_edit_rect) {
286 
287 	//used by editors, implement at will
288 }
289 
edit_rotate(float p_rot)290 void CanvasItem::edit_rotate(float p_rot) {
291 }
292 
edit_get_minimum_size() const293 Size2 CanvasItem::edit_get_minimum_size() const {
294 
295 	return Size2(-1, -1); //no limit
296 }
297 
_update_callback()298 void CanvasItem::_update_callback() {
299 
300 	if (!is_inside_tree()) {
301 		pending_update = false;
302 		return;
303 	}
304 
305 	VisualServer::get_singleton()->canvas_item_clear(get_canvas_item());
306 	//todo updating = true - only allow drawing here
307 	if (is_visible()) { //todo optimize this!!
308 		if (first_draw) {
309 			notification(NOTIFICATION_VISIBILITY_CHANGED);
310 			first_draw = false;
311 		}
312 		drawing = true;
313 		notification(NOTIFICATION_DRAW);
314 		emit_signal(SceneStringNames::get_singleton()->draw);
315 		if (get_script_instance()) {
316 			Variant::CallError err;
317 			get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_draw, NULL, 0);
318 		}
319 		drawing = false;
320 	}
321 	//todo updating = false
322 	pending_update = false; // don't change to false until finished drawing (avoid recursive update)
323 }
324 
get_global_transform_with_canvas() const325 Matrix32 CanvasItem::get_global_transform_with_canvas() const {
326 
327 	const CanvasItem *ci = this;
328 	Matrix32 xform;
329 	const CanvasItem *last_valid = NULL;
330 
331 	while (ci) {
332 
333 		last_valid = ci;
334 		xform = ci->get_transform() * xform;
335 		ci = ci->get_parent_item();
336 	}
337 
338 	if (last_valid->canvas_layer)
339 		return last_valid->canvas_layer->get_transform() * xform;
340 	else if (is_inside_tree())
341 		return get_viewport()->get_canvas_transform() * xform;
342 
343 	return xform;
344 }
345 
get_global_transform() const346 Matrix32 CanvasItem::get_global_transform() const {
347 
348 	if (global_invalid) {
349 
350 		const CanvasItem *pi = get_parent_item();
351 		if (pi)
352 			global_transform = pi->get_global_transform() * get_transform();
353 		else
354 			global_transform = get_transform();
355 
356 		global_invalid = false;
357 	}
358 
359 	return global_transform;
360 }
361 
_queue_sort_children()362 void CanvasItem::_queue_sort_children() {
363 
364 	if (pending_children_sort)
365 		return;
366 
367 	pending_children_sort = true;
368 	MessageQueue::get_singleton()->push_call(this, "_sort_children");
369 }
370 
_sort_children()371 void CanvasItem::_sort_children() {
372 
373 	pending_children_sort = false;
374 
375 	if (!is_inside_tree())
376 		return;
377 
378 	for (int i = 0; i < get_child_count(); i++) {
379 
380 		Node *n = get_child(i);
381 		CanvasItem *ci = n->cast_to<CanvasItem>();
382 
383 		if (ci) {
384 			if (ci->toplevel || ci->group != "")
385 				continue;
386 			VisualServer::get_singleton()->canvas_item_raise(n->cast_to<CanvasItem>()->canvas_item);
387 		}
388 	}
389 }
390 
_raise_self()391 void CanvasItem::_raise_self() {
392 
393 	if (!is_inside_tree())
394 		return;
395 
396 	VisualServer::get_singleton()->canvas_item_raise(canvas_item);
397 }
398 
_enter_canvas()399 void CanvasItem::_enter_canvas() {
400 
401 	if ((!get_parent() || !get_parent()->cast_to<CanvasItem>()) || toplevel) {
402 
403 		Node *n = this;
404 
405 		canvas_layer = NULL;
406 
407 		while (n) {
408 
409 			canvas_layer = n->cast_to<CanvasLayer>();
410 			if (canvas_layer) {
411 				break;
412 			}
413 			n = n->get_parent();
414 		}
415 
416 		RID canvas;
417 		if (canvas_layer)
418 			canvas = canvas_layer->get_world_2d()->get_canvas();
419 		else
420 			canvas = get_viewport()->find_world_2d()->get_canvas();
421 
422 		VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas);
423 
424 		group = "root_canvas" + itos(canvas.get_id());
425 
426 		add_to_group(group);
427 		get_tree()->call_group(SceneTree::GROUP_CALL_UNIQUE, group, "_raise_self");
428 
429 	} else {
430 
431 		CanvasItem *parent = get_parent_item();
432 		canvas_layer = parent->canvas_layer;
433 		VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item());
434 		parent->_queue_sort_children();
435 	}
436 
437 	pending_update = false;
438 	update();
439 
440 	notification(NOTIFICATION_ENTER_CANVAS);
441 }
442 
_exit_canvas()443 void CanvasItem::_exit_canvas() {
444 
445 	notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification
446 	VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, RID());
447 	canvas_layer = NULL;
448 	group = "";
449 }
450 
_notification(int p_what)451 void CanvasItem::_notification(int p_what) {
452 
453 	switch (p_what) {
454 		case NOTIFICATION_ENTER_TREE: {
455 
456 			first_draw = true;
457 			pending_children_sort = false;
458 			if (get_parent()) {
459 				CanvasItem *ci = get_parent()->cast_to<CanvasItem>();
460 				if (ci)
461 					C = ci->children_items.push_back(this);
462 			}
463 			_enter_canvas();
464 			if (!block_transform_notify && !xform_change.in_list()) {
465 				get_tree()->xform_change_list.add(&xform_change);
466 			}
467 		} break;
468 		case NOTIFICATION_MOVED_IN_PARENT: {
469 
470 			if (group != "") {
471 				get_tree()->call_group(SceneTree::GROUP_CALL_UNIQUE, group, "_raise_self");
472 			} else {
473 				CanvasItem *p = get_parent_item();
474 				ERR_FAIL_COND(!p);
475 				p->_queue_sort_children();
476 			}
477 
478 		} break;
479 		case NOTIFICATION_EXIT_TREE: {
480 			if (xform_change.in_list())
481 				get_tree()->xform_change_list.remove(&xform_change);
482 			_exit_canvas();
483 			if (C) {
484 				get_parent()->cast_to<CanvasItem>()->children_items.erase(C);
485 				C = NULL;
486 			}
487 			global_invalid = true;
488 		} break;
489 		case NOTIFICATION_DRAW: {
490 
491 		} break;
492 		case NOTIFICATION_TRANSFORM_CHANGED: {
493 
494 		} break;
495 		case NOTIFICATION_VISIBILITY_CHANGED: {
496 
497 			emit_signal(SceneStringNames::get_singleton()->visibility_changed);
498 		} break;
499 	}
500 }
501 
_set_visible_(bool p_visible)502 void CanvasItem::_set_visible_(bool p_visible) {
503 
504 	if (p_visible)
505 		show();
506 	else
507 		hide();
508 }
_is_visible_() const509 bool CanvasItem::_is_visible_() const {
510 
511 	return !is_hidden();
512 }
513 
update()514 void CanvasItem::update() {
515 
516 	if (!is_inside_tree())
517 		return;
518 	if (pending_update)
519 		return;
520 
521 	pending_update = true;
522 
523 	MessageQueue::get_singleton()->push_call(this, "_update_callback");
524 }
525 
set_opacity(float p_opacity)526 void CanvasItem::set_opacity(float p_opacity) {
527 
528 	opacity = p_opacity;
529 	VisualServer::get_singleton()->canvas_item_set_opacity(canvas_item, opacity);
530 }
get_opacity() const531 float CanvasItem::get_opacity() const {
532 
533 	return opacity;
534 }
535 
set_as_toplevel(bool p_toplevel)536 void CanvasItem::set_as_toplevel(bool p_toplevel) {
537 
538 	if (toplevel == p_toplevel)
539 		return;
540 
541 	if (!is_inside_tree()) {
542 		toplevel = p_toplevel;
543 		return;
544 	}
545 
546 	_exit_canvas();
547 	toplevel = p_toplevel;
548 	_enter_canvas();
549 }
550 
is_set_as_toplevel() const551 bool CanvasItem::is_set_as_toplevel() const {
552 
553 	return toplevel;
554 }
555 
get_parent_item() const556 CanvasItem *CanvasItem::get_parent_item() const {
557 
558 	if (toplevel)
559 		return NULL;
560 
561 	Node *parent = get_parent();
562 	if (!parent)
563 		return NULL;
564 
565 	return parent->cast_to<CanvasItem>();
566 }
567 
set_self_opacity(float p_self_opacity)568 void CanvasItem::set_self_opacity(float p_self_opacity) {
569 
570 	self_opacity = p_self_opacity;
571 	VisualServer::get_singleton()->canvas_item_set_self_opacity(canvas_item, self_opacity);
572 }
get_self_opacity() const573 float CanvasItem::get_self_opacity() const {
574 
575 	return self_opacity;
576 }
577 
set_blend_mode(BlendMode p_blend_mode)578 void CanvasItem::set_blend_mode(BlendMode p_blend_mode) {
579 
580 	ERR_FAIL_INDEX(p_blend_mode, 5);
581 	blend_mode = p_blend_mode;
582 	VisualServer::get_singleton()->canvas_item_set_blend_mode(canvas_item, VS::MaterialBlendMode(blend_mode));
583 }
584 
get_blend_mode() const585 CanvasItem::BlendMode CanvasItem::get_blend_mode() const {
586 
587 	return blend_mode;
588 }
589 
set_light_mask(int p_light_mask)590 void CanvasItem::set_light_mask(int p_light_mask) {
591 
592 	light_mask = p_light_mask;
593 	VS::get_singleton()->canvas_item_set_light_mask(canvas_item, p_light_mask);
594 }
595 
get_light_mask() const596 int CanvasItem::get_light_mask() const {
597 
598 	return light_mask;
599 }
600 
item_rect_changed()601 void CanvasItem::item_rect_changed() {
602 
603 	update();
604 	emit_signal(SceneStringNames::get_singleton()->item_rect_changed);
605 }
606 
draw_line(const Point2 & p_from,const Point2 & p_to,const Color & p_color,float p_width)607 void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) {
608 
609 	if (!drawing) {
610 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
611 		ERR_FAIL();
612 	}
613 
614 	VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
615 }
616 
draw_rect(const Rect2 & p_rect,const Color & p_color)617 void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color) {
618 
619 	if (!drawing) {
620 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
621 		ERR_FAIL();
622 	}
623 
624 	VisualServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color);
625 }
626 
draw_circle(const Point2 & p_pos,float p_radius,const Color & p_color)627 void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p_color) {
628 
629 	if (!drawing) {
630 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
631 		ERR_FAIL();
632 	}
633 
634 	VisualServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color);
635 }
636 
draw_texture(const Ref<Texture> & p_texture,const Point2 & p_pos,const Color & p_modulate)637 void CanvasItem::draw_texture(const Ref<Texture> &p_texture, const Point2 &p_pos, const Color &p_modulate) {
638 
639 	if (!drawing) {
640 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
641 		ERR_FAIL();
642 	}
643 
644 	ERR_FAIL_COND(p_texture.is_null());
645 
646 	p_texture->draw(canvas_item, p_pos, p_modulate);
647 }
648 
draw_texture_rect(const Ref<Texture> & p_texture,const Rect2 & p_rect,bool p_tile,const Color & p_modulate,bool p_transpose)649 void CanvasItem::draw_texture_rect(const Ref<Texture> &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) {
650 
651 	if (!drawing) {
652 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
653 		ERR_FAIL();
654 	}
655 
656 	ERR_FAIL_COND(p_texture.is_null());
657 	p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose);
658 }
draw_texture_rect_region(const Ref<Texture> & p_texture,const Rect2 & p_rect,const Rect2 & p_src_rect,const Color & p_modulate,bool p_transpose)659 void CanvasItem::draw_texture_rect_region(const Ref<Texture> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) {
660 
661 	if (!drawing) {
662 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
663 		ERR_FAIL();
664 	}
665 	ERR_FAIL_COND(p_texture.is_null());
666 	p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose);
667 }
668 
draw_style_box(const Ref<StyleBox> & p_style_box,const Rect2 & p_rect)669 void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) {
670 	if (!drawing) {
671 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
672 		ERR_FAIL();
673 	}
674 
675 	ERR_FAIL_COND(p_style_box.is_null());
676 
677 	p_style_box->draw(canvas_item, p_rect);
678 }
draw_primitive(const Vector<Point2> & p_points,const Vector<Color> & p_colors,const Vector<Point2> & p_uvs,Ref<Texture> p_texture,float p_width)679 void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture, float p_width) {
680 
681 	if (!drawing) {
682 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
683 		ERR_FAIL();
684 	}
685 
686 	RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
687 
688 	VisualServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width);
689 }
draw_set_transform(const Point2 & p_offset,float p_rot,const Size2 & p_scale)690 void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale) {
691 
692 	if (!drawing) {
693 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
694 		ERR_FAIL();
695 	}
696 
697 	Matrix32 xform(p_rot, p_offset);
698 	xform.scale_basis(p_scale);
699 	VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item, xform);
700 }
701 
draw_set_transform_matrix(const Matrix32 & p_matrix)702 void CanvasItem::draw_set_transform_matrix(const Matrix32 &p_matrix) {
703 
704 	if (!drawing) {
705 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
706 		ERR_FAIL();
707 	}
708 
709 	VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix);
710 }
711 
draw_polygon(const Vector<Point2> & p_points,const Vector<Color> & p_colors,const Vector<Point2> & p_uvs,Ref<Texture> p_texture)712 void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture> p_texture) {
713 
714 	if (!drawing) {
715 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
716 		ERR_FAIL();
717 	}
718 
719 	RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
720 
721 	VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, rid);
722 }
723 
draw_colored_polygon(const Vector<Point2> & p_points,const Color & p_color,const Vector<Point2> & p_uvs,Ref<Texture> p_texture)724 void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs, Ref<Texture> p_texture) {
725 
726 	if (!drawing) {
727 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
728 		ERR_FAIL();
729 	}
730 
731 	Vector<Color> colors;
732 	colors.push_back(p_color);
733 	RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
734 
735 	VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid);
736 }
737 
draw_string(const Ref<Font> & p_font,const Point2 & p_pos,const String & p_text,const Color & p_modulate,int p_clip_w)738 void CanvasItem::draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate, int p_clip_w) {
739 
740 	if (!drawing) {
741 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
742 		ERR_FAIL();
743 	}
744 
745 	ERR_FAIL_COND(p_font.is_null());
746 	p_font->draw(canvas_item, p_pos, p_text, p_modulate, p_clip_w);
747 }
748 
draw_char(const Ref<Font> & p_font,const Point2 & p_pos,const String & p_char,const String & p_next,const Color & p_modulate)749 float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next, const Color &p_modulate) {
750 
751 	if (!drawing) {
752 		ERR_EXPLAIN("Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
753 		ERR_FAIL_V(0);
754 	}
755 
756 	ERR_FAIL_COND_V(p_char.length() != 1, 0);
757 	ERR_FAIL_COND_V(p_font.is_null(), 0);
758 
759 	return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], p_modulate);
760 }
761 
_notify_transform(CanvasItem * p_node)762 void CanvasItem::_notify_transform(CanvasItem *p_node) {
763 
764 	if (p_node->xform_change.in_list() && p_node->global_invalid)
765 		return; //nothing to do
766 
767 	p_node->global_invalid = true;
768 
769 	if (!p_node->xform_change.in_list()) {
770 		if (!p_node->block_transform_notify) {
771 			if (p_node->is_inside_tree())
772 				get_tree()->xform_change_list.add(&p_node->xform_change);
773 		}
774 	}
775 
776 	for (List<CanvasItem *>::Element *E = p_node->children_items.front(); E; E = E->next()) {
777 
778 		CanvasItem *ci = E->get();
779 		if (ci->toplevel)
780 			continue;
781 		_notify_transform(ci);
782 	}
783 }
784 
get_viewport_rect() const785 Rect2 CanvasItem::get_viewport_rect() const {
786 
787 	ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
788 	return get_viewport()->get_visible_rect();
789 }
790 
get_canvas() const791 RID CanvasItem::get_canvas() const {
792 
793 	ERR_FAIL_COND_V(!is_inside_tree(), RID());
794 
795 	if (canvas_layer)
796 		return canvas_layer->get_world_2d()->get_canvas();
797 	else
798 		return get_viewport()->find_world_2d()->get_canvas();
799 }
800 
get_toplevel() const801 CanvasItem *CanvasItem::get_toplevel() const {
802 
803 	CanvasItem *ci = const_cast<CanvasItem *>(this);
804 	while (!ci->toplevel && ci->get_parent() && ci->get_parent()->cast_to<CanvasItem>()) {
805 		ci = ci->get_parent()->cast_to<CanvasItem>();
806 	}
807 
808 	return ci;
809 }
810 
get_world_2d() const811 Ref<World2D> CanvasItem::get_world_2d() const {
812 
813 	ERR_FAIL_COND_V(!is_inside_tree(), Ref<World2D>());
814 
815 	CanvasItem *tl = get_toplevel();
816 
817 	if (tl->canvas_layer) {
818 		return tl->canvas_layer->get_world_2d();
819 	} else if (tl->get_viewport()) {
820 		return tl->get_viewport()->find_world_2d();
821 	} else {
822 		return Ref<World2D>();
823 	}
824 }
825 
get_viewport_rid() const826 RID CanvasItem::get_viewport_rid() const {
827 
828 	ERR_FAIL_COND_V(!is_inside_tree(), RID());
829 	return get_viewport()->get_viewport();
830 }
831 
set_block_transform_notify(bool p_enable)832 void CanvasItem::set_block_transform_notify(bool p_enable) {
833 	block_transform_notify = p_enable;
834 }
835 
is_block_transform_notify_enabled() const836 bool CanvasItem::is_block_transform_notify_enabled() const {
837 
838 	return block_transform_notify;
839 }
840 
set_draw_behind_parent(bool p_enable)841 void CanvasItem::set_draw_behind_parent(bool p_enable) {
842 
843 	if (behind == p_enable)
844 		return;
845 	behind = p_enable;
846 	VisualServer::get_singleton()->canvas_item_set_on_top(canvas_item, !behind);
847 }
848 
is_draw_behind_parent_enabled() const849 bool CanvasItem::is_draw_behind_parent_enabled() const {
850 
851 	return behind;
852 }
853 
set_material(const Ref<CanvasItemMaterial> & p_material)854 void CanvasItem::set_material(const Ref<CanvasItemMaterial> &p_material) {
855 
856 	material = p_material;
857 	RID rid;
858 	if (material.is_valid())
859 		rid = material->get_rid();
860 	VS::get_singleton()->canvas_item_set_material(canvas_item, rid);
861 	_change_notify(); //properties for material exposed
862 }
863 
set_use_parent_material(bool p_use_parent_material)864 void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
865 
866 	use_parent_material = p_use_parent_material;
867 	VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item, p_use_parent_material);
868 }
869 
get_use_parent_material() const870 bool CanvasItem::get_use_parent_material() const {
871 
872 	return use_parent_material;
873 }
874 
get_material() const875 Ref<CanvasItemMaterial> CanvasItem::get_material() const {
876 
877 	return material;
878 }
879 
make_canvas_pos_local(const Vector2 & screen_point) const880 Vector2 CanvasItem::make_canvas_pos_local(const Vector2 &screen_point) const {
881 
882 	ERR_FAIL_COND_V(!is_inside_tree(), screen_point);
883 
884 	Matrix32 local_matrix = (get_canvas_transform() *
885 							 get_global_transform())
886 									.affine_inverse();
887 
888 	return local_matrix.xform(screen_point);
889 }
890 
make_input_local(const InputEvent & p_event) const891 InputEvent CanvasItem::make_input_local(const InputEvent &p_event) const {
892 
893 	ERR_FAIL_COND_V(!is_inside_tree(), p_event);
894 
895 	return p_event.xform_by((get_canvas_transform() * get_global_transform()).affine_inverse());
896 }
897 
get_global_mouse_pos() const898 Vector2 CanvasItem::get_global_mouse_pos() const {
899 
900 	ERR_FAIL_COND_V(!get_viewport(), Vector2());
901 	return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_pos());
902 }
get_local_mouse_pos() const903 Vector2 CanvasItem::get_local_mouse_pos() const {
904 
905 	ERR_FAIL_COND_V(!get_viewport(), Vector2());
906 
907 	return get_global_transform().affine_inverse().xform(get_global_mouse_pos());
908 }
909 
_bind_methods()910 void CanvasItem::_bind_methods() {
911 
912 	ObjectTypeDB::bind_method(_MD("_sort_children"), &CanvasItem::_sort_children);
913 	ObjectTypeDB::bind_method(_MD("_raise_self"), &CanvasItem::_raise_self);
914 	ObjectTypeDB::bind_method(_MD("_update_callback"), &CanvasItem::_update_callback);
915 	ObjectTypeDB::bind_method(_MD("_set_visible_"), &CanvasItem::_set_visible_);
916 	ObjectTypeDB::bind_method(_MD("_is_visible_"), &CanvasItem::_is_visible_);
917 
918 	ObjectTypeDB::bind_method(_MD("edit_set_state", "state"), &CanvasItem::edit_set_state);
919 	ObjectTypeDB::bind_method(_MD("edit_get_state:Variant"), &CanvasItem::edit_get_state);
920 	ObjectTypeDB::bind_method(_MD("edit_set_rect", "rect"), &CanvasItem::edit_set_rect);
921 	ObjectTypeDB::bind_method(_MD("edit_rotate", "degrees"), &CanvasItem::edit_rotate);
922 
923 	ObjectTypeDB::bind_method(_MD("get_item_rect"), &CanvasItem::get_item_rect);
924 	ObjectTypeDB::bind_method(_MD("get_item_and_children_rect"), &CanvasItem::get_item_and_children_rect);
925 	//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
926 
927 	ObjectTypeDB::bind_method(_MD("get_canvas_item"), &CanvasItem::get_canvas_item);
928 
929 	ObjectTypeDB::bind_method(_MD("is_visible"), &CanvasItem::is_visible);
930 	ObjectTypeDB::bind_method(_MD("is_hidden"), &CanvasItem::is_hidden);
931 	ObjectTypeDB::bind_method(_MD("show"), &CanvasItem::show);
932 	ObjectTypeDB::bind_method(_MD("hide"), &CanvasItem::hide);
933 	ObjectTypeDB::bind_method(_MD("set_hidden", "hidden"), &CanvasItem::set_hidden);
934 
935 	ObjectTypeDB::bind_method(_MD("update"), &CanvasItem::update);
936 
937 	ObjectTypeDB::bind_method(_MD("set_as_toplevel", "enable"), &CanvasItem::set_as_toplevel);
938 	ObjectTypeDB::bind_method(_MD("is_set_as_toplevel"), &CanvasItem::is_set_as_toplevel);
939 
940 	ObjectTypeDB::bind_method(_MD("set_blend_mode", "blend_mode"), &CanvasItem::set_blend_mode);
941 	ObjectTypeDB::bind_method(_MD("get_blend_mode"), &CanvasItem::get_blend_mode);
942 
943 	ObjectTypeDB::bind_method(_MD("set_light_mask", "light_mask"), &CanvasItem::set_light_mask);
944 	ObjectTypeDB::bind_method(_MD("get_light_mask"), &CanvasItem::get_light_mask);
945 
946 	ObjectTypeDB::bind_method(_MD("set_opacity", "opacity"), &CanvasItem::set_opacity);
947 	ObjectTypeDB::bind_method(_MD("get_opacity"), &CanvasItem::get_opacity);
948 	ObjectTypeDB::bind_method(_MD("set_self_opacity", "self_opacity"), &CanvasItem::set_self_opacity);
949 	ObjectTypeDB::bind_method(_MD("get_self_opacity"), &CanvasItem::get_self_opacity);
950 
951 	ObjectTypeDB::bind_method(_MD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
952 	ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
953 
954 	ObjectTypeDB::bind_method(_MD("_set_on_top", "on_top"), &CanvasItem::_set_on_top);
955 	ObjectTypeDB::bind_method(_MD("_is_on_top"), &CanvasItem::_is_on_top);
956 	//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
957 
958 	ObjectTypeDB::bind_method(_MD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0));
959 	ObjectTypeDB::bind_method(_MD("draw_rect", "rect", "color"), &CanvasItem::draw_rect);
960 	ObjectTypeDB::bind_method(_MD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle);
961 	ObjectTypeDB::bind_method(_MD("draw_texture", "texture:Texture", "pos", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
962 	ObjectTypeDB::bind_method(_MD("draw_texture_rect", "texture:Texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
963 	ObjectTypeDB::bind_method(_MD("draw_texture_rect_region", "texture:Texture", "rect", "src_rect", "modulate", "transpose"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
964 	ObjectTypeDB::bind_method(_MD("draw_style_box", "style_box:StyleBox", "rect"), &CanvasItem::draw_style_box);
965 	ObjectTypeDB::bind_method(_MD("draw_primitive", "points", "colors", "uvs", "texture:Texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0));
966 	ObjectTypeDB::bind_method(_MD("draw_polygon", "points", "colors", "uvs", "texture:Texture"), &CanvasItem::draw_polygon, DEFVAL(Vector2Array()), DEFVAL(Variant()));
967 	ObjectTypeDB::bind_method(_MD("draw_colored_polygon", "points", "color", "uvs", "texture:Texture"), &CanvasItem::draw_colored_polygon, DEFVAL(Vector2Array()), DEFVAL(Variant()));
968 	ObjectTypeDB::bind_method(_MD("draw_string", "font:Font", "pos", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
969 	ObjectTypeDB::bind_method(_MD("draw_char", "font:Font", "pos", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1)));
970 
971 	ObjectTypeDB::bind_method(_MD("draw_set_transform", "pos", "rot", "scale"), &CanvasItem::draw_set_transform);
972 	ObjectTypeDB::bind_method(_MD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix);
973 	ObjectTypeDB::bind_method(_MD("get_transform"), &CanvasItem::get_transform);
974 	ObjectTypeDB::bind_method(_MD("get_global_transform"), &CanvasItem::get_global_transform);
975 	ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"), &CanvasItem::get_global_transform_with_canvas);
976 	ObjectTypeDB::bind_method(_MD("get_viewport_transform"), &CanvasItem::get_viewport_transform);
977 	ObjectTypeDB::bind_method(_MD("get_viewport_rect"), &CanvasItem::get_viewport_rect);
978 	ObjectTypeDB::bind_method(_MD("get_canvas_transform"), &CanvasItem::get_canvas_transform);
979 	ObjectTypeDB::bind_method(_MD("get_local_mouse_pos"), &CanvasItem::get_local_mouse_pos);
980 	ObjectTypeDB::bind_method(_MD("get_global_mouse_pos"), &CanvasItem::get_global_mouse_pos);
981 	ObjectTypeDB::bind_method(_MD("get_canvas"), &CanvasItem::get_canvas);
982 	ObjectTypeDB::bind_method(_MD("get_world_2d"), &CanvasItem::get_world_2d);
983 	//ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport);
984 
985 	ObjectTypeDB::bind_method(_MD("set_material", "material:CanvasItemMaterial"), &CanvasItem::set_material);
986 	ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"), &CanvasItem::get_material);
987 
988 	ObjectTypeDB::bind_method(_MD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material);
989 	ObjectTypeDB::bind_method(_MD("get_use_parent_material"), &CanvasItem::get_use_parent_material);
990 
991 	ObjectTypeDB::bind_method(_MD("make_canvas_pos_local", "screen_point"),
992 			&CanvasItem::make_canvas_pos_local);
993 	ObjectTypeDB::bind_method(_MD("make_input_local", "event"), &CanvasItem::make_input_local);
994 
995 	BIND_VMETHOD(MethodInfo("_draw"));
996 
997 	ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "visibility/visible"), _SCS("_set_visible_"), _SCS("_is_visible_"));
998 	ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "visibility/opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"), _SCS("get_opacity"));
999 	ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "visibility/self_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"), _SCS("get_self_opacity"));
1000 	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "visibility/behind_parent"), _SCS("set_draw_behind_parent"), _SCS("is_draw_behind_parent_enabled"));
1001 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visibility/on_top", PROPERTY_HINT_NONE, "", 0), _SCS("_set_on_top"), _SCS("_is_on_top")); //compatibility
1002 
1003 	ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "visibility/blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"), _SCS("get_blend_mode"));
1004 	ADD_PROPERTYNO(PropertyInfo(Variant::INT, "visibility/light_mask", PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"), _SCS("get_light_mask"));
1005 	ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material/material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"), _SCS("get_material"));
1006 	ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "material/use_parent"), _SCS("set_use_parent_material"), _SCS("get_use_parent_material"));
1007 	//exporting these two things doesn't really make much sense i think
1008 	//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
1009 	//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
1010 
1011 	ADD_SIGNAL(MethodInfo("draw"));
1012 	ADD_SIGNAL(MethodInfo("visibility_changed"));
1013 	ADD_SIGNAL(MethodInfo("hide"));
1014 	ADD_SIGNAL(MethodInfo("item_rect_changed"));
1015 
1016 	BIND_CONSTANT(BLEND_MODE_MIX);
1017 	BIND_CONSTANT(BLEND_MODE_ADD);
1018 	BIND_CONSTANT(BLEND_MODE_SUB);
1019 	BIND_CONSTANT(BLEND_MODE_MUL);
1020 	BIND_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
1021 
1022 	BIND_CONSTANT(NOTIFICATION_DRAW);
1023 	BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
1024 	BIND_CONSTANT(NOTIFICATION_ENTER_CANVAS);
1025 	BIND_CONSTANT(NOTIFICATION_EXIT_CANVAS);
1026 	BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
1027 }
1028 
get_canvas_transform() const1029 Matrix32 CanvasItem::get_canvas_transform() const {
1030 
1031 	ERR_FAIL_COND_V(!is_inside_tree(), Matrix32());
1032 
1033 	if (canvas_layer)
1034 		return canvas_layer->get_transform();
1035 	else if (get_parent()->cast_to<CanvasItem>())
1036 		return get_parent()->cast_to<CanvasItem>()->get_canvas_transform();
1037 	else
1038 		return get_viewport()->get_canvas_transform();
1039 }
1040 
get_viewport_transform() const1041 Matrix32 CanvasItem::get_viewport_transform() const {
1042 
1043 	ERR_FAIL_COND_V(!is_inside_tree(), Matrix32());
1044 
1045 	if (canvas_layer) {
1046 
1047 		if (get_viewport()) {
1048 			return get_viewport()->get_final_transform() * canvas_layer->get_transform();
1049 		} else {
1050 			return canvas_layer->get_transform();
1051 		}
1052 
1053 	} else {
1054 		return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
1055 	}
1056 }
1057 
set_notify_local_transform(bool p_enable)1058 void CanvasItem::set_notify_local_transform(bool p_enable) {
1059 	notify_local_transform = p_enable;
1060 }
1061 
is_local_transform_notification_enabled() const1062 bool CanvasItem::is_local_transform_notification_enabled() const {
1063 	return notify_local_transform;
1064 }
1065 
get_canvas_layer() const1066 int CanvasItem::get_canvas_layer() const {
1067 
1068 	if (canvas_layer)
1069 		return canvas_layer->get_layer();
1070 	else
1071 		return 0;
1072 }
1073 
get_item_and_children_rect() const1074 Rect2 CanvasItem::get_item_and_children_rect() const {
1075 
1076 	Rect2 rect = get_item_rect();
1077 
1078 	for (int i = 0; i < get_child_count(); i++) {
1079 		CanvasItem *c = get_child(i)->cast_to<CanvasItem>();
1080 		if (c) {
1081 			Rect2 sir = c->get_transform().xform(c->get_item_and_children_rect());
1082 			rect = rect.merge(sir);
1083 		}
1084 	}
1085 
1086 	return rect;
1087 }
1088 
CanvasItem()1089 CanvasItem::CanvasItem() :
1090 		xform_change(this) {
1091 
1092 	canvas_item = VisualServer::get_singleton()->canvas_item_create();
1093 	hidden = false;
1094 	pending_update = false;
1095 	opacity = 1;
1096 	self_opacity = 1;
1097 	toplevel = false;
1098 	pending_children_sort = false;
1099 	first_draw = false;
1100 	blend_mode = BLEND_MODE_MIX;
1101 	drawing = false;
1102 	behind = false;
1103 	block_transform_notify = false;
1104 	//	viewport=NULL;
1105 	canvas_layer = NULL;
1106 	use_parent_material = false;
1107 	global_invalid = true;
1108 	notify_local_transform = false;
1109 	light_mask = 1;
1110 
1111 	C = NULL;
1112 }
1113 
~CanvasItem()1114 CanvasItem::~CanvasItem() {
1115 
1116 	VisualServer::get_singleton()->free(canvas_item);
1117 }
1118