Week 64: Plug-in all the things

An animated GIF showing my new plugin UI within Godot.
Reusable plugin UI for all my frameworks!


tl;dr: Last week I made a lot plugin UI features, which make my frameworks much easier to use, and I made a powerful new color-configuration system.


What happened last week?

Highlights

  • I created a main-screen plugin UI.
    • My frameworks each have many nested configurable properties.
    • This new UI exposes these properties in a form that's easy to understand and edit.
    • This also includes features for overriding these properties depending on various active "modes".
    • I also created a custom accordion-panel system for my plugin UIs.
  • I created a new system for configuring colors.
    • This provides a more powerful way of representing colors.
    • With PaletteColorConfig, you can reference a dynamic Color value according to its corresponding palette key. Then, the actual color can be changed, and a static Color representation will only be used when needed.
    • With HsvRangeColorConfig, you can define a range of color parameters, and then sample random colors within these parameters.
    • With any ColorConfig subclass, you can define overrides and deltas for hue, saturation, value, and alpha, and these overrides will apply on top of whichever color would otherwise have been returned from the subclass.
  • Create custom controls for editing my new color values within Godot's inspector panel.
A screenshot of the Godot editor's scene editor and inspector panel with my new color widget.
I created polished controls for editing values in my new color system.

Laundry list

  • Move some Surfacer configuration from the old manifest pattern to the new one.
  • Add some doc comments to FrameworkGlobal functions.
  • Update Surfacer amend_manifest to amend the correct manifest instance.
  • Move some Scaffolder manifest configuration from the old pattern to the new.
  • Start adding support for toggling various manifest modes within the main-screen plugin.
  • Defer instantiation of the schema, since Godot's script dependency system can't handle some types of circular deps at certain bootstrap times, and scripts are marked as `can_instance=false` then.
  • Fix JSON INF/NAN encoding to work with Vector2, Vector3, and Rect2.
  • Create custom controls for editing multi-number types like Vector2, Vector3, and Rect2.
  • Fix some issues with how I was checking for explicit-vs-implicit manifest types within arrays.
  • Continue moving configurations from the old manifest system to the new one.
  • Port the default input-map to the new manifest schema.
  • Fix some issues from the recent manifest port.
  • Fix an issue with how default array values were being set up when parsing schemas.
  • Updated Godot to 3.5 beta.
    • This version doesn’t open the console window by default.
    • Instead, it includes a separate .cmd file that can be run to open a separate console window.
    • Windows makes it difficult to create a Taskbar shortcut for this .cmd file, but I eventually found a hacky way to do this:
      • https://www.businessinsider.com/pin-to-windows-taskbar
  • Rename Time to ScaffolderTime.
    • This was needed because the latest version of Godot includes a built-in Time class, which my class was shadowing.
  • Add a missing parameter to an extended TileMap function, which was added in the latest version of Godot.
  • Replace plugin-manifest-row TextEdit with LineEdit.
  • Fix MultiNumberEditor styling.
  • Fix input-map structure to work with new manifest schema.
  • Add accordions for framework-manifest panel roots.
  • Move framework icon path calculation to schema.
  • Start adding a bare-bones accordion widget for manifest panels.
  • Spend a few hours testing various patterns for arranging plugin vs autoload vs schema instantiation and interdependencies.
    • If a script depends on an AutoLoad type, then that script—and any script that transitively depends on it—cannot be instantiated until the AutoLoad is registered.
    • This means that the plugin script cannot transitively reference the AutoLoad type.
    • Also, this means that the plugin script cannot instantiate the schema until after registering the AutoLoad.
  • Move plugin files into a separate subdirectory.
  • Create a new autoload for plugin-specific stuff.
  • Decouple FrameworkPlugin from any transitive dependencies on FrameworkGlobal types.
  • Create a separate PluginMetadata class for accessing constant framework state.
    • This fixes dependency issues, while still allowing FrameworkSchema instances to reference non-const state and any dependencies.
  • Add UI scaling for plugins.
  • Add new progressive-disclosure caret icons.
  • Start implementing accordion header presses.
  • Add support for storing arbitrary values on Singletons.
  • Finish implementing plugin-manifest accordion-panel functionality.
  • Start adding support for shading manifest row-group entries with zebra-striping.
  • Fix manifest row-group accordion-header buttons right alignment.
  • Fix manifest row heights.
  • Fix zebra-striping on group-header rows.
  • Add new framework plugin icons.
  • Update plugin metadata to support icons in different directories.
  • Update the icon and label used in the plugin main-screen tab.
  • Fix an issue with manifest row-group carets sometimes not rotating with the open state.
    • This was happening because Godot Containers control rect_rotation of their children, which can override any changes you try to make.
  • Add support in the manifest for specifying an array's explicit child type without including a default child in the array.
  • Auto-open manifest rows when adding and deleting array items.
  • Fix a bug when trying to reference a default value from beyond the bounds of a schema array.
  • Add support for saving/loading which plugin rows are expanded.
  • Update Singletons to use set_meta/get_meta on an external singleton to prevent potential issues with Reference unloading.
  • Fix an issue with Dictionary keys being converted from ints into Strings when saving to JSON.
  • Move mode declarations to metadata from schema.
  • Fix mode save/load logic.
  • Rename ScaffoldBootstrap to FrameworkBootstrap.
  • Fix manifest-mode dropdown widths.
  • Start refactoring manifest-override patterns.
  • Update manifest overrides to use modes.
  • Add a new threading mode.
  • Move mode-loading into FrameworkBootstrap.
  • Add support for dynamically registering new manifest modes.
  • Update flags on `metadata` for the current modes.
  • Include both pixelated and anti-aliased versions of manifest state in the manifest UI, then choose one based on the current modes.
  • Add a utility function for recursively merging the entries of two dictionaries.
  • Add a system for overriding one schema's properties from another schema.
  • Add support for highlighting manifest rows that are overridden by FrameworkGlobal logic.
  • Rename SurfacerDefaultAppManifest to SurfacerFrameworkGlobal.
  • Add a standard system for overriding manifest properties.
  • Add support for highlighting manifest rows that are overridden.
  • Add support for annotating manifest rows with a colored marker that indicates which manifest-mode overrides the property.
  • Remove overly strict manifest-override warnings.
  • Fix _get_common_overrides_for_annotations_mode.
    • The problem:
      • Sc.ann_params isn't defined until after framework initialization.
      • Sc.manifest.annotation_parameters_manifest doesn't actually contain any state from the schema.
        • It was only ever populated in _get_common_overrides_for_annotations_mode.
      • _get_common_overrides_for_annotations_mode needs to reference one of these two objects in order to get the state to base its overrides off of.
    • I could have created two separate override lifecycle events, one before framework-initialization that acts on the manifest object, and one after that acts on the framework-global object.
    • But, I instead just hard-coded the override values in _get_common_overrides_for_annotations_mode, which violates the DRY principle, but keeps the overall system much simpler.
  • Start adding a new color-configuration system.
    • This provides a more powerful way of representing colors.
    • With PaletteColorConfig, you can reference a dynamic Color value according to its corresponding palette key. Then, the actual color can be changed, and a static Color representation will only be used when needed.
    • With HsvRangeColorConfig, you can define a range of color parameters, and then sample random colors within these parameters.
    • With any ColorConfig subclass, you can define overrides for hue, saturation, value, and alpha, and these overrides will apply on top of whichever color would otherwise have been returned from the subclass.
  • Add ColorConfig doc comments.
  • Add support for color hsv deltas.
  • Add the ColorPalette class.
  • Replace old usages of ScaffolderColor.opacify with the new ColorFactory.opacify.
  • Add default values to ColorPalette.
  • Add support for registering either Color or ColorConfig values with ColorPalette.
  • Remove the old ScaffolderColors class.
  • Fix an issue with plugin _set_up being called more than once.
  • Start adding ColorConfigEditorProperty.
    • This is a widget that will be used for editing ColorConfig instances within the editor UI.
  • Add a custom TYPE_FONT and TYPE_COLOR_CONFIG.
  • Add support for encoding/decoding ColorConfigs with JSON.
  • Add some more ColorConfig aggregate Color getters and setters.
    • These make encoding/decoding with JSON easier.
  • Split-out ColorConfigEdit from ColorConfigEditorProperty.
  • Fix ColorConfigEdit styling.
  • Fix another bug with json decoding yielding floats when ints are expected.
  • Update the ColorConfigEdit to use a dropdown for selecting the palette key from those that are registered.
  • Add some to_string methods for ColorConfig subclasses.
  • Debug ColorConfigEdit.

What's next?

  • Another game jam next weekend: Ludum Dare 50!
  • I'll spend this week stabilizing and publishing my recent framework features.


🎉 Cheers!


This is a simple icon representing my sabbatical.

Comments