Week 30: Scene-based player configuration, and keeping state of of scene files

A screenshot of the Godot scene-editor with the Squirrel Away squirrel-player scene open. It shows a lot of grouped editable properties in the inspector-panel on the right side.
I made Surfacer player configuration editable within Godot's scene editor tools!

A screenshot of the Godot script-editor with the Squirrel Away squirrel-params script open. It shows a lot of editable variables.
This is how I used to edit Surfacer player configuration.
It involved a lot of error-prone typing,
and it required a lot of up-front knowledge about what all of the options are.

tl;dr: I updated Surfacer player movement and animation configuration to be scene-based instead of script-based, I added fixes to prevent certain data from leaking into scene files, and I updated Squirrel Away for all the recent framework changes.

What happened last week?


  • I refactored player movement and animation configuration to be scene-based instead of script-based.
  • I made some changes in order to prevent stuff from being saved in scene (.tscn) files.
  • I updated Squirrel Away to work with all of my recent Scaffolder and Surfacer framework changes.
  • I thought about how to best keep Squirrel Away in-sync with the latest framework changes.
  • And I made lots of other configuration improvements in Surfacer.

Laundry list

  • Refactor various Player configuration to be scene-based instead of script-based:
    • Refactor MovementParams to use scene-based configuration:
      • Refactor many MovementParams properties to be multipliers based on default values configured globally in Su.
        • This multiplier-based configuration is easier to set up quickly!
      • Refactor per-player movement-parameter configurations to fit the new scene-based system.
      • Update MovementParameter defaults, and add movement-parameter validation to Su.
      • Remove obsolete movement_params configuration from the old script-based system.
      • Add support for recording player_name and movement_params state in Player-implementation scene files, and also add support for parsing this information when configuring Surfacer.
      • Add support for saving collider-shape information on the MovementParams node within a Player-implementation scene file.
      • Remove obsolete PlayerParams and PlayerParamUtils classes; they are now consolidated into MovementParams and Su.
      • Create a utility function for handling some of the boilerplate for accessing property state from a node in a PackedScene file.
      • Experiment with how to record a property in the .tscn file for a certain node, while having the property be assigned by the parent node.
      • Update Player and MovementParams to correctly record shape state on the MovementParams node in the .tscn file, while populating this according to a sibling CollisionShape2D node.
      • Add manual remote parsing and instancing of MovementParams from SurfacerBootstrap.
      • Debounce configuration updates in MovementParams.
      • Finish reincorporating movement-params derivation and validation.
      • Fix various issues with sequencing of in-editor scene property-updating and property-saving.
      • Fix remaining bugs left-over from Player scene-editor-based configuration refactor.
      • Create a utility for configuring property-groups in the inspector panel.
      • Add inspector-panel property-groups for MovementParams properties.
    • Refactor PlayerAnimator to use scene-based configuration:
      • Replace PlayerAnimationType enum with Strings.
      • Refactor PlayerAnimator animation configurations to be scene-editor-based rather than script-code-based.
        • I now export an editable array of simple Dictionaries.
        • Each of these Dictionaries represents configuration information for an AnimationPlayer animation.
        • These Dictionaries are auto-populated according to the animations defined on the AnimationPlayer.
        • These Dictionaries contain additional info that isn’t available within the native AnimationPlayer configuration, such as a default playback rate for each animation, and the name of a Sprite to automatically show when playing the animation.
      • Encode player animator playback speeds in scene files.
  • Keeping stuff out of scene (.tscn) files:
    • I ran into a problem with Scaffolder referencing file-paths that belong to the client app, rather than inside itself.
    • The main reason this is a problem, is that the editor reports errors and won't run the game when I try to open Scaffolder in a different project, and Godot can't find the files!
    • At run-time, this shouldn't actually be a problem though, since all of these file-paths are dynamically assigned according to the top-level app-manifest.
    • I also discovered that a lot of dynamically-assigned image data is being unnecessarily recorded in scene files, which has a big impact on file size.
    • So I looked for ways to prevent these paths from being saved within Godot's .tscn files.
    • After a lot of experimentation, I learned that Godot doesn't support removing the storage flag from the _get_property_list() amendment.
      • This has the unfortunate consequence that if I have a `tool` script that renders something that is assigned in an `export` property, I cannot prevent that value from being saved in the .tscn file.
      • This is a problem for me, since I dynamically assign app-local images into framework scenes, which shouldn’t be saved with the app-local information.
      • I can work around this by refactoring my widgets to accept strings, instead of images directly, and then lookup the image in the manifest.
    • Update stylebox subclasses to not assign texture values when running in the editor.
    • Move some images out of ScaffolderMetadata and into ScaffolderImages.
      • Making sure all images are registered in the same place is an important first step to refactoring my widgets to look-up images by a key.
    • Update all texture-based widgets to support referencing textures indirectly via a string-key, which lets us prevent texture-path references from leaking into .tscn files.
    • Update default manifest to not reference app-local file-paths.
  • Thought about how to best keep Squirrel Away in-sync with the latest framework changes.
    • When I start working on a new game, I make a lot of changes to the Scaffolder and Surfacer frameworks, as needed.
    • However, any previous games then don’t work with the latest versions!
    • For the most part, I think the best approach for this problem is to get over it. When I move-on from a game, I shouldn’t look back.
    • However, I do want to keep Squirrel Away always up-to-date, as a good example app for how to use the frameworks.
    • This shouldn’t be too much work, since it should always be a pretty simple app that doesn’t do much beyond what the frameworks provide, by design.
    • However, it would still be nice if I didn’t have to remember to keep it in sync...
    • So I keep revisiting this problem, and trying to think whether there is any good way to keep separate game codebases up-to-date with the latest Scaffolder and Surfacer framework changes.
    • My latest thought this week, was maybe to always include Squirrel Away as an additional sub-module under the `addons/` directory, like `addons/scaffolder/` and addons/surfacer/`.
      • But I gave up on this after realizing how difficult it would be to juggle whether or not paths are prefixed with `addons/squirrel-away/`, depending on the context.
    • Oh well...
  • Miscellaneous:
    • Create a new SurfacerMovementManifest class, and move some top-level config into there from Su.
    • Create a new SurfacerAnnotationsManifest class, and move some top-level config into there from Su.
    • Declare more scripts as `tool`s, so they run indirectly in-editor correctly.
    • Did some research into whether there is any way to automatically assert that children classes include the `tool` keyword as needed.
    • Add a check to ensure that sub-classes are tools.
    • Create new editor icons: PlayerAnimator, Main, CollidableTileMap, and ScaffolderLevel.
    • Consolidate CollidableTileMap and SurfacesTileMap.
    • Fix dashed-capsule drawing calculations.
    • Add some more documentation for getting set up.
    • Move images into more subdirectories.
    • Rename ScaffolderIcons to ScaffolderImages.
      • Update stylebox subclasses to not re-assign any size state when running in the editor.
        • This is also important to prevent extra image state from being saved in .tscn files.
    • Added support to DefaultAppManifest for conveniently overriding only a subset of default properties in a manifest dictionary.
    • Create a default placeholder loading-image scene for easy default app configuration.
    • Rename "_active" images to "_pressed", which is more “Godotey”.
    • Create a default tile-set, so default example logic doesn’t need to reference app-local filepaths.
    • Start updating Squirrel Away for recent framework changes.
    • Update AnimationPlayer to work with other types of animation implementations.
    • Adapt squirrel-away legacy movement, animator, and level params for new systems.
    • Add support for offsetting loading images.

What's next?

  • Add some convenience tools for implementing certain types of high-level navigation behavior.
  • Implement a handful of remaining Surfacer configuration features.
  • Fix a handful of Surfacer bugs.

🎉 Cheers!

This is a simple icon representing my sabbatical.