fn process_animation_control<T>(
    entity: &Entity,
    animation: &Animation<T>,
    control: &mut AnimationControl<T>,
    hierarchy: Option<&AnimationHierarchy<T>>,
    sampler_storage: &AssetStorage<Sampler<T::Primitive>>,
    samplers: &mut WriteStorage<SamplerControlSet<T>>,
    rest_states: &mut WriteStorage<RestState<T>>,
    targets: &ReadStorage<T>,
    remove: &mut bool,
    next_id: &mut u64,
    apply_data: &<T as ApplyData>::ApplyData,
) -> Option<ControlState>
where
    T: AnimationSampling + Component + Clone,
{
    // Checking hierarchy
    let h_fallback = AnimationHierarchy::new_single(animation.nodes[0].0, *entity);
    let hierarchy = match hierarchy {
        Some(h) => h,
        None => if only_one_index(&animation.nodes) {
            &h_fallback
        } else {
            error!(
                "Animation control which target multiple nodes without a hierarchy detected, dropping"
            );
            *remove = true;
            return None;
        },
    };
    match (&control.state, &control.command) {
        // Check for aborted or done animation
        (_, &AnimationCommand::Abort) | (&ControlState::Abort, _) | (&ControlState::Done, _) => {
            // signal samplers to abort, and remove control object if all samplers are done and removed
            if check_and_terminate_animation(control.id, hierarchy, samplers) {
                *remove = true;
            }
            Some(ControlState::Abort)
        }

        // Animation was just requested, start it
        // We ignore the command here because we need the animation to be
        // started before we can pause it, and to avoid a lot of checks for
        // abort. The command will be processed next frame.
        (&ControlState::Requested, &AnimationCommand::Start) => {
            control.id = *next_id;
            *next_id += 1;
            if start_animation(
                animation,
                sampler_storage,
                control,
                hierarchy,
                samplers,
                rest_states,
                targets,
                apply_data,
            ) {
                Some(ControlState::Running(Duration::from_secs(0)))
            } else {
                None // Try again next frame, might just be that samplers haven't finished loading
            }
        }

        (&ControlState::Deferred(..), &AnimationCommand::Start) => {
            control.id = *next_id;
            *next_id += 1;
            if start_animation(
                animation,
                sampler_storage,
                control,
                hierarchy,
                samplers,
                rest_states,
                targets,
                apply_data,
            ) {
                Some(ControlState::Running(Duration::from_secs(0)))
            } else {
                None // Try again next frame, might just be that samplers haven't finished loading
            }
        }

        // If pause was requested on a running animation, pause it
        (&ControlState::Running(..), &AnimationCommand::Pause) => {
            pause_animation(control.id, hierarchy, samplers);
            Some(ControlState::Paused(Duration::from_secs(0)))
        }

        // If start was requested on a paused animation, unpause it
        (&ControlState::Paused(_), &AnimationCommand::Start) => {
            unpause_animation(control.id, hierarchy, samplers);
            Some(ControlState::Running(Duration::from_secs(0)))
        }

        (&ControlState::Running(..), &AnimationCommand::Step(ref dir)) => {
            step_animation(control.id, hierarchy, samplers, sampler_storage, dir);
            None
        }

        (&ControlState::Running(..), &AnimationCommand::SetInputValue(value)) => {
            set_animation_input(control.id, hierarchy, samplers, value);
            None
        }

        (&ControlState::Running(..), &AnimationCommand::SetBlendWeights(ref weights)) => {
            set_blend_weights(control.id, hierarchy, samplers, weights);
            None
        }

        // check for finished/aborted animations, wait for samplers to signal done,
        // then remove control objects
        (&ControlState::Running(..), _) => {
            if check_termination(control.id, hierarchy, &samplers) {
                // Do termination
                for (_, node_entity) in &hierarchy.nodes {
                    let empty = samplers
                        .get_mut(*node_entity)
                        .map(|sampler| {
                            sampler.clear(control.id);
                            sampler.is_empty()
                        })
                        .unwrap_or(false);
                    if empty {
                        samplers.remove(*node_entity);
                    }
                }
                *remove = true;
            } else {
                update_animation_rate(control.id, hierarchy, samplers, control.rate_multiplier);
            }
            None
        }

        _ => None,
    }
}
/// Process a single animation control object.
///
/// ## Parameters:
///
/// - `entity`: the entity the control object is active for
/// - `animation`: the animation the control is for
/// - `control`: animation control object
/// - `hierarchy`: the animation node hierarchy for the entity hierarchy the animation instance is
///                active for, if this is None the animation must be for a single node, which is the
///                local entity. If the animation contains more than a single node index, the
///                animation will be silently dropped.
/// - `sampler_storage`: `AssetStorage` for all `Sampler`s
/// - `samplers`: the active sampler sets
/// - `targets`: Target components, used to retrieve the rest pose before animation starts.
/// - `remove`: all entities pushed here will have the control object removed at the end of the system execution
/// - `next_id`: next id to use for the animation control id
///
/// ##
///
/// Optionally returns a new `ControlState` for the animation. This will be the new state of the
/// control object.
Process a single animation control object.
Process a single animation control object .
fn process_animation_control<T>(
    entity: &Entity,
    animation: &Animation<T>,
    control: &mut AnimationControl<T>,
    hierarchy: Option<&AnimationHierarchy<T>>,
    sampler_storage: &AssetStorage<Sampler<T::Primitive>>,
    samplers: &mut WriteStorage<SamplerControlSet<T>>,
    rest_states: &mut WriteStorage<RestState<T>>,
    targets: &ReadStorage<T>,
    remove: &mut bool,
    next_id: &mut u64,
    apply_data: &<T as ApplyData>::ApplyData,
) -> Option<ControlState>
where
    T: AnimationSampling + Component + Clone,
{
    // Checking hierarchy
    let h_fallback = AnimationHierarchy::new_single(animation.nodes[0].0, *entity);
    let hierarchy = match hierarchy {
        Some(h) => h,
        None => if only_one_index(&animation.nodes) {
            &h_fallback
        } else {
            error!(
                "Animation control which target multiple nodes without a hierarchy detected, dropping"
            );
            *remove = true;
            return None;
        },
    };
    match (&control.state, &control.command) {
        // Check for aborted or done animation
        (_, &AnimationCommand::Abort) | (&ControlState::Abort, _) | (&ControlState::Done, _) => {
            // signal samplers to abort, and remove control object if all samplers are done and removed
            if check_and_terminate_animation(control.id, hierarchy, samplers) {
                *remove = true;
            }
            Some(ControlState::Abort)
        }
        // Animation was just requested, start it
        // We ignore the command here because we need the animation to be
        // started before we can pause it, and to avoid a lot of checks for
        // abort. The command will be processed next frame.
        (&ControlState::Requested, &AnimationCommand::Start) => {
            control.id = *next_id;
            *next_id += 1;
            if start_animation(
                animation,
                sampler_storage,
                control,
                hierarchy,
                samplers,
                rest_states,
                targets,
                apply_data,
            ) {
                Some(ControlState::Running(Duration::from_secs(0)))
            } else {
                None // Try again next frame, might just be that samplers haven't finished loading
            }
        }
        (&ControlState::Deferred(..), &AnimationCommand::Start) => {
            control.id = *next_id;
            *next_id += 1;
            if start_animation(
                animation,
                sampler_storage,
                control,
                hierarchy,
                samplers,
                rest_states,
                targets,
                apply_data,
            ) {
                Some(ControlState::Running(Duration::from_secs(0)))
            } else {
                None // Try again next frame, might just be that samplers haven't finished loading
            }
        }
        // If pause was requested on a running animation, pause it
        (&ControlState::Running(..), &AnimationCommand::Pause) => {
            pause_animation(control.id, hierarchy, samplers);
            Some(ControlState::Paused(Duration::from_secs(0)))
        }
        // If start was requested on a paused animation, unpause it
        (&ControlState::Paused(_), &AnimationCommand::Start) => {
            unpause_animation(control.id, hierarchy, samplers);
            Some(ControlState::Running(Duration::from_secs(0)))
        }
        (&ControlState::Running(..), &AnimationCommand::Step(ref dir)) => {
            step_animation(control.id, hierarchy, samplers, sampler_storage, dir);
            None
        }
        (&ControlState::Running(..), &AnimationCommand::SetInputValue(value)) => {
            set_animation_input(control.id, hierarchy, samplers, value);
            None
        }
        (&ControlState::Running(..), &AnimationCommand::SetBlendWeights(ref weights)) => {
            set_blend_weights(control.id, hierarchy, samplers, weights);
            None
        }
        // check for finished/aborted animations, wait for samplers to signal done,
        // then remove control objects
        (&ControlState::Running(..), _) => {
            if check_termination(control.id, hierarchy, &samplers) {
                // Do termination
                for (_, node_entity) in &hierarchy.nodes {
                    let empty = samplers
                        .get_mut(*node_entity)
                        .map(|sampler| {
                            sampler.clear(control.id);
                            sampler.is_empty()
                        })
                        .unwrap_or(false);
                    if empty {
                        samplers.remove(*node_entity);
                    }
                }
                *remove = true;
            } else {
                update_animation_rate(control.id, hierarchy, samplers, control.rate_multiplier);
            }
            None
        }
        _ => None,
    }
}
fn process_animation_control < T > ( entity : & Entity , animation : & Animation < T > , control : & mut AnimationControl < T > , hierarchy : Option < & AnimationHierarchy < T > > , sampler_storage : & AssetStorage < Sampler < T :: Primitive > > , samplers : & mut WriteStorage < SamplerControlSet < T > > , rest_states : & mut WriteStorage < RestState < T > > , targets : & ReadStorage < T > , remove : & mut bool , next_id : & mut u64 , apply_data : & < T as ApplyData > :: ApplyData , ) -> Option < ControlState > where T : AnimationSampling + Component + Clone , { // Checking hierarchy let h_fallback = AnimationHierarchy :: new_single ( animation . nodes [ 0 ] . 0 , * entity ) ; let hierarchy = match hierarchy { Some ( h ) => h , None => if only_one_index ( & animation . nodes ) { & h_fallback } else { error ! ( " " ) ; * remove = true ; return None ; } , } ; match ( & control . state , & control . command ) { // Check for aborted or done animation ( _ , & AnimationCommand :: Abort ) | ( & ControlState :: Abort , _ ) | ( & ControlState :: Done , _ ) => { // signal samplers to abort, and remove control object if all samplers are done and removed if check_and_terminate_animation ( control . id , hierarchy , samplers ) { * remove = true ; } Some ( ControlState :: Abort ) } // Animation was just requested, start it // We ignore the command here because we need the animation to be // started before we can pause it, and to avoid a lot of checks for // abort. The command will be processed next frame. ( & ControlState :: Requested , & AnimationCommand :: Start ) => { control . id = * next_id ; * next_id += 1 ; if start_animation ( animation , sampler_storage , control , hierarchy , samplers , rest_states , targets , apply_data , ) { Some ( ControlState :: Running ( Duration :: from_secs ( 0 ) ) ) } else { None // Try again next frame, might just be that samplers haven't finished loading } } ( & ControlState :: Deferred ( .. ) , & AnimationCommand :: Start ) => { control . id = * next_id ; * next_id += 1 ; if start_animation ( animation , sampler_storage , control , hierarchy , samplers , rest_states , targets , apply_data , ) { Some ( ControlState :: Running ( Duration :: from_secs ( 0 ) ) ) } else { None // Try again next frame, might just be that samplers haven't finished loading } } // If pause was requested on a running animation, pause it ( & ControlState :: Running ( .. ) , & AnimationCommand :: Pause ) => { pause_animation ( control . id , hierarchy , samplers ) ; Some ( ControlState :: Paused ( Duration :: from_secs ( 0 ) ) ) } // If start was requested on a paused animation, unpause it ( & ControlState :: Paused ( _ ) , & AnimationCommand :: Start ) => { unpause_animation ( control . id , hierarchy , samplers ) ; Some ( ControlState :: Running ( Duration :: from_secs ( 0 ) ) ) } ( & ControlState :: Running ( .. ) , & AnimationCommand :: Step ( ref dir ) ) => { step_animation ( control . id , hierarchy , samplers , sampler_storage , dir ) ; None } ( & ControlState :: Running ( .. ) , & AnimationCommand :: SetInputValue ( value ) ) => { set_animation_input ( control . id , hierarchy , samplers , value ) ; None } ( & ControlState :: Running ( .. ) , & AnimationCommand :: SetBlendWeights ( ref weights ) ) => { set_blend_weights ( control . id , hierarchy , samplers , weights ) ; None } // check for finished/aborted animations, wait for samplers to signal done, // then remove control objects ( & ControlState :: Running ( .. ) , _ ) => { if check_termination ( control . id , hierarchy , & samplers ) { // Do termination for ( _ , node_entity ) in & hierarchy . nodes { let empty = samplers . get_mut ( * node_entity ) . map ( | sampler | { sampler . clear ( control . id ) ; sampler . is_empty ( ) } ) . unwrap_or ( false ) ; if empty { samplers . remove ( * node_entity ) ; } } * remove = true ; } else { update_animation_rate ( control . id , hierarchy , samplers , control . rate_multiplier ) ; } None } _ => None , } }
Process a single animation control object.
Process a single animation control object .
entity
&Entity
animation
&Animation<T>
control
&mut AnimationControl<T>
hierarchy
Option<&AnimationHierarchy<T>>
sampler_storage
&AssetStorage<Sampler<T::Primitive>>
samplers
&mut WriteStorage<SamplerControlSet<T>>
rest_states
&mut WriteStorage<RestState<T>>
targets
&ReadStorage<T>
remove
&mut bool
next_id
&mut u64
apply_data
&<T as ApplyData>::ApplyData
entity
&Entity
animation
&Animation<T>
control
&mut AnimationControl<T>
hierarchy
Option<&AnimationHierarchy<T>>
sampler_storage
&AssetStorage<Sampler<T::Primitive>>
samplers
&mut WriteStorage<SamplerControlSet<T>>
rest_states
&mut WriteStorage<RestState<T>>
targets
&ReadStorage<T>
remove
&mut bool
next_id
&mut u64
apply_data
&<T as ApplyData>::ApplyData
parameters:
`entity`: the entity the control object is active for
`animation`: the animation the control is for
`control`: animation control object
`hierarchy`: the animation node hierarchy for the entity hierarchy the animation instance is
active for, if this is None the animation must be for a single node, which is the
local entity. If the animation contains more than a single node index, the
animation will be silently dropped.
`sampler_storage`: `AssetStorage` for all `Sampler`s
`samplers`: the active sampler sets
`targets`: Target components, used to retrieve the rest pose before animation starts.
`remove`: all entities pushed here will have the control object removed at the end of the system execution
`next_id`: next id to use for the animation control id



Optionally returns a new `ControlState` for the animation. This will be the new state of the
control object.
` entity ` : the entity the control object is active for ` animation ` : the animation the control is for ` control ` : animation control object ` hierarchy ` : the animation node hierarchy for the entity hierarchy the animation instance is active for if this is None the animation must be for a single node which is the local entity . If the animation contains more than a single node index the animation will be silently dropped . ` sampler_storage ` : ` AssetStorage ` for all ` Sampler ` s ` samplers ` : the active sampler sets ` targets ` : Target components used to retrieve the rest pose before animation starts . ` remove ` : all entities pushed here will have the control object removed at the end of the system execution ` next_id ` : next id to use for the animation control id Optionally returns a new ` ControlState ` for the animation . This will be the new state of the control object .