A framework for making true global plugins for the Godot Game Engine.
This is not an addon, but a project for you to keep on your computer. All you need to do is open this project in godot, and a script will be injected into EditorSettings. The project has 3 directories, one for each type of plugin:
editor-only
plugins are global, running in the Editor every time you open a project.addons
will be imported & enabled when projects load, depending on what color you assign their folders.project-manager
plugins will run alongside the project manager.
There's a 4th _internal
folder, where all the code that makes the project work is stored. You can ignore this unless you're curious of how things work under the hood.
In this directory you store subfolders that contain your plugin. Scripts that end with plugin.gd
and extend EditorPlugin
will be loaded, instantiated, and ran everytime the editor loads.
As always, EditorPlugins should have
@tool
at the top of the file.
editor-only
└── my-subfolder
├── my-plugin.gd # ✓ Automatically instantiated
└── my-script.gd # x Must load manually from "my-plugin.gd"
They work mostly the same as normal EditorPlugins, but with a few differences. For starters, they will not be available to projects, only the editor, hence editor-only
.
These plugins are not copied into any project, rather they are loaded directly from the global-project folder. They're not like the plugins you enable in ProjectSettings, so they don't have access to:
EditorPlugin
virtual methodsEditorPlugin
signals
Every other function should still be available though.
They're also handled in a special way when it comes to dependencies. Normally when loading resources, res://
paths can only point to the current project's directory. To load global-project files, they must use absolute paths. The editor makes that very hard to do, so I've come up with a way to automatically convert them.
When the global-project loads or saves, any resource in the editor-only
or project-manager
directory will be copied & processed into the .processed
folder (hidden from the editor).
The processed files have their paths converted to absolute, pointing to other files in the .processed
directory. It works slightly different depending on whether its a script, a normal resource, or an imported resource:
- Normal resources ending in
.tres
or.tscn
, are copied into the.processed
folder, and theirext_resource
paths are converted. - For imported resources, the raw resource will not be touched. However, the
.import
file will be copied into the.processed
folder, and its paths will be converted. - For scripts ending in
.gd
, theirpreload
paths are converted.# This var my_res_file := preload("res://editor-only/my-plugin/my-file.gd") # Becomes something like this var my_abs_file := preload("D:/Godot/global-project//editor-only/my-plugin/my-file.gd")
- If you want to load manually, you can get direct access to the global-project path by preloading the included
paths.gd
script like sovar Paths := preload("res://editor-only/included/paths.gd") # Paths.global is the global-project path var my_file_path := Paths.global + "/my_file.txt" var some_file = FileAccess.open(my_file_path, FileAccess.READ) # Paths.processed is where the processed files are stored var my_resource_path := Paths.processed + "/my_resource.tres" var some_res = load(my_resource_path)
Tip
The entire addon import functionality (next section) is implemented as an editor-only
plugin in /editor-only/included/addon-importer-plugin.gd
. You can view that code as an example.
You'll notice that it uses a code based UI framework, GDX. I made it because for most of the development, PackedScenes, or any resource with external dependencies, could not be loaded. That's not the case anymore, but it's still included for convenience, and its how the included plugins render UI.
Warning
Binary resources, files ending in .res
and .scn
, won't be processed. Since they're not stored as text they can't be easily converted.
Imported resources, like icon.svg
, have an accompanying .import
file. Only the .import
will be converted and saved into the .processed
folder. So when manually loading an asset, if you want to load it as a resource, use Paths.processed
. But if you want the raw asset, use Paths.global
.
Caution
class_name
should not be declared for editor-only
and project-manager
scripts. Since these files won't be in a project's directory, the editor won't load the class_names into the global namespace. Use preloads instead, which have similar intellisense. The only difference is they cannot be used as types directly.
Built-in scripts with dependencies are also not supported, since currently it relies on the file extension to decide how to process the file. Built-in scripts are embedded in .tres
or .tscn
files, so they won't get processed like .gd
scripts. Simple isolated scripts should still work though.
Store your normal / typical addons in this directory, even ones from the AssetLib. There are various options for how these addons should be (automatically) imported, depending on folder colors.
Set the folder color by right click > Set Folder Color...
- This folder works the same as the
editor-only
folder, except the scripts run in the project manager instead of the editor. - The scripts should not extend
EditorPlugin
and should not use any function fromEditorInterface
, since those do not exist in the project manager. But they should still end withplugin.gd
- There is no simple api for accessing parts of the UI. You'll have to access nodes manually, but you shouldn't rely on
NodePaths
, as node names have random generated numbers in them. Use index based paths instead, likeEngine.get_main_loop().get_child(0).get_child(0)
, or recursively search the tree and useString.match()
- I have created and included a
project-manager
plugin that adds aninspect
button to the top right, to help you find the node in the SceneTree structure.
- This pops up a window that lets you view the project manager's scene tree. On the right is the selected node's property list.
- If you click
Pick from UI
, you can click directly in the UI to pick a node. The hovered node will be highlighted in red.
Since editor-only and project-manager plugins load alongside the editor, if one of them is bugged, the editor may crash. To fix this:
- Open the global-project's
project.godot
file directly, since global plugins are disabled for that project - Fix the bugged plugin or remove it altogether
- It helps to open the console version of the editor, so you can view the debug logs
If for some reason the global-project also crashes:
- Find
_internal/loader.gd
. This is the script that loads plugins when it itself is loaded - Temporarily rename or move the file, so that it doesn't get loaded
- If you suspect that the
loader.gd
file had a bug, please report it
If that still doesn't work, there might be a bug in the injected EditorSettings script. This is very unlikely due to how simple it is, but just in case you'll want to remove that script. This requires you to locate the EditorSettings file.
Check here for its location. Open the editor_settings-4.3
(or whichever verion) file in a text editor and erase the script. It'll look something like this, just erase this whole chunk of text:
If you don't know how to open it in a text editor, or are too scared to make changes, just delete the whole editor_settings-4.x
file, and godot will recreate it when it next loads. Again, its very unlikely you'll need to do this.