/// <summary> /// Plays the specified animation. /// </summary> /// <param name="mode">The animation mode.</param> /// <param name="animation">The animation to play.</param> /// <param name="speedMultiplier">The relative speed at which to play the animation.</param> /// <param name="easeInFunction">The easing function to apply when easing in the animation.</param> /// <param name="easeInDuration">The number of seconds over which to ease in the animation.</param> /// <param name="easeOutFunction">The easing function to apply when easing out the animation.</param> /// <param name="easeOutDuration">The number of seconds over which to ease out the animation.</param> /// <param name="callbacks">The set of callbacks to invoke for this animation.</param> public void Play(SkinnedAnimationMode mode, SkinnedAnimation animation, Single speedMultiplier, EasingFunction easeInFunction, Double easeInDuration, EasingFunction easeOutFunction, Double easeOutDuration, SkinnedAnimationCallbacks?callbacks = null) { Contract.Require(animation, nameof(animation)); Contract.Require(easeInFunction, nameof(easeInFunction)); Contract.EnsureRange(easeInDuration >= 0, nameof(easeInDuration)); Contract.Require(easeOutFunction, nameof(easeOutFunction)); Contract.EnsureRange(easeOutDuration >= 0, nameof(easeOutDuration)); this.currentAnimationMode = mode; this.CurrentAnimation = animation; this.currentAnimationTime = 0.0; this.SpeedMultiplier = speedMultiplier; if (mode != SkinnedAnimationMode.Manual) { this.easeInFunction = easeInFunction; this.easeInDuration = easeInDuration; this.easeOutFunction = easeOutFunction; this.easeOutDuration = easeOutDuration; } else { this.easeInFunction = null; this.easeInDuration = 0; this.easeOutFunction = null; this.easeOutDuration = 0; } this.easeInElasped = 0; this.easeOutElapsed = 0; this.BlendingWeight = 1f; this.callbacks = callbacks; }
/// <summary> /// Allocates a track to play the specified animation. /// </summary> private KeyValuePair <Int32, SkinnedAnimationTrack> AllocateTrack(SkinnedAnimation animation) { var existing = GetTrackForAnimationInternal(animation); if (existing.Value != null) { return(existing); } // If no existing controller, find one that isn't playing. var leastRecentlyPlayed = default(SkinnedAnimationTrack); var leastRecentlyPlayedIndex = -1; var leastRecentlyPlayedOrder = Int64.MaxValue; for (var i = 0; i < tracks.Length; i++) { var controller = tracks[i]; var order = ordering[i]; if (leastRecentlyPlayed == null || order < leastRecentlyPlayedOrder) { leastRecentlyPlayed = controller; leastRecentlyPlayedIndex = i; leastRecentlyPlayedOrder = order; } if (!controller.IsPlaying) { return(new KeyValuePair <Int32, SkinnedAnimationTrack>(i, controller)); } } // If no stopped controller, override the one that was least recently played. return(new KeyValuePair <Int32, SkinnedAnimationTrack>(leastRecentlyPlayedIndex, leastRecentlyPlayed)); }
/// <summary> /// Plays the specified animation. If the animation is already playing, /// it will be restarted using the specified mode. /// </summary> /// <param name="mode">A <see cref="SkinnedAnimationMode"/> value which describes the animation mode.</param> /// <param name="animation">The animation to play.</param> /// <param name="speedMultiplier">The relative speed at which to play the animation.</param> /// <param name="callbacks">The set of callbacks to invoke for this animation.</param> /// <returns>The <see cref="SkinnedAnimationTrack"/> which is playing the animation, or <see langword="null"/> if the animation could not be played.</returns> public SkinnedAnimationTrack PlayAnimation(SkinnedAnimationMode mode, SkinnedAnimation animation, Single speedMultiplier = 1f, SkinnedAnimationCallbacks?callbacks = null) { var controllerAllocation = AllocateTrack(animation); var controller = controllerAllocation.Value; controller.Play(mode, animation, speedMultiplier, callbacks); ordering[controllerAllocation.Key] = ++orderingCounter; UpdateAnimationState(); return(controller); }
/// <summary> /// Immediately stops the specified animation without performing any easing. /// </summary> /// <param name="animation">The animation to stop.</param> /// <returns>The <see cref="SkinnedAnimationTrack"/> which was playing the animation, or <see langword="null"/> if the animation was not being played.</returns> public SkinnedAnimationTrack StopAnimationImmediate(SkinnedAnimation animation) { var controller = GetTrackForAnimation(animation); if (controller != null) { controller.StopImmediate(); UpdateAnimationState(); return(controller); } return(null); }
/// <summary> /// Processes the node's animations. /// </summary> private static IEnumerable <SkinnedAnimation> ProcessAnimations(ModelRoot input, IEnumerable <ModelScene> scenes, Int32 nodesCount) { var uvAnimations = new List <SkinnedAnimation>(input.LogicalAnimations.Count); foreach (var animation in input.LogicalAnimations) { var uvNodeAnimations = new SkinnedModelNodeAnimation[nodesCount]; TraverseModelNodes(scenes, (n, state) => { var gltfNode = input.LogicalNodes[n.LogicalIndex]; var animScale = animation.FindScaleSampler(gltfNode); var animTranslation = animation.FindTranslationSampler(gltfNode); var animRotation = animation.FindRotationSampler(gltfNode); var animMorphWeights = animation.FindMorphSampler(gltfNode); if (animScale != null || animRotation != null || animTranslation != null || animMorphWeights != null) { var curveScale = CreateCurve(animScale, x => x, Vector3CurveStepSampler.Instance, Vector3CurveLinearSampler.Instance, Vector3CurveCubicSplineSampler.Instance); var curveTranslation = CreateCurve(animTranslation, x => x, Vector3CurveStepSampler.Instance, Vector3CurveLinearSampler.Instance, Vector3CurveCubicSplineSampler.Instance); var curveRotation = CreateCurve(animRotation, x => x, QuaternionCurveStepSampler.Instance, QuaternionCurveLinearSampler.Instance, QuaternionCurveCubicSplineSampler.Instance); var curveMorphWeights = CreateCurve(animMorphWeights, x => new ArraySegment <Single>(x), SingleArrayCurveStepSampler.Instance, SingleArrayCurveLinearSampler.Instance, SingleArrayCurveCubicSplineSampler.Instance); var uvNodeAnimation = new SkinnedModelNodeAnimation(n, curveScale, curveTranslation, curveRotation, curveMorphWeights); uvNodeAnimations[gltfNode.LogicalIndex] = uvNodeAnimation; } }); var uvAnimation = new SkinnedAnimation(animation.Name, uvNodeAnimations); uvAnimations.Add(uvAnimation); } return(uvAnimations); }
/// <summary> /// Gets the track that is currently playing the specified animation. /// </summary> private KeyValuePair <Int32, SkinnedAnimationTrack> GetTrackForAnimationInternal(SkinnedAnimation animation) { for (var i = 0; i < tracks.Length; i++) { var controller = tracks[i]; if (controller.IsPlayingAnimation(animation)) { return(new KeyValuePair <Int32, SkinnedAnimationTrack>(i, controller)); } } return(new KeyValuePair <Int32, SkinnedAnimationTrack>(-1, null)); }
/// <summary> /// Gets the track that is currently playing the specified animation. /// </summary> /// <param name="animation">The animation to evaluate.</param> /// <returns>The <see cref="SkinnedAnimationTrack"/> which is currently playing the specified /// animation, or <see langword="null"/> if no track is playing the animation.</returns> public SkinnedAnimationTrack GetTrackForAnimation(SkinnedAnimation animation) { return(GetTrackForAnimationInternal(animation).Value); }
/// <summary> /// Gets a value indicating whether the track is currently playing the specified animation. /// </summary> /// <param name="animation">The animation to evaluate.</param> /// <returns><see langword="true"/> if the track is currently playing the specified animation; otherwise, <see langword="false"/>.</returns> public Boolean IsPlayingAnimation(SkinnedAnimation animation) { Contract.Require(animation, nameof(animation)); return(animation == CurrentAnimation); }
/// <summary> /// Plays the specified animation. /// </summary> /// <param name="mode">The animation mode.</param> /// <param name="animation">The animation to play.</param> /// <param name="speedMultiplier">The relative speed at which to play the animation.</param> /// <param name="callbacks">The set of callbacks to invoke for this animation.</param> public void Play(SkinnedAnimationMode mode, SkinnedAnimation animation, Single speedMultiplier = 1f, SkinnedAnimationCallbacks?callbacks = null) { Play(mode, animation, speedMultiplier, Easings.EaseInLinear, 0.0, Easings.EaseOutLinear, 0.0, callbacks); }