Exemple #1
0
        static void AnimateKineticInternal(IAnimatable self, string name, Func <double, double, bool> callback, double velocity, double drag, Action?finished = null)
        {
            var key = new AnimatableKey(self, name);

            AbortKinetic(key);

            double sign = velocity / Math.Abs(velocity);

            velocity = Math.Abs(velocity);

            int tick = Ticker.Default.Insert(step =>
            {
                long ms = step;

                velocity -= drag * ms;
                velocity  = Math.Max(0, velocity);

                var result = false;
                if (velocity > 0)
                {
                    result = callback(sign * velocity * ms, velocity);
                }

                if (!result)
                {
                    finished?.Invoke();
                    s_kinetics.Remove(key);
                }
                return(result);
            });

            s_kinetics[key] = tick;
        }
Exemple #2
0
        static void AnimateInternal <T>(IAnimatable self, string name, Func <double, T> transform, Action <T> callback,
                                        uint rate, uint length, Easing?easing, Action <T, bool>?finished, Func <bool>?repeat)
        {
            var key = new AnimatableKey(self, name);

            AbortAnimation(key);

            Action <double>       step  = f => callback(transform(f));
            Action <double, bool>?final = null;

            if (finished != null)
            {
                final = (f, b) => finished(transform(f), b);
            }


            var tweener = new Tweener(length, rate);

            tweener.Handle        = key;
            tweener.ValueUpdated += HandleTweenerUpdated;
            tweener.Finished     += HandleTweenerFinished;

            var info = new Info(rate, length, easing ?? Easing.Linear, tweener, step, new WeakReference <IAnimatable>(self));

            info.Finished     = final;
            info.Repeat       = repeat;
            s_animations[key] = info;

            info.Callback(0.0f);
            tweener.Start();
        }
Exemple #3
0
        static void AbortKinetic(AnimatableKey key)
        {
            if (!s_kinetics.ContainsKey(key))
            {
                return;
            }

            Ticker.Default.Remove(s_kinetics[key]);
            s_kinetics.Remove(key);
        }
Exemple #4
0
        public static bool AbortAnimation(this IAnimatable self, string handle)
        {
            var key = new AnimatableKey(self, handle);

            if (!s_animations.ContainsKey(key) && !s_kinetics.ContainsKey(key))
            {
                return(false);
            }

            Action abort = () =>
            {
                AbortAnimation(key);
                AbortKinetic(key);
            };

            DoAction(self, abort);

            return(true);
        }
Exemple #5
0
        protected bool Equals(AnimatableKey other)
        {
            if (!string.Equals(Handle, other.Handle))
            {
                return(false);
            }

            IAnimatable?thisAnimatable;

            if (!Animatable.TryGetTarget(out thisAnimatable))
            {
                return(false);
            }

            IAnimatable?thatAnimatable;

            if (!other.Animatable.TryGetTarget(out thatAnimatable))
            {
                return(false);
            }

            return(Equals(thisAnimatable, thatAnimatable));
        }
Exemple #6
0
        static void AbortAnimation(AnimatableKey key)
        {
            // If multiple animations on the same view with the same name (IOW, the same AnimatableKey) are invoked
            // asynchronously (e.g., from the `[Animate]To` methods in `ViewExtensions`), it's possible to get into
            // a situation where after invoking the `Finished` handler below `s_animations` will have a new `Info`
            // object in it with the same AnimatableKey. We need to continue cancelling animations until that is no
            // longer the case; thus, the `while` loop.

            // If we don't cancel all of the animations popping in with this key, `AnimateInternal` will overwrite one
            // of them with the new `Info` object, and the overwritten animation will never complete; any `await` for
            // it will never return.

            while (s_animations.ContainsKey(key))
            {
                Info info = s_animations[key];

                s_animations.Remove(key);

                info.Tweener.ValueUpdated -= HandleTweenerUpdated;
                info.Tweener.Finished     -= HandleTweenerFinished;
                info.Tweener.Stop();
                info.Finished?.Invoke(1.0f, true);
            }
        }
Exemple #7
0
        public static bool AnimationIsRunning(this IAnimatable self, string handle)
        {
            var key = new AnimatableKey(self, handle);

            return(s_animations.ContainsKey(key));
        }