public static void DoScale(TransfromNeededEventArg e, Animation animation)
 {
     var rect = e.ClientRectangle;
     var center = new PointF(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
     e.Matrix.Translate(center.X, center.Y);
     var kx = 1f - animation.ScaleCoeff.X * e.CurrentTime;
     var ky = 1f - animation.ScaleCoeff.X * e.CurrentTime;
     if (Math.Abs(kx) <= 0.001f) kx = 0.001f;
     if (Math.Abs(ky) <= 0.001f) ky = 0.001f;
     e.Matrix.Scale(kx, ky);
     e.Matrix.Translate(-center.X, -center.Y);
 }
 public void Add(Animation a)
 {
     SlideCoeff = new PointF(SlideCoeff.X + a.SlideCoeff.X, SlideCoeff.Y + a.SlideCoeff.Y);
     RotateCoeff += a.RotateCoeff;
     RotateLimit += a.RotateLimit;
     ScaleCoeff = new PointF(ScaleCoeff.X + a.ScaleCoeff.X, ScaleCoeff.Y + a.ScaleCoeff.Y);
     TransparencyCoeff += a.TransparencyCoeff;
     LeafCoeff += a.LeafCoeff;
     MosaicShift = new PointF(MosaicShift.X + a.MosaicShift.X, MosaicShift.Y + a.MosaicShift.Y);
     MosaicCoeff = new PointF(MosaicCoeff.X + a.MosaicCoeff.X, MosaicCoeff.Y + a.MosaicCoeff.Y);
     MosaicSize += a.MosaicSize;
     BlindCoeff = new PointF(BlindCoeff.X + a.BlindCoeff.X, BlindCoeff.Y + a.BlindCoeff.Y);
     TimeCoeff += a.TimeCoeff;
     Padding += a.Padding;
 }
        public static void DoBlind(NonLinearTransfromNeededEventArg e, Animation animation)
        {
            if (animation.BlindCoeff == PointF.Empty)
                return;

            var pixels = e.Pixels;
            var sx = e.ClientRectangle.Width;
            var sy = e.ClientRectangle.Height;
            var s = e.Stride;
            var kx = animation.BlindCoeff.X;
            var ky = animation.BlindCoeff.Y;
            var a = (int)((sx * kx + sy * ky) * (1 - e.CurrentTime));

            for (int x = 0; x < sx; x++)
                for (int y = 0; y < sy; y++)
                {
                    int i = y * s + x * bytesPerPixel;
                    var d = x * kx + y * ky - a;
                    if (d >= 0)
                        pixels[i + 3] = (byte)0;
                }
        }
 private Controller CreateDoubleBitmap(Control control, AnimateMode mode, Animation animation, Rectangle clipRect)
 {
     var controller = new Controller(control, mode, animation, TimeStep, clipRect);
     controller.TransfromNeeded += OnTransformNeeded;
     if (NonLinearTransfromNeeded != null)
         controller.NonLinearTransfromNeeded += OnNonLinearTransfromNeeded;
     controller.MouseDown += OnMouseDown;
     controller.DoubleBitmap.Cursor = Cursor;
     controller.FramePainted += OnFramePainted;
     return controller;
 }
        /// <summary>
        /// Adds the contol to animation queue.
        /// </summary>
        /// <param name="control">Target control</param>
        /// <param name="mode">Animation mode</param>
        /// <param name="parallel">Allows to animate it same time as other animations</param>
        /// <param name="animation">Personal animation</param> 
        public void AddToQueue(Control control, AnimateMode mode, bool parallel = true, Animation animation = null, Rectangle clipRectangle = default(Rectangle))
        {
            if (animation == null)
                animation = DefaultAnimation;

            if (control is IFakeControl)
            {
                control.Visible = false;
                return;
            }

            var item = new QueueItem() { animation = animation, control = control, IsActive = parallel, mode = mode, clipRectangle = clipRectangle };

            //check visible state
            switch (mode)
            {
                case AnimateMode.Show:
                    if (control.Visible)//already showed
                    {
                        OnCompleted(new QueueItem { control = control, mode = mode });
                        return;
                    }
                    break;
                case AnimateMode.Hide:
                    if (!control.Visible)//already hidden
                    {
                        OnCompleted(new QueueItem { control = control, mode = mode });
                        return;
                    }
                    break;
            }

            //add to queue
            lock (queue)
                queue.Add(item);
            lock (requests)
                requests.Add(item);
        }
        /// <summary>
        /// It makes snapshot of the control before updating. It requires EndUpdate calling.
        /// </summary>
        /// <param name="control">Target control</param>
        /// <param name="parallel">Allows to animate it same time as other animations</param>
        /// <param name="animation">Personal animation</param>
        /// <param name="clipRectangle">Clip rectangle for animation</param>
        public void BeginUpdate(Control control, bool parallel = false, Animation animation = null, Rectangle clipRectangle = default(Rectangle))
        {
            AddToQueue(control, AnimateMode.BeginUpdate, parallel, animation, clipRectangle);

            bool wait = false;
            do
            {
                wait = false;
                lock (queue)
                    foreach (var item in queue)
                        if (item.control == control && item.mode == AnimateMode.BeginUpdate)
                        {
                            if (item.controller == null)
                                wait = true;
                        }

                if (wait)
                    Application.DoEvents();

            } while (wait);
        }
 /// <summary>
 /// Hides the control and waits while animation will be completed. As result the control will be hidden with animation.
 /// </summary>
 /// <param name="control">Target control</param>
 /// <param name="parallel">Allows to animate it same time as other animations</param>
 /// <param name="animation">Personal animation</param>
 public void HideSync(Control control, bool parallel = false, Animation animation = null)
 {
     Hide(control, parallel, animation);
     WaitAnimation(control);
 }
 /// <summary>
 /// Hides the control. As result the control will be hidden with animation.
 /// </summary>
 /// <param name="control">Target control</param>
 /// <param name="parallel">Allows to animate it same time as other animations</param>
 /// <param name="animation">Personal animation</param>
 public void Hide(Control control, bool parallel = false, Animation animation = null)
 {
     AddToQueue(control, AnimateMode.Hide, parallel, animation);
 }
 /// <summary>
 /// Shows the control and waits while animation will be completed. As result the control will be shown with animation.
 /// </summary>
 /// <param name="control">Target control</param>
 /// <param name="parallel">Allows to animate it same time as other animations</param>
 /// <param name="animation">Personal animation</param>
 public void ShowSync(Control control, bool parallel = false, Animation animation = null)
 {
     Show(control, parallel, animation);
     WaitAnimation(control);
 }
        protected virtual void Init()
        {
            AnimationType = AnimationType.VertSlide;
            DefaultAnimation = new Animation();
            MaxAnimationTime = 1500;
            TimeStep = 0.02f;
            Interval = 10;

            Disposed += new EventHandler(Animator_Disposed);

            timer = new Timer();
            timer.Tick += new EventHandler(timer_Tick);
            timer.Interval = 1;
            timer.Start();
        }
        public Controller(Control control, AnimateMode mode, Animation animation, float timeStep, Rectangle controlClipRect)
        {
            if (control is Form)
                DoubleBitmap = new DoubleBitmapForm();
            else
                DoubleBitmap = new DoubleBitmapControl();

            (DoubleBitmap as IFakeControl).FramePainting += OnFramePainting;
            (DoubleBitmap as IFakeControl).FramePainted += OnFramePainting;
            (DoubleBitmap as IFakeControl).TransfromNeeded += OnTransfromNeeded;
            DoubleBitmap.MouseDown += OnMouseDown;

            this.animation = animation;
            this.AnimatedControl = control;
            this.mode = mode;

            this.CustomClipRect = controlClipRect;

            if (mode == AnimateMode.Show || mode == AnimateMode.BeginUpdate)
                timeStep = -timeStep;

            this.TimeStep = timeStep * (animation.TimeCoeff == 0f ? 1f : animation.TimeCoeff);
            if (this.TimeStep == 0f)
                timeStep = 0.01f;

            try
            {
                switch (mode)
                {
                    case AnimateMode.Hide:
                        {
                            BgBmp = GetBackground(control);
                            (DoubleBitmap as IFakeControl).InitParent(control, animation.Padding);
                            ctrlBmp = GetForeground(control);
                            DoubleBitmap.Visible = true;
                            control.Visible = false;
                        }
                        break;

                    case AnimateMode.Show:
                        {
                            BgBmp = GetBackground(control);
                            (DoubleBitmap as IFakeControl).InitParent(control, animation.Padding);
                            DoubleBitmap.Visible = true;
                            DoubleBitmap.Refresh();
                            control.Visible = true;
                            ctrlBmp = GetForeground(control);
                        }
                        break;

                    case AnimateMode.BeginUpdate:
                    case AnimateMode.Update:
                        {
                            (DoubleBitmap as IFakeControl).InitParent(control, animation.Padding);
                            BgBmp = GetBackground(control, true);
                            DoubleBitmap.Visible = true;

                        }
                        break;
                }
            }
            catch
            {
                Dispose();
            }
#if debug
            BgBmp.Save("c:\\bgBmp.png");
            if (ctrlBmp != null)
                ctrlBmp.Save("c:\\ctrlBmp.png");
#endif

            CurrentTime = timeStep > 0 ? animation.MinTime : animation.MaxTime;
        }
        public static void DoMosaic(NonLinearTransfromNeededEventArg e, Animation animation, ref Point[] buffer, ref byte[] pixelsBuffer)
        {
            if (animation.MosaicCoeff == PointF.Empty || animation.MosaicSize == 0)
                return;

            var pixels = e.Pixels;
            var sx = e.ClientRectangle.Width;
            var sy = e.ClientRectangle.Height;
            var s = e.Stride;
            var a = e.CurrentTime;
            var count = pixels.Length;
            var opacity = 1 - e.CurrentTime;
            if (opacity < 0f) opacity = 0f;
            if (opacity > 1f) opacity = 1f;
            var mkx = animation.MosaicCoeff.X;
            var mky = animation.MosaicCoeff.Y;

            if (buffer == null)
            {
                buffer = new Point[pixels.Length];
                for (int i = 0; i < pixels.Length; i++)
                    buffer[i] = new Point((int)(mkx * (rnd.NextDouble() - 0.5)), (int)(mky * (rnd.NextDouble() - 0.5)));
            }

            if (pixelsBuffer == null)
                pixelsBuffer = (byte[])pixels.Clone();


            for (int i = 0; i < count; i += bytesPerPixel)
            {
                pixels[i + 0] = 255;
                pixels[i + 1] = 255;
                pixels[i + 2] = 255;
                pixels[i + 3] = 0;
            }

            var ms = animation.MosaicSize;
            var msx = animation.MosaicShift.X;
            var msy = animation.MosaicShift.Y;

            for (int y = 0; y < sy; y++)
                for (int x = 0; x < sx; x++)
                {
                    int yi = (y / ms);
                    int xi = (x / ms);
                    int i = y * s + x * bytesPerPixel;
                    int j = yi * s + xi * bytesPerPixel;

                    var newX = x + (int)(a * (buffer[j].X + xi * msx));
                    var newY = y + (int)(a * (buffer[j].Y + yi * msy));

                    if (newX >= 0 && newX < sx)
                        if (newY >= 0 && newY < sy)
                        {
                            int newI = newY * s + newX * bytesPerPixel;
                            pixels[newI + 0] = pixelsBuffer[i + 0];
                            pixels[newI + 1] = pixelsBuffer[i + 1];
                            pixels[newI + 2] = pixelsBuffer[i + 2];
                            pixels[newI + 3] = (byte)(pixelsBuffer[i + 3] * opacity);
                        }
                }
        }
 public static void DoSlide(TransfromNeededEventArg e, Animation animation)
 {
     var k = e.CurrentTime;
     e.Matrix.Translate(-e.ClientRectangle.Width * k * animation.SlideCoeff.X, -e.ClientRectangle.Height * k * animation.SlideCoeff.Y);
 }
        public static void DoRotate(TransfromNeededEventArg e, Animation animation)
        {
            var rect = e.ClientRectangle;
            var center = new PointF(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);

            e.Matrix.Translate(center.X, center.Y);
            if (e.CurrentTime > animation.RotateLimit)
                e.Matrix.Rotate(360 * (e.CurrentTime - animation.RotateLimit) * animation.RotateCoeff);
            e.Matrix.Translate(-center.X, -center.Y);
        }
        public static void DoTransparent(NonLinearTransfromNeededEventArg e, Animation animation)
        {
            if (animation.TransparencyCoeff == 0f)
                return;
            var opacity = 1f - animation.TransparencyCoeff * e.CurrentTime;
            if (opacity < 0f)
                opacity = 0f;
            if (opacity > 1f)
                opacity = 1f;

            var pixels = e.Pixels;
            for (int counter = 0; counter < pixels.Length; counter += bytesPerPixel)
                pixels[counter + 3] = (byte)(pixels[counter + 3] * opacity);
        }
        public static void DoLeaf(NonLinearTransfromNeededEventArg e, Animation animation)
        {
            if (animation.LeafCoeff == 0f)
                return;

            var pixels = e.Pixels;
            var sx = e.ClientRectangle.Width;
            var sy = e.ClientRectangle.Height;
            var s = e.Stride;
            var a = (int)((sx + sy) * (1 - e.CurrentTime * e.CurrentTime));

            var count = pixels.Length;

            for (int x = 0; x < sx; x++)
                for (int y = 0; y < sy; y++)
                {
                    int i = y * s + x * bytesPerPixel;
                    if (x + y >= a)
                    {
                        var newX = a - y;
                        var newY = a - x;
                        var d = a - x - y;
                        if (d < -20)
                            d = -20;

                        int newI = newY * s + newX * bytesPerPixel;
                        if (newX >= 0 && newY >= 0)
                            if (newI >= 0 && newI < count)
                                if (pixels[i + 3] > 0)
                                {
                                    pixels[newI + 0] = (byte)Math.Min(255, d + 250 + pixels[i + 0] / 10);
                                    pixels[newI + 1] = (byte)Math.Min(255, d + 250 + pixels[i + 1] / 10);
                                    pixels[newI + 2] = (byte)Math.Min(255, d + 250 + pixels[i + 2] / 10);
                                    pixels[newI + 3] = 230;
                                }
                        pixels[i + 3] = (byte)(0);
                    }
                }
        }