Example #1
0
        /// <summary>
        /// Gets the cycle offset for a time value.
        /// </summary>
        /// <typeparam name="T">The type of animation value.</typeparam>
        /// <param name="time">The time value.</param>
        /// <param name="startTime">The start time.</param>
        /// <param name="endTime">The end time.</param>
        /// <param name="startValue">In: The animation value at <paramref name="startTime"/>.</param>
        /// <param name="endValue">In: The animation value at <paramref name="endTime"/>.</param>
        /// <param name="traits">The traits of the animation value.</param>
        /// <param name="loopBehavior">The post-loop behavior.</param>
        /// <param name="cycleOffset">
        /// Out: The cycle offset.
        /// </param>
        /// <remarks>
        /// The cycle offset is <see cref="IAnimationValueTraits{T}.SetIdentity"/> if the
        /// <see cref="LoopBehavior"/> is unequal to <see cref="LoopBehavior.CycleOffset"/> or if the
        /// <paramref name="time"/> is in the regular cycle (between the first and the last key frame).
        /// </remarks>
        internal static void GetCycleOffset <T>(TimeSpan time,
                                                TimeSpan startTime, TimeSpan endTime,
                                                ref T startValue, ref T endValue,
                                                IAnimationValueTraits <T> traits,
                                                LoopBehavior loopBehavior,
                                                ref T cycleOffset)
        {
            Debug.Assert(endTime > startTime, "Invalid start and end time.");
            TimeSpan length = endTime - startTime;

            // Handle cycle offset.
            if (loopBehavior == LoopBehavior.CycleOffset && length != TimeSpan.Zero)
            {
                traits.Invert(ref startValue, ref startValue);
                traits.Add(ref startValue, ref endValue, ref cycleOffset);

                if (time < startTime)
                {
                    long numberOfPeriods = (time.Ticks - endTime.Ticks) / length.Ticks;
                    Debug.Assert(numberOfPeriods < 0, "Negative number of periods expected.");
                    traits.Multiply(ref cycleOffset, (int)numberOfPeriods, ref cycleOffset);
                }
                else if (time > endTime)
                {
                    long numberOfPeriods = (time.Ticks - startTime.Ticks) / length.Ticks;
                    Debug.Assert(numberOfPeriods > 0, "Positive number of periods expected.");
                    traits.Multiply(ref cycleOffset, (int)numberOfPeriods, ref cycleOffset);
                }
                else
                {
                    traits.SetIdentity(ref cycleOffset);
                }
            }
        }
Example #2
0
            /// <summary>
            /// Animates the dependency value using an internally-managed clock.
            /// </summary>
            /// <param name="value">The animation's target value.</param>
            /// <param name="fn">The animation's easing function.</param>
            /// <param name="loopBehavior">A <see cref="LoopBehavior"/> value specifying the loop behavior of the animation.</param>
            /// <param name="duration">The animation's duration.</param>
            public void Animate(T value, EasingFunction fn, LoopBehavior loopBehavior, TimeSpan duration)
            {
                var clock      = SimpleClockPool.Instance.Retrieve(this);
                var clockValue = clock.Value;

                clockValue.SetLoopBehavior(loopBehavior);
                clockValue.SetDuration(duration);
                clockValue.Start();

                Animate(value, fn, clockValue);
            }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TimelineClip"/> class for the given timeline.
        /// </summary>
        /// <param name="timeline">The timeline.</param>
        public TimelineClip(ITimeline timeline)
        {
            Timeline = timeline;

            FillBehavior = FillBehavior.Hold;
            TargetObject = null;

            ClipStart      = null;
            ClipEnd        = null;
            ClipOffset     = TimeSpan.Zero;
            IsClipReversed = false;

            Delay        = TimeSpan.Zero;
            Duration     = null;
            Speed        = 1.0f;
            LoopBehavior = LoopBehavior.Constant;
        }
        /// <summary>
        /// Animates the specified dependency property to the specified target value using an internally-managed clock.
        /// </summary>
        /// <typeparam name="T">The type of value being animated.</typeparam>
        /// <param name="dp">A <see cref="DependencyProperty"/> instance which identifies the dependency property to animate.</param>
        /// <param name="value">The animation's target value.</param>
        /// <param name="fn">The animation's easing function.</param>
        /// <param name="loopBehavior">A <see cref="LoopBehavior"/> value specifying the loop behavior of the animation.</param>
        /// <param name="duration">The animation's duration.</param>
        public void Animate <T>(DependencyProperty dp, T value, EasingFunction fn, LoopBehavior loopBehavior, TimeSpan duration)
        {
            Contract.Require(dp, nameof(dp));

            if (dp.IsReadOnly)
            {
                throw new InvalidOperationException(PresentationStrings.DependencyPropertyIsReadOnly.Format(dp.Name));
            }

            if (!typeof(T).Equals(dp.PropertyType))
            {
                throw new InvalidCastException();
            }

            var wrapper = GetDependencyPropertyValue <T>(dp);

            wrapper.Animate(value, fn, loopBehavior, duration);
        }
Example #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AnimationClip{T}"/> class for the given
        /// animation.
        /// </summary>
        /// <param name="animation">The original animation.</param>
        public AnimationClip(IAnimation <T> animation)
        {
            Animation = animation;

            FillBehavior   = FillBehavior.Hold;
            IsAdditive     = false;
            TargetObject   = null;
            TargetProperty = null;

            ClipStart      = null;
            ClipEnd        = null;
            ClipOffset     = TimeSpan.Zero;
            IsClipReversed = false;

            Delay        = TimeSpan.Zero;
            Duration     = null;
            Speed        = 1.0f;
            LoopBehavior = LoopBehavior.Constant;
        }
Example #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Storyboard"/> class.
 /// </summary>
 /// <param name="uv">The Ultraviolet context.</param>
 /// <param name="loopBehavior">The storyboard's loop behavior.</param>
 public Storyboard(UltravioletContext uv, LoopBehavior loopBehavior = LoopBehavior.None)
 {
     this.targets      = new StoryboardTargetCollection(this);
     this.loopBehavior = loopBehavior;
 }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UvssStoryboard"/> class.
 /// </summary>
 /// <param name="name">The storyboard's name.</param>
 /// <param name="loopBehavior">The storyboard's loop behavior.</param>
 /// <param name="targets">The storyboard's collection of targets.</param>
 internal UvssStoryboard(String name, LoopBehavior loopBehavior, UvssStoryboardTargetCollection targets)
 {
     this.name = name;
     this.loopBehavior = loopBehavior;
     this.targets = targets;
 }
Example #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UvssStoryboard"/> class.
 /// </summary>
 /// <param name="name">The storyboard's name.</param>
 /// <param name="loopBehavior">The storyboard's loop behavior.</param>
 /// <param name="targets">The storyboard's collection of targets.</param>
 internal UvssStoryboard(String name, LoopBehavior loopBehavior, UvssStoryboardTargetCollection targets)
 {
     this.name         = name;
     this.loopBehavior = loopBehavior;
     this.targets      = targets;
 }
Example #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Storyboard"/> class.
 /// </summary>
 /// <param name="uv">The Ultraviolet context.</param>
 /// <param name="loopBehavior">The storyboard's loop behavior.</param>
 public Storyboard(UltravioletContext uv, LoopBehavior loopBehavior = LoopBehavior.None)
 {
     this.targets = new StoryboardTargetCollection(this);
     this.loopBehavior = loopBehavior;
 }
 /// <summary>
 /// Sets the clock's loop behavior.
 /// </summary>
 /// <param name="loopBehavior">The clock's loop behavior.</param>
 internal void SetLoopBehavior(LoopBehavior loopBehavior)
 {
     this.loopBehavior = loopBehavior;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="SimpleClock"/> class.
 /// </summary>
 /// <param name="loopBehavior">The clock's loop behavior.</param>
 /// <param name="duration">The clock's duration.</param>
 public SimpleClock(LoopBehavior loopBehavior, TimeSpan duration)
 {
     this.loopBehavior = loopBehavior;
     this.duration     = duration;
 }
Example #12
0
    /// <summary>
    /// Initializes a new instance of the <see cref="TimelineClip"/> class for the given timeline.
    /// </summary>
    /// <param name="timeline">The timeline.</param>
    public TimelineClip(ITimeline timeline)
    {
      Timeline = timeline;

      FillBehavior = FillBehavior.Hold;
      TargetObject = null;

      ClipStart = null;
      ClipEnd = null;
      ClipOffset = TimeSpan.Zero;
      IsClipReversed = false;

      Delay = TimeSpan.Zero;
      Duration = null;
      Speed = 1.0f;
      LoopBehavior = LoopBehavior.Constant;
    }
Example #13
0
 /// <summary>
 /// Sets the clock's loop behavior.
 /// </summary>
 /// <param name="loopBehavior">The clock's loop behavior.</param>
 internal void SetLoopBehavior(LoopBehavior loopBehavior)
 {
     this.loopBehavior = loopBehavior;
 }
Example #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SimpleClock"/> class.
 /// </summary>
 /// <param name="loopBehavior">The clock's loop behavior.</param>
 /// <param name="duration">The clock's duration.</param>
 public SimpleClock(LoopBehavior loopBehavior, TimeSpan duration)
 {
     this.loopBehavior = loopBehavior;
     this.duration = duration;
 }
Example #15
0
        /// <summary>
        /// Handles different loop behaviors by changing the given time value so that it lies between
        /// start and end time.
        /// </summary>
        /// <param name="time">The time value.</param>
        /// <param name="startTime">The start time.</param>
        /// <param name="endTime">The end time.</param>
        /// <param name="loopBehavior">The loop behavior.</param>
        /// <param name="loopedTime">The adjusted time value.</param>
        /// <returns>
        /// <see langword="true"/> if the current cycle requires an offset; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        internal static bool LoopParameter(TimeSpan time, TimeSpan startTime, TimeSpan endTime, LoopBehavior loopBehavior, out TimeSpan loopedTime)
        {
            Debug.Assert(endTime >= startTime, "Invalid start and end time.");
            TimeSpan length = endTime - startTime;

            if (length == TimeSpan.Zero)
            {
                loopedTime = startTime;
                return(false);
            }

            if (time < startTime)
            {
                #region ----- Pre-loop -----

                // Handle pre-loop. For some loop types we return immediately. For some
                // we adjust the time value.
                if (loopBehavior == LoopBehavior.Constant)
                {
                    loopedTime = startTime;
                    return(false);
                }

                long numberOfPeriods = (endTime.Ticks - time.Ticks) / length.Ticks;
                if (loopBehavior == LoopBehavior.Cycle || loopBehavior == LoopBehavior.CycleOffset)
                {
                    loopedTime = new TimeSpan(time.Ticks + length.Ticks * numberOfPeriods);
                    return(loopBehavior == LoopBehavior.CycleOffset);
                }

                Debug.Assert(loopBehavior == LoopBehavior.Oscillate);

                if (numberOfPeriods % 2 != 0)
                {
                    // odd = mirrored
                    loopedTime = new TimeSpan(startTime.Ticks + endTime.Ticks - (time.Ticks + length.Ticks * numberOfPeriods));
                    return(false);
                }

                // even = not mirrored
                loopedTime = new TimeSpan(time.Ticks + length.Ticks * numberOfPeriods);
                return(false);

                #endregion
            }

            if (time > endTime)
            {
                #region ----- Post-loop -----

                // Handle post-loop. For some loop types we return immediately. For some
                // we adjust the time value.
                if (loopBehavior == LoopBehavior.Constant)
                {
                    loopedTime = endTime;
                    return(false);
                }

                long numberOfPeriods = (time.Ticks - startTime.Ticks) / length.Ticks;
                if (loopBehavior == LoopBehavior.Cycle || loopBehavior == LoopBehavior.CycleOffset)
                {
                    loopedTime = new TimeSpan(time.Ticks - length.Ticks * numberOfPeriods);
                    return(loopBehavior == LoopBehavior.CycleOffset);
                }

                Debug.Assert(loopBehavior == LoopBehavior.Oscillate);

                if (numberOfPeriods % 2 != 0)
                {
                    // odd = mirrored
                    loopedTime = new TimeSpan(endTime.Ticks - (time.Ticks - startTime.Ticks - length.Ticks * numberOfPeriods));
                    return(false);
                }

                // even = not mirrored
                loopedTime = new TimeSpan(time.Ticks - length.Ticks * numberOfPeriods);
                return(false);

                #endregion
            }

            loopedTime = time;
            return(false);
        }
Example #16
0
        /// <summary>
        /// Determines whether the given time value corresponds to a mirrored oscillation loop.
        /// </summary>
        /// <param name="time">The time value.</param>
        /// <param name="startTime">The start time.</param>
        /// <param name="endTime">The end time.</param>
        /// <param name="loopBehavior">The loop behavior.</param>
        /// <returns>
        /// <see langword="true"/> if the time value is in a mirrored oscillation loop; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        internal static bool IsInMirroredOscillation(TimeSpan time, TimeSpan startTime, TimeSpan endTime, LoopBehavior loopBehavior)
        {
            Debug.Assert(endTime >= startTime, "Invalid start and end time.");
            TimeSpan length = endTime - startTime;

            if (length == TimeSpan.Zero)
            {
                return(false);
            }

            if (loopBehavior == LoopBehavior.Oscillate)
            {
                if (time < startTime)
                {
                    return(((startTime.Ticks - time.Ticks) / length.Ticks) % 2 == 0);
                }

                if (time > endTime)
                {
                    return(((time.Ticks - endTime.Ticks) / length.Ticks) % 2 == 0);
                }
            }

            return(false);
        }