/// <summary>
        /// Registers the specified animation instance.
        /// </summary>
        /// <param name="animationInstance">The animation instance.</param>
        /// <param name="handoffBehavior">
        /// A value indicating how the new animations interact with existing ones.
        /// </param>
        /// <param name="previousInstance">
        /// Optional: The animation instance after which <paramref name="animationInstance"/> will be
        /// added in the animation composition chain. If set to <see langword="null"/>
        /// <paramref name="animationInstance"/> will be appended at the end of the composition chain.
        /// This parameter is only relevant when <paramref name="handoffBehavior"/> is
        /// <see cref="HandoffBehavior.Compose"/>.
        /// </param>
        /// <remarks>
        /// <para>
        /// This method adds the specified animation tree (<paramref name="animationInstance"/> and all
        /// of its children) to the animation system. The animation system will from now on
        /// automatically advance and update the animations.
        /// </para>
        /// <para>
        /// Adding and removing animation instances is usually controlled by
        /// <see cref="AnimationTransition"/> instances.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="animationInstance" /> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Cannot add <paramref name="animationInstance"/> to animation system. The animation instance
        /// is already registered, or it is not a root instance.
        /// </exception>
        internal void Add(AnimationInstance animationInstance, HandoffBehavior handoffBehavior, AnimationInstance previousInstance)
        {
            if (animationInstance == null)
            {
                throw new ArgumentNullException("animationInstance");
            }
            if (_rootInstances.Contains(animationInstance))  // TODO: This is slow if there are many animation instances!
            {
                throw new ArgumentException("Cannot add animation instance to animation system. The animation instance is already registered.");
            }
            if (!animationInstance.IsRoot)
            {
                throw new ArgumentException("Cannot add animation instance to animation system because it is not a root instance. You need to disconnect the instance from its parent first.");
            }

            _rootInstances.Add(animationInstance);

            // Normally, the time is NaN and starts to run now. (Unless the user has set a custom
            // time value.)
            if (animationInstance.Time == null)
            {
                animationInstance.Time = TimeSpan.Zero;
            }

            animationInstance.AddToCompositionChains(this, handoffBehavior, previousInstance);
        }
Example #2
0
        public static T GetValue <T>(this AnimationInstance <T> animationInstance, T defaultSource, T defaultTarget)
        {
            T result = default(T);

            animationInstance.GetValue(ref defaultSource, ref defaultTarget, ref result);
            return(result);
        }
 /// <summary>
 /// Stops the specified animations.
 /// </summary>
 /// <param name="animationInstance">The animation instance.</param>
 internal void StopAnimation(AnimationInstance animationInstance)
 {
     if (animationInstance != null)
     {
         Remove(animationInstance);
     }
 }
Example #4
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc/>
        public AnimationInstance CreateInstance()
        {
            var animationInstance = AnimationInstance.Create(this);

            animationInstance.Children.Add(Timeline.CreateInstance());

            return(animationInstance);
        }
Example #5
0
        /// <summary>
        /// Gradually replaces the specified animation with the new animation. The new animation fades
        /// in over the specified duration. After this duration the previous animation is stopped and
        /// removed from the animation system.
        /// </summary>
        /// <param name="previousAnimation">The animation that should be replaced.</param>
        /// <param name="fadeInDuration">The duration over which the new animation fades in.</param>
        /// <returns>The <see cref="AnimationTransition"/>.</returns>
        public static AnimationTransition Replace(AnimationInstance previousAnimation, TimeSpan fadeInDuration)
        {
            if (fadeInDuration > TimeSpan.Zero)
            {
                return(new FadeInAndReplaceTransition(previousAnimation, fadeInDuration));
            }

            return(new ReplaceTransition(previousAnimation));
        }
Example #6
0
        /// <summary>
        /// Gets the leaves of the <see cref="AnimationInstance"/> in the animation tree.
        /// </summary>
        /// <param name="animationInstance">The animation instance where to start the search.</param>
        /// <returns>
        /// The leaves of <paramref name="animationInstance"/> in the animation tree.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="animationInstance"/> is <see langword="null"/>.
        /// </exception>
        public static IEnumerable <AnimationInstance> GetLeaves(this AnimationInstance animationInstance)
        {
            if (animationInstance == null)
            {
                throw new ArgumentNullException("animationInstance");
            }

            return(TreeHelper.GetLeaves(animationInstance, GetChildren));
        }
Example #7
0
        /// <summary>
        /// Gets the subtree (the given <see cref="AnimationInstance"/> and all of its descendants in the
        /// animation tree) using either a depth-first or a breadth-first search.
        /// </summary>
        /// <param name="animationInstance">The animation instance where to start the search.</param>
        /// <param name="depthFirst">
        /// If set to <see langword="true"/> then a depth-first search for descendants will be made;
        /// otherwise a breadth-first search will be made.
        /// </param>
        /// <returns>
        /// The <paramref name="animationInstance"/> and all of its descendants in the animation tree.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="animationInstance"/> is <see langword="null"/>.
        /// </exception>
        public static IEnumerable <AnimationInstance> GetSubtree(this AnimationInstance animationInstance, bool depthFirst)
        {
            if (animationInstance == null)
            {
                throw new ArgumentNullException("animationInstance");
            }

            return(TreeHelper.GetSubtree(animationInstance, GetChildren, depthFirst));
        }
Example #8
0
        /// <summary>
        /// Gets the <see cref="AnimationInstance"/> and its ancestors in the animation tree.
        /// </summary>
        /// <param name="animationInstance">The animation instance where to start the search.</param>
        /// <returns>
        /// The <paramref name="animationInstance"/> and its ancestors in the animation tree.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="animationInstance"/> is <see langword="null"/>.
        /// </exception>
        public static IEnumerable <AnimationInstance> GetSelfAndAncestors(this AnimationInstance animationInstance)
        {
            if (animationInstance == null)
            {
                throw new ArgumentNullException("animationInstance");
            }

            return(TreeHelper.GetSelfAndAncestors(animationInstance, GetParent));
        }
        /// <summary>
        /// Starts the animations using the specified transition.
        /// </summary>
        /// <param name="animationInstance">The animation instance.</param>
        /// <param name="transition">
        /// The animation transition. (Can be <see langword="null"/>, in which case
        /// <see cref="AnimationTransitions.SnapshotAndReplace()"/> will be used.)
        /// </param>
        internal void StartAnimation(AnimationInstance animationInstance, AnimationTransition transition)
        {
            if (transition == null)
            {
                transition = AnimationTransitions.SnapshotAndReplace();
            }

            transition.AnimationInstance = animationInstance;
            Add(transition);
        }
Example #10
0
        //--------------------------------------------------------------
        #region Creation & Cleanup
        //--------------------------------------------------------------

        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationController"/> struct.
        /// </summary>
        internal AnimationController(AnimationManager animationManager, AnimationInstance animationInstance)
        {
            Debug.Assert(animationManager != null, "The animation system is null.");
            Debug.Assert(animationInstance != null, "The animation instance is null.");
            Debug.Assert(animationInstance.RunCount > 0, "The animation instance has an invalid RunCount.");

            _id = animationInstance.RunCount;
            _animationManager  = animationManager;
            _animationInstance = animationInstance;
        }
Example #11
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc/>
        public AnimationInstance CreateInstance()
        {
            var animationInstance = AnimationInstance.Create(this);

            foreach (var timeline in _timelines)
            {
                animationInstance.Children.Add(timeline.CreateInstance());
            }

            return(animationInstance);
        }
Example #12
0
        /// <summary>
        /// Inserts an item to the <see cref="IList{T}"/> at the specified index.
        /// </summary>
        /// <param name="index">
        /// The zero-based index at which <paramref name="item"/> should be inserted.
        /// </param>
        /// <param name="item">
        /// The object to insert into the <see cref="IList{T}"/>.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="index"/> is not a valid index in the <see cref="IList{T}"/>.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// The <see cref="IList{T}"/> is read-only.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="item"/> is not of type <see cref="AnimationInstance{T}"/>.
        /// </exception>
        void IList <AnimationInstance> .Insert(int index, AnimationInstance item)
        {
            var animationInstance = item as AnimationInstance <T>;

            if (animationInstance == null)
            {
                throw new ArgumentException("Cannot add animation instance to animation composition chain. The instance is not of the correct type.", "item");
            }

            Insert(index, animationInstance);
        }
Example #13
0
        /// <summary>
        /// Removes the first occurrence of a specific object from the <see cref="ICollection{T}"/>.
        /// </summary>
        /// <param name="item">The object to remove from the <see cref="ICollection{T}"/>.</param>
        /// <returns>
        /// <see langword="true"/> if <paramref name="item"/> was successfully removed from the
        /// <see cref="ICollection{T}"/>; otherwise, <see langword="false"/>. This method also returns
        /// <see langword="false"/> if <paramref name="item"/> is not found in the original
        /// <see cref="ICollection{T}"/>.
        /// </returns>
        bool ICollection <AnimationInstance> .Remove(AnimationInstance item)
        {
            var animationInstance = item as AnimationInstance <T>;

            if (animationInstance == null)
            {
                return(false);
            }

            return(Remove(animationInstance));
        }
Example #14
0
        /// <summary>
        /// Determines the index of a specific item in the <see cref="IList{T}"/>.
        /// </summary>
        /// <param name="item">
        /// The object to locate in the <see cref="IList{T}"/>.
        /// </param>
        /// <returns>
        /// The index of <paramref name="item"/> if found in the list; otherwise, -1.
        /// </returns>
        /// <exception cref="ArgumentException">
        /// <paramref name="item"/> is not of type <see cref="AnimationInstance{T}"/>.
        /// </exception>
        int IList <AnimationInstance> .IndexOf(AnimationInstance item)
        {
            var animationInstance = item as AnimationInstance <T>;

            if (animationInstance == null)
            {
                return(-1);
            }

            return(IndexOf(animationInstance));
        }
Example #15
0
        /// <summary>
        /// Adds an item to the <see cref="ICollection{T}"/>.
        /// </summary>
        /// <param name="item">
        /// The object to add to the <see cref="ICollection{T}"/>.
        /// </param>
        /// <exception cref="ArgumentException">
        /// <paramref name="item"/> is not of type <see cref="AnimationInstance{T}"/>.
        /// </exception>
        void ICollection <AnimationInstance> .Add(AnimationInstance item)
        {
            var animationInstance = item as AnimationInstance <T>;

            if (animationInstance == null)
            {
                throw new ArgumentException("Cannot add animation instance to animation composition chain. The instance is not of the correct type.", "item");
            }

            Add(animationInstance);
        }
Example #16
0
        /// <summary>
        /// Determines whether the <see cref="ICollection{T}"/> contains a specific value.
        /// </summary>
        /// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
        /// <returns>
        /// <see langword="true"/> if <paramref name="item"/> is found in the
        /// <see cref="ICollection{T}"/>; otherwise, <see langword="false"/>.
        /// </returns>
        bool ICollection <AnimationInstance> .Contains(AnimationInstance item)
        {
            var animationInstance = item as AnimationInstance <T>;

            if (animationInstance == null)
            {
                return(false);
            }

            return(Contains(animationInstance));
        }
Example #17
0
        /// <summary>
        /// Removes all animations before the specified animation.
        /// </summary>
        /// <param name="animationInstance">The animation instance.</param>
        internal void RemoveBefore(AnimationInstance animationInstance)
        {
            Debug.Assert(animationInstance.IsRoot, "The animation instance in RemoveBefore needs to be a root instance.");
            Debug.Assert(_tempProperties.Count == 0, "Temporary list of animatable properties has not been reset.");
            Debug.Assert(_tempInstances.Count == 0, "Temporary list of animation instances has not been reset.");

            // Get all animated properties.
            animationInstance.GetAssignedProperties(_tempProperties);

            // Collect all animation instances before animationInstance.
            foreach (var property in _tempProperties)
            {
                if (property == null)
                {
                    continue;
                }

                int index;
                IAnimationCompositionChain compositionChain;
                _compositionChains.Get(property, out index, out compositionChain);

                if (compositionChain == null)
                {
                    continue;
                }

                var numberOfInstances = compositionChain.Count;
                for (int i = 0; i < numberOfInstances; i++)
                {
                    var instance     = compositionChain[i];
                    var rootInstance = instance.GetRoot();
                    if (rootInstance == animationInstance)
                    {
                        // Break inner loop, continue with next composition chain.
                        break;
                    }

                    if (!_tempInstances.Contains(rootInstance))
                    {
                        _tempInstances.Add(rootInstance);
                    }
                }
            }

            // Stop the found animation instances.
            foreach (var oldInstance in _tempInstances)
            {
                Remove(oldInstance);
            }

            _tempProperties.Clear();
            _tempInstances.Clear();
        }
Example #18
0
        /// <summary>
        /// Returns the root instance of an animation tree.
        /// </summary>
        /// <param name="animationInstance">The animation instance where to start the search.</param>
        /// <returns>The root instance.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="animationInstance"/> is <see langword="null"/>.
        /// </exception>
        public static AnimationInstance GetRoot(this AnimationInstance animationInstance)
        {
            if (animationInstance == null)
            {
                throw new ArgumentNullException("animationInstance");
            }

            while (animationInstance.Parent != null)
            {
                animationInstance = animationInstance.Parent;
            }

            return(animationInstance);
        }
Example #19
0
        /// <summary>
        /// Removes the animation transitions controlling the given animation instance.
        /// </summary>
        /// <param name="animationInstance">The animation instance.</param>
        private void StopTransitions(AnimationInstance animationInstance)
        {
            for (int i = _transitions.Count - 1; i >= 0; i--)
            {
                if (i >= _transitions.Count)
                {
                    // Multiple transitions were removed in the previous iteration.
                    // --> Skip index.
                    continue;
                }

                var transition = _transitions[i];
                if (transition.AnimationInstance == animationInstance)
                {
                    Remove(transition);
                }
            }
        }
Example #20
0
        /// <summary>
        /// Resets this animation instance.
        /// </summary>
        internal void Reset()
        {
            Debug.Assert(SpeedProperty.IsAnimated == false, "The speed ratio is still animated. Make sure that all animations are stopped before recycling an animation instance!");
            Debug.Assert(WeightProperty.IsAnimated == false, "The animation weight is still animated. Make sure that all animations are stopped before recycling an animation instance!");
            Debug.Assert(State == AnimationState.Stopped, "Animation instance is still running.");

            _animation          = null;
            _autoRecycleEnabled = false;
            _isPaused           = false;
            _isStateValid       = false;
            _parent             = null;
            _state = AnimationState.Stopped;
            _time  = null;
            _speedProperty.Value  = 1.0f;
            _weightProperty.Value = 1.0f;
            _children.Clear();
            Completed = null;

            // The animation instance requires a new ID: Increment RunCount.
            _runCount++;
        }
Example #21
0
        /// <summary>
        /// Unregisters the specified animation instance.
        /// </summary>
        /// <param name="animationInstance">The animation instance.</param>
        /// <remarks>
        /// <para>
        /// This method removes the specified animation tree from the animation system. If
        /// <see cref="AnimationInstance.AutoRecycleEnabled"/> is set on the root node of the animation
        /// tree, then all instances will be recycled.
        /// </para>
        /// <para>
        /// Adding and removing animation instances is usually controlled by
        /// <see cref="AnimationTransition"/> instances.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentException">
        /// Cannot remove <paramref name="animationInstance"/> from the animation system. The animation
        /// instance is not a root instance.
        /// </exception>
        internal void Remove(AnimationInstance animationInstance)
        {
            if (!animationInstance.IsRoot)
            {
                throw new ArgumentException("Cannot remove animation instance from animation system because it is not the root instance.");
            }

            // Remove animation instance.
            bool removed = _rootInstances.Remove(animationInstance);

            if (removed)
            {
                // Remove animation transitions, if any.
                StopTransitions(animationInstance);

                // Stop all secondary animations.
                animationInstance.StopSecondaryAnimations(this);

                // Remove animations from composition chains.
                animationInstance.RemoveFromCompositionChains(this);

                // Note: The instances are not unassigned from the properties.
                // Animations can be restart when using an animation controller.
                //animationInstance.Unassign();

                // Reset animation time (State = Stopped).
                animationInstance.Time = null;

                // Recycle instance, if no longer needed.
                if (animationInstance.AutoRecycleEnabled)
                {
                    // If the instance is in the completedInstances list, we need to wait
                    // until the Completed events were fired in ApplyAnimations().
                    if (!_completedInstances.Contains(animationInstance))
                    {
                        animationInstance.Recycle();
                    }
                }
            }
        }
Example #22
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <inheritdoc cref="ITimeline.CreateInstance"/>
        public AnimationInstance CreateInstance()
        {
            return(AnimationInstance <T> .Create(this));
        }
        /// <inheritdoc/>
        internal override void AddToCompositionChains(AnimationManager animationManager, HandoffBehavior handoffBehavior, AnimationInstance previousInstance)
        {
            var property = Property;

            if (property == null)
            {
                return;
            }

            // Get (or create) the animation composition chain.
            var compositionChain = animationManager.GetCompositionChain(property, Animation.Traits, true);

            if (handoffBehavior == HandoffBehavior.SnapshotAndReplace)
            {
                // Make a snapshot of the current animation value.
                compositionChain.TakeSnapshot();
            }

            if (handoffBehavior == HandoffBehavior.Replace || handoffBehavior == HandoffBehavior.SnapshotAndReplace)
            {
                // Remove all previous animations.
                if (compositionChain.Count > 0)
                {
                    var rootInstance = this.GetRoot();
                    for (int i = compositionChain.Count - 1; i >= 0; i--)
                    {
                        var animationInstance = compositionChain[i];

                        // Do not remove animation instances of the same animation tree!
                        if (animationInstance.GetRoot() != rootInstance)
                        {
                            compositionChain.RemoveAt(i);
                        }
                    }
                }
            }

            AnimationInstance <T> referenceInstance = null;

            if (previousInstance != null)
            {
                // previousInstance is either a single animation instance or an animation tree that
                // should be replaced. Find the instance that is assigned to the current property.
                referenceInstance = previousInstance.GetAssignedInstance(Property) as AnimationInstance <T>;
            }

            if (referenceInstance == null)
            {
                // Add at the end of the animation composition chain.
                compositionChain.Add(this);
            }
            else
            {
                // Insert in animation composition chain at a certain index.
                int index = compositionChain.IndexOf(referenceInstance);
                if (index == -1)
                {
                    // The referenceInstance has not been applied to the current property.
                    compositionChain.Add(this);
                }
                else
                {
                    // Insert after referenceInstance.
                    index++;

                    // Other animation instances of the same animation tree might have already been
                    // inserted after referenceInstance. To maintain the correct order we need to add
                    // this instance after the other instances of the same tree.
                    var rootInstance      = this.GetRoot();
                    var numberOfInstances = compositionChain.Count;
                    while (index < numberOfInstances && compositionChain[index].GetRoot() == rootInstance)
                    {
                        index++;
                    }

                    compositionChain.Insert(index, this);
                }
            }
        }
Example #24
0
 /// <summary>
 /// Replaces the specified animation with the new animation. The new animation takes effect
 /// immediately. The previous animation is stopped and removed from the animation system.
 /// </summary>
 /// <param name="previousAnimation">The animation that should be replaced.</param>
 /// <returns>The <see cref="AnimationTransition"/>.</returns>
 public static AnimationTransition Replace(AnimationInstance previousAnimation)
 {
     return(new ReplaceTransition(previousAnimation));
 }
Example #25
0
 /// <summary>
 /// Combines the new animation with existing animations by inserting the new animation after the
 /// specified animation into the composition chains. The new animation takes effect immediately.
 /// </summary>
 /// <param name="previousAnimation">
 /// The animation after which the new animation should be added.
 /// </param>
 /// <returns>The <see cref="AnimationTransition"/>.</returns>
 public static AnimationTransition Compose(AnimationInstance previousAnimation)
 {
     return(new ComposeTransition(previousAnimation));
 }
Example #26
0
 /// <summary>
 /// Applies this animation tree to the assigned properties.
 /// </summary>
 /// <param name="animationManager">The <see cref="AnimationManager"/>.</param>
 /// <param name="handoffBehavior">
 /// A value indicating how the new animations interact with existing ones.
 /// </param>
 /// <param name="previousInstance">
 /// Optional: The animation instance after which this animation instance will be added in the
 /// animation composition chain. If set to <see langword="null"/> this animation instance will
 /// be appended at the end of the composition chain. This parameter is only relevant when
 /// <paramref name="handoffBehavior"/> is <see cref="HandoffBehavior.Compose"/>.
 /// </param>
 internal virtual void AddToCompositionChains(AnimationManager animationManager, HandoffBehavior handoffBehavior, AnimationInstance previousInstance)
 {
     foreach (var child in Children)
     {
         child.AddToCompositionChains(animationManager, handoffBehavior, previousInstance);
     }
 }
Example #27
0
 /// <summary>
 /// Throws an <see cref="InvalidOperationException"/>.
 /// </summary>
 /// <param name="index">
 /// The zero-based index at which <paramref name="child"/> should be inserted.
 /// </param>
 /// <param name="child">The object to insert.</param>
 /// <exception cref="InvalidOperationException">
 /// Cannot add animation instance. The current animation instance cannot have children.
 /// </exception>
 protected override void InsertItem(int index, AnimationInstance child)
 {
     throw new InvalidOperationException("Cannot add animation instance. The current animation instance cannot have children.");
 }