// Event handling - animation state changed. // We need to capture that because: // 1: state can be changed over time. // 2: synchronization of states private void AnimationStateChanged(MyStateMachineTransitionWithStart transitionWithStart) { var animationTransition = transitionWithStart.Transition as MyAnimationStateMachineTransition; if (animationTransition == null) { return; } var animationSourceNode = transitionWithStart.StartNode as MyAnimationStateMachineNode; var animationTargetNode = animationTransition.TargetNode as MyAnimationStateMachineNode; if (animationSourceNode != null) { // synchronization if (animationTargetNode != null) { bool targetAnimationStillPlaying = false; foreach (var blending in m_stateTransitionBlending) { if (blending.SourceState == animationTargetNode) { targetAnimationStillPlaying = true; break; } } // synchronization options... use them only if target animation is not playing already if (!targetAnimationStillPlaying) { switch (animationTransition.Sync) { case MyAnimationTransitionSyncType.Restart: if (animationTargetNode.RootAnimationNode != null) { animationTargetNode.RootAnimationNode.SetLocalTimeNormalized(0); } break; case MyAnimationTransitionSyncType.Synchronize: if (animationSourceNode.RootAnimationNode != null && animationTargetNode.RootAnimationNode != null) { float normalizedTimeInSource = animationSourceNode.RootAnimationNode.GetLocalTimeNormalized(); animationTargetNode.RootAnimationNode.SetLocalTimeNormalized(normalizedTimeInSource); } break; case MyAnimationTransitionSyncType.NoSynchonization: // do nothing break; default: Debug.Fail("Unknown synchronization option."); break; } } } // transition over time if ((animationTransition.TransitionTimeInSec > 0.0 || transitionWithStart.Transition.TargetNode.PassThrough) && !transitionWithStart.StartNode.PassThrough) { MyStateTransitionBlending stateTransitionBlending = new MyStateTransitionBlending // struct { SourceState = animationSourceNode, TimeLeftInSeconds = animationTransition.TransitionTimeInSec, InvTotalTime = 1.0 / animationTransition.TransitionTimeInSec }; if (!stateTransitionBlending.InvTotalTime.IsValid()) { stateTransitionBlending.InvTotalTime = 1.0f; } m_stateTransitionBlending.Insert(0, stateTransitionBlending); } else { if (transitionWithStart.StartNode.PassThrough && m_stateTransitionBlending.Count > 0) { // node1 -> pass -> node2, take maximum transition time MyStateTransitionBlending stateTransitionBlending = m_stateTransitionBlending[0]; // struct stateTransitionBlending.TimeLeftInSeconds = Math.Max(animationTransition.TransitionTimeInSec, m_stateTransitionBlending[0].TimeLeftInSeconds); stateTransitionBlending.InvTotalTime = 1.0 / stateTransitionBlending.TimeLeftInSeconds; if (!stateTransitionBlending.InvTotalTime.IsValid()) { stateTransitionBlending.InvTotalTime = 1.0f; } m_stateTransitionBlending[0] = stateTransitionBlending; } else if (animationTransition.TransitionTimeInSec <= MyMathConstants.EPSILON) { m_stateTransitionBlending.Clear(); // instantly play new animation, forget about all blending stuff! } } } }
// Event handling - animation state changed. // We need to capture that because: // 1: state can be changed over time. // 2: synchronization of states private void AnimationStateChanged(MyStateMachineTransitionWithStart transitionWithStart) { var animationTransition = transitionWithStart.Transition as MyAnimationStateMachineTransition; if (animationTransition == null) return; var animationSourceNode = transitionWithStart.StartNode as MyAnimationStateMachineNode; var animationTargetNode = animationTransition.TargetNode as MyAnimationStateMachineNode; if (animationSourceNode != null) { // synchronization if (animationTargetNode != null) { bool targetAnimationStillPlaying = false; foreach (var blending in m_stateTransitionBlending) { if (blending.SourceState == animationTargetNode) { targetAnimationStillPlaying = true; break; } } // synchronization options... use them only if target animation is not playing already switch (animationTransition.Sync) { case MyAnimationTransitionSyncType.Restart: if (animationTargetNode.RootAnimationNode != null) { animationTargetNode.RootAnimationNode.SetLocalTimeNormalized(0); } break; case MyAnimationTransitionSyncType.Synchronize: if (!targetAnimationStillPlaying && animationSourceNode.RootAnimationNode != null && animationTargetNode.RootAnimationNode != null) { float normalizedTimeInSource = animationSourceNode.RootAnimationNode.GetLocalTimeNormalized(); animationTargetNode.RootAnimationNode.SetLocalTimeNormalized(normalizedTimeInSource); } break; case MyAnimationTransitionSyncType.NoSynchonization: // do nothing break; default: Debug.Fail("Unknown synchronization option."); break; } } // transition over time if ((animationTransition.TransitionTimeInSec > 0.0 || transitionWithStart.Transition.TargetNode.PassThrough) && !transitionWithStart.StartNode.PassThrough) { MyStateTransitionBlending stateTransitionBlending = new MyStateTransitionBlending // struct { SourceState = animationSourceNode, TimeLeftInSeconds = animationTransition.TransitionTimeInSec, InvTotalTime = 1.0/animationTransition.TransitionTimeInSec }; if (!stateTransitionBlending.InvTotalTime.IsValid()) stateTransitionBlending.InvTotalTime = 1.0f; m_stateTransitionBlending.Insert(0, stateTransitionBlending); } else { if (transitionWithStart.StartNode.PassThrough && m_stateTransitionBlending.Count > 0) { // node1 -> pass -> node2, take maximum transition time MyStateTransitionBlending stateTransitionBlending = m_stateTransitionBlending[0]; // struct stateTransitionBlending.TimeLeftInSeconds = Math.Max(animationTransition.TransitionTimeInSec, m_stateTransitionBlending[0].TimeLeftInSeconds); stateTransitionBlending.InvTotalTime = 1.0 / stateTransitionBlending.TimeLeftInSeconds; if (!stateTransitionBlending.InvTotalTime.IsValid()) stateTransitionBlending.InvTotalTime = 1.0f; m_stateTransitionBlending[0] = stateTransitionBlending; } else if (animationTransition.TransitionTimeInSec <= MyMathConstants.EPSILON) { m_stateTransitionBlending.Clear(); // instantly play new animation, forget about all blending stuff! } } } }