You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-27 15:57:02 +00:00
Prevent errors when using ViewportTexture
This commit is contained in:
@@ -500,6 +500,13 @@
|
|||||||
Returns [code]true[/code] if the local system is the multiplayer authority of this node.
|
Returns [code]true[/code] if the local system is the multiplayer authority of this node.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</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">
|
<method name="is_physics_processing" qualifiers="const">
|
||||||
<return type="bool" />
|
<return type="bool" />
|
||||||
<description>
|
<description>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<description>
|
<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.
|
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.
|
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>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
<link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link>
|
<link title="GUI in 3D Demo">https://godotengine.org/asset-library/asset/127</link>
|
||||||
|
|||||||
@@ -2786,6 +2786,10 @@ bool Node::is_displayed_folded() const {
|
|||||||
return data.display_folded;
|
return data.display_folded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Node::is_ready() const {
|
||||||
|
return !data.ready_first;
|
||||||
|
}
|
||||||
|
|
||||||
void Node::request_ready() {
|
void Node::request_ready() {
|
||||||
data.ready_first = true;
|
data.ready_first = true;
|
||||||
}
|
}
|
||||||
@@ -2932,6 +2936,7 @@ void Node::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("queue_free"), &Node::queue_free);
|
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("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("set_multiplayer_authority", "id", "recursive"), &Node::set_multiplayer_authority, DEFVAL(true));
|
||||||
ClassDB::bind_method(D_METHOD("get_multiplayer_authority"), &Node::get_multiplayer_authority);
|
ClassDB::bind_method(D_METHOD("get_multiplayer_authority"), &Node::get_multiplayer_authority);
|
||||||
|
|||||||
@@ -500,6 +500,7 @@ public:
|
|||||||
bool can_process_notification(int p_what) const;
|
bool can_process_notification(int p_what) const;
|
||||||
bool is_enabled() const;
|
bool is_enabled() const;
|
||||||
|
|
||||||
|
bool is_ready() const;
|
||||||
void request_ready();
|
void request_ready();
|
||||||
|
|
||||||
static void print_orphan_nodes();
|
static void print_orphan_nodes();
|
||||||
|
|||||||
@@ -61,6 +61,10 @@
|
|||||||
#include "servers/rendering/rendering_server_globals.h"
|
#include "servers/rendering/rendering_server_globals.h"
|
||||||
|
|
||||||
void ViewportTexture::setup_local_to_scene() {
|
void ViewportTexture::setup_local_to_scene() {
|
||||||
|
if (vp_pending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Node *loc_scene = get_local_scene();
|
Node *loc_scene = get_local_scene();
|
||||||
if (!loc_scene) {
|
if (!loc_scene) {
|
||||||
return;
|
return;
|
||||||
@@ -72,22 +76,11 @@ void ViewportTexture::setup_local_to_scene() {
|
|||||||
|
|
||||||
vp = nullptr;
|
vp = nullptr;
|
||||||
|
|
||||||
Node *vpn = loc_scene->get_node(path);
|
if (loc_scene->is_ready()) {
|
||||||
ERR_FAIL_COND_MSG(!vpn, "ViewportTexture: Path to node is invalid.");
|
_setup_local_to_scene(loc_scene);
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
ERR_FAIL_COND(proxy.is_valid()); // Should be invalid.
|
loc_scene->connect(SNAME("ready"), callable_mp(this, &ViewportTexture::_setup_local_to_scene).bind(loc_scene), CONNECT_ONE_SHOT);
|
||||||
proxy = RS::get_singleton()->texture_proxy_create(vp->texture_rid);
|
vp_pending = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,17 +101,32 @@ NodePath ViewportTexture::get_viewport_path_in_scene() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ViewportTexture::get_width() 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;
|
return vp->size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ViewportTexture::get_height() const {
|
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;
|
return vp->size.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2 ViewportTexture::get_size() const {
|
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;
|
return vp->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,10 +143,36 @@ bool ViewportTexture::has_alpha() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ref<Image> ViewportTexture::get_image() 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);
|
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() {
|
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("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);
|
ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene);
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ class ViewportTexture : public Texture2D {
|
|||||||
|
|
||||||
friend class Viewport;
|
friend class Viewport;
|
||||||
Viewport *vp = nullptr;
|
Viewport *vp = nullptr;
|
||||||
|
bool vp_pending = false;
|
||||||
|
|
||||||
|
void _setup_local_to_scene(const Node *p_loc_scene);
|
||||||
|
|
||||||
mutable RID proxy_ph;
|
mutable RID proxy_ph;
|
||||||
mutable RID proxy;
|
mutable RID proxy;
|
||||||
|
|||||||
Reference in New Issue
Block a user