diff --git a/assets/skeleton/suit_v1/forearm.glb b/assets/skeleton/suit_v1/lower_arm.glb similarity index 100% rename from assets/skeleton/suit_v1/forearm.glb rename to assets/skeleton/suit_v1/lower_arm.glb diff --git a/assets/skeleton/suit_v1/thigh.glb b/assets/skeleton/suit_v1/upper_leg.glb similarity index 100% rename from assets/skeleton/suit_v1/thigh.glb rename to assets/skeleton/suit_v1/upper_leg.glb diff --git a/src/skeleton.rs b/src/skeleton.rs index d8bdb7b..179093f 100644 --- a/src/skeleton.rs +++ b/src/skeleton.rs @@ -39,9 +39,68 @@ pub fn asset_name_to_path(name: &str) -> &'static str { pub fn skeleton_name_to_skeletondef(name: &str) -> Option { match name { - "suitv1" => Some(SkeletonDef { - base: "skeleton/suit_v1/base.glb#Scene0".to_string(), - }), + "suitv1" => Some(SkeletonDef::Human(HumanDef { + collider: "skeleton/suit_v1/collider.glb#Scene0".into(), + base: "skeleton/suit_v1/base.glb#Scene0".into(), + limbs: vec![ + LimbDef { + class: Limb::Head, + path: "skeleton/suit_v1/head.glb#Scene0".into(), + pos: Vec3::new(0.0, 0.5, 0.0), + ..default() + }, + LimbDef { + class: Limb::UpperArmLeft, + path: "skeleton/suit_v1/upper_arm.glb#Scene0".into(), + pos: Vec3::new(0.25, 0.3, 0.0), + mirror: true, + children: vec![LimbDef { + class: Limb::LowerArmLeft, + path: "skeleton/suit_v1/lower_arm.glb#Scene0".into(), + pos: Vec3::new(-0.33, 0.0, 0.0), + ..default() + }], + ..default() + }, + LimbDef { + class: Limb::UpperArmRight, + path: "skeleton/suit_v1/upper_arm.glb#Scene0".into(), + pos: Vec3::new(-0.25, 0.3, 0.0), + children: vec![LimbDef { + class: Limb::LowerArmRight, + path: "skeleton/suit_v1/lower_arm.glb#Scene0".into(), + pos: Vec3::new(-0.33, 0.0, 0.0), + ..default() + }], + ..default() + }, + LimbDef { + class: Limb::UpperLegLeft, + path: "skeleton/suit_v1/upper_leg.glb#Scene0".into(), + pos: Vec3::new(0.15, -0.25, 0.0), + mirror: true, + children: vec![LimbDef { + class: Limb::LowerLegLeft, + path: "skeleton/suit_v1/lower_leg.glb#Scene0".into(), + pos: Vec3::new(0.0, -0.3, 0.0), + ..default() + }], + ..default() + }, + LimbDef { + class: Limb::UpperLegRight, + path: "skeleton/suit_v1/upper_leg.glb#Scene0".into(), + pos: Vec3::new(-0.15, -0.25, 0.0), + children: vec![LimbDef { + class: Limb::LowerLegRight, + path: "skeleton/suit_v1/lower_leg.glb#Scene0".into(), + pos: Vec3::new(0.0, -0.3, 0.0), + ..default() + }], + ..default() + }, + ], + })), _ => None, } } @@ -54,19 +113,39 @@ impl Plugin for SkeletonPlugin { } #[derive(Component)] pub struct SkeletonLimb; -pub struct SkeletonDef { - pub base: String, +pub enum SkeletonDef { + Human(HumanDef) } -//pub fn spawn( -// name: &str, -// commands: Commands, -// asset_server: &AssetServer, -//) -> EntityCommands { -// let mut entity_commands = commands.spawn_empty(); -// load(name, &mut entity_commands, asset_server); -// return entity_commands; -//} +pub struct HumanDef { + collider: String, + base: String, + limbs: Vec, +} + +#[derive(Default)] +pub struct LimbDef { + path: String, + pos: Vec3, + class: Limb, + mirror: bool, + children: Vec, +} + +#[derive(Component, Default)] +pub enum Limb { + #[default] + Base, + Head, + UpperArmRight, + UpperArmLeft, + LowerArmRight, + LowerArmLeft, + UpperLegRight, + UpperLegLeft, + LowerLegRight, + LowerLegLeft, +} pub fn load( name: &str, @@ -74,7 +153,54 @@ pub fn load( asset_server: &AssetServer, ) { if let Some(skel) = skeleton_name_to_skeletondef(name) { - entity_commands.insert(load_scene_by_path(skel.base.as_str(), asset_server)); + 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, + 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, + SceneBundle { + scene: load_scene_by_path(limb.path.as_str(), asset_server), + transform: Transform::from_translation(limb.pos).with_rotation(rot), + ..default() + } + )); + 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 + }; + parent.spawn(( + child_limb.class, + SceneBundle { + scene: load_scene_by_path(child_limb.path.as_str(), asset_server), + transform: Transform::from_translation(child_limb.pos).with_rotation(rot), + ..default() + } + )); + } + }); + } + } + }); + } + } } else { entity_commands.insert(load_scene_by_path(asset_name_to_path(name), asset_server)); }