diff options
author | kobewi <kobewi4e@gmail.com> | 2023-04-06 14:47:49 +0200 |
---|---|---|
committer | RĂ©mi Verschelde <rverschelde@gmail.com> | 2023-05-12 12:31:22 +0200 |
commit | 1146172b302a68393e4f97b47e6460d78db75518 (patch) | |
tree | 6b2cfc2e2ac14f2e6aa177ea561c569630c11f73 | |
parent | 2a8501e1a26b12dadd4f6fcbed799e319cd77027 (diff) |
Prevent errors when using ViewportTexture
(cherry picked from commit 1b9802fa8cb45e876cd90d6a174b95b270a7f934)
-rw-r--r-- | doc/classes/Node.xml | 7 | ||||
-rw-r--r-- | doc/classes/ViewportTexture.xml | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 5 | ||||
-rw-r--r-- | scene/main/node.h | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 72 | ||||
-rw-r--r-- | scene/main/viewport.h | 3 |
6 files changed, 70 insertions, 20 deletions
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 62d708618a..ead022ecb3 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -500,6 +500,13 @@ Returns [code]true[/code] if the local system is the multiplayer authority of this node. </description> </method> + <method name="is_node_ready" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the node is ready, i.e. it's inside scene tree and all its children are initialized. + [method request_ready] resets it back to [code]false[/code]. + </description> + </method> <method name="is_physics_processing" qualifiers="const"> <return type="bool" /> <description> diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml index 6bd64a50bb..8ecda45bd6 100644 --- a/doc/classes/ViewportTexture.xml +++ b/doc/classes/ViewportTexture.xml @@ -6,7 +6,7 @@ <description> Displays the content of a [Viewport] node as a dynamic [Texture2D]. This can be used to mix controls, 2D, and 3D elements in the same scene. To create a ViewportTexture in code, use the [method Viewport.get_texture] method on the target viewport. - [b]Note:[/b] When local to scene, this texture uses [method Resource.setup_local_to_scene] to set the proxy texture and flags in the local viewport. + [b]Note:[/b] When local to scene, this texture uses [method Resource.setup_local_to_scene] to set the proxy texture and flags in the local viewport. Local to scene viewport textures will return incorrect data until the scene root is ready (see [signal Node.ready]). </description> <tutorials> <link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link> diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 52c1df8110..057fd15f1b 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2759,6 +2759,10 @@ bool Node::is_displayed_folded() const { return data.display_folded; } +bool Node::is_ready() const { + return !data.ready_first; +} + void Node::request_ready() { data.ready_first = true; } @@ -2897,6 +2901,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("queue_free"), &Node::queue_free); ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready); + ClassDB::bind_method(D_METHOD("is_node_ready"), &Node::is_ready); ClassDB::bind_method(D_METHOD("set_multiplayer_authority", "id", "recursive"), &Node::set_multiplayer_authority, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_multiplayer_authority"), &Node::get_multiplayer_authority); diff --git a/scene/main/node.h b/scene/main/node.h index 493578bc5b..4a606538a8 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -455,6 +455,7 @@ public: bool can_process_notification(int p_what) const; bool is_enabled() const; + bool is_ready() const; void request_ready(); static void print_orphan_nodes(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8cd57536bf..8bdcd9302f 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -61,6 +61,10 @@ #include "servers/rendering/rendering_server_globals.h" void ViewportTexture::setup_local_to_scene() { + if (vp_pending) { + return; + } + Node *loc_scene = get_local_scene(); if (!loc_scene) { return; @@ -72,22 +76,11 @@ void ViewportTexture::setup_local_to_scene() { vp = nullptr; - Node *vpn = loc_scene->get_node(path); - ERR_FAIL_COND_MSG(!vpn, "ViewportTexture: Path to node is invalid."); - - vp = Object::cast_to<Viewport>(vpn); - - ERR_FAIL_COND_MSG(!vp, "ViewportTexture: Path to node does not point to a viewport."); - - vp->viewport_textures.insert(this); - - ERR_FAIL_NULL(RenderingServer::get_singleton()); - if (proxy_ph.is_valid()) { - RS::get_singleton()->texture_proxy_update(proxy, vp->texture_rid); - RS::get_singleton()->free(proxy_ph); + if (loc_scene->is_ready()) { + _setup_local_to_scene(loc_scene); } else { - ERR_FAIL_COND(proxy.is_valid()); // Should be invalid. - proxy = RS::get_singleton()->texture_proxy_create(vp->texture_rid); + loc_scene->connect(SNAME("ready"), callable_mp(this, &ViewportTexture::_setup_local_to_scene).bind(loc_scene), CONNECT_ONE_SHOT); + vp_pending = true; } } @@ -108,17 +101,32 @@ NodePath ViewportTexture::get_viewport_path_in_scene() const { } int ViewportTexture::get_width() const { - ERR_FAIL_COND_V_MSG(!vp, 0, "Viewport Texture must be set to use it."); + if (!vp) { + if (!vp_pending) { + ERR_PRINT("Viewport Texture must be set to use it."); + } + return 0; + } return vp->size.width; } int ViewportTexture::get_height() const { - ERR_FAIL_COND_V_MSG(!vp, 0, "Viewport Texture must be set to use it."); + if (!vp) { + if (!vp_pending) { + ERR_PRINT("Viewport Texture must be set to use it."); + } + return 0; + } return vp->size.height; } Size2 ViewportTexture::get_size() const { - ERR_FAIL_COND_V_MSG(!vp, Size2(), "Viewport Texture must be set to use it."); + if (!vp) { + if (!vp_pending) { + ERR_PRINT("Viewport Texture must be set to use it."); + } + return Size2(); + } return vp->size; } @@ -135,10 +143,36 @@ bool ViewportTexture::has_alpha() const { } Ref<Image> ViewportTexture::get_image() const { - ERR_FAIL_COND_V_MSG(!vp, Ref<Image>(), "Viewport Texture must be set to use it."); + if (!vp) { + if (!vp_pending) { + ERR_PRINT("Viewport Texture must be set to use it."); + } + return Ref<Image>(); + } return RS::get_singleton()->texture_2d_get(vp->texture_rid); } +void ViewportTexture::_setup_local_to_scene(const Node *p_loc_scene) { + Node *vpn = p_loc_scene->get_node(path); + ERR_FAIL_COND_MSG(!vpn, "ViewportTexture: Path to node is invalid."); + + vp = Object::cast_to<Viewport>(vpn); + + ERR_FAIL_COND_MSG(!vp, "ViewportTexture: Path to node does not point to a viewport."); + + vp->viewport_textures.insert(this); + + ERR_FAIL_NULL(RenderingServer::get_singleton()); + if (proxy_ph.is_valid()) { + RS::get_singleton()->texture_proxy_update(proxy, vp->texture_rid); + RS::get_singleton()->free(proxy_ph); + } else { + ERR_FAIL_COND(proxy.is_valid()); // Should be invalid. + proxy = RS::get_singleton()->texture_proxy_create(vp->texture_rid); + } + vp_pending = false; +} + void ViewportTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene); ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 5213c0db01..e88e0628dd 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -59,6 +59,9 @@ class ViewportTexture : public Texture2D { friend class Viewport; Viewport *vp = nullptr; + bool vp_pending = false; + + void _setup_local_to_scene(const Node *p_loc_scene); mutable RID proxy_ph; mutable RID proxy; |