Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/main/canvas_item.cpp
20882 views
1
/**************************************************************************/
2
/* canvas_item.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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.h"
32
#include "canvas_item.compat.inc"
33
34
#include "scene/2d/canvas_group.h"
35
#include "scene/main/canvas_layer.h"
36
#include "scene/main/window.h"
37
#include "scene/resources/atlas_texture.h"
38
#include "scene/resources/font.h"
39
#include "scene/resources/multimesh.h"
40
#include "scene/resources/style_box.h"
41
#include "scene/resources/world_2d.h"
42
43
#define ERR_DRAW_GUARD \
44
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside this node's `_draw()`, functions connected to its `draw` signal, or when it receives NOTIFICATION_DRAW.")
45
46
#ifdef DEBUG_ENABLED
47
bool CanvasItem::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
48
if (_edit_use_rect()) {
49
return _edit_get_rect().has_point(p_point);
50
} else {
51
return p_point.length() < p_tolerance;
52
}
53
}
54
#endif // DEBUG_ENABLED
55
56
#ifdef TOOLS_ENABLED
57
Transform2D CanvasItem::_edit_get_transform() const {
58
return Transform2D(_edit_get_rotation(), _edit_get_position() + _edit_get_pivot());
59
}
60
#endif //TOOLS_ENABLED
61
62
bool CanvasItem::is_visible_in_tree() const {
63
ERR_READ_THREAD_GUARD_V(false);
64
return visible && parent_visible_in_tree;
65
}
66
67
void CanvasItem::_propagate_visibility_changed(bool p_parent_visible_in_tree) {
68
parent_visible_in_tree = p_parent_visible_in_tree;
69
if (!visible) {
70
return;
71
}
72
73
_handle_visibility_change(p_parent_visible_in_tree);
74
}
75
76
void CanvasItem::set_visible(bool p_visible) {
77
ERR_MAIN_THREAD_GUARD;
78
if (visible == p_visible) {
79
return;
80
}
81
82
visible = p_visible;
83
84
if (!parent_visible_in_tree) {
85
notification(NOTIFICATION_VISIBILITY_CHANGED);
86
return;
87
}
88
89
_handle_visibility_change(p_visible);
90
}
91
92
void CanvasItem::_handle_visibility_change(bool p_visible) {
93
RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, p_visible);
94
notification(NOTIFICATION_VISIBILITY_CHANGED);
95
96
if (p_visible) {
97
queue_redraw();
98
} else {
99
emit_signal(SceneStringName(hidden));
100
}
101
102
_block();
103
for (int i = 0; i < get_child_count(); i++) {
104
CanvasItem *c = Object::cast_to<CanvasItem>(get_child(i));
105
106
if (c) { // Should the top_levels stop propagation? I think so, but...
107
c->_propagate_visibility_changed(p_visible);
108
}
109
}
110
_unblock();
111
}
112
113
void CanvasItem::show() {
114
ERR_MAIN_THREAD_GUARD;
115
set_visible(true);
116
}
117
118
void CanvasItem::hide() {
119
ERR_MAIN_THREAD_GUARD;
120
set_visible(false);
121
}
122
123
bool CanvasItem::is_visible() const {
124
ERR_READ_THREAD_GUARD_V(false);
125
return visible;
126
}
127
128
CanvasItem *CanvasItem::current_item_drawn = nullptr;
129
CanvasItem *CanvasItem::get_current_item_drawn() {
130
return current_item_drawn;
131
}
132
133
void CanvasItem::_redraw_callback() {
134
if (!is_inside_tree()) {
135
pending_update = false;
136
return;
137
}
138
139
if (draw_commands_dirty) {
140
RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item());
141
draw_commands_dirty = false;
142
}
143
144
if (is_visible_in_tree()) {
145
drawing = true;
146
TextServer::set_current_drawn_item_oversampling(get_viewport()->get_oversampling());
147
current_item_drawn = this;
148
notification(NOTIFICATION_DRAW);
149
emit_signal(SceneStringName(draw));
150
GDVIRTUAL_CALL(_draw);
151
current_item_drawn = nullptr;
152
TextServer::set_current_drawn_item_oversampling(0.0);
153
drawing = false;
154
draw_commands_dirty = true;
155
}
156
pending_update = false; // Don't change to false until finished drawing (avoid recursive update).
157
}
158
159
Transform2D CanvasItem::get_global_transform_with_canvas() const {
160
ERR_READ_THREAD_GUARD_V(Transform2D());
161
if (canvas_layer) {
162
return canvas_layer->get_final_transform() * get_global_transform();
163
} else if (is_inside_tree()) {
164
return get_viewport()->get_canvas_transform() * get_global_transform();
165
} else {
166
return get_global_transform();
167
}
168
}
169
170
Transform2D CanvasItem::get_screen_transform() const {
171
ERR_READ_THREAD_GUARD_V(Transform2D());
172
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
173
return get_viewport()->get_popup_base_transform() * get_global_transform_with_canvas();
174
}
175
176
Transform2D CanvasItem::get_global_transform() const {
177
ERR_READ_THREAD_GUARD_V(Transform2D());
178
179
if (_is_global_invalid()) {
180
// This code can enter multiple times from threads if dirty, this is expected.
181
const CanvasItem *pi = get_parent_item();
182
Transform2D new_global;
183
if (pi) {
184
new_global = pi->get_global_transform() * get_transform();
185
} else {
186
new_global = get_transform();
187
}
188
189
global_transform = new_global;
190
_set_global_invalid(false);
191
}
192
193
return global_transform;
194
}
195
196
// Same as get_global_transform() but no reset for `global_invalid`.
197
Transform2D CanvasItem::get_global_transform_const() const {
198
if (_is_global_invalid()) {
199
const CanvasItem *pi = get_parent_item();
200
if (pi) {
201
global_transform = pi->get_global_transform_const() * get_transform();
202
} else {
203
global_transform = get_transform();
204
}
205
}
206
207
return global_transform;
208
}
209
210
void CanvasItem::_set_global_invalid(bool p_invalid) const {
211
if (is_group_processing()) {
212
if (p_invalid) {
213
global_invalid.mt.set();
214
} else {
215
global_invalid.mt.clear();
216
}
217
} else {
218
global_invalid.st = p_invalid;
219
}
220
}
221
222
void CanvasItem::_top_level_raise_self() {
223
if (!is_inside_tree()) {
224
return;
225
}
226
227
if (canvas_layer) {
228
RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, canvas_layer->get_sort_index());
229
} else {
230
RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_viewport()->gui_get_canvas_sort_index());
231
}
232
}
233
234
void CanvasItem::_enter_canvas() {
235
// Resolves to nullptr if the node is top_level.
236
CanvasItem *parent_item = get_parent_item();
237
238
if (get_parent()) {
239
get_viewport()->canvas_parent_mark_dirty(get_parent());
240
}
241
242
if (parent_item) {
243
canvas_layer = parent_item->canvas_layer;
244
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent_item->get_canvas_item());
245
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer);
246
} else {
247
Node *n = this;
248
249
canvas_layer = nullptr;
250
251
while (n) {
252
canvas_layer = Object::cast_to<CanvasLayer>(n);
253
if (canvas_layer) {
254
break;
255
}
256
if (Object::cast_to<Viewport>(n)) {
257
break;
258
}
259
n = n->get_parent();
260
}
261
262
RID canvas;
263
if (canvas_layer) {
264
canvas = canvas_layer->get_canvas();
265
} else {
266
canvas = get_viewport()->find_world_2d()->get_canvas();
267
}
268
269
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas);
270
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, visibility_layer);
271
272
canvas_group = "_root_canvas" + itos(canvas.get_id());
273
274
add_to_group(canvas_group);
275
if (canvas_layer) {
276
canvas_layer->reset_sort_index();
277
} else {
278
get_viewport()->gui_reset_canvas_sort_index();
279
}
280
}
281
282
queue_redraw();
283
284
notification(NOTIFICATION_ENTER_CANVAS);
285
}
286
287
void CanvasItem::_exit_canvas() {
288
notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification
289
RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, RID());
290
canvas_layer = nullptr;
291
if (canvas_group != StringName()) {
292
remove_from_group(canvas_group);
293
canvas_group = StringName();
294
}
295
}
296
297
void CanvasItem::_notification(int p_what) {
298
switch (p_what) {
299
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
300
RID ae = get_accessibility_element();
301
ERR_FAIL_COND(ae.is_null());
302
303
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_HIDDEN, !visible);
304
} break;
305
306
case NOTIFICATION_ENTER_TREE: {
307
ERR_MAIN_THREAD_GUARD;
308
ERR_FAIL_COND(!is_inside_tree());
309
310
Node *parent = get_parent();
311
if (parent) {
312
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
313
314
if (ci) {
315
parent_visible_in_tree = ci->is_visible_in_tree();
316
317
data.index_in_parent = ci->data.canvas_item_children.size();
318
ci->data.canvas_item_children.push_back(this);
319
} else {
320
if (data.index_in_parent != UINT32_MAX) {
321
data.index_in_parent = UINT32_MAX;
322
ERR_PRINT("CanvasItem ENTER_TREE detected without EXIT_TREE, recovering.");
323
}
324
325
CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);
326
327
if (cl) {
328
parent_visible_in_tree = cl->is_visible();
329
} else {
330
// Look for a window.
331
Viewport *viewport = nullptr;
332
333
while (parent) {
334
viewport = Object::cast_to<Viewport>(parent);
335
if (viewport) {
336
break;
337
}
338
parent = parent->get_parent();
339
}
340
341
ERR_FAIL_NULL(viewport);
342
343
window = Object::cast_to<Window>(viewport);
344
if (window) {
345
window->connect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
346
parent_visible_in_tree = window->is_visible();
347
} else {
348
parent_visible_in_tree = true;
349
}
350
}
351
}
352
}
353
354
_set_global_invalid(true);
355
_enter_canvas();
356
357
RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, is_visible_in_tree()); // The visibility of the parent may change.
358
if (is_visible_in_tree()) {
359
notification(NOTIFICATION_VISIBILITY_CHANGED); // Considered invisible until entered.
360
}
361
362
_update_texture_filter_changed(false);
363
_update_texture_repeat_changed(false);
364
365
if (!block_transform_notify && !xform_change.in_list()) {
366
get_tree()->xform_change_list.add(&xform_change);
367
}
368
369
if (get_viewport()) {
370
get_parent()->connect(SNAME("child_order_changed"), callable_mp(get_viewport(), &Viewport::canvas_parent_mark_dirty).bind(get_parent()), CONNECT_REFERENCE_COUNTED);
371
}
372
373
// If using physics interpolation, reset for this node only,
374
// as a helper, as in most cases, users will want items reset when
375
// adding to the tree.
376
// In cases where they move immediately after adding,
377
// there will be little cost in having two resets as these are cheap,
378
// and it is worth it for convenience.
379
// Do not propagate to children, as each child of an added branch
380
// receives its own NOTIFICATION_ENTER_TREE, and this would
381
// cause unnecessary duplicate resets.
382
if (is_physics_interpolated_and_enabled()) {
383
notification(NOTIFICATION_RESET_PHYSICS_INTERPOLATION);
384
}
385
386
} break;
387
case NOTIFICATION_EXIT_TREE: {
388
ERR_MAIN_THREAD_GUARD;
389
390
if (xform_change.in_list()) {
391
get_tree()->xform_change_list.remove(&xform_change);
392
}
393
_exit_canvas();
394
395
CanvasItem *parent = Object::cast_to<CanvasItem>(get_parent());
396
if (parent) {
397
if (data.index_in_parent != UINT32_MAX) {
398
// Aliases
399
uint32_t c = data.index_in_parent;
400
LocalVector<CanvasItem *> &parent_children = parent->data.canvas_item_children;
401
402
parent_children.remove_at_unordered(c);
403
404
// After unordered remove, we need to inform the moved child
405
// what their new id is in the parent children list.
406
if (parent_children.size() > c) {
407
parent_children[c]->data.index_in_parent = c;
408
}
409
} else {
410
ERR_PRINT("CanvasItem index_in_parent unset at EXIT_TREE.");
411
}
412
}
413
data.index_in_parent = UINT32_MAX;
414
415
if (window) {
416
window->disconnect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
417
window = nullptr;
418
}
419
_set_global_invalid(true);
420
parent_visible_in_tree = false;
421
422
if (get_viewport()) {
423
get_parent()->disconnect(SNAME("child_order_changed"), callable_mp(get_viewport(), &Viewport::canvas_parent_mark_dirty).bind(get_parent()));
424
}
425
} break;
426
427
case NOTIFICATION_RESET_PHYSICS_INTERPOLATION: {
428
if (is_visible_in_tree() && is_physics_interpolated_and_enabled()) {
429
RenderingServer::get_singleton()->canvas_item_reset_physics_interpolation(canvas_item);
430
}
431
} break;
432
433
case NOTIFICATION_VISIBILITY_CHANGED: {
434
ERR_MAIN_THREAD_GUARD;
435
436
emit_signal(SceneStringName(visibility_changed));
437
} break;
438
case NOTIFICATION_WORLD_2D_CHANGED: {
439
ERR_MAIN_THREAD_GUARD;
440
441
_exit_canvas();
442
_enter_canvas();
443
} break;
444
case NOTIFICATION_PARENTED: {
445
// The node is not inside the tree during this notification.
446
ERR_MAIN_THREAD_GUARD;
447
448
_notify_transform();
449
} break;
450
}
451
}
452
453
void CanvasItem::update_draw_order() {
454
ERR_MAIN_THREAD_GUARD;
455
456
if (!is_inside_tree()) {
457
return;
458
}
459
460
if (canvas_group != StringName()) {
461
get_tree()->call_group_flags(SceneTree::GROUP_CALL_UNIQUE | SceneTree::GROUP_CALL_DEFERRED, canvas_group, "_top_level_raise_self");
462
} else {
463
ERR_FAIL_NULL_MSG(get_parent_item(), "Moved child is in incorrect state (no canvas group, no canvas item parent).");
464
RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index());
465
}
466
}
467
468
void CanvasItem::_window_visibility_changed() {
469
_propagate_visibility_changed(window->is_visible());
470
}
471
472
void CanvasItem::queue_redraw() {
473
ERR_THREAD_GUARD; // Calling from thread is safe.
474
if (!is_inside_tree()) {
475
return;
476
}
477
if (pending_update) {
478
return;
479
}
480
481
pending_update = true;
482
483
callable_mp(this, &CanvasItem::_redraw_callback).call_deferred();
484
}
485
486
void CanvasItem::move_to_front() {
487
ERR_MAIN_THREAD_GUARD;
488
if (!get_parent()) {
489
return;
490
}
491
get_parent()->move_child(this, -1);
492
}
493
494
void CanvasItem::set_modulate(const Color &p_modulate) {
495
ERR_THREAD_GUARD;
496
if (modulate == p_modulate) {
497
return;
498
}
499
500
modulate = p_modulate;
501
RenderingServer::get_singleton()->canvas_item_set_modulate(canvas_item, modulate);
502
}
503
504
Color CanvasItem::get_modulate() const {
505
ERR_READ_THREAD_GUARD_V(Color());
506
return modulate;
507
}
508
509
Color CanvasItem::get_modulate_in_tree() const {
510
ERR_READ_THREAD_GUARD_V(Color());
511
Color final_modulate = modulate;
512
CanvasItem *parent_item = get_parent_item();
513
while (parent_item) {
514
final_modulate *= parent_item->get_modulate();
515
parent_item = parent_item->get_parent_item();
516
}
517
return final_modulate;
518
}
519
520
void CanvasItem::set_as_top_level(bool p_top_level) {
521
ERR_MAIN_THREAD_GUARD;
522
if (top_level == p_top_level) {
523
return;
524
}
525
526
if (!is_inside_tree()) {
527
top_level = p_top_level;
528
_notify_transform();
529
return;
530
}
531
532
_exit_canvas();
533
top_level = p_top_level;
534
_top_level_changed();
535
_enter_canvas();
536
537
_notify_transform();
538
539
if (get_viewport()) {
540
get_viewport()->canvas_item_top_level_changed();
541
}
542
reset_physics_interpolation();
543
}
544
545
void CanvasItem::_top_level_changed() {
546
// Inform children that top_level status has changed on a parent.
547
int children = get_child_count();
548
for (int i = 0; i < children; i++) {
549
CanvasItem *child = Object::cast_to<CanvasItem>(get_child(i));
550
if (child) {
551
child->_top_level_changed_on_parent();
552
}
553
}
554
}
555
556
void CanvasItem::_top_level_changed_on_parent() {
557
// Inform children that top_level status has changed on a parent.
558
_top_level_changed();
559
}
560
561
bool CanvasItem::is_set_as_top_level() const {
562
return top_level;
563
}
564
565
CanvasItem *CanvasItem::get_parent_item() const {
566
ERR_READ_THREAD_GUARD_V(nullptr);
567
if (top_level) {
568
return nullptr;
569
}
570
571
return Object::cast_to<CanvasItem>(get_parent());
572
}
573
574
void CanvasItem::set_self_modulate(const Color &p_self_modulate) {
575
ERR_THREAD_GUARD;
576
if (self_modulate == p_self_modulate) {
577
return;
578
}
579
580
self_modulate = p_self_modulate;
581
RenderingServer::get_singleton()->canvas_item_set_self_modulate(canvas_item, self_modulate);
582
}
583
584
Color CanvasItem::get_self_modulate() const {
585
ERR_READ_THREAD_GUARD_V(Color());
586
return self_modulate;
587
}
588
589
void CanvasItem::set_light_mask(int p_light_mask) {
590
ERR_THREAD_GUARD;
591
if (light_mask == p_light_mask) {
592
return;
593
}
594
595
light_mask = p_light_mask;
596
RS::get_singleton()->canvas_item_set_light_mask(canvas_item, p_light_mask);
597
}
598
599
int CanvasItem::get_light_mask() const {
600
ERR_READ_THREAD_GUARD_V(0);
601
return light_mask;
602
}
603
604
const StringName *CanvasItem::_instance_shader_parameter_get_remap(const StringName &p_name) const {
605
StringName *r = instance_shader_parameter_property_remap.getptr(p_name);
606
if (!r) {
607
String s = p_name;
608
if (s.begins_with("instance_shader_parameters/")) {
609
StringName name = s.trim_prefix("instance_shader_parameters/");
610
instance_shader_parameter_property_remap[p_name] = name;
611
return instance_shader_parameter_property_remap.getptr(p_name);
612
}
613
return nullptr;
614
}
615
return r;
616
}
617
618
bool CanvasItem::_set(const StringName &p_name, const Variant &p_value) {
619
const StringName *r = _instance_shader_parameter_get_remap(p_name);
620
if (r) {
621
set_instance_shader_parameter(*r, p_value);
622
return true;
623
}
624
return false;
625
}
626
627
bool CanvasItem::_get(const StringName &p_name, Variant &r_ret) const {
628
const StringName *r = _instance_shader_parameter_get_remap(p_name);
629
if (r) {
630
r_ret = get_instance_shader_parameter(*r);
631
return true;
632
}
633
634
return false;
635
}
636
637
void CanvasItem::_get_property_list(List<PropertyInfo> *p_list) const {
638
List<PropertyInfo> pinfo;
639
RS::get_singleton()->canvas_item_get_instance_shader_parameter_list(get_canvas_item(), &pinfo);
640
641
for (PropertyInfo &pi : pinfo) {
642
bool has_def_value = false;
643
Variant def_value = RS::get_singleton()->canvas_item_get_instance_shader_parameter_default_value(get_canvas_item(), pi.name);
644
if (def_value.get_type() != Variant::NIL) {
645
has_def_value = true;
646
}
647
if (instance_shader_parameters.has(pi.name)) {
648
pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : PROPERTY_USAGE_NONE);
649
} else {
650
pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : PROPERTY_USAGE_NONE); // Do not save if not changed.
651
}
652
653
pi.name = "instance_shader_parameters/" + pi.name;
654
p_list->push_back(pi);
655
}
656
}
657
658
void CanvasItem::item_rect_changed(bool p_size_changed) {
659
ERR_MAIN_THREAD_GUARD;
660
if (p_size_changed) {
661
queue_redraw();
662
}
663
emit_signal(SceneStringName(item_rect_changed));
664
}
665
666
void CanvasItem::set_z_index(int p_z) {
667
ERR_THREAD_GUARD;
668
ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN);
669
ERR_FAIL_COND(p_z > RS::CANVAS_ITEM_Z_MAX);
670
z_index = p_z;
671
RS::get_singleton()->canvas_item_set_z_index(canvas_item, z_index);
672
update_configuration_warnings();
673
}
674
675
void CanvasItem::set_z_as_relative(bool p_enabled) {
676
ERR_THREAD_GUARD;
677
if (z_relative == p_enabled) {
678
return;
679
}
680
z_relative = p_enabled;
681
RS::get_singleton()->canvas_item_set_z_as_relative_to_parent(canvas_item, p_enabled);
682
}
683
684
bool CanvasItem::is_z_relative() const {
685
ERR_READ_THREAD_GUARD_V(false);
686
return z_relative;
687
}
688
689
int CanvasItem::get_z_index() const {
690
ERR_READ_THREAD_GUARD_V(0);
691
return z_index;
692
}
693
694
int CanvasItem::get_effective_z_index() const {
695
ERR_READ_THREAD_GUARD_V(0);
696
int effective_z_index = z_index;
697
if (is_z_relative()) {
698
CanvasItem *p = get_parent_item();
699
if (p) {
700
effective_z_index += p->get_effective_z_index();
701
}
702
}
703
return effective_z_index;
704
}
705
706
void CanvasItem::set_y_sort_enabled(bool p_enabled) {
707
ERR_THREAD_GUARD;
708
y_sort_enabled = p_enabled;
709
RS::get_singleton()->canvas_item_set_sort_children_by_y(canvas_item, y_sort_enabled);
710
}
711
712
bool CanvasItem::is_y_sort_enabled() const {
713
ERR_READ_THREAD_GUARD_V(false);
714
return y_sort_enabled;
715
}
716
717
void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned, bool p_antialiased) {
718
ERR_THREAD_GUARD;
719
ERR_DRAW_GUARD;
720
ERR_FAIL_COND(p_dash <= 0.0);
721
722
float length = (p_to - p_from).length();
723
Vector2 step = p_dash * (p_to - p_from).normalized();
724
725
if (length < p_dash || step == Vector2()) {
726
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
727
return;
728
}
729
730
int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash);
731
if (steps % 2 == 0) {
732
steps--;
733
}
734
735
Point2 off = p_from;
736
if (p_aligned) {
737
off += (p_to - p_from).normalized() * (length - steps * p_dash) / 2.0;
738
}
739
740
Vector<Vector2> points;
741
points.resize(steps + 1);
742
for (int i = 0; i < steps; i += 2) {
743
points.write[i] = (i == 0) ? p_from : off;
744
points.write[i + 1] = (p_aligned && i == steps - 1) ? p_to : (off + step);
745
off += step * 2;
746
}
747
748
Vector<Color> colors = { p_color };
749
750
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, points, colors, p_width, p_antialiased);
751
}
752
753
void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
754
ERR_THREAD_GUARD;
755
ERR_DRAW_GUARD;
756
757
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
758
}
759
760
void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
761
ERR_THREAD_GUARD;
762
ERR_DRAW_GUARD;
763
764
Vector<Color> colors = { p_color };
765
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width, p_antialiased);
766
}
767
768
void CanvasItem::draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
769
ERR_THREAD_GUARD;
770
ERR_DRAW_GUARD;
771
772
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width, p_antialiased);
773
}
774
775
void CanvasItem::draw_ellipse_arc(const Vector2 &p_center, real_t p_major, real_t p_minor, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width, bool p_antialiased) {
776
ERR_THREAD_GUARD;
777
ERR_DRAW_GUARD;
778
779
Vector<Point2> points;
780
points.resize(p_point_count);
781
Point2 *points_ptr = points.ptrw();
782
783
// Clamp angle difference to full circle so arc won't overlap itself.
784
const real_t delta_angle = CLAMP(p_end_angle - p_start_angle, -Math::TAU, Math::TAU);
785
for (int i = 0; i < p_point_count; i++) {
786
real_t theta = (i / (p_point_count - 1.0f)) * delta_angle + p_start_angle;
787
points_ptr[i] = p_center + Vector2(p_major * Math::cos(theta), p_minor * Math::sin(theta));
788
}
789
790
draw_polyline(points, p_color, p_width, p_antialiased);
791
}
792
793
void CanvasItem::draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width, bool p_antialiased) {
794
ERR_THREAD_GUARD;
795
ERR_DRAW_GUARD;
796
797
draw_ellipse_arc(p_center, p_radius, p_radius, p_start_angle, p_end_angle, p_point_count, p_color, p_width, p_antialiased);
798
}
799
800
void CanvasItem::draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
801
ERR_THREAD_GUARD;
802
ERR_DRAW_GUARD;
803
804
Vector<Color> colors = { p_color };
805
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width, p_antialiased);
806
}
807
808
void CanvasItem::draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width, bool p_antialiased) {
809
ERR_THREAD_GUARD;
810
ERR_DRAW_GUARD;
811
812
RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width, p_antialiased);
813
}
814
815
void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
816
ERR_THREAD_GUARD;
817
ERR_DRAW_GUARD;
818
819
Rect2 rect = p_rect.abs();
820
821
if (p_filled) {
822
if (p_width != -1.0) {
823
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
824
}
825
826
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect, p_color, p_antialiased);
827
} else if (p_width >= rect.size.width || p_width >= rect.size.height) {
828
RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, rect.grow(0.5f * p_width), p_color, p_antialiased);
829
} else {
830
Vector<Vector2> points;
831
points.resize(5);
832
points.write[0] = rect.position;
833
points.write[1] = rect.position + Vector2(rect.size.x, 0);
834
points.write[2] = rect.position + rect.size;
835
points.write[3] = rect.position + Vector2(0, rect.size.y);
836
points.write[4] = rect.position;
837
838
Vector<Color> colors = { p_color };
839
840
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased);
841
}
842
}
843
844
void CanvasItem::draw_ellipse(const Point2 &p_pos, real_t p_major, real_t p_minor, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
845
ERR_THREAD_GUARD;
846
ERR_DRAW_GUARD;
847
848
if (p_filled) {
849
if (p_width != -1.0) {
850
WARN_PRINT("The \"width\" argument has no effect when \"filled\" is \"true\".");
851
}
852
853
RenderingServer::get_singleton()->canvas_item_add_ellipse(canvas_item, p_pos, p_major, p_minor, p_color, p_antialiased);
854
} else if (p_width >= 2.0 * MAX(p_major, p_minor)) {
855
RenderingServer::get_singleton()->canvas_item_add_ellipse(canvas_item, p_pos, p_major + 0.5 * p_width, p_minor + 0.5 * p_width, p_color, p_antialiased);
856
} else {
857
// Tessellation count is hardcoded. Keep in sync with the same variable in `RendererCanvasCull::canvas_item_add_circle()`.
858
const int circle_segments = 64;
859
860
Vector<Vector2> points;
861
points.resize(circle_segments + 1);
862
863
Vector2 *points_ptr = points.ptrw();
864
const real_t circle_point_step = Math::TAU / circle_segments;
865
866
for (int i = 0; i < circle_segments; i++) {
867
float angle = i * circle_point_step;
868
points_ptr[i].x = Math::cos(angle) * p_major;
869
points_ptr[i].y = Math::sin(angle) * p_minor;
870
points_ptr[i] += p_pos;
871
}
872
points_ptr[circle_segments] = points_ptr[0];
873
874
Vector<Color> colors = { p_color };
875
876
RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, points, colors, p_width, p_antialiased);
877
}
878
}
879
880
void CanvasItem::draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color, bool p_filled, real_t p_width, bool p_antialiased) {
881
ERR_THREAD_GUARD;
882
ERR_DRAW_GUARD;
883
884
draw_ellipse(p_pos, p_radius, p_radius, p_color, p_filled, p_width, p_antialiased);
885
}
886
887
void CanvasItem::draw_texture(RequiredParam<Texture2D> rp_texture, const Point2 &p_pos, const Color &p_modulate) {
888
ERR_THREAD_GUARD;
889
ERR_DRAW_GUARD;
890
891
EXTRACT_PARAM_OR_FAIL(p_texture, rp_texture);
892
893
p_texture->draw(canvas_item, p_pos, p_modulate, false);
894
}
895
896
void CanvasItem::draw_texture_rect(RequiredParam<Texture2D> rp_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) {
897
ERR_THREAD_GUARD;
898
ERR_DRAW_GUARD;
899
900
EXTRACT_PARAM_OR_FAIL(p_texture, rp_texture);
901
p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose);
902
}
903
904
void CanvasItem::draw_texture_rect_region(RequiredParam<Texture2D> rp_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {
905
ERR_THREAD_GUARD;
906
ERR_DRAW_GUARD;
907
EXTRACT_PARAM_OR_FAIL(p_texture, rp_texture);
908
p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv);
909
}
910
911
void CanvasItem::draw_msdf_texture_rect_region(RequiredParam<Texture2D> rp_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range, double p_scale) {
912
ERR_THREAD_GUARD;
913
ERR_DRAW_GUARD;
914
EXTRACT_PARAM_OR_FAIL(p_texture, rp_texture);
915
RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range, p_scale);
916
}
917
918
void CanvasItem::draw_lcd_texture_rect_region(RequiredParam<Texture2D> rp_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) {
919
ERR_THREAD_GUARD;
920
ERR_DRAW_GUARD;
921
EXTRACT_PARAM_OR_FAIL(p_texture, rp_texture);
922
RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate);
923
}
924
925
void CanvasItem::draw_style_box(RequiredParam<StyleBox> rp_style_box, const Rect2 &p_rect) {
926
ERR_THREAD_GUARD;
927
ERR_DRAW_GUARD;
928
929
EXTRACT_PARAM_OR_FAIL(p_style_box, rp_style_box);
930
931
p_style_box->draw(canvas_item, p_rect);
932
}
933
934
void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) {
935
ERR_THREAD_GUARD;
936
ERR_DRAW_GUARD;
937
938
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
939
RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid);
940
}
941
942
void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const Size2 &p_scale) {
943
ERR_THREAD_GUARD;
944
ERR_DRAW_GUARD;
945
946
Transform2D xform(p_rot, p_scale, 0.0, p_offset);
947
RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, xform);
948
}
949
950
void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) {
951
ERR_THREAD_GUARD;
952
ERR_DRAW_GUARD;
953
954
RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix);
955
}
956
void CanvasItem::draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {
957
ERR_THREAD_GUARD;
958
ERR_DRAW_GUARD;
959
960
RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, p_animation_length, p_slice_begin, p_slice_end, p_offset);
961
}
962
963
void CanvasItem::draw_end_animation() {
964
ERR_THREAD_GUARD;
965
ERR_DRAW_GUARD;
966
967
RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, 1, 0, 2, 0);
968
}
969
970
void CanvasItem::draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) {
971
ERR_THREAD_GUARD;
972
ERR_DRAW_GUARD;
973
974
const Ref<AtlasTexture> atlas = p_texture;
975
if (atlas.is_valid() && atlas->get_atlas().is_valid()) {
976
const Ref<Texture2D> &texture = atlas->get_atlas();
977
const Vector2 atlas_size = texture->get_size();
978
979
const Vector2 remap_min = atlas->get_region().position / atlas_size;
980
const Vector2 remap_max = atlas->get_region().get_end() / atlas_size;
981
982
PackedVector2Array uvs = p_uvs;
983
for (Vector2 &p : uvs) {
984
p.x = Math::remap(p.x, 0, 1, remap_min.x, remap_max.x);
985
p.y = Math::remap(p.y, 0, 1, remap_min.y, remap_max.y);
986
}
987
RenderingServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, uvs, texture->get_rid());
988
} else {
989
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
990
RenderingServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, texture_rid);
991
}
992
}
993
994
void CanvasItem::draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) {
995
draw_polygon(p_points, { p_color }, p_uvs, p_texture);
996
}
997
998
void CanvasItem::draw_mesh(RequiredParam<Mesh> rp_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform, const Color &p_modulate) {
999
ERR_THREAD_GUARD;
1000
EXTRACT_PARAM_OR_FAIL(p_mesh, rp_mesh);
1001
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
1002
1003
RenderingServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), p_transform, p_modulate, texture_rid);
1004
}
1005
1006
void CanvasItem::draw_multimesh(RequiredParam<MultiMesh> rp_multimesh, const Ref<Texture2D> &p_texture) {
1007
ERR_THREAD_GUARD;
1008
EXTRACT_PARAM_OR_FAIL(p_multimesh, rp_multimesh);
1009
RID texture_rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
1010
RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid);
1011
}
1012
1013
void CanvasItem::draw_string(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
1014
ERR_THREAD_GUARD;
1015
ERR_DRAW_GUARD;
1016
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1017
1018
p_font->draw_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_modulate, p_jst_flags, p_direction, p_orientation, p_oversampling);
1019
}
1020
1021
void CanvasItem::draw_multiline_string(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
1022
ERR_THREAD_GUARD;
1023
ERR_DRAW_GUARD;
1024
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1025
1026
p_font->draw_multiline_string(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_modulate, p_brk_flags, p_jst_flags, p_direction, p_orientation, p_oversampling);
1027
}
1028
1029
void CanvasItem::draw_string_outline(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
1030
ERR_THREAD_GUARD;
1031
ERR_DRAW_GUARD;
1032
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1033
1034
p_font->draw_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_size, p_modulate, p_jst_flags, p_direction, p_orientation, p_oversampling);
1035
}
1036
1037
void CanvasItem::draw_multiline_string_outline(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
1038
ERR_THREAD_GUARD;
1039
ERR_DRAW_GUARD;
1040
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1041
1042
p_font->draw_multiline_string_outline(canvas_item, p_pos, p_text, p_alignment, p_width, p_font_size, p_max_lines, p_size, p_modulate, p_brk_flags, p_jst_flags, p_direction, p_orientation, p_oversampling);
1043
}
1044
1045
void CanvasItem::draw_char(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_char, int p_font_size, const Color &p_modulate, float p_oversampling) const {
1046
ERR_THREAD_GUARD;
1047
ERR_DRAW_GUARD;
1048
ERR_FAIL_COND(p_char.length() != 1);
1049
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1050
1051
p_font->draw_char(canvas_item, p_pos, p_char[0], p_font_size, p_modulate, p_oversampling);
1052
}
1053
1054
void CanvasItem::draw_char_outline(RequiredParam<Font> rp_font, const Point2 &p_pos, const String &p_char, int p_font_size, int p_size, const Color &p_modulate, float p_oversampling) const {
1055
ERR_THREAD_GUARD;
1056
ERR_DRAW_GUARD;
1057
ERR_FAIL_COND(p_char.length() != 1);
1058
EXTRACT_PARAM_OR_FAIL(p_font, rp_font);
1059
1060
p_font->draw_char_outline(canvas_item, p_pos, p_char[0], p_font_size, p_size, p_modulate, p_oversampling);
1061
}
1062
1063
void CanvasItem::_notify_transform_deferred() {
1064
if (is_inside_tree() && notify_transform && !xform_change.in_list()) {
1065
get_tree()->xform_change_list.add(&xform_change);
1066
}
1067
}
1068
1069
void CanvasItem::_notify_transform(CanvasItem *p_node) {
1070
/* This check exists to avoid re-propagating the transform
1071
* notification down the tree on dirty nodes. It provides
1072
* optimization by avoiding redundancy (nodes are dirty, will get the
1073
* notification anyway).
1074
*/
1075
1076
if (/*p_node->xform_change.in_list() &&*/ p_node->_is_global_invalid()) {
1077
return; //nothing to do
1078
}
1079
1080
p_node->_set_global_invalid(true);
1081
1082
if (p_node->notify_transform && !p_node->xform_change.in_list()) {
1083
if (!p_node->block_transform_notify) {
1084
if (p_node->is_inside_tree()) {
1085
if (is_accessible_from_caller_thread()) {
1086
get_tree()->xform_change_list.add(&p_node->xform_change);
1087
} else {
1088
// Should be rare, but still needs to be handled.
1089
callable_mp(p_node, &CanvasItem::_notify_transform_deferred).call_deferred();
1090
}
1091
}
1092
}
1093
}
1094
1095
for (uint32_t n = 0; n < p_node->data.canvas_item_children.size(); n++) {
1096
CanvasItem *ci = p_node->data.canvas_item_children[n];
1097
if (!ci->top_level) {
1098
_notify_transform(ci);
1099
}
1100
}
1101
}
1102
1103
void CanvasItem::_physics_interpolated_changed() {
1104
RenderingServer::get_singleton()->canvas_item_set_interpolated(canvas_item, is_physics_interpolated());
1105
}
1106
1107
void CanvasItem::set_canvas_item_use_identity_transform(bool p_enable) {
1108
// Prevent sending item transforms to RenderingServer when using global coords.
1109
_set_use_identity_transform(p_enable);
1110
1111
// Let RenderingServer know not to concatenate the parent transform during the render.
1112
RenderingServer::get_singleton()->canvas_item_set_use_identity_transform(get_canvas_item(), p_enable);
1113
1114
if (is_inside_tree()) {
1115
if (p_enable) {
1116
// Make sure item is using identity transform in server.
1117
RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), Transform2D());
1118
} else {
1119
// Make sure item transform is up to date in server if switching identity transform off.
1120
RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), get_transform());
1121
}
1122
}
1123
}
1124
1125
Rect2 CanvasItem::get_viewport_rect() const {
1126
ERR_READ_THREAD_GUARD_V(Rect2());
1127
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
1128
return get_viewport()->get_visible_rect();
1129
}
1130
1131
RID CanvasItem::get_canvas() const {
1132
ERR_READ_THREAD_GUARD_V(RID());
1133
ERR_FAIL_COND_V(!is_inside_tree(), RID());
1134
1135
if (canvas_layer) {
1136
return canvas_layer->get_canvas();
1137
} else {
1138
return get_viewport()->find_world_2d()->get_canvas();
1139
}
1140
}
1141
1142
ObjectID CanvasItem::get_canvas_layer_instance_id() const {
1143
ERR_READ_THREAD_GUARD_V(ObjectID());
1144
if (canvas_layer) {
1145
return canvas_layer->get_instance_id();
1146
} else {
1147
return ObjectID();
1148
}
1149
}
1150
1151
CanvasItem *CanvasItem::get_top_level() const {
1152
ERR_READ_THREAD_GUARD_V(nullptr);
1153
CanvasItem *ci = const_cast<CanvasItem *>(this);
1154
while (!ci->top_level && Object::cast_to<CanvasItem>(ci->get_parent())) {
1155
ci = Object::cast_to<CanvasItem>(ci->get_parent());
1156
}
1157
1158
return ci;
1159
}
1160
1161
Ref<World2D> CanvasItem::get_world_2d() const {
1162
ERR_READ_THREAD_GUARD_V(Ref<World2D>());
1163
ERR_FAIL_COND_V(!is_inside_tree(), Ref<World2D>());
1164
1165
CanvasItem *tl = get_top_level();
1166
1167
if (tl->get_viewport()) {
1168
return tl->get_viewport()->find_world_2d();
1169
} else {
1170
return Ref<World2D>();
1171
}
1172
}
1173
1174
RID CanvasItem::get_viewport_rid() const {
1175
ERR_READ_THREAD_GUARD_V(RID());
1176
ERR_FAIL_COND_V(!is_inside_tree(), RID());
1177
return get_viewport()->get_viewport_rid();
1178
}
1179
1180
void CanvasItem::set_block_transform_notify(bool p_enable) {
1181
ERR_THREAD_GUARD;
1182
block_transform_notify = p_enable;
1183
}
1184
1185
bool CanvasItem::is_block_transform_notify_enabled() const {
1186
ERR_READ_THREAD_GUARD_V(false);
1187
return block_transform_notify;
1188
}
1189
1190
void CanvasItem::set_draw_behind_parent(bool p_enable) {
1191
ERR_THREAD_GUARD;
1192
if (behind == p_enable) {
1193
return;
1194
}
1195
behind = p_enable;
1196
RenderingServer::get_singleton()->canvas_item_set_draw_behind_parent(canvas_item, behind);
1197
}
1198
1199
bool CanvasItem::is_draw_behind_parent_enabled() const {
1200
ERR_READ_THREAD_GUARD_V(false);
1201
return behind;
1202
}
1203
1204
void CanvasItem::set_material(const Ref<Material> &p_material) {
1205
ERR_THREAD_GUARD;
1206
material = p_material;
1207
RID rid;
1208
if (material.is_valid()) {
1209
rid = material->get_rid();
1210
}
1211
RS::get_singleton()->canvas_item_set_material(canvas_item, rid);
1212
notify_property_list_changed(); //properties for material exposed
1213
}
1214
1215
void CanvasItem::set_use_parent_material(bool p_use_parent_material) {
1216
ERR_THREAD_GUARD;
1217
use_parent_material = p_use_parent_material;
1218
RS::get_singleton()->canvas_item_set_use_parent_material(canvas_item, p_use_parent_material);
1219
}
1220
1221
void CanvasItem::set_instance_shader_parameter(const StringName &p_name, const Variant &p_value) {
1222
if (p_value.get_type() == Variant::NIL) {
1223
Variant def_value = RS::get_singleton()->canvas_item_get_instance_shader_parameter_default_value(get_canvas_item(), p_name);
1224
RS::get_singleton()->canvas_item_set_instance_shader_parameter(get_canvas_item(), p_name, def_value);
1225
instance_shader_parameters.erase(p_value);
1226
} else {
1227
instance_shader_parameters[p_name] = p_value;
1228
if (p_value.get_type() == Variant::OBJECT) {
1229
RID tex_id = p_value;
1230
RS::get_singleton()->canvas_item_set_instance_shader_parameter(get_canvas_item(), p_name, tex_id);
1231
} else {
1232
RS::get_singleton()->canvas_item_set_instance_shader_parameter(get_canvas_item(), p_name, p_value);
1233
}
1234
}
1235
}
1236
1237
Variant CanvasItem::get_instance_shader_parameter(const StringName &p_name) const {
1238
return RS::get_singleton()->canvas_item_get_instance_shader_parameter(get_canvas_item(), p_name);
1239
}
1240
1241
bool CanvasItem::get_use_parent_material() const {
1242
ERR_READ_THREAD_GUARD_V(false);
1243
return use_parent_material;
1244
}
1245
1246
Ref<Material> CanvasItem::get_material() const {
1247
ERR_READ_THREAD_GUARD_V(Ref<Material>());
1248
return material;
1249
}
1250
1251
Vector2 CanvasItem::make_canvas_position_local(const Vector2 &screen_point) const {
1252
ERR_READ_THREAD_GUARD_V(Vector2());
1253
ERR_FAIL_COND_V(!is_inside_tree(), screen_point);
1254
1255
Transform2D local_matrix = (get_canvas_transform() * get_global_transform()).affine_inverse();
1256
1257
return local_matrix.xform(screen_point);
1258
}
1259
1260
RequiredResult<InputEvent> CanvasItem::make_input_local(RequiredParam<InputEvent> rp_event) const {
1261
ERR_READ_THREAD_GUARD_V(Ref<InputEvent>());
1262
EXTRACT_PARAM_OR_FAIL_V(p_event, rp_event, Ref<InputEvent>());
1263
ERR_FAIL_COND_V(!is_inside_tree(), p_event);
1264
1265
return p_event->xformed_by((get_canvas_transform() * get_global_transform()).affine_inverse());
1266
}
1267
1268
Vector2 CanvasItem::get_global_mouse_position() const {
1269
ERR_READ_THREAD_GUARD_V(Vector2());
1270
ERR_FAIL_NULL_V(get_viewport(), Vector2());
1271
return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_position());
1272
}
1273
1274
Vector2 CanvasItem::get_local_mouse_position() const {
1275
ERR_READ_THREAD_GUARD_V(Vector2());
1276
ERR_FAIL_NULL_V(get_viewport(), Vector2());
1277
1278
return get_global_transform().affine_inverse().xform(get_global_mouse_position());
1279
}
1280
1281
void CanvasItem::force_update_transform() {
1282
ERR_THREAD_GUARD;
1283
ERR_FAIL_COND(!is_inside_tree());
1284
if (!xform_change.in_list()) {
1285
return;
1286
}
1287
1288
get_tree()->xform_change_list.remove(&xform_change);
1289
1290
notification(NOTIFICATION_TRANSFORM_CHANGED);
1291
}
1292
1293
void CanvasItem::_validate_property(PropertyInfo &p_property) const {
1294
if (hide_clip_children && p_property.name == "clip_children") {
1295
p_property.usage = PROPERTY_USAGE_NONE;
1296
}
1297
}
1298
1299
PackedStringArray CanvasItem::get_configuration_warnings() const {
1300
PackedStringArray warnings = Node::get_configuration_warnings();
1301
1302
if (clip_children_mode != CLIP_CHILDREN_DISABLED && is_inside_tree()) {
1303
bool warned_about_ancestor_clipping = false;
1304
bool warned_about_canvasgroup_ancestor = false;
1305
Node *n = get_parent();
1306
while (n) {
1307
CanvasItem *as_canvas_item = Object::cast_to<CanvasItem>(n);
1308
if (!warned_about_ancestor_clipping && as_canvas_item && as_canvas_item->clip_children_mode != CLIP_CHILDREN_DISABLED) {
1309
warnings.push_back(vformat(RTR("Ancestor \"%s\" clips its children, so this node will not be able to clip its children."), as_canvas_item->get_name()));
1310
warned_about_ancestor_clipping = true;
1311
}
1312
1313
CanvasGroup *as_canvas_group = Object::cast_to<CanvasGroup>(n);
1314
if (!warned_about_canvasgroup_ancestor && as_canvas_group) {
1315
warnings.push_back(vformat(RTR("Ancestor \"%s\" is a CanvasGroup, so this node will not be able to clip its children."), as_canvas_group->get_name()));
1316
warned_about_canvasgroup_ancestor = true;
1317
}
1318
1319
// Only break out early once both warnings have been triggered, so
1320
// that the user is aware of both possible reasons for clipping not working.
1321
if (warned_about_ancestor_clipping && warned_about_canvasgroup_ancestor) {
1322
break;
1323
}
1324
n = n->get_parent();
1325
}
1326
}
1327
1328
return warnings;
1329
}
1330
1331
void CanvasItem::_bind_methods() {
1332
ClassDB::bind_method(D_METHOD("_top_level_raise_self"), &CanvasItem::_top_level_raise_self);
1333
1334
#ifdef TOOLS_ENABLED
1335
ClassDB::bind_method(D_METHOD("_edit_set_state", "state"), &CanvasItem::_edit_set_state);
1336
ClassDB::bind_method(D_METHOD("_edit_get_state"), &CanvasItem::_edit_get_state);
1337
ClassDB::bind_method(D_METHOD("_edit_set_position", "position"), &CanvasItem::_edit_set_position);
1338
ClassDB::bind_method(D_METHOD("_edit_get_position"), &CanvasItem::_edit_get_position);
1339
ClassDB::bind_method(D_METHOD("_edit_set_scale", "scale"), &CanvasItem::_edit_set_scale);
1340
ClassDB::bind_method(D_METHOD("_edit_get_scale"), &CanvasItem::_edit_get_scale);
1341
ClassDB::bind_method(D_METHOD("_edit_set_rect", "rect"), &CanvasItem::_edit_set_rect);
1342
ClassDB::bind_method(D_METHOD("_edit_get_rect"), &CanvasItem::_edit_get_rect);
1343
ClassDB::bind_method(D_METHOD("_edit_use_rect"), &CanvasItem::_edit_use_rect);
1344
ClassDB::bind_method(D_METHOD("_edit_set_rotation", "degrees"), &CanvasItem::_edit_set_rotation);
1345
ClassDB::bind_method(D_METHOD("_edit_get_rotation"), &CanvasItem::_edit_get_rotation);
1346
ClassDB::bind_method(D_METHOD("_edit_use_rotation"), &CanvasItem::_edit_use_rotation);
1347
ClassDB::bind_method(D_METHOD("_edit_set_pivot", "pivot"), &CanvasItem::_edit_set_pivot);
1348
ClassDB::bind_method(D_METHOD("_edit_get_pivot"), &CanvasItem::_edit_get_pivot);
1349
ClassDB::bind_method(D_METHOD("_edit_use_pivot"), &CanvasItem::_edit_use_pivot);
1350
ClassDB::bind_method(D_METHOD("_edit_get_transform"), &CanvasItem::_edit_get_transform);
1351
#endif //TOOLS_ENABLED
1352
1353
ClassDB::bind_method(D_METHOD("get_canvas_item"), &CanvasItem::get_canvas_item);
1354
1355
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &CanvasItem::set_visible);
1356
ClassDB::bind_method(D_METHOD("is_visible"), &CanvasItem::is_visible);
1357
ClassDB::bind_method(D_METHOD("is_visible_in_tree"), &CanvasItem::is_visible_in_tree);
1358
ClassDB::bind_method(D_METHOD("show"), &CanvasItem::show);
1359
ClassDB::bind_method(D_METHOD("hide"), &CanvasItem::hide);
1360
1361
ClassDB::bind_method(D_METHOD("queue_redraw"), &CanvasItem::queue_redraw);
1362
ClassDB::bind_method(D_METHOD("move_to_front"), &CanvasItem::move_to_front);
1363
1364
ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &CanvasItem::set_as_top_level);
1365
ClassDB::bind_method(D_METHOD("is_set_as_top_level"), &CanvasItem::is_set_as_top_level);
1366
1367
ClassDB::bind_method(D_METHOD("set_light_mask", "light_mask"), &CanvasItem::set_light_mask);
1368
ClassDB::bind_method(D_METHOD("get_light_mask"), &CanvasItem::get_light_mask);
1369
1370
ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &CanvasItem::set_modulate);
1371
ClassDB::bind_method(D_METHOD("get_modulate"), &CanvasItem::get_modulate);
1372
1373
ClassDB::bind_method(D_METHOD("set_self_modulate", "self_modulate"), &CanvasItem::set_self_modulate);
1374
ClassDB::bind_method(D_METHOD("get_self_modulate"), &CanvasItem::get_self_modulate);
1375
1376
ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &CanvasItem::set_z_index);
1377
ClassDB::bind_method(D_METHOD("get_z_index"), &CanvasItem::get_z_index);
1378
1379
ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &CanvasItem::set_z_as_relative);
1380
ClassDB::bind_method(D_METHOD("is_z_relative"), &CanvasItem::is_z_relative);
1381
1382
ClassDB::bind_method(D_METHOD("set_y_sort_enabled", "enabled"), &CanvasItem::set_y_sort_enabled);
1383
ClassDB::bind_method(D_METHOD("is_y_sort_enabled"), &CanvasItem::is_y_sort_enabled);
1384
1385
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
1386
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
1387
1388
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(-1.0), DEFVAL(false));
1389
ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned", "antialiased"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true), DEFVAL(false));
1390
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(-1.0), DEFVAL(false));
1391
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(-1.0), DEFVAL(false));
1392
ClassDB::bind_method(D_METHOD("draw_ellipse_arc", "center", "major", "minor", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_ellipse_arc, DEFVAL(-1.0), DEFVAL(false));
1393
ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(-1.0), DEFVAL(false));
1394
ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width", "antialiased"), &CanvasItem::draw_multiline, DEFVAL(-1.0), DEFVAL(false));
1395
ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0), DEFVAL(false));
1396
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width", "antialiased"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
1397
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color", "filled", "width", "antialiased"), &CanvasItem::draw_circle, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
1398
ClassDB::bind_method(D_METHOD("draw_ellipse", "position", "major", "minor", "color", "filled", "width", "antialiased"), &CanvasItem::draw_ellipse, DEFVAL(true), DEFVAL(-1.0), DEFVAL(false));
1399
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
1400
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
1401
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
1402
ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range", "scale"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0), DEFVAL(1.0));
1403
ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)));
1404
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
1405
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()));
1406
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
1407
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
1408
ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "justification_flags", "direction", "orientation", "oversampling"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
1409
ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "justification_flags", "direction", "orientation", "oversampling"), &CanvasItem::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
1410
ClassDB::bind_method(D_METHOD("draw_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "justification_flags", "direction", "orientation", "oversampling"), &CanvasItem::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
1411
ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "font", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "justification_flags", "direction", "orientation", "oversampling"), &CanvasItem::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
1412
ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "font_size", "modulate", "oversampling"), &CanvasItem::draw_char, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(0.0));
1413
ClassDB::bind_method(D_METHOD("draw_char_outline", "font", "pos", "char", "font_size", "size", "modulate", "oversampling"), &CanvasItem::draw_char_outline, DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(0.0));
1414
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1)));
1415
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture"), &CanvasItem::draw_multimesh);
1416
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0)));
1417
ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix);
1418
ClassDB::bind_method(D_METHOD("draw_animation_slice", "animation_length", "slice_begin", "slice_end", "offset"), &CanvasItem::draw_animation_slice, DEFVAL(0.0));
1419
ClassDB::bind_method(D_METHOD("draw_end_animation"), &CanvasItem::draw_end_animation);
1420
ClassDB::bind_method(D_METHOD("get_transform"), &CanvasItem::get_transform);
1421
ClassDB::bind_method(D_METHOD("get_global_transform"), &CanvasItem::get_global_transform);
1422
ClassDB::bind_method(D_METHOD("get_global_transform_with_canvas"), &CanvasItem::get_global_transform_with_canvas);
1423
ClassDB::bind_method(D_METHOD("get_viewport_transform"), &CanvasItem::get_viewport_transform);
1424
ClassDB::bind_method(D_METHOD("get_viewport_rect"), &CanvasItem::get_viewport_rect);
1425
ClassDB::bind_method(D_METHOD("get_canvas_transform"), &CanvasItem::get_canvas_transform);
1426
ClassDB::bind_method(D_METHOD("get_screen_transform"), &CanvasItem::get_screen_transform);
1427
ClassDB::bind_method(D_METHOD("get_local_mouse_position"), &CanvasItem::get_local_mouse_position);
1428
ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position);
1429
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas);
1430
ClassDB::bind_method(D_METHOD("get_canvas_layer_node"), &CanvasItem::get_canvas_layer_node);
1431
ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d);
1432
//ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport);
1433
1434
ClassDB::bind_method(D_METHOD("set_material", "material"), &CanvasItem::set_material);
1435
ClassDB::bind_method(D_METHOD("get_material"), &CanvasItem::get_material);
1436
1437
ClassDB::bind_method(D_METHOD("set_instance_shader_parameter", "name", "value"), &CanvasItem::set_instance_shader_parameter);
1438
ClassDB::bind_method(D_METHOD("get_instance_shader_parameter", "name"), &CanvasItem::get_instance_shader_parameter);
1439
1440
ClassDB::bind_method(D_METHOD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material);
1441
ClassDB::bind_method(D_METHOD("get_use_parent_material"), &CanvasItem::get_use_parent_material);
1442
1443
ClassDB::bind_method(D_METHOD("set_notify_local_transform", "enable"), &CanvasItem::set_notify_local_transform);
1444
ClassDB::bind_method(D_METHOD("is_local_transform_notification_enabled"), &CanvasItem::is_local_transform_notification_enabled);
1445
1446
ClassDB::bind_method(D_METHOD("set_notify_transform", "enable"), &CanvasItem::set_notify_transform);
1447
ClassDB::bind_method(D_METHOD("is_transform_notification_enabled"), &CanvasItem::is_transform_notification_enabled);
1448
1449
ClassDB::bind_method(D_METHOD("force_update_transform"), &CanvasItem::force_update_transform);
1450
1451
ClassDB::bind_method(D_METHOD("make_canvas_position_local", "viewport_point"), &CanvasItem::make_canvas_position_local);
1452
ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local);
1453
1454
ClassDB::bind_method(D_METHOD("set_visibility_layer", "layer"), &CanvasItem::set_visibility_layer);
1455
ClassDB::bind_method(D_METHOD("get_visibility_layer"), &CanvasItem::get_visibility_layer);
1456
ClassDB::bind_method(D_METHOD("set_visibility_layer_bit", "layer", "enabled"), &CanvasItem::set_visibility_layer_bit);
1457
ClassDB::bind_method(D_METHOD("get_visibility_layer_bit", "layer"), &CanvasItem::get_visibility_layer_bit);
1458
1459
ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &CanvasItem::set_texture_filter);
1460
ClassDB::bind_method(D_METHOD("get_texture_filter"), &CanvasItem::get_texture_filter);
1461
1462
ClassDB::bind_method(D_METHOD("set_texture_repeat", "mode"), &CanvasItem::set_texture_repeat);
1463
ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasItem::get_texture_repeat);
1464
1465
ClassDB::bind_method(D_METHOD("set_clip_children_mode", "mode"), &CanvasItem::set_clip_children_mode);
1466
ClassDB::bind_method(D_METHOD("get_clip_children_mode"), &CanvasItem::get_clip_children_mode);
1467
1468
GDVIRTUAL_BIND(_draw);
1469
1470
ADD_GROUP("Visibility", "");
1471
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
1472
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
1473
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate");
1474
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled");
1475
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
1476
ADD_PROPERTY(PropertyInfo(Variant::INT, "clip_children", PROPERTY_HINT_ENUM, "Disabled,Clip Only,Clip + Draw"), "set_clip_children_mode", "get_clip_children_mode");
1477
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
1478
ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_layer", PROPERTY_HINT_LAYERS_2D_RENDER), "set_visibility_layer", "get_visibility_layer");
1479
1480
ADD_GROUP("Ordering", "");
1481
ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index");
1482
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative");
1483
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sort_enabled"), "set_y_sort_enabled", "is_y_sort_enabled");
1484
1485
ADD_GROUP("Texture", "texture_");
1486
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
1487
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
1488
1489
ADD_GROUP("Material", "");
1490
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial"), "set_material", "get_material");
1491
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material");
1492
// ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),"set_transform_notify","is_transform_notify_enabled");
1493
1494
// Supply property explicitly; workaround for GH-111431 docs issue.
1495
ADD_PROPERTY_DEFAULT("physics_interpolation_mode", PhysicsInterpolationMode::PHYSICS_INTERPOLATION_MODE_INHERIT);
1496
1497
ADD_SIGNAL(MethodInfo("draw"));
1498
ADD_SIGNAL(MethodInfo("visibility_changed"));
1499
ADD_SIGNAL(MethodInfo("hidden"));
1500
ADD_SIGNAL(MethodInfo("item_rect_changed"));
1501
1502
BIND_CONSTANT(NOTIFICATION_TRANSFORM_CHANGED);
1503
BIND_CONSTANT(NOTIFICATION_LOCAL_TRANSFORM_CHANGED);
1504
BIND_CONSTANT(NOTIFICATION_DRAW);
1505
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
1506
BIND_CONSTANT(NOTIFICATION_ENTER_CANVAS);
1507
BIND_CONSTANT(NOTIFICATION_EXIT_CANVAS);
1508
BIND_CONSTANT(NOTIFICATION_WORLD_2D_CHANGED);
1509
1510
BIND_ENUM_CONSTANT(TEXTURE_FILTER_PARENT_NODE);
1511
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST);
1512
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR);
1513
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS);
1514
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
1515
BIND_ENUM_CONSTANT(TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC);
1516
BIND_ENUM_CONSTANT(TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC);
1517
BIND_ENUM_CONSTANT(TEXTURE_FILTER_MAX);
1518
1519
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_PARENT_NODE);
1520
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_DISABLED);
1521
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED);
1522
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR);
1523
BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MAX);
1524
1525
BIND_ENUM_CONSTANT(CLIP_CHILDREN_DISABLED);
1526
BIND_ENUM_CONSTANT(CLIP_CHILDREN_ONLY);
1527
BIND_ENUM_CONSTANT(CLIP_CHILDREN_AND_DRAW);
1528
BIND_ENUM_CONSTANT(CLIP_CHILDREN_MAX);
1529
}
1530
1531
Transform2D CanvasItem::get_canvas_transform() const {
1532
ERR_READ_THREAD_GUARD_V(Transform2D());
1533
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
1534
1535
if (canvas_layer) {
1536
return canvas_layer->get_final_transform();
1537
} else if (Object::cast_to<CanvasItem>(get_parent())) {
1538
return Object::cast_to<CanvasItem>(get_parent())->get_canvas_transform();
1539
} else {
1540
return get_viewport()->get_canvas_transform();
1541
}
1542
}
1543
1544
Transform2D CanvasItem::get_viewport_transform() const {
1545
ERR_READ_THREAD_GUARD_V(Transform2D());
1546
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
1547
1548
if (canvas_layer) {
1549
return get_viewport()->get_final_transform() * canvas_layer->get_final_transform();
1550
} else {
1551
return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
1552
}
1553
}
1554
1555
void CanvasItem::set_notify_local_transform(bool p_enable) {
1556
ERR_THREAD_GUARD;
1557
notify_local_transform = p_enable;
1558
}
1559
1560
bool CanvasItem::is_local_transform_notification_enabled() const {
1561
ERR_READ_THREAD_GUARD_V(false);
1562
return notify_local_transform;
1563
}
1564
1565
void CanvasItem::set_notify_transform(bool p_enable) {
1566
ERR_THREAD_GUARD;
1567
if (notify_transform == p_enable) {
1568
return;
1569
}
1570
1571
notify_transform = p_enable;
1572
1573
if (notify_transform && is_inside_tree()) {
1574
// This ensures that invalid globals get resolved, so notifications can be received.
1575
_ALLOW_DISCARD_ get_global_transform();
1576
}
1577
}
1578
1579
bool CanvasItem::is_transform_notification_enabled() const {
1580
ERR_READ_THREAD_GUARD_V(false);
1581
return notify_transform;
1582
}
1583
1584
int CanvasItem::get_canvas_layer() const {
1585
ERR_READ_THREAD_GUARD_V(0);
1586
if (canvas_layer) {
1587
return canvas_layer->get_layer();
1588
} else {
1589
return 0;
1590
}
1591
}
1592
1593
CanvasLayer *CanvasItem::get_canvas_layer_node() const {
1594
ERR_READ_THREAD_GUARD_V(nullptr);
1595
return canvas_layer;
1596
}
1597
1598
void CanvasItem::set_visibility_layer(uint32_t p_visibility_layer) {
1599
ERR_THREAD_GUARD;
1600
visibility_layer = p_visibility_layer;
1601
RenderingServer::get_singleton()->canvas_item_set_visibility_layer(canvas_item, p_visibility_layer);
1602
}
1603
1604
uint32_t CanvasItem::get_visibility_layer() const {
1605
ERR_READ_THREAD_GUARD_V(0);
1606
return visibility_layer;
1607
}
1608
1609
void CanvasItem::set_visibility_layer_bit(uint32_t p_visibility_layer, bool p_enable) {
1610
ERR_THREAD_GUARD;
1611
ERR_FAIL_UNSIGNED_INDEX(p_visibility_layer, 32);
1612
if (p_enable) {
1613
set_visibility_layer(visibility_layer | (1 << p_visibility_layer));
1614
} else {
1615
set_visibility_layer(visibility_layer & (~(1 << p_visibility_layer)));
1616
}
1617
}
1618
1619
bool CanvasItem::get_visibility_layer_bit(uint32_t p_visibility_layer) const {
1620
ERR_READ_THREAD_GUARD_V(false);
1621
ERR_FAIL_UNSIGNED_INDEX_V(p_visibility_layer, 32, false);
1622
return (visibility_layer & (1 << p_visibility_layer));
1623
}
1624
1625
void CanvasItem::_refresh_texture_filter_cache() const {
1626
if (!is_inside_tree()) {
1627
return;
1628
}
1629
1630
if (texture_filter == TEXTURE_FILTER_PARENT_NODE) {
1631
CanvasItem *parent_item = get_parent_item();
1632
if (parent_item) {
1633
texture_filter_cache = parent_item->texture_filter_cache;
1634
} else {
1635
texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
1636
}
1637
} else {
1638
texture_filter_cache = RS::CanvasItemTextureFilter(texture_filter);
1639
}
1640
}
1641
1642
void CanvasItem::_update_self_texture_filter(RS::CanvasItemTextureFilter p_texture_filter) {
1643
RS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), p_texture_filter);
1644
queue_redraw();
1645
}
1646
1647
void CanvasItem::_update_texture_filter_changed(bool p_propagate) {
1648
if (!is_inside_tree()) {
1649
return;
1650
}
1651
_refresh_texture_filter_cache();
1652
_update_self_texture_filter(texture_filter_cache);
1653
1654
if (p_propagate) {
1655
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
1656
CanvasItem *ci = data.canvas_item_children[n];
1657
1658
if (!ci->top_level && ci->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
1659
ci->_update_texture_filter_changed(true);
1660
}
1661
}
1662
}
1663
}
1664
1665
void CanvasItem::set_texture_filter(TextureFilter p_texture_filter) {
1666
ERR_MAIN_THREAD_GUARD; // Goes down in the tree, so only main thread can set.
1667
ERR_FAIL_INDEX(p_texture_filter, TEXTURE_FILTER_MAX);
1668
if (texture_filter == p_texture_filter) {
1669
return;
1670
}
1671
texture_filter = p_texture_filter;
1672
_update_texture_filter_changed(true);
1673
notify_property_list_changed();
1674
}
1675
1676
CanvasItem::TextureFilter CanvasItem::get_texture_filter() const {
1677
ERR_READ_THREAD_GUARD_V(TEXTURE_FILTER_NEAREST);
1678
return texture_filter;
1679
}
1680
1681
void CanvasItem::_refresh_texture_repeat_cache() const {
1682
if (!is_inside_tree()) {
1683
return;
1684
}
1685
1686
if (texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
1687
CanvasItem *parent_item = get_parent_item();
1688
if (parent_item) {
1689
texture_repeat_cache = parent_item->texture_repeat_cache;
1690
} else {
1691
texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
1692
}
1693
} else {
1694
texture_repeat_cache = RS::CanvasItemTextureRepeat(texture_repeat);
1695
}
1696
}
1697
1698
void CanvasItem::_update_self_texture_repeat(RS::CanvasItemTextureRepeat p_texture_repeat) {
1699
RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), p_texture_repeat);
1700
queue_redraw();
1701
}
1702
1703
void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
1704
if (!is_inside_tree()) {
1705
return;
1706
}
1707
_refresh_texture_repeat_cache();
1708
_update_self_texture_repeat(texture_repeat_cache);
1709
1710
if (p_propagate) {
1711
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
1712
CanvasItem *ci = data.canvas_item_children[n];
1713
if (!ci->top_level && ci->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
1714
ci->_update_texture_repeat_changed(true);
1715
}
1716
}
1717
}
1718
}
1719
1720
void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) {
1721
ERR_MAIN_THREAD_GUARD; // Goes down in the tree, so only main thread can set.
1722
ERR_FAIL_INDEX(p_texture_repeat, TEXTURE_REPEAT_MAX);
1723
if (texture_repeat == p_texture_repeat) {
1724
return;
1725
}
1726
texture_repeat = p_texture_repeat;
1727
_update_texture_repeat_changed(true);
1728
notify_property_list_changed();
1729
}
1730
1731
void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) {
1732
ERR_THREAD_GUARD;
1733
ERR_FAIL_COND(p_clip_mode >= CLIP_CHILDREN_MAX);
1734
1735
if (clip_children_mode == p_clip_mode) {
1736
return;
1737
}
1738
clip_children_mode = p_clip_mode;
1739
1740
update_configuration_warnings();
1741
1742
if (Object::cast_to<CanvasGroup>(this) != nullptr) {
1743
//avoid accidental bugs, make this not work on CanvasGroup
1744
return;
1745
}
1746
1747
RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CanvasGroupMode(clip_children_mode));
1748
}
1749
1750
CanvasItem::ClipChildrenMode CanvasItem::get_clip_children_mode() const {
1751
ERR_READ_THREAD_GUARD_V(CLIP_CHILDREN_DISABLED);
1752
return clip_children_mode;
1753
}
1754
1755
CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {
1756
ERR_READ_THREAD_GUARD_V(TEXTURE_REPEAT_DISABLED);
1757
return texture_repeat;
1758
}
1759
1760
CanvasItem::TextureFilter CanvasItem::get_texture_filter_in_tree() const {
1761
ERR_READ_THREAD_GUARD_V(TEXTURE_FILTER_NEAREST);
1762
_refresh_texture_filter_cache();
1763
return (TextureFilter)texture_filter_cache;
1764
}
1765
1766
CanvasItem::TextureRepeat CanvasItem::get_texture_repeat_in_tree() const {
1767
ERR_READ_THREAD_GUARD_V(TEXTURE_REPEAT_DISABLED);
1768
_refresh_texture_repeat_cache();
1769
return (TextureRepeat)texture_repeat_cache;
1770
}
1771
1772
CanvasItem::CanvasItem() :
1773
xform_change(this) {
1774
_define_ancestry(AncestralClass::CANVAS_ITEM);
1775
1776
canvas_item = RenderingServer::get_singleton()->canvas_item_create();
1777
}
1778
1779
CanvasItem::~CanvasItem() {
1780
ERR_FAIL_NULL(RenderingServer::get_singleton());
1781
RenderingServer::get_singleton()->free_rid(canvas_item);
1782
}
1783
1784
///////////////////////////////////////////////////////////////////
1785
1786
void CanvasTexture::set_diffuse_texture(const Ref<Texture2D> &p_diffuse) {
1787
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
1788
if (diffuse_texture == p_diffuse) {
1789
return;
1790
}
1791
diffuse_texture = p_diffuse;
1792
1793
RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID();
1794
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE, tex_rid);
1795
emit_changed();
1796
}
1797
Ref<Texture2D> CanvasTexture::get_diffuse_texture() const {
1798
return diffuse_texture;
1799
}
1800
1801
void CanvasTexture::set_normal_texture(const Ref<Texture2D> &p_normal) {
1802
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
1803
if (normal_texture == p_normal) {
1804
return;
1805
}
1806
normal_texture = p_normal;
1807
RID tex_rid = normal_texture.is_valid() ? normal_texture->get_rid() : RID();
1808
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_NORMAL, tex_rid);
1809
emit_changed();
1810
}
1811
Ref<Texture2D> CanvasTexture::get_normal_texture() const {
1812
return normal_texture;
1813
}
1814
1815
void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) {
1816
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
1817
if (specular_texture == p_specular) {
1818
return;
1819
}
1820
specular_texture = p_specular;
1821
RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID();
1822
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid);
1823
emit_changed();
1824
}
1825
1826
Ref<Texture2D> CanvasTexture::get_specular_texture() const {
1827
return specular_texture;
1828
}
1829
1830
void CanvasTexture::set_specular_color(const Color &p_color) {
1831
if (specular == p_color) {
1832
return;
1833
}
1834
specular = p_color;
1835
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
1836
emit_changed();
1837
}
1838
1839
Color CanvasTexture::get_specular_color() const {
1840
return specular;
1841
}
1842
1843
void CanvasTexture::set_specular_shininess(real_t p_shininess) {
1844
if (shininess == p_shininess) {
1845
return;
1846
}
1847
shininess = p_shininess;
1848
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
1849
emit_changed();
1850
}
1851
1852
real_t CanvasTexture::get_specular_shininess() const {
1853
return shininess;
1854
}
1855
1856
void CanvasTexture::set_texture_filter(CanvasItem::TextureFilter p_filter) {
1857
if (texture_filter == p_filter) {
1858
return;
1859
}
1860
texture_filter = p_filter;
1861
RS::get_singleton()->canvas_texture_set_texture_filter(canvas_texture, RS::CanvasItemTextureFilter(p_filter));
1862
emit_changed();
1863
}
1864
CanvasItem::TextureFilter CanvasTexture::get_texture_filter() const {
1865
return texture_filter;
1866
}
1867
1868
void CanvasTexture::set_texture_repeat(CanvasItem::TextureRepeat p_repeat) {
1869
if (texture_repeat == p_repeat) {
1870
return;
1871
}
1872
texture_repeat = p_repeat;
1873
RS::get_singleton()->canvas_texture_set_texture_repeat(canvas_texture, RS::CanvasItemTextureRepeat(p_repeat));
1874
emit_changed();
1875
}
1876
CanvasItem::TextureRepeat CanvasTexture::get_texture_repeat() const {
1877
return texture_repeat;
1878
}
1879
1880
int CanvasTexture::get_width() const {
1881
if (diffuse_texture.is_valid()) {
1882
return diffuse_texture->get_width();
1883
} else {
1884
return 1;
1885
}
1886
}
1887
int CanvasTexture::get_height() const {
1888
if (diffuse_texture.is_valid()) {
1889
return diffuse_texture->get_height();
1890
} else {
1891
return 1;
1892
}
1893
}
1894
1895
bool CanvasTexture::is_pixel_opaque(int p_x, int p_y) const {
1896
if (diffuse_texture.is_valid()) {
1897
return diffuse_texture->is_pixel_opaque(p_x, p_y);
1898
} else {
1899
return false;
1900
}
1901
}
1902
1903
bool CanvasTexture::has_alpha() const {
1904
if (diffuse_texture.is_valid()) {
1905
return diffuse_texture->has_alpha();
1906
} else {
1907
return false;
1908
}
1909
}
1910
1911
Ref<Image> CanvasTexture::get_image() const {
1912
if (diffuse_texture.is_valid()) {
1913
return diffuse_texture->get_image();
1914
} else {
1915
return Ref<Image>();
1916
}
1917
}
1918
1919
RID CanvasTexture::get_rid() const {
1920
return canvas_texture;
1921
}
1922
1923
void CanvasTexture::_bind_methods() {
1924
ClassDB::bind_method(D_METHOD("set_diffuse_texture", "texture"), &CanvasTexture::set_diffuse_texture);
1925
ClassDB::bind_method(D_METHOD("get_diffuse_texture"), &CanvasTexture::get_diffuse_texture);
1926
1927
ClassDB::bind_method(D_METHOD("set_normal_texture", "texture"), &CanvasTexture::set_normal_texture);
1928
ClassDB::bind_method(D_METHOD("get_normal_texture"), &CanvasTexture::get_normal_texture);
1929
1930
ClassDB::bind_method(D_METHOD("set_specular_texture", "texture"), &CanvasTexture::set_specular_texture);
1931
ClassDB::bind_method(D_METHOD("get_specular_texture"), &CanvasTexture::get_specular_texture);
1932
1933
ClassDB::bind_method(D_METHOD("set_specular_color", "color"), &CanvasTexture::set_specular_color);
1934
ClassDB::bind_method(D_METHOD("get_specular_color"), &CanvasTexture::get_specular_color);
1935
1936
ClassDB::bind_method(D_METHOD("set_specular_shininess", "shininess"), &CanvasTexture::set_specular_shininess);
1937
ClassDB::bind_method(D_METHOD("get_specular_shininess"), &CanvasTexture::get_specular_shininess);
1938
1939
ClassDB::bind_method(D_METHOD("set_texture_filter", "filter"), &CanvasTexture::set_texture_filter);
1940
ClassDB::bind_method(D_METHOD("get_texture_filter"), &CanvasTexture::get_texture_filter);
1941
1942
ClassDB::bind_method(D_METHOD("set_texture_repeat", "repeat"), &CanvasTexture::set_texture_repeat);
1943
ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasTexture::get_texture_repeat);
1944
1945
ADD_GROUP("Diffuse", "diffuse_");
1946
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "diffuse_texture", PROPERTY_HINT_RESOURCE_TYPE, Texture2D::get_class_static()), "set_diffuse_texture", "get_diffuse_texture");
1947
ADD_GROUP("NormalMap", "normal_");
1948
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, Texture2D::get_class_static()), "set_normal_texture", "get_normal_texture");
1949
ADD_GROUP("Specular", "specular_");
1950
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "specular_texture", PROPERTY_HINT_RESOURCE_TYPE, Texture2D::get_class_static()), "set_specular_texture", "get_specular_texture");
1951
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color");
1952
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "specular_shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular_shininess", "get_specular_shininess");
1953
ADD_GROUP("Texture", "texture_");
1954
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
1955
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
1956
}
1957
1958
CanvasTexture::CanvasTexture() {
1959
canvas_texture = RS::get_singleton()->canvas_texture_create();
1960
}
1961
CanvasTexture::~CanvasTexture() {
1962
ERR_FAIL_NULL(RenderingServer::get_singleton());
1963
RS::get_singleton()->free_rid(canvas_texture);
1964
}
1965
1966