Skip to content

Commit

Permalink
feat!: add SpawnExclusions to LdtkSettings for skipping layers by…
Browse files Browse the repository at this point in the history
… identifier (#275)

I made this a separate `LdtkExclusions` struct because, even though
there's only one use case for this now, it would be a logical extension
to add other exclusions in the future (like entities, both IID and UID
based), and if so, it's better to group them together instead of
cluttering up the main `LdtkSettings`.

Caveat: Adding a `Vec` (or any other collection) to the `LdtkSettings`
or any sub-structure means we can no longer derive `Copy`. It doesn't
appear to be required by any part of `bevy_ecs_ldtk` itself, and there's
no compelling reason why users should absolutely need it (copying a
`Resource` is pretty rare?), but this is potentially a breaking change
for some users. The only way around this would be to avoid putting this
in `LdtkSettings` altogether and define the `LdtkExclusions` as its own
resource (and modify the various systems accordingly). I feel that's a
YAGNI problem so I went the easy route and just removed `Copy`.

Unit testing seems infeasible at the moment due to the complexity of the
`spawn_level` method and absence of existing test infra for it, but I
manually tested the exact same change on the 0.8 branch in an actual
game and it worked perfectly.

Note also that the use of `Vec` over `HashSet` is intentional. I'd
expect there to be a very small number of items in that list (say 2 or
3). In lists with fewer than 10-15 items, the cost of the hash tends to
exceed the cost of the iteration
([example](https://gist.github.com/daboross/976978d8200caf86e02acb6805961195)).

Fixes #272
  • Loading branch information
focustense authored Dec 6, 2023
1 parent 833af01 commit 282404d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 7 deletions.
19 changes: 14 additions & 5 deletions src/level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,16 @@ pub fn spawn_level(
}
}

for layer_instance in layer_instances.iter().rev() {
for layer_instance in layer_instances
.iter()
.filter(|layer| {
!ldtk_settings
.exclusions
.layer_identifiers
.contains(&layer.identifier)
})
.rev()
{
let layer_offset = Vec2::new(
layer_instance.px_total_offset_x as f32,
-layer_instance.px_total_offset_y as f32,
Expand Down Expand Up @@ -550,10 +559,10 @@ pub fn spawn_level(
.filter(|(_, v)| **v != 0)
{
let grid_coords = int_grid_index_to_grid_coords(
i,
layer_instance.c_wid as u32,
layer_instance.c_hei as u32,
).expect("int_grid_csv indices should be within the bounds of 0..(layer_width * layer_height)");
i,
layer_instance.c_wid as u32,
layer_instance.c_hei as u32,
).expect("int_grid_csv indices should be within the bounds of 0..(layer_width * layer_height)");

if let Some(tile_entity) = storage.get(&grid_coords.into()) {
let mut entity_commands = commands.entity(tile_entity);
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub mod prelude {
plugin::{LdtkPlugin, ProcessLdtkApi},
resources::{
IntGridRendering, LdtkSettings, LevelBackground, LevelEvent, LevelSelection,
LevelSpawnBehavior, SetClearColor,
LevelSpawnBehavior, SetClearColor, SpawnExclusions,
},
};

Expand Down
13 changes: 12 additions & 1 deletion src/resources/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Resources and events used by the plugin.
use bevy::prelude::*;

#[allow(unused_imports)]
use crate::assets::LdtkProject;
#[allow(unused_imports)]
use crate::components::LdtkWorldBundle;

Expand Down Expand Up @@ -67,12 +69,21 @@ pub enum LevelBackground {
Nonexistent,
}

/// Specifies data that should be ignored completely when spawning levels. Excluded items will still
/// be present in the [`LdtkProject`] but will not cause any entities to be spawned in the world.
#[derive(Clone, Eq, PartialEq, Debug, Default)]
pub struct SpawnExclusions {
/// List of layer `Identifier` names (not UIDs) to skip spawning as tilemaps.
pub layer_identifiers: Vec<String>,
}

/// Settings resource for the plugin.
/// Check out the documentation for each field type to learn more.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Resource)]
#[derive(Clone, Eq, PartialEq, Debug, Default, Resource)]
pub struct LdtkSettings {
pub level_spawn_behavior: LevelSpawnBehavior,
pub set_clear_color: SetClearColor,
pub int_grid_rendering: IntGridRendering,
pub level_background: LevelBackground,
pub exclusions: SpawnExclusions,
}

0 comments on commit 282404d

Please sign in to comment.