prefab loading

Building prefab loading
This commit is contained in:
2024-11-18 22:35:18 -05:00
parent 4cfe2d9079
commit 953650e394
6 changed files with 121 additions and 25 deletions

View File

@@ -1 +1 @@
pub mod macros; pub mod macros;

View File

@@ -1,14 +1,15 @@
use asset_loader::create_asset_loader; use asset_loader::create_asset_loader;
use bevy::prelude::*; use bevy::{gltf::GltfMesh, prelude::*};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use shared::identifiers::ResourceIdentifier; use shared::{identifiers::ResourceIdentifier, prefab_defination::*};
use crate::{ use crate::{
buildings::{ buildings::{
basic_building::BasicBuildingInfo, conduit_building::ResourceConduitInfo, conduit_building::ResourceConduitInfo, factory_building::FactoryBuildingInfo,
factory_building::FactoryBuildingInfo, resource_gathering::ResourceGatheringBuildingInfo, resource_gathering::ResourceGatheringBuildingInfo,
}, },
footprint::BuildingFootprint, footprint::BuildingFootprint,
prelude::Building,
}; };
#[derive(Asset, TypePath, Debug, Serialize, Deserialize)] #[derive(Asset, TypePath, Debug, Serialize, Deserialize)]
@@ -18,7 +19,8 @@ pub struct BuildingAsset {
pub footprint: BuildingFootprint, pub footprint: BuildingFootprint,
pub prefab_path: String, pub prefab_path: String,
#[serde(skip)] #[serde(skip)]
pub prefab: Handle<Scene>, pub prefab: Handle<Gltf>,
pub base_mesh_path: String,
pub cost: Vec<ResourceIdentifier>, pub cost: Vec<ResourceIdentifier>,
pub consumption: Vec<ResourceIdentifier>, pub consumption: Vec<ResourceIdentifier>,
@@ -27,7 +29,44 @@ pub struct BuildingAsset {
pub health: u32, pub health: u32,
pub building_type: BuildingType, pub building_type: BuildingType,
pub animations: Vec<AnimationComponent>, pub children: Option<Vec<PrefabDefination>>,
}
impl BuildingAsset {
pub fn spawn(
&self,
pos: Vec3,
rot: Quat,
gltf: &Gltf,
commands: &mut Commands,
meshes: &Assets<GltfMesh>,
) -> Option<Entity> {
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)] #[derive(Serialize, Deserialize, Debug, TypePath)]
@@ -38,11 +77,6 @@ pub enum BuildingType {
ResourceConduit(ResourceConduitInfo), ResourceConduit(ResourceConduitInfo),
} }
#[derive(Serialize, Deserialize, Debug, Reflect)]
pub enum AnimationComponent {
Rotation,
Slider,
}
create_asset_loader!( create_asset_loader!(
BuildingAssetPlugin, BuildingAssetPlugin,
BuildingAssetLoader, BuildingAssetLoader,

View File

@@ -1,6 +1,6 @@
use std::f32::consts::E; 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::{ use bevy_asset_loader::loading_state::{
config::{ConfigureLoadingState, LoadingStateConfig}, config::{ConfigureLoadingState, LoadingStateConfig},
LoadingStateAppExt, LoadingStateAppExt,
@@ -87,7 +87,6 @@ fn hq_placement(
mut build_queue: ResMut<BuildQueue>, mut build_queue: ResMut<BuildQueue>,
mut next_state: ResMut<NextState<GameplayState>>, mut next_state: ResMut<NextState<GameplayState>>,
) { ) {
if let Some(contact) = tile_under_cursor.0 { if let Some(contact) = tile_under_cursor.0 {
let positions = map.hex_select(&contact.tile, 3, true, |pos, h, _| pos.to_world(h)); let positions = map.hex_select(&contact.tile, 3, true, |pos, h, _| pos.to_world(h));
show_indicators(positions, &mut commands, &indicator); show_indicators(positions, &mut commands, &indicator);
@@ -122,6 +121,8 @@ fn process_build_queue(
mut commands: Commands, mut commands: Commands,
db: Res<BuildingDatabase>, db: Res<BuildingDatabase>,
building_assets: Res<Assets<BuildingAsset>>, building_assets: Res<Assets<BuildingAsset>>,
gltf_assets: Res<Assets<Gltf>>,
gltf_meshes: Res<Assets<GltfMesh>>,
mut building_map: ResMut<BuildingMap>, mut building_map: ResMut<BuildingMap>,
heightmap: Res<Map>, heightmap: Res<Map>,
) { ) {
@@ -130,16 +131,14 @@ fn process_build_queue(
if let Some(building) = building_assets.get(handle.id()) { if let Some(building) = building_assets.get(handle.id()) {
let h = heightmap.sample_height(&item.pos); let h = heightmap.sample_height(&item.pos);
println!("Spawning {} at {}", building.name, item.pos); println!("Spawning {} at {}", building.name, item.pos);
let e = commands.spawn(( if let Some(gltf) = gltf_assets.get(building.prefab.id()) {
SceneBundle { let e = building.spawn(item.pos.to_world(h), Quat::IDENTITY, gltf, &mut commands, &gltf_meshes);
scene: building.prefab.clone(), if let Some(b) = e {
transform: Transform::from_translation(item.pos.to_world(h)), building_map.add_building(BuildingEntry::new(item.pos, b));
..Default::default() }
}, } else {
Building, warn!("Failed to spawn building");
)); }
building_map.add_building(BuildingEntry::new(item.pos, e.id()));
} }
} }
queue.queue.clear(); queue.queue.clear();

View File

@@ -9,6 +9,7 @@ pub mod resources;
pub mod sets; pub mod sets;
pub mod states; pub mod states;
pub mod tags; pub mod tags;
pub mod prefab_defination;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum Tier { pub enum Tier {

View File

@@ -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<Vec<PrefabDefination>>,
pub animations: Option<Vec<AnimationComponent>>,
}
impl PrefabDefination {
pub fn spawn_recursive(&self, gltf: &Gltf, commands: &mut ChildBuilder, meshes: &Assets<GltfMesh>) {
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<Mesh>, Handle<StandardMaterial>);
}
impl UnpackGltfMesh for GltfMesh {
fn unpack(&self) -> (Handle<Mesh>, Handle<StandardMaterial>) {
let p = &self.primitives[0];
let mut mat: Handle<StandardMaterial> = 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,
}