Skip to content
Snippets Groups Projects
configs.rs 2.14 KiB
Newer Older
use crate::system::AppState;
use bevy::asset::{AddAsset, AssetLoader, AssetServer, BoxedFuture, LoadContext, LoadedAsset};
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use bevy::reflect::{TypePath, TypeUuid};
use paste::paste;
use serde::{Deserialize, Serialize};

macro_rules! impl_config_lifecycle {
    ($(($struct: ident, $ext: literal)),*) => {
		paste! {
			#[allow(dead_code)]
			mod _inner {
				use super::*;
				$(
					struct [<$struct Loader>];
					impl AssetLoader for [<$struct Loader>] {
						fn load<'a>(
							&'a self,
							bytes: &'a [u8],
							load_context: &'a mut LoadContext,
						) -> BoxedFuture<'a, anyhow::Result<()>> {
							Box::pin(async move {
								let value: $struct = serde_json::from_slice(bytes)?;
								load_context.set_default_asset(LoadedAsset::new(value));
								Ok(())
							})
						}

						fn extensions(&self) -> &[&str] {
							&[$ext]
						}
					}
					#[derive(Resource)]
					struct [<$struct Wrapper>] {
						handle: Handle<$struct>,
					}

					#[derive(SystemParam)]
					pub struct [<Fetch $struct>]<'w> {
						wrapper: Res<'w, [<$struct Wrapper>]>,
						asset: Res<'w, Assets<$struct>>,
					}

					impl<'w> [<Fetch $struct>]<'w> {
						pub fn get(&self) -> Option<&$struct> {
							self.asset.get(&self.wrapper.handle)
						}
					}

					fn [<init_ $struct:snake>](mut commands: Commands, assets: Res<AssetServer>) {
						let handle = assets.load(format!("config/config.{}", $ext));
						commands.insert_resource([<$struct Wrapper>] { handle });
					}
				)*

				pub struct ConfigsPlugin;
				impl Plugin for ConfigsPlugin {
					fn build(&self, app: &mut App) {$(
						app.add_asset::<$struct>()
							.add_asset_loader([<$struct Loader>])
							.add_systems(OnEnter(AppState::Preload), [<init_ $struct:snake>]);
					)*}
				}
			}

			pub use _inner::ConfigsPlugin;
			pub use _inner::{$([<Fetch $struct>]),*};
		}
	};
}

#[derive(Copy, Clone, TypeUuid, TypePath, Debug, Default, Serialize, Deserialize)]
#[uuid = "f7d88160-28e4-11ee-bcad-b34d9ff949be"]
pub struct PhysicsConfig {
	pub gravity: f32,
	pub jump: f32,
	pub speed: f32,
}

impl_config_lifecycle!((PhysicsConfig, "phys"));