gltf prefabs
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
use asset_loader::create_asset_loader;
|
use asset_loader::create_asset_loader;
|
||||||
use bevy::{gltf::GltfMesh, prelude::*};
|
use bevy::{
|
||||||
|
gltf::{GltfMesh, GltfNode},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use shared::{identifiers::ResourceIdentifier, prefab_defination::*};
|
use shared::{component_defination::ComponentDefination, identifiers::ResourceIdentifier, prefab_defination::*};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
buildings::{
|
buildings::{
|
||||||
@@ -29,7 +32,7 @@ pub struct BuildingAsset {
|
|||||||
pub health: u32,
|
pub health: u32,
|
||||||
|
|
||||||
pub building_type: BuildingType,
|
pub building_type: BuildingType,
|
||||||
pub children: Option<Vec<PrefabDefination>>,
|
pub components: Option<Vec<ComponentDefination>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuildingAsset {
|
impl BuildingAsset {
|
||||||
@@ -40,31 +43,79 @@ impl BuildingAsset {
|
|||||||
gltf: &Gltf,
|
gltf: &Gltf,
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
meshes: &Assets<GltfMesh>,
|
meshes: &Assets<GltfMesh>,
|
||||||
|
nodes: &Assets<GltfNode>,
|
||||||
) -> Option<Entity> {
|
) -> Option<Entity> {
|
||||||
let keys: Vec<_> = gltf.named_meshes.keys().collect();
|
let base_node = &gltf.named_nodes[&self.base_mesh_path.clone().into_boxed_str()];
|
||||||
info!("{keys:#?}");
|
if let Some(node) = nodes.get(base_node.id()) {
|
||||||
let mesh_handle = &gltf.named_meshes[&self.base_mesh_path.clone().into_boxed_str()];
|
if let Some(mesh_handle) = &node.mesh {
|
||||||
if let Some(gltf_mesh) = meshes.get(mesh_handle.id()) {
|
if let Some(gltf_mesh) = meshes.get(mesh_handle.id()) {
|
||||||
let (mesh, mat) = gltf_mesh.unpack();
|
let (mesh, mat) = gltf_mesh.unpack();
|
||||||
let mut entity = commands.spawn((
|
let mut entity = commands.spawn((
|
||||||
PbrBundle {
|
PbrBundle {
|
||||||
mesh,
|
mesh,
|
||||||
material: mat,
|
material: mat,
|
||||||
transform: Transform::from_translation(pos)
|
transform: Transform::from_translation(pos).with_rotation(rot),
|
||||||
.with_rotation(Quat::from_rotation_arc(Vec3::NEG_Z, Vec3::Y) * rot),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Building,
|
Building,
|
||||||
));
|
));
|
||||||
if let Some(children) = &self.children {
|
|
||||||
entity.with_children(|b| {
|
entity.with_children(|b| {
|
||||||
for child in children {
|
for child in &node.children {
|
||||||
child.spawn_recursive(gltf, b, meshes);
|
self.process_node(child, meshes, b, &node.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if let Some(component) = self.get_component_def(&format!("/{0}", &node.name)) {
|
||||||
|
component.apply(&mut entity);
|
||||||
}
|
}
|
||||||
return Some(entity.id());
|
return Some(entity.id());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_node(
|
||||||
|
&self,
|
||||||
|
node: &GltfNode,
|
||||||
|
meshes: &Assets<GltfMesh>,
|
||||||
|
commands: &mut ChildBuilder,
|
||||||
|
parent: &String,
|
||||||
|
) -> Option<Entity> {
|
||||||
|
let path = format!("{0}/{1}", parent, node.name);
|
||||||
|
if let Some(mesh) = &node.mesh {
|
||||||
|
if let Some(gltf_mesh) = meshes.get(mesh.id()) {
|
||||||
|
let (mesh, mat) = gltf_mesh.unpack();
|
||||||
|
let mut entity = commands.spawn((
|
||||||
|
PbrBundle {
|
||||||
|
mesh,
|
||||||
|
material: mat,
|
||||||
|
transform: node.transform,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
Building,
|
||||||
|
));
|
||||||
|
entity.with_children(|b| {
|
||||||
|
for child in &node.children {
|
||||||
|
self.process_node(child, meshes, b, &path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(component) = self.get_component_def(&path) {
|
||||||
|
component.apply(&mut entity);
|
||||||
|
}
|
||||||
|
return Some(entity.id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_component_def(&self, path: &String) -> Option<&ComponentDefination> {
|
||||||
|
if let Some(components) = &self.components {
|
||||||
|
for c in components {
|
||||||
|
if c.path.eq(path) {
|
||||||
|
return Some(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
use std::f32::consts::E;
|
use std::f32::consts::E;
|
||||||
|
|
||||||
use bevy::{ecs::world::CommandQueue, gltf::GltfMesh, prelude::*, window::PrimaryWindow};
|
use bevy::{
|
||||||
|
ecs::world::CommandQueue,
|
||||||
|
gltf::{GltfMesh, GltfNode},
|
||||||
|
prelude::*,
|
||||||
|
window::PrimaryWindow,
|
||||||
|
};
|
||||||
use bevy_asset_loader::loading_state::{
|
use bevy_asset_loader::loading_state::{
|
||||||
config::{ConfigureLoadingState, LoadingStateConfig},
|
config::{ConfigureLoadingState, LoadingStateConfig},
|
||||||
LoadingStateAppExt,
|
LoadingStateAppExt,
|
||||||
@@ -123,6 +128,7 @@ fn process_build_queue(
|
|||||||
building_assets: Res<Assets<BuildingAsset>>,
|
building_assets: Res<Assets<BuildingAsset>>,
|
||||||
gltf_assets: Res<Assets<Gltf>>,
|
gltf_assets: Res<Assets<Gltf>>,
|
||||||
gltf_meshes: Res<Assets<GltfMesh>>,
|
gltf_meshes: Res<Assets<GltfMesh>>,
|
||||||
|
gltf_nodes: Res<Assets<GltfNode>>,
|
||||||
mut building_map: ResMut<BuildingMap>,
|
mut building_map: ResMut<BuildingMap>,
|
||||||
heightmap: Res<Map>,
|
heightmap: Res<Map>,
|
||||||
) {
|
) {
|
||||||
@@ -132,7 +138,14 @@ fn process_build_queue(
|
|||||||
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);
|
||||||
if let Some(gltf) = gltf_assets.get(building.prefab.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);
|
let e = building.spawn(
|
||||||
|
item.pos.to_world(h),
|
||||||
|
Quat::IDENTITY,
|
||||||
|
gltf,
|
||||||
|
&mut commands,
|
||||||
|
&gltf_meshes,
|
||||||
|
&gltf_nodes,
|
||||||
|
);
|
||||||
if let Some(b) = e {
|
if let Some(b) = e {
|
||||||
building_map.add_building(BuildingEntry::new(item.pos, b));
|
building_map.add_building(BuildingEntry::new(item.pos, b));
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule game/main/assets updated: 4f7ec753b1...bba1aa9629
@@ -15,6 +15,7 @@ use bevy_rapier3d::geometry::Collider;
|
|||||||
use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin};
|
use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin};
|
||||||
use buildings::BuildingPugin;
|
use buildings::BuildingPugin;
|
||||||
use iyes_perf_ui::prelude::*;
|
use iyes_perf_ui::prelude::*;
|
||||||
|
use shared::animation_plugin::SimpleAnimationPlugin;
|
||||||
use shared::sets::GameplaySet;
|
use shared::sets::GameplaySet;
|
||||||
use shared::states::{GameplayState, MenuState};
|
use shared::states::{GameplayState, MenuState};
|
||||||
use shared::{despawn::DespawnPuglin, states::AssetLoadState};
|
use shared::{despawn::DespawnPuglin, states::AssetLoadState};
|
||||||
@@ -38,6 +39,7 @@ impl Plugin for PhosGamePlugin {
|
|||||||
MapInitPlugin,
|
MapInitPlugin,
|
||||||
RenderDistancePlugin,
|
RenderDistancePlugin,
|
||||||
BuildingPugin,
|
BuildingPugin,
|
||||||
|
SimpleAnimationPlugin,
|
||||||
// BuildUiPlugin,
|
// BuildUiPlugin,
|
||||||
UnitsPlugin,
|
UnitsPlugin,
|
||||||
DespawnPuglin,
|
DespawnPuglin,
|
||||||
|
|||||||
18
game/shared/src/animation_plugin.rs
Normal file
18
game/shared/src/animation_plugin.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::prefab_defination::RotationAnimation;
|
||||||
|
|
||||||
|
pub struct SimpleAnimationPlugin;
|
||||||
|
|
||||||
|
impl Plugin for SimpleAnimationPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(Update, rotate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rotate(mut query: Query<(&mut Transform, &RotationAnimation)>, time: Res<Time>) {
|
||||||
|
for (mut transform, rot) in query.iter_mut() {
|
||||||
|
let cur_rot = transform.rotation;
|
||||||
|
transform.rotation = cur_rot * Quat::from_axis_angle(rot.axis, rot.speed.to_radians() * time.elapsed_seconds());
|
||||||
|
}
|
||||||
|
}
|
||||||
20
game/shared/src/component_defination.rs
Normal file
20
game/shared/src/component_defination.rs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
use bevy::{
|
||||||
|
ecs::system::EntityCommands, math::{Quat, Vec3}, prelude::*
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::prefab_defination::AnimationComponent;
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct ComponentDefination {
|
||||||
|
pub path: String,
|
||||||
|
pub animations: Vec<AnimationComponent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ComponentDefination {
|
||||||
|
pub fn apply(&self, commands: &mut EntityCommands){
|
||||||
|
for c in &self.animations {
|
||||||
|
c.apply(commands);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ pub mod sets;
|
|||||||
pub mod states;
|
pub mod states;
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
pub mod prefab_defination;
|
pub mod prefab_defination;
|
||||||
|
pub mod component_defination;
|
||||||
|
pub mod animation_plugin;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum Tier {
|
pub enum Tier {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
|
ecs::system::{EntityCommand, EntityCommands},
|
||||||
gltf::{Gltf, GltfMesh},
|
gltf::{Gltf, GltfMesh},
|
||||||
math::{Quat, Vec3},
|
math::{Quat, Vec3},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@@ -57,6 +58,23 @@ impl UnpackGltfMesh for GltfMesh {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub enum AnimationComponent {
|
pub enum AnimationComponent {
|
||||||
Rotation,
|
Rotation(RotationAnimation),
|
||||||
Slider,
|
Slider,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Component, Clone, Copy)]
|
||||||
|
pub struct RotationAnimation {
|
||||||
|
pub axis: Vec3,
|
||||||
|
pub speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimationComponent {
|
||||||
|
pub fn apply(&self, commands: &mut EntityCommands) {
|
||||||
|
match self {
|
||||||
|
AnimationComponent::Rotation(comp) => {
|
||||||
|
commands.insert(comp.clone());
|
||||||
|
}
|
||||||
|
AnimationComponent::Slider => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user