From 296d79afeb0c95a8c30900e425331949a63aeb82 Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Thu, 23 Nov 2023 21:25:58 -0800 Subject: [PATCH] Half way implementing fog tweakfile changes Parsing the fog parameter in toml is a PITA but a good lesson for future tweaks I guess... --- ...martian.audio.tweak => martian.tweak.toml} | 8 +- src/audio.rs | 79 +++++-------------- src/display3d.rs | 51 +++++++++++- src/loading.rs | 12 +-- src/main.rs | 4 +- src/tweak.rs | 60 ++++++++++++++ 6 files changed, 143 insertions(+), 71 deletions(-) rename assets/{audio/martian.audio.tweak => martian.tweak.toml} (74%) create mode 100644 src/tweak.rs diff --git a/assets/audio/martian.audio.tweak b/assets/martian.tweak.toml similarity index 74% rename from assets/audio/martian.audio.tweak rename to assets/martian.tweak.toml index d91f944..454f0ec 100644 --- a/assets/audio/martian.audio.tweak +++ b/assets/martian.tweak.toml @@ -1,15 +1,15 @@ -[display2d] +[audio.display2d] pick_up = "/SFX/2D/2DPickUpPiece" put_down = "/SFX/2D/2DPutDownPiece" -[display3d] +[audio.display3d] pick_up = "/SFX/3D/3DPickUpPiece" put_down = "/SFX/3D/3DPutDownPiece" idle = "/SFX/3D/3DPickup-Idle-PutdownWhirr" invalid = "/sfx/3D/3DInvalidMove" -[music] +[audio.music] main = "/Music/Main Track2" -[menu] +[audio.menu] select = "/SFX/MenuSelect" \ No newline at end of file diff --git a/src/audio.rs b/src/audio.rs index 65102c1..c7cb36d 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -2,12 +2,7 @@ /// TODO: Custom Asset: FmodEventMapper /// use crate::prelude::*; -use bevy::{ - asset::{AssetLoader, LoadContext, LoadedAsset}, - prelude::*, - reflect::{TypePath, TypeUuid}, - utils::BoxedFuture, -}; +use bevy::prelude::*; use bevy_fmod::prelude::AudioSource; use bevy_fmod::prelude::*; use serde::Deserialize; @@ -18,8 +13,6 @@ impl Plugin for AudioPlugin { fn build(&self, app: &mut App) { app.add_event::(); - app.add_systems(OnEnter(GameState::Loading), load_tweakfile); - app.add_plugins(FmodPlugin { audio_banks_paths: &[ "./assets/audio/Martian Chess Audio/Build/Desktop/Master.bank", @@ -28,8 +21,6 @@ impl Plugin for AudioPlugin { "./assets/audio/Martian Chess Audio/Build/Desktop/SFX.bank", ], }); - app.add_asset::() - .init_asset_loader::(); app.add_systems(OnEnter(GameState::Menu), play_background); app.add_systems( @@ -55,14 +46,6 @@ pub enum AudioEvent { Invalid, } -#[derive(Resource)] -struct AudioTweakfile(Handle); - -fn load_tweakfile(server: Res, mut commands: Commands) { - let handle: Handle = server.load("audio/martian.audio.tweak"); - commands.insert_resource(AudioTweakfile(handle)); -} - fn play_background(mut events: EventWriter) { events.send(AudioEvent::MainMusic); } @@ -77,33 +60,33 @@ fn audio_trigger( studio: Res, mut commands: Commands, server: Res, - audio_settings: Res>, + tweakfiles: Res>, display_state: Res>, ) { - let tweak = audio_settings - .get(&server.load("audio/martian.audio.tweak")) - .expect("Load audio tweakfile"); - debug!("Audio tweaks: {:?}", tweak); + let tweak = tweakfiles + .get(&server.load("martian.tweak.toml")) + .expect("Load tweakfile"); + debug!("Audio tweaks: {:?}", tweak.audio); let state = display_state.get(); events.iter().for_each(|event| { let aud = match event { - AudioEvent::MainMusic | AudioEvent::StopMainMusic => tweak.music.main.clone(), - AudioEvent::MenuSelect => tweak.menu.select.clone(), + AudioEvent::MainMusic | AudioEvent::StopMainMusic => tweak.audio.music.main.clone(), + AudioEvent::MenuSelect => tweak.audio.menu.select.clone(), AudioEvent::PickUp => match state { - DisplayState::Display2d => tweak.display2d.pick_up.clone(), - DisplayState::Display3d => tweak.display3d.pick_up.clone(), + DisplayState::Display2d => tweak.audio.display2d.pick_up.clone(), + DisplayState::Display3d => tweak.audio.display3d.pick_up.clone(), }, AudioEvent::PutDown => match state { - DisplayState::Display2d => tweak.display2d.put_down.clone(), - DisplayState::Display3d => tweak.display3d.put_down.clone(), + DisplayState::Display2d => tweak.audio.display2d.put_down.clone(), + DisplayState::Display3d => tweak.audio.display3d.put_down.clone(), }, AudioEvent::Idle | AudioEvent::StopIdle => match state { - DisplayState::Display2d => tweak.display2d.idle.clone(), - DisplayState::Display3d => tweak.display3d.idle.clone(), + DisplayState::Display2d => tweak.audio.display2d.idle.clone(), + DisplayState::Display3d => tweak.audio.display3d.idle.clone(), }, AudioEvent::Invalid => match state { - DisplayState::Display2d => tweak.display2d.invalid.clone(), - DisplayState::Display3d => tweak.display3d.invalid.clone(), + DisplayState::Display2d => tweak.audio.display2d.invalid.clone(), + DisplayState::Display3d => tweak.audio.display3d.invalid.clone(), }, }; // There is an event for this @@ -146,9 +129,9 @@ fn audio_trigger( }); } -#[derive(Debug, Deserialize, TypeUuid, TypePath)] -#[uuid = "5c7a67ee-56a9-4fe9-9e91-1a709fbc3cf0"] -pub(crate) struct AudioSettings { +/// Tweaks made to audio in the Tweakfile +#[derive(Debug, Deserialize, Default)] +pub(crate) struct AudioTweaks { #[serde(default)] display2d: PlaySettings, #[serde(default)] @@ -181,26 +164,4 @@ struct PlaySettings { idle: String, #[serde(default)] invalid: String, -} - -#[derive(Default)] -pub struct AudioSettingsLoader; - -impl AssetLoader for AudioSettingsLoader { - fn load<'a>( - &'a self, - bytes: &'a [u8], - load_context: &'a mut LoadContext, - ) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> { - Box::pin(async move { - let s = std::str::from_utf8(bytes)?; - let custom_asset = toml::from_str::(s)?; - load_context.set_default_asset(LoadedAsset::new(custom_asset)); - Ok(()) - }) - } - - fn extensions(&self) -> &[&str] { - &["audio.tweak"] - } -} +} \ No newline at end of file diff --git a/src/display3d.rs b/src/display3d.rs index 41bb7f0..0427295 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -1,5 +1,5 @@ use crate::{ - game::{Board, BoardIndex, Piece, Side, BoardComponent}, + game::{Board, BoardIndex, Piece, Side}, prelude::*, }; use bevy::{ @@ -11,6 +11,7 @@ use bevy::{ }, window::PrimaryWindow, }; +use serde::{Deserialize, Deserializer}; pub(crate) struct Display3dPlugin; @@ -82,6 +83,54 @@ impl Plugin for Display3dPlugin { } } +#[derive(Deserialize, Default)] +struct Display3dTweaks { + #[serde(default)] + fog: FogTweaks, +} + +#[derive(Deserialize)] +struct FogTweaks { + #[serde(default)] + color: Color, + #[serde(default)] + light_color: Color, + #[serde(default)] + exponent: f32, + #[serde(default = "default_fog_falloff", deserialize_with = "deserialize_fog_falloff")] + falloff: FogFalloff, +} + +fn default_fog_falloff() -> FogFalloff { + FogFalloff::Exponential { + density: 1.0, + } +} + +fn deserialize_fog_falloff<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + if let Ok(s) = String::deserailize(deserializer) { + // Linear [start f32] [end f32] + if s.starts_with("Linear") { + todo!("Parse linear parameters"); + Ok(FogFalloff::Linear { ..default() }) + // Exponential [density f32] + } else if s.starts_with("Exponential") { + todo!("Parse exponential parameters"); + Ok(FogFalloff::Exponential { ..default() }) + // ExponentialSquared [density f32] + } else if s.starts_with("ExponentialSquared") { + todo!("Parse exponentialsquared parameters"); + Ok(FogFalloff::ExponentialSquared { ..default() }) + // Atmospheric (extinction [r: f32] [g: f32] [b: f32]) (inscattering [r: f32] [g: f32] [b: f32]) + } else if s.startswith("Atmospheric") { + todo!("Parse atmospheric parameters"); + Ok(FogFalloff::Atmospheric { ..default() }) + } else { + Err(D::Error) + } + } +} + #[derive(Debug, Component)] pub(crate) struct Display3d; diff --git a/src/loading.rs b/src/loading.rs index 10d9eb4..13cb1e6 100644 --- a/src/loading.rs +++ b/src/loading.rs @@ -54,7 +54,7 @@ fn loading( server: Res, sprites: Res>, gltfs: Res>, - tweakfile: Res>, + tweakfile: Res>, mut next_state: ResMut>, ) { let s_ids = sprites @@ -67,16 +67,16 @@ fn loading( .filter(|&id| matches!(id, HandleId::AssetPathId(_))) .collect::>(); - let a_ids = tweakfile + let t_ids = tweakfile .ids() .filter(|&id| matches!(id, HandleId::AssetPathId(_))) .collect::>(); debug!( - "Sprite len: {:?} | GLTF len: {:?} | Audio Tweakfile: {:?}", + "Sprite len: {:?} | GLTF len: {:?} | Tweakfile: {:?}", s_ids.len(), g_ids.len(), - a_ids.len(), + t_ids.len(), ); if s_ids.len() > 0 && g_ids.len() > 0 { @@ -86,10 +86,10 @@ fn loading( let g_ready = g_ids .iter() .all(|&id| server.get_load_state(id) == LoadState::Loaded); - let a_ready = a_ids + let t_ready = t_ids .iter() .all(|&id| server.get_load_state(id) == LoadState::Loaded); - if s_ready && g_ready && a_ready { + if s_ready && g_ready && t_ready { next_state.set(GameState::Menu) } } diff --git a/src/main.rs b/src/main.rs index bc594e1..d2ed3dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,13 +11,14 @@ mod hit; mod loading; mod menu; mod prelude; +mod tweak; mod ui; use std::time::Duration; use bevy::{ asset::{ChangeWatcher, HandleId}, - input::ButtonState, + input::ButtonState, pbr::FogPlugin, core_pipeline::fxaa::FxaaPlugin, }; use crate::prelude::*; @@ -70,6 +71,7 @@ fn main() { app.add_plugins(menu::MenuPlugin); app.add_plugins(audio::AudioPlugin); app.add_plugins(ui::UiPlugin); + app.add_plugins(tweak::TweakPlugin); app.run(); } diff --git a/src/tweak.rs b/src/tweak.rs new file mode 100644 index 0000000..b3a96dd --- /dev/null +++ b/src/tweak.rs @@ -0,0 +1,60 @@ +use crate::prelude::*; +use bevy::{ + asset::{AssetLoader, LoadContext, LoadedAsset}, + reflect::{TypePath, TypeUuid}, + utils::BoxedFuture, +}; +use serde::Deserialize; + +/// A Tweakfile is resource used to specify game customization like asset names, +/// and non-user customizations made to the game during development. +pub(crate) struct TweakPlugin; + +impl Plugin for TweakPlugin { + fn build(&self, app: &mut App) { + + app.add_systems(OnEnter(GameState::Loading), load_tweakfile); + + app.add_asset::() + .init_asset_loader::(); + } +} + +fn load_tweakfile(server: Res, mut commands: Commands) { + let handle: Handle = server.load("martian.tweak.toml"); + commands.insert_resource(GameTweakfile(handle)); +} + +#[derive(Debug, Resource)] +struct GameTweakfile(Handle); + +/// Tweakfile contains tweaks made to other parts of the game +#[derive(Debug, Deserialize, TypeUuid, TypePath)] +#[uuid = "e5768efe-edce-4267-bdf4-dd8f8ca613c7"] +pub(crate) struct Tweakfile { + #[serde(default)] + pub audio: audio::AudioTweaks, +} + + +#[derive(Default)] +pub struct TweakfileLoader; + +impl AssetLoader for TweakfileLoader { + fn load<'a>( + &'a self, + bytes: &'a [u8], + load_context: &'a mut LoadContext, + ) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> { + Box::pin(async move { + let s = std::str::from_utf8(bytes)?; + let custom_asset = toml::from_str::(s)?; + load_context.set_default_asset(LoadedAsset::new(custom_asset)); + Ok(()) + }) + } + + fn extensions(&self) -> &[&str] { + &["tweak.toml"] + } +} \ No newline at end of file