bevy_ecs_ldtk
bevy_ecs_ldtk copied to clipboard
Implement dynamic autotiling
Hello!
With this PR I'd like to add support for dynamic auto-tiling.
And by that I mean that layers who are auto-tiled depending on another int grid layer, will now have their tiles automatically updated whenever the values of the corresponding IntGridCell are changed.
You can see this in action in the screencap below, which happens to be captured from the new autotile example that I've also added to this repo.
This is for now a draft PR and a request for feedback.
In particular, I would ideally like some maintainer to help me with the following questions.
- Should this functionality always be available, or enabled via a cargo feature?
- Should it be always on for all auto layers? Or perhaps controlled by some marker component (e.g
EnableAutoLayer)? In the case of the latter, should the marker be added to all newly spawned auto layers by default, or should the user opt-in to this functionality? - The system I've added currently starts by looking up which layers are affected for each int grid layer, and this is done by querying up to find the project and get the information from the json metadata. Since this inter-layer dependency will not change since loading the project though, I propose to cache this information as a new field in
LayerMetadata. Do you agree? Or even better in a new component, since this only concerns int grid layers.
The implementation itself is also a work in progress, after we settle on the above I'd like to do some refactoring and maybe also add some tests if it makes sense.
Since the PR went a bit under the radar, I took some liberties with my previous questions to make it ready for the review.
The current design goes like this:
- The dynamic autotiling behavior is enabled with a new component called
EnableDynamicAutotilingwhich is added by default to all layers. - A new component on int grid layers called
IntGridLayerAffectedLayerskeeps the list of the other layerEntityids which have some dependency on it for autotiling. It gets initialized for newly spawned layers by the newinit_int_grid_affected_layerssystem. - A new component on int grid layers called
IntGridLayerCellValueskeeps a copy of the 2D array of current int grid cell values on the layer. This is used both to speed up lookups, and to avoid triggering changes unnecessary. This is updated by the newupdate_int_grid_layer_valuessystem which watches forChanged<IntGridCell>. - The new system
apply_int_grid_autotilingwatches forChanged<IntGridLayerCellValues>and performs the autotiling on all affected layers accordingly.
I guess some further optimization can be achieved by storing the autotiling rules (which is a Vec<AutoLayerRuleGroup) on each autotiled layer. What do you think?
Also some cases are currently not handled, and they error-out here:
https://github.com/Trouv/bevy_ecs_ldtk/blob/a566896d288e6a859776e8bcc0f4fdf1ec72b9ae/src/systems.rs#L368-L374