diff --git a/assets/martian.tweak.toml b/assets/martian.tweak.toml index f6fd2c6..bdab7a3 100644 --- a/assets/martian.tweak.toml +++ b/assets/martian.tweak.toml @@ -177,9 +177,12 @@ assets_file = "models/Martian Chess.glb" skybox_file = "images/skybox.png" [display3d.models.scenes] -queen = "Queen" -drone = "Drone" -pawn = "Pawn" +queen_red = "QueenRed" +drone_red = "DroneRed" +pawn_red = "PawnRed" +queen_blue = "QueenBlue" +drone_blue = "DroneBlue" +pawn_blue = "PawnBlue" board = "Gameboard" valid_move = "Valid Move Spot" @@ -190,29 +193,28 @@ turn_b = "GameCamSide2>1" turn_a = "GameCamSide1>2" [display3d.models.animations.pick_up] -pawn = "PawnPiecePickup" -drone = "DronePiecePickup" -queen = "QueenPiecePickup" +pawn_blue = "PawnBluePiecePickup" +pawn_red = "PawnRedPiecePickup" +drone_blue = "DroneBluePiecePickup" +drone_red = "DroneRedPiecePickup" +queen_blue = "QueenBluePiecePickup" +queen_red = "QueenRedPiecePickup" [display3d.models.animations.put_down] -pawn = "PawnPiecePutDown" -drone = "DronePiecePutDown" -queen = "QueenPiecePutDown" +pawn_blue = "PawnBluePiecePutDown" +pawn_red = "PawnRedPiecePutDown" +drone_blue = "DroneBluePiecePutDown" +drone_red = "DroneRedPiecePutDown" +queen_blue = "QueenBluePiecePutDown" +queen_red = "QueenRedPiecePutDown" [display3d.models.animations.idle] -pawn = "PawnPieceIdle" -drone = "DronePieceIdle" -queen = "QueenPieceIdle" - -[display3d.models.materials] -queen_red = "Queen" -queen_blue = "QueenBlue" -drone_red = "Drone" -drone_blue = "DroneBlue" -pawn_red = "Pawn" -pawn_blue = "DroneBlue" -dots_red = "Dots" -dots_blue = "DotsBlue" +pawn_blue = "PawnBluePieceIdle" +pawn_red = "PawnRedPieceIdle" +drone_blue = "DroneBluePieceIdle" +drone_red = "DroneRedPieceIdle" +queen_blue = "QueenBluePieceIdle" +queen_red = "QueenRedPieceIdle" [display3d.lights.scaling] # https://docs.rs/bevy/0.11.3/bevy/pbr/struct.SpotLight.html diff --git a/assets/models/Martian Chess.glb b/assets/models/Martian Chess.glb index d40e64d..842686d 100644 --- a/assets/models/Martian Chess.glb +++ b/assets/models/Martian Chess.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f12f1d0da2a87e6324b24fce74fb9ac9f587ff79bf5b692c68f20de850091f1a -size 30092588 +oid sha256:1e7ebc1dde15a343a19ce814482329c9a25320f1f4fef02fc53385e4ef91098f +size 33852088 diff --git a/assets/untitled.glb b/assets/untitled.glb deleted file mode 100644 index bad8c7c..0000000 --- a/assets/untitled.glb +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9bcb44ade7ce6f867eb86ddbedb980ac37e4f1603dbc663391da8c5b262c10bd -size 107092 diff --git a/src/display3d.rs b/src/display3d.rs index 51268d0..cac7a8c 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -30,12 +30,13 @@ impl Plugin for Display3dPlugin { switch_sides .run_if(in_state(GameState::Play)) .run_if(state_changed::), - set_piece_model - .run_if(any_component_added::().or_else(any_component_changed::())), - set_piece_texture - .run_if(any_component_changed::().or_else(any_component_added::())) - .run_if(resource_exists::), - set_piece_position.run_if(any_component_changed::()), + update_pieces.run_if( + resource_exists::.and_then( + any_component_changed::() + .or_else(any_component_changed::()) + .or_else(any_component_changed::()) + ) + ), set_board_model.run_if( any_component_added::() .or_else(any_component_added::()) @@ -79,7 +80,7 @@ impl Plugin for Display3dPlugin { .add_systems( OnEnter(GameState::Play), ( - set_piece_texture.run_if(resource_exists::), + update_pieces.run_if(resource_exists::), update_tweaks.run_if(resource_exists::), opening_animation .run_if(run_once()) @@ -381,51 +382,6 @@ fn fix_skybox( } } -/// Set the model for each piece based on the game::Piece::* marker -fn set_piece_model( - mut events: Query< - (&mut Handle, &Piece), - ( - Or<(Added, Changed)>, - With, - ), - >, - gltfs: Res>, - tweaks: Res>, - tweaks_file: Res, -) { - let tweak = tweaks - .get(tweaks_file.handle.clone()) - .expect("Load tweakfile"); - events.iter_mut().for_each(|(mut handle, piece)| { - let assets_handle = tweak - .get_handle::("display3d_models_assets_file") - .unwrap(); - let gltf = gltfs.get(assets_handle).expect("Load GLTF content"); - *handle = match piece { - game::Piece::Pawn => gltf.named_scenes.get( - tweak - .get::("display3d_models_scenes_pawn") - .unwrap() - .as_str(), - ), - game::Piece::Drone => gltf.named_scenes.get( - tweak - .get::("display3d_models_scenes_drone") - .unwrap() - .as_str(), - ), - game::Piece::Queen => gltf.named_scenes.get( - tweak - .get::("display3d_models_scenes_queen") - .unwrap() - .as_str(), - ), - } - .expect("Game board model") - .clone(); - }); -} fn set_board_model( mut boards: Query< @@ -461,18 +417,6 @@ fn set_board_model( }); } -/// Sets a piece location given it's board index -fn set_piece_position( - mut events: Query< - (&mut Transform, &BoardIndex), - (With, With, Changed), - >, -) { - events.iter_mut().for_each(|(mut t, i)| { - t.translation = board_translation(i); - }); -} - /// Given a board index returns the Vec3 location in space fn board_translation(&BoardIndex { x, y }: &BoardIndex) -> Vec3 { // Scale x down by 4 to account for -4..4 scaling @@ -550,184 +494,58 @@ fn mouse_zoom( }); } -/// Set the Texture for a piece given it's position (left or right) on the bord. -/// Executed when Side is changed or upon entry to Display3d state -/// Getting this to run _after_ GLTF is loaded is a pain. -/// PERF: We are saving what to work on in a Vector which is bad. -/// CAVEAT: We are only exeucting this when a piece changes or state is changed. -fn set_piece_texture( - query: Query< - (Entity, &Piece, &Side), - ( - With, - With, - ), - >, +// The dumbest way to achieve this goal +// Essentially we iterate over every piece and set the appropriate model and texture +fn update_pieces( + mut query: Query<(Entity, &Piece, &Side, &BoardIndex, &mut Transform, &mut Handle, &AnimationPlayer)>, gltfs: Res>, - children: Query<&Children>, - mut models: Query<(&Name, &mut Handle)>, tweaks: Res>, tweaks_file: Res, ) { - query.iter().for_each(|(entity, piece, side)| { - debug!("Checking piece texture for {:?}", entity); - let tweak = tweaks.get(tweaks_file.handle.clone()).unwrap(); - let assets_handle = tweak - .get_handle::("display3d_models_assets_file") - .unwrap(); - if let Some(gltf) = gltfs.get(assets_handle) { - // Why can't we just models.iter_many_mut(...).for_each(...)?? - let mut stuff = models.iter_many_mut(children.iter_descendants(entity)); - while let Some((n, mut m)) = stuff.fetch_next() { - debug!("Setting piece texture for {:?}", n); - match (*piece, side, n.as_str()) { - (Piece::Queen, Side::A, "Queen.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_queen_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Queen texture") - .clone() - } - (Piece::Queen, Side::A, "Queen.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Dots texture") - .clone() - } - (Piece::Queen, Side::B, "Queen.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_queen_blue") - .unwrap() - .as_str(), - ) - .expect("Load Blue Queen texture") - .clone() - } - (Piece::Queen, Side::B, "Queen.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_blue") - .unwrap() - .as_str(), - ) - .expect("Load Red Dots texture") - .clone() - } - (Piece::Drone, Side::A, "Drone.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_drone_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Drone texture") - .clone() - } - (Piece::Drone, Side::A, "Drone.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Dots texture") - .clone() - } - (Piece::Drone, Side::B, "Drone.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_drone_blue") - .unwrap() - .as_str(), - ) - .expect("Load Blue Drone texture") - .clone() - } - (Piece::Drone, Side::B, "Drone.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_blue") - .unwrap() - .as_str(), - ) - .expect("Load Blue Dots texture") - .clone() - } - (Piece::Pawn, Side::A, "Pawn.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_pawn_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Pawn texture") - .clone() - } - (Piece::Pawn, Side::A, "Pawn.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_red") - .unwrap() - .as_str(), - ) - .expect("Load Red Dots texture") - .clone() - } - (Piece::Pawn, Side::B, "Pawn.0") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_pawn_blue") - .unwrap() - .as_str(), - ) - .expect("Load Blue Pawn texture") - .clone() - } - (Piece::Pawn, Side::B, "Pawn.1") => { - *m = gltf - .named_materials - .get( - tweak - .get::("display3d_models_materials_dots_blue") - .unwrap() - .as_str(), - ) - .expect("Load Blue Dots texture") - .clone() - } - _ => warn!("???"), - } + let tweak = tweaks + .get(tweaks_file.handle.clone()) + .expect("Load tweakfile"); + let assets_handle = tweak + .get_handle::("display3d_models_assets_file") + .unwrap(); + let models = gltfs.get(assets_handle).unwrap(); + + query.iter_mut().for_each(|(entity, piece, side, board_index, mut transform, mut scene, animation_player)| { + // Set position of piece + let new_translation = board_translation(board_index); + if transform.translation != new_translation { + transform.translation = new_translation; + } + + // Find name of this piece's model scene + let scene_tweak_name: Option = match (piece, side) { + (Piece::Pawn, Side::A) => { + tweak.get("display3d_models_scenes_pawn_red") + }, + (Piece::Pawn, Side::B) => { + tweak.get("display3d_models_scenes_pawn_blue") } + (Piece::Drone, Side::A) => { + tweak.get("display3d_models_scenes_drone_red") + }, + (Piece::Drone, Side::B) => { + tweak.get("display3d_models_scenes_drone_blue") + } + (Piece::Queen, Side::A) => { + tweak.get("display3d_models_scenes_queen_red") + }, + (Piece::Queen, Side::B) => { + tweak.get("display3d_models_scenes_queen_blue") + } + }; + + // Get model scene for this piece + let scene_handle = models.named_scenes.get(&scene_tweak_name.unwrap()).unwrap(); + + // Set scene model for this piece + if *scene != *scene_handle { + warn!("Updating scene for piece {:?}", entity); + *scene = scene_handle.clone(); } }); } @@ -854,13 +672,9 @@ fn set_valid_move_model( } } -fn _play_valid_move_animation(_players: Query<&AnimationPlayer>) { - todo!(); -} - fn pick_up( mut events: Query< - (Entity, &game::Piece), + (Entity, &game::Piece, &game::Side), (With, With, Added), >, gltfs: Res>, @@ -873,7 +687,7 @@ fn pick_up( let tweak = tweaks .get(tweaks_file.handle.clone()) .expect("Load tweakfile"); - events.iter_mut().for_each(|(entity, piece)| { + events.iter_mut().for_each(|(entity, piece, side)| { let assets_handle = tweak .get_handle::("display3d_models_assets_file") .unwrap(); @@ -884,7 +698,7 @@ fn pick_up( if let Ok((name, mut player)) = players.get_mut(child) { info!("Picking up {:?} ({:?}) {:?}", name, entity, piece); let pickup_animation = - format!("display3d_models_animations_pick_up_{:?}", piece).to_ascii_lowercase(); + format!("display3d_models_animations_pick_up_{:?}_{}", piece, side.color_str()).to_ascii_lowercase(); let pickup_handle = gltf .named_animations .get( @@ -895,7 +709,7 @@ fn pick_up( ) .expect("Pickup Animation"); let idle_animation = - format!("display3d_models_animations_idle_{:?}", piece).to_ascii_lowercase(); + format!("display3d_models_animations_idle_{:?}_{}", piece, side.color_str()).to_ascii_lowercase(); let idle_handle = gltf .named_animations .get( @@ -928,7 +742,7 @@ fn pick_up( fn put_down( mut events: RemovedComponents, - mut query: Query<&game::Piece, (With, With, With)>, + mut query: Query<(&game::Piece, &game::Side), (With, With, With)>, gltfs: Res>, children: Query<&Children>, mut players: Query<(&Name, &mut AnimationPlayer)>, @@ -940,7 +754,7 @@ fn put_down( .get(&tweaks_file.handle.clone()) .expect("Load tweakfile"); events.read().for_each(|entity| { - if let Ok(piece) = query.get_mut(entity) { + if let Ok((piece, side)) = query.get_mut(entity) { let assets_handle = tweak .get_handle::("display3d_models_assets_file") .unwrap(); @@ -949,7 +763,7 @@ fn put_down( if let Ok((name, mut player)) = players.get_mut(child) { info!("Putting down {:?}", entity); let putdown_animation = - format!("display3d_models_animations_put_down_{:?}", piece) + format!("display3d_models_animations_put_down_{:?}_{}", piece, side.color_str()) .to_ascii_lowercase(); let putdown_handle = gltf .named_animations @@ -962,6 +776,7 @@ fn put_down( .expect("PutDown Animation"); if let Some(putdown_clip) = clips.get(putdown_handle) { if putdown_clip.compatible_with(name) { + info!("Compatible with both clips!"); player .start_with_transition( putdown_handle.clone(), @@ -1473,4 +1288,4 @@ fn debug_selected( ), ); }); -} +} \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index 8e95f49..173cc04 100644 --- a/src/game.rs +++ b/src/game.rs @@ -218,6 +218,15 @@ pub(crate) enum Side { B, } +impl Side { + pub(crate) fn color_str(&self) -> &'static str { + match self { + Side::A => "red", + Side::B => "blue", + } + } +} + impl std::ops::Not for Side { type Output = Self;