mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-03 23:21:15 +00:00 
			
		
		
		
	Merge pull request #23407 from bojidar-bg/3281-ysort-recursive
Y-Sort children together in nested YSorts
This commit is contained in:
		
						commit
						8e4837f357
					
				
					 2 changed files with 62 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -51,6 +51,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, Transform2D *r_extra_transforms, int &r_index) {
 | 
			
		||||
	int child_item_count = p_canvas_item->child_items.size();
 | 
			
		||||
	VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw();
 | 
			
		||||
	for (int i = 0; i < child_item_count; i++) {
 | 
			
		||||
		if (r_items) {
 | 
			
		||||
			r_items[r_index] = child_items[i];
 | 
			
		||||
			child_items[i]->ysort_xform = p_transform;
 | 
			
		||||
			child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		r_index++;
 | 
			
		||||
 | 
			
		||||
		if (child_items[i]->sort_y)
 | 
			
		||||
			_collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_extra_transforms, r_index);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) {
 | 
			
		||||
 | 
			
		||||
	Item *ci = p_canvas_item;
 | 
			
		||||
| 
						 | 
				
			
			@ -58,10 +75,10 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
 | 
			
		|||
	if (!ci->visible)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (p_canvas_item->children_order_dirty) {
 | 
			
		||||
	if (ci->children_order_dirty) {
 | 
			
		||||
 | 
			
		||||
		p_canvas_item->child_items.sort_custom<ItemIndexSort>();
 | 
			
		||||
		p_canvas_item->children_order_dirty = false;
 | 
			
		||||
		ci->child_items.sort_custom<ItemIndexSort>();
 | 
			
		||||
		ci->children_order_dirty = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Rect2 rect = ci->get_rect();
 | 
			
		||||
| 
						 | 
				
			
			@ -82,8 +99,8 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
 | 
			
		|||
		return;
 | 
			
		||||
 | 
			
		||||
	int child_item_count = ci->child_items.size();
 | 
			
		||||
	Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *));
 | 
			
		||||
	copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *));
 | 
			
		||||
	Item **child_items = ci->child_items.ptrw();
 | 
			
		||||
	Transform2D *child_extra_transforms = NULL;
 | 
			
		||||
 | 
			
		||||
	if (ci->clip) {
 | 
			
		||||
		if (p_canvas_clip != NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +116,17 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
 | 
			
		|||
 | 
			
		||||
	if (ci->sort_y) {
 | 
			
		||||
 | 
			
		||||
		if (ci->ysort_children_count == -1) {
 | 
			
		||||
			ci->ysort_children_count = 0;
 | 
			
		||||
			_collect_ysort_children(ci, Transform2D(), NULL, NULL, 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(), child_items, child_extra_transforms, i);
 | 
			
		||||
 | 
			
		||||
		SortArray<Item *, ItemPtrSort> sorter;
 | 
			
		||||
		sorter.sort(child_items, child_item_count);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -110,10 +138,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
 | 
			
		|||
 | 
			
		||||
	for (int i = 0; i < child_item_count; i++) {
 | 
			
		||||
 | 
			
		||||
		if (!child_items[i]->behind)
 | 
			
		||||
		if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (ci->sort_y) {
 | 
			
		||||
			_render_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, p_material_owner);
 | 
			
		||||
		} else {
 | 
			
		||||
			_render_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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ci->copy_back_buffer) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,10 +180,14 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor
 | 
			
		|||
 | 
			
		||||
	for (int i = 0; i < child_item_count; i++) {
 | 
			
		||||
 | 
			
		||||
		if (child_items[i]->behind)
 | 
			
		||||
		if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y))
 | 
			
		||||
			continue;
 | 
			
		||||
		if (ci->sort_y) {
 | 
			
		||||
			_render_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, p_material_owner);
 | 
			
		||||
		} else {
 | 
			
		||||
			_render_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 VisualServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) {
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +336,7 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
 | 
			
		|||
 | 
			
		||||
			Item *item_owner = canvas_item_owner.get(canvas_item->parent);
 | 
			
		||||
			item_owner->child_items.erase(canvas_item);
 | 
			
		||||
			item_owner->ysort_children_count = -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		canvas_item->parent = RID();
 | 
			
		||||
| 
						 | 
				
			
			@ -319,6 +356,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) {
 | 
			
		|||
			item_owner->child_items.push_back(canvas_item);
 | 
			
		||||
			item_owner->children_order_dirty = true;
 | 
			
		||||
 | 
			
		||||
			Item *ysort_owner = item_owner;
 | 
			
		||||
			while (ysort_owner && ysort_owner->sort_y) {
 | 
			
		||||
				item_owner->ysort_children_count = -1;
 | 
			
		||||
				ysort_owner = canvas_item_owner.getornull(ysort_owner->parent);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			ERR_EXPLAIN("Invalid parent");
 | 
			
		||||
| 
						 | 
				
			
			@ -826,6 +869,7 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e
 | 
			
		|||
	ERR_FAIL_COND(!canvas_item);
 | 
			
		||||
 | 
			
		||||
	canvas_item->sort_y = p_enable;
 | 
			
		||||
	canvas_item->ysort_children_count = -1;
 | 
			
		||||
}
 | 
			
		||||
void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,9 @@ public:
 | 
			
		|||
		bool use_parent_material;
 | 
			
		||||
		int index;
 | 
			
		||||
		bool children_order_dirty;
 | 
			
		||||
		int ysort_children_count;
 | 
			
		||||
		Transform2D ysort_xform;
 | 
			
		||||
		Vector2 ysort_pos;
 | 
			
		||||
 | 
			
		||||
		Vector<Item *> child_items;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +64,9 @@ public:
 | 
			
		|||
			use_parent_material = false;
 | 
			
		||||
			z_relative = true;
 | 
			
		||||
			index = 0;
 | 
			
		||||
			ysort_children_count = -1;
 | 
			
		||||
			ysort_xform = Transform2D();
 | 
			
		||||
			ysort_pos = Vector2();
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -76,10 +82,10 @@ public:
 | 
			
		|||
 | 
			
		||||
		_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
 | 
			
		||||
 | 
			
		||||
			if (Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON)
 | 
			
		||||
				return p_left->xform.elements[2].x < p_right->xform.elements[2].x;
 | 
			
		||||
			if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON)
 | 
			
		||||
				return p_left->ysort_pos.x < p_right->ysort_pos.x;
 | 
			
		||||
			else
 | 
			
		||||
				return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
 | 
			
		||||
				return p_left->ysort_pos.y < p_right->ysort_pos.y;
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue