|
@@ -44,10 +44,10 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
|
|
|
memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
|
|
|
|
|
|
for (int i = 0; i < p_child_item_count; i++) {
|
|
|
- _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);
|
|
|
+ _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, true);
|
|
|
}
|
|
|
if (p_canvas_item) {
|
|
|
- _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr);
|
|
|
+ _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
|
|
|
}
|
|
|
|
|
|
RendererCanvasRender::Item *list = nullptr;
|
|
@@ -104,98 +104,7 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<Rende
|
|
|
} while (ysort_owner && ysort_owner->sort_y);
|
|
|
}
|
|
|
|
|
|
-void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
|
|
|
- Item *ci = p_canvas_item;
|
|
|
-
|
|
|
- if (!ci->visible) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (ci->children_order_dirty) {
|
|
|
- ci->child_items.sort_custom<ItemIndexSort>();
|
|
|
- ci->children_order_dirty = false;
|
|
|
- }
|
|
|
-
|
|
|
- Rect2 rect = ci->get_rect();
|
|
|
- Transform2D xform = ci->xform;
|
|
|
- if (snapping_2d_transforms_to_pixel) {
|
|
|
- xform.elements[2] = xform.elements[2].floor();
|
|
|
- }
|
|
|
- xform = p_transform * xform;
|
|
|
-
|
|
|
- Rect2 global_rect = xform.xform(rect);
|
|
|
- global_rect.position += p_clip_rect.position;
|
|
|
-
|
|
|
- if (ci->use_parent_material && p_material_owner) {
|
|
|
- ci->material_owner = p_material_owner;
|
|
|
- } else {
|
|
|
- p_material_owner = ci;
|
|
|
- ci->material_owner = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a);
|
|
|
-
|
|
|
- if (modulate.a < 0.007) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- int child_item_count = ci->child_items.size();
|
|
|
- Item **child_items = ci->child_items.ptrw();
|
|
|
-
|
|
|
- if (ci->clip) {
|
|
|
- if (p_canvas_clip != nullptr) {
|
|
|
- ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
|
|
|
- } else {
|
|
|
- ci->final_clip_rect = global_rect;
|
|
|
- }
|
|
|
- ci->final_clip_rect.position = ci->final_clip_rect.position.round();
|
|
|
- ci->final_clip_rect.size = ci->final_clip_rect.size.round();
|
|
|
- ci->final_clip_owner = ci;
|
|
|
-
|
|
|
- } else {
|
|
|
- ci->final_clip_owner = p_canvas_clip;
|
|
|
- }
|
|
|
-
|
|
|
- if (ci->sort_y) {
|
|
|
- if (ci->ysort_children_count == -1) {
|
|
|
- ci->ysort_children_count = 0;
|
|
|
- _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
|
|
|
- }
|
|
|
-
|
|
|
- child_item_count = ci->ysort_children_count;
|
|
|
- child_items = (Item **)alloca(child_item_count * sizeof(Item *));
|
|
|
-
|
|
|
- int i = 0;
|
|
|
- _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
|
|
|
-
|
|
|
- SortArray<Item *, ItemPtrSort> sorter;
|
|
|
- sorter.sort(child_items, child_item_count);
|
|
|
- }
|
|
|
-
|
|
|
- if (ci->z_relative) {
|
|
|
- p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
|
|
|
- } else {
|
|
|
- p_z = ci->z_index;
|
|
|
- }
|
|
|
-
|
|
|
- RendererCanvasRender::Item *canvas_group_from = nullptr;
|
|
|
- bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
|
|
|
- if (use_canvas_group) {
|
|
|
- int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
|
|
|
- canvas_group_from = z_last_list[zidx];
|
|
|
- }
|
|
|
-
|
|
|
- for (int i = 0; i < child_item_count; i++) {
|
|
|
- if ((!child_items[i]->behind && !use_canvas_group) || (ci->sort_y && child_items[i]->sort_y)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (ci->sort_y) {
|
|
|
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
|
|
|
- } else {
|
|
|
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from) {
|
|
|
if (ci->copy_back_buffer) {
|
|
|
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);
|
|
|
}
|
|
@@ -229,7 +138,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
|
|
|
// 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.
|
|
|
// If nothing has been drawn, we just take it over and draw it ourselves.
|
|
|
if (ci->canvas_group->fit_empty && (ci->commands == nullptr ||
|
|
|
- (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RendererCanvasRender::CANVAS_RECT_IS_GROUP)))) {
|
|
|
+ (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)))) {
|
|
|
// No commands, or sole command is the one used to draw, so we (re)create the draw command.
|
|
|
ci->clear();
|
|
|
|
|
@@ -291,15 +200,117 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
|
|
|
|
|
|
ci->next = nullptr;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- for (int i = 0; i < child_item_count; i++) {
|
|
|
- if (child_items[i]->behind || use_canvas_group || (ci->sort_y && child_items[i]->sort_y)) {
|
|
|
- continue;
|
|
|
+void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort) {
|
|
|
+ Item *ci = p_canvas_item;
|
|
|
+
|
|
|
+ if (!ci->visible) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ci->children_order_dirty) {
|
|
|
+ ci->child_items.sort_custom<ItemIndexSort>();
|
|
|
+ ci->children_order_dirty = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ Rect2 rect = ci->get_rect();
|
|
|
+ Transform2D xform = ci->xform;
|
|
|
+ if (snapping_2d_transforms_to_pixel) {
|
|
|
+ xform.elements[2] = xform.elements[2].floor();
|
|
|
+ }
|
|
|
+ xform = p_transform * xform;
|
|
|
+
|
|
|
+ Rect2 global_rect = xform.xform(rect);
|
|
|
+ global_rect.position += p_clip_rect.position;
|
|
|
+
|
|
|
+ if (ci->use_parent_material && p_material_owner) {
|
|
|
+ ci->material_owner = p_material_owner;
|
|
|
+ } else {
|
|
|
+ p_material_owner = ci;
|
|
|
+ ci->material_owner = nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a);
|
|
|
+
|
|
|
+ if (modulate.a < 0.007) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int child_item_count = ci->child_items.size();
|
|
|
+ Item **child_items = ci->child_items.ptrw();
|
|
|
+
|
|
|
+ if (ci->clip) {
|
|
|
+ if (p_canvas_clip != nullptr) {
|
|
|
+ ci->final_clip_rect = p_canvas_clip->final_clip_rect.intersection(global_rect);
|
|
|
+ } else {
|
|
|
+ ci->final_clip_rect = global_rect;
|
|
|
}
|
|
|
- if (ci->sort_y) {
|
|
|
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner);
|
|
|
+ ci->final_clip_rect.position = ci->final_clip_rect.position.round();
|
|
|
+ ci->final_clip_rect.size = ci->final_clip_rect.size.round();
|
|
|
+ ci->final_clip_owner = ci;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ ci->final_clip_owner = p_canvas_clip;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ci->z_relative) {
|
|
|
+ p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
|
|
|
+ } else {
|
|
|
+ p_z = ci->z_index;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ci->sort_y) {
|
|
|
+ if (allow_y_sort) {
|
|
|
+ if (ci->ysort_children_count == -1) {
|
|
|
+ ci->ysort_children_count = 0;
|
|
|
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
|
|
|
+ }
|
|
|
+
|
|
|
+ child_item_count = ci->ysort_children_count + 1;
|
|
|
+ child_items = (Item **)alloca(child_item_count * sizeof(Item *));
|
|
|
+
|
|
|
+ child_items[0] = ci;
|
|
|
+ int i = 1;
|
|
|
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
|
|
|
+ ci->ysort_xform = ci->xform.affine_inverse();
|
|
|
+
|
|
|
+ SortArray<Item *, ItemPtrSort> sorter;
|
|
|
+ sorter.sort(child_items, child_item_count);
|
|
|
+
|
|
|
+ for (i = 0; i < child_item_count; i++) {
|
|
|
+ _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
|
|
|
+ }
|
|
|
} else {
|
|
|
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner);
|
|
|
+ RendererCanvasRender::Item *canvas_group_from = nullptr;
|
|
|
+ bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
|
|
|
+ if (use_canvas_group) {
|
|
|
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
|
|
|
+ canvas_group_from = z_last_list[zidx];
|
|
|
+ }
|
|
|
+
|
|
|
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ RendererCanvasRender::Item *canvas_group_from = nullptr;
|
|
|
+ bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
|
|
|
+ if (use_canvas_group) {
|
|
|
+ int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
|
|
|
+ canvas_group_from = z_last_list[zidx];
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < child_item_count; i++) {
|
|
|
+ if (!child_items[i]->behind && !use_canvas_group) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
|
|
|
+ }
|
|
|
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from);
|
|
|
+ for (int i = 0; i < child_item_count; i++) {
|
|
|
+ if (child_items[i]->behind || use_canvas_group) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
|
|
|
}
|
|
|
}
|
|
|
}
|