Skip to content

Package to develope a godot plugin and a corresponding standalone app using the same codebase.

License

Notifications You must be signed in to change notification settings

HolonProduction/godot_standalone_plugin

Repository files navigation

📦 Standalone Plugin

Godot: 4.0.beta5

This package makes it possible to develop a godot plugin and a corresponding standalone app using the same codebase.


🌱 Setup

  1. Add your plugin to the res://addons folder or create a new plugin.
  2. Copy res://standalone_plugin/editor.gd into your plugins directory. (And rename it if you want.)
  3. Modify the main script of your plugin to inherit the copied file from step 2.
  4. You are ready to go. 🎉

Step 2 and 3 can also be done automatically by calling Project>Tools>Make Plugin Standalone

If you use any of the helper options inside of the tools menu it is highly recommended to restart the edior afterwards. The build in script editor may not update the changed scripts otherwise. (No way to do it by code :/)


🚀 Features

Not every method of EditorPlugin can be reproduced without Godot internals like the import or export systems. Therefore not all methods of EditorPlugin will have an effect when running standalone. This won't throw an error though, in case your plugin has more functionality in Godot but should still run standalone.

Calling unsuported methods won't throw an error but when it comes to return values there can be problems. You should add null checks for all return values (e.g. get_script_create_dialog will return null on runtime). Same goes for everything returned from EditorInterface

Check if running standalone

If your plugin relies on godot internal systems adapting to standalone may require to disable some features. You can easily test whether you are running in the editor by calling Engine.is_editor_hint. This allows you to enable certain features only when running standalone or as plugin. For example the standalone app may require additional steps to select a file to edit.

Supported methods of EditorPlugin

Method Standalone Editor May Return null
_apply_changes virtual ✔️
_build virtual ✔️
_clear virtual ✔️
_disable_plugin virtual ✔️ ✔️
_edit virtual ✔️
_enable_plugin virtual ✔️ ✔️
_forward_3d_draw_over_viewport virtual ✔️
_forward_3d_force_draw_over_viewport virtual ✔️
_forward_3d_gui_input virtual ✔️
_forward_canvas_draw_over_viewport virtual ✔️
_forward_canvas_force_draw_over_viewport virtual ✔️
_forward_canvas_gui_input virtual ✔️
_get_breakpoints virtual ✔️
_get_plugin_icon virtual ✔️ ✔️
_get_plugin_name virtual ✔️ ✔️
_get_state virtual ✔️
_get_window_layout virtual ✔️ ✔️
_handles virtual ✔️
_has_main_screen virtual ✔️ ✔️
_make_visible virtual ✔️ ✔️
_save_external_data virtual ✔️ only when exiting ✔️
_set_state virtual ✔️
_set_window_layout virtual ✔️ ✔️
add_autoload_singelton 🔶 not at runtime but when registered in editor plugin it is still in the export ✔️
add_control_to_bottom_panel ✔️ ✔️
add_control_to_container 🔶 Only CONTAINER_TOOLBAR. Also adds new containers that are not supported in editor: CONTAINER_LAUNCH_PAD ✔️
add_control_to_dock ✔️ ✔️
add_custom_type ✔️
add_debugger_plugin ✔️
add_export_plugin ✔️
add_import_plugin ✔️
add_inspector_plugin ✔️
add_scene_format_importer_plugin ✔️
add_scene_post_import_plugin ✔️
add_spacial_gizmo_plugin ✔️
add_tool_menu_item 🔶 use the standalone exclusive menu api ✔️
add_tool_submenu_item 🔶 use the standalone exclusive menu api ✔️
add_translation_parser_plugin ✔️
add_undo_redo_inspector_hook_callback ✔️
get_editor_interface 🔶 returns an standalone interface ✔️ No
get_export_as_menu ✔️ Yes
get_script_create_dialog ✔️ Yes
get_undo_redo ✔️ ✔️ No
hide_bottom_panel ✔️ ✔️
make_bottom_panel_item_visible ✔️ ✔️
queue_save_layout ✔️ ✔️
remove_autoload_singelton ✔️
remove_control_from_bottom_panel ✔️ ✔️
remove_control_from_container 🔶 ✔️
remove_control_from_docks ✔️ ✔️
remove_custom_type ✔️
remove_debugger_plugin ✔️
remove_export_plugin ✔️
remove_import_plugin ✔️
remove_inspector_plugin ✔️
remove_scene_format_importer_plugin ✔️
remove_scene_post_import_plugin ✔️
remove_spatial_gizmo_plugin ✔️
remove_tool_menu_item ✔️
remove_translation_parser_plugin ✔️
remove_undo_redo_inspector_hook_callback ✔️
set_force_draw_over_forwarding_enabled ✔️
update_overlays ✔️
add_menu_popup ✔️🚧
remove_menu_popup ✔️🚧

Supported methods of EditorInterface

Method Standalone Editor May Return null
edit_node ✔️
edit_resource ✔️
edit_script ✔️
get_base_control ✔️ ✔️ No
get_command_palette ✔️ Yes
get_current_path 🔶 will always return user:// ✔️ No
get_edited_scene_root ✔️ Yes
get_editor_main_screen ✔️ ✔️ No
get_editor_paths ✔️ the paths are diffrent ✔️ No
get_editor_scale ✔️ will always return 1.0 ✔️ No
get_editor_settings ✔️ Yes
get_file_system_dock ✔️ Yes
get_inspector ✔️ Yes
get_open_scenes 🔶 will always be empty ✔️ No
get_playing_scene 🔶 will always be empty ✔️ No
get_resource_filesystem ✔️ Yes
get_resource_previewer ✔️ Yes
get_script_editor ✔️ Yes
get_selected_path 🔶 will always return user:// ✔️ No
get_selection ✔️ Yes
inspect_object ✔️
is_playing_scene 🔶 will always be false ✔️ No
is_plugin_enabled ✔️ ✔️ No
make_mesh_previews ❌ will return PlaceholderTexture2D ✔️ No
open_scene_from_path ✔️
play_current_scene ✔️
play_custom_scene ✔️
play_main_scene ✔️
reload_scene_from_path ✔️
restart_editor ✔️
save_scene ❌ will always return OK ✔️ No
save_scene_as ✔️
select_file ✔️
set_main_screen_editor ✔️ ✔️
set_plugin_enabled ✔️ ✔️
stop_playing_scene ✔️

🔧 For the curious minded (and for me in one month)

🤷 How on earth does this piece of witchcraft work?

The script you copied before starts with the following line of code.

#@standalone

Before building your project the package will loop over all activated plugins. It will check for each whether the main script inherits a script which starts with this very line. In this way a list of plugins that should run standalone is obtained. This list is then stored in your ProjectSettings (the key is editor_plugins/standalone). When running your app the runtime compontents will read the list from the settings and there you have it.

🙋 But wait. The script does still inherit EditorPlugin or does it?

The script in your plugins directory does. This is the reason why your plugin can still be used in the godot editor. But this package does another usefull thing on build time. With the list of standalone plugins it also has a list of all scripts, that inherit EditorPlugin. Luckily Godot has the powerfull feature to load resource packs on runtime (read more on it here). This resource packs can override files at certain paths.
While building a resource pack is created, that overrides all the scripts inheriting EditorPlugin. They get replaced with a version that hooks the methods into the standalone UI.

🙆 I see, it is that simple!

Of course one still needs an ExportPlugin that ensures that the resource pack and all the plugins are included in the export. But you must have thought of that yourself, haven't you?

🙇 Sure...

About

Package to develope a godot plugin and a corresponding standalone app using the same codebase.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published