diff --git a/engine/asset_loader/src/lib.rs b/engine/asset_loader/src/lib.rs index d28af63..eda363d 100644 --- a/engine/asset_loader/src/lib.rs +++ b/engine/asset_loader/src/lib.rs @@ -1 +1 @@ -pub mod macros; \ No newline at end of file +pub mod macros; diff --git a/game/buildings/src/assets/building_asset.rs b/game/buildings/src/assets/building_asset.rs index 4187b6d..765619e 100644 --- a/game/buildings/src/assets/building_asset.rs +++ b/game/buildings/src/assets/building_asset.rs @@ -1,14 +1,15 @@ use asset_loader::create_asset_loader; -use bevy::prelude::*; +use bevy::{gltf::GltfMesh, prelude::*}; use serde::{Deserialize, Serialize}; -use shared::identifiers::ResourceIdentifier; +use shared::{identifiers::ResourceIdentifier, prefab_defination::*}; use crate::{ buildings::{ - basic_building::BasicBuildingInfo, conduit_building::ResourceConduitInfo, - factory_building::FactoryBuildingInfo, resource_gathering::ResourceGatheringBuildingInfo, + conduit_building::ResourceConduitInfo, factory_building::FactoryBuildingInfo, + resource_gathering::ResourceGatheringBuildingInfo, }, footprint::BuildingFootprint, + prelude::Building, }; #[derive(Asset, TypePath, Debug, Serialize, Deserialize)] @@ -18,7 +19,8 @@ pub struct BuildingAsset { pub footprint: BuildingFootprint, pub prefab_path: String, #[serde(skip)] - pub prefab: Handle, + pub prefab: Handle, + pub base_mesh_path: String, pub cost: Vec, pub consumption: Vec, @@ -27,7 +29,44 @@ pub struct BuildingAsset { pub health: u32, pub building_type: BuildingType, - pub animations: Vec, + pub children: Option>, +} + +impl BuildingAsset { + pub fn spawn( + &self, + pos: Vec3, + rot: Quat, + gltf: &Gltf, + commands: &mut Commands, + meshes: &Assets, + ) -> Option { + let keys: Vec<_> = gltf.named_meshes.keys().collect(); + info!("{keys:#?}"); + let mesh_handle = &gltf.named_meshes[&self.base_mesh_path.clone().into_boxed_str()]; + if let Some(gltf_mesh) = meshes.get(mesh_handle.id()) { + let (mesh, mat) = gltf_mesh.unpack(); + let mut entity = commands.spawn(( + PbrBundle { + mesh, + material: mat, + transform: Transform::from_translation(pos) + .with_rotation(Quat::from_rotation_arc(Vec3::NEG_Z, Vec3::Y) * rot), + ..Default::default() + }, + Building, + )); + if let Some(children) = &self.children { + entity.with_children(|b| { + for child in children { + child.spawn_recursive(gltf, b, meshes); + } + }); + } + return Some(entity.id()); + } + return None; + } } #[derive(Serialize, Deserialize, Debug, TypePath)] @@ -38,11 +77,6 @@ pub enum BuildingType { ResourceConduit(ResourceConduitInfo), } -#[derive(Serialize, Deserialize, Debug, Reflect)] -pub enum AnimationComponent { - Rotation, - Slider, -} create_asset_loader!( BuildingAssetPlugin, BuildingAssetLoader, diff --git a/game/buildings/src/building_plugin.rs b/game/buildings/src/building_plugin.rs index 5d63463..bfd207f 100644 --- a/game/buildings/src/building_plugin.rs +++ b/game/buildings/src/building_plugin.rs @@ -1,6 +1,6 @@ use std::f32::consts::E; -use bevy::{ecs::world::CommandQueue, prelude::*, window::PrimaryWindow}; +use bevy::{ecs::world::CommandQueue, gltf::GltfMesh, prelude::*, window::PrimaryWindow}; use bevy_asset_loader::loading_state::{ config::{ConfigureLoadingState, LoadingStateConfig}, LoadingStateAppExt, @@ -87,7 +87,6 @@ fn hq_placement( mut build_queue: ResMut, mut next_state: ResMut>, ) { - if let Some(contact) = tile_under_cursor.0 { let positions = map.hex_select(&contact.tile, 3, true, |pos, h, _| pos.to_world(h)); show_indicators(positions, &mut commands, &indicator); @@ -122,6 +121,8 @@ fn process_build_queue( mut commands: Commands, db: Res, building_assets: Res>, + gltf_assets: Res>, + gltf_meshes: Res>, mut building_map: ResMut, heightmap: Res, ) { @@ -130,16 +131,14 @@ fn process_build_queue( if let Some(building) = building_assets.get(handle.id()) { let h = heightmap.sample_height(&item.pos); println!("Spawning {} at {}", building.name, item.pos); - let e = commands.spawn(( - SceneBundle { - scene: building.prefab.clone(), - transform: Transform::from_translation(item.pos.to_world(h)), - ..Default::default() - }, - Building, - )); - - building_map.add_building(BuildingEntry::new(item.pos, e.id())); + if let Some(gltf) = gltf_assets.get(building.prefab.id()) { + let e = building.spawn(item.pos.to_world(h), Quat::IDENTITY, gltf, &mut commands, &gltf_meshes); + if let Some(b) = e { + building_map.add_building(BuildingEntry::new(item.pos, b)); + } + } else { + warn!("Failed to spawn building"); + } } } queue.queue.clear(); diff --git a/game/main/assets b/game/main/assets index 7fa3e1f..4f7ec75 160000 --- a/game/main/assets +++ b/game/main/assets @@ -1 +1 @@ -Subproject commit 7fa3e1fc9cea4ec2232ee86edb4eb62ecde604fe +Subproject commit 4f7ec753b1ee5c3194506c66717ee082cbca2f69 diff --git a/game/shared/src/lib.rs b/game/shared/src/lib.rs index 2de0e49..0f93a6b 100644 --- a/game/shared/src/lib.rs +++ b/game/shared/src/lib.rs @@ -9,6 +9,7 @@ pub mod resources; pub mod sets; pub mod states; pub mod tags; +pub mod prefab_defination; #[derive(Debug, Serialize, Deserialize)] pub enum Tier { diff --git a/game/shared/src/prefab_defination.rs b/game/shared/src/prefab_defination.rs new file mode 100644 index 0000000..bd029b7 --- /dev/null +++ b/game/shared/src/prefab_defination.rs @@ -0,0 +1,62 @@ +use bevy::{ + gltf::{Gltf, GltfMesh}, + math::{Quat, Vec3}, + prelude::*, +}; +use serde::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize, Debug)] +pub struct PrefabDefination { + pub path: String, + pub pos: Vec3, + pub rot: Vec3, + pub children: Option>, + pub animations: Option>, +} + +impl PrefabDefination { + pub fn spawn_recursive(&self, gltf: &Gltf, commands: &mut ChildBuilder, meshes: &Assets) { + let mesh_handle = &gltf.named_meshes[&self.path.clone().into_boxed_str()]; + if let Some(gltf_mesh) = meshes.get(mesh_handle.id()) { + let (m, mat) = gltf_mesh.unpack(); + let mut entity = commands.spawn(PbrBundle { + mesh: m, + material: mat, + transform: Transform::from_translation(self.pos).with_rotation(Quat::from_euler( + bevy::math::EulerRot::XYZ, + self.rot.x, + self.rot.y, + self.rot.z, + )), + ..Default::default() + }); + if let Some(children) = &self.children { + entity.with_children(|b| { + for child in children { + child.spawn_recursive(gltf, b, meshes); + } + }); + } + } + } +} + +pub trait UnpackGltfMesh { + fn unpack(&self) -> (Handle, Handle); +} + +impl UnpackGltfMesh for GltfMesh { + fn unpack(&self) -> (Handle, Handle) { + let p = &self.primitives[0]; + let mut mat: Handle = default(); + if let Some(mesh_material) = &p.material { + mat = mesh_material.clone(); + } + return (p.mesh.clone(), mat); + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub enum AnimationComponent { + Rotation, + Slider, +}