Skip to content

Commit

Permalink
feat: add level locale types and begin splitting internal_levels and …
Browse files Browse the repository at this point in the history
…external_levels features (#237)

As part of the rework of the asset types, it is useful to be able to
define types that are generic over the "level locale" of the project
they represent. The terminology level locale refers to whether or not
the project uses internal levels (level data embedded in the main
project asset) or external levels (level data stored in separate
individual-level files). Such a generic type is able to define different
implementations of the same trait for the two locales, or the same
implementation of the same trait, or even completely different methods
between the two locales.

To facilitate this, this PR adds a `LevelLocale` trait, which is mostly
a marker trait implemented by the new `InternalLevels` and
`ExternalLevels` unit structs. It does provide an associated type to the
sort of level metadata that is created for the two locales, but other
than that it will mostly be used as a trait bound for generic types. The
fact that the trait is private means that users will not be able to
create new locales that don't fit into the canonical asset type design
defined here.

This also introduces the `internal_levels` and `external_levels`
features. These two features are not mutually exclusive, but at least
one of them does need to be enabled. The eventual asset type design will
hide most things behind these features so users can slightly optimize
their compilation if they want to.

(Ignore broken doc-links here, they will no longer be broken in future
PRs)
  • Loading branch information
Trouv authored Oct 14, 2023
1 parent 1ee3be3 commit 8129e55
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 14 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ jobs:
uses: dtolnay/rust-toolchain@stable
- name: Install Dependencies
run: sudo apt-get update; sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
- name: Run cargo check (no features, exclude examples)
run: cargo check --no-default-features
- name: Run cargo check (minimal features, internal levels, exclude examples)
run: cargo check --no-default-features --features internal_levels
- name: Run cargo check (minimal features, external levels, exclude examples)
run: cargo check --no-default-features --features external_levels
- name: Run cargo check (default features)
run: cargo check --all-targets
- name: Run cargo check (all features)
Expand Down
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ rand = "0.8"
bevy-inspector-egui = "0.19.0"

[features]
default = ["derive", "render"]
default = ["derive", "render", "internal_levels"]
derive = ["bevy_ecs_ldtk_macros"]
atlas = ["bevy_ecs_tilemap/atlas"]
render = ["bevy_ecs_tilemap/render"]
internal_levels = []
external_levels = []

[[example]]
name = "platformer"
Expand Down
4 changes: 3 additions & 1 deletion src/assets/level_indices.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use bevy::reflect::Reflect;

/// Indices pointing to the location of a level in an [`LdtkProject`] or [`LdtkJson`].
///
/// This type supports multi-world projects by storing an optional `world` index.
Expand All @@ -6,7 +8,7 @@
///
/// [`LdtkProject`]: crate::assets::LdtkProject
/// [`LdtkJson`]: crate::ldtk::LdtkJson
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Reflect)]
pub struct LevelIndices {
/// The index of the world the level belongs to, if the project is multi-world.
pub world: Option<usize>,
Expand Down
48 changes: 48 additions & 0 deletions src/assets/level_locale.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use bevy::reflect::Reflect;

#[cfg(feature = "internal_levels")]
use crate::assets::LevelMetadata;

#[cfg(feature = "external_levels")]
use crate::assets::ExternalLevelMetadata;

/// Trait for marker types describing the location of levels.
///
/// Used as a trait bound to parameterize [`LdtkJsonWithMetadata`].
/// Also provides an associated type defining the level metadata type for the locale.
///
/// Only implemented by [`InternalLevels`] and [`ExternalLevels`].
///
/// [`LdtkJsonWithMetadata`]: crate::assets::LdtkJsonWithMetadata
pub trait LevelLocale {
/// Level metadata type used for this locale.
type Metadata;
}

#[cfg(feature = "internal_levels")]
/// Marker type for indicating an internal-levels LDtk project.
///
/// Used to parameterize [`LdtkJsonWithMetadata`].
///
/// [`LdtkJsonWithMetadata`]: crate::assets::LdtkJsonWithMetadata
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Reflect)]
pub struct InternalLevels;

#[cfg(feature = "internal_levels")]
impl LevelLocale for InternalLevels {
type Metadata = LevelMetadata;
}

#[cfg(feature = "external_levels")]
/// Marker type for indicating an external-levels LDtk projects.
///
/// Used to parameterize [`LdtkJsonWithMetadata`].
///
/// [`LdtkJsonWithMetadata`]: crate::assets::LdtkJsonWithMetadata
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Reflect)]
pub struct ExternalLevels;

#[cfg(feature = "external_levels")]
impl LevelLocale for ExternalLevels {
type Metadata = ExternalLevelMetadata;
}
15 changes: 7 additions & 8 deletions src/assets/level_metadata.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use crate::assets::LevelIndices;
use bevy::{
prelude::*,
reflect::{TypePath, TypeUuid},
};
use bevy::{prelude::*, reflect::Reflect};
use derive_getters::Getters;

#[cfg(feature = "external_levels")]
use crate::assets::LdtkLevel;

/// Metadata produced for every level during [`LdtkProject`] loading.
///
/// [`LdtkProject`]: crate::assets::LdtkProject
#[derive(Clone, Debug, Default, Eq, PartialEq, TypeUuid, TypePath, Getters)]
#[uuid = "bba47e30-5036-4994-acde-d62a440b16b8"]
#[derive(Clone, Debug, Default, Eq, PartialEq, Getters, Reflect)]
pub struct LevelMetadata {
/// Image handle for the background image of this level, if it has one.
bg_image: Option<Handle<Image>>,
Expand All @@ -26,18 +23,19 @@ impl LevelMetadata {
}
}

#[cfg(feature = "external_levels")]
/// Metadata produced for every level during [`LdtkProject`] loading for external-levels projects.
///
/// [`LdtkProject`]: crate::assets::LdtkProject
#[derive(Clone, Debug, Default, Eq, PartialEq, TypeUuid, TypePath, Getters)]
#[uuid = "d3190ad4-6fa4-4f47-b15b-87f92f191738"]
#[derive(Clone, Debug, Default, Eq, PartialEq, Getters, Reflect)]
pub struct ExternalLevelMetadata {
/// Common metadata for this level.
metadata: LevelMetadata,
/// Handle to this external level's asset data.
external_handle: Handle<LdtkLevel>,
}

#[cfg(feature = "external_levels")]
impl ExternalLevelMetadata {
/// Construct a new [`ExternalLevelMetadata`].
pub fn new(metadata: LevelMetadata, external_handle: Handle<LdtkLevel>) -> Self {
Expand Down Expand Up @@ -73,6 +71,7 @@ mod tests {
assert_eq!(*level_metadata.indices(), LevelIndices::in_world(2, 3));
}

#[cfg(feature = "external_levels")]
#[test]
fn external_level_metadata_construction() {
let level_metadata = LevelMetadata::new(None, LevelIndices::in_root(1));
Expand Down
14 changes: 13 additions & 1 deletion src/assets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@ mod ldtk_asset_plugin;
pub use ldtk_asset_plugin::LdtkAssetPlugin;

mod level_metadata;
pub use level_metadata::{ExternalLevelMetadata, LevelMetadata};

pub use level_metadata::LevelMetadata;

#[cfg(feature = "external_levels")]
pub use level_metadata::ExternalLevelMetadata;

mod level_locale;

#[cfg(feature = "internal_levels")]
pub use level_locale::InternalLevels;

#[cfg(feature = "external_levels")]
pub use level_locale::ExternalLevels;

mod level_metadata_accessor;
pub use level_metadata_accessor::LevelMetadataAccessor;
Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,18 @@
//! ### Feature flags
//!
//! This crate uses the following set of [feature flags]:
//! - `internal_levels`: Enable support for projects that store levels internally.
//! I.e., projects that store level data within the main project file.
//! - `external_levels`: Enable support for projects that store levels externally.
//! I.e., projects that store data for each level in files separate from the main project file.
//! - `derive`: Enables the derive macros for [LdtkEntity] and [LdtkIntCell].
//! - `render`: Enables rendering via [bevy_ecs_tilemap]'s `render` feature. Disable it if you want
//! to run in headless mode.
//! - `atlas`: Enables the `atlas` feature of [bevy_ecs_tilemap]. This is required for WASM support
//! and also for tile spacing to work on Tile and AutoTile layers.
//!
//! The `derive` and `render` features are enabled by default.
//! The `derive`, `render`, and `internal_levels` features are enabled by default.
//! Furthermore, one or both of `internal_levels` and `external_levels` must be enabled.
//!
//! [App]: bevy::prelude::App
//! [Commands]: bevy::prelude::Commands
Expand Down

0 comments on commit 8129e55

Please sign in to comment.