From 688d9c70a4de1d7e90a17eb8484a7a43f6de6ac5 Mon Sep 17 00:00:00 2001 From: betalars Date: Tue, 21 Jan 2025 13:06:37 +0100 Subject: [PATCH 1/4] Fix #9430 by suggesting to use better naming for plugin script --- .../plugins/editor/inspector_plugins.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tutorials/plugins/editor/inspector_plugins.rst b/tutorials/plugins/editor/inspector_plugins.rst index 0cc4bd8fdaa..2665787b4b4 100644 --- a/tutorials/plugins/editor/inspector_plugins.rst +++ b/tutorials/plugins/editor/inspector_plugins.rst @@ -27,15 +27,16 @@ Create a new empty plugin to get started. .. seealso:: See :ref:`doc_making_plugins` guide to set up your new plugin. -Let's assume you've called your plugin folder ``my_inspector_plugin``. If so, -you should end up with a new ``addons/my_inspector_plugin`` folder that contains -two files: ``plugin.cfg`` and ``plugin.gd``. - -As before, ``plugin.gd`` is a script extending :ref:`class_EditorPlugin` and you -need to introduce new code for its ``_enter_tree`` and ``_exit_tree`` methods. -To set up your inspector plugin, you must load its script, then create and add -the instance by calling ``add_inspector_plugin()``. If the plugin is disabled, -you should remove the instance you have added by calling +Let's assume you've called your plugin folder ``my_inspector_plugin`` and named +the script accordingly. If so, you should end up with a new +``addons/my_inspector_plugin`` folder that contains two files: ``plugin.cfg`` +and ``my_inspector_plugin.gd``. + +As before, ``my_inspector_plugin.gd`` is a script extending +:ref:`class_EditorPlugin` and you need to introduce new code for its ``_enter_tree`` +and ``_exit_tree`` methods. To set up your inspector plugin, you must load its +script, then create and add the instance by calling ``add_inspector_plugin()``. +If the plugin is disabled, you should remove the instance you have added by calling ``remove_inspector_plugin()``. .. note:: Here, you are loading a script and not a packed scene. Therefore you From de52d9dd12837b4e4074c1c4179d4743169912c5 Mon Sep 17 00:00:00 2001 From: betalars Date: Thu, 23 Jan 2025 00:32:25 +0100 Subject: [PATCH 2/4] overhauling instancing scenes, fixes #7668 --- .../plugins/running_code_in_the_editor.rst | 104 ++++++++++++++---- .../scripting/nodes_and_scene_instances.rst | 1 + 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/tutorials/plugins/running_code_in_the_editor.rst b/tutorials/plugins/running_code_in_the_editor.rst index 8f6c8638a8b..ffe73785db4 100644 --- a/tutorials/plugins/running_code_in_the_editor.rst +++ b/tutorials/plugins/running_code_in_the_editor.rst @@ -552,40 +552,102 @@ of all OmniLight3D nodes: Instancing scenes ----------------- -You can instantiate packed scenes normally and add them to the scene currently -opened in the editor. By default, nodes or scenes added with -:ref:`Node.add_child(node) ` are **not** visible -in the Scene tree dock and are **not** persisted to disk. If you wish the node -or scene to be visible in the scene tree dock and persisted to disk when saving -the scene, you need to set the child node's :ref:`owner ` -property to the currently edited scene root. +You can +:ref:`create instances of a packed scene<_doc_nodes_and_scene_instances_instancing_scenes>` +and add them to the scene tree using :ref:`add_child(node) `. -If you are using ``@tool``: +Instances can then be modified to create a fence for instance: .. tabs:: - .. code-tab:: gdscript GDScript + .. code-tab:: gdscript + # Define length and spacing of fence. + var length = 10 + var offset = Vector3(2, 0, 0) + func _ready(): - var node = Node3D.new() - add_child(node) # Parent could be any node in the scene + # Pre-loads a packed scene. + var packed_panel = preload("res://Models/Fence01.tscn") + + # Repeat for the number of panels needed to fit the length. + for i in range(length/offset.length()): - # The line below is required to make the node visible in the Scene tree dock - # and persist changes made by the tool script to the saved scene file. - node.owner = get_tree().edited_scene_root + # Instances i fence panels. + var fence_instance = packed_panel.instantiate() + + # Adds instance as child to this script's node. + add_child(fence_instance) + + # Applies correct positional offset for each panel. + fence_instance.position = i * offset .. code-tab:: csharp + // Define length and spacing of fence. + public float Length = 10.0; + public Vector3 Offset = new Vector3(2.0, 0.0, 0.0); + public override void _Ready() + { + // Loads a packed scene. + var packed_panel = ResourceLoader.Load("res://Models/Fence01.tscn"); + + # Repeat for the number of panels needed to fit the length. + for (int index = 1; index <= Length/Offset.Length(); index++) + { + // Instances i fence panels. + var panel_instance = packed_panel.Instantiate(); + + // Adds instance as child to this script's node. + add_child(panel_instance); + + # Applies correct positional offset for each panel. + fence_instance.position = i * offset + } + } + +Remember that children added via code are **not** saved with the scene +and therefore won't be visible in the scene dock. +Tools can either generate dynamic instances during :ref:`_ready` +or make instances persistent by setting children's :ref:`owner` +as the scene root: + +.. tabs:: + .. code-tab:: gdscript GDScript + # Either add dynamic children at ready: + func _ready(): + add_dynamic_fence() + + # Or create a persistent fence once: + func add_persistent_fence(): + var fence_instance = preload("res://Models/Fence01.tscn").instantiate() + add_child(fence_instance) + + # Sets child owner to scene root so it is visible in the scene dock and persistent. + fence_instance.owner = get_tree().edited_scene_root + + .. code-tab:: csharp C# + // Either add dynamic children at ready: + public override void _Ready() + { + AddDynamicFence(); + } + + // Or create a persistent fence once: + public void AddPersistentFence() { var node = new Node3D(); AddChild(node); // Parent could be any node in the scene - // The line below is required to make the node visible in the Scene tree dock - // and persist changes made by the tool script to the saved scene file. + // Sets child owner to scene root so it is visible in the scene dock and persistent. node.Owner = GetTree().EditedSceneRoot; } -If you are using :ref:`EditorScript`: +.. danger:: + Instanced Scenes cannot set their children's :ref:`owner ` + as the scene root, but can store scene-specific persistent settings in their properties. + +You can also generate persistent children using :ref:`EditorScript`: .. tabs:: .. code-tab:: gdscript GDScript @@ -596,8 +658,8 @@ If you are using :ref:`EditorScript`: var node = Node3D.new() parent.add_child(node) - # The line below is required to make the node visible in the Scene tree dock - # and persist changes made by the tool script to the saved scene file. + # As Editor Scripts only run once, they must set child owner to the scene root. + # This makes a Node persistent and visible in the scene dock. node.owner = get_scene() .. code-tab:: csharp @@ -609,8 +671,8 @@ If you are using :ref:`EditorScript`: var node = new Node3D(); parent.AddChild(node); - // The line below is required to make the node visible in the Scene tree dock - // and persist changes made by the tool script to the saved scene file. + // As Editor Scripts only run once, they must set child owner to the scene root. + // This makes a Node persistent and visible in the scene dock. node.Owner = GetScene(); } diff --git a/tutorials/scripting/nodes_and_scene_instances.rst b/tutorials/scripting/nodes_and_scene_instances.rst index e10571c0208..473747a72dd 100644 --- a/tutorials/scripting/nodes_and_scene_instances.rst +++ b/tutorials/scripting/nodes_and_scene_instances.rst @@ -174,6 +174,7 @@ When you free a node, it also frees all its children. Thanks to this, to delete an entire branch of the scene tree, you only have to free the topmost parent node. +.. _doc_nodes_and_scene_instances_instancing_scenes: Instancing scenes ----------------- From 65a74731676dcb8c1178c09be39ef64f0585bb26 Mon Sep 17 00:00:00 2001 From: betalars Date: Thu, 23 Jan 2025 00:59:07 +0100 Subject: [PATCH 3/4] fix syntax errors --- tutorials/plugins/running_code_in_the_editor.rst | 2 +- tutorials/scripting/nodes_and_scene_instances.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tutorials/plugins/running_code_in_the_editor.rst b/tutorials/plugins/running_code_in_the_editor.rst index ffe73785db4..a0cff067424 100644 --- a/tutorials/plugins/running_code_in_the_editor.rst +++ b/tutorials/plugins/running_code_in_the_editor.rst @@ -553,7 +553,7 @@ Instancing scenes ----------------- You can -:ref:`create instances of a packed scene<_doc_nodes_and_scene_instances_instancing_scenes>` +:ref:`create instances of a packed scene` and add them to the scene tree using :ref:`add_child(node) `. Instances can then be modified to create a fence for instance: diff --git a/tutorials/scripting/nodes_and_scene_instances.rst b/tutorials/scripting/nodes_and_scene_instances.rst index 473747a72dd..598669a3fc7 100644 --- a/tutorials/scripting/nodes_and_scene_instances.rst +++ b/tutorials/scripting/nodes_and_scene_instances.rst @@ -175,6 +175,7 @@ an entire branch of the scene tree, you only have to free the topmost parent node. .. _doc_nodes_and_scene_instances_instancing_scenes: + Instancing scenes ----------------- From a5fa88b42c0f9c66c5518dedc061fc6695435959 Mon Sep 17 00:00:00 2001 From: betalars Date: Thu, 23 Jan 2025 23:55:01 +0100 Subject: [PATCH 4/4] enhance comments and replace incorrect danger tag with tip --- tutorials/plugins/running_code_in_the_editor.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tutorials/plugins/running_code_in_the_editor.rst b/tutorials/plugins/running_code_in_the_editor.rst index a0cff067424..16973b33cdd 100644 --- a/tutorials/plugins/running_code_in_the_editor.rst +++ b/tutorials/plugins/running_code_in_the_editor.rst @@ -616,6 +616,7 @@ as the scene root: .. code-tab:: gdscript GDScript # Either add dynamic children at ready: func _ready(): + # Generates a fence each time the node is ready: add_dynamic_fence() # Or create a persistent fence once: @@ -623,13 +624,14 @@ as the scene root: var fence_instance = preload("res://Models/Fence01.tscn").instantiate() add_child(fence_instance) - # Sets child owner to scene root so it is visible in the scene dock and persistent. + # Sets child owner to scene root so it is persistent. fence_instance.owner = get_tree().edited_scene_root .. code-tab:: csharp C# // Either add dynamic children at ready: public override void _Ready() { + // Generates a fence each time the node is ready: AddDynamicFence(); } @@ -639,11 +641,11 @@ as the scene root: var node = new Node3D(); AddChild(node); // Parent could be any node in the scene - // Sets child owner to scene root so it is visible in the scene dock and persistent. + // Sets child owner to scene root so it is persistent. node.Owner = GetTree().EditedSceneRoot; } -.. danger:: +.. tip:: Instanced Scenes cannot set their children's :ref:`owner ` as the scene root, but can store scene-specific persistent settings in their properties.