Week 63: Pluginification

A combination of 21 different 16x16 pixel-art images that each represent a different children's song.
Ok, fine, this doesn't actually have anything to do with game-dev stuff I did last week.
I recorded a bunch of songs the week before, and I made these as cover images for them.
So, here you go!

tl;dr: Last week I started creating a better user-experience for my frameworks by using Godot's plugin system.

What is Godot's plugin system?

Godot's plugin system lets you mod the editor UI. This makes it easy to do things like add custom panels and controls, or change the behavior and appearance for other controls shown in places like the inspector panel.

Godot also has support for running any of your script logic within the editor environment with their `tool` system. I've been heavily using this for a long time, since it's the only way that I can get things to look right when you're using my frameworks within Godot's scene editor. Already having all of my logic ready for the `tool` system made it easier to start using plugin features.

Why is this better?

It's difficult for new users to understand how to use my frameworks in their current form!

I now have a collection of general-purpose frameworks I've made. Each of these frameworks is highly re-usable across different games, and I think that they would probably be useful for other folks. However, my frameworks currently require a lot of up-front knowledge to use, and they require that you configure a lot of script properties and global dependencies in a particular way.

Godot's plugin system lets me make framework setup much easier for the user. Here are some of the benefits:

  • It lets me automatically configure AutoLoad singletons.
    • Most of my frameworks depends on at least one other of my frameworks.
      • That is, the AutoLoad instances depend on another AutoLoad being present.
      • And also, the order that the AutoLoads are registered matters!
    • Now that I can automatically control how and when these AutoLoads are registered, I can remove a common headache for users trying to set things up.
  • It lets me create a separate main-screen panel and tab within the Godot editor.
    • I can create more-user-friendly GUIs here for editing each of the configurable properties for each of my frameworks.
  • It lets me create custom controls within Godot's inspector panel when using the scene editor.
    • For example, I can use this to add a button for re-calculating all cells within a TileMap when the tileset author has made a change to the tileset.

What happened last week?


  • I created a "main screen" plugin panel, with dynamically populated editor controls to match the configurable properties of the framework's manifest schema.
  • I refactored my framework-registration logic to support frameworks being added in any order, regardless of their inter-dependencies.
  • I refactored my framework-registration logic to save and load manifest properties from JSON files rather than from static GDScript.

Laundry list

  • Move SurfaceTiler files into subdirectories.
  • Create a separate AutoLoad for SurfaceTiler.
  • Create a “main Screen” for the SurfaceTiler plugin.
  • Create a generic framework-manifest-schema pattern, which will make it easy to configure my various frameworks within new Godot editor plugin UIs rather than through the GDScript editor.
  • Add support for updating the SurfaceTiler editor icon to match the current editor theme and window-scale settings.
  • Add generic life-cycle tracking logic for all framework config objects.
  • Update the plugin logic to defer the UI initialization until after the framework config is ready.
  • Add a utility for getting a string representation from a type int.
  • Add support for defining custom resource types for configuring within framework manifests.
  • Dynamically populate manifest-editor controls according to the manifest schema.
  • Update my JSON encoding logic to handle more file IO behavior.
  • Update my JSON encoding logic to handle Resource instances.
  • Update my JSON encoding logic to handle INF and NAN values.
  • Add a utility for clearing all children of a Node.
  • Add support for printing a JSON string with the newlines included (will help with version control).
  • Move manifest-editor row UI into a separate scene.
  • Fix an issue with the FrameworkManifestController Reference instance being deallocated when stored directly on the EditorPlugin instance.
  • Add support for group manifest row UIs.
  • Finish adding support for adding/removing items from manifest arrays through the SurfaceTiler plugin UI.
  • Fix SurfaceTiler plugin zebra-striping when dynamically adding/removing manifest items.
  • Add better JSON float parsing.
  • Add support for saving/loading tileset corner-type mappings with JSON files.
  • Add support for lazy-loading/parsing corner-type mappings.
  • Make the plugin main-screen layout responsive.
  • Start adding support for customizable non-stateful manifest schema entries.
  • Refactor framework-manifest representation to use a more-powerful and more-maintainable custom node-based structure.
  • Update manifest schemas to include default values.
  • Refactor framework registration to be robust to different registration sequencing.
  • Debug some plugin manifest-node logic.
  • Add a utility function for testing whether a value is either int or float.
  • Fix a bug with how manifest values were stored in nodes.
  • Add support for automatically setting-up all frameworks as soon as the last framework is registered.
  • Add support for resetting framework state.
  • Sort registered frameworks according to their inter-dependencies.
  • Learned about and installed a very useful Chrome Extension to show Git history for moved files within the GitHub UI.
  • Create a reusable FrameworkPlugin parent class.
  • Move standard framework-plugin classes from SurfaceTiler to Scaffolder.
  • Create separate plugin boilerplate for each framework.
  • Create a utility for instancing singletons.
  • Consolidate framework metadata into schema classes.
  • Start implementing a pattern for all framework plugins to share the same main-screen.
  • Rename FrameworkManifestSchema to FrameworkSchema.
  • Rename FrameworkGlobal to FrameworkGlobal.
  • Add placeholder plugin editor-icons.
  • Hook-up the new schema-loading pattern with the old framework-initialization pattern.
  • Rename _register_manifest to _parse_manifest.
  • Rename scaffolder_(bootstrap|plugin_main_panel) to framework_(...).

What's next?

  • Finish converting my frameworks into the more-polished plugin format.
  • Pull-out GUI logic from Scaffolder into a separate plugin.
  • Pull-out surface-parsing logic from Surfacer into a separate plugin.

🎉 Cheers!

This is a simple icon representing my sabbatical.