Extending the Editor with Plugins in Godot
- Getting Started
- Plugin Overview
- Creating Your First Plugin
- Taking a Closer Look
- Handling Node Selection
- Adding the Button
- Developing an Advanced Plugin
- Creating the Menu Scene
- Loading and Unloading the Menu
- Getting Selected Nodes
- 2D Physics in Godot
- Starting and Stopping Physics
- Custom Physics Spaces
- Physics Frames
- Adding Quality of Life Features
- Where to Go From Here?
Adding the Button
Instead of using the editor to create a button, you’ll do so by code. To get started, you’ll need a variable to store a reference to the button. Add a new variable below
var node_to_edit : Node:
var visibility_button : Button
With that out of the way, replace the
pass keyword in the
_add_button function with the code below:
visibility_button = Button.new()
visibility_button.text = "Toggle visibility"
visibility_button.focus_mode = Control.FOCUS_NONE
visibility_button.flat = true
Most of the code above is creating the button and setting it up. Here’s a breakdown:
- Set the text of the button to “Toggle visibility”
- Disable the button’s focus mode so it doesn’t steal focus from the editor
- Make the button appear flat like the other buttons in the toolbar
- Check if the button already exists. If it does, return and don’t do anything.
- Create a new button and set its properties:
- Connect the button’s
pressedsignal to the
_on_button_pressedfunction, which doesn’t exist yet.
- Add the button to the toolbar using the
add_control_to_containerfunction. This function takes two parameters: the container to add the button to and the button itself.
There are a lot more places you can add controls to besides the toolbar. Godot has two enums for this as part of the
DockSlot. You can find a full list in the EditorPlugin page of the documentation. You can experiment with these to find a suitable place to add your control(s).
Next up is defining what should happen when you click the button. This is the easiest part! It’s the same code as you’d expect to use in a game. Add the function below:
func _on_button_pressed() -> void:
node_to_edit.visible = !node_to_edit.visible
This changes the
visible property of the selected node to be the opposite of what it was before.
With the code you have set up now, you can already test out the plugin. Open the Project Settings menu and restart the plugin via the Plugins tab by toggling its Enable status off and on.
Next, open the 2D screen and select any node. You should see the button you defined above appear in the toolbar. When you click it, the selected node gets hidden or shown depending on its current state. Pretty neat!
Before patting yourself on the back too much, don’t forget about the cleanup. Right now, a new button will get added to the toolbar each time you restart the plugin and select a node. Deselecting a node won’t do anything either, so that’s not ideal.
A quick reload of the project fixes this, but you should probably handle this the correct way. :]
To fix this, you’ll need to implement the
_remove_button function so the button gets properly removed. Open the script again and remove the
pass keyword from the
_remove_button function. Now add the code below in its place:
visibility_button = null
This will remove the button from the toolbar and free its memory. Here’s a more detailed look at the code:
- Check if the button exists. If there’s no button, nothing can be removed so don’t do anything.
- Remove the button from the toolbar using the
- Destroy the button from memory using the
queue_freefunction. Also clear the reference to it by setting it to
null, forgetting to do this will cause a memory leak.
Save the script and try selecting and deselecting some nodes in the scene while in the 2D screen. The button appears and disappears as it should now.
Your first plugin is now complete, well done. You can adjust the code to make it do all sorts of useful things. If you want, you can add more than one control to the toolbar at once and add labels to show more information about the selected node.
While great, this way of writing plugins does come with a huge limitation: it only works with a single node at a time. If you try selecting more than one node at once, the button disappears from the toolbar. For some plugins, this won’t matter, but I bet you already have some plugin ideas whirling around in your head that require editing many nodes at the same time.
If you want to discover another way of writing plugins, read on!
Developing an Advanced Plugin
For your next plugin, you’ll create a menu with buttons that allows you to simulate 2D gravity in the editor. Along the way, you’ll learn how physics work in Godot and how you can let the physics engine only affect selected nodes.
To start, you’ll need to create a new plugin. In the Project Settings menu, select the Plugins tab and click the Create New Plugin button. Fill in the following information:
- Plugin Name: Physics Menu
- Subfolder: physics_menu
- Description: Run physics on selected objects in the editor.
- Author: Your name or username
- Script Name: physics_menu.gd
Here’s what it should look like:
Next, click the Create button to create the new plugin. The physics_menu.gd script will automatically open in the script editor. You won’t be coding yet though; unlike the first plugin you’ve created, you’re going to create a new scene first to hold the menu.
Creating the Menu Scene
By creating a scene, you can easily customize the menu to your liking. While it’s possible to do this via code like you did above, creating UI via the editor is more streamlined and allows for quick tweaks.
First up, create a new scene in the addons/physics_menu folder and name it
menu_ui.tscn. You can do this by right-clicking the folder and selecting Create New ▸ Scene….
Make this new scene have an VBoxContainer as its root node and name this root node Menu. Here’s what this looks like in the dialog:
Once you’ve filled in the scene properties, click the OK button to create the scene. Now make the Menu node take up the full viewport by selecting it and selecting the Full Rect anchor preset in the toolbar.
Doing this ensures that the menu will use all available space in whichever container you add it to.
Now all that’s left is to add the buttons to the menu. Add a new Button node as a child node of Menu and name it ShowSelectionButton. Change its Text property to “Show selection”.
Now repeat the steps above (or duplicate the button) and add these other buttons:
- StartPhysicsButton: “Start physics”
- StopPhysicsButton: “Stop physics”
- TenFramesButton: “Simulate 10 physics frames”
- ResetVelocityButton: “Reset velocity”
Each of these buttons will have a specific function:
- ShowSelectionButton will show the selected nodes in the console.
- StartPhysicsButton will start physics on the selected nodes in the editor.
- StopPhysicsButton will stop physics for the selected nodes.
- TenFramesButton will simulate 10 physics frames, which is useful for a quick test.
- ResetVelocityButton will reset the linear and angular velocity of the selected nodes. This makes it so they don’t immediately start moving or spinning when you start the project.
That’s it for the scene! If you want to be fancy, you can add an icon to each button, maybe a kitten or a puppy? At any rate, you don’t need to attach a script here, as all logic will be handled by the plugin script.