use bevy::{ ecs::{ query::{ReadOnlyWorldQuery, WorldQuery}, system::Command, }, prelude::*, transform::TransformSystem, utils::HashMap, }; use studio_bvh::{frames::Frame, ChannelType}; mod error; mod loader; use crate::{ math::Lerp, scene::{BindPoseGlobal, InvBindPose, SceneState, SkeletalJoint}, }; use self::loader::BvhLoader; pub struct BvhPlugin; impl Plugin for BvhPlugin { fn build(&self, app: &mut App) { app.init_asset::() .register_asset_loader(BvhLoader) // FIXME: Need to add a state for this module (similar to scene // module's `SceneState`) to manage the order/frequency at // which these systems run instead of just running them all // every frame .add_systems( PostUpdate, ( compute_inverse_bindposes, apply_deferred, animate_bvh, retarget_bvh, ) .chain() .run_if(in_state(SceneState::Active)) .after(TransformSystem::TransformPropagate), ) .register_type::() .register_type::() .insert_resource(RetargetMap::default()); } } //============================================================================== // Bvh Asset //============================================================================== #[derive(Clone, Debug, Default, Asset, TypePath)] pub struct Bvh(studio_bvh::Bvh); //============================================================================== // Bvh Anim Component //============================================================================== #[derive(Component, Debug, Reflect)] pub struct BvhAnim { #[reflect(ignore)] bvh: Handle, should_play: bool, frame: usize, #[reflect(ignore)] timer: Timer, } fn compute_inverse_bindposes( mut cmd: Commands, q_bvh_joints: Query<(Entity, &GlobalTransform), (With, Without)>, ) { for (ent, world_xform) in q_bvh_joints.iter() { let inv_bind_pose = world_xform.compute_matrix().inverse(); cmd.entity(ent).insert(InvBindPose(inv_bind_pose)); } } pub fn animate_bvh( mut q_bvh_anims: Query<(&mut BvhAnim, &Children)>, mut q_bvh_joints: Query>, r_bvh_assets: Res>, r_time: Res