bevy_vrm1 0.7.1

Allows you to use VRM and VRMA in Bevy
Documentation
use crate::prelude::VrmSystemSets;
use crate::vrm::RestTransform;
use crate::vrm::node_constraint::RotationConstraintDestinations;
use bevy::app::{AnimationSystems, Plugin};
use bevy::prelude::*;

pub(crate) struct RotationConstraintBindPlugin;

impl Plugin for RotationConstraintBindPlugin {
    fn build(
        &self,
        app: &mut App,
    ) {
        app.add_systems(
            PostUpdate,
            bind_rotation_constraints
                .in_set(VrmSystemSets::Constraints)
                .after(AnimationSystems),
        );
    }
}

fn bind_rotation_constraints(
    par_commands: ParallelCommands,
    sources: Query<
        (&Transform, &RestTransform, &RotationConstraintDestinations),
        Changed<Transform>,
    >,
    dests: Query<(&Transform, &RestTransform)>,
) {
    sources
        .par_iter()
        .for_each(|(src_tf, src_rest, destinations)| {
            for dest in &destinations.0 {
                if let Ok((dest_tf, dest_rest)) = dests.get(dest.dest) {
                    let src_delta_quat = src_rest.rotation.inverse() * src_tf.rotation;
                    let new_rot = dest_rest
                        .rotation
                        .slerp(dest_rest.rotation * src_delta_quat, dest.weight);
                    par_commands.command_scope(|mut commands| {
                        commands.entity(dest.dest).insert(Transform {
                            rotation: new_rot,
                            ..*dest_tf
                        });
                    });
                }
            }
        });
}