2
0
Эх сурвалжийг харах

Implement multiple clip_children modes for CanvasItems

clayjohn 3 жил өмнө
parent
commit
b6f44859d7

+ 9 - 1
doc/classes/CanvasItem.xml

@@ -535,7 +535,7 @@
 		</method>
 		</method>
 	</methods>
 	</methods>
 	<members>
 	<members>
-		<member name="clip_children" type="bool" setter="set_clip_children" getter="is_clipping_children" default="false">
+		<member name="clip_children" type="int" setter="set_clip_children_mode" getter="get_clip_children_mode" enum="CanvasItem.ClipChildrenMode" default="0">
 			Allows the current node to clip children nodes, essentially acting as a mask.
 			Allows the current node to clip children nodes, essentially acting as a mask.
 		</member>
 		</member>
 		<member name="light_mask" type="int" setter="set_light_mask" getter="get_light_mask" default="1">
 		<member name="light_mask" type="int" setter="set_light_mask" getter="get_light_mask" default="1">
@@ -653,5 +653,13 @@
 		<constant name="TEXTURE_REPEAT_MAX" value="4" enum="TextureRepeat">
 		<constant name="TEXTURE_REPEAT_MAX" value="4" enum="TextureRepeat">
 			Represents the size of the [enum TextureRepeat] enum.
 			Represents the size of the [enum TextureRepeat] enum.
 		</constant>
 		</constant>
+		<constant name="CLIP_CHILDREN_DISABLED" value="0" enum="ClipChildrenMode">
+		</constant>
+		<constant name="CLIP_CHILDREN_ONLY" value="1" enum="ClipChildrenMode">
+		</constant>
+		<constant name="CLIP_CHILDREN_AND_DRAW" value="2" enum="ClipChildrenMode">
+		</constant>
+		<constant name="CLIP_CHILDREN_MAX" value="3" enum="ClipChildrenMode">
+		</constant>
 	</constants>
 	</constants>
 </class>
 </class>

+ 4 - 2
doc/classes/RenderingServer.xml

@@ -4576,9 +4576,11 @@
 		</constant>
 		</constant>
 		<constant name="CANVAS_GROUP_MODE_DISABLED" value="0" enum="CanvasGroupMode">
 		<constant name="CANVAS_GROUP_MODE_DISABLED" value="0" enum="CanvasGroupMode">
 		</constant>
 		</constant>
-		<constant name="CANVAS_GROUP_MODE_OPAQUE" value="1" enum="CanvasGroupMode">
+		<constant name="CANVAS_GROUP_MODE_CLIP_ONLY" value="1" enum="CanvasGroupMode">
 		</constant>
 		</constant>
-		<constant name="CANVAS_GROUP_MODE_TRANSPARENT" value="2" enum="CanvasGroupMode">
+		<constant name="CANVAS_GROUP_MODE_CLIP_AND_DRAW" value="2" enum="CanvasGroupMode">
+		</constant>
+		<constant name="CANVAS_GROUP_MODE_TRANSPARENT" value="3" enum="CanvasGroupMode">
 		</constant>
 		</constant>
 		<constant name="CANVAS_LIGHT_MODE_POINT" value="0" enum="CanvasLightMode">
 		<constant name="CANVAS_LIGHT_MODE_POINT" value="0" enum="CanvasLightMode">
 		</constant>
 		</constant>

+ 8 - 4
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -433,10 +433,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
 				_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
 				_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, starting_index, false);
 				item_count = 0;
 				item_count = 0;
 
 
-				if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+				if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
 					Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
 					Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
 					texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
 					texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
-					items[item_count++] = ci->canvas_group_owner;
+					if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+						items[item_count++] = ci->canvas_group_owner;
+					}
 				} else if (!backbuffer_cleared) {
 				} else if (!backbuffer_cleared) {
 					texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
 					texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
 					backbuffer_cleared = true;
 					backbuffer_cleared = true;
@@ -545,12 +547,14 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou
 
 
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
 		if (ci->canvas_group != nullptr) {
 		if (ci->canvas_group != nullptr) {
-			if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+			if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
 				if (!p_to_backbuffer) {
 				if (!p_to_backbuffer) {
 					material = default_clip_children_material;
 					material = default_clip_children_material;
 				}
 				}
 			} else {
 			} else {
-				if (material.is_null()) {
+				if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
+					material = default_clip_children_material;
+				} else {
 					material = default_canvas_group_material;
 					material = default_canvas_group_material;
 				}
 				}
 			}
 			}

+ 17 - 9
scene/main/canvas_item.cpp

@@ -986,8 +986,8 @@ void CanvasItem::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_texture_repeat", "mode"), &CanvasItem::set_texture_repeat);
 	ClassDB::bind_method(D_METHOD("set_texture_repeat", "mode"), &CanvasItem::set_texture_repeat);
 	ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasItem::get_texture_repeat);
 	ClassDB::bind_method(D_METHOD("get_texture_repeat"), &CanvasItem::get_texture_repeat);
 
 
-	ClassDB::bind_method(D_METHOD("set_clip_children", "enable"), &CanvasItem::set_clip_children);
-	ClassDB::bind_method(D_METHOD("is_clipping_children"), &CanvasItem::is_clipping_children);
+	ClassDB::bind_method(D_METHOD("set_clip_children_mode", "mode"), &CanvasItem::set_clip_children_mode);
+	ClassDB::bind_method(D_METHOD("get_clip_children_mode"), &CanvasItem::get_clip_children_mode);
 
 
 	GDVIRTUAL_BIND(_draw);
 	GDVIRTUAL_BIND(_draw);
 
 
@@ -997,7 +997,7 @@ void CanvasItem::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_children"), "set_clip_children", "is_clipping_children");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "clip_children", PROPERTY_HINT_ENUM, "Disabled,Clip Only, Clip + Draw"), "set_clip_children_mode", "get_clip_children_mode");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
 
 
 	ADD_GROUP("Texture", "texture_");
 	ADD_GROUP("Texture", "texture_");
@@ -1035,6 +1035,11 @@ void CanvasItem::_bind_methods() {
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED);
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_ENABLED);
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR);
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MIRROR);
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MAX);
 	BIND_ENUM_CONSTANT(TEXTURE_REPEAT_MAX);
+
+	BIND_ENUM_CONSTANT(CLIP_CHILDREN_DISABLED);
+	BIND_ENUM_CONSTANT(CLIP_CHILDREN_ONLY);
+	BIND_ENUM_CONSTANT(CLIP_CHILDREN_AND_DRAW);
+	BIND_ENUM_CONSTANT(CLIP_CHILDREN_MAX);
 }
 }
 
 
 Transform2D CanvasItem::get_canvas_transform() const {
 Transform2D CanvasItem::get_canvas_transform() const {
@@ -1169,20 +1174,23 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) {
 	notify_property_list_changed();
 	notify_property_list_changed();
 }
 }
 
 
-void CanvasItem::set_clip_children(bool p_enabled) {
-	if (clip_children == p_enabled) {
+void CanvasItem::set_clip_children_mode(ClipChildrenMode p_clip_mode) {
+	ERR_FAIL_COND(p_clip_mode >= CLIP_CHILDREN_MAX);
+
+	if (clip_children_mode == p_clip_mode) {
 		return;
 		return;
 	}
 	}
-	clip_children = p_enabled;
+	clip_children_mode = p_clip_mode;
 
 
 	if (Object::cast_to<CanvasGroup>(this) != nullptr) {
 	if (Object::cast_to<CanvasGroup>(this) != nullptr) {
 		//avoid accidental bugs, make this not work on CanvasGroup
 		//avoid accidental bugs, make this not work on CanvasGroup
 		return;
 		return;
 	}
 	}
-	RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), clip_children ? RS::CANVAS_GROUP_MODE_OPAQUE : RS::CANVAS_GROUP_MODE_DISABLED);
+
+	RS::get_singleton()->canvas_item_set_canvas_group_mode(get_canvas_item(), RS::CanvasGroupMode(clip_children_mode));
 }
 }
-bool CanvasItem::is_clipping_children() const {
-	return clip_children;
+CanvasItem::ClipChildrenMode CanvasItem::get_clip_children_mode() const {
+	return clip_children_mode;
 }
 }
 
 
 CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {
 CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {

+ 14 - 4
scene/main/canvas_item.h

@@ -66,8 +66,16 @@ public:
 		TEXTURE_REPEAT_MAX,
 		TEXTURE_REPEAT_MAX,
 	};
 	};
 
 
+	enum ClipChildrenMode {
+		CLIP_CHILDREN_DISABLED,
+		CLIP_CHILDREN_ONLY,
+		CLIP_CHILDREN_AND_DRAW,
+		CLIP_CHILDREN_MAX,
+	};
+
 private:
 private:
-	mutable SelfList<Node> xform_change;
+	mutable SelfList<Node>
+			xform_change;
 
 
 	RID canvas_item;
 	RID canvas_item;
 	StringName canvas_group;
 	StringName canvas_group;
@@ -85,7 +93,6 @@ private:
 	Window *window = nullptr;
 	Window *window = nullptr;
 	bool visible = true;
 	bool visible = true;
 	bool parent_visible_in_tree = false;
 	bool parent_visible_in_tree = false;
-	bool clip_children = false;
 	bool pending_update = false;
 	bool pending_update = false;
 	bool top_level = false;
 	bool top_level = false;
 	bool drawing = false;
 	bool drawing = false;
@@ -95,6 +102,8 @@ private:
 	bool notify_local_transform = false;
 	bool notify_local_transform = false;
 	bool notify_transform = false;
 	bool notify_transform = false;
 
 
+	ClipChildrenMode clip_children_mode = CLIP_CHILDREN_DISABLED;
+
 	RS::CanvasItemTextureFilter texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
 	RS::CanvasItemTextureFilter texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
 	RS::CanvasItemTextureRepeat texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
 	RS::CanvasItemTextureRepeat texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
 	TextureFilter texture_filter = TEXTURE_FILTER_PARENT_NODE;
 	TextureFilter texture_filter = TEXTURE_FILTER_PARENT_NODE;
@@ -200,8 +209,8 @@ public:
 	void queue_redraw();
 	void queue_redraw();
 	void move_to_front();
 	void move_to_front();
 
 
-	void set_clip_children(bool p_enabled);
-	bool is_clipping_children() const;
+	void set_clip_children_mode(ClipChildrenMode p_clip_mode);
+	ClipChildrenMode get_clip_children_mode() const;
 
 
 	virtual void set_light_mask(int p_light_mask);
 	virtual void set_light_mask(int p_light_mask);
 	int get_light_mask() const;
 	int get_light_mask() const;
@@ -321,6 +330,7 @@ public:
 
 
 VARIANT_ENUM_CAST(CanvasItem::TextureFilter)
 VARIANT_ENUM_CAST(CanvasItem::TextureFilter)
 VARIANT_ENUM_CAST(CanvasItem::TextureRepeat)
 VARIANT_ENUM_CAST(CanvasItem::TextureRepeat)
+VARIANT_ENUM_CAST(CanvasItem::ClipChildrenMode)
 
 
 class CanvasTexture : public Texture2D {
 class CanvasTexture : public Texture2D {
 	GDCLASS(CanvasTexture, Texture2D);
 	GDCLASS(CanvasTexture, Texture2D);

+ 2 - 2
servers/rendering/renderer_rd/effects/copy_effects.cpp

@@ -357,8 +357,8 @@ void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, cons
 		copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
 		copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
 	}
 	}
 
 
-	copy.push_constant.section[0] = 0;
-	copy.push_constant.section[1] = 0;
+	copy.push_constant.section[0] = p_rect.position.x;
+	copy.push_constant.section[1] = p_rect.position.y;
 	copy.push_constant.section[2] = p_rect.size.width;
 	copy.push_constant.section[2] = p_rect.size.width;
 	copy.push_constant.section[3] = p_rect.size.height;
 	copy.push_constant.section[3] = p_rect.size.height;
 	copy.push_constant.target[0] = p_rect.position.x;
 	copy.push_constant.target[0] = p_rect.position.x;

+ 12 - 4
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -1112,13 +1112,17 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
 		RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
 
 
 		if (ci->canvas_group != nullptr) {
 		if (ci->canvas_group != nullptr) {
-			if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+			if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
 				if (!p_to_backbuffer) {
 				if (!p_to_backbuffer) {
 					material = default_clip_children_material;
 					material = default_clip_children_material;
 				}
 				}
 			} else {
 			} else {
 				if (material.is_null()) {
 				if (material.is_null()) {
-					material = default_canvas_group_material;
+					if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
+						material = default_clip_children_material;
+					} else {
+						material = default_canvas_group_material;
+					}
 				}
 				}
 			}
 			}
 		}
 		}
@@ -1445,10 +1449,12 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
 				_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
 				_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
 				item_count = 0;
 				item_count = 0;
 
 
-				if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+				if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
 					Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
 					Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
 					texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
 					texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
-					items[item_count++] = ci->canvas_group_owner;
+					if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+						items[item_count++] = ci->canvas_group_owner;
+					}
 				} else if (!backbuffer_cleared) {
 				} else if (!backbuffer_cleared) {
 					texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
 					texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
 					backbuffer_cleared = true;
 					backbuffer_cleared = true;
@@ -2752,7 +2758,9 @@ void fragment() {
 
 
 		material_storage->shader_set_code(default_clip_children_shader, R"(
 		material_storage->shader_set_code(default_clip_children_shader, R"(
 // Default clip children shader.
 // Default clip children shader.
+
 shader_type canvas_item;
 shader_type canvas_item;
+
 void fragment() {
 void fragment() {
 	vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
 	vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
 	COLOR.rgb = c.rgb;
 	COLOR.rgb = c.rgb;

+ 2 - 1
servers/rendering_server.cpp

@@ -2636,7 +2636,8 @@ void RenderingServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX);
 	BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX);
 
 
 	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_DISABLED);
 	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_DISABLED);
-	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_OPAQUE);
+	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_ONLY);
+	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_AND_DRAW);
 	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT);
 	BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT);
 
 
 	/* CANVAS LIGHT */
 	/* CANVAS LIGHT */

+ 2 - 1
servers/rendering_server.h

@@ -1367,7 +1367,8 @@ public:
 
 
 	enum CanvasGroupMode {
 	enum CanvasGroupMode {
 		CANVAS_GROUP_MODE_DISABLED,
 		CANVAS_GROUP_MODE_DISABLED,
-		CANVAS_GROUP_MODE_OPAQUE,
+		CANVAS_GROUP_MODE_CLIP_ONLY,
+		CANVAS_GROUP_MODE_CLIP_AND_DRAW,
 		CANVAS_GROUP_MODE_TRANSPARENT,
 		CANVAS_GROUP_MODE_TRANSPARENT,
 	};
 	};