Path: blob/master/servers/rendering/renderer_canvas_cull.cpp
11351 views
/**************************************************************************/1/* renderer_canvas_cull.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "renderer_canvas_cull.h"3132#include "core/config/project_settings.h"33#include "core/math/geometry_2d.h"34#include "core/math/transform_interpolator.h"35#include "renderer_viewport.h"36#include "rendering_server_default.h"37#include "rendering_server_globals.h"38#include "servers/rendering/storage/texture_storage.h"3940// Use the same antialiasing feather size as StyleBoxFlat's default41// (but doubled, as it's specified for both sides here).42// This value is empirically determined to provide good antialiasing quality43// while not making lines appear too soft.44const static float FEATHER_SIZE = 1.25f;4546static RendererCanvasCull *_canvas_cull_singleton = nullptr;4748void RendererCanvasCull::_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {49Item *item = (Item *)p_tracker->userdata;5051switch (p_notification) {52case Dependency::DEPENDENCY_CHANGED_MATERIAL: {53_canvas_cull_singleton->_item_queue_update(item, true);54} break;55default: {56} break;57}58}5960void RendererCanvasCull::_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {61Item *item = (Item *)p_tracker->userdata;6263if (p_dependency == item->material) {64_canvas_cull_singleton->canvas_item_set_material(item->self, RID());65}66_canvas_cull_singleton->_item_queue_update(item, true);67}6869void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {70RENDER_TIMESTAMP("Cull CanvasItem Tree");7172// This is used to avoid passing the camera transform down the rendering73// function calls, as it won't be used in 99% of cases, because the camera74// transform is normally concatenated with the item global transform.75_current_camera_transform = p_transform;7677memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *));78memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));7980for (int i = 0; i < p_child_item_count; i++) {81_cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, false, p_canvas_cull_mask, Point2(), 1, nullptr);82}8384RendererCanvasRender::Item *list = nullptr;85RendererCanvasRender::Item *list_end = nullptr;8687for (int i = 0; i < z_range; i++) {88if (!z_list[i]) {89continue;90}91if (!list) {92list = z_list[i];93list_end = z_last_list[i];94} else {95list_end->next = z_list[i];96list_end = z_last_list[i];97}98}99100RENDER_TIMESTAMP("Render CanvasItems");101102bool sdf_flag;103RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, sdf_flag, r_render_info);104if (sdf_flag) {105sdf_used = true;106}107}108109void RendererCanvasCull::_collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, RendererCanvasCull::Item *p_material_owner, const Color &p_modulate, RendererCanvasCull::Item **r_items, int &r_index, int &r_ysort_children_count, int p_z, uint32_t p_canvas_cull_mask) {110int child_item_count = p_canvas_item->child_items.size();111RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();112for (int i = 0; i < child_item_count; i++) {113if (child_items[i]->visible) {114if (child_items[i]->visibility_layer & p_canvas_cull_mask) {115// To y-sort according to the item's final position, physics interpolation116// and transform snapping need to be applied before y-sorting.117Transform2D child_xform;118if (!_interpolation_data.interpolation_enabled || !child_items[i]->interpolated) {119child_xform = child_items[i]->xform_curr;120} else {121real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();122TransformInterpolator::interpolate_transform_2d(child_items[i]->xform_prev, child_items[i]->xform_curr, child_xform, f);123}124125if (snapping_2d_transforms_to_pixel) {126child_xform.columns[2] = (child_xform.columns[2] + Point2(0.5, 0.5)).floor();127}128129r_items[r_index] = child_items[i];130child_items[i]->ysort_xform = p_canvas_item->ysort_xform * child_xform;131child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;132child_items[i]->ysort_modulate = p_modulate;133child_items[i]->ysort_index = r_index;134child_items[i]->ysort_parent_abs_z_index = p_z;135136if (!child_items[i]->repeat_source) {137child_items[i]->repeat_size = p_canvas_item->repeat_size;138child_items[i]->repeat_times = p_canvas_item->repeat_times;139child_items[i]->repeat_source_item = p_canvas_item->repeat_source_item;140}141142// Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items.143int abs_z = 0;144if (child_items[i]->z_relative) {145abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);146} else {147abs_z = child_items[i]->z_index;148}149150r_index++;151152if (child_items[i]->sort_y) {153_collect_ysort_children(child_items[i], child_items[i]->use_parent_material ? p_material_owner : child_items[i], p_modulate * child_items[i]->modulate, r_items, r_index, r_ysort_children_count, abs_z, p_canvas_cull_mask);154}155} else {156r_ysort_children_count--;157if (child_items[i]->sort_y) {158r_ysort_children_count -= child_items[i]->ysort_children_count;159}160}161}162}163}164165int RendererCanvasCull::_count_ysort_children(RendererCanvasCull::Item *p_canvas_item) {166int ysort_children_count = 0;167int child_item_count = p_canvas_item->child_items.size();168RendererCanvasCull::Item *const *child_items = p_canvas_item->child_items.ptr();169for (int i = 0; i < child_item_count; i++) {170if (child_items[i]->visible) {171ysort_children_count++;172if (child_items[i]->sort_y) {173if (child_items[i]->ysort_children_count == -1) {174child_items[i]->ysort_children_count = _count_ysort_children(child_items[i]);175}176ysort_children_count += child_items[i]->ysort_children_count;177}178}179}180return ysort_children_count;181}182183void RendererCanvasCull::_mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner) {184do {185ysort_owner->ysort_children_count = -1;186ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.get_or_null(ysort_owner->parent) : nullptr;187} while (ysort_owner && ysort_owner->sort_y);188}189190void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &p_transform, const Rect2 &p_clip_rect, Rect2 p_global_rect, const Color &p_modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *r_canvas_group_from) {191if (ci->copy_back_buffer) {192ci->copy_back_buffer->screen_rect = p_transform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);193}194195if (p_use_canvas_group) {196int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;197if (r_canvas_group_from == nullptr) {198// no list before processing this item, means must put stuff in group from the beginning of list.199r_canvas_group_from = r_z_list[zidx];200} else {201// there was a list before processing, so begin group from this one.202r_canvas_group_from = r_canvas_group_from->next;203}204205if (r_canvas_group_from) {206// Has a place to begin the group from!207208//compute a global rect (in global coords) for children in the same z layer209Rect2 rect_accum;210RendererCanvasRender::Item *c = r_canvas_group_from;211while (c) {212if (c == r_canvas_group_from) {213rect_accum = c->global_rect_cache;214} else {215rect_accum = rect_accum.merge(c->global_rect_cache);216}217218c = c->next;219}220221// We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this.222// If nothing has been drawn, we just take it over and draw it ourselves.223if (ci->canvas_group->fit_empty && (ci->commands == nullptr || (ci->commands->next == nullptr && ci->commands->type == RendererCanvasCull::Item::Command::TYPE_RECT && (static_cast<RendererCanvasCull::Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {224// No commands, or sole command is the one used to draw, so we (re)create the draw command.225ci->clear();226227if (rect_accum == Rect2()) {228rect_accum.size = Size2(1, 1);229}230231rect_accum = rect_accum.grow(ci->canvas_group->fit_margin);232233//draw it?234RendererCanvasRender::Item::CommandRect *crect = ci->alloc_command<RendererCanvasRender::Item::CommandRect>();235236crect->flags = RendererCanvasRender::CANVAS_RECT_IS_GROUP; // so we can recognize it later237crect->rect = p_transform.affine_inverse().xform(rect_accum);238crect->modulate = Color(1, 1, 1, 1);239240//the global rect is used to do the copying, so update it241p_global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin242p_global_rect.position += p_clip_rect.position;243} else {244p_global_rect.position -= p_clip_rect.position;245246p_global_rect = p_global_rect.merge(rect_accum); //must use both rects for this247p_global_rect = p_global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin248249p_global_rect.position += p_clip_rect.position;250}251252// Very important that this is cleared after used in RendererCanvasRender to avoid253// potential crashes.254r_canvas_group_from->canvas_group_owner = ci;255}256}257258if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(p_global_rect, true)) || ci->vp_render || ci->copy_back_buffer) {259// Something to draw?260261if (ci->update_when_visible) {262RenderingServerDefault::redraw_request();263}264265if (ci->commands != nullptr || ci->copy_back_buffer) {266ci->final_transform = !ci->use_identity_transform ? p_transform : _current_camera_transform;267ci->final_modulate = p_modulate * ci->self_modulate;268ci->global_rect_cache = p_global_rect;269ci->global_rect_cache.position -= p_clip_rect.position;270ci->light_masked = false;271272int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;273274if (r_z_last_list[zidx]) {275r_z_last_list[zidx]->next = ci;276r_z_last_list[zidx] = ci;277278} else {279r_z_list[zidx] = ci;280r_z_last_list[zidx] = ci;281}282283ci->z_final = p_z;284285ci->next = nullptr;286}287288if (ci->visibility_notifier) {289if (!ci->visibility_notifier->visible_element.in_list()) {290visibility_notifier_list.add(&ci->visibility_notifier->visible_element);291ci->visibility_notifier->just_visible = true;292}293294ci->visibility_notifier->visible_in_frame = RSG::rasterizer->get_frame_number();295}296} else if (ci->repeat_source) {297// If repeat source does not draw itself it still needs transform updated as its child items' repeat offsets are relative to it.298ci->final_transform = p_transform;299}300}301302void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_parent_xform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_is_already_y_sorted, uint32_t p_canvas_cull_mask, const Point2 &p_repeat_size, int p_repeat_times, RendererCanvasRender::Item *p_repeat_source_item) {303Item *ci = p_canvas_item;304305if (!ci->visible) {306return;307}308309if (!(ci->visibility_layer & p_canvas_cull_mask)) {310return;311}312313if (ci->children_order_dirty) {314ci->child_items.sort_custom<ItemIndexSort>();315ci->children_order_dirty = false;316}317318if (ci->use_parent_material && p_material_owner) {319ci->material_owner = p_material_owner;320} else {321p_material_owner = ci;322ci->material_owner = nullptr;323}324325Color modulate = ci->modulate * p_modulate;326327if (modulate.a < 0.007) {328return;329}330331Rect2 rect = ci->get_rect();332333if (ci->visibility_notifier) {334if (ci->visibility_notifier->area.size != Vector2()) {335rect = rect.merge(ci->visibility_notifier->area);336}337}338339// Always calculate final transform as if not using identity xform.340// This is so the expected transform is passed to children.341// However, if use_identity_xform is set,342// we can override the transform for rendering purposes for this item only.343Transform2D self_xform;344Transform2D final_xform;345if (p_is_already_y_sorted) {346// Y-sorted item's final transform is calculated before y-sorting,347// and is passed as `p_parent_xform` afterwards. No need to recalculate.348final_xform = p_parent_xform;349} else {350if (!_interpolation_data.interpolation_enabled || !ci->interpolated) {351self_xform = ci->xform_curr;352} else {353real_t f = Engine::get_singleton()->get_physics_interpolation_fraction();354TransformInterpolator::interpolate_transform_2d(ci->xform_prev, ci->xform_curr, self_xform, f);355}356357Transform2D parent_xform = p_parent_xform;358359if (snapping_2d_transforms_to_pixel) {360self_xform.columns[2] = (self_xform.columns[2] + Point2(0.5, 0.5)).floor();361parent_xform.columns[2] = (parent_xform.columns[2] + Point2(0.5, 0.5)).floor();362}363364final_xform = parent_xform * self_xform;365}366367Point2 repeat_size = p_repeat_size;368int repeat_times = p_repeat_times;369RendererCanvasRender::Item *repeat_source_item = p_repeat_source_item;370371if (ci->repeat_source) {372repeat_size = ci->repeat_size;373repeat_times = ci->repeat_times;374repeat_source_item = ci;375} else {376ci->repeat_size = repeat_size;377ci->repeat_times = repeat_times;378ci->repeat_source_item = repeat_source_item;379}380381Rect2 global_rect;382if (!p_canvas_item->use_identity_transform) {383global_rect = final_xform.xform(rect);384} else {385global_rect = _current_camera_transform.xform(rect);386}387if (repeat_source_item && (repeat_size.x || repeat_size.y)) {388// Top-left repeated rect.389Rect2 corner_rect = global_rect;390corner_rect.position -= repeat_source_item->final_transform.basis_xform((repeat_times / 2) * repeat_size);391global_rect = corner_rect;392393// Plus top-right repeated rect.394Size2 size_x_offset = repeat_source_item->final_transform.basis_xform(repeat_times * Size2(repeat_size.x, 0));395corner_rect.position += size_x_offset;396global_rect = global_rect.merge(corner_rect);397398// Plus bottom-right repeated rect.399corner_rect.position += repeat_source_item->final_transform.basis_xform(repeat_times * Size2(0, repeat_size.y));400global_rect = global_rect.merge(corner_rect);401402// Plus bottom-left repeated rect.403corner_rect.position -= size_x_offset;404global_rect = global_rect.merge(corner_rect);405}406global_rect.position += p_clip_rect.position;407408int child_item_count = ci->child_items.size();409Item **child_items = ci->child_items.ptrw();410411if (ci->clip) {412if (p_canvas_clip != nullptr) {413ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);414} else {415ci->final_clip_rect = p_clip_rect.intersection(global_rect);416}417if (ci->final_clip_rect.size.width < 0.5 || ci->final_clip_rect.size.height < 0.5) {418// The clip rect area is 0, so don't draw the item.419return;420}421ci->final_clip_rect.position = ci->final_clip_rect.position.round();422ci->final_clip_rect.size = ci->final_clip_rect.size.round();423ci->final_clip_owner = ci;424425} else {426ci->final_clip_owner = p_canvas_clip;427}428429int parent_z = p_z;430if (ci->z_relative) {431p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);432} else {433p_z = ci->z_index;434}435436if (ci->sort_y) {437if (!p_is_already_y_sorted) {438if (ci->ysort_children_count == -1) {439ci->ysort_children_count = _count_ysort_children(ci);440}441442child_item_count = ci->ysort_children_count + 1;443child_items = (Item **)alloca(child_item_count * sizeof(Item *));444445ci->ysort_xform = Transform2D();446ci->ysort_modulate = Color(1, 1, 1, 1) / ci->modulate;447ci->ysort_index = 0;448ci->ysort_parent_abs_z_index = parent_z;449child_items[0] = ci;450int i = 1;451_collect_ysort_children(ci, p_material_owner, Color(1, 1, 1, 1), child_items, i, child_item_count, p_z, p_canvas_cull_mask);452453SortArray<Item *, ItemYSort> sorter;454sorter.sort(child_items, child_item_count);455456for (i = 0; i < child_item_count; i++) {457_cull_canvas_item(child_items[i], final_xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, true, p_canvas_cull_mask, child_items[i]->repeat_size, child_items[i]->repeat_times, child_items[i]->repeat_source_item);458}459} else {460RendererCanvasRender::Item *canvas_group_from = nullptr;461bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);462if (use_canvas_group) {463int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;464canvas_group_from = r_z_last_list[zidx];465}466467_attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, final_xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);468}469} else {470RendererCanvasRender::Item *canvas_group_from = nullptr;471bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);472if (use_canvas_group) {473int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;474canvas_group_from = r_z_last_list[zidx];475}476477for (int i = 0; i < child_item_count; i++) {478if (!child_items[i]->behind && !use_canvas_group) {479continue;480}481_cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, false, p_canvas_cull_mask, repeat_size, repeat_times, repeat_source_item);482}483_attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, final_xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);484for (int i = 0; i < child_item_count; i++) {485if (child_items[i]->behind || use_canvas_group) {486continue;487}488_cull_canvas_item(child_items[i], final_xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, false, p_canvas_cull_mask, repeat_size, repeat_times, repeat_source_item);489}490}491}492493void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) {494RENDER_TIMESTAMP("> Render Canvas");495496sdf_used = false;497snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel;498499if (p_canvas->children_order_dirty) {500p_canvas->child_items.sort();501p_canvas->children_order_dirty = false;502}503504int l = p_canvas->child_items.size();505Canvas::ChildItem *ci = p_canvas->child_items.ptrw();506507_render_canvas_item_tree(p_render_target, ci, l, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask, r_render_info);508509RENDER_TIMESTAMP("< Render Canvas");510}511512bool RendererCanvasCull::was_sdf_used() {513return sdf_used;514}515516RID RendererCanvasCull::canvas_allocate() {517return canvas_owner.allocate_rid();518}519void RendererCanvasCull::canvas_initialize(RID p_rid) {520canvas_owner.initialize_rid(p_rid);521}522523void RendererCanvasCull::canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) {524Canvas *canvas = canvas_owner.get_or_null(p_canvas);525ERR_FAIL_NULL(canvas);526Item *canvas_item = canvas_item_owner.get_or_null(p_item);527ERR_FAIL_NULL(canvas_item);528529int idx = canvas->find_item(canvas_item);530ERR_FAIL_COND(idx == -1);531532bool is_repeat_source = (p_mirroring.x || p_mirroring.y);533canvas_item->repeat_source = is_repeat_source;534canvas_item->repeat_source_item = is_repeat_source ? canvas_item : nullptr;535canvas_item->repeat_size = p_mirroring;536canvas_item->repeat_times = 1;537}538539void RendererCanvasCull::canvas_set_item_repeat(RID p_item, const Point2 &p_repeat_size, int p_repeat_times) {540ERR_FAIL_COND(p_repeat_times < 0);541Item *canvas_item = canvas_item_owner.get_or_null(p_item);542ERR_FAIL_NULL(canvas_item);543544bool is_repeat_source = (p_repeat_size.x || p_repeat_size.y) && p_repeat_times;545canvas_item->repeat_source = is_repeat_source;546canvas_item->repeat_source_item = is_repeat_source ? canvas_item : nullptr;547canvas_item->repeat_size = p_repeat_size;548canvas_item->repeat_times = p_repeat_times;549}550551void RendererCanvasCull::canvas_set_modulate(RID p_canvas, const Color &p_color) {552Canvas *canvas = canvas_owner.get_or_null(p_canvas);553ERR_FAIL_NULL(canvas);554canvas->modulate = p_color;555}556557void RendererCanvasCull::canvas_set_disable_scale(bool p_disable) {558disable_scale = p_disable;559}560561void RendererCanvasCull::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) {562Canvas *canvas = canvas_owner.get_or_null(p_canvas);563ERR_FAIL_NULL(canvas);564565canvas->parent = p_parent;566canvas->parent_scale = p_scale;567}568569RID RendererCanvasCull::canvas_item_allocate() {570return canvas_item_owner.allocate_rid();571}572void RendererCanvasCull::canvas_item_initialize(RID p_rid) {573canvas_item_owner.initialize_rid(p_rid);574Item *instance = canvas_item_owner.get_or_null(p_rid);575instance->self = p_rid;576}577578void RendererCanvasCull::canvas_item_set_parent(RID p_item, RID p_parent) {579Item *canvas_item = canvas_item_owner.get_or_null(p_item);580ERR_FAIL_NULL(canvas_item);581582if (canvas_item->parent.is_valid()) {583if (canvas_owner.owns(canvas_item->parent)) {584Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);585canvas->erase_item(canvas_item);586} else if (canvas_item_owner.owns(canvas_item->parent)) {587Item *item_owner = canvas_item_owner.get_or_null(canvas_item->parent);588item_owner->child_items.erase(canvas_item);589590if (item_owner->sort_y) {591_mark_ysort_dirty(item_owner);592}593}594595canvas_item->parent = RID();596}597598if (p_parent.is_valid()) {599if (canvas_owner.owns(p_parent)) {600Canvas *canvas = canvas_owner.get_or_null(p_parent);601Canvas::ChildItem ci;602ci.item = canvas_item;603canvas->child_items.push_back(ci);604canvas->children_order_dirty = true;605} else if (canvas_item_owner.owns(p_parent)) {606Item *item_owner = canvas_item_owner.get_or_null(p_parent);607item_owner->child_items.push_back(canvas_item);608item_owner->children_order_dirty = true;609610if (item_owner->sort_y) {611_mark_ysort_dirty(item_owner);612}613614} else {615ERR_FAIL_MSG("Invalid parent.");616}617}618619canvas_item->parent = p_parent;620}621622void RendererCanvasCull::canvas_item_set_visible(RID p_item, bool p_visible) {623Item *canvas_item = canvas_item_owner.get_or_null(p_item);624ERR_FAIL_NULL(canvas_item);625626canvas_item->visible = p_visible;627628_mark_ysort_dirty(canvas_item);629}630631void RendererCanvasCull::canvas_item_set_light_mask(RID p_item, int p_mask) {632Item *canvas_item = canvas_item_owner.get_or_null(p_item);633ERR_FAIL_NULL(canvas_item);634635canvas_item->light_mask = p_mask;636}637638void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) {639Item *canvas_item = canvas_item_owner.get_or_null(p_item);640ERR_FAIL_NULL(canvas_item);641642if (_interpolation_data.interpolation_enabled && canvas_item->interpolated) {643if (!canvas_item->on_interpolate_transform_list) {644_interpolation_data.canvas_item_transform_update_list_curr->push_back(p_item);645canvas_item->on_interpolate_transform_list = true;646} else {647DEV_ASSERT(_interpolation_data.canvas_item_transform_update_list_curr->size() > 0);648}649}650651canvas_item->xform_curr = p_transform;652}653654void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) {655Item *canvas_item = canvas_item_owner.get_or_null(p_item);656ERR_FAIL_NULL(canvas_item);657658canvas_item->visibility_layer = p_visibility_layer;659}660661uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) {662Item *canvas_item = canvas_item_owner.get_or_null(p_item);663if (!canvas_item) {664return 0;665}666return canvas_item->visibility_layer;667}668669void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) {670Item *canvas_item = canvas_item_owner.get_or_null(p_item);671ERR_FAIL_NULL(canvas_item);672673canvas_item->clip = p_clip;674}675676void RendererCanvasCull::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) {677Item *canvas_item = canvas_item_owner.get_or_null(p_item);678ERR_FAIL_NULL(canvas_item);679680canvas_item->distance_field = p_enable;681}682683void RendererCanvasCull::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) {684Item *canvas_item = canvas_item_owner.get_or_null(p_item);685ERR_FAIL_NULL(canvas_item);686687canvas_item->custom_rect = p_custom_rect;688canvas_item->rect = p_rect;689}690691void RendererCanvasCull::canvas_item_set_modulate(RID p_item, const Color &p_color) {692Item *canvas_item = canvas_item_owner.get_or_null(p_item);693ERR_FAIL_NULL(canvas_item);694695canvas_item->modulate = p_color;696}697698void RendererCanvasCull::canvas_item_set_self_modulate(RID p_item, const Color &p_color) {699Item *canvas_item = canvas_item_owner.get_or_null(p_item);700ERR_FAIL_NULL(canvas_item);701702canvas_item->self_modulate = p_color;703}704705void RendererCanvasCull::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) {706Item *canvas_item = canvas_item_owner.get_or_null(p_item);707ERR_FAIL_NULL(canvas_item);708709canvas_item->behind = p_enable;710}711712void RendererCanvasCull::canvas_item_set_use_identity_transform(RID p_item, bool p_enable) {713Item *canvas_item = canvas_item_owner.get_or_null(p_item);714ERR_FAIL_NULL(canvas_item);715716canvas_item->use_identity_transform = p_enable;717}718719void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_update) {720Item *canvas_item = canvas_item_owner.get_or_null(p_item);721ERR_FAIL_NULL(canvas_item);722723canvas_item->update_when_visible = p_update;724}725726void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) {727Item *canvas_item = canvas_item_owner.get_or_null(p_item);728ERR_FAIL_NULL(canvas_item);729730Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();731ERR_FAIL_NULL(line);732733Vector2 diff = (p_from - p_to);734Vector2 dir = diff.orthogonal().normalized();735Vector2 t = dir * p_width * 0.5;736737Vector2 begin_left;738Vector2 begin_right;739Vector2 end_left;740Vector2 end_right;741742if (p_width >= 0.0) {743begin_left = p_from + t;744begin_right = p_from - t;745end_left = p_to + t;746end_right = p_to - t;747748line->points[0] = begin_left;749line->points[1] = begin_right;750line->points[2] = end_right;751line->points[3] = end_left;752line->point_count = 4;753} else {754begin_left = p_from;755begin_right = p_from;756end_left = p_to;757end_right = p_to;758759line->points[0] = p_from;760line->points[1] = p_to;761line->point_count = 2;762}763for (uint32_t i = 0; i < line->point_count; i++) {764line->colors[i] = p_color;765}766767if (p_antialiased) {768float border_size = FEATHER_SIZE;769770if (0.0f <= p_width && p_width < 1.0f) {771border_size *= p_width;772}773Vector2 dir2 = diff.normalized();774775Vector2 border = dir * border_size;776Vector2 border2 = dir2 * border_size;777778Color transparent = Color(p_color, 0.0);779780{781Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();782ERR_FAIL_NULL(left_border);783784left_border->points[0] = begin_left;785left_border->points[1] = begin_left + border;786left_border->points[2] = end_left + border;787left_border->points[3] = end_left;788789left_border->colors[0] = p_color;790left_border->colors[1] = transparent;791left_border->colors[2] = transparent;792left_border->colors[3] = p_color;793794left_border->point_count = 4;795}796{797Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();798ERR_FAIL_NULL(right_border);799800right_border->points[0] = begin_right;801right_border->points[1] = begin_right - border;802right_border->points[2] = end_right - border;803right_border->points[3] = end_right;804805right_border->colors[0] = p_color;806right_border->colors[1] = transparent;807right_border->colors[2] = transparent;808right_border->colors[3] = p_color;809810right_border->point_count = 4;811}812{813Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();814ERR_FAIL_NULL(top_border);815816top_border->points[0] = begin_left;817top_border->points[1] = begin_left + border2;818top_border->points[2] = begin_right + border2;819top_border->points[3] = begin_right;820821top_border->colors[0] = p_color;822top_border->colors[1] = transparent;823top_border->colors[2] = transparent;824top_border->colors[3] = p_color;825826top_border->point_count = 4;827}828{829Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();830ERR_FAIL_NULL(bottom_border);831832bottom_border->points[0] = end_left;833bottom_border->points[1] = end_left - border2;834bottom_border->points[2] = end_right - border2;835bottom_border->points[3] = end_right;836837bottom_border->colors[0] = p_color;838bottom_border->colors[1] = transparent;839bottom_border->colors[2] = transparent;840bottom_border->colors[3] = p_color;841842bottom_border->point_count = 4;843}844{845Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();846ERR_FAIL_NULL(top_left_corner);847848top_left_corner->points[0] = begin_left;849top_left_corner->points[1] = begin_left + border2;850top_left_corner->points[2] = begin_left + border + border2;851top_left_corner->points[3] = begin_left + border;852853top_left_corner->colors[0] = p_color;854top_left_corner->colors[1] = transparent;855top_left_corner->colors[2] = transparent;856top_left_corner->colors[3] = transparent;857858top_left_corner->point_count = 4;859}860{861Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();862ERR_FAIL_NULL(top_right_corner);863864top_right_corner->points[0] = begin_right;865top_right_corner->points[1] = begin_right + border2;866top_right_corner->points[2] = begin_right - border + border2;867top_right_corner->points[3] = begin_right - border;868869top_right_corner->colors[0] = p_color;870top_right_corner->colors[1] = transparent;871top_right_corner->colors[2] = transparent;872top_right_corner->colors[3] = transparent;873874top_right_corner->point_count = 4;875}876{877Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();878ERR_FAIL_NULL(bottom_left_corner);879880bottom_left_corner->points[0] = end_left;881bottom_left_corner->points[1] = end_left - border2;882bottom_left_corner->points[2] = end_left + border - border2;883bottom_left_corner->points[3] = end_left + border;884885bottom_left_corner->colors[0] = p_color;886bottom_left_corner->colors[1] = transparent;887bottom_left_corner->colors[2] = transparent;888bottom_left_corner->colors[3] = transparent;889890bottom_left_corner->point_count = 4;891}892{893Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();894ERR_FAIL_NULL(bottom_right_corner);895896bottom_right_corner->points[0] = end_right;897bottom_right_corner->points[1] = end_right - border2;898bottom_right_corner->points[2] = end_right - border - border2;899bottom_right_corner->points[3] = end_right - border;900901bottom_right_corner->colors[0] = p_color;902bottom_right_corner->colors[1] = transparent;903bottom_right_corner->colors[2] = transparent;904bottom_right_corner->colors[3] = transparent;905906bottom_right_corner->point_count = 4;907}908}909}910911static Vector2 compute_polyline_segment_dir(const Vector<Point2> &p_points, int p_index, const Vector2 &p_prev_segment_dir) {912int point_count = p_points.size();913914bool is_last_point = (p_index == point_count - 1);915916Vector2 segment_dir;917918if (is_last_point) {919segment_dir = p_prev_segment_dir;920} else {921segment_dir = (p_points[p_index + 1] - p_points[p_index]).normalized();922923if (segment_dir.is_zero_approx()) {924segment_dir = p_prev_segment_dir;925}926}927928return segment_dir;929}930931static Vector2 compute_polyline_edge_offset_clamped(const Vector2 &p_segment_dir, const Vector2 &p_prev_segment_dir) {932Vector2 bisector;933float length = 1.0f;934935bisector = (p_prev_segment_dir * p_segment_dir.length() - p_segment_dir * p_prev_segment_dir.length()).normalized();936937float angle = std::atan2(bisector.cross(p_prev_segment_dir), bisector.dot(p_prev_segment_dir));938float sin_angle = std::sin(angle);939940if (!Math::is_zero_approx(sin_angle) && !p_segment_dir.is_equal_approx(p_prev_segment_dir)) {941length = 1.0f / sin_angle;942length = CLAMP(length, -3.0f, 3.0f);943} else {944bisector = p_segment_dir.orthogonal();945}946947if (bisector.is_zero_approx()) {948bisector = p_segment_dir.orthogonal();949}950951return bisector * length;952}953954void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {955ERR_FAIL_COND(p_points.size() < 2);956Item *canvas_item = canvas_item_owner.get_or_null(p_item);957ERR_FAIL_NULL(canvas_item);958959Color color = Color(1, 1, 1, 1);960961Vector<int> indices;962int point_count = p_points.size();963964Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();965ERR_FAIL_NULL(pline);966967if (p_width < 0) {968if (p_antialiased) {969WARN_PRINT("Antialiasing is not supported for thin polylines drawn using line strips (`p_width < 0`).");970}971972pline->primitive = RS::PRIMITIVE_LINE_STRIP;973974if (p_colors.size() == 1 || p_colors.size() == point_count) {975pline->polygon.create(indices, p_points, p_colors);976} else {977Vector<Color> colors;978if (p_colors.is_empty()) {979colors.push_back(color);980} else {981colors.resize(point_count);982Color *colors_ptr = colors.ptrw();983for (int i = 0; i < point_count; i++) {984if (i < p_colors.size()) {985color = p_colors[i];986}987colors_ptr[i] = color;988}989}990pline->polygon.create(indices, p_points, colors);991}992return;993}994995int polyline_point_count = point_count * 2;996997bool loop = p_points[0].is_equal_approx(p_points[point_count - 1]);998Vector2 first_segment_dir;999Vector2 last_segment_dir;10001001// Search for first non-zero vector between two segments.1002for (int i = 1; i < point_count; i++) {1003first_segment_dir = (p_points[i] - p_points[i - 1]).normalized();10041005if (!first_segment_dir.is_zero_approx()) {1006break;1007}1008}10091010// Search for last non-zero vector between two segments.1011for (int i = point_count - 1; i >= 1; i--) {1012last_segment_dir = (p_points[i] - p_points[i - 1]).normalized();10131014if (!last_segment_dir.is_zero_approx()) {1015break;1016}1017}10181019PackedColorArray colors;1020PackedVector2Array points;10211022// Additional 2+2 vertices to antialias begin+end of the middle triangle strip.1023colors.resize(polyline_point_count + ((p_antialiased && !loop) ? 4 : 0));1024points.resize(polyline_point_count + ((p_antialiased && !loop) ? 4 : 0));10251026Vector2 *points_ptr = points.ptrw();1027Color *colors_ptr = colors.ptrw();10281029if (p_antialiased) {1030float border_size = FEATHER_SIZE;1031if (p_width < 1.0f) {1032border_size *= p_width;1033}1034Color color2 = Color(1, 1, 1, 0);10351036Item::CommandPolygon *pline_left = canvas_item->alloc_command<Item::CommandPolygon>();1037ERR_FAIL_NULL(pline_left);10381039Item::CommandPolygon *pline_right = canvas_item->alloc_command<Item::CommandPolygon>();1040ERR_FAIL_NULL(pline_right);10411042PackedColorArray colors_left;1043PackedVector2Array points_left;10441045PackedColorArray colors_right;1046PackedVector2Array points_right;10471048// 2+2 additional vertices for begin+end corners.1049// 1 additional vertex to swap the orientation of the triangles within the end corner's quad.1050colors_left.resize(polyline_point_count + (loop ? 0 : 5));1051points_left.resize(polyline_point_count + (loop ? 0 : 5));10521053colors_right.resize(polyline_point_count + (loop ? 0 : 5));1054points_right.resize(polyline_point_count + (loop ? 0 : 5));10551056Color *colors_left_ptr = colors_left.ptrw();1057Vector2 *points_left_ptr = points_left.ptrw();10581059Vector2 *points_right_ptr = points_right.ptrw();1060Color *colors_right_ptr = colors_right.ptrw();10611062Vector2 prev_segment_dir;1063for (int i = 0; i < point_count; i++) {1064bool is_first_point = (i == 0);1065bool is_last_point = (i == point_count - 1);10661067Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir);1068if (is_first_point && loop) {1069prev_segment_dir = last_segment_dir;1070} else if (is_last_point && loop) {1071prev_segment_dir = first_segment_dir;1072}10731074Vector2 base_edge_offset;1075if (is_first_point && !loop) {1076base_edge_offset = first_segment_dir.orthogonal();1077} else if (is_last_point && !loop) {1078base_edge_offset = last_segment_dir.orthogonal();1079} else {1080base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir);1081}10821083Vector2 edge_offset = base_edge_offset * (p_width * 0.5f);1084Vector2 border = base_edge_offset * border_size;1085Vector2 pos = p_points[i];10861087int j = i * 2 + (loop ? 0 : 2);10881089points_ptr[j + 0] = pos + edge_offset;1090points_ptr[j + 1] = pos - edge_offset;10911092points_left_ptr[j + 0] = pos + edge_offset;1093points_left_ptr[j + 1] = pos + edge_offset + border;10941095points_right_ptr[j + 0] = pos - edge_offset;1096points_right_ptr[j + 1] = pos - edge_offset - border;10971098if (i < p_colors.size()) {1099color = p_colors[i];1100color2 = Color(color.r, color.g, color.b, 0);1101}11021103colors_ptr[j + 0] = color;1104colors_ptr[j + 1] = color;11051106colors_left_ptr[j + 0] = color;1107colors_left_ptr[j + 1] = color2;11081109colors_right_ptr[j + 0] = color;1110colors_right_ptr[j + 1] = color2;11111112if (is_first_point && !loop) {1113Vector2 begin_border = -segment_dir * border_size;11141115points_ptr[0] = pos + edge_offset + begin_border;1116points_ptr[1] = pos - edge_offset + begin_border;11171118colors_ptr[0] = color2;1119colors_ptr[1] = color2;11201121points_left_ptr[0] = pos + edge_offset + begin_border;1122points_left_ptr[1] = pos + edge_offset + begin_border + border;11231124colors_left_ptr[0] = color2;1125colors_left_ptr[1] = color2;11261127points_right_ptr[0] = pos - edge_offset + begin_border;1128points_right_ptr[1] = pos - edge_offset + begin_border - border;11291130colors_right_ptr[0] = color2;1131colors_right_ptr[1] = color2;1132}11331134if (is_last_point && !loop) {1135Vector2 end_border = prev_segment_dir * border_size;1136int end_index = polyline_point_count + 2;11371138points_ptr[end_index + 0] = pos + edge_offset + end_border;1139points_ptr[end_index + 1] = pos - edge_offset + end_border;11401141colors_ptr[end_index + 0] = color2;1142colors_ptr[end_index + 1] = color2;11431144// Swap orientation of the triangles within both end corner quads so the visual seams1145// between triangles goes from the edge corner. Done by going back to the edge corner1146// (1 additional vertex / zero-area triangle per left/right corner).1147points_left_ptr[end_index + 0] = pos + edge_offset;1148points_left_ptr[end_index + 1] = pos + edge_offset + end_border + border;1149points_left_ptr[end_index + 2] = pos + edge_offset + end_border;11501151colors_left_ptr[end_index + 0] = color;1152colors_left_ptr[end_index + 1] = color2;1153colors_left_ptr[end_index + 2] = color2;11541155points_right_ptr[end_index + 0] = pos - edge_offset;1156points_right_ptr[end_index + 1] = pos - edge_offset + end_border - border;1157points_right_ptr[end_index + 2] = pos - edge_offset + end_border;11581159colors_right_ptr[end_index + 0] = color;1160colors_right_ptr[end_index + 1] = color2;1161colors_right_ptr[end_index + 2] = color2;1162}11631164prev_segment_dir = segment_dir;1165}11661167pline_left->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;1168pline_left->polygon.create(indices, points_left, colors_left);11691170pline_right->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;1171pline_right->polygon.create(indices, points_right, colors_right);1172} else {1173// Makes a single triangle strip for drawing the line.11741175Vector2 prev_segment_dir;1176for (int i = 0; i < point_count; i++) {1177bool is_first_point = (i == 0);1178bool is_last_point = (i == point_count - 1);11791180Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir);1181if (is_first_point && loop) {1182prev_segment_dir = last_segment_dir;1183} else if (is_last_point && loop) {1184prev_segment_dir = first_segment_dir;1185}11861187Vector2 base_edge_offset;1188if (is_first_point && !loop) {1189base_edge_offset = first_segment_dir.orthogonal();1190} else if (is_last_point && !loop) {1191base_edge_offset = last_segment_dir.orthogonal();1192} else {1193base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir);1194}11951196Vector2 edge_offset = base_edge_offset * (p_width * 0.5f);1197Vector2 pos = p_points[i];11981199points_ptr[i * 2 + 0] = pos + edge_offset;1200points_ptr[i * 2 + 1] = pos - edge_offset;12011202if (i < p_colors.size()) {1203color = p_colors[i];1204}12051206colors_ptr[i * 2 + 0] = color;1207colors_ptr[i * 2 + 1] = color;12081209prev_segment_dir = segment_dir;1210}1211}12121213pline->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;1214pline->polygon.create(indices, points, colors);1215}12161217void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {1218ERR_FAIL_COND(p_points.is_empty() || p_points.size() % 2 != 0);1219ERR_FAIL_COND(p_colors.size() != 1 && p_colors.size() * 2 != p_points.size());12201221// TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.1222if (p_width < 0) {1223if (p_antialiased) {1224WARN_PRINT("Antialiasing is not supported for thin multilines drawn using line strips (`p_width < 0`).");1225}1226Item *canvas_item = canvas_item_owner.get_or_null(p_item);1227ERR_FAIL_NULL(canvas_item);12281229Vector<Color> colors;1230if (p_colors.size() == 1) {1231colors = p_colors;1232} else { //} else if (p_colors.size() << 1 == p_points.size()) {1233colors.resize(p_points.size());1234Color *colors_ptr = colors.ptrw();1235for (int i = 0; i < p_colors.size(); i++) {1236Color color = p_colors[i];1237colors_ptr[i * 2 + 0] = color;1238colors_ptr[i * 2 + 1] = color;1239}1240}12411242Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();1243ERR_FAIL_NULL(pline);1244pline->primitive = RS::PRIMITIVE_LINES;1245pline->polygon.create(Vector<int>(), p_points, colors);1246} else {1247if (p_colors.size() == 1) {1248Color color = p_colors[0];1249for (int i = 0; i < p_points.size() >> 1; i++) {1250Vector2 from = p_points[i * 2 + 0];1251Vector2 to = p_points[i * 2 + 1];12521253canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);1254}1255} else { //} else if (p_colors.size() << 1 == p_points.size()) {1256for (int i = 0; i < p_colors.size(); i++) {1257Color color = p_colors[i];1258Vector2 from = p_points[i * 2 + 0];1259Vector2 to = p_points[i * 2 + 1];12601261canvas_item_add_line(p_item, from, to, color, p_width, p_antialiased);1262}1263}1264}1265}12661267void RendererCanvasCull::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color, bool p_antialiased) {1268Item *canvas_item = canvas_item_owner.get_or_null(p_item);1269ERR_FAIL_NULL(canvas_item);12701271Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();1272ERR_FAIL_NULL(rect);1273rect->modulate = p_color;1274rect->rect = p_rect;12751276// Add feathers.1277if (p_antialiased) {1278float border_size = FEATHER_SIZE;12791280const real_t size = MIN(p_rect.size.width, p_rect.size.height);1281if (0.0f <= size && size < 1.0f) {1282border_size *= size;1283}12841285const Vector2 vec_down = Vector2(0.0f, p_rect.size.height);1286const Vector2 vec_right = Vector2(p_rect.size.width, 0.0f);12871288const Vector2 begin_left = p_rect.position;1289const Vector2 begin_right = p_rect.position + vec_down;1290const Vector2 end_left = p_rect.position + vec_right;1291const Vector2 end_right = p_rect.position + p_rect.size;12921293const Vector2 dir = Vector2(0.0f, -1.0f);1294const Vector2 dir2 = Vector2(-1.0f, 0.0f);1295const Vector2 border = dir * border_size;1296const Vector2 border2 = dir2 * border_size;12971298Color transparent = Color(p_color, 0.0);12991300{1301Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();1302ERR_FAIL_NULL(left_border);13031304left_border->points[0] = begin_left;1305left_border->points[1] = begin_left + border;1306left_border->points[2] = end_left + border;1307left_border->points[3] = end_left;13081309left_border->colors[0] = p_color;1310left_border->colors[1] = transparent;1311left_border->colors[2] = transparent;1312left_border->colors[3] = p_color;13131314left_border->point_count = 4;1315}1316{1317Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();1318ERR_FAIL_NULL(right_border);13191320right_border->points[0] = begin_right;1321right_border->points[1] = begin_right - border;1322right_border->points[2] = end_right - border;1323right_border->points[3] = end_right;13241325right_border->colors[0] = p_color;1326right_border->colors[1] = transparent;1327right_border->colors[2] = transparent;1328right_border->colors[3] = p_color;13291330right_border->point_count = 4;1331}1332{1333Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();1334ERR_FAIL_NULL(top_border);13351336top_border->points[0] = begin_left;1337top_border->points[1] = begin_left + border2;1338top_border->points[2] = begin_right + border2;1339top_border->points[3] = begin_right;13401341top_border->colors[0] = p_color;1342top_border->colors[1] = transparent;1343top_border->colors[2] = transparent;1344top_border->colors[3] = p_color;13451346top_border->point_count = 4;1347}1348{1349Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();1350ERR_FAIL_NULL(bottom_border);13511352bottom_border->points[0] = end_left;1353bottom_border->points[1] = end_left - border2;1354bottom_border->points[2] = end_right - border2;1355bottom_border->points[3] = end_right;13561357bottom_border->colors[0] = p_color;1358bottom_border->colors[1] = transparent;1359bottom_border->colors[2] = transparent;1360bottom_border->colors[3] = p_color;13611362bottom_border->point_count = 4;1363}1364{1365Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();1366ERR_FAIL_NULL(top_left_corner);13671368top_left_corner->points[0] = begin_left;1369top_left_corner->points[1] = begin_left + border2;1370top_left_corner->points[2] = begin_left + border + border2;1371top_left_corner->points[3] = begin_left + border;13721373top_left_corner->colors[0] = p_color;1374top_left_corner->colors[1] = transparent;1375top_left_corner->colors[2] = transparent;1376top_left_corner->colors[3] = transparent;13771378top_left_corner->point_count = 4;1379}1380{1381Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();1382ERR_FAIL_NULL(top_right_corner);13831384top_right_corner->points[0] = begin_right;1385top_right_corner->points[1] = begin_right + border2;1386top_right_corner->points[2] = begin_right - border + border2;1387top_right_corner->points[3] = begin_right - border;13881389top_right_corner->colors[0] = p_color;1390top_right_corner->colors[1] = transparent;1391top_right_corner->colors[2] = transparent;1392top_right_corner->colors[3] = transparent;13931394top_right_corner->point_count = 4;1395}1396{1397Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();1398ERR_FAIL_NULL(bottom_left_corner);13991400bottom_left_corner->points[0] = end_left;1401bottom_left_corner->points[1] = end_left - border2;1402bottom_left_corner->points[2] = end_left + border - border2;1403bottom_left_corner->points[3] = end_left + border;14041405bottom_left_corner->colors[0] = p_color;1406bottom_left_corner->colors[1] = transparent;1407bottom_left_corner->colors[2] = transparent;1408bottom_left_corner->colors[3] = transparent;14091410bottom_left_corner->point_count = 4;1411}1412{1413Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();1414ERR_FAIL_NULL(bottom_right_corner);14151416bottom_right_corner->points[0] = end_right;1417bottom_right_corner->points[1] = end_right - border2;1418bottom_right_corner->points[2] = end_right - border - border2;1419bottom_right_corner->points[3] = end_right - border;14201421bottom_right_corner->colors[0] = p_color;1422bottom_right_corner->colors[1] = transparent;1423bottom_right_corner->colors[2] = transparent;1424bottom_right_corner->colors[3] = transparent;14251426bottom_right_corner->point_count = 4;1427}1428}1429}14301431void RendererCanvasCull::canvas_item_add_ellipse(RID p_item, const Point2 &p_pos, float p_major, float p_minor, const Color &p_color, bool p_antialiased) {1432Item *canvas_item = canvas_item_owner.get_or_null(p_item);1433ERR_FAIL_NULL(canvas_item);14341435static const int ellipse_segments = 64;14361437{1438Item::CommandPolygon *ellipse = canvas_item->alloc_command<Item::CommandPolygon>();1439ERR_FAIL_NULL(ellipse);14401441ellipse->primitive = RS::PRIMITIVE_TRIANGLES;14421443Vector<int> indices;1444Vector<Vector2> points;14451446points.resize(ellipse_segments + 2);1447Vector2 *points_ptr = points.ptrw();14481449// Store ellipse center in the last point.1450points_ptr[ellipse_segments + 1] = p_pos;14511452const real_t ellipse_point_step = Math::TAU / ellipse_segments;14531454for (int i = 0; i < ellipse_segments + 1; i++) {1455float angle = i * ellipse_point_step;1456points_ptr[i].x = Math::cos(angle) * p_major;1457points_ptr[i].y = Math::sin(angle) * p_minor;1458points_ptr[i] += p_pos;1459}14601461indices.resize(ellipse_segments * 3);1462int *indices_ptr = indices.ptrw();14631464for (int i = 0; i < ellipse_segments; i++) {1465indices_ptr[i * 3 + 0] = ellipse_segments + 1;1466indices_ptr[i * 3 + 1] = i;1467indices_ptr[i * 3 + 2] = i + 1;1468}14691470Vector<Color> color;1471color.push_back(p_color);1472ellipse->polygon.create(indices, points, color);1473}14741475if (p_antialiased) {1476float border_size = FEATHER_SIZE;14771478const float max_axis = fmax(p_major, p_minor) * 2.0f;1479if (0.0f <= max_axis && max_axis < 1.0f) {1480border_size *= max_axis * 0.5f;1481}14821483Item::CommandPolygon *feather = canvas_item->alloc_command<Item::CommandPolygon>();1484ERR_FAIL_NULL(feather);1485feather->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;14861487Color transparent = Color(p_color, 0.0);14881489Vector<int> indices;1490Vector<Color> colors;1491Vector<Vector2> points;14921493points.resize(2 * ellipse_segments + 2);1494colors.resize(2 * ellipse_segments + 2);14951496const real_t ellipse_point_step = Math::TAU / ellipse_segments;14971498Vector2 *points_ptr = points.ptrw();1499Color *colors_ptr = colors.ptrw();15001501for (int i = 0; i < ellipse_segments + 1; i++) {1502const float angle = i * ellipse_point_step;1503const float c = Math::cos(angle);1504const float s = Math::sin(angle);15051506points_ptr[i * 2].x = c * p_major;1507points_ptr[i * 2].y = s * p_minor;1508points_ptr[i * 2] += p_pos;15091510points_ptr[i * 2 + 1].x = c * (p_major + border_size);1511points_ptr[i * 2 + 1].y = s * (p_minor + border_size);1512points_ptr[i * 2 + 1] += p_pos;15131514colors_ptr[i * 2] = p_color;1515colors_ptr[i * 2 + 1] = transparent;1516}15171518feather->polygon.create(indices, points, colors);1519}1520}15211522void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color, bool p_antialiased) {1523canvas_item_add_ellipse(p_item, p_pos, p_radius, p_radius, p_color, p_antialiased);1524}15251526void RendererCanvasCull::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) {1527Item *canvas_item = canvas_item_owner.get_or_null(p_item);1528ERR_FAIL_NULL(canvas_item);15291530Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();1531ERR_FAIL_NULL(rect);1532rect->modulate = p_modulate;1533rect->rect = p_rect;1534rect->flags = 0;1535if (p_tile) {1536rect->flags |= RendererCanvasRender::CANVAS_RECT_TILE;1537rect->flags |= RendererCanvasRender::CANVAS_RECT_REGION;1538rect->source = Rect2(0, 0, Math::abs(p_rect.size.width), Math::abs(p_rect.size.height));1539}15401541if (p_rect.size.x < 0) {1542rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;1543rect->rect.size.x = -rect->rect.size.x;1544}1545if (p_rect.size.y < 0) {1546rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;1547rect->rect.size.y = -rect->rect.size.y;1548}1549if (p_transpose) {1550rect->flags |= RendererCanvasRender::CANVAS_RECT_TRANSPOSE;1551SWAP(rect->rect.size.x, rect->rect.size.y);1552}15531554rect->texture = p_texture;1555}15561557void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, int p_outline_size, float p_px_range, float p_scale) {1558Item *canvas_item = canvas_item_owner.get_or_null(p_item);1559ERR_FAIL_NULL(canvas_item);15601561Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();1562ERR_FAIL_NULL(rect);1563rect->modulate = p_modulate;1564rect->rect = p_rect;15651566rect->texture = p_texture;15671568rect->source = p_src_rect;1569rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_MSDF;15701571if (p_rect.size.x < 0) {1572rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;1573rect->rect.size.x = -rect->rect.size.x;1574}1575if (p_src_rect.size.x < 0) {1576rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;1577rect->source.size.x = -rect->source.size.x;1578}1579if (p_rect.size.y < 0) {1580rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;1581rect->rect.size.y = -rect->rect.size.y;1582}1583if (p_src_rect.size.y < 0) {1584rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;1585rect->source.size.y = -rect->source.size.y;1586}1587rect->outline = (float)p_outline_size / p_scale / 4.0;1588rect->px_range = p_px_range;1589}15901591void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) {1592Item *canvas_item = canvas_item_owner.get_or_null(p_item);1593ERR_FAIL_NULL(canvas_item);15941595Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();1596ERR_FAIL_NULL(rect);1597rect->modulate = p_modulate;1598rect->rect = p_rect;15991600rect->texture = p_texture;16011602rect->source = p_src_rect;1603rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD;16041605if (p_rect.size.x < 0) {1606rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;1607rect->rect.size.x = -rect->rect.size.x;1608}1609if (p_src_rect.size.x < 0) {1610rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;1611rect->source.size.x = -rect->source.size.x;1612}1613if (p_rect.size.y < 0) {1614rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;1615rect->rect.size.y = -rect->rect.size.y;1616}1617if (p_src_rect.size.y < 0) {1618rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;1619rect->source.size.y = -rect->source.size.y;1620}1621}16221623void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {1624Item *canvas_item = canvas_item_owner.get_or_null(p_item);1625ERR_FAIL_NULL(canvas_item);16261627Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();1628ERR_FAIL_NULL(rect);1629rect->modulate = p_modulate;1630rect->rect = p_rect;16311632rect->texture = p_texture;16331634rect->source = p_src_rect;1635rect->flags = RendererCanvasRender::CANVAS_RECT_REGION;16361637if (p_rect.size.x < 0) {1638rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;1639rect->rect.size.x = -rect->rect.size.x;1640}1641if (p_src_rect.size.x < 0) {1642rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;1643rect->source.size.x = -rect->source.size.x;1644}1645if (p_rect.size.y < 0) {1646rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;1647rect->rect.size.y = -rect->rect.size.y;1648}1649if (p_src_rect.size.y < 0) {1650rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;1651rect->source.size.y = -rect->source.size.y;1652}16531654if (p_transpose) {1655rect->flags |= RendererCanvasRender::CANVAS_RECT_TRANSPOSE;1656SWAP(rect->rect.size.x, rect->rect.size.y);1657}16581659if (p_clip_uv) {1660rect->flags |= RendererCanvasRender::CANVAS_RECT_CLIP_UV;1661}1662}16631664void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate) {1665Item *canvas_item = canvas_item_owner.get_or_null(p_item);1666ERR_FAIL_NULL(canvas_item);16671668Item::CommandNinePatch *style = canvas_item->alloc_command<Item::CommandNinePatch>();1669ERR_FAIL_NULL(style);16701671style->texture = p_texture;16721673style->rect = p_rect;1674style->source = p_source;1675style->draw_center = p_draw_center;1676style->color = p_modulate;1677style->margin[SIDE_LEFT] = p_topleft.x;1678style->margin[SIDE_TOP] = p_topleft.y;1679style->margin[SIDE_RIGHT] = p_bottomright.x;1680style->margin[SIDE_BOTTOM] = p_bottomright.y;1681style->axis_x = p_x_axis_mode;1682style->axis_y = p_y_axis_mode;1683}16841685void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) {1686uint32_t pc = p_points.size();1687ERR_FAIL_COND(pc == 0 || pc > 4);16881689Item *canvas_item = canvas_item_owner.get_or_null(p_item);1690ERR_FAIL_NULL(canvas_item);16911692Item::CommandPrimitive *prim = canvas_item->alloc_command<Item::CommandPrimitive>();1693ERR_FAIL_NULL(prim);16941695for (int i = 0; i < p_points.size(); i++) {1696prim->points[i] = p_points[i];1697if (i < p_uvs.size()) {1698prim->uvs[i] = p_uvs[i];1699}1700if (i < p_colors.size()) {1701prim->colors[i] = p_colors[i];1702} else if (p_colors.size()) {1703prim->colors[i] = p_colors[0];1704} else {1705prim->colors[i] = Color(1, 1, 1, 1);1706}1707}17081709prim->point_count = p_points.size();17101711prim->texture = p_texture;1712}17131714void RendererCanvasCull::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) {1715Item *canvas_item = canvas_item_owner.get_or_null(p_item);1716ERR_FAIL_NULL(canvas_item);1717#ifdef DEBUG_ENABLED1718int pointcount = p_points.size();1719ERR_FAIL_COND(pointcount < 3);1720int color_size = p_colors.size();1721int uv_size = p_uvs.size();1722ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount);1723ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount));1724#endif1725Vector<int> indices = Geometry2D::triangulate_polygon(p_points);1726ERR_FAIL_COND_MSG(indices.is_empty(), "Invalid polygon data, triangulation failed.");17271728Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();1729ERR_FAIL_NULL(polygon);1730polygon->primitive = RS::PRIMITIVE_TRIANGLES;1731polygon->texture = p_texture;1732polygon->polygon.create(indices, p_points, p_colors, p_uvs);1733}17341735void RendererCanvasCull::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count) {1736Item *canvas_item = canvas_item_owner.get_or_null(p_item);1737ERR_FAIL_NULL(canvas_item);17381739int vertex_count = p_points.size();1740ERR_FAIL_COND(vertex_count == 0);1741ERR_FAIL_COND(!p_colors.is_empty() && p_colors.size() != vertex_count && p_colors.size() != 1);1742ERR_FAIL_COND(!p_uvs.is_empty() && p_uvs.size() != vertex_count);1743ERR_FAIL_COND(!p_bones.is_empty() && p_bones.size() != vertex_count * 4);1744ERR_FAIL_COND(!p_weights.is_empty() && p_weights.size() != vertex_count * 4);17451746Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>();1747ERR_FAIL_NULL(polygon);17481749polygon->texture = p_texture;17501751polygon->polygon.create(p_indices, p_points, p_colors, p_uvs, p_bones, p_weights, p_count);17521753polygon->primitive = RS::PRIMITIVE_TRIANGLES;1754}17551756void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) {1757Item *canvas_item = canvas_item_owner.get_or_null(p_item);1758ERR_FAIL_NULL(canvas_item);17591760Item::CommandTransform *tr = canvas_item->alloc_command<Item::CommandTransform>();1761ERR_FAIL_NULL(tr);1762tr->xform = p_transform;1763}17641765void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) {1766Item *canvas_item = canvas_item_owner.get_or_null(p_item);1767ERR_FAIL_NULL(canvas_item);1768ERR_FAIL_COND(!p_mesh.is_valid());17691770Item::CommandMesh *m = canvas_item->alloc_command<Item::CommandMesh>();1771ERR_FAIL_NULL(m);1772m->mesh = p_mesh;1773if (canvas_item->skeleton.is_valid()) {1774m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh);1775RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);1776}17771778m->texture = p_texture;17791780m->transform = p_transform;1781m->modulate = p_modulate;1782}17831784void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) {1785Item *canvas_item = canvas_item_owner.get_or_null(p_item);1786ERR_FAIL_NULL(canvas_item);17871788Item::CommandParticles *part = canvas_item->alloc_command<Item::CommandParticles>();1789ERR_FAIL_NULL(part);1790part->particles = p_particles;17911792part->texture = p_texture;17931794//take the chance and request processing for them, at least once until they become visible again1795RSG::particles_storage->particles_request_process(p_particles);1796}17971798void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) {1799Item *canvas_item = canvas_item_owner.get_or_null(p_item);1800ERR_FAIL_NULL(canvas_item);18011802Item::CommandMultiMesh *mm = canvas_item->alloc_command<Item::CommandMultiMesh>();1803ERR_FAIL_NULL(mm);1804mm->multimesh = p_mesh;18051806mm->texture = p_texture;1807}18081809void RendererCanvasCull::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {1810Item *canvas_item = canvas_item_owner.get_or_null(p_item);1811ERR_FAIL_NULL(canvas_item);18121813Item::CommandClipIgnore *ci = canvas_item->alloc_command<Item::CommandClipIgnore>();1814ERR_FAIL_NULL(ci);1815ci->ignore = p_ignore;1816}18171818void RendererCanvasCull::canvas_item_add_animation_slice(RID p_item, double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) {1819Item *canvas_item = canvas_item_owner.get_or_null(p_item);1820ERR_FAIL_NULL(canvas_item);18211822Item::CommandAnimationSlice *as = canvas_item->alloc_command<Item::CommandAnimationSlice>();1823ERR_FAIL_NULL(as);1824as->animation_length = p_animation_length;1825as->slice_begin = p_slice_begin;1826as->slice_end = p_slice_end;1827as->offset = p_offset;1828}18291830void RendererCanvasCull::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {1831Item *canvas_item = canvas_item_owner.get_or_null(p_item);1832ERR_FAIL_NULL(canvas_item);18331834canvas_item->sort_y = p_enable;18351836_mark_ysort_dirty(canvas_item);1837}18381839void RendererCanvasCull::canvas_item_set_z_index(RID p_item, int p_z) {1840ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN || p_z > RS::CANVAS_ITEM_Z_MAX);18411842Item *canvas_item = canvas_item_owner.get_or_null(p_item);1843ERR_FAIL_NULL(canvas_item);18441845canvas_item->z_index = p_z;1846}18471848void RendererCanvasCull::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) {1849Item *canvas_item = canvas_item_owner.get_or_null(p_item);1850ERR_FAIL_NULL(canvas_item);18511852canvas_item->z_relative = p_enable;1853}18541855void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) {1856Item *canvas_item = canvas_item_owner.get_or_null(p_item);1857ERR_FAIL_NULL(canvas_item);1858if (canvas_item->skeleton == p_skeleton) {1859return;1860}1861canvas_item->skeleton = p_skeleton;18621863Item::Command *c = canvas_item->commands;18641865while (c) {1866if (c->type == Item::Command::TYPE_MESH) {1867Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c);1868if (canvas_item->skeleton.is_valid()) {1869if (cm->mesh_instance.is_null()) {1870cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh);1871}1872RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);1873} else {1874if (cm->mesh_instance.is_valid()) {1875RSG::mesh_storage->mesh_instance_free(cm->mesh_instance);1876cm->mesh_instance = RID();1877}1878}1879}1880c = c->next;1881}1882}18831884void RendererCanvasCull::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) {1885Item *canvas_item = canvas_item_owner.get_or_null(p_item);1886ERR_FAIL_NULL(canvas_item);1887if (p_enable && (canvas_item->copy_back_buffer == nullptr)) {1888canvas_item->copy_back_buffer = memnew(RendererCanvasRender::Item::CopyBackBuffer);1889}1890if (!p_enable && (canvas_item->copy_back_buffer != nullptr)) {1891memdelete(canvas_item->copy_back_buffer);1892canvas_item->copy_back_buffer = nullptr;1893}18941895if (p_enable) {1896canvas_item->copy_back_buffer->rect = p_rect;1897canvas_item->copy_back_buffer->full = p_rect == Rect2();1898}1899}19001901void RendererCanvasCull::canvas_item_clear(RID p_item) {1902Item *canvas_item = canvas_item_owner.get_or_null(p_item);1903ERR_FAIL_NULL(canvas_item);19041905canvas_item->clear();19061907#ifdef DEBUG_ENABLED1908if (debug_redraw) {1909canvas_item->debug_redraw_time = debug_redraw_time;1910}1911#endif1912}19131914void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) {1915Item *canvas_item = canvas_item_owner.get_or_null(p_item);1916ERR_FAIL_NULL(canvas_item);19171918canvas_item->index = p_index;19191920if (canvas_item_owner.owns(canvas_item->parent)) {1921Item *canvas_item_parent = canvas_item_owner.get_or_null(canvas_item->parent);1922canvas_item_parent->children_order_dirty = true;1923return;1924}19251926Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);1927if (canvas) {1928canvas->children_order_dirty = true;1929return;1930}1931}19321933void RendererCanvasCull::canvas_item_set_material(RID p_item, RID p_material) {1934Item *canvas_item = canvas_item_owner.get_or_null(p_item);1935ERR_FAIL_NULL(canvas_item);19361937canvas_item->material = p_material;1938_item_queue_update(canvas_item, true);1939}19401941void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {1942Item *canvas_item = canvas_item_owner.get_or_null(p_item);1943ERR_FAIL_NULL(canvas_item);19441945canvas_item->use_parent_material = p_enable;1946_item_queue_update(canvas_item, true);1947}19481949void RendererCanvasCull::canvas_item_set_instance_shader_parameter(RID p_item, const StringName &p_parameter, const Variant &p_value) {1950Item *item = canvas_item_owner.get_or_null(p_item);1951ERR_FAIL_NULL(item);19521953item->instance_uniforms.set(item->self, p_parameter, p_value);1954}19551956Variant RendererCanvasCull::canvas_item_get_instance_shader_parameter(RID p_item, const StringName &p_parameter) const {1957const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);1958ERR_FAIL_NULL_V(item, Variant());19591960return item->instance_uniforms.get(p_parameter);1961}19621963Variant RendererCanvasCull::canvas_item_get_instance_shader_parameter_default_value(RID p_item, const StringName &p_parameter) const {1964const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);1965ERR_FAIL_NULL_V(item, Variant());19661967return item->instance_uniforms.get_default(p_parameter);1968}19691970void RendererCanvasCull::canvas_item_get_instance_shader_parameter_list(RID p_item, List<PropertyInfo> *p_parameters) const {1971ERR_FAIL_NULL(p_parameters);1972const Item *item = const_cast<RendererCanvasCull *>(this)->canvas_item_owner.get_or_null(p_item);1973ERR_FAIL_NULL(item);1974const_cast<RendererCanvasCull *>(this)->update_dirty_items();19751976item->instance_uniforms.get_property_list(*p_parameters);1977}19781979void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) {1980Item *canvas_item = canvas_item_owner.get_or_null(p_item);1981ERR_FAIL_NULL(canvas_item);19821983if (p_enable) {1984if (!canvas_item->visibility_notifier) {1985canvas_item->visibility_notifier = visibility_notifier_allocator.alloc();1986}1987canvas_item->visibility_notifier->area = p_area;1988canvas_item->visibility_notifier->enter_callable = p_enter_callable;1989canvas_item->visibility_notifier->exit_callable = p_exit_callable;19901991} else {1992if (canvas_item->visibility_notifier) {1993visibility_notifier_allocator.free(canvas_item->visibility_notifier);1994canvas_item->visibility_notifier = nullptr;1995}1996}1997}19981999void RendererCanvasCull::canvas_item_set_debug_redraw(bool p_enabled) {2000debug_redraw = p_enabled;2001RSG::canvas_render->set_debug_redraw(p_enabled, debug_redraw_time, debug_redraw_color);2002}20032004bool RendererCanvasCull::canvas_item_get_debug_redraw() const {2005return debug_redraw;2006}20072008void RendererCanvasCull::canvas_item_set_interpolated(RID p_item, bool p_interpolated) {2009Item *canvas_item = canvas_item_owner.get_or_null(p_item);2010ERR_FAIL_NULL(canvas_item);2011canvas_item->interpolated = p_interpolated;2012}20132014void RendererCanvasCull::canvas_item_reset_physics_interpolation(RID p_item) {2015Item *canvas_item = canvas_item_owner.get_or_null(p_item);2016ERR_FAIL_NULL(canvas_item);2017canvas_item->xform_prev = canvas_item->xform_curr;2018}20192020// Useful especially for origin shifting.2021void RendererCanvasCull::canvas_item_transform_physics_interpolation(RID p_item, const Transform2D &p_transform) {2022Item *canvas_item = canvas_item_owner.get_or_null(p_item);2023ERR_FAIL_NULL(canvas_item);2024canvas_item->xform_prev = p_transform * canvas_item->xform_prev;2025canvas_item->xform_curr = p_transform * canvas_item->xform_curr;2026}20272028void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {2029Item *canvas_item = canvas_item_owner.get_or_null(p_item);2030ERR_FAIL_NULL(canvas_item);20312032if (p_mode == RS::CANVAS_GROUP_MODE_DISABLED) {2033if (canvas_item->canvas_group != nullptr) {2034memdelete(canvas_item->canvas_group);2035canvas_item->canvas_group = nullptr;2036}2037} else {2038if (canvas_item->canvas_group == nullptr) {2039canvas_item->canvas_group = memnew(RendererCanvasRender::Item::CanvasGroup);2040}2041canvas_item->canvas_group->mode = p_mode;2042canvas_item->canvas_group->fit_empty = p_fit_empty;2043canvas_item->canvas_group->fit_margin = p_fit_margin;2044canvas_item->canvas_group->blur_mipmaps = p_blur_mipmaps;2045canvas_item->canvas_group->clear_margin = p_clear_margin;2046}2047}20482049RID RendererCanvasCull::canvas_light_allocate() {2050return canvas_light_owner.allocate_rid();2051}2052void RendererCanvasCull::canvas_light_initialize(RID p_rid) {2053canvas_light_owner.initialize_rid(p_rid);2054RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_rid);2055clight->light_internal = RSG::canvas_render->light_create();2056}20572058void RendererCanvasCull::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) {2059RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2060ERR_FAIL_NULL(clight);20612062if (clight->mode == p_mode) {2063return;2064}20652066RID canvas = clight->canvas;20672068if (canvas.is_valid()) {2069canvas_light_attach_to_canvas(p_light, RID());2070}20712072clight->mode = p_mode;20732074if (canvas.is_valid()) {2075canvas_light_attach_to_canvas(p_light, canvas);2076}2077}20782079void RendererCanvasCull::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) {2080RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2081ERR_FAIL_NULL(clight);20822083if (clight->canvas.is_valid()) {2084Canvas *canvas = canvas_owner.get_or_null(clight->canvas);2085if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {2086canvas->lights.erase(clight);2087} else {2088canvas->directional_lights.erase(clight);2089}2090}20912092if (!canvas_owner.owns(p_canvas)) {2093p_canvas = RID();2094}20952096clight->canvas = p_canvas;20972098if (clight->canvas.is_valid()) {2099Canvas *canvas = canvas_owner.get_or_null(clight->canvas);2100if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) {2101canvas->lights.insert(clight);2102} else {2103canvas->directional_lights.insert(clight);2104}2105}2106}21072108void RendererCanvasCull::canvas_light_set_enabled(RID p_light, bool p_enabled) {2109RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2110ERR_FAIL_NULL(clight);21112112clight->enabled = p_enabled;2113}21142115void RendererCanvasCull::canvas_light_set_texture_scale(RID p_light, float p_scale) {2116RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2117ERR_FAIL_NULL(clight);21182119clight->scale = p_scale;2120}21212122void RendererCanvasCull::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) {2123RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2124ERR_FAIL_NULL(clight);21252126if (_interpolation_data.interpolation_enabled && clight->interpolated) {2127if (!clight->on_interpolate_transform_list) {2128_interpolation_data.canvas_light_transform_update_list_curr->push_back(p_light);2129clight->on_interpolate_transform_list = true;2130} else {2131DEV_ASSERT(_interpolation_data.canvas_light_transform_update_list_curr->size() > 0);2132}2133}21342135clight->xform_curr = p_transform;2136}21372138void RendererCanvasCull::canvas_light_set_texture(RID p_light, RID p_texture) {2139RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2140ERR_FAIL_NULL(clight);21412142if (clight->texture == p_texture) {2143return;2144}2145clight->texture = p_texture;2146clight->version++;2147RSG::canvas_render->light_set_texture(clight->light_internal, p_texture);2148}21492150void RendererCanvasCull::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) {2151RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2152ERR_FAIL_NULL(clight);21532154clight->texture_offset = p_offset;2155}21562157void RendererCanvasCull::canvas_light_set_color(RID p_light, const Color &p_color) {2158RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2159ERR_FAIL_NULL(clight);21602161clight->color = p_color;2162}21632164void RendererCanvasCull::canvas_light_set_height(RID p_light, float p_height) {2165RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2166ERR_FAIL_NULL(clight);21672168clight->height = p_height;2169}21702171void RendererCanvasCull::canvas_light_set_energy(RID p_light, float p_energy) {2172RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2173ERR_FAIL_NULL(clight);21742175clight->energy = p_energy;2176}21772178void RendererCanvasCull::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) {2179RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2180ERR_FAIL_NULL(clight);21812182clight->z_min = p_min_z;2183clight->z_max = p_max_z;2184}21852186void RendererCanvasCull::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) {2187RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2188ERR_FAIL_NULL(clight);21892190clight->layer_max = p_max_layer;2191clight->layer_min = p_min_layer;2192}21932194void RendererCanvasCull::canvas_light_set_item_cull_mask(RID p_light, int p_mask) {2195RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2196ERR_FAIL_NULL(clight);21972198clight->item_mask = p_mask;2199}22002201void RendererCanvasCull::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) {2202RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2203ERR_FAIL_NULL(clight);22042205clight->item_shadow_mask = p_mask;2206}22072208void RendererCanvasCull::canvas_light_set_directional_distance(RID p_light, float p_distance) {2209RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2210ERR_FAIL_NULL(clight);22112212clight->directional_distance = p_distance;2213}22142215void RendererCanvasCull::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) {2216RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2217ERR_FAIL_NULL(clight);22182219clight->blend_mode = p_mode;2220}22212222void RendererCanvasCull::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) {2223RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2224ERR_FAIL_NULL(clight);22252226if (clight->use_shadow == p_enabled) {2227return;2228}2229clight->use_shadow = p_enabled;2230clight->version++;2231RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow);2232}22332234void RendererCanvasCull::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) {2235RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2236ERR_FAIL_NULL(clight);22372238clight->shadow_filter = p_filter;2239}22402241void RendererCanvasCull::canvas_light_set_shadow_color(RID p_light, const Color &p_color) {2242RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2243ERR_FAIL_NULL(clight);22442245clight->shadow_color = p_color;2246}22472248void RendererCanvasCull::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) {2249RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2250ERR_FAIL_NULL(clight);2251clight->shadow_smooth = p_smooth;2252}22532254void RendererCanvasCull::canvas_light_set_interpolated(RID p_light, bool p_interpolated) {2255RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2256ERR_FAIL_NULL(clight);2257clight->interpolated = p_interpolated;2258}22592260void RendererCanvasCull::canvas_light_reset_physics_interpolation(RID p_light) {2261RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2262ERR_FAIL_NULL(clight);2263clight->xform_prev = clight->xform_curr;2264}22652266void RendererCanvasCull::canvas_light_transform_physics_interpolation(RID p_light, const Transform2D &p_transform) {2267RendererCanvasRender::Light *clight = canvas_light_owner.get_or_null(p_light);2268ERR_FAIL_NULL(clight);2269clight->xform_prev = p_transform * clight->xform_prev;2270clight->xform_curr = p_transform * clight->xform_curr;2271}22722273RID RendererCanvasCull::canvas_light_occluder_allocate() {2274return canvas_light_occluder_owner.allocate_rid();2275}2276void RendererCanvasCull::canvas_light_occluder_initialize(RID p_rid) {2277return canvas_light_occluder_owner.initialize_rid(p_rid);2278}22792280void RendererCanvasCull::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) {2281RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2282ERR_FAIL_NULL(occluder);22832284if (occluder->canvas.is_valid()) {2285Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);2286canvas->occluders.erase(occluder);2287}22882289if (!canvas_owner.owns(p_canvas)) {2290p_canvas = RID();2291}22922293occluder->canvas = p_canvas;22942295if (occluder->canvas.is_valid()) {2296Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);2297canvas->occluders.insert(occluder);2298}2299}23002301void RendererCanvasCull::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) {2302RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2303ERR_FAIL_NULL(occluder);23042305occluder->enabled = p_enabled;2306}23072308void RendererCanvasCull::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) {2309RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2310ERR_FAIL_NULL(occluder);23112312if (occluder->polygon.is_valid()) {2313LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(occluder->polygon);2314if (occluder_poly) {2315occluder_poly->owners.erase(occluder);2316}2317}23182319occluder->polygon = p_polygon;2320occluder->occluder = RID();23212322if (occluder->polygon.is_valid()) {2323LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_polygon);2324if (!occluder_poly) {2325occluder->polygon = RID();2326ERR_FAIL_NULL(occluder_poly);2327} else {2328occluder_poly->owners.insert(occluder);2329occluder->occluder = occluder_poly->occluder;2330occluder->aabb_cache = occluder_poly->aabb;2331occluder->cull_cache = occluder_poly->cull_mode;2332}2333}2334}23352336void RendererCanvasCull::canvas_light_occluder_set_as_sdf_collision(RID p_occluder, bool p_enable) {2337RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2338ERR_FAIL_NULL(occluder);23392340occluder->sdf_collision = p_enable;2341}23422343void RendererCanvasCull::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) {2344RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2345ERR_FAIL_NULL(occluder);23462347if (_interpolation_data.interpolation_enabled && occluder->interpolated) {2348if (!occluder->on_interpolate_transform_list) {2349_interpolation_data.canvas_light_occluder_transform_update_list_curr->push_back(p_occluder);2350occluder->on_interpolate_transform_list = true;2351} else {2352DEV_ASSERT(_interpolation_data.canvas_light_occluder_transform_update_list_curr->size() > 0);2353}2354}23552356occluder->xform_curr = p_xform;2357}23582359void RendererCanvasCull::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) {2360RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2361ERR_FAIL_NULL(occluder);23622363occluder->light_mask = p_mask;2364}23652366void RendererCanvasCull::canvas_light_occluder_set_interpolated(RID p_occluder, bool p_interpolated) {2367RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2368ERR_FAIL_NULL(occluder);2369occluder->interpolated = p_interpolated;2370}23712372void RendererCanvasCull::canvas_light_occluder_reset_physics_interpolation(RID p_occluder) {2373RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2374ERR_FAIL_NULL(occluder);2375occluder->xform_prev = occluder->xform_curr;2376}23772378void RendererCanvasCull::canvas_light_occluder_transform_physics_interpolation(RID p_occluder, const Transform2D &p_transform) {2379RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_occluder);2380ERR_FAIL_NULL(occluder);2381occluder->xform_prev = p_transform * occluder->xform_prev;2382occluder->xform_curr = p_transform * occluder->xform_curr;2383}23842385RID RendererCanvasCull::canvas_occluder_polygon_allocate() {2386return canvas_light_occluder_polygon_owner.allocate_rid();2387}2388void RendererCanvasCull::canvas_occluder_polygon_initialize(RID p_rid) {2389canvas_light_occluder_polygon_owner.initialize_rid(p_rid);2390LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_rid);2391occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create();2392}23932394void RendererCanvasCull::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed) {2395LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_occluder_polygon);2396ERR_FAIL_NULL(occluder_poly);23972398uint32_t pc = p_shape.size();2399ERR_FAIL_COND(pc < 2);24002401occluder_poly->aabb = Rect2();2402const Vector2 *r = p_shape.ptr();2403for (uint32_t i = 0; i < pc; i++) {2404if (i == 0) {2405occluder_poly->aabb.position = r[i];2406} else {2407occluder_poly->aabb.expand_to(r[i]);2408}2409}24102411RSG::canvas_render->occluder_polygon_set_shape(occluder_poly->occluder, p_shape, p_closed);24122413for (RendererCanvasRender::LightOccluderInstance *E : occluder_poly->owners) {2414E->aabb_cache = occluder_poly->aabb;2415}2416}24172418void RendererCanvasCull::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) {2419LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_occluder_polygon);2420ERR_FAIL_NULL(occluder_poly);2421occluder_poly->cull_mode = p_mode;2422RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode);2423for (RendererCanvasRender::LightOccluderInstance *E : occluder_poly->owners) {2424E->cull_cache = p_mode;2425}2426}24272428void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {2429RSG::canvas_render->set_shadow_texture_size(p_size);2430}24312432RID RendererCanvasCull::canvas_texture_allocate() {2433return RSG::texture_storage->canvas_texture_allocate();2434}2435void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {2436RSG::texture_storage->canvas_texture_initialize(p_rid);2437}24382439void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {2440RSG::texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);2441}24422443void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) {2444RSG::texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);2445}24462447void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {2448RSG::texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);2449}24502451void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {2452RSG::texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);2453}24542455void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {2456Item *ci = canvas_item_owner.get_or_null(p_item);2457ERR_FAIL_NULL(ci);2458ci->texture_filter = p_filter;2459}2460void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) {2461Item *ci = canvas_item_owner.get_or_null(p_item);2462ERR_FAIL_NULL(ci);2463ci->texture_repeat = p_repeat;2464}24652466void RendererCanvasCull::update_visibility_notifiers() {2467SelfList<Item::VisibilityNotifierData> *E = visibility_notifier_list.first();2468while (E) {2469SelfList<Item::VisibilityNotifierData> *N = E->next();24702471Item::VisibilityNotifierData *visibility_notifier = E->self();2472if (visibility_notifier->just_visible) {2473visibility_notifier->just_visible = false;24742475if (visibility_notifier->enter_callable.is_valid()) {2476if (RSG::threaded) {2477visibility_notifier->enter_callable.call_deferred();2478} else {2479visibility_notifier->enter_callable.call();2480}2481}2482} else {2483if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {2484visibility_notifier_list.remove(E);24852486if (visibility_notifier->exit_callable.is_valid()) {2487if (RSG::threaded) {2488visibility_notifier->exit_callable.call_deferred();2489} else {2490visibility_notifier->exit_callable.call();2491}2492}2493}2494}24952496E = N;2497}2498}24992500Rect2 RendererCanvasCull::_debug_canvas_item_get_rect(RID p_item) {2501Item *canvas_item = canvas_item_owner.get_or_null(p_item);2502ERR_FAIL_NULL_V(canvas_item, Rect2());2503return canvas_item->get_rect();2504}25052506void RendererCanvasCull::_item_queue_update(Item *p_item, bool p_update_dependencies) {2507if (p_update_dependencies) {2508p_item->update_dependencies = true;2509}25102511if (!p_item->update_item.in_list()) {2512_item_update_list.add(&p_item->update_item);2513}2514}25152516void RendererCanvasCull::update_dirty_items() {2517while (_item_update_list.first()) {2518_update_dirty_item(_item_update_list.first()->self());2519}25202521// Instance updates may affect resources.2522RSG::utilities->update_dirty_resources();2523}25242525void RendererCanvasCull::_update_dirty_item(Item *p_item) {2526if (p_item->update_dependencies) {2527RID material = p_item->material;25282529if (p_item->use_parent_material) {2530Item *parent = canvas_item_owner.get_or_null(p_item->parent);2531while (parent != nullptr) {2532material = parent->material;2533if (!parent->use_parent_material) {2534break;2535}2536parent = canvas_item_owner.get_or_null(parent->parent);2537}2538}25392540p_item->dependency_tracker.update_begin();25412542p_item->instance_uniforms.materials_start();25432544if (material.is_valid()) {2545p_item->instance_uniforms.materials_append(material);2546RSG::material_storage->material_update_dependency(material, &p_item->dependency_tracker);2547}25482549if (p_item->instance_uniforms.materials_finish(p_item->self)) {2550p_item->instance_allocated_shader_uniforms_offset = p_item->instance_uniforms.location();2551}25522553p_item->dependency_tracker.update_end();2554}2555_item_update_list.remove(&p_item->update_item);2556p_item->update_dependencies = false;2557}25582559void RendererCanvasCull::update() {2560update_dirty_items();2561}25622563bool RendererCanvasCull::free(RID p_rid) {2564if (canvas_owner.owns(p_rid)) {2565Canvas *canvas = canvas_owner.get_or_null(p_rid);2566ERR_FAIL_NULL_V(canvas, false);25672568while (canvas->viewports.size()) {2569RendererViewport::Viewport *vp = RSG::viewport->viewport_owner.get_or_null(*canvas->viewports.begin());2570ERR_FAIL_NULL_V(vp, true);25712572HashMap<RID, RendererViewport::Viewport::CanvasData>::Iterator E = vp->canvas_map.find(p_rid);2573ERR_FAIL_COND_V(!E, true);2574vp->canvas_map.erase(p_rid);25752576canvas->viewports.erase(*canvas->viewports.begin());2577}25782579for (int i = 0; i < canvas->child_items.size(); i++) {2580canvas->child_items[i].item->parent = RID();2581}25822583for (RendererCanvasRender::Light *E : canvas->lights) {2584E->canvas = RID();2585}25862587for (RendererCanvasRender::LightOccluderInstance *E : canvas->occluders) {2588E->canvas = RID();2589}25902591canvas_owner.free(p_rid);25922593} else if (canvas_item_owner.owns(p_rid)) {2594Item *canvas_item = canvas_item_owner.get_or_null(p_rid);2595ERR_FAIL_NULL_V(canvas_item, true);2596_interpolation_data.notify_free_canvas_item(p_rid, *canvas_item);25972598if (canvas_item->parent.is_valid()) {2599if (canvas_owner.owns(canvas_item->parent)) {2600Canvas *canvas = canvas_owner.get_or_null(canvas_item->parent);2601canvas->erase_item(canvas_item);2602} else if (canvas_item_owner.owns(canvas_item->parent)) {2603Item *item_owner = canvas_item_owner.get_or_null(canvas_item->parent);2604item_owner->child_items.erase(canvas_item);26052606if (item_owner->sort_y) {2607_mark_ysort_dirty(item_owner);2608}2609}2610}26112612for (int i = 0; i < canvas_item->child_items.size(); i++) {2613canvas_item->child_items[i]->parent = RID();2614}26152616if (canvas_item->visibility_notifier != nullptr) {2617visibility_notifier_allocator.free(canvas_item->visibility_notifier);2618}26192620canvas_item_set_material(canvas_item->self, RID());2621update_dirty_items();2622canvas_item->instance_uniforms.free(canvas_item->self);26232624if (canvas_item->canvas_group != nullptr) {2625memdelete(canvas_item->canvas_group);2626canvas_item->canvas_group = nullptr;2627}26282629canvas_item_owner.free(p_rid);26302631} else if (canvas_light_owner.owns(p_rid)) {2632RendererCanvasRender::Light *canvas_light = canvas_light_owner.get_or_null(p_rid);2633ERR_FAIL_NULL_V(canvas_light, true);2634_interpolation_data.notify_free_canvas_light(p_rid, *canvas_light);26352636if (canvas_light->canvas.is_valid()) {2637Canvas *canvas = canvas_owner.get_or_null(canvas_light->canvas);2638if (canvas) {2639canvas->lights.erase(canvas_light);2640}2641}26422643RSG::canvas_render->free(canvas_light->light_internal);26442645canvas_light_owner.free(p_rid);26462647} else if (canvas_light_occluder_owner.owns(p_rid)) {2648RendererCanvasRender::LightOccluderInstance *occluder = canvas_light_occluder_owner.get_or_null(p_rid);2649ERR_FAIL_NULL_V(occluder, true);2650_interpolation_data.notify_free_canvas_light_occluder(p_rid, *occluder);26512652if (occluder->polygon.is_valid()) {2653LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(occluder->polygon);2654if (occluder_poly) {2655occluder_poly->owners.erase(occluder);2656}2657}26582659if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {2660Canvas *canvas = canvas_owner.get_or_null(occluder->canvas);2661canvas->occluders.erase(occluder);2662}26632664canvas_light_occluder_owner.free(p_rid);26652666} else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {2667LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get_or_null(p_rid);2668ERR_FAIL_NULL_V(occluder_poly, true);2669RSG::canvas_render->free(occluder_poly->occluder);26702671while (occluder_poly->owners.size()) {2672(*occluder_poly->owners.begin())->polygon = RID();2673occluder_poly->owners.remove(occluder_poly->owners.begin());2674}26752676canvas_light_occluder_polygon_owner.free(p_rid);2677} else {2678return false;2679}26802681return true;2682}26832684template <typename T>2685void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) {2686LocalVector<RID> owned = p_owner.get_owned_list();2687if (owned.size()) {2688if (owned.size() == 1) {2689WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type));2690} else {2691WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));2692}2693for (const RID &rid : owned) {2694free(rid);2695}2696}2697}26982699void RendererCanvasCull::finalize() {2700_free_rids(canvas_owner, "Canvas");2701_free_rids(canvas_item_owner, "CanvasItem");2702_free_rids(canvas_light_owner, "CanvasLight");2703_free_rids(canvas_light_occluder_owner, "CanvasLightOccluder");2704_free_rids(canvas_light_occluder_polygon_owner, "CanvasLightOccluderPolygon");2705}27062707void RendererCanvasCull::tick() {2708if (_interpolation_data.interpolation_enabled) {2709update_interpolation_tick(true);2710}2711}27122713void RendererCanvasCull::update_interpolation_tick(bool p_process) {2714#define GODOT_UPDATE_INTERPOLATION_TICK(m_list_prev, m_list_curr, m_type, m_owner_list) \2715/* Detect any that were on the previous transform list that are no longer active. */ \2716for (unsigned int n = 0; n < _interpolation_data.m_list_prev->size(); n++) { \2717const RID &rid = (*_interpolation_data.m_list_prev)[n]; \2718m_type *item = m_owner_list.get_or_null(rid); \2719/* no longer active? (either the instance deleted or no longer being transformed) */ \2720if (item && !item->on_interpolate_transform_list) { \2721item->xform_prev = item->xform_curr; \2722} \2723} \2724/* and now for any in the transform list (being actively interpolated), */ \2725/* keep the previous transform value up to date and ready for next tick */ \2726if (p_process) { \2727for (unsigned int n = 0; n < _interpolation_data.m_list_curr->size(); n++) { \2728const RID &rid = (*_interpolation_data.m_list_curr)[n]; \2729m_type *item = m_owner_list.get_or_null(rid); \2730if (item) { \2731item->xform_prev = item->xform_curr; \2732item->on_interpolate_transform_list = false; \2733} \2734} \2735} \2736SWAP(_interpolation_data.m_list_curr, _interpolation_data.m_list_prev); \2737_interpolation_data.m_list_curr->clear();27382739GODOT_UPDATE_INTERPOLATION_TICK(canvas_item_transform_update_list_prev, canvas_item_transform_update_list_curr, Item, canvas_item_owner);2740GODOT_UPDATE_INTERPOLATION_TICK(canvas_light_transform_update_list_prev, canvas_light_transform_update_list_curr, RendererCanvasRender::Light, canvas_light_owner);2741GODOT_UPDATE_INTERPOLATION_TICK(canvas_light_occluder_transform_update_list_prev, canvas_light_occluder_transform_update_list_curr, RendererCanvasRender::LightOccluderInstance, canvas_light_occluder_owner);27422743#undef GODOT_UPDATE_INTERPOLATION_TICK2744}27452746void RendererCanvasCull::InterpolationData::notify_free_canvas_item(RID p_rid, RendererCanvasCull::Item &r_canvas_item) {2747r_canvas_item.on_interpolate_transform_list = false;27482749if (!interpolation_enabled) {2750return;2751}27522753// If the instance was on any of the lists, remove.2754canvas_item_transform_update_list_curr->erase_multiple_unordered(p_rid);2755canvas_item_transform_update_list_prev->erase_multiple_unordered(p_rid);2756}27572758void RendererCanvasCull::InterpolationData::notify_free_canvas_light(RID p_rid, RendererCanvasRender::Light &r_canvas_light) {2759r_canvas_light.on_interpolate_transform_list = false;27602761if (!interpolation_enabled) {2762return;2763}27642765// If the instance was on any of the lists, remove.2766canvas_light_transform_update_list_curr->erase_multiple_unordered(p_rid);2767canvas_light_transform_update_list_prev->erase_multiple_unordered(p_rid);2768}27692770void RendererCanvasCull::InterpolationData::notify_free_canvas_light_occluder(RID p_rid, RendererCanvasRender::LightOccluderInstance &r_canvas_light_occluder) {2771r_canvas_light_occluder.on_interpolate_transform_list = false;27722773if (!interpolation_enabled) {2774return;2775}27762777// If the instance was on any of the lists, remove.2778canvas_light_occluder_transform_update_list_curr->erase_multiple_unordered(p_rid);2779canvas_light_occluder_transform_update_list_prev->erase_multiple_unordered(p_rid);2780}27812782RendererCanvasCull::RendererCanvasCull() {2783_canvas_cull_singleton = this;27842785z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));2786z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));27872788disable_scale = false;27892790debug_redraw_time = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "debug/canvas_items/debug_redraw_time", PROPERTY_HINT_RANGE, "0.1,2,0.001,or_greater"), 1.0);2791debug_redraw_color = GLOBAL_DEF(PropertyInfo(Variant::COLOR, "debug/canvas_items/debug_redraw_color"), Color(1.0, 0.2, 0.2, 0.5));2792}27932794RendererCanvasCull::~RendererCanvasCull() {2795memfree(z_list);2796memfree(z_last_list);2797_canvas_cull_singleton = nullptr;2798}279928002801