Browse Source

Fix canvas stacking not deterministic on same layer

Fixes #22687.
Pedro J. Estébanez 6 years ago
parent
commit
cf8976de41

+ 5 - 2
doc/classes/VisualServer.xml

@@ -3613,7 +3613,7 @@
 				If [code]true[/code] sets the viewport active, else sets it inactive.
 				If [code]true[/code] sets the viewport active, else sets it inactive.
 			</description>
 			</description>
 		</method>
 		</method>
-		<method name="viewport_set_canvas_layer">
+		<method name="viewport_set_canvas_stacking">
 			<return type="void">
 			<return type="void">
 			</return>
 			</return>
 			<argument index="0" name="viewport" type="RID">
 			<argument index="0" name="viewport" type="RID">
@@ -3622,8 +3622,11 @@
 			</argument>
 			</argument>
 			<argument index="2" name="layer" type="int">
 			<argument index="2" name="layer" type="int">
 			</argument>
 			</argument>
+			<argument index="3" name="sublayer" type="int">
+			</argument>
 			<description>
 			<description>
-				Sets the renderlayer for a viewport's canvas.
+				Sets the stacking order for a viewport's canvas.
+				[code]layer[/code] is the actual canvas layer, while [code]sublayer[/code] specifies the stacking order of the canvas among those in the same layer.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="viewport_set_canvas_transform">
 		<method name="viewport_set_canvas_transform">

+ 7 - 3
scene/main/canvas_layer.cpp

@@ -35,7 +35,7 @@ void CanvasLayer::set_layer(int p_xform) {
 
 
 	layer = p_xform;
 	layer = p_xform;
 	if (viewport.is_valid())
 	if (viewport.is_valid())
-		VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer);
+		VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
 }
 }
 
 
 int CanvasLayer::get_layer() const {
 int CanvasLayer::get_layer() const {
@@ -149,7 +149,7 @@ void CanvasLayer::_notification(int p_what) {
 			viewport = vp->get_viewport_rid();
 			viewport = vp->get_viewport_rid();
 
 
 			VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
 			VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
-			VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer);
+			VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
 			VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
 			VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
 
 
 		} break;
 		} break;
@@ -159,6 +159,10 @@ void CanvasLayer::_notification(int p_what) {
 			viewport = RID();
 			viewport = RID();
 
 
 		} break;
 		} break;
+		case NOTIFICATION_MOVED_IN_PARENT: {
+
+			VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
+		} break;
 	}
 	}
 }
 }
 
 
@@ -201,7 +205,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) {
 		viewport = vp->get_viewport_rid();
 		viewport = vp->get_viewport_rid();
 
 
 		VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
 		VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas);
-		VisualServer::get_singleton()->viewport_set_canvas_layer(viewport, canvas, layer);
+		VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform);
 	}
 	}
 }
 }

+ 1 - 1
servers/visual/visual_server_raster.h

@@ -474,7 +474,7 @@ public:
 	BIND2(viewport_set_transparent_background, RID, bool)
 	BIND2(viewport_set_transparent_background, RID, bool)
 
 
 	BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
 	BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
-	BIND3(viewport_set_canvas_layer, RID, RID, int)
+	BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
 	BIND2(viewport_set_shadow_atlas_size, RID, int)
 	BIND2(viewport_set_shadow_atlas_size, RID, int)
 	BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	BIND2(viewport_set_msaa, RID, ViewportMSAA)
 	BIND2(viewport_set_msaa, RID, ViewportMSAA)

+ 6 - 4
servers/visual/visual_server_viewport.cpp

@@ -137,7 +137,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
 				}
 				}
 			}
 			}
 
 
-			canvas_map[Viewport::CanvasKey(E->key(), E->get().layer)] = &E->get();
+			canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
 		}
 		}
 
 
 		if (lights_with_shadow) {
 		if (lights_with_shadow) {
@@ -176,7 +176,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
 
 
 		VSG::rasterizer->restore_render_target();
 		VSG::rasterizer->restore_render_target();
 
 
-		if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer > scenario_canvas_max_layer) {
+		if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
 			Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
 			Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
 
 
 			if (!can_draw_3d) {
 			if (!can_draw_3d) {
@@ -209,7 +209,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::E
 			VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect);
 			VSG::canvas->render_canvas(canvas, xform, canvas_lights, lights_with_mask, clip_rect);
 			i++;
 			i++;
 
 
-			if (scenario_draw_canvas_bg && E->key().layer >= scenario_canvas_max_layer) {
+			if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
 				Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
 				Ref<ARVRInterface> arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
 
 
 				if (!can_draw_3d) {
 				if (!can_draw_3d) {
@@ -496,6 +496,7 @@ void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas)
 	canvas->viewports.insert(p_viewport);
 	canvas->viewports.insert(p_viewport);
 	viewport->canvas_map[p_canvas] = Viewport::CanvasData();
 	viewport->canvas_map[p_canvas] = Viewport::CanvasData();
 	viewport->canvas_map[p_canvas].layer = 0;
 	viewport->canvas_map[p_canvas].layer = 0;
+	viewport->canvas_map[p_canvas].sublayer = 0;
 	viewport->canvas_map[p_canvas].canvas = canvas;
 	viewport->canvas_map[p_canvas].canvas = canvas;
 }
 }
 
 
@@ -534,13 +535,14 @@ void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,
 
 
 	viewport->global_transform = p_transform;
 	viewport->global_transform = p_transform;
 }
 }
-void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) {
+void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
 
 
 	Viewport *viewport = viewport_owner.getornull(p_viewport);
 	Viewport *viewport = viewport_owner.getornull(p_viewport);
 	ERR_FAIL_COND(!viewport);
 	ERR_FAIL_COND(!viewport);
 
 
 	ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
 	ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
 	viewport->canvas_map[p_canvas].layer = p_layer;
 	viewport->canvas_map[p_canvas].layer = p_layer;
+	viewport->canvas_map[p_canvas].sublayer = p_sublayer;
 }
 }
 
 
 void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
 void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {

+ 12 - 7
servers/visual/visual_server_viewport.h

@@ -78,17 +78,21 @@ public:
 
 
 		struct CanvasKey {
 		struct CanvasKey {
 
 
-			int layer;
+			int64_t stacking;
 			RID canvas;
 			RID canvas;
 			bool operator<(const CanvasKey &p_canvas) const {
 			bool operator<(const CanvasKey &p_canvas) const {
-				if (layer == p_canvas.layer) return canvas < p_canvas.canvas;
-				return layer < p_canvas.layer;
+				if (stacking == p_canvas.stacking)
+					return canvas < p_canvas.canvas;
+				return stacking < p_canvas.stacking;
+			}
+			CanvasKey() {
+				stacking = 0;
 			}
 			}
-			CanvasKey() { layer = 0; }
-			CanvasKey(const RID &p_canvas, int p_layer) {
+			CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
 				canvas = p_canvas;
 				canvas = p_canvas;
-				layer = p_layer;
+				stacking = ((int64_t)p_layer << 32) + p_sublayer;
 			}
 			}
+			int get_layer() const { return stacking >> 32; }
 		};
 		};
 
 
 		struct CanvasData {
 		struct CanvasData {
@@ -96,6 +100,7 @@ public:
 			CanvasBase *canvas;
 			CanvasBase *canvas;
 			Transform2D transform;
 			Transform2D transform;
 			int layer;
 			int layer;
+			int sublayer;
 		};
 		};
 
 
 		Transform2D global_transform;
 		Transform2D global_transform;
@@ -176,7 +181,7 @@ public:
 	void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
 	void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
 
 
 	void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
 	void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
-	void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer);
+	void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
 
 
 	void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
 	void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
 	void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
 	void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);

+ 1 - 1
servers/visual/visual_server_wrap_mt.h

@@ -400,7 +400,7 @@ public:
 	FUNC2(viewport_set_transparent_background, RID, bool)
 	FUNC2(viewport_set_transparent_background, RID, bool)
 
 
 	FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
 	FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
-	FUNC3(viewport_set_canvas_layer, RID, RID, int)
+	FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
 	FUNC2(viewport_set_shadow_atlas_size, RID, int)
 	FUNC2(viewport_set_shadow_atlas_size, RID, int)
 	FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
 	FUNC2(viewport_set_msaa, RID, ViewportMSAA)
 	FUNC2(viewport_set_msaa, RID, ViewportMSAA)

+ 1 - 1
servers/visual_server.cpp

@@ -1890,7 +1890,7 @@ void VisualServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform);
 	ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform);
 	ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background);
 	ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background);
 	ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform);
 	ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform);
-	ClassDB::bind_method(D_METHOD("viewport_set_canvas_layer", "viewport", "canvas", "layer"), &VisualServer::viewport_set_canvas_layer);
+	ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &VisualServer::viewport_set_canvas_stacking);
 	ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
 	ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size);
 	ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
 	ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision);
 	ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);
 	ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa);

+ 1 - 1
servers/visual_server.h

@@ -644,7 +644,7 @@ public:
 	virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0;
 	virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0;
 
 
 	virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
 	virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0;
-	virtual void viewport_set_canvas_layer(RID p_viewport, RID p_canvas, int p_layer) = 0;
+	virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0;
 
 
 	virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
 	virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0;
 	virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
 	virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;