Merge pull request #69952 from lawnjelly/canvas_layer_ordering
Consistent render ordering for CanvasLayers
This commit is contained in:
commit
54e293bfcb
|
@ -35,7 +35,11 @@
|
||||||
void CanvasLayer::set_layer(int p_xform) {
|
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_stacking(viewport, canvas, layer, get_position_in_parent());
|
// For the sublayer, we will use the order in which the layer occurs in the scene tree
|
||||||
|
// rather than just the child_id via get_position_in_parent().
|
||||||
|
// We have 32 bits to play with for the sublayer (or more likely 31, as sublayer is signed)
|
||||||
|
// (see Viewport::CanvasKey constructor in visual_server_viewport.h).
|
||||||
|
VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, _layer_order_in_tree);
|
||||||
vp->_gui_set_root_order_dirty();
|
vp->_gui_set_root_order_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +63,34 @@ void CanvasLayer::set_visible(bool p_visible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure layer orders are up to date whenever moving layers in the tree.
|
||||||
|
void CanvasLayer::_update_layer_orders() {
|
||||||
|
if (is_inside_tree() && get_tree()) {
|
||||||
|
Node *root = get_tree()->get_root();
|
||||||
|
if (root) {
|
||||||
|
uint32_t layer_order_count = 0;
|
||||||
|
_calculate_layer_orders_in_tree(root, layer_order_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When rendering layers, if the layer id (set by user) and sublayer (child id) is the same
|
||||||
|
// we need something else sensible which we can sort repeatably to determine which layers should render first,
|
||||||
|
// so we will simply calculate the order that the layers occur throughout the scene tree.
|
||||||
|
void CanvasLayer::_calculate_layer_orders_in_tree(Node *p_node, uint32_t &r_order) {
|
||||||
|
CanvasLayer *layer = Object::cast_to<CanvasLayer>(p_node);
|
||||||
|
if (layer) {
|
||||||
|
layer->_layer_order_in_tree = r_order++;
|
||||||
|
|
||||||
|
// Force an update of the layer order in the VisualServer
|
||||||
|
set_layer(get_layer());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int n = 0; n < p_node->get_child_count(); n++) {
|
||||||
|
_calculate_layer_orders_in_tree(p_node->get_child(n), r_order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CanvasLayer::show() {
|
void CanvasLayer::show() {
|
||||||
set_visible(true);
|
set_visible(true);
|
||||||
}
|
}
|
||||||
|
@ -183,25 +215,24 @@ 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_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);
|
||||||
_update_follow_viewport();
|
_update_follow_viewport();
|
||||||
|
_update_layer_orders();
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized.");
|
ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized.");
|
||||||
|
_update_layer_orders();
|
||||||
|
|
||||||
vp->_canvas_layer_remove(this);
|
vp->_canvas_layer_remove(this);
|
||||||
VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
|
VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
|
||||||
viewport = RID();
|
viewport = RID();
|
||||||
_update_follow_viewport(false);
|
_update_follow_viewport(false);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_MOVED_IN_PARENT: {
|
case NOTIFICATION_MOVED_IN_PARENT: {
|
||||||
if (is_inside_tree()) {
|
// Note: As this step requires traversing the entire scene tree, it is thus expensive
|
||||||
VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent());
|
// to move the canvas layer multiple times. Take special care when deleting / moving
|
||||||
}
|
// multiple nodes to prevent multiple NOTIFICATION_MOVED_IN_PARENT occurring.
|
||||||
|
_update_layer_orders();
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,8 +279,8 @@ 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_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);
|
||||||
|
_update_layer_orders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +410,7 @@ CanvasLayer::CanvasLayer() {
|
||||||
visible = true;
|
visible = true;
|
||||||
follow_viewport = false;
|
follow_viewport = false;
|
||||||
follow_viewport_scale = 1.0;
|
follow_viewport_scale = 1.0;
|
||||||
|
_layer_order_in_tree = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasLayer::~CanvasLayer() {
|
CanvasLayer::~CanvasLayer() {
|
||||||
|
|
|
@ -45,6 +45,7 @@ class CanvasLayer : public Node {
|
||||||
int layer;
|
int layer;
|
||||||
Transform2D transform;
|
Transform2D transform;
|
||||||
RID canvas;
|
RID canvas;
|
||||||
|
uint32_t _layer_order_in_tree;
|
||||||
|
|
||||||
ObjectID custom_viewport_id; // to check validity
|
ObjectID custom_viewport_id; // to check validity
|
||||||
Viewport *custom_viewport;
|
Viewport *custom_viewport;
|
||||||
|
@ -61,6 +62,8 @@ class CanvasLayer : public Node {
|
||||||
void _update_xform();
|
void _update_xform();
|
||||||
void _update_locrotscale();
|
void _update_locrotscale();
|
||||||
void _update_follow_viewport(bool p_force_exit = false);
|
void _update_follow_viewport(bool p_force_exit = false);
|
||||||
|
void _calculate_layer_orders_in_tree(Node *p_node, uint32_t &r_order);
|
||||||
|
void _update_layer_orders();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
|
|
Loading…
Reference in New Issue