Skip to content

Plugin/AddOn Documentation Overhaul #10535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions tutorials/plugins/editor/inspector_plugins.rst
Original file line number Diff line number Diff line change
@@ -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
106 changes: 85 additions & 21 deletions tutorials/plugins/running_code_in_the_editor.rst
Original file line number Diff line number Diff line change
@@ -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) <class_Node_method_add_child>` 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 <class_Node_property_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) <class_Node_method_add_child>`.

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<PackedScene>("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<class_Node_private_method__ready>`
or make instances persistent by setting children's :ref:`owner<class_Node_property_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<class_EditorScript>`:
.. tip::
Instanced Scenes cannot set their children's :ref:`owner <class_Node_property_owner>`
as the scene root, but can store scene-specific persistent settings in their properties.

You can also generate persistent children using :ref:`EditorScript<class_EditorScript>`:

.. tabs::
.. code-tab:: gdscript GDScript
@@ -596,8 +660,8 @@ If you are using :ref:`EditorScript<class_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<class_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();
}

2 changes: 2 additions & 0 deletions tutorials/scripting/nodes_and_scene_instances.rst
Original file line number Diff line number Diff line change
@@ -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
-----------------