Пример #1
0
    /// <summary>
    /// Gets the animation composition chain of the given animatable property and type.
    /// </summary>
    /// <typeparam name="T">The type of the property.</typeparam>
    /// <param name="property">
    /// The animatable property. Can be <see langword="null"/>.
    /// </param>
    /// <param name="traits">
    /// The animation value traits.
    /// </param>
    /// <param name="createIfNotFound">
    /// If set to <see langword="true"/> a new animation composition chain will be created 
    /// automatically when necessary. (<paramref name="property"/> must not be 
    /// <see langword="null"/>.)
    /// </param>
    /// <returns>
    /// The <see cref="IAnimationCompositionChain"/> of the animated property.
    /// </returns>
    /// <exception cref="ArgumentNullException">
    /// <paramref name="createIfNotFound"/> is set, but <paramref name="property"/> or 
    /// <paramref name="traits"/> is <see langword="null"/>.
    /// </exception>
    internal AnimationCompositionChain<T> GetCompositionChain<T>(IAnimatableProperty<T> property, IAnimationValueTraits<T> traits, bool createIfNotFound)
    {
      if (property == null)
      {
        if (createIfNotFound)
          throw new ArgumentNullException("property", "The property must not be null if a new animation composition chain should be created.");

        return null;
      }

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

      AnimationCompositionChain<T> compositionChain = untypedCompositionChain as AnimationCompositionChain<T>;
      if (compositionChain == null && createIfNotFound)
      {
        if (traits == null)
          throw new ArgumentNullException("traits", "The animation value traits need to be set when a new animation composition chain should be created.");

        // Create new animation composition chain.
        compositionChain = AnimationCompositionChain<T>.Create(property, traits);
        _compositionChains.Insert(index, compositionChain);
      }

      return compositionChain;
    }
Пример #2
0
        /// <summary>
        /// 在指定的属性上开始创建基于表达式的动画。
        /// </summary>
        /// <param name="targetProperty"></param>
        /// <returns></returns>
        public ExpressionAnimationFluentContext AnimateWithExpression(IAnimatableProperty targetProperty)
        {
            var result = new ExpressionAnimationFluentContext(this, Target.Compositor.CreateExpressionAnimation(), targetProperty.PropertyPath);

            _animations.Add(result);
            return(result);
        }
Пример #3
0
 /// <summary>
 /// Assigns this animation tree to the specified property.
 /// </summary>
 /// <param name="property">The animatable property.</param>
 internal virtual void AssignTo(IAnimatableProperty property)
 {
     foreach (var child in Children)
     {
         child.AssignTo(property);
     }
 }
Пример #4
0
        /// <inheritdoc/>
        public void Apply()
        {
            IAnimatableProperty <T> property = Property;

            if (property == null)
            {
                // The animated object has been garbage collected.
                return;
            }

            if (property is ImmediateAnimatableProperty <T> )
            {
                // Special: ImmediateAnimatableProperty<T> are set in Update().
                // All other properties are set in Apply();
                return;
            }

            if (Items.Count > 0)
            {
                // Apply output of chain to property.
                SetProperty(property);
            }
            else
            {
                // All animations have stopped or were removed.
                ResetProperty(property);
            }
        }
Пример #5
0
        /// <inheritdoc/>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="value"/> or <paramref name="property"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// The value of <paramref name="property"/> must not be <see langword="null"/>.
        /// </exception>
        public void Set(ref SkeletonPose value, IAnimatableProperty <SkeletonPose> property)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (property == null)
            {
                throw new ArgumentNullException("property");
            }

            var animationValue = property.AnimationValue;

            if (animationValue == null)
            {
                if (property.HasBaseValue)
                {
                    // The SkeletonPose will be recycled in Reset().
                    Create(ref value, out animationValue);
                    property.AnimationValue = animationValue;
                }
                else
                {
                    throw new ArgumentException("The value of the property must not be null. This exception usually occurs when an IAnimatableProperty<SkeletonPose> is being animated, but the value of the property is null. A SkeletonPose must be set before the property can be animated.");
                }
            }

            SkeletonHelper.Copy(value, animationValue);
        }
Пример #6
0
        /// <summary>
        /// Creates a new instance of the <see cref="AnimationCompositionChain{T}"/> class.
        /// </summary>
        /// <param name="property">The property that should be animated.</param>
        /// <param name="traits">The animation value traits.</param>
        /// <exception cref="ArgumentNullException">
        /// Either <paramref name="property"/> or <paramref name="traits"/> is <see langword="null"/>.
        /// </exception>
        public static AnimationCompositionChain <T> Create(IAnimatableProperty <T> property, IAnimationValueTraits <T> traits)
        {
            var compositionChain = Pool.Obtain();

            compositionChain.Initialize(property, traits);
            return(compositionChain);
        }
Пример #7
0
        /// <inheritdoc/>
        internal override bool IsAssignableTo(IAnimatableProperty property)
        {
            // Note: In this case we do not check whether Animation.TargetProperty matches property.Name.
            // This method should only be called to explicitly assign the animation to the given property.

            return(property is IAnimatableProperty <T>);
        }
Пример #8
0
 /// <summary>
 /// Writes the property value.
 /// </summary>
 /// <param name="property">The property.</param>
 private void SetProperty(IAnimatableProperty <T> property)
 {
     // Important: AnimationValue should be set BEFORE IsAnimated.
     // This is relevant because a property (such as a DigitalRune.Game.GameProperty<T>)
     // could raise Changed-events. If we call the setters in the wrong order the
     // property might raise too many Changed-events.
     Traits.Set(ref _value, property);
     property.IsAnimated = true;
 }
Пример #9
0
    /// <inheritdoc/>
    public bool IsAnimated(IAnimatableProperty animatableProperty)
    {
      if (animatableProperty == null)
        throw new ArgumentNullException("animatableProperty");

      int index;
      IAnimationCompositionChain compositionChain;
      _compositionChains.Get(animatableProperty, out index, out compositionChain);
      return compositionChain != null;
    }
Пример #10
0
    /// <inheritdoc/>
    public AnimationController CreateController(ITimeline animation, IAnimatableProperty targetProperty)
    {
      if (targetProperty == null)
        throw new ArgumentNullException("targetProperty");
      if (animation == null)
        throw new ArgumentNullException("animation");

      var animationInstance = animation.CreateInstance();
      animationInstance.AssignTo(targetProperty);
      return new AnimationController(this, animationInstance);
    }
Пример #11
0
 /// <summary>
 /// Resets the property.
 /// </summary>
 /// <param name="property">The property.</param>
 private void ResetProperty(IAnimatableProperty <T> property)
 {
     // Important: AnimationValue should be set AFTER IsAnimated.
     // Again this is relevant to avoid too many Changed-events.
     property.IsAnimated = false;
     if (property.HasBaseValue)
     {
         // If the property has a base value we should reset the animation value
         // to avoid memory leaks.
         Traits.Reset(property);
     }
 }
Пример #12
0
        /// <inheritdoc/>
        internal override void AssignTo(IAnimatableProperty property)
        {
            // Note: In this case we do not check whether Animation.TargetProperty matches property.Name.
            // This method should only be called to explicitly assign the animation to the given property.

            var typedProperty = property as IAnimatableProperty <T>;

            if (typedProperty != null)
            {
                Property = typedProperty;
            }
        }
Пример #13
0
        /// <summary>
        /// Determines whether this animation tree is assigned to the specified property.
        /// </summary>
        /// <param name="property">The animatable property.</param>
        /// <returns>
        /// <see langword="true"/> if this animation instance (or one of its children) is assigned to
        /// <paramref name="property"/>; otherwise, <see langword="false"/>.
        /// </returns>
        internal virtual bool IsAssignedTo(IAnimatableProperty property)
        {
            foreach (var child in Children)
            {
                if (child.IsAssignedTo(property))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #14
0
        ///// <summary>
        ///// Unassigns this animation trees. (Removes all references to the currently assigned
        ///// properties.)
        ///// </summary>
        //internal virtual void Unassign()
        //{
        //  foreach (var child in Children)
        //    child.Unassign();
        //}


        /// <summary>
        /// Checks whether this animation tree is assigned to a certain animated property and returns
        /// the animation instance.
        /// </summary>
        /// <param name="property">The animatable property.</param>
        /// <returns>
        /// The animation instance that is assigned to <paramref name="property"/>.
        /// <see langword="null"/> if neither this instance nor its children are assigned to the
        /// property. If multiple children are assigned to the property the last found child is
        /// returned.
        /// </returns>
        internal virtual AnimationInstance GetAssignedInstance(IAnimatableProperty property)
        {
            for (int i = Children.Count - 1; i >= 0; i--)
            {
                var child            = Children[i];
                var assignedInstance = child.GetAssignedInstance(property);
                if (assignedInstance != null)
                {
                    return(assignedInstance);
                }
            }

            return(null);
        }
Пример #15
0
    /// <inheritdoc/>
    public void UpdateAndApplyAnimation(IAnimatableProperty property)
    {
      int index;
      IAnimationCompositionChain compositionChain;
      _compositionChains.Get(property, out index, out compositionChain);
      if (compositionChain != null)
      {
        compositionChain.Update(this);
        compositionChain.Apply();

        // Remove empty animation composition chains.
        if (compositionChain.IsEmpty)
          _compositionChains.RemoveAt(index);
      }
    }
Пример #16
0
        /// <inheritdoc/>
        public AnimationController StartAnimation(ITimeline animation, IAnimatableProperty targetProperty, AnimationTransition transition)
        {
            if (targetProperty == null)
            {
                throw new ArgumentNullException("targetProperty");
            }
            if (animation == null)
            {
                throw new ArgumentNullException("animation");
            }

            var animationInstance = animation.CreateInstance();

            animationInstance.AssignTo(targetProperty);
            StartAnimation(animationInstance, transition);
            return(new AnimationController(this, animationInstance));
        }
Пример #17
0
        /// <summary>
        /// Takes a snapshot of the current animation value.
        /// </summary>
        /// <remarks>
        /// The first animation instance in the composition chain will receive snapshot as its source
        /// value instead of the properties' base value.
        /// </remarks>
        /// <seealso cref="ClearSnapshot"/>
        public void TakeSnapshot()
        {
            IAnimatableProperty <T> property = Property;

            if (property != null)
            {
                if (Items.Count > 0)
                {
                    // Take snapshot of last animation value.
                    if (!_hasSnapshot)
                    {
                        // Allocate object, if necessary.
                        _traits.Create(ref _value, out _snapshot);
                        _hasSnapshot = true;
                    }

                    _traits.Copy(ref _value, ref _snapshot);
                }
                else if (property.HasBaseValue)
                {
                    // No animations: Take snapshot of base value.
                    if (!_hasSnapshot)
                    {
                        // Allocate object, if necessary.
                        _traits.Create(ref _value, out _snapshot);
                        _hasSnapshot = true;
                    }

                    var baseValue = property.BaseValue;
                    _traits.Copy(ref baseValue, ref _snapshot);
                }
                else
                {
                    // The property does not have animations nor a base value.
                    // Clear the snapshot. The animations will use the default
                    // value (AnimationValueTraits.Identity).
                    ClearSnapshot();
                }
            }
            else
            {
                // The animatable property is recycled while the animation is started.
                // Clear snapshot just to be safe. (Should never occur in practice.
                ClearSnapshot();
            }
        }
Пример #18
0
        /// <inheritdoc/>
        public void Reset(IAnimatableProperty <SkeletonPose> property)
        {
            // ReSharper disable once RedundantIfElseBlock

            if (property.HasBaseValue)
            {
                // Recycle SkeletonPose which has been allocated in Set().
                var animationValue = property.AnimationValue;
                property.AnimationValue = null;
                Recycle(ref animationValue);
            }
            else
            {
                // IAnimatableProperty<SkeletonPose> does not have a base value. The animation value
                // does not have to be set to null.
                // --> Do nothing.
            }
        }
    /// <summary>
    /// Initializes the <see cref="AnimationCompositionChain{T}"/>.
    /// </summary>
    /// <param name="property">The property that should be animated.</param>
    /// <param name="traits">The animation value traits.</param>
    /// <exception cref="ArgumentNullException">
    /// Either <paramref name="property"/> or <paramref name="traits"/> is <see langword="null"/>.
    /// </exception>
    public void Initialize(IAnimatableProperty<T> property, IAnimationValueTraits<T> traits)
    {
      Debug.Assert(Count == 0, "Animation composition chain has not been reset properly.");
      Debug.Assert(_weakReference.Target == null, "Animation composition chain has not been reset properly.");
      Debug.Assert(_hasSnapshot == false, "Animation composition chain has not been reset properly.");
      Debug.Assert(_traits == null, "Animation composition chain has not been reset properly.");

      if (property == null)
        throw new ArgumentNullException("property");
      if (traits == null)
        throw new ArgumentNullException("traits");

      _weakReference.Target = property;
      _traits = traits;

      var reference = (property.HasBaseValue) ? property.BaseValue : property.AnimationValue;
      traits.Create(ref reference, out _value);
    }
Пример #20
0
        protected EasyTransitionAnimationFluentContext <T> Animate <T>(IAnimatableProperty <T> targetProperty)
        {
            AnimationFluentContext result;

            switch (targetProperty.AnimationType)
            {
            case AnimationTypes.Single:
                result = new ScalarEasyTransitionAnimationFluentContext(this, Target.Compositor.CreateScalarKeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.Vector2:
                result = new Vector2EasyTransitionAnimationFluentContext(this, Target.Compositor.CreateVector2KeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.Vector3:
                result = new Vector3EasyTransitionAnimationFluentContext(this, Target.Compositor.CreateVector3KeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.Vector4:
                result = new Vector4EasyTransitionAnimationFluentContext(this, Target.Compositor.CreateVector4KeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.Color:
                result = new ColorEasyTransitionAnimationFluentContext(this, Target.Compositor.CreateColorKeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.Quaternion:
                result = new QuaternionEasyTransitionAnimationFluentContext(this, Target.Compositor.CreateQuaternionKeyFrameAnimation(), targetProperty.PropertyPath);
                _animations.Add(result);
                return((EasyTransitionAnimationFluentContext <T>)result);

            case AnimationTypes.NotSupport:
            default:
                throw new InvalidOperationException("");
            }
        }
Пример #21
0
    /// <inheritdoc/>
    public void StopAnimation(IAnimatableProperty animatedProperty)
    {
      int index;
      IAnimationCompositionChain compositionChain;
      _compositionChains.Get(animatedProperty, out index, out compositionChain);

      if (compositionChain != null)
      {
        for (int i = compositionChain.Count - 1; i >= 0; i--)
        {
          if (i >= compositionChain.Count)
          {
            // Multiple instances were removed in the previous iteration.
            // --> Skip index.
            continue;
          }

          var animationInstance = compositionChain[i].GetRoot();
          Remove(animationInstance);
        }
      }
    }
Пример #22
0
        ///// <inheritdoc/>
        //internal override void Unassign()
        //{
        //  Property = null;
        //}


        /// <inheritdoc/>
        internal override AnimationInstance GetAssignedInstance(IAnimatableProperty property)
        {
            return(IsAssignedTo(property) ? this : null);
        }
Пример #23
0
        /// <inheritdoc/>
        internal override bool IsAssignedTo(IAnimatableProperty property)
        {
            var assignedProperty = Property;

            return(assignedProperty != null && assignedProperty == property);
        }
Пример #24
0
 /// <inheritdoc/>
 public void Reset(IAnimatableProperty <Color> property)
 {
 }
Пример #25
0
 /// <inheritdoc/>
 public void Set(ref Vector2 value, IAnimatableProperty <Vector2> property)
 {
     property.AnimationValue = value;
 }
Пример #26
0
 /// <inheritdoc/>
 public void Set(ref Color value, IAnimatableProperty <Color> property)
 {
     property.AnimationValue = value;
 }
Пример #27
0
 // Reset the animation value of the given property.
 public void Reset(IAnimatableProperty <string> property)
 {
 }
Пример #28
0
 // Set an animatable property to the given value.
 public void Set(ref string value, IAnimatableProperty <string> property)
 {
     property.AnimationValue = value;
 }
Пример #29
0
        /// <summary>
        /// Gets the composition chain for the specified <paramref name="property"/>.
        /// </summary>
        /// <param name="property">The animatable property.</param>
        /// <param name="index">
        /// The index of the composition chain in this collection. If no suitable composition chain is
        /// found, this is the index where a new composition chain should be inserted.
        /// </param>
        /// <param name="chain">
        /// The found composition chain. <see langword="null"/> if no suitable chain was found.
        /// </param>
        public void Get(IAnimatableProperty property, out int index, out IAnimationCompositionChain chain)
        {
            // Abort if property is null.
            if (property == null)
            {
                index = -1;
                chain = null;
                return;
            }

            // Composition chains for immediate animatable properties are stored at the front - unsorted.
            if (property is IImmediateAnimatableProperty)
            {
                // Search immediates in sequential order.
                for (int i = 0; i < _numberOfImmediates; i++)
                {
                    var candidate = _compositionChains[i];
                    if (candidate.Property == property)
                    {
                        index = i;
                        chain = candidate;
                        return;
                    }
                }

                index = 0;
                chain = null;
                return;
            }

            // The other chains are stored after the immediates, sorted by the hash codes of the
            // properties.
            uint hashCode = (uint)property.GetHashCode();

            // Search for non-immediates using binary search.
            int start = _numberOfImmediates;
            var numberOfCompositionChains = _compositionChains.Count;
            int end = numberOfCompositionChains - 1;

            while (start <= end)
            {
                index = start + (end - start >> 1);
                long comparison = (long)_hashCodes[index] - (long)hashCode;
                if (comparison == 0)
                {
                    chain = _compositionChains[index];
                    if (chain.Property == property)
                    {
                        return;
                    }

                    // Found the correct hash value. Must search vicinity because there could be more
                    // properties with this hash code.

                    // Search forward.
                    int savedIndex = index;
                    index++;
                    while (index < numberOfCompositionChains && _hashCodes[index] == hashCode)
                    {
                        chain = _compositionChains[index];
                        if (chain.Property == property)
                        {
                            return;
                        }
                        index++;
                    }

                    // Search backward.
                    index = savedIndex - 1;
                    while (index >= _numberOfImmediates && _hashCodes[index] == hashCode)
                    {
                        chain = _compositionChains[index];
                        if (chain.Property == property)
                        {
                            return;
                        }
                        index--;
                    }

                    index = savedIndex;
                    chain = null;
                    return;
                }

                if (comparison < 0)
                {
                    Debug.Assert(hashCode > _hashCodes[index]);
                    start = index + 1;
                }
                else
                {
                    Debug.Assert(hashCode < _hashCodes[index]);
                    end = index - 1;
                }
            }

            index = start;
            chain = null;
            return;
        }
Пример #30
0
 /// <inheritdoc/>
 public void Reset(IAnimatableProperty <Vector2> property)
 {
 }