diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 9c4b0feea2c..cf8b6b8f94e 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -1158,6 +1158,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList::List rs->canvas_item_set_transform(canvas_item, xform); rs->canvas_item_set_light_mask(canvas_item, get_light_mask()); + rs->canvas_item_set_z_as_relative_to_parent(canvas_item, true); rs->canvas_item_set_z_index(canvas_item, z_index); rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(get_texture_filter())); diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index bc1e8eb348b..dea68ac61cd 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -76,10 +76,11 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas } } -void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index) { +void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index, int p_z) { int child_item_count = p_canvas_item->child_items.size(); RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw(); for (int i = 0; i < child_item_count; i++) { + int abs_z = 0; if (child_items[i]->visible) { if (r_items) { r_items[r_index] = child_items[i]; @@ -87,12 +88,20 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2 child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]); child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr; child_items[i]->ysort_index = r_index; + child_items[i]->ysort_parent_abs_z_index = p_z; + + // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items. + if (child_items[i]->z_relative) { + abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX); + } else { + abs_z = child_items[i]->z_index; + } } r_index++; if (child_items[i]->sort_y) { - _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index, abs_z); } } } @@ -277,6 +286,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 ci->final_clip_owner = p_canvas_clip; } + int parent_z = p_z; if (ci->z_relative) { p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX); } else { @@ -287,22 +297,23 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 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); + _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count, p_z); } child_item_count = ci->ysort_children_count + 1; child_items = (Item **)alloca(child_item_count * sizeof(Item *)); + ci->ysort_parent_abs_z_index = parent_z; child_items[0] = ci; int i = 1; - _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); + _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i, p_z); ci->ysort_xform = ci->xform.affine_inverse(); SortArray 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); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 963cca7630c..48d0598c9f3 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -53,6 +53,7 @@ public: Transform2D ysort_xform; Vector2 ysort_pos; int ysort_index; + int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting. Vector child_items; @@ -84,6 +85,7 @@ public: ysort_xform = Transform2D(); ysort_pos = Vector2(); ysort_index = 0; + ysort_parent_abs_z_index = 0; } };