diff --git a/doc/classes/ViewportTexture.xml b/doc/classes/ViewportTexture.xml index 8ecda45bd6d..36390863cf0 100644 --- a/doc/classes/ViewportTexture.xml +++ b/doc/classes/ViewportTexture.xml @@ -17,6 +17,7 @@ The path to the [Viewport] node to display. This is relative to the scene root, not to the node which uses the texture. + [b]Note:[/b] In the editor, it is automatically updated when the target viewport's node path changes due to renaming or moving the viewport or its ancestors. At runtime, it may not be able to automatically update due to the inability to determine the scene root. diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 01a574def66..348e1ead4a4 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -3998,7 +3998,6 @@ void EditorPropertyResource::_viewport_selected(const NodePath &p_path) { Ref vt; vt.instantiate(); vt->set_viewport_path_in_scene(get_tree()->get_edited_scene_root()->get_path_to(to_node)); - vt->setup_local_to_scene(); emit_changed(get_edited_property(), vt); update_property(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8bdcd9302f3..4aaa2e8f5b9 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -72,10 +72,9 @@ void ViewportTexture::setup_local_to_scene() { if (vp) { vp->viewport_textures.erase(this); + vp = nullptr; } - vp = nullptr; - if (loc_scene->is_ready()) { _setup_local_to_scene(loc_scene); } else { @@ -91,8 +90,24 @@ void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) { path = p_path; - if (get_local_scene()) { + if (vp) { + vp->viewport_textures.erase(this); + vp = nullptr; + } + + if (proxy_ph.is_valid()) { + RS::get_singleton()->free(proxy_ph); + } + if (proxy.is_valid()) { + RS::get_singleton()->free(proxy); + } + proxy_ph = RID(); + proxy = RID(); + + if (get_local_scene() && !path.is_empty()) { setup_local_to_scene(); + } else { + emit_changed(); } } @@ -171,6 +186,8 @@ void ViewportTexture::_setup_local_to_scene(const Node *p_loc_scene) { proxy = RS::get_singleton()->texture_proxy_create(vp->texture_rid); } vp_pending = false; + + emit_changed(); } void ViewportTexture::_bind_methods() { @@ -408,9 +425,28 @@ int Viewport::_sub_window_find(Window *p_window) { return -1; } +void Viewport::_update_viewport_path() { + if (viewport_textures.is_empty()) { + return; + } + + Node *scene_root = get_scene_file_path().is_empty() ? get_owner() : this; + if (!scene_root && is_inside_tree()) { + scene_root = get_tree()->get_edited_scene_root(); + } + if (scene_root && (scene_root == this || scene_root->is_ancestor_of(this))) { + NodePath path_in_scene = scene_root->get_path_to(this); + for (ViewportTexture *E : viewport_textures) { + E->path = path_in_scene; + } + } +} + void Viewport::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { + _update_viewport_path(); + if (get_parent()) { parent = get_parent()->get_viewport(); RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid()); @@ -503,6 +539,10 @@ void Viewport::_notification(int p_what) { RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID()); } break; + case NOTIFICATION_PATH_RENAMED: { + _update_viewport_path(); + } break; + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (!get_tree()) { return; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index e88e0628dd7..de0abec052c 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -317,6 +317,8 @@ private: Ref default_texture; HashSet viewport_textures; + void _update_viewport_path(); + SDFOversize sdf_oversize = SDF_OVERSIZE_120_PERCENT; SDFScale sdf_scale = SDF_SCALE_50_PERCENT;