@ -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 ::< Tweakfile > ( ) . register_asset_loader ( TweakfileLoader ) ;
app . init_asset ::< Tweakfile > ( )
. 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 < String , TweakValue > ) ;
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 < T : Asset > ( & self , key : & str ) -> Option < Handle < T > > {
self . 0. get ( key ) . map ( | val | Handle ::< T > ::from ( val . clone ( ) ) )
}
fn get_int ( & self , key : & str ) -> Option < i64 > {
self . 0. get ( key ) . map ( | val | i64 ::from ( val . clone ( ) ) )
}
fn get_float ( & self , key : & str ) -> Option < f64 > {
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 < TweakValue > ) ,
}
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 < T : Asset > From < TweakValue > for Handle < T > {
fn from ( src : TweakValue ) -> Handle < T > {
match src {
TweakValue ::Handle ( h ) = > h . clone ( ) . typed ::< T > ( ) ,
_ = > panic! ( "{:?} is not a handle" , src ) ,
}
}
}
impl From < TweakValue > for String {
fn from ( src : TweakValue ) -> String {
match src {
TweakValue ::Str ( s ) = > s ,
_ = > panic! ( "{:?} is not a bool" , src ) ,
}
}
}
impl From < TweakValue > for i64 {
fn from ( src : TweakValue ) -> i64 {
match src {
TweakValue ::Int ( i ) = > i ,
_ = > panic! ( "{:?} is not an integer" , src ) ,
}
}
}
impl From < TweakValue > for f64 {
fn from ( src : TweakValue ) -> f64 {
match src {
TweakValue ::Float ( f ) = > f ,
_ = > panic! ( "{:?} is not a float" , src ) ,
}
}
}
impl From < TweakValue > 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 ::< Tweakfile > ( s ) ? ;
result . display3d . load_dependencies ( load_context ) ;
Ok ( result )
let parsed = toml ::from_str ::< toml ::Table > ( s ) ? ;
let list = Tweaks ::from_table ( & parsed , load_context , String ::new ( ) ) ;
let result : HashMap < String , TweakValue > = list . into_iter ( ) . collect ( ) ;
// Ok(Tweaks(result))
Ok ( Tweakfile ::default ( ) )
} )
}