123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- .. _doc_making_plugins:
- Making plugins
- ==============
- About plugins
- ~~~~~~~~~~~~~
- A plugin is a great way to extend the editor with useful tools. It can be made
- entirely with GDScript and standard scenes, without even reloading the editor.
- Unlike modules, you don't need to create C++ code nor recompile the engine.
- While this makes plugins less powerful, there are still many things you can
- do with them. Note that a plugin is similar to any scene you can already
- make, except it is created using a script to add functionality.
- This tutorial will guide you through the creation of two simple plugins so
- you can understand how they work and be able to develop your own. The first
- will be a custom node that you can add to any scene in the project and the
- other will be a custom dock added to the editor.
- Creating a plugin
- ~~~~~~~~~~~~~~~~~
- Before starting, create a new empty project wherever you want. This will serve
- as a base to develop and test the plugins.
- The first thing you need to do is to create a new plugin the editor can
- understand as such. You need two files for that: ``plugin.cfg`` for the
- configuration and a custom GDScript with the functionality.
- Plugins have a standard path like ``addons/plugin_name`` inside the project
- folder. For this example, create a folder ``my_custom_node`` inside ``addons``.
- You should end up with a directory structure like this:
- .. image:: img/making_plugins-my_custom_mode_folder.png
- Now, open the script editor, click the **File** menu, choose **New TextFile**,
- then navigate to the plugin folder and name the file ``plugin.cfg``.
- Add the following structure to ``plugin.cfg``:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- [plugin]
- name="My Custom Node"
- description="A custom node made to extend the Godot Engine."
- author="Your Name Here"
- version="1.0.0"
- script="custom_node.gd"
- .. code-tab:: csharp
-
- [plugin]
- name="My Custom Node"
- description="A custom node made to extend the Godot Engine."
- author="Your Name Here"
- version="1.0.0"
- script="CustomNode.cs"
- This is a simple INI file with metadata about your plugin. You need to set
- the name and description so people can understand what it does. Don't forget
- to add your own name so you can be properly credited. Add a version number
- so people can see if they have an outdated version; if you are unsure on
- how to come up with the version number, check out `Semantic Versioning <https://semver.org/>`_.
- Finally, set the main script file to load when your plugin is active.
- The script file
- ^^^^^^^^^^^^^^^
- Open the script editor (F3) and create a new GDScript file called
- ``custom_node.gd`` inside the ``my_custom_node`` folder. This script is special
- and it has two requirements: it must be a ``tool`` script and it has to
- inherit from :ref:`class_EditorPlugin`.
- It's important to deal with initialization and clean-up of resources.
- A good practice is to use the virtual function
- :ref:`_enter_tree() <class_Node_method__enter_tree>` to initialize your plugin and
- :ref:`_exit_tree() <class_Node_method__exit_tree>` to clean it up. You can delete the
- default GDScript template from your file and replace it with the following
- structure:
- .. _doc_making_plugins_template_code:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- tool
- extends EditorPlugin
- func _enter_tree():
- # Initialization of the plugin goes here
- pass
- func _exit_tree():
- # Clean-up of the plugin goes here
- pass
- .. code-tab:: csharp
-
- #if TOOLS
- using Godot;
- using System;
- [Tool]
- public class CustomNode : EditorPlugin
- {
- public override void _EnterTree()
- {
- // Initialization of the plugin goes here
- }
- public override void _ExitTree()
- {
- // Initialization of the plugin goes here
- }
- }
- #endif
- This is a good template to use when creating new plugins.
- A custom node
- ~~~~~~~~~~~~~
- Sometimes you want a certain behavior in many nodes, such as a custom scene
- or control that can be reused. Instancing is helpful in a lot of cases, but
- sometimes it can be cumbersome, especially if you're using it in many
- projects. A good solution to this is to make a plugin that adds a node with a
- custom behavior.
- To create a new node type, you can use the function
- :ref:`add_custom_type() <class_EditorPlugin_method_add_custom_type>` from the
- :ref:`class_EditorPlugin` class. This function can add new types to the editor
- (nodes or resources). However, before you can create the type, you need a script
- that will act as the logic for the type. While that script doesn't have to use
- the ``tool`` keyword, it can be added so the script runs in the editor.
- For this tutorial, we'll create a simple button that prints a message when
- clicked. For that, we'll need a simple script that extends from
- :ref:`class_Button`. It could also extend
- :ref:`class_BaseButton` if you prefer:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- tool
- extends Button
- func _enter_tree():
- connect("pressed", self, "clicked")
- func clicked():
- print("You clicked me!")
- .. code-tab:: csharp
-
- using Godot;
- using System;
- [Tool]
- public class MyButton : Button
- {
- public override void _EnterTree()
- {
- Connect("pressed", this, "clicked");
- }
- public void clicked()
- {
- GD.Print("You clicked me!");
- }
- }
- That's it for our basic button. You can save this as ``my_button.gd`` inside the
- plugin folder. You'll also need a 16×16 icon to show in the scene tree. If you
- don't have one, you can grab the default one from the engine and save it in your
- `addons/my_custom_node` folder as `icon.png`, or use the default Godot logo
- (`preload("res://icon.png")`). You can also use SVG icons if desired.
- .. image:: img/making_plugins-custom_node_icon.png
- Now, we need to add it as a custom type so it shows on the **Create New Node**
- dialog. For that, change the ``custom_node.gd`` script to the following:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- tool
- extends EditorPlugin
- func _enter_tree():
- # Initialization of the plugin goes here
- # Add the new type with a name, a parent type, a script and an icon
- add_custom_type("MyButton", "Button", preload("my_button.gd"), preload("icon.png"))
- func _exit_tree():
- # Clean-up of the plugin goes here
- # Always remember to remove it from the engine when deactivated
- remove_custom_type("MyButton")
- .. code-tab:: csharp
-
- #if TOOLS
- using Godot;
- using System;
- [Tool]
- public class CustomNode : EditorPlugin
- {
- public override void _EnterTree()
- {
- // Initialization of the plugin goes here
- // Add the new type with a name, a parent type, a script and an icon
- var script = GD.Load<Script>("addons/MyButton.cs");
- var texture = GD.Load<Texture>("icon.png");
- AddCustomType("MyButton", "Button", script, texture);
- }
- public override void _ExitTree()
- {
- // Clean-up of the plugin goes here
- // Always remember to remove it from the engine when deactivated
- RemoveCustomType("MyButton");
- }
- }
- #endif
- With that done, the plugin should already be available in the plugin list in the
- **Project Settings**, so activate it as explained in `Checking the results`_.
- Then try it out by adding your new node:
- .. image:: img/making_plugins-custom_node_create.png
- When you add the node, you can see that it already has the script you created
- attached to it. Set a text to the button, save and run the scene. When you
- click the button, you can see some text in the console:
- .. image:: img/making_plugins-custom_node_console.png
- A custom dock
- ^^^^^^^^^^^^^
- Sometimes, you need to extend the editor and add tools that are always available.
- An easy way to do it is to add a new dock with a plugin. Docks are just scenes
- based on Control, so they are created in a way similar to usual GUI scenes.
- Creating a custom dock is done just like a custom node. Create a new
- ``plugin.cfg`` file in the ``addons/my_custom_dock`` folder, then
- add the following content to it:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- [plugin]
- name="My Custom Dock"
- description="A custom dock made so I can learn how to make plugins."
- author="Your Name Here"
- version="1.0"
- script="custom_dock.gd"
- .. code-tab:: csharp
-
- [plugin]
- name="My Custom Dock"
- description="A custom dock made so I can learn how to make plugins."
- author="Your Name Here"
- version="1.0"
- script="CustomDock.cs"
- Then create the script ``custom_dock.gd`` in the same folder. Fill it with the
- :ref:`template we've seen before <doc_making_plugins_template_code>` to get a
- good start.
- Since we're trying to add a new custom dock, we need to create the contents of
- the dock. This is nothing more than a standard Godot scene: just create
- a new scene in the editor then edit it.
- For an editor dock, the root node **must** be a :ref:`Control <class_Control>`
- or one of its child classes. For this tutorial, you can create a single button.
- The name of the root node will also be the name that appears on the dock tab,
- so be sure to give it a short and descriptive name.
- Also, don't forget to add some text to your button.
- .. image:: img/making_plugins-my_custom_dock_scene.png
- Save this scene as ``my_dock.tscn``. Now, we need to grab the scene we created
- then add it as a dock in the editor. For this, you can rely on the function
- :ref:`add_control_to_dock() <class_EditorPlugin_method_add_control_to_dock>` from the
- :ref:`EditorPlugin <class_EditorPlugin>` class.
- You need to select a dock position and define the control to add
- (which is the scene you just created). Don't forget to
- **remove the dock** when the plugin is deactivated.
- The script could look like this:
- .. tabs::
- .. code-tab:: gdscript GDScript
-
- tool
- extends EditorPlugin
- # A class member to hold the dock during the plugin lifecycle
- var dock
- func _enter_tree():
- # Initialization of the plugin goes here
- # Load the dock scene and instance it
- dock = preload("res://addons/my_custom_dock/my_dock.tscn").instance()
- # Add the loaded scene to the docks
- add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
- # Note that LEFT_UL means the left of the editor, upper-left dock
- func _exit_tree():
- # Clean-up of the plugin goes here
- # Remove the dock
- remove_control_from_docks(dock)
- # Erase the control from the memory
- dock.free()
- .. code-tab:: csharp
-
- #if TOOLS
- using Godot;
- using System;
- [Tool]
- public class CustomDock : EditorPlugin
- {
- Control dock;
-
- public override void _EnterTree()
- {
- dock = (Control)GD.Load<PackedScene>("addons/my_custom_dock/my_dock.tscn").Instance();
- AddControlToDock(DockSlot.LeftUl, dock);
- }
- public override void _ExitTree()
- {
- // Clean-up of the plugin goes here
- // Remove the dock
- RemoveControlFromDocks(dock);
- // Erase the control from the memory
- dock.Free();
- }
- }
- #endif
- Note that, while the dock will initially appear at its specified position,
- the user can freely change its position and save the resulting layout.
- Checking the results
- ^^^^^^^^^^^^^^^^^^^^
- It's now time to check the results of your work. Open the **Project
- Settings** and click on the **Plugins** tab. Your plugin should be the only one
- on the list. If it is not showing, click on the **Update** button in the
- top-right corner.
- .. image:: img/making_plugins-project_settings.png
- You can see the plugin is inactive on the **Status** column; click on the status
- to select **Active**. The dock should become visible before you even close
- the settings window. You should now have a custom dock:
- .. image:: img/making_plugins-custom_dock.png
- Going beyond
- ~~~~~~~~~~~~
- Now that you've learned how to make basic plugins, you can extend the editor in
- several ways. Lots of functionality can be added to the editor with GDScript;
- it is a powerful way to create specialized editors without having to delve into
- C++ modules.
- You can make your own plugins to help yourself and share them in the
- `Asset Library <https://godotengine.org/asset-library/>`_ so that people
- can benefit from your work.
|