Browse Source

Account for relative z-indexes when y-sorting

Xentripetal 3 years ago
parent
commit
f514b82fd3

+ 1 - 0
scene/2d/tile_map.cpp

@@ -1158,6 +1158,7 @@ void TileMap::_rendering_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
 						rs->canvas_item_set_transform(canvas_item, xform);
 						rs->canvas_item_set_transform(canvas_item, xform);
 
 
 						rs->canvas_item_set_light_mask(canvas_item, get_light_mask());
 						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_z_index(canvas_item, z_index);
 
 
 						rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(get_texture_filter()));
 						rs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(get_texture_filter()));

+ 16 - 5
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();
 	int child_item_count = p_canvas_item->child_items.size();
 	RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();
 	RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();
 	for (int i = 0; i < child_item_count; i++) {
 	for (int i = 0; i < child_item_count; i++) {
+		int abs_z = 0;
 		if (child_items[i]->visible) {
 		if (child_items[i]->visible) {
 			if (r_items) {
 			if (r_items) {
 				r_items[r_index] = child_items[i];
 				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]->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]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
 				child_items[i]->ysort_index = r_index;
 				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++;
 			r_index++;
 
 
 			if (child_items[i]->sort_y) {
 			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;
 		ci->final_clip_owner = p_canvas_clip;
 	}
 	}
 
 
+	int parent_z = p_z;
 	if (ci->z_relative) {
 	if (ci->z_relative) {
 		p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
 		p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
 	} else {
 	} else {
@@ -287,22 +297,23 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
 		if (allow_y_sort) {
 		if (allow_y_sort) {
 			if (ci->ysort_children_count == -1) {
 			if (ci->ysort_children_count == -1) {
 				ci->ysort_children_count = 0;
 				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_item_count = ci->ysort_children_count + 1;
 			child_items = (Item **)alloca(child_item_count * sizeof(Item *));
 			child_items = (Item **)alloca(child_item_count * sizeof(Item *));
 
 
+			ci->ysort_parent_abs_z_index = parent_z;
 			child_items[0] = ci;
 			child_items[0] = ci;
 			int i = 1;
 			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();
 			ci->ysort_xform = ci->xform.affine_inverse();
 
 
 			SortArray<Item *, ItemPtrSort> sorter;
 			SortArray<Item *, ItemPtrSort> sorter;
 			sorter.sort(child_items, child_item_count);
 			sorter.sort(child_items, child_item_count);
 
 
 			for (i = 0; i < child_item_count; i++) {
 			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 {
 		} else {
 			RendererCanvasRender::Item *canvas_group_from = nullptr;
 			RendererCanvasRender::Item *canvas_group_from = nullptr;

+ 2 - 0
servers/rendering/renderer_canvas_cull.h

@@ -53,6 +53,7 @@ public:
 		Transform2D ysort_xform;
 		Transform2D ysort_xform;
 		Vector2 ysort_pos;
 		Vector2 ysort_pos;
 		int ysort_index;
 		int ysort_index;
+		int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting.
 
 
 		Vector<Item *> child_items;
 		Vector<Item *> child_items;
 
 
@@ -84,6 +85,7 @@ public:
 			ysort_xform = Transform2D();
 			ysort_xform = Transform2D();
 			ysort_pos = Vector2();
 			ysort_pos = Vector2();
 			ysort_index = 0;
 			ysort_index = 0;
+			ysort_parent_abs_z_index = 0;
 		}
 		}
 	};
 	};