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 diff --git a/tutorials/plugins/running_code_in_the_editor.rst b/tutorials/plugins/running_code_in_the_editor.rst index 8f6c8638a8b..16973b33cdd 100644 --- a/tutorials/plugins/running_code_in_the_editor.rst +++ b/tutorials/plugins/running_code_in_the_editor.rst @@ -552,40 +552,104 @@ 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` +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(): + # Generates a fence each time the node is 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 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(); + } + + // 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 persistent. node.Owner = GetTree().EditedSceneRoot; } -If you are using :ref:`EditorScript`: +.. tip:: + 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 +660,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 +673,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..598669a3fc7 100644 --- a/tutorials/scripting/nodes_and_scene_instances.rst +++ b/tutorials/scripting/nodes_and_scene_instances.rst @@ -174,6 +174,8 @@ 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 -----------------