From cef69b81cc673b11df1d0b0dcdee08ac84a1c136 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Thu, 14 Dec 2023 20:26:58 -0800 Subject: [PATCH] Toml generalization Trying to make the tweakfile code more general purpose. I'd like to just throw stuff in there and reference it in code without having to modify structs and stuff. So far it's tedious, but mostly because I'll have to go back and rewrite a bunch of code... sadge. --- examples/toml-stuff.rs | 19 ++++++ src/tweak.rs | 133 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 examples/toml-stuff.rs diff --git a/examples/toml-stuff.rs b/examples/toml-stuff.rs new file mode 100644 index 0000000..99d2bc0 --- /dev/null +++ b/examples/toml-stuff.rs @@ -0,0 +1,19 @@ +use bevy::utils::HashMap; +use serde::Deserialize; +use toml::Table; + +#[derive(Deserialize, Debug)] +enum Val { + A(String), + B(usize), + C(bool), +} + +fn main() { + let s = r#"val = "asdf" +other = 123 +final = false + "#; + let v = toml::from_str::(s).unwrap(); + println!("{:?}", v); +} diff --git a/src/tweak.rs b/src/tweak.rs index 9c99436..2a21af1 100644 --- a/src/tweak.rs +++ b/src/tweak.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use bevy::asset::AsyncReadExt; +use bevy::utils::HashMap; use bevy::{ asset::{io::Reader, AssetLoader, LoadContext}, reflect::TypePath, @@ -17,7 +18,8 @@ impl Plugin for TweakPlugin { fn build(&self, app: &mut App) { app.add_systems(OnEnter(GameState::Loading), load_tweakfile); - app.init_asset::().register_asset_loader(TweakfileLoader); + app.init_asset::() + .register_asset_loader(TweakfileLoader); } } @@ -32,7 +34,7 @@ pub(crate) struct GameTweakfile { } /// Tweakfile contains tweaks made to other parts of the game -#[derive(Debug, Deserialize, TypePath, Asset)] +#[derive(Debug, Deserialize, TypePath, Asset, Default)] pub struct Tweakfile { #[serde(default)] pub audio: audio::AudioTweaks, @@ -42,6 +44,125 @@ pub struct Tweakfile { pub display2d: display2d::tweaks::Display2dTweaks, } +#[derive(Debug, Asset, TypePath)] +pub struct Tweaks(HashMap); + +impl Tweaks { + fn from_table( + table: &toml::Table, + load_context: &mut LoadContext, + base: String, + ) -> Vec<(String, TweakValue)> { + table + .iter() + .flat_map(|(k, v)| { + let key = if base.len() > 0 { + format!("{}_{}", base, k) + } else { + k.clone() + }; + match v { + toml::Value::Table(t) => Tweaks::from_table(t, load_context, key), + toml::Value::Datetime(_) => panic!("This type is not supported!"), + _ => vec![(key, TweakValue::from_toml(v, load_context))], + } + }) + .collect() + } + + fn get_handle(&self, key: &str) -> Option> { + self.0.get(key).map(|val| Handle::::from(val.clone())) + } + + fn get_int(&self, key: &str) -> Option { + self.0.get(key).map(|val| i64::from(val.clone())) + } + + fn get_float(&self, key: &str) -> Option { + self.0.get(key).map(|val| f64::from(val.clone())) + } +} + +#[derive(Debug, Clone)] +pub enum TweakValue { + Handle(UntypedHandle), + Int(i64), + Float(f64), + Bool(bool), + Str(String), + List(Vec), +} + +impl TweakValue { + fn from_toml(val: &toml::Value, load_context: &mut LoadContext) -> TweakValue { + match val { + toml::Value::String(s) => { + if std::path::Path::new(&format!("assets/{}", s)).exists() { + TweakValue::Handle(load_context.load_untyped(s).untyped()) + } else { + TweakValue::Str(s.clone()) + } + } + toml::Value::Integer(i) => TweakValue::Int(*i), + toml::Value::Float(f) => TweakValue::Float(*f), + toml::Value::Boolean(b) => TweakValue::Bool(*b), + toml::Value::Array(a) => TweakValue::List( + a.iter() + .map(|v| TweakValue::from_toml(v, load_context)) + .collect(), + ), + toml::Value::Table(_) | toml::Value::Datetime(_) => { + panic!("This type is not supported!") + } + } + } +} + +impl From for Handle { + fn from(src: TweakValue) -> Handle { + match src { + TweakValue::Handle(h) => h.clone().typed::(), + _ => panic!("{:?} is not a handle", src), + } + } +} + +impl From for String { + fn from(src: TweakValue) -> String { + match src { + TweakValue::Str(s) => s, + _ => panic!("{:?} is not a bool", src), + } + } +} + +impl From for i64 { + fn from(src: TweakValue) -> i64 { + match src { + TweakValue::Int(i) => i, + _ => panic!("{:?} is not an integer", src), + } + } +} + +impl From for f64 { + fn from(src: TweakValue) -> f64 { + match src { + TweakValue::Float(f) => f, + _ => panic!("{:?} is not a float", src), + } + } +} + +impl From for bool { + fn from(src: TweakValue) -> bool { + match src { + TweakValue::Bool(b) => b, + _ => panic!("{:?} is not a bool", src), + } + } +} + #[derive(Default)] pub struct TweakfileLoader; @@ -70,9 +191,11 @@ impl AssetLoader for TweakfileLoader { let mut bytes = Vec::new(); reader.read_to_end(&mut bytes).await?; let s = std::str::from_utf8(bytes.as_slice())?; - let mut result = toml::from_str::(s)?; - result.display3d.load_dependencies(load_context); - Ok(result) + let parsed = toml::from_str::(s)?; + let list = Tweaks::from_table(&parsed, load_context, String::new()); + let result: HashMap = list.into_iter().collect(); + // Ok(Tweaks(result)) + Ok(Tweakfile::default()) }) }