making_plugins.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. .. _doc_making_plugins:
  2. Making plugins
  3. ==============
  4. About plugins
  5. ~~~~~~~~~~~~~
  6. A plugin is a great way to extend the editor with useful tools. It can be made
  7. entirely with GDScript and standard scenes, without even reloading the editor.
  8. Unlike modules, you don't need to create C++ code nor recompile the engine.
  9. While this makes plugins less powerful, there are still many things you can
  10. do with them. Note that a plugin is similar to any scene you can already
  11. make, except it is created using a script to add functionality.
  12. This tutorial will guide you through the creation of two simple plugins so
  13. you can understand how they work and be able to develop your own. The first
  14. will be a custom node that you can add to any scene in the project and the
  15. other will be a custom dock added to the editor.
  16. Creating a plugin
  17. ~~~~~~~~~~~~~~~~~
  18. Before starting, create a new empty project wherever you want. This will serve
  19. as a base to develop and test the plugins.
  20. The first thing you need to do is to create a new plugin the editor can
  21. understand as such. You need two files for that: ``plugin.cfg`` for the
  22. configuration and a custom GDScript with the functionality.
  23. Plugins have a standard path like ``addons/plugin_name`` inside the project
  24. folder. For this example, create a folder ``my_custom_node`` inside ``addons``.
  25. You should end up with a directory structure like this:
  26. .. image:: img/making_plugins-my_custom_mode_folder.png
  27. Now, open the script editor, click the **File** menu, choose **New TextFile**,
  28. then navigate to the plugin folder and name the file ``plugin.cfg``.
  29. Add the following structure to ``plugin.cfg``:
  30. .. tabs::
  31. .. code-tab:: gdscript GDScript
  32. [plugin]
  33. name="My Custom Node"
  34. description="A custom node made to extend the Godot Engine."
  35. author="Your Name Here"
  36. version="1.0.0"
  37. script="custom_node.gd"
  38. .. code-tab:: csharp
  39. [plugin]
  40. name="My Custom Node"
  41. description="A custom node made to extend the Godot Engine."
  42. author="Your Name Here"
  43. version="1.0.0"
  44. script="CustomNode.cs"
  45. This is a simple INI file with metadata about your plugin. You need to set
  46. the name and description so people can understand what it does. Don't forget
  47. to add your own name so you can be properly credited. Add a version number
  48. so people can see if they have an outdated version; if you are unsure on
  49. how to come up with the version number, check out `Semantic Versioning <https://semver.org/>`_.
  50. Finally, set the main script file to load when your plugin is active.
  51. The script file
  52. ^^^^^^^^^^^^^^^
  53. Open the script editor (F3) and create a new GDScript file called
  54. ``custom_node.gd`` inside the ``my_custom_node`` folder. This script is special
  55. and it has two requirements: it must be a ``tool`` script and it has to
  56. inherit from :ref:`class_EditorPlugin`.
  57. It's important to deal with initialization and clean-up of resources.
  58. A good practice is to use the virtual function
  59. :ref:`_enter_tree() <class_Node_method__enter_tree>` to initialize your plugin and
  60. :ref:`_exit_tree() <class_Node_method__exit_tree>` to clean it up. You can delete the
  61. default GDScript template from your file and replace it with the following
  62. structure:
  63. .. _doc_making_plugins_template_code:
  64. .. tabs::
  65. .. code-tab:: gdscript GDScript
  66. tool
  67. extends EditorPlugin
  68. func _enter_tree():
  69. # Initialization of the plugin goes here
  70. pass
  71. func _exit_tree():
  72. # Clean-up of the plugin goes here
  73. pass
  74. .. code-tab:: csharp
  75. #if TOOLS
  76. using Godot;
  77. using System;
  78. [Tool]
  79. public class CustomNode : EditorPlugin
  80. {
  81. public override void _EnterTree()
  82. {
  83. // Initialization of the plugin goes here
  84. }
  85. public override void _ExitTree()
  86. {
  87. // Initialization of the plugin goes here
  88. }
  89. }
  90. #endif
  91. This is a good template to use when creating new plugins.
  92. A custom node
  93. ~~~~~~~~~~~~~
  94. Sometimes you want a certain behavior in many nodes, such as a custom scene
  95. or control that can be reused. Instancing is helpful in a lot of cases, but
  96. sometimes it can be cumbersome, especially if you're using it in many
  97. projects. A good solution to this is to make a plugin that adds a node with a
  98. custom behavior.
  99. To create a new node type, you can use the function
  100. :ref:`add_custom_type() <class_EditorPlugin_method_add_custom_type>` from the
  101. :ref:`class_EditorPlugin` class. This function can add new types to the editor
  102. (nodes or resources). However, before you can create the type, you need a script
  103. that will act as the logic for the type. While that script doesn't have to use
  104. the ``tool`` keyword, it can be added so the script runs in the editor.
  105. For this tutorial, we'll create a simple button that prints a message when
  106. clicked. For that, we'll need a simple script that extends from
  107. :ref:`class_Button`. It could also extend
  108. :ref:`class_BaseButton` if you prefer:
  109. .. tabs::
  110. .. code-tab:: gdscript GDScript
  111. tool
  112. extends Button
  113. func _enter_tree():
  114. connect("pressed", self, "clicked")
  115. func clicked():
  116. print("You clicked me!")
  117. .. code-tab:: csharp
  118. using Godot;
  119. using System;
  120. [Tool]
  121. public class MyButton : Button
  122. {
  123. public override void _EnterTree()
  124. {
  125. Connect("pressed", this, "clicked");
  126. }
  127. public void clicked()
  128. {
  129. GD.Print("You clicked me!");
  130. }
  131. }
  132. That's it for our basic button. You can save this as ``my_button.gd`` inside the
  133. plugin folder. You'll also need a 16×16 icon to show in the scene tree. If you
  134. don't have one, you can grab the default one from the engine and save it in your
  135. `addons/my_custom_node` folder as `icon.png`, or use the default Godot logo
  136. (`preload("res://icon.png")`). You can also use SVG icons if desired.
  137. .. image:: img/making_plugins-custom_node_icon.png
  138. Now, we need to add it as a custom type so it shows on the **Create New Node**
  139. dialog. For that, change the ``custom_node.gd`` script to the following:
  140. .. tabs::
  141. .. code-tab:: gdscript GDScript
  142. tool
  143. extends EditorPlugin
  144. func _enter_tree():
  145. # Initialization of the plugin goes here
  146. # Add the new type with a name, a parent type, a script and an icon
  147. add_custom_type("MyButton", "Button", preload("my_button.gd"), preload("icon.png"))
  148. func _exit_tree():
  149. # Clean-up of the plugin goes here
  150. # Always remember to remove it from the engine when deactivated
  151. remove_custom_type("MyButton")
  152. .. code-tab:: csharp
  153. #if TOOLS
  154. using Godot;
  155. using System;
  156. [Tool]
  157. public class CustomNode : EditorPlugin
  158. {
  159. public override void _EnterTree()
  160. {
  161. // Initialization of the plugin goes here
  162. // Add the new type with a name, a parent type, a script and an icon
  163. var script = GD.Load<Script>("addons/MyButton.cs");
  164. var texture = GD.Load<Texture>("icon.png");
  165. AddCustomType("MyButton", "Button", script, texture);
  166. }
  167. public override void _ExitTree()
  168. {
  169. // Clean-up of the plugin goes here
  170. // Always remember to remove it from the engine when deactivated
  171. RemoveCustomType("MyButton");
  172. }
  173. }
  174. #endif
  175. With that done, the plugin should already be available in the plugin list in the
  176. **Project Settings**, so activate it as explained in `Checking the results`_.
  177. Then try it out by adding your new node:
  178. .. image:: img/making_plugins-custom_node_create.png
  179. When you add the node, you can see that it already has the script you created
  180. attached to it. Set a text to the button, save and run the scene. When you
  181. click the button, you can see some text in the console:
  182. .. image:: img/making_plugins-custom_node_console.png
  183. A custom dock
  184. ^^^^^^^^^^^^^
  185. Sometimes, you need to extend the editor and add tools that are always available.
  186. An easy way to do it is to add a new dock with a plugin. Docks are just scenes
  187. based on Control, so they are created in a way similar to usual GUI scenes.
  188. Creating a custom dock is done just like a custom node. Create a new
  189. ``plugin.cfg`` file in the ``addons/my_custom_dock`` folder, then
  190. add the following content to it:
  191. .. tabs::
  192. .. code-tab:: gdscript GDScript
  193. [plugin]
  194. name="My Custom Dock"
  195. description="A custom dock made so I can learn how to make plugins."
  196. author="Your Name Here"
  197. version="1.0"
  198. script="custom_dock.gd"
  199. .. code-tab:: csharp
  200. [plugin]
  201. name="My Custom Dock"
  202. description="A custom dock made so I can learn how to make plugins."
  203. author="Your Name Here"
  204. version="1.0"
  205. script="CustomDock.cs"
  206. Then create the script ``custom_dock.gd`` in the same folder. Fill it with the
  207. :ref:`template we've seen before <doc_making_plugins_template_code>` to get a
  208. good start.
  209. Since we're trying to add a new custom dock, we need to create the contents of
  210. the dock. This is nothing more than a standard Godot scene: just create
  211. a new scene in the editor then edit it.
  212. For an editor dock, the root node **must** be a :ref:`Control <class_Control>`
  213. or one of its child classes. For this tutorial, you can create a single button.
  214. The name of the root node will also be the name that appears on the dock tab,
  215. so be sure to give it a short and descriptive name.
  216. Also, don't forget to add some text to your button.
  217. .. image:: img/making_plugins-my_custom_dock_scene.png
  218. Save this scene as ``my_dock.tscn``. Now, we need to grab the scene we created
  219. then add it as a dock in the editor. For this, you can rely on the function
  220. :ref:`add_control_to_dock() <class_EditorPlugin_method_add_control_to_dock>` from the
  221. :ref:`EditorPlugin <class_EditorPlugin>` class.
  222. You need to select a dock position and define the control to add
  223. (which is the scene you just created). Don't forget to
  224. **remove the dock** when the plugin is deactivated.
  225. The script could look like this:
  226. .. tabs::
  227. .. code-tab:: gdscript GDScript
  228. tool
  229. extends EditorPlugin
  230. # A class member to hold the dock during the plugin lifecycle
  231. var dock
  232. func _enter_tree():
  233. # Initialization of the plugin goes here
  234. # Load the dock scene and instance it
  235. dock = preload("res://addons/my_custom_dock/my_dock.tscn").instance()
  236. # Add the loaded scene to the docks
  237. add_control_to_dock(DOCK_SLOT_LEFT_UL, dock)
  238. # Note that LEFT_UL means the left of the editor, upper-left dock
  239. func _exit_tree():
  240. # Clean-up of the plugin goes here
  241. # Remove the dock
  242. remove_control_from_docks(dock)
  243. # Erase the control from the memory
  244. dock.free()
  245. .. code-tab:: csharp
  246. #if TOOLS
  247. using Godot;
  248. using System;
  249. [Tool]
  250. public class CustomDock : EditorPlugin
  251. {
  252. Control dock;
  253. public override void _EnterTree()
  254. {
  255. dock = (Control)GD.Load<PackedScene>("addons/my_custom_dock/my_dock.tscn").Instance();
  256. AddControlToDock(DockSlot.LeftUl, dock);
  257. }
  258. public override void _ExitTree()
  259. {
  260. // Clean-up of the plugin goes here
  261. // Remove the dock
  262. RemoveControlFromDocks(dock);
  263. // Erase the control from the memory
  264. dock.Free();
  265. }
  266. }
  267. #endif
  268. Note that, while the dock will initially appear at its specified position,
  269. the user can freely change its position and save the resulting layout.
  270. Checking the results
  271. ^^^^^^^^^^^^^^^^^^^^
  272. It's now time to check the results of your work. Open the **Project
  273. Settings** and click on the **Plugins** tab. Your plugin should be the only one
  274. on the list. If it is not showing, click on the **Update** button in the
  275. top-right corner.
  276. .. image:: img/making_plugins-project_settings.png
  277. You can see the plugin is inactive on the **Status** column; click on the status
  278. to select **Active**. The dock should become visible before you even close
  279. the settings window. You should now have a custom dock:
  280. .. image:: img/making_plugins-custom_dock.png
  281. Going beyond
  282. ~~~~~~~~~~~~
  283. Now that you've learned how to make basic plugins, you can extend the editor in
  284. several ways. Lots of functionality can be added to the editor with GDScript;
  285. it is a powerful way to create specialized editors without having to delve into
  286. C++ modules.
  287. You can make your own plugins to help yourself and share them in the
  288. `Asset Library <https://godotengine.org/asset-library/>`_ so that people
  289. can benefit from your work.