cleanup
This commit is contained in:
parent
eeffe3cc8c
commit
10acb83b83
277
src/skeleton.rs
277
src/skeleton.rs
|
@ -10,14 +10,12 @@
|
||||||
//
|
//
|
||||||
// This module manages model loading and animation.
|
// This module manages model loading and animation.
|
||||||
|
|
||||||
use crate::world;
|
|
||||||
use bevy::ecs::system::EntityCommands;
|
use bevy::ecs::system::EntityCommands;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub struct SkeletonPlugin;
|
pub struct SkeletonPlugin;
|
||||||
impl Plugin for SkeletonPlugin {
|
impl Plugin for SkeletonPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Update, animate_skeleton_parts);
|
|
||||||
app.add_systems(Update, play_animations);
|
app.add_systems(Update, play_animations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,187 +51,12 @@ pub fn asset_name_to_path(name: &str) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skeleton_name_to_skeletondef(name: &str) -> Option<SkeletonDef> {
|
|
||||||
// x: positive: left, negative: right
|
|
||||||
// y: positive: upward, negative: downward
|
|
||||||
// z: positive: forward, negative: backward
|
|
||||||
match name {
|
|
||||||
"suitv1" => Some(SkeletonDef::Human(HumanDef {
|
|
||||||
collider: "models/suit_v1/collider.glb#Scene0".into(),
|
|
||||||
base: "models/suit_v1/base.glb#Scene0".into(),
|
|
||||||
limbs: vec![
|
|
||||||
LimbDef {
|
|
||||||
class: Limb::Head,
|
|
||||||
path: "models/suit_v1/head.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(0.0, 0.46, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
LimbDef {
|
|
||||||
class: Limb::UpperArmLeft,
|
|
||||||
path: "models/suit_v1/upper_arm.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(0.22, 0.3, 0.0),
|
|
||||||
mirror: true,
|
|
||||||
children: vec![LimbDef {
|
|
||||||
class: Limb::LowerArmLeft,
|
|
||||||
path: "models/suit_v1/lower_arm.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(-0.33, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
}],
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
LimbDef {
|
|
||||||
class: Limb::UpperArmRight,
|
|
||||||
path: "models/suit_v1/upper_arm.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(-0.22, 0.3, 0.0),
|
|
||||||
children: vec![LimbDef {
|
|
||||||
class: Limb::LowerArmRight,
|
|
||||||
path: "models/suit_v1/lower_arm.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(-0.33, 0.0, 0.0),
|
|
||||||
..default()
|
|
||||||
}],
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
LimbDef {
|
|
||||||
class: Limb::UpperLegLeft,
|
|
||||||
path: "models/suit_v1/upper_leg.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(0.15, -0.25, 0.1),
|
|
||||||
mirror: true,
|
|
||||||
children: vec![LimbDef {
|
|
||||||
class: Limb::LowerLegLeft,
|
|
||||||
path: "models/suit_v1/lower_leg.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(0.0, -0.3, 0.0),
|
|
||||||
..default()
|
|
||||||
}],
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
LimbDef {
|
|
||||||
class: Limb::UpperLegRight,
|
|
||||||
path: "models/suit_v1/upper_leg.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(-0.15, -0.25, 0.1),
|
|
||||||
children: vec![LimbDef {
|
|
||||||
class: Limb::LowerLegRight,
|
|
||||||
path: "models/suit_v1/lower_leg.glb#Scene0".into(),
|
|
||||||
pos: Vec3::new(0.0, -0.3, 0.0),
|
|
||||||
..default()
|
|
||||||
}],
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)] pub struct SkeletonLimb;
|
|
||||||
#[derive(Component)] pub struct MirroredLimb;
|
|
||||||
pub enum SkeletonDef {
|
|
||||||
Human(HumanDef)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct HumanDef {
|
|
||||||
collider: String,
|
|
||||||
base: String,
|
|
||||||
limbs: Vec<LimbDef>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LimbDef {
|
|
||||||
path: String,
|
|
||||||
pos: Vec3,
|
|
||||||
class: Limb,
|
|
||||||
mirror: bool,
|
|
||||||
children: Vec<LimbDef>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Default)]
|
|
||||||
pub enum Limb {
|
|
||||||
#[default]
|
|
||||||
Base,
|
|
||||||
Head,
|
|
||||||
UpperArmRight,
|
|
||||||
UpperArmLeft,
|
|
||||||
LowerArmRight,
|
|
||||||
LowerArmLeft,
|
|
||||||
UpperLegRight,
|
|
||||||
UpperLegLeft,
|
|
||||||
LowerLegRight,
|
|
||||||
LowerLegLeft,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub enum Animation {
|
|
||||||
HumanFloat,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load(
|
pub fn load(
|
||||||
name: &str,
|
name: &str,
|
||||||
entity_commands: &mut EntityCommands,
|
entity_commands: &mut EntityCommands,
|
||||||
asset_server: &AssetServer,
|
asset_server: &AssetServer,
|
||||||
) {
|
) {
|
||||||
if let Some(skel) = skeleton_name_to_skeletondef(name) {
|
|
||||||
match skel {
|
|
||||||
SkeletonDef::Human(human) => {
|
|
||||||
entity_commands.insert(load_scene_by_path(human.collider.as_str(), asset_server));
|
|
||||||
entity_commands.with_children(|parent| {
|
|
||||||
parent.spawn((
|
|
||||||
Limb::Base,
|
|
||||||
Animation::HumanFloat,
|
|
||||||
world::DespawnOnPlayerDeath,
|
|
||||||
SceneBundle {
|
|
||||||
scene: load_scene_by_path(human.base.as_str(), asset_server),
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
for limb in human.limbs {
|
|
||||||
let rot = if limb.mirror {
|
|
||||||
Quat::from_rotation_y(180.0f32.to_radians())
|
|
||||||
} else {
|
|
||||||
Quat::IDENTITY
|
|
||||||
};
|
|
||||||
let mut parent_limb = parent.spawn((
|
|
||||||
limb.class,
|
|
||||||
Animation::HumanFloat,
|
|
||||||
world::DespawnOnPlayerDeath,
|
|
||||||
SceneBundle {
|
|
||||||
scene: load_scene_by_path(limb.path.as_str(), asset_server),
|
|
||||||
transform: Transform::from_translation(limb.pos).with_rotation(rot),
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
if limb.mirror {
|
|
||||||
parent_limb.insert(MirroredLimb);
|
|
||||||
}
|
|
||||||
if !limb.children.is_empty() {
|
|
||||||
parent_limb.with_children(|parent| {
|
|
||||||
for child_limb in limb.children {
|
|
||||||
let rot = if child_limb.mirror {
|
|
||||||
Quat::from_rotation_y(180.0f32.to_radians())
|
|
||||||
} else {
|
|
||||||
Quat::IDENTITY
|
|
||||||
};
|
|
||||||
let mut entity_commands = parent.spawn((
|
|
||||||
child_limb.class,
|
|
||||||
Animation::HumanFloat,
|
|
||||||
world::DespawnOnPlayerDeath,
|
|
||||||
SceneBundle {
|
|
||||||
scene: load_scene_by_path(child_limb.path.as_str(), asset_server),
|
|
||||||
transform: Transform::from_translation(child_limb.pos).with_rotation(rot),
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
if child_limb.mirror {
|
|
||||||
entity_commands.insert(MirroredLimb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
entity_commands.insert(load_scene_by_path(asset_name_to_path(name), asset_server));
|
entity_commands.insert(load_scene_by_path(asset_name_to_path(name), asset_server));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -249,85 +72,6 @@ pub fn load_scene_by_path(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _build_body(
|
|
||||||
_name: String,
|
|
||||||
mut _entity_commands: EntityCommands,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn animate_skeleton_parts(
|
|
||||||
time: Res<Time>,
|
|
||||||
mut q_limb: Query<(&mut Transform, &Limb, &Animation, Option<&MirroredLimb>)>,
|
|
||||||
) {
|
|
||||||
let t = time.elapsed_seconds();
|
|
||||||
for (mut trans, limb, animation, mirror) in &mut q_limb {
|
|
||||||
let mirror = mirror.is_some();
|
|
||||||
match animation {
|
|
||||||
Animation::HumanFloat =>
|
|
||||||
animate_human_float(&mut trans, &limb, mirror, t),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rot(trans: &mut Transform, x: f32, y: f32, z: f32) {
|
|
||||||
trans.rotation = Quat::from_euler(
|
|
||||||
EulerRot::XYZ,
|
|
||||||
x.to_radians(),
|
|
||||||
y.to_radians(),
|
|
||||||
z.to_radians()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn animate_human_float(mut trans: &mut Transform, limb: &Limb, mirror: bool, t: f32) {
|
|
||||||
// x: lean head forward/backward
|
|
||||||
// y: close/open arms together in front of the torso
|
|
||||||
// z: spread legs sidewards
|
|
||||||
let m = {|angle| if mirror { 180f32 + angle } else { angle }};
|
|
||||||
match limb {
|
|
||||||
Limb::UpperArmRight => rot(&mut trans,
|
|
||||||
0.0,
|
|
||||||
m(40.0 + 5.0 * (t * 0.5).sin()),
|
|
||||||
20.0 + 10.0 * (t * 0.5).sin(),
|
|
||||||
),
|
|
||||||
Limb::UpperArmLeft => rot(&mut trans,
|
|
||||||
0.0,
|
|
||||||
m(-(40.0 + 5.0 * (t * 0.5).sin())),
|
|
||||||
20.0 + 10.0 * (t * 0.5).sin(),
|
|
||||||
),
|
|
||||||
Limb::LowerArmRight => rot(&mut trans,
|
|
||||||
0.0,
|
|
||||||
m(20.0),
|
|
||||||
-20.0,
|
|
||||||
),
|
|
||||||
Limb::LowerArmLeft => rot(&mut trans,
|
|
||||||
0.0,
|
|
||||||
m(-20.0),
|
|
||||||
-20.0,
|
|
||||||
),
|
|
||||||
Limb::UpperLegRight => rot(&mut trans,
|
|
||||||
-30.0 + 10.0 * (t * 0.5).sin(),
|
|
||||||
0.0,
|
|
||||||
-20.0 + 2.5 * (t * 0.5).cos(),
|
|
||||||
),
|
|
||||||
Limb::UpperLegLeft => rot(&mut trans,
|
|
||||||
-30.0 + 10.0 * (t * 0.5).sin(),
|
|
||||||
0.0,
|
|
||||||
20.0 - 2.5 * (t * 0.5).cos(),
|
|
||||||
),
|
|
||||||
Limb::LowerLegRight => rot(&mut trans,
|
|
||||||
35.0 + 5.0 * (t * 0.5).sin(),
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
),
|
|
||||||
Limb::LowerLegLeft => rot(&mut trans,
|
|
||||||
35.0 + 5.0 * (t * 0.5).sin(),
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
),
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn play_animations(
|
fn play_animations(
|
||||||
mut players: Query<&mut AnimationPlayer, Added<AnimationPlayer>>,
|
mut players: Query<&mut AnimationPlayer, Added<AnimationPlayer>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
@ -337,24 +81,3 @@ fn play_animations(
|
||||||
player.play(animation.clone()).repeat();
|
player.play(animation.clone()).repeat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn play_animations(
|
|
||||||
// players: Query<(Entity, &Parent, &AnimationPlayer), Added<AnimationPlayer>>,
|
|
||||||
// q_parents: Query<(Entity, &Parent)>,
|
|
||||||
// world: &World,
|
|
||||||
//) {
|
|
||||||
// for (entity, parent, player) in &players {
|
|
||||||
// info!("Got player!");
|
|
||||||
//// dbg!(world.inspect_entity(entity));
|
|
||||||
//// let parent_entity = q_parents.get(parent.get());
|
|
||||||
//// if let Ok((parent_entity, parent_parents)) = parent_entity {
|
|
||||||
//// //dbg!(world.inspect_entity(parent_entity));
|
|
||||||
//// let parent_entity = q_parents.get(parent_parents.get());
|
|
||||||
//// if let Ok((parent_entity, parent_parents)) = parent_entity {
|
|
||||||
//// dbg!(world.inspect_entity(parent_entity));
|
|
||||||
//// }
|
|
||||||
//// }
|
|
||||||
// //dbg!(player);
|
|
||||||
// //player.play(animations.0[0].clone_weak()).repeat();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
Loading…
Reference in a new issue