Full Code of falahati/WinFormAnimation for AI

master 326ec7812f96 cached
50 files
292.0 KB
66.5k tokens
311 symbols
1 requests
Download .txt
Showing preview only (308K chars total). Download the full file or copy to clipboard to get everything.
Repository: falahati/WinFormAnimation
Branch: master
Commit: 326ec7812f96
Files: 50
Total size: 292.0 KB

Directory structure:
gitextract_akg5khpk/

├── .gitignore
├── LICENSE
├── README.md
├── WinFormAnimation/
│   ├── AnimationFunctions.cs
│   ├── Animator.cs
│   ├── Animator2D.cs
│   ├── Animator3D.cs
│   ├── AnimatorStatus.cs
│   ├── FPSLimiterKnownValues.cs
│   ├── FloatExtensions.cs
│   ├── IAnimator.cs
│   ├── KnownAnimationFunctions.cs
│   ├── Path.cs
│   ├── Path2D.cs
│   ├── Path2DExtensions.cs
│   ├── Path3D.cs
│   ├── Path3DExtensions.cs
│   ├── PathExtensions.cs
│   ├── SafeInvoker.cs
│   ├── SafeInvoker`1.cs
│   ├── Timer.cs
│   ├── WinFormAnimation.csproj
│   ├── float2D.cs
│   ├── float3D.cs
│   └── readme.txt
├── WinFormAnimation.Samples/
│   ├── Demo1.Designer.cs
│   ├── Demo1.cs
│   ├── Demo1.resx
│   ├── Demo2.Designer.cs
│   ├── Demo2.cs
│   ├── Demo2.resx
│   ├── Demo3.Designer.cs
│   ├── Demo3.cs
│   ├── Demo3.resx
│   ├── Demo4.Designer.cs
│   ├── Demo4.cs
│   ├── Demo4.resx
│   ├── MainForm.Designer.cs
│   ├── MainForm.cs
│   ├── MainForm.resx
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── WinFormAnimation.Samples.csproj
│   └── app.config
├── WinFormAnimation.sln
└── WinFormAnimation.sln.DotSettings

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
[Bb]in/
[Oo]bj/

# mstest test results
TestResults

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.sln.docstates

# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc
*.vssscc
.builds

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf

# Visual Studio profiler
*.psess
*.vsp
*.vspx

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*

# NCrunch
*.ncrunch*
.*crunch*.local.xml

# Installshield output folder 
[Ee]xpress

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish

# Publish Web Output
*.Publish.xml

# NuGet Packages Directory
packages

# Windows Azure Build Output
csx
*.build.csdef

# Windows Store app package directory
AppPackages/

# Others
[Bb]in
[Oo]bj
sql
TestResults
[Tt]est[Rr]esult*
*.Cache
ClientBin
[Ss]tyle[Cc]op.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects

# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
*.nupkg
/.vs/*
*.pfx


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2016 Soroush

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# <img src="WinFormAnimation/Icon.png" width="42" alt="Icon"> WinForm Animation Library [.Net3.5+]
[![](https://img.shields.io/github/license/falahati/WinFormAnimation.svg?style=flat-square)](https://github.com/falahati/WinFormAnimation/blob/master/LICENSE)
[![](https://img.shields.io/github/commit-activity/y/falahati/WinFormAnimation.svg?style=flat-square)](https://github.com/falahati/WinFormAnimation/commits/master)
[![](https://img.shields.io/github/issues/falahati/WinFormAnimation.svg?style=flat-square)](https://github.com/falahati/WinFormAnimation/issues)

A simple library for animating controls/values in .Net WinForm (.Net 3.5 and later). Key frame (Path) based and fully customizable.

*Please note that even though this library designed for WinForm but its usage is not limited to WinForm and can be used in other environments. Only reference of the library is to 'System.Drawing' name space.*

## How to get
[![](https://img.shields.io/nuget/dt/WinFormAnimation.svg?style=flat-square)](https://www.nuget.org/packages/WinFormAnimation)
[![](https://img.shields.io/nuget/v/WinFormAnimation.svg?style=flat-square)](https://www.nuget.org/packages/WinFormAnimation)

This library is available as a NuGet package at [nuget.org](https://www.nuget.org/packages/WinFormAnimation/).

## Help me fund my own Death Star

[![](https://img.shields.io/badge/crypto-CoinPayments-8a00a3.svg?style=flat-square)](https://www.coinpayments.net/index.php?cmd=_donate&reset=1&merchant=820707aded07845511b841f9c4c335cd&item_name=Donate&currency=USD&amountf=20.00000000&allow_amount=1&want_shipping=0&allow_extra=1)
[![](https://img.shields.io/badge/shetab-ZarinPal-8a00a3.svg?style=flat-square)](https://zarinp.al/@falahati)
[![](https://img.shields.io/badge/usd-Paypal-8a00a3.svg?style=flat-square)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ramin.graphix@gmail.com&lc=US&item_name=Donate&no_note=0&cn=&curency_code=USD&bn=PP-DonationsBF:btn_donateCC_LG.gif:NonHosted)

**--OR--**

You can always donate your time by contributing to the project or by introducing it to others..

## Documentation

* `Float2D`: A class containing two `float` values as Vertical and Horizontal coordinates representing a point in a 2D plane.
* `Float3D`: A class containing three `float` values as Vertical, Horizontal and Depth coordinates representing a point in a 3D plane.
* `Path`: A class containing a `float` starting and a `float` ending point for a single dimensional animation as well as duration and the function to control the animation.
* `Path2D`: A class containing a `Float2D` starting and a `Float2D` ending point for a two dimensional animation as well as duration and the function to control the animation.
* `Path3D`: A class containing a `Float3D` starting and a `Float3D` ending point for a three dimensional animation as well as duration and the function to control the animation.
* `Animator`: A class for animating an array of `Path` objects. This class is one of the main classes and starting points of a basic animation.
* `Animator2D`: A class for animating an array of `Path2D` objects. This class is one of the main classes and starting points of a basic animation.
* `Animator2D`: A class for animating an array of `Path3D` objects. This class is one of the main classes and starting points of a basic animation.
* `SafeInvoker`: A class holding a reference to a function to invoke in the correct thread, detected by a `Control` object passed to it. Useful for easier UI manipulations.
* `SafeInvoker<T>`: Same as `SafeInvoker` class but with a generic argument for the function to invoke.

For full documentation of the classes and their members, please take a look at our doxygen page at [falahati.github.io](https://falahati.github.io/WinFormAnimation/doxygen).

## Basic examples
### ONE DIMENSIONAL ANIMATION OF A PROPERTY
Following code animates a property named `Value` of a `ProgressBar` named `pb_progress` in 5 seconds from zero to one hundred:
```C#
new Animator(new Path(0, 100, 5000))
    .Play(pb_progress, Animator.KnownProperties.Value);
```

### TWO DIMENSIONAL ANIMATION OF A PROPERTY
Following code animates a `Form` in two paths. First one moves the `Form` from (0, -100) to (100, 200) and second path waits for 3 seconds and then moved the `Form` to its initial location in 2 seconds. (`this` is a `Form`)
```C#
new Animator2D(
        new Path2D(0, 100, -100, 200, 5000).ContinueTo(this.Location.ToFloat2D(), 2000, 3000))
    .Play(this, Animator2D.KnownProperties.Location);
```

### THREE DIMENSIONAL ANIMATION OF A PROPERTY
Following code animates a property named `CustomColor` of a `Control` named `c_customLabel` in 2 seconds and after a delay of 1 second using the `AnimationFunctions.CubicEaseIn` function and with maximum of 10 frames per second.
```C#
new Animator3D(
        new Path3D(Color.Blue.ToFloat3D(), Color.Red.ToFloat3D(), 2000, 1000, AnimationFunctions.CubicEaseIn), 
        FPSLimiterKnownValues.LimitTen)
    .Play(c_customLabel, "CustomColor");
```


### KEYFRAMES
There are extension methods for `Path`, `Path2D`, `Path3D` and their arrays to let you continue the path easily and define the key frames as fast as possible. For example, following code moves a `Control` named `c_control` in a rectangular path infinitely:
```C#
new Animator2D(
    new Path2D(new Float2D(100, 100), new Float2D(200, 100), 1000)
        .ContinueTo(new Float2D(200, 200), 1000)
        .ContinueTo(new Float2D(100, 200), 1000)
        .ContinueTo(new Float2D(100, 100), 1000))
{
    Repeat = true
}.Play(c_control, Animator2D.KnownProperties.Location);
```

### CALLBACKS
It is possible to define a custom callback as frame handler as well as defining a call back to handle the end of the animation. Following example will call a method named `CustomSetMethod` for setting new values and handle the frames, and starts the animation in reverse path after its end for one more time:

```C#
var animator = new Animator(new Path(100, 200, 1000).ContinueTo(400, 500));
animator.Play(new SafeInvoker<float>(CustomSetMethod), new SafeInvoker(() =>
{
    animator.Paths = animator.Paths.Select(path => path.Reverse()).Reverse().ToArray();
    animator.Play(new SafeInvoker<float>(CustomSetMethod));
}));
```

## Demo
Check the 'WinFormAnimation.Samples' project for simple usage examples.
![Screenshot](/screenshot.gif?raw=true "Screenshot")

## License
The MIT License (MIT)

Copyright (c) 2016-2020 Soroush Falahati

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: WinFormAnimation/AnimationFunctions.cs
================================================
using System;

namespace WinFormAnimation
{
    /// <summary>
    ///     The functions gallery for animation
    /// </summary>
    public static class AnimationFunctions
    {
        /// <summary>
        ///     The base delegate for defining new animation functions.
        /// </summary>
        /// <param name="time">
        ///     The time of the animation.
        /// </param>
        /// <param name="beginningValue">
        ///     The starting value.
        /// </param>
        /// <param name="changeInValue">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="duration">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public delegate float Function(float time, float beginningValue, float changeInValue, float duration);

        /// <summary>
        ///     Returns a function delegate based on the the passed known animation function
        /// </summary>
        /// <param name="knownFunction">The animation function</param>
        /// <returns>Animation fucntion delegate</returns>
        public static Function FromKnown(KnownAnimationFunctions knownFunction)
        {
            switch (knownFunction)
            {
                case KnownAnimationFunctions.CubicEaseIn:
                    return CubicEaseIn;
                case KnownAnimationFunctions.CubicEaseInOut:
                    return CubicEaseInOut;
                case KnownAnimationFunctions.CubicEaseOut:
                    return CubicEaseOut;
                case KnownAnimationFunctions.Linear:
                    return Linear;
                case KnownAnimationFunctions.CircularEaseInOut:
                    return CircularEaseInOut;
                case KnownAnimationFunctions.CircularEaseIn:
                    return CircularEaseIn;
                case KnownAnimationFunctions.CircularEaseOut:
                    return CircularEaseOut;
                case KnownAnimationFunctions.QuadraticEaseIn:
                    return QuadraticEaseIn;
                case KnownAnimationFunctions.QuadraticEaseOut:
                    return QuadraticEaseOut;
                case KnownAnimationFunctions.QuadraticEaseInOut:
                    return QuadraticEaseInOut;
                case KnownAnimationFunctions.QuarticEaseIn:
                    return QuarticEaseIn;
                case KnownAnimationFunctions.QuarticEaseOut:
                    return QuarticEaseOut;
                case KnownAnimationFunctions.QuarticEaseInOut:
                    return QuarticEaseInOut;
                case KnownAnimationFunctions.QuinticEaseInOut:
                    return QuinticEaseInOut;
                case KnownAnimationFunctions.QuinticEaseIn:
                    return QuinticEaseIn;
                case KnownAnimationFunctions.QuinticEaseOut:
                    return QuinticEaseOut;
                case KnownAnimationFunctions.SinusoidalEaseIn:
                    return SinusoidalEaseIn;
                case KnownAnimationFunctions.SinusoidalEaseOut:
                    return SinusoidalEaseOut;
                case KnownAnimationFunctions.SinusoidalEaseInOut:
                    return SinusoidalEaseInOut;
                case KnownAnimationFunctions.ExponentialEaseIn:
                    return ExponentialEaseIn;
                case KnownAnimationFunctions.ExponentialEaseOut:
                    return ExponentialEaseOut;
                case KnownAnimationFunctions.ExponentialEaseInOut:
                    return ExponentialEaseInOut;
                default:
                    throw new ArgumentOutOfRangeException(nameof(knownFunction), knownFunction,
                        "The passed animation function is unknown.");
            }
        }


        /// <summary>
        ///     The cubic ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CubicEaseIn(float t, float b, float c, float d)
        {
            t /= d;
            return c*t*t*t + b;
        }

        /// <summary>
        ///     The cubic ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CubicEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1)
                return c/2*t*t*t + b;

            t -= 2;
            return c/2*(t*t*t + 2) + b;
        }

        /// <summary>
        ///     The cubic ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CubicEaseOut(float t, float b, float c, float d)
        {
            t /= d;
            t--;
            return c*(t*t*t + 1) + b;
        }

        /// <summary>
        ///     The linear animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float Linear(float t, float b, float c, float d)
        {
            return c*t/d + b;
        }

        /// <summary>
        ///     The circular ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CircularEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1)
                return (float) (-c/2*(Math.Sqrt(1 - t*t) - 1) + b);
            t -= 2;
            return (float) (c/2*(Math.Sqrt(1 - t*t) + 1) + b);
        }


        /// <summary>
        ///     The circular ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CircularEaseIn(float t, float b, float c, float d)
        {
            t /= d;
            return (float) (-c*(Math.Sqrt(1 - t*t) - 1) + b);
        }


        /// <summary>
        ///     The circular ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float CircularEaseOut(float t, float b, float c, float d)
        {
            t /= d;
            t--;
            return (float) (c*Math.Sqrt(1 - t*t) + b);
        }


        /// <summary>
        ///     The quadratic ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuadraticEaseIn(float t, float b, float c, float d)
        {
            t /= d;
            return c*t*t + b;
        }


        /// <summary>
        ///     The quadratic ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuadraticEaseOut(float t, float b, float c, float d)
        {
            t /= d;
            return -c*t*(t - 2) + b;
        }


        /// <summary>
        ///     The quadratic ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuadraticEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1) return c/2*t*t + b;
            t--;
            return -c/2*(t*(t - 2) - 1) + b;
        }

        /// <summary>
        ///     The quartic ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuarticEaseIn(float t, float b, float c, float d)
        {
            t /= d;
            return c*t*t*t*t + b;
        }

        /// <summary>
        ///     The quartic ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuarticEaseOut(float t, float b, float c, float d)
        {
            t /= d;
            t--;
            return -c*(t*t*t*t - 1) + b;
        }

        /// <summary>
        ///     The quartic ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuarticEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1) return c/2*t*t*t*t + b;
            t -= 2;
            return -c/2*(t*t*t*t - 2) + b;
        }

        /// <summary>
        ///     The quintic ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuinticEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1) return c/2*t*t*t*t*t + b;
            t -= 2;
            return c/2*(t*t*t*t*t + 2) + b;
        }

        /// <summary>
        ///     The quintic ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuinticEaseIn(float t, float b, float c, float d)
        {
            t /= d;
            return c*t*t*t*t*t + b;
        }

        /// <summary>
        ///     The quintic ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float QuinticEaseOut(float t, float b, float c, float d)
        {
            t /= d;
            t--;
            return c*(t*t*t*t*t + 1) + b;
        }

        /// <summary>
        ///     The sinusoidal ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float SinusoidalEaseIn(float t, float b, float c, float d)
        {
            return (float) (-c*Math.Cos(t/d*(Math.PI/2)) + c + b);
        }

        /// <summary>
        ///     The sinusoidal ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float SinusoidalEaseOut(float t, float b, float c, float d)
        {
            return (float) (c*Math.Sin(t/d*(Math.PI/2)) + b);
        }

        /// <summary>
        ///     The sinusoidal ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float SinusoidalEaseInOut(float t, float b, float c, float d)
        {
            return (float) (-c/2*(Math.Cos(Math.PI*t/d) - 1) + b);
        }

        /// <summary>
        ///     The exponential ease-in animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float ExponentialEaseIn(float t, float b, float c, float d)
        {
            return (float) (c*Math.Pow(2, 10*(t/d - 1)) + b);
        }

        /// <summary>
        ///     The exponential ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float ExponentialEaseOut(float t, float b, float c, float d)
        {
            return (float) (c*(-Math.Pow(2, -10*t/d) + 1) + b);
        }


        /// <summary>
        ///     The exponential ease-in and ease-out animation function.
        /// </summary>
        /// <param name="t">
        ///     The time of the animation.
        /// </param>
        /// <param name="b">
        ///     The starting value.
        /// </param>
        /// <param name="c">
        ///     The different between starting and ending value.
        /// </param>
        /// <param name="d">
        ///     The duration of the animations.
        /// </param>
        /// <returns>
        ///     The calculated current value of the animation
        /// </returns>
        public static float ExponentialEaseInOut(float t, float b, float c, float d)
        {
            t /= d/2;
            if (t < 1)
                return (float) (c/2*Math.Pow(2, 10*(t - 1)) + b);
            t--;
            return (float) (c/2*(-Math.Pow(2, -10*t) + 2) + b);
        }
    }
}

================================================
FILE: WinFormAnimation/Animator.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace WinFormAnimation
{
    /// <summary>
    ///     The one dimensional animator class, useful for animating raw values
    /// </summary>
    public class Animator : IAnimator
    {
        /// <summary>
        ///     The known one dimensional properties of WinForm controls
        /// </summary>
        public enum KnownProperties
        {
            /// <summary>
            ///     The property named 'Value' of the object
            /// </summary>
            Value,

            /// <summary>
            ///     The property named 'Text' of the object
            /// </summary>
            Text,

            /// <summary>
            ///     The property named 'Caption' of the object
            /// </summary>
            Caption,

            /// <summary>
            ///     The property named 'BackColor' of the object
            /// </summary>
            BackColor,

            /// <summary>
            ///     The property named 'ForeColor' of the object
            /// </summary>
            ForeColor,

            /// <summary>
            ///     The property named 'Opacity' of the object
            /// </summary>
            Opacity
        }

        private readonly List<Path> _paths = new List<Path>();

        private readonly List<Path> _tempPaths = new List<Path>();

        private readonly Timer _timer;

        private bool _tempReverseRepeat;

        /// <summary>
        ///     The callback to get invoked at the end of the animation
        /// </summary>
        protected SafeInvoker EndCallback;

        /// <summary>
        ///     The callback to get invoked at each frame
        /// </summary>
        protected SafeInvoker<float> FrameCallback;

        /// <summary>
        ///     The target object to change the property of
        /// </summary>
        protected object TargetObject;

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        public Animator()
            : this(new Path[] {})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator(FPSLimiterKnownValues fpsLimiter)
            : this(new Path[] {}, fpsLimiter)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        public Animator(Path path)
            : this(new[] {path})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator(Path path, FPSLimiterKnownValues fpsLimiter)
            : this(new[] {path}, fpsLimiter)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        public Animator(Path[] paths) : this(paths, FPSLimiterKnownValues.LimitThirty)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator(Path[] paths, FPSLimiterKnownValues fpsLimiter)
        {
            CurrentStatus = AnimatorStatus.Stopped;
            _timer = new Timer(Elapsed, fpsLimiter);
            Paths = paths;
        }

        /// <summary>
        ///     Gets or sets an array containing the list of paths of the animation
        /// </summary>
        /// <exception cref="InvalidOperationException">Animation is running</exception>
        public Path[] Paths
        {
            get { return _paths.ToArray(); }
            set
            {
                if (CurrentStatus == AnimatorStatus.Stopped)
                {
                    _paths.Clear();
                    _paths.AddRange(value);
                }
                else
                {
                    throw new InvalidOperationException("Animation is running.");
                }
            }
        }

        /// <summary>
        ///     Gets the currently active path.
        /// </summary>
        public Path ActivePath { get; private set; }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation after its ending
        /// </summary>
        public virtual bool Repeat { get; set; }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation in reverse after its ending.
        /// </summary>
        public virtual bool ReverseRepeat { get; set; }

        /// <summary>
        ///     Gets the current status of the animation
        /// </summary>
        public virtual AnimatorStatus CurrentStatus { get; private set; }

        /// <summary>
        ///     Pause the animation
        /// </summary>
        public virtual void Pause()
        {
            if (CurrentStatus != AnimatorStatus.OnHold && CurrentStatus != AnimatorStatus.Playing)
                return;
            _timer.Stop();
            CurrentStatus = AnimatorStatus.Paused;
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        public virtual void Play(object targetObject, string propertyName)
        {
            Play(targetObject, propertyName, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public virtual void Play(object targetObject, string propertyName, SafeInvoker endCallback)
        {
            TargetObject = targetObject;
            var prop = TargetObject.GetType()
                .GetProperty(
                    propertyName,
                    BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance |
                    BindingFlags.SetProperty);
            if (prop == null) return;
            Play(
                new SafeInvoker<float>(
                    value => prop.SetValue(TargetObject, Convert.ChangeType(value, prop.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter)
        {
            Play(targetObject, propertySetter, null);
        }


        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter, SafeInvoker endCallback)
        {
            if (propertySetter == null)
                return;
            TargetObject = targetObject;

            var property =
                ((propertySetter.Body as MemberExpression) ??
                 (((UnaryExpression) propertySetter.Body).Operand as MemberExpression))?.Member as PropertyInfo;
            if (property == null)
            {
                throw new ArgumentException(nameof(propertySetter));
            }

            Play(
                new SafeInvoker<float>(
                    value => property.SetValue(TargetObject, Convert.ChangeType(value, property.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Resume the animation from where it paused
        /// </summary>
        public virtual void Resume()
        {
            if (CurrentStatus == AnimatorStatus.Paused)
            {
                _timer.Resume();
            }
        }

        /// <summary>
        ///     Stops the animation and resets its status, resume is no longer possible
        /// </summary>
        public virtual void Stop()
        {
            _timer.Stop();
            lock (_tempPaths)
            {
                _tempPaths.Clear();
            }
            ActivePath = null;
            CurrentStatus = AnimatorStatus.Stopped;
            _tempReverseRepeat = false;
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        public virtual void Play(object targetObject, KnownProperties property)
        {
            Play(targetObject, property, null);
        }


        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public virtual void Play(object targetObject, KnownProperties property, SafeInvoker endCallback)
        {
            Play(targetObject, property.ToString(), endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        public virtual void Play(SafeInvoker<float> frameCallback)
        {
            Play(frameCallback, (SafeInvoker<float>) null);
        }


        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public virtual void Play(SafeInvoker<float> frameCallback, SafeInvoker endCallback)
        {
            Stop();
            FrameCallback = frameCallback;
            EndCallback = endCallback;
            _timer.ResetClock();
            lock (_tempPaths)
            {
                _tempPaths.AddRange(_paths);
            }
            _timer.Start();
        }

        private void Elapsed(ulong millSinceBeginning = 0)
        {
            while (true)
            {
                lock (_tempPaths)
                {
                    if (_tempPaths != null && ActivePath == null && _tempPaths.Count > 0)
                    {
                        while (ActivePath == null)
                        {
                            if (_tempReverseRepeat)
                            {
                                ActivePath = _tempPaths.LastOrDefault();
                                _tempPaths.RemoveAt(_tempPaths.Count - 1);
                            }
                            else
                            {
                                ActivePath = _tempPaths.FirstOrDefault();
                                _tempPaths.RemoveAt(0);
                            }
                            _timer.ResetClock();
                            millSinceBeginning = 0;
                        }
                    }
                    var ended = ActivePath == null;
                    if (ActivePath != null)
                    {
                        if (!_tempReverseRepeat && millSinceBeginning < ActivePath.Delay)
                        {
                            CurrentStatus = AnimatorStatus.OnHold;
                            return;
                        }
                        if (millSinceBeginning - (!_tempReverseRepeat ? ActivePath.Delay : 0) <= ActivePath.Duration)
                        {
                            if (CurrentStatus != AnimatorStatus.Playing)
                            {
                                CurrentStatus = AnimatorStatus.Playing;
                            }
                            var value = ActivePath.Function(_tempReverseRepeat ? ActivePath.Duration - millSinceBeginning : millSinceBeginning - ActivePath.Delay, ActivePath.Start, ActivePath.Change, ActivePath.Duration);
                            FrameCallback.Invoke(value);
                            return;
                        }
                        if (CurrentStatus == AnimatorStatus.Playing)
                        {
                            if (_tempPaths.Count == 0)
                            {
                                // For the last path, we make sure that control is in end point
                                FrameCallback.Invoke(_tempReverseRepeat ? ActivePath.Start : ActivePath.End);
                                ended = true;
                            }
                            else
                            {
                                if ((_tempReverseRepeat && ActivePath.Delay > 0) || !_tempReverseRepeat && _tempPaths.FirstOrDefault()?.Delay > 0)
                                {
                                    // Or if the next path or this one in revese order has a delay
                                    FrameCallback.Invoke(_tempReverseRepeat ? ActivePath.Start : ActivePath.End);
                                }
                            }
                        }
                        if (_tempReverseRepeat && (millSinceBeginning - ActivePath.Duration) < ActivePath.Delay)
                        {
                            CurrentStatus = AnimatorStatus.OnHold;
                            return;
                        }
                        ActivePath = null;
                    }
                    if (!ended)
                    {
                        return;
                    }
                }
                if (Repeat)
                {
                    lock (_tempPaths)
                    {
                        _tempPaths.AddRange(_paths);
                        _tempReverseRepeat = ReverseRepeat && !_tempReverseRepeat;
                    }
                    millSinceBeginning = 0;
                    continue;
                }
                Stop();
                EndCallback?.Invoke();
                break;
            }
        }
    }
}

================================================
FILE: WinFormAnimation/Animator2D.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace WinFormAnimation
{
    /// <summary>
    ///     The two dimensional animator class, useful for animating values
    ///     created from two underlying values
    /// </summary>
    public class Animator2D : IAnimator
    {
        /// <summary>
        ///     The known two dimensional properties of WinForm controls
        /// </summary>
        public enum KnownProperties
        {
            /// <summary>
            ///     The property named 'Size' of the object
            /// </summary>
            Size,

            /// <summary>
            ///     The property named 'Location' of the object
            /// </summary>
            Location
        }

        private readonly List<Path2D> _paths = new List<Path2D>();


        /// <summary>
        ///     The callback to get invoked at the end of the animation
        /// </summary>
        protected SafeInvoker EndCallback;

        /// <summary>
        ///     The callback to get invoked at each frame
        /// </summary>
        protected SafeInvoker<Float2D> FrameCallback;

        /// <summary>
        ///     A boolean value indicating if the EndInvoker already invoked
        /// </summary>
        protected bool IsEnded;

        /// <summary>
        ///     The target object to change the property of
        /// </summary>
        protected object TargetObject;

        /// <summary>
        ///     The latest horizontal value
        /// </summary>
        protected float? XValue;

        /// <summary>
        ///     The latest vertical value
        /// </summary>
        protected float? YValue;


        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        public Animator2D()
            : this(new Path2D[] {})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator2D(FPSLimiterKnownValues fpsLimiter)
            : this(new Path2D[] {}, fpsLimiter)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        public Animator2D(Path2D path)
            : this(new[] {path})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator2D(Path2D path, FPSLimiterKnownValues fpsLimiter)
            : this(new[] {path}, fpsLimiter)
        {
        }


        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        public Animator2D(Path2D[] paths) : this(paths, FPSLimiterKnownValues.LimitThirty)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator2D" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator2D(Path2D[] paths, FPSLimiterKnownValues fpsLimiter)
        {
            HorizontalAnimator = new Animator(fpsLimiter);
            VerticalAnimator = new Animator(fpsLimiter);
            Paths = paths;
        }

        /// <summary>
        ///     Gets the currently active path.
        /// </summary>
        public Path2D ActivePath => new Path2D(HorizontalAnimator.ActivePath, VerticalAnimator.ActivePath);

        /// <summary>
        ///     Gets the horizontal animator.
        /// </summary>
        public Animator HorizontalAnimator { get; protected set; }

        /// <summary>
        ///     Gets the vertical animator.
        /// </summary>
        public Animator VerticalAnimator { get; protected set; }

        /// <summary>
        ///     Gets or sets an array containing the list of paths of the animation
        /// </summary>
        /// <exception cref="InvalidOperationException">Animation is running</exception>
        public Path2D[] Paths
        {
            get { return _paths.ToArray(); }
            set
            {
                if (CurrentStatus == AnimatorStatus.Stopped)
                {
                    _paths.Clear();
                    _paths.AddRange(value);
                    var pathsH = new List<Path>();
                    var pathsV = new List<Path>();
                    foreach (var p in value)
                    {
                        pathsH.Add(p.HorizontalPath);
                        pathsV.Add(p.VerticalPath);
                    }
                    HorizontalAnimator.Paths = pathsH.ToArray();
                    VerticalAnimator.Paths = pathsV.ToArray();
                }
                else
                {
                    throw new InvalidOperationException("Animation is running.");
                }
            }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation after its ending
        /// </summary>
        public virtual bool Repeat
        {
            get { return HorizontalAnimator.Repeat && VerticalAnimator.Repeat; }

            set { HorizontalAnimator.Repeat = VerticalAnimator.Repeat = value; }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation in reverse after its ending.
        /// </summary>
        public virtual bool ReverseRepeat
        {
            get { return HorizontalAnimator.ReverseRepeat && VerticalAnimator.ReverseRepeat; }

            set { HorizontalAnimator.ReverseRepeat = VerticalAnimator.ReverseRepeat = value; }
        }

        /// <summary>
        ///     Gets the current status of the animation
        /// </summary>
        public virtual AnimatorStatus CurrentStatus
        {
            get
            {
                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.Stopped
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.Stopped)
                {
                    return AnimatorStatus.Stopped;
                }

                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.Paused
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.Paused)
                {
                    return AnimatorStatus.Paused;
                }

                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.OnHold
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.OnHold)
                {
                    return AnimatorStatus.OnHold;
                }

                return AnimatorStatus.Playing;
            }
        }

        /// <summary>
        ///     Pause the animation
        /// </summary>
        public virtual void Pause()
        {
            if (CurrentStatus == AnimatorStatus.OnHold || CurrentStatus == AnimatorStatus.Playing)
            {
                HorizontalAnimator.Pause();
                VerticalAnimator.Pause();
            }
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        public virtual void Play(object targetObject, string propertyName)
        {
            Play(targetObject, propertyName, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public virtual void Play(object targetObject, string propertyName, SafeInvoker endCallback)
        {
            TargetObject = targetObject;
            var prop = TargetObject.GetType()
                .GetProperty(
                    propertyName,
                    BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance |
                    BindingFlags.SetProperty);
            if (prop == null) return;

            Play(
                new SafeInvoker<Float2D>(
                    value =>
                        prop.SetValue(TargetObject, Convert.ChangeType(value, prop.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter)
        {
            Play(targetObject, propertySetter, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter, SafeInvoker endCallback)
        {
            if (propertySetter == null)
                return;
            TargetObject = targetObject;

            var property =
                ((propertySetter.Body as MemberExpression) ??
                 (((UnaryExpression) propertySetter.Body).Operand as MemberExpression))?.Member as PropertyInfo;
            if (property == null)
            {
                throw new ArgumentException(nameof(propertySetter));
            }

            Play(
                new SafeInvoker<Float2D>(
                    value =>
                        property.SetValue(TargetObject, Convert.ChangeType(value, property.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Resume the animation from where it paused
        /// </summary>
        public virtual void Resume()
        {
            if (CurrentStatus == AnimatorStatus.Paused)
            {
                HorizontalAnimator.Resume();
                VerticalAnimator.Resume();
            }
        }

        /// <summary>
        ///     Stops the animation and resets its status, resume is no longer possible
        /// </summary>
        public virtual void Stop()
        {
            HorizontalAnimator.Stop();
            VerticalAnimator.Stop();
            XValue = YValue = null;
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        public void Play(object targetObject, KnownProperties property)
        {
            Play(targetObject, property, null);
        }


        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public void Play(object targetObject, KnownProperties property, SafeInvoker endCallback)
        {
            Play(targetObject, property.ToString(), endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        public void Play(SafeInvoker<Float2D> frameCallback)
        {
            Play(frameCallback, (SafeInvoker) null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public void Play(SafeInvoker<Float2D> frameCallback, SafeInvoker endCallback)
        {
            Stop();
            FrameCallback = frameCallback;
            EndCallback = endCallback;
            HorizontalAnimator.Play(
                new SafeInvoker<float>(
                    value =>
                    {
                        XValue = value;
                        InvokeSetter();
                    }),
                new SafeInvoker(InvokeFinisher));
            VerticalAnimator.Play(
                new SafeInvoker<float>(
                    value =>
                    {
                        YValue = value;
                        InvokeSetter();
                    }),
                new SafeInvoker(InvokeFinisher));
        }

        private void InvokeFinisher()
        {
            if (EndCallback != null && !IsEnded)
            {
                lock (EndCallback)
                {
                    if (CurrentStatus == AnimatorStatus.Stopped)
                    {
                        IsEnded = true;
                        EndCallback.Invoke();
                    }
                }
            }
        }

        private void InvokeSetter()
        {
            if (XValue != null && YValue != null)
            {
                FrameCallback.Invoke(new Float2D(XValue.Value, YValue.Value));
            }
        }
    }
}

================================================
FILE: WinFormAnimation/Animator3D.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;

namespace WinFormAnimation
{
    /// <summary>
    ///     The three dimensional animator class, useful for animating values
    ///     created from three underlying values
    /// </summary>
    public class Animator3D : IAnimator
    {
        /// <summary>
        ///     The known three dimensional properties of WinForm controls
        /// </summary>
        public enum KnownProperties
        {
            /// <summary>
            ///     The property named 'BackColor' of the object
            /// </summary>
            BackColor,

            /// <summary>
            ///     The property named 'ForeColor' of the object
            /// </summary>
            ForeColor
        }

        private readonly List<Path3D> _paths = new List<Path3D>();

        /// <summary>
        ///     The callback to get invoked at the end of the animation
        /// </summary>
        protected SafeInvoker EndCallback;

        /// <summary>
        ///     The callback to get invoked at each frame
        /// </summary>
        protected SafeInvoker<Float3D> FrameCallback;

        /// <summary>
        ///     A boolean value indicating if the EndInvoker already invoked
        /// </summary>
        protected bool IsEnded;

        /// <summary>
        ///     The target object to change the property of
        /// </summary>
        protected object TargetObject;

        /// <summary>
        ///     The latest horizontal value
        /// </summary>
        protected float? XValue;

        /// <summary>
        ///     The latest vertical value
        /// </summary>
        protected float? YValue;

        /// <summary>
        ///     The latest depth value
        /// </summary>
        protected float? ZValue;


        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        public Animator3D()
            : this(new Path3D[] {})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator3D(FPSLimiterKnownValues fpsLimiter)
            : this(new Path3D[] {}, fpsLimiter)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        public Animator3D(Path3D path)
            : this(new[] {path})
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        /// <param name="path">
        ///     The path of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator3D(Path3D path, FPSLimiterKnownValues fpsLimiter)
            : this(new[] {path}, fpsLimiter)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        public Animator3D(Path3D[] paths) : this(paths, FPSLimiterKnownValues.LimitThirty)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Animator3D" /> class.
        /// </summary>
        /// <param name="paths">
        ///     An array containing the list of paths of the animation
        /// </param>
        /// <param name="fpsLimiter">
        ///     Limits the maximum frames per seconds
        /// </param>
        public Animator3D(Path3D[] paths, FPSLimiterKnownValues fpsLimiter)
        {
            HorizontalAnimator = new Animator(fpsLimiter);
            VerticalAnimator = new Animator(fpsLimiter);
            DepthAnimator = new Animator(fpsLimiter);
            Paths = paths;
        }

        /// <summary>
        ///     Gets the currently active path.
        /// </summary>
        public Path3D ActivePath => new Path3D(
            HorizontalAnimator.ActivePath,
            VerticalAnimator.ActivePath,
            DepthAnimator.ActivePath);

        /// <summary>
        ///     Gets the horizontal animator.
        /// </summary>
        public Animator HorizontalAnimator { get; protected set; }

        /// <summary>
        ///     Gets the vertical animator.
        /// </summary>
        public Animator VerticalAnimator { get; protected set; }

        /// <summary>
        ///     Gets the depth animator.
        /// </summary>
        public Animator DepthAnimator { get; protected set; }


        /// <summary>
        ///     Gets or sets an array containing the list of paths of the animation
        /// </summary>
        /// <exception cref="InvalidOperationException">Animation is running</exception>
        public Path3D[] Paths
        {
            get { return _paths.ToArray(); }
            set
            {
                if (CurrentStatus == AnimatorStatus.Stopped)
                {
                    _paths.Clear();
                    _paths.AddRange(value);
                    var pathsX = new List<Path>();
                    var pathsY = new List<Path>();
                    var pathsZ = new List<Path>();
                    foreach (var p in value)
                    {
                        pathsX.Add(p.HorizontalPath);
                        pathsY.Add(p.VerticalPath);
                        pathsZ.Add(p.DepthPath);
                    }

                    HorizontalAnimator.Paths = pathsX.ToArray();
                    VerticalAnimator.Paths = pathsY.ToArray();
                    DepthAnimator.Paths = pathsZ.ToArray();
                }
                else
                {
                    throw new NotSupportedException("Animation is running.");
                }
            }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation after its ending
        /// </summary>
        public virtual bool Repeat
        {
            get { return HorizontalAnimator.Repeat && VerticalAnimator.Repeat && DepthAnimator.Repeat; }

            set { HorizontalAnimator.Repeat = VerticalAnimator.Repeat = DepthAnimator.Repeat = value; }
        }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation in reverse after its ending.
        /// </summary>
        public virtual bool ReverseRepeat
        {
            get
            {
                return HorizontalAnimator.ReverseRepeat && VerticalAnimator.ReverseRepeat
                       && DepthAnimator.ReverseRepeat;
            }

            set
            {
                HorizontalAnimator.ReverseRepeat =
                    VerticalAnimator.ReverseRepeat = DepthAnimator.ReverseRepeat = value;
            }
        }

        /// <summary>
        ///     Gets the current status of the animation
        /// </summary>
        public virtual AnimatorStatus CurrentStatus
        {
            get
            {
                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.Stopped
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.Stopped
                    && DepthAnimator.CurrentStatus == AnimatorStatus.Stopped)
                {
                    return AnimatorStatus.Stopped;
                }

                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.Paused
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.Paused
                    && DepthAnimator.CurrentStatus == AnimatorStatus.Paused)
                {
                    return AnimatorStatus.Paused;
                }

                if (HorizontalAnimator.CurrentStatus == AnimatorStatus.OnHold
                    && VerticalAnimator.CurrentStatus == AnimatorStatus.OnHold
                    && DepthAnimator.CurrentStatus == AnimatorStatus.OnHold)
                {
                    return AnimatorStatus.OnHold;
                }

                return AnimatorStatus.Playing;
            }
        }

        /// <summary>
        ///     Pause the animation
        /// </summary>
        public virtual void Pause()
        {
            if (CurrentStatus == AnimatorStatus.OnHold || CurrentStatus == AnimatorStatus.Playing)
            {
                HorizontalAnimator.Pause();
                VerticalAnimator.Pause();
                DepthAnimator.Pause();
            }
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        public virtual void Play(object targetObject, string propertyName)
        {
            Play(targetObject, propertyName, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public virtual void Play(object targetObject, string propertyName, SafeInvoker endCallback)
        {
            TargetObject = targetObject;
            var prop = TargetObject.GetType()
                .GetProperty(
                    propertyName,
                    BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance |
                    BindingFlags.SetProperty);
            if (prop == null) return;

            Play(
                new SafeInvoker<Float3D>(
                    value =>
                        prop.SetValue(TargetObject, Convert.ChangeType(value, prop.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter)
        {
            Play(targetObject, propertySetter, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        public virtual void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter, SafeInvoker endCallback)
        {
            if (propertySetter == null)
                return;
            TargetObject = targetObject;

            var property =
                ((propertySetter.Body as MemberExpression) ??
                 (((UnaryExpression) propertySetter.Body).Operand as MemberExpression))?.Member as PropertyInfo;
            if (property == null)
            {
                throw new ArgumentException(nameof(propertySetter));
            }

            Play(
                new SafeInvoker<Float3D>(
                    value =>
                        property.SetValue(TargetObject, Convert.ChangeType(value, property.PropertyType), null),
                    TargetObject),
                endCallback);
        }

        /// <summary>
        ///     Resume the animation from where it paused
        /// </summary>
        public virtual void Resume()
        {
            if (CurrentStatus == AnimatorStatus.Paused)
            {
                HorizontalAnimator.Resume();
                VerticalAnimator.Resume();
                DepthAnimator.Resume();
            }
        }

        /// <summary>
        ///     Stops the animation and resets its status, resume is no longer possible
        /// </summary>
        public virtual void Stop()
        {
            HorizontalAnimator.Stop();
            VerticalAnimator.Stop();
            DepthAnimator.Stop();
            XValue = YValue = ZValue = null;
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        public void Play(object targetObject, KnownProperties property)
        {
            Play(targetObject, property, null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="property">
        ///     The property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public void Play(object targetObject, KnownProperties property, SafeInvoker endCallback)
        {
            Play(targetObject, property.ToString(), endCallback);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        public void Play(SafeInvoker<Float3D> frameCallback)
        {
            Play(frameCallback, (SafeInvoker) null);
        }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="frameCallback">
        ///     The callback to get invoked at each frame
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        public void Play(SafeInvoker<Float3D> frameCallback, SafeInvoker endCallback)
        {
            Stop();
            FrameCallback = frameCallback;
            EndCallback = endCallback;
            IsEnded = false;
            HorizontalAnimator.Play(
                new SafeInvoker<float>(
                    value =>
                    {
                        XValue = value;
                        InvokeSetter();
                    }),
                new SafeInvoker(InvokeFinisher));
            VerticalAnimator.Play(
                new SafeInvoker<float>(
                    value =>
                    {
                        YValue = value;
                        InvokeSetter();
                    }),
                new SafeInvoker(InvokeFinisher));
            DepthAnimator.Play(
                new SafeInvoker<float>(
                    value =>
                    {
                        ZValue = value;
                        InvokeSetter();
                    }),
                new SafeInvoker(InvokeFinisher));
        }

        private void InvokeFinisher()
        {
            if (EndCallback != null && !IsEnded)
            {
                lock (EndCallback)
                {
                    if (CurrentStatus == AnimatorStatus.Stopped)
                    {
                        IsEnded = true;
                        EndCallback.Invoke();
                    }
                }
            }
        }

        private void InvokeSetter()
        {
            if (XValue != null && YValue != null && ZValue != null)
            {
                FrameCallback.Invoke(new Float3D(XValue.Value, YValue.Value, ZValue.Value));
            }
        }
    }
}

================================================
FILE: WinFormAnimation/AnimatorStatus.cs
================================================
namespace WinFormAnimation
{
    /// <summary>
    ///     The possible statuses for an animator instance
    /// </summary>
    public enum AnimatorStatus
    {
        /// <summary>
        ///     Animation is stopped
        /// </summary>
        Stopped,

        /// <summary>
        ///     Animation is now playing
        /// </summary>
        Playing,

        /// <summary>
        ///     Animation is now on hold for path delay, consider this value as playing
        /// </summary>
        OnHold,

        /// <summary>
        ///     Animation is paused
        /// </summary>
        Paused
    }
}

================================================
FILE: WinFormAnimation/FPSLimiterKnownValues.cs
================================================
namespace WinFormAnimation
{
    /// <summary>
    ///     FPS limiter known values
    /// </summary>
    public enum FPSLimiterKnownValues
    {
        /// <summary>
        ///     Limits maximum frames per second to 10fps
        /// </summary>
        LimitTen = 10,

        /// <summary>
        ///     Limits maximum frames per second to 20fps
        /// </summary>
        LimitTwenty = 20,

        /// <summary>
        ///     Limits maximum frames per second to 30fps
        /// </summary>
        LimitThirty = 30,

        /// <summary>
        ///     Limits maximum frames per second to 60fps
        /// </summary>
        LimitSixty = 60,

        /// <summary>
        ///     Limits maximum frames per second to 100fps
        /// </summary>
        LimitOneHundred = 100,

        /// <summary>
        ///     Limits maximum frames per second to 200fps
        /// </summary>
        LimitTwoHundred = 200,

        /// <summary>
        ///     Adds no limit to the number of frames per second
        /// </summary>
        NoFPSLimit = -1
    }
}

================================================
FILE: WinFormAnimation/FloatExtensions.cs
================================================
using System.Drawing;

namespace WinFormAnimation
{
    /// <summary>
    ///     Contains public extension methods about Float2D and Fload3D classes
    /// </summary>
    public static class FloatExtensions
    {
        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from this instance
        /// </summary>
        /// <param name="point">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D ToFloat2D(this Point point)
        {
            return Float2D.FromPoint(point);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from this instance
        /// </summary>
        /// <param name="point">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D ToFloat2D(this PointF point)
        {
            return Float2D.FromPoint(point);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from this instance
        /// </summary>
        /// <param name="size">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D ToFloat2D(this Size size)
        {
            return Float2D.FromSize(size);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from this instance
        /// </summary>
        /// <param name="size">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D ToFloat2D(this SizeF size)
        {
            return Float2D.FromSize(size);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float3D" /> class from this instance
        /// </summary>
        /// <param name="color">The object to create the <see cref="Float3D" /> instance from</param>
        /// <returns>The newly created <see cref="Float3D" /> instance</returns>
        public static Float3D ToFloat3D(this Color color)
        {
            return Float3D.FromColor(color);
        }
    }
}

================================================
FILE: WinFormAnimation/IAnimator.cs
================================================
using System;
using System.Linq.Expressions;

namespace WinFormAnimation
{
    /// <summary>
    ///     The base interface for any Animator class, custom or build-in
    /// </summary>
    public interface IAnimator
    {
        /// <summary>
        ///     Gets the current status of the animation
        /// </summary>
        AnimatorStatus CurrentStatus { get; }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation after its ending
        /// </summary>
        bool Repeat { get; set; }

        /// <summary>
        ///     Gets or sets a value indicating whether animator should repeat the animation in reverse after its ending.
        /// </summary>
        bool ReverseRepeat { get; set; }

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        void Play(object targetObject, string propertyName);

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertyName">
        ///     The name of the property to change
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        void Play(object targetObject, string propertyName, SafeInvoker endCallback);

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter);

        /// <summary>
        ///     Starts the playing of the animation
        /// </summary>
        /// <param name="targetObject">
        ///     The target object to change the property
        /// </param>
        /// <param name="propertySetter">
        ///     The expression that represents the property of the target object
        /// </param>
        /// <param name="endCallback">
        ///     The callback to get invoked at the end of the animation
        /// </param>
        /// <typeparam name="T">
        ///     Any object containing a property
        /// </typeparam>
        void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter, SafeInvoker endCallback);

        /// <summary>
        ///     Resume the animation from where it paused
        /// </summary>
        void Resume();

        /// <summary>
        ///     Stops the animation and resets its status, resume is no longer possible
        /// </summary>
        void Stop();

        /// <summary>
        ///     Pause the animation
        /// </summary>
        void Pause();
    }
}

================================================
FILE: WinFormAnimation/KnownAnimationFunctions.cs
================================================
namespace WinFormAnimation
{
    /// <summary>
    ///     Contains a list of all known animation functions
    /// </summary>
    public enum KnownAnimationFunctions
    {
        /// <summary>
        ///     No known animation function
        /// </summary>
        None,

        /// <summary>
        ///     The cubic ease-in animation function.
        /// </summary>
        CubicEaseIn,

        /// <summary>
        ///     The cubic ease-in and ease-out animation function.
        /// </summary>
        CubicEaseInOut,

        /// <summary>
        ///     The cubic ease-out animation function.
        /// </summary>
        CubicEaseOut,

        /// <summary>
        ///     The linear animation function.
        /// </summary>
        Linear,

        /// <summary>
        ///     The circular ease-in and ease-out animation function.
        /// </summary>
        CircularEaseInOut,

        /// <summary>
        ///     The circular ease-in animation function.
        /// </summary>
        CircularEaseIn,

        /// <summary>
        ///     The circular ease-out animation function.
        /// </summary>
        CircularEaseOut,

        /// <summary>
        ///     The quadratic ease-in animation function.
        /// </summary>
        QuadraticEaseIn,

        /// <summary>
        ///     The quadratic ease-out animation function.
        /// </summary>
        QuadraticEaseOut,

        /// <summary>
        ///     The quadratic ease-in and ease-out animation function.
        /// </summary>
        QuadraticEaseInOut,

        /// <summary>
        ///     The quartic ease-in animation function.
        /// </summary>
        QuarticEaseIn,

        /// <summary>
        ///     The quartic ease-out animation function.
        /// </summary>
        QuarticEaseOut,

        /// <summary>
        ///     The quartic ease-in and ease-out animation function.
        /// </summary>
        QuarticEaseInOut,

        /// <summary>
        ///     The quintic ease-in and ease-out animation function.
        /// </summary>
        QuinticEaseInOut,

        /// <summary>
        ///     The quintic ease-in animation function.
        /// </summary>
        QuinticEaseIn,

        /// <summary>
        ///     The quintic ease-out animation function.
        /// </summary>
        QuinticEaseOut,

        /// <summary>
        ///     The sinusoidal ease-in animation function.
        /// </summary>
        SinusoidalEaseIn,

        /// <summary>
        ///     The sinusoidal ease-out animation function.
        /// </summary>
        SinusoidalEaseOut,

        /// <summary>
        ///     The sinusoidal ease-in and ease-out animation function.
        /// </summary>
        SinusoidalEaseInOut,

        /// <summary>
        ///     The exponential ease-in animation function.
        /// </summary>
        ExponentialEaseIn,

        /// <summary>
        ///     The exponential ease-out animation function.
        /// </summary>
        ExponentialEaseOut,

        /// <summary>
        ///     The exponential ease-in and ease-out animation function.
        /// </summary>
        ExponentialEaseInOut
    }
}

================================================
FILE: WinFormAnimation/Path.cs
================================================
using System;

namespace WinFormAnimation
{
    /// <summary>
    ///     The Path class is a representation of a line in a 1D plane and the
    ///     speed in which the animator plays it
    /// </summary>
    public class Path
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Path" /> class.
        /// </summary>
        public Path() : this(default(float), default(float), default(ulong), 0, null)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting value
        /// </param>
        /// <param name="end">
        ///     The ending value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path(float start, float end, ulong duration) : this(start, end, duration, 0, null)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting value
        /// </param>
        /// <param name="end">
        ///     The ending value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path(float start, float end, ulong duration, AnimationFunctions.Function function)
            : this(start, end, duration, 0, function)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting value
        /// </param>
        /// <param name="end">
        ///     The ending value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path(float start, float end, ulong duration, ulong delay) : this(start, end, duration, delay, null)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting value
        /// </param>
        /// <param name="end">
        ///     The ending value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path(float start, float end, ulong duration, ulong delay, AnimationFunctions.Function function)
        {
            Start = start;
            End = end;
            Function = function ?? AnimationFunctions.Linear;
            Duration = duration;
            Delay = delay;
        }

        /// <summary>
        ///     Gets the difference of starting and ending values
        /// </summary>
        public float Change => End - Start;

        /// <summary>
        ///     Gets or sets the starting delay
        /// </summary>
        public ulong Delay { get; set; }

        /// <summary>
        ///     Gets or sets the duration in milliseconds
        /// </summary>
        public ulong Duration { get; set; }

        /// <summary>
        ///     Gets or sets the ending value
        /// </summary>
        public float End { get; set; }

        /// <summary>
        ///     Gets or sets the animation function
        /// </summary>
        public AnimationFunctions.Function Function { get; set; }

        /// <summary>
        ///     Gets or sets the starting value
        /// </summary>
        public float Start { get; set; }

        /// <summary>
        ///     Creates and returns a new <see cref="Path" /> based on the current path but in reverse order
        /// </summary>
        /// <returns>
        ///     A new <see cref="Path" /> which is the reverse of the current <see cref="Path" />
        /// </returns>
        public Path Reverse()
        {
            return new Path(End, Start, Duration, Delay, Function);
        }
    }
}

================================================
FILE: WinFormAnimation/Path2D.cs
================================================
using System;

namespace WinFormAnimation
{
    /// <summary>
    ///     The Path2D class is a representation of a line in a 2D plane and the
    ///     speed in which the animator plays it
    /// </summary>
    public class Path2D
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(
            float startX,
            float endX,
            float startY,
            float endY,
            ulong duration,
            ulong delay,
            AnimationFunctions.Function function)
            : this(new Path(startX, endX, duration, delay, function), new Path(startY, endY, duration, delay, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(
            float startX,
            float endX,
            float startY,
            float endY,
            ulong duration,
            ulong delay)
            : this(new Path(startX, endX, duration, delay), new Path(startY, endY, duration, delay))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(
            float startX,
            float endX,
            float startY,
            float endY,
            ulong duration,
            AnimationFunctions.Function function)
            : this(new Path(startX, endX, duration, function), new Path(startY, endY, duration, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(
            float startX,
            float endX,
            float startY,
            float endY,
            ulong duration)
            : this(new Path(startX, endX, duration), new Path(startY, endY, duration))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point or location
        /// </param>
        /// <param name="end">
        ///     The ending point or location
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(Float2D start, Float2D end, ulong duration, ulong delay, AnimationFunctions.Function function)
            : this(
                new Path(start.X, end.X, duration, delay, function),
                new Path(start.Y, end.Y, duration, delay, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point or location
        /// </param>
        /// <param name="end">
        ///     The ending point or location
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(Float2D start, Float2D end, ulong duration, ulong delay)
            : this(
                new Path(start.X, end.X, duration, delay),
                new Path(start.Y, end.Y, duration, delay))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point or location
        /// </param>
        /// <param name="end">
        ///     The ending point or location
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(Float2D start, Float2D end, ulong duration, AnimationFunctions.Function function)
            : this(
                new Path(start.X, end.X, duration, function),
                new Path(start.Y, end.Y, duration, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point or location
        /// </param>
        /// <param name="end">
        ///     The ending point or location
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path2D(Float2D start, Float2D end, ulong duration)
            : this(
                new Path(start.X, end.X, duration),
                new Path(start.Y, end.Y, duration))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path2D" /> class.
        /// </summary>
        /// <param name="x">
        ///     The horizontal path.
        /// </param>
        /// <param name="y">
        ///     The vertical path.
        /// </param>
        public Path2D(Path x, Path y)
        {
            HorizontalPath = x;
            VerticalPath = y;
        }

        /// <summary>
        ///     Gets the horizontal path
        /// </summary>
        public Path HorizontalPath { get; }

        /// <summary>
        ///     Gets the vertical path
        /// </summary>
        public Path VerticalPath { get; }

        /// <summary>
        ///     Gets the starting point of the path
        /// </summary>
        public Float2D Start => new Float2D(HorizontalPath.Start, VerticalPath.Start);


        /// <summary>
        ///     Gets the ending point of the path
        /// </summary>
        public Float2D End => new Float2D(HorizontalPath.End, VerticalPath.End);

        /// <summary>
        ///     Creates and returns a new <see cref="Path2D" /> based on the current path but in reverse order
        /// </summary>
        /// <returns>
        ///     A new <see cref="Path2D" /> which is the reverse of the current <see cref="Path2D" />
        /// </returns>
        public Path2D Reverse()
        {
            return new Path2D(HorizontalPath.Reverse(), VerticalPath.Reverse());
        }
    }
}

================================================
FILE: WinFormAnimation/Path2DExtensions.cs
================================================
using System.Linq;

namespace WinFormAnimation
{
    /// <summary>
    ///     Contains public extensions methods about Path2D class
    /// </summary>
    public static class Path2DExtensions
    {
        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ulong duration)
        {
            return paths.Concat(new[] {new Path2D(paths.Last().End, end, duration)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ulong duration,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path2D(paths.Last().End, end, duration, function)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ulong duration, ulong delay)
        {
            return paths.Concat(new[] {new Path2D(paths.Last().End, end, duration, delay)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path2D(paths.Last().End, end, duration, delay, function)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, float endX, float endY, ulong duration)
        {
            return paths.Concat(new[] {new Path2D(paths.Last().End, new Float2D(endX, endY), duration)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, float endX, float endY, ulong duration,
            AnimationFunctions.Function function)
        {
            return
                paths.Concat(new[] {new Path2D(paths.Last().End, new Float2D(endX, endY), duration, function)})
                    .ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, float endX, float endY, ulong duration, ulong delay)
        {
            return
                paths.Concat(new[] {new Path2D(paths.Last().End, new Float2D(endX, endY), duration, delay)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, float endX, float endY, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return
                paths.Concat(new[] {new Path2D(paths.Last().End, new Float2D(endX, endY), duration, delay, function)})
                    .ToArray();
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong duration)
        {
            return path.ToArray().ContinueTo(end, duration);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong duration,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong duration, ulong delay)
        {
            return path.ToArray().ContinueTo(end, duration, delay);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, delay, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, float endX, float endY, ulong duration)
        {
            return path.ToArray().ContinueTo(endX, endY, duration);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, float endX, float endY, ulong duration,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(endX, endY, duration, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, float endX, float endY, ulong duration, ulong delay)
        {
            return path.ToArray().ContinueTo(endX, endY, duration, delay);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path2D[] ContinueTo(this Path2D path, float endX, float endY, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(endX, endY, duration, delay, function);
        }

        /// <summary>
        ///     Continue the path array with a new ones
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path2D[] ContinueTo(this Path2D[] paths, params Path2D[] newPaths)
        {
            return paths.Concat(newPaths).ToArray();
        }

        /// <summary>
        ///     Continue the path with a new ones
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path2D[] ContinueTo(this Path2D path, params Path2D[] newPaths)
        {
            return path.ToArray().ContinueTo(newPaths);
        }

        /// <summary>
        ///     Contains a single path in an array
        /// </summary>
        /// <param name="path">The path to add to the array</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path2D[] ToArray(this Path2D path)
        {
            return new[] {path};
        }
    }
}

================================================
FILE: WinFormAnimation/Path3D.cs
================================================
using System;

namespace WinFormAnimation
{
    /// <summary>
    ///     The Path3D class is a representation of a line in a 3D plane and the
    ///     speed in which the animator plays it
    /// </summary>
    public class Path3D
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="startZ">
        ///     The starting depth value
        /// </param>
        /// <param name="endZ">
        ///     The ending depth value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(
            float startX,
            float endX,
            float startY,
            float endY,
            float startZ,
            float endZ,
            ulong duration,
            ulong delay,
            AnimationFunctions.Function function)
            : this(
                new Path(startX, endX, duration, delay, function),
                new Path(startY, endY, duration, delay, function),
                new Path(startZ, endZ, duration, delay, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="startZ">
        ///     The starting depth value
        /// </param>
        /// <param name="endZ">
        ///     The ending depth value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(
            float startX,
            float endX,
            float startY,
            float endY,
            float startZ,
            float endZ,
            ulong duration,
            ulong delay)
            : this(
                new Path(startX, endX, duration, delay),
                new Path(startY, endY, duration, delay),
                new Path(startZ, endZ, duration, delay))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="startZ">
        ///     The starting depth value
        /// </param>
        /// <param name="endZ">
        ///     The ending depth value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(
            float startX,
            float endX,
            float startY,
            float endY,
            float startZ,
            float endZ,
            ulong duration,
            AnimationFunctions.Function function)
            : this(
                new Path(startX, endX, duration, function),
                new Path(startY, endY, duration, function),
                new Path(startZ, endZ, duration, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="startX">
        ///     The starting horizontal value
        /// </param>
        /// <param name="endX">
        ///     The ending horizontal value
        /// </param>
        /// <param name="startY">
        ///     The starting vertical value
        /// </param>
        /// <param name="endY">
        ///     The ending vertical value
        /// </param>
        /// <param name="startZ">
        ///     The starting depth value
        /// </param>
        /// <param name="endZ">
        ///     The ending depth value
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(
            float startX,
            float endX,
            float startY,
            float endY,
            float startZ,
            float endZ,
            ulong duration)
            : this(new Path(startX, endX, duration), new Path(startY, endY, duration), new Path(startZ, endZ, duration))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point in a 3D plane
        /// </param>
        /// <param name="end">
        ///     The ending point in a 3D plane
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(Float3D start, Float3D end, ulong duration, ulong delay, AnimationFunctions.Function function)
            : this(
                new Path(start.X, end.X, duration, delay, function),
                new Path(start.Y, end.Y, duration, delay, function),
                new Path(start.Z, end.Z, duration, delay, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point in a 3D plane
        /// </param>
        /// <param name="end">
        ///     The ending point in a 3D plane
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="delay">
        ///     The time in miliseconds that the animator must wait before playing this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(Float3D start, Float3D end, ulong duration, ulong delay)
            : this(
                new Path(start.X, end.X, duration, delay),
                new Path(start.Y, end.Y, duration, delay),
                new Path(start.Z, end.Z, duration, delay))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point in a 3D plane
        /// </param>
        /// <param name="end">
        ///     The ending point in a 3D plane
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <param name="function">
        ///     The animation function
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(Float3D start, Float3D end, ulong duration, AnimationFunctions.Function function)
            : this(
                new Path(start.X, end.X, duration, function),
                new Path(start.Y, end.Y, duration, function),
                new Path(start.Z, end.Z, duration, function))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="start">
        ///     The starting point in a 3D plane
        /// </param>
        /// <param name="end">
        ///     The ending point in a 3D plane
        /// </param>
        /// <param name="duration">
        ///     The time in miliseconds that the animator must play this path
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     Duration is less than zero
        /// </exception>
        public Path3D(Float3D start, Float3D end, ulong duration)
            : this(
                new Path(start.X, end.X, duration),
                new Path(start.Y, end.Y, duration),
                new Path(start.Z, end.Z, duration))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Path3D" /> class.
        /// </summary>
        /// <param name="x">
        ///     The horizontal path.
        /// </param>
        /// <param name="y">
        ///     The vertical path.
        /// </param>
        /// <param name="z">
        ///     The depth path.
        /// </param>
        public Path3D(Path x, Path y, Path z)
        {
            HorizontalPath = x;
            VerticalPath = y;
            DepthPath = z;
        }

        /// <summary>
        ///     Gets the horizontal path
        /// </summary>
        public Path HorizontalPath { get; }

        /// <summary>
        ///     Gets the vertical path
        /// </summary>
        public Path VerticalPath { get; }

        /// <summary>
        ///     Gets the depth path
        /// </summary>
        public Path DepthPath { get; }


        /// <summary>
        ///     Gets the starting point of the path
        /// </summary>
        public Float3D Start => new Float3D(HorizontalPath.Start, VerticalPath.Start, DepthPath.Start);


        /// <summary>
        ///     Gets the ending point of the path
        /// </summary>
        public Float3D End => new Float3D(HorizontalPath.End, VerticalPath.End, DepthPath.End);

        /// <summary>
        ///     Creates and returns a new <see cref="Path3D" /> based on the current path but in reverse order
        /// </summary>
        /// <returns>
        ///     A new <see cref="Path" /> which is the reverse of the current <see cref="Path3D" />
        /// </returns>
        public Path3D Reverse()
        {
            return new Path3D(HorizontalPath.Reverse(), VerticalPath.Reverse(), DepthPath.Reverse());
        }
    }
}

================================================
FILE: WinFormAnimation/Path3DExtensions.cs
================================================
using System.Linq;

namespace WinFormAnimation
{
    /// <summary>
    ///     Contains public extensions methods about Path3D class
    /// </summary>
    public static class Path3DExtensions
    {
        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ulong duration)
        {
            return paths.Concat(new[] {new Path3D(paths.Last().End, end, duration)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ulong duration,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path3D(paths.Last().End, end, duration, function)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ulong duration, ulong delay)
        {
            return paths.Concat(new[] {new Path3D(paths.Last().End, end, duration, delay)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path3D(paths.Last().End, end, duration, delay, function)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, float endX, float endY, float endZ, ulong duration)
        {
            return paths.Concat(new[] {new Path3D(paths.Last().End, new Float3D(endX, endY, endZ), duration)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, float endX, float endY, float endZ, ulong duration,
            AnimationFunctions.Function function)
        {
            return
                paths.Concat(new[] {new Path3D(paths.Last().End, new Float3D(endX, endY, endZ), duration, function)})
                    .ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, float endX, float endY, float endZ, ulong duration,
            ulong delay)
        {
            return
                paths.Concat(new[] {new Path3D(paths.Last().End, new Float3D(endX, endY, endZ), duration, delay)})
                    .ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, float endX, float endY, float endZ, ulong duration,
            ulong delay,
            AnimationFunctions.Function function)
        {
            return
                paths.Concat(new[]
                {new Path3D(paths.Last().End, new Float3D(endX, endY, endZ), duration, delay, function)})
                    .ToArray();
        }


        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong duration)
        {
            return path.ToArray().ContinueTo(end, duration);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong duration,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong duration, ulong delay)
        {
            return path.ToArray().ContinueTo(end, duration, delay);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, delay, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, float endX, float endY, float endZ, ulong duration)
        {
            return path.ToArray().ContinueTo(endX, endY, endZ, duration);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, float endX, float endY, float endZ, ulong duration,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(endX, endY, endZ, duration, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, float endX, float endY, float endZ, ulong duration,
            ulong delay)
        {
            return path.ToArray().ContinueTo(endX, endY, endZ, duration, delay);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="endX">Horizontal value of the next point to follow</param>
        /// <param name="endY">Vertical value of the next point to follow</param>
        /// <param name="endZ">Depth value of the next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path3D[] ContinueTo(this Path3D path, float endX, float endY, float endZ, ulong duration,
            ulong delay,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(endX, endY, endZ, duration, delay, function);
        }


        /// <summary>
        ///     Continue the path array with a new ones
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path3D[] ContinueTo(this Path3D[] paths, params Path3D[] newPaths)
        {
            return paths.Concat(newPaths).ToArray();
        }

        /// <summary>
        ///     Continue the path with a new ones
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path3D[] ContinueTo(this Path3D path, params Path3D[] newPaths)
        {
            return path.ToArray().ContinueTo(newPaths);
        }

        /// <summary>
        ///     Contains a single path in an array
        /// </summary>
        /// <param name="path">The path to add to the array</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path3D[] ToArray(this Path3D path)
        {
            return new[] {path};
        }
    }
}

================================================
FILE: WinFormAnimation/PathExtensions.cs
================================================
using System.Linq;

namespace WinFormAnimation
{
    /// <summary>
    ///     Contains public extensions methods about Path class
    /// </summary>
    public static class PathExtensions
    {
        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path[] paths, float end, ulong duration)
        {
            return paths.Concat(new[] {new Path(paths.Last().End, end, duration)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path[] paths, float end, ulong duration,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path(paths.Last().End, end, duration, function)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path[] paths, float end, ulong duration, ulong delay)
        {
            return paths.Concat(new[] {new Path(paths.Last().End, end, duration, delay)}).ToArray();
        }

        /// <summary>
        ///     Continue the last paths with a new one
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path[] paths, float end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return paths.Concat(new[] {new Path(paths.Last().End, end, duration, delay, function)}).ToArray();
        }


        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path path, float end, ulong duration)
        {
            return path.ToArray().ContinueTo(end, duration);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path path, float end, ulong duration, AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, function);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path path, float end, ulong duration, ulong delay)
        {
            return path.ToArray().ContinueTo(end, duration, delay);
        }

        /// <summary>
        ///     Continue the path with a new one
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="end">Next point to follow</param>
        /// <param name="duration">Duration of the animation</param>
        /// <param name="delay">Starting delay</param>
        /// <param name="function">Animation controller function</param>
        /// <returns>An array of paths including the newly created one</returns>
        public static Path[] ContinueTo(this Path path, float end, ulong duration, ulong delay,
            AnimationFunctions.Function function)
        {
            return path.ToArray().ContinueTo(end, duration, delay, function);
        }


        /// <summary>
        ///     Continue the path array with a new ones
        /// </summary>
        /// <param name="paths">Array of paths</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path[] ContinueTo(this Path[] paths, params Path[] newPaths)
        {
            return paths.Concat(newPaths).ToArray();
        }

        /// <summary>
        ///     Continue the path with a new ones
        /// </summary>
        /// <param name="path">The path to continue</param>
        /// <param name="newPaths">An array of new paths to adds</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path[] ContinueTo(this Path path, params Path[] newPaths)
        {
            return path.ToArray().ContinueTo(newPaths);
        }

        /// <summary>
        ///     Contains a single path in an array
        /// </summary>
        /// <param name="path">The path to add to the array</param>
        /// <returns>An array of paths including the new ones</returns>
        public static Path[] ToArray(this Path path)
        {
            return new[] {path};
        }
    }
}

================================================
FILE: WinFormAnimation/SafeInvoker.cs
================================================
using System;
using System.Reflection;
using System.Threading;

namespace WinFormAnimation
{
    /// <summary>
    ///     The safe invoker class is a delegate reference holder that always
    ///     execute them in the correct thread based on the passed control.
    /// </summary>
    public class SafeInvoker
    {
        private MethodInfo _invokeMethod;

        private PropertyInfo _invokeRequiredProperty;
        private object _targetControl;

        /// <summary>
        ///     Initializes a new instance of the SafeInvoker class.
        /// </summary>
        /// <param name="action">
        ///     The callback to be invoked
        /// </param>
        /// <param name="targetControl">
        ///     The control to be used to invoke the callback in UI thread
        /// </param>
        public SafeInvoker(Action action, object targetControl) : this((Delegate) action, targetControl)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the SafeInvoker class.
        /// </summary>
        /// <param name="action">
        ///     The callback to be invoked
        /// </param>
        /// <param name="targetControl">
        ///     The control to be used to invoke the callback in UI thread
        /// </param>
        protected SafeInvoker(Delegate action, object targetControl)
        {
            UnderlyingDelegate = action;
            if (targetControl != null)
            {
                TargetControl = targetControl;
            }
        }

        /// <summary>
        ///     Initializes a new instance of the SafeInvoker class.
        /// </summary>
        /// <param name="action">
        ///     The callback to be invoked
        /// </param>
        public SafeInvoker(Action action) : this(action, null)
        {
        }

        /// <summary>
        ///     Gets or sets the reference to the control thats going to be used to invoke the callback in UI thread
        /// </summary>
        protected object TargetControl
        {
            get { return _targetControl; }
            set
            {
                _invokeRequiredProperty = value.GetType()
                    .GetProperty("InvokeRequired", BindingFlags.Instance | BindingFlags.Public);
                _invokeMethod = value.GetType()
                    .GetMethod(
                        "Invoke",
                        BindingFlags.Instance | BindingFlags.Public,
                        Type.DefaultBinder,
                        new[] {typeof(Delegate)},
                        null);
                if (_invokeRequiredProperty != null && _invokeMethod != null)
                {
                    _targetControl = value;
                }
            }
        }


        /// <summary>
        ///     Gets the reference to the callback to be invoked
        /// </summary>
        protected Delegate UnderlyingDelegate { get; }

        /// <summary>
        ///     Invoke the contained callback
        /// </summary>
        public virtual void Invoke()
        {
            Invoke(null);
        }

        /// <summary>
        ///     Invoke the referenced callback
        /// </summary>
        /// <param name="value">The argument to send to the callback</param>
        protected void Invoke(object value)
        {
            try
            {
                ThreadPool.QueueUserWorkItem(
                    state =>
                    {
                        try
                        {
                            if (TargetControl != null && (bool)_invokeRequiredProperty.GetValue(TargetControl, null))
                            {
                                _invokeMethod.Invoke(
                                    TargetControl,
                                    new object[]
                                    {
                                    new Action(
                                        () => UnderlyingDelegate.DynamicInvoke(value != null ? new[] {value} : null))
                                    });
                                return;
                            }
                        }
                        catch
                        {
                            // ignored
                        }
                        UnderlyingDelegate.DynamicInvoke(value != null ? new[] {value} : null);
                    });
            }
            catch
            {
                // ignored
            }
        }
    }
}

================================================
FILE: WinFormAnimation/SafeInvoker`1.cs
================================================
using System;

namespace WinFormAnimation
{
    /// <summary>
    ///     The safe invoker class is a delegate reference holder that always
    ///     execute them in the correct thread based on the passed control.
    /// </summary>
    public class SafeInvoker<T> : SafeInvoker
    {
        /// <summary>
        ///     Initializes a new instance of the SafeInvoker class.
        /// </summary>
        /// <param name="action">
        ///     The callback to be invoked
        /// </param>
        /// <param name="targetControl">
        ///     The control to be used to invoke the callback in UI thread
        /// </param>
        public SafeInvoker(Action<T> action, object targetControl) : base(action, targetControl)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the SafeInvoker class.
        /// </summary>
        /// <param name="action">
        ///     The callback to be invoked
        /// </param>
        public SafeInvoker(Action<T> action) : this(action, null)
        {
        }

        /// <summary>
        ///     Invoke the contained callback with the specified value as the parameter
        /// </summary>
        /// <param name="value"></param>
        public void Invoke(T value)
        {
            Invoke((object) value);
        }
    }
}

================================================
FILE: WinFormAnimation/Timer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace WinFormAnimation
{
    /// <summary>
    ///     The timer class, will execute your code in specific time frames
    /// </summary>
    public class Timer
    {
        private static Thread _timerThread;

        private static readonly object LockHandle = new object();

        private static readonly long StartTimeAsMs = DateTime.Now.Ticks;

        private static readonly List<Timer> Subscribers = new List<Timer>();

        private readonly Action<ulong> _callback;

        /// <summary>
        ///     Initializes a new instance of the <see cref="Timer" /> class.
        /// </summary>
        /// <param name="callback">
        ///     The callback to be executed at each tick
        /// </param>
        /// <param name="fpsKnownLimit">
        ///     The max ticks per second
        /// </param>
        public Timer(Action<ulong> callback, FPSLimiterKnownValues fpsKnownLimit = FPSLimiterKnownValues.LimitThirty)
            : this(callback, (int) fpsKnownLimit)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Timer" /> class.
        /// </summary>
        /// <param name="callback">
        ///     The callback to be executed at each tick
        /// </param>
        /// <param name="fpsLimit">
        ///     The max ticks per second
        /// </param>
        public Timer(Action<ulong> callback, int fpsLimit)
        {
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            _callback = callback;
            FrameLimiter = fpsLimit;
            lock (LockHandle)
            {
                if (_timerThread == null)
                {
                    (_timerThread = new Thread(ThreadCycle) {IsBackground = true}).Start();
                }
            }
        }

        /// <summary>
        ///     Gets the time of the last frame/tick related to the global-timer start reference
        /// </summary>
        public long LastTick { get; private set; }

        /// <summary>
        ///     Gets or sets the maximum frames/ticks per second
        /// </summary>
        public int FrameLimiter { get; set; }

        /// <summary>
        ///     Gets the time of the first frame/tick related to the global-timer start reference
        /// </summary>
        public long FirstTick { get; private set; }


        private void Tick()
        {
            if ((1000/FrameLimiter) < (GetTimeDifferenceAsMs() - LastTick))
            {
                LastTick = GetTimeDifferenceAsMs();
                _callback((ulong) (LastTick - FirstTick));
            }
        }

        private static long GetTimeDifferenceAsMs()
        {
            return (DateTime.Now.Ticks - StartTimeAsMs)/10000;
        }

        private static void ThreadCycle()
        {
            while (true)
            {
                try
                {
                    bool hibernate;
                    lock (Subscribers)
                    {
                        hibernate = Subscribers.Count == 0;
                        if (!hibernate)
                        {
                            foreach (var t in Subscribers.ToList())
                            {
                                t.Tick();
                            }
                        }
                    }

                    Thread.Sleep(hibernate ? 50 : 1);
                }
                catch
                {
                    // ignored
                }
            }
            // ReSharper disable once FunctionNeverReturns
        }

        /// <summary>
        ///     The method to reset the time of the starting frame/tick
        /// </summary>
        public void ResetClock()
        {
            FirstTick = GetTimeDifferenceAsMs();
        }

        /// <summary>
        ///     The method to resume the timer after stopping it
        /// </summary>
        public void Resume()
        {
            lock (Subscribers)
                if (!Subscribers.Contains(this))
                {
                    FirstTick += GetTimeDifferenceAsMs() - LastTick;
                    Subscribers.Add(this);
                }
        }

        /// <summary>
        ///     The method to start the timer from the beginning
        /// </summary>
        public void Start()
        {
            lock (Subscribers)
                if (!Subscribers.Contains(this))
                {
                    FirstTick = GetTimeDifferenceAsMs();
                    Subscribers.Add(this);
                }
        }

        /// <summary>
        ///     The method to stop the timer from generating any new ticks/frames
        /// </summary>
        public void Stop()
        {
            lock (Subscribers)
                if (Subscribers.Contains(this))
                {
                    Subscribers.Remove(this);
                }
        }
    }
}

================================================
FILE: WinFormAnimation/WinFormAnimation.csproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net4</TargetFrameworks>
    <PackageId>WinFormAnimation</PackageId>
    <Version>1.6.0.4</Version>
    <Authors>Soroush Falahati</Authors>
    <Description>A simple library for animating controls/values in .Net using key-frames.</Description>
    <PackageLicenseUrl>https://github.com/falahati/WinFormAnimation/blob/master/LICENSE</PackageLicenseUrl>
    <PackageProjectUrl>https://falahati.github.io/WinFormAnimation/</PackageProjectUrl>
    <PackageIconUrl>https://github.com/falahati/WinFormAnimation/blob/master/WinFormAnimation/Icon.png?raw=true</PackageIconUrl>
    <RepositoryUrl>https://github.com/falahati/WinFormAnimatio</RepositoryUrl>
    <IncludeSymbols>true</IncludeSymbols>
    <IncludeSource>true</IncludeSource>
    <NeutralLanguage>en-US</NeutralLanguage>
    <Copyright>Copyright (c) 2019 Soroush Falahati</Copyright>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <Title>Key-Frame Based Animation Library (.Net 4+)</Title>
    <AssemblyOriginatorKeyFile>OpenSourceStrongNameSignKey.pfx</AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference PrivateAssets="all" Include="MSBump" Version="2.3.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="Icon.png">
      <Pack>true</Pack>
      <PackagePath>\</PackagePath>
    </Content>
    <Content Include="readme.txt">
      <Pack>true</Pack>
      <PackagePath>\</PackagePath>
    </Content>
  </ItemGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <OutputPath>..\Debug</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <BumpRevision>True</BumpRevision>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <OutputPath>..\Release</OutputPath>
    <SignAssembly>true</SignAssembly>
  </PropertyGroup>
</Project>

================================================
FILE: WinFormAnimation/float2D.cs
================================================
using System;
using System.Drawing;

namespace WinFormAnimation
{
    /// <summary>
    ///     The Float2D class contains two <see langword="float" /> values and
    ///     represents a point in a 2D plane
    /// </summary>
    public class Float2D : IConvertible, IEquatable<Float2D>, IEquatable<Point>, IEquatable<PointF>, IEquatable<Size>,
        IEquatable<SizeF>
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Float2D" /> class.
        /// </summary>
        /// <param name="x">
        ///     The horizontal value
        /// </param>
        /// <param name="y">
        ///     The vertical value
        /// </param>
        public Float2D(float x, float y)
        {
            X = x;
            Y = y;
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Float2D" /> class.
        /// </summary>
        public Float2D() : this(default(float), default(float))
        {
        }

        /// <summary>
        ///     Gets the horizontal value of the point
        /// </summary>
        public float X { get; set; }

        /// <summary>
        ///     Gets the vertical value of the point
        /// </summary>
        public float Y { get; set; }

        /// <summary>
        ///     Returns the <see cref="T:System.TypeCode" /> for this instance.
        /// </summary>
        /// <returns>
        ///     The enumerated constant that is the <see cref="T:System.TypeCode" /> of the class or value type that implements
        ///     this interface.
        /// </returns>
        public TypeCode GetTypeCode()
        {
            return TypeCode.Object;
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting
        ///     information.
        /// </summary>
        /// <returns>
        ///     A Boolean value equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public bool ToBoolean(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 8-bit unsigned integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public byte ToByte(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent Unicode character using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     A Unicode character equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public char ToChar(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent <see cref="T:System.DateTime" /> using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.DateTime" /> instance equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public DateTime ToDateTime(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent <see cref="T:System.Decimal" /> number using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.Decimal" /> number equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public decimal ToDecimal(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent double-precision floating-point number using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A double-precision floating-point number equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public double ToDouble(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 16-bit signed integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public short ToInt16(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 32-bit signed integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public int ToInt32(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 64-bit signed integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public long ToInt64(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 8-bit signed integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public sbyte ToSByte(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent single-precision floating-point number using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A single-precision floating-point number equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public float ToSingle(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 16-bit unsigned integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public ushort ToUInt16(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 32-bit unsigned integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public uint ToUInt32(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 64-bit unsigned integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public ulong ToUInt64(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent <see cref="T:System.String" /> using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.String" /> instance equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        public string ToString(IFormatProvider provider)
        {
            return ToString();
        }

        /// <summary>
        ///     Converts the value of this instance to an <see cref="T:System.Object" /> of the specified
        ///     <see cref="T:System.Type" /> that has an equivalent value, using the specified culture-specific formatting
        ///     information.
        /// </summary>
        /// <returns>
        ///     An <see cref="T:System.Object" /> instance of type <paramref name="conversionType" /> whose value is equivalent to
        ///     the value of this instance.
        /// </returns>
        /// <param name="conversionType">The <see cref="T:System.Type" /> to which the value of this instance is converted. </param>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        public object ToType(Type conversionType, IFormatProvider provider)
        {
            if (conversionType == typeof (Point))
            {
                return (Point) this;
            }
            if (conversionType == typeof (Size))
            {
                return (Size) this;
            }
            if (conversionType == typeof (PointF))
            {
                return (PointF) this;
            }
            if (conversionType == typeof (SizeF))
            {
                return (SizeF) this;
            }
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        ///     true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(Float2D other)
        {
            return this == other;
        }

        /// <summary>
        ///     Indicates whether the current object is equal to a <see cref="Point" /> object.
        /// </summary>
        /// <returns>
        ///     true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(Point other)
        {
            return this == other;
        }

        /// <summary>
        ///     Indicates whether the current object is equal to a <see cref="PointF" /> object.
        /// </summary>
        /// <returns>
        ///     true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(PointF other)
        {
            return this == other;
        }

        /// <summary>
        ///     Indicates whether the current object is equal to a <see cref="Size" /> object.
        /// </summary>
        /// <returns>
        ///     true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(Size other)
        {
            return this == other;
        }

        /// <summary>
        ///     Indicates whether the current object is equal to a <see cref="SizeF" /> object.
        /// </summary>
        /// <returns>
        ///     true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(SizeF other)
        {
            return this == other;
        }

        /// <summary>
        ///     Determines whether the specified <see cref="T:System.Object" /> is equal to the current
        ///     <see cref="T:System.Object" />.
        /// </summary>
        /// <returns>
        ///     true if the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />;
        ///     otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object" /> to compare with the current <see cref="T:System.Object" />. </param>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            var conversionType = obj.GetType();
            if (conversionType == typeof (Point))
            {
                return this == (Point) obj;
            }
            if (conversionType == typeof (PointF))
            {
                return this == (PointF) obj;
            }
            if (conversionType == typeof (Size))
            {
                return this == (Size) obj;
            }
            if (conversionType == typeof (SizeF))
            {
                return this == (SizeF) obj;
            }
            return obj.GetType() == GetType() && Equals((Float2D) obj);
        }

        /// <summary>
        ///     Serves as a hash function for a particular type. This code will change of the values of the X and Y changes. Make
        ///     sure to not change the values while stored in a hash dependent data structure.
        /// </summary>
        /// <returns>
        ///     A hash code for the current <see cref="Float2D" />.
        /// </returns>
        public override int GetHashCode()
        {
            unchecked
            {
                // ReSharper disable NonReadonlyMemberInGetHashCode
                return (X.GetHashCode()*397) ^ Y.GetHashCode();
                // ReSharper restore NonReadonlyMemberInGetHashCode
            }
        }

        /// <summary>
        ///     Compares two <see cref="Float2D" /> objects for equality
        /// </summary>
        /// <param name="left">Left <see cref="Float2D" /> object</param>
        /// <param name="right">Right <see cref="Float2D" /> object</param>
        /// <returns>true if both objects are equal, otherwise false</returns>
        public static bool operator ==(Float2D left, Float2D right)
        {
            if (ReferenceEquals(left, null) || ReferenceEquals(right, null))
            {
                return ReferenceEquals(left, null) && ReferenceEquals(right, null);
            }
            // ReSharper disable CompareOfFloatsByEqualityOperator
            return ReferenceEquals(left, right) || ((double) (left.X) == right.X && (double) (left.Y) == right.Y);
            // ReSharper restore CompareOfFloatsByEqualityOperator
        }

        /// <summary>
        ///     Compares two <see cref="Float2D" /> objects for in-equality
        /// </summary>
        /// <param name="left">Left <see cref="Float2D" /> object</param>
        /// <param name="right">Right <see cref="Float2D" /> object</param>
        /// <returns>false if both objects are equal, otherwise true</returns>
        public static bool operator !=(Float2D left, Float2D right)
        {
            return !(left == right);
        }

        /// <summary>
        ///     Represents the values as an instance of the <see cref="Size" /> class
        /// </summary>
        /// <param name="float2D">
        ///     The <see cref="Float2D" /> class to convert
        /// </param>
        /// <returns>
        ///     A new instance of the <see cref="Size" /> class representing the values in the <see cref="Float2D" /> instance
        /// </returns>
        public static implicit operator Size(Float2D float2D)
        {
            return new Size((int) float2D.X, (int) float2D.Y);
        }

        /// <summary>
        ///     Represents the values as an instance of the <see cref="Point" /> class
        /// </summary>
        /// <param name="float2D">
        ///     The <see cref="Float2D" /> class to convert
        /// </param>
        /// <returns>
        ///     A new instance of the <see cref="Point" /> class representing the values in the <see cref="Float2D" /> instance
        /// </returns>
        public static implicit operator Point(Float2D float2D)
        {
            return new Point((int) float2D.X, (int) float2D.Y);
        }


        /// <summary>
        ///     Represents the values as an instance of the <see cref="SizeF" /> class
        /// </summary>
        /// <param name="float2D">
        ///     The <see cref="Float2D" /> class to convert
        /// </param>
        /// <returns>
        ///     A new instance of the <see cref="SizeF" /> class representing the values in the <see cref="Float2D" /> instance
        /// </returns>
        public static implicit operator SizeF(Float2D float2D)
        {
            return new SizeF(float2D.X, float2D.Y);
        }

        /// <summary>
        ///     Represents the values as an instance of the <see cref="PointF" /> class
        /// </summary>
        /// <param name="float2D">
        ///     The <see cref="Float2D" /> class to convert
        /// </param>
        /// <returns>
        ///     A new instance of the <see cref="PointF" /> class representing the values in the <see cref="Float2D" /> instance
        /// </returns>
        public static implicit operator PointF(Float2D float2D)
        {
            return new PointF(float2D.X, float2D.Y);
        }

        /// <summary>
        ///     Returns a string that represents the current <see cref="Float2D" />.
        /// </summary>
        /// <returns>
        ///     A string that represents the current <see cref="Float2D" />.
        /// </returns>
        public override string ToString()
        {
            return "(" + X.ToString("0.00") + "," + Y.ToString("0.00") + ")";
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from a <see cref="Point" /> instance
        /// </summary>
        /// <param name="point">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D FromPoint(Point point)
        {
            return new Float2D(point.X, point.Y);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from a <see cref="PointF" /> instance
        /// </summary>
        /// <param name="point">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D FromPoint(PointF point)
        {
            return new Float2D(point.X, point.Y);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from a <see cref="Size" /> instance
        /// </summary>
        /// <param name="size">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D FromSize(Size size)
        {
            return new Float2D(size.Width, size.Height);
        }

        /// <summary>
        ///     Creates and returns a new instance of the <see cref="Float2D" /> class from a <see cref="SizeF" /> instance
        /// </summary>
        /// <param name="size">The object to create the <see cref="Float2D" /> instance from</param>
        /// <returns>The newly created <see cref="Float2D" /> instance</returns>
        public static Float2D FromSize(SizeF size)
        {
            return new Float2D(size.Width, size.Height);
        }
    }
}

================================================
FILE: WinFormAnimation/float3D.cs
================================================
using System;
using System.Drawing;

namespace WinFormAnimation
{
    /// <summary>
    ///     The Float3D class contains two <see langword="float" /> values and
    ///     represents a point in a 3D plane
    /// </summary>
    public class Float3D : IConvertible, IEquatable<Float3D>, IEquatable<Color>
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="Float3D" /> class.
        /// </summary>
        /// <param name="x">
        ///     The horizontal value
        /// </param>
        /// <param name="y">
        ///     The vertical value
        /// </param>
        /// <param name="z">
        ///     The depth value
        /// </param>
        public Float3D(float x, float y, float z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="Float3D" /> class.
        /// </summary>
        public Float3D() : this(default(float), default(float), default(float))
        {
        }

        /// <summary>
        ///     Gets the horizontal value of the point
        /// </summary>
        public float X { get; set; }

        /// <summary>
        ///     Gets the vertical value of the point
        /// </summary>
        public float Y { get; set; }

        /// <summary>
        ///     Gets the depth value of the point
        /// </summary>
        public float Z { get; set; }

        /// <summary>
        ///     Returns the <see cref="T:System.TypeCode" /> for this instance.
        /// </summary>
        /// <returns>
        ///     The enumerated constant that is the <see cref="T:System.TypeCode" /> of the class or value type that implements
        ///     this interface.
        /// </returns>
        public TypeCode GetTypeCode()
        {
            return TypeCode.Object;
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting
        ///     information.
        /// </summary>
        /// <returns>
        ///     A Boolean value equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public bool ToBoolean(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     An 8-bit unsigned integer equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public byte ToByte(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        /// <summary>
        ///     Converts the value of this instance to an equivalent Unicode character using the specified culture-specific
        ///     formatting information.
        /// </summary>
        /// <returns>
        ///     A Unicode character equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public char ToChar(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent <see cref="T:System.DateTime" /> using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.DateTime" /> instance equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public DateTime ToDateTime(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent <see cref="T:System.Decimal" /> number using the specified
        ///     culture-specific formatting information.
        /// </summary>
        /// <returns>
        ///     A <see cref="T:System.Decimal" /> number equivalent to the value of this instance.
        /// </returns>
        /// <param name="provider">
        ///     An <see cref="T:System.IFormatProvider" /> interface implementation that supplies
        ///     culture-specific formatting information.
        /// </param>
        /// <exception cref="InvalidCastException">This method is not supported</exception>
        public decimal ToDecimal(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }


        /// <summary>
        ///     Converts the value of this instance to an equivalent double-precision floating-point number using the specified
        ///     culture-specific formatting information.
        /// </summary>
Download .txt
gitextract_akg5khpk/

├── .gitignore
├── LICENSE
├── README.md
├── WinFormAnimation/
│   ├── AnimationFunctions.cs
│   ├── Animator.cs
│   ├── Animator2D.cs
│   ├── Animator3D.cs
│   ├── AnimatorStatus.cs
│   ├── FPSLimiterKnownValues.cs
│   ├── FloatExtensions.cs
│   ├── IAnimator.cs
│   ├── KnownAnimationFunctions.cs
│   ├── Path.cs
│   ├── Path2D.cs
│   ├── Path2DExtensions.cs
│   ├── Path3D.cs
│   ├── Path3DExtensions.cs
│   ├── PathExtensions.cs
│   ├── SafeInvoker.cs
│   ├── SafeInvoker`1.cs
│   ├── Timer.cs
│   ├── WinFormAnimation.csproj
│   ├── float2D.cs
│   ├── float3D.cs
│   └── readme.txt
├── WinFormAnimation.Samples/
│   ├── Demo1.Designer.cs
│   ├── Demo1.cs
│   ├── Demo1.resx
│   ├── Demo2.Designer.cs
│   ├── Demo2.cs
│   ├── Demo2.resx
│   ├── Demo3.Designer.cs
│   ├── Demo3.cs
│   ├── Demo3.resx
│   ├── Demo4.Designer.cs
│   ├── Demo4.cs
│   ├── Demo4.resx
│   ├── MainForm.Designer.cs
│   ├── MainForm.cs
│   ├── MainForm.resx
│   ├── Program.cs
│   ├── Properties/
│   │   ├── AssemblyInfo.cs
│   │   ├── Resources.Designer.cs
│   │   ├── Resources.resx
│   │   ├── Settings.Designer.cs
│   │   └── Settings.settings
│   ├── WinFormAnimation.Samples.csproj
│   └── app.config
├── WinFormAnimation.sln
└── WinFormAnimation.sln.DotSettings
Download .txt
SYMBOL INDEX (311 symbols across 33 files)

FILE: WinFormAnimation.Samples/Demo1.Designer.cs
  class Demo1 (line 3) | partial class Demo1
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 27) | private void InitializeComponent()

FILE: WinFormAnimation.Samples/Demo1.cs
  class Demo1 (line 6) | internal partial class Demo1 : UserControl
    method Demo1 (line 10) | public Demo1()
    method PlayButton (line 16) | private void PlayButton(object sender, EventArgs e)
    method StopButton (line 21) | private void StopButton(object sender, EventArgs e)
    method ResumeButton (line 26) | private void ResumeButton(object sender, EventArgs e)
    method PauseButton (line 31) | private void PauseButton(object sender, EventArgs e)

FILE: WinFormAnimation.Samples/Demo2.Designer.cs
  class Demo2 (line 3) | partial class Demo2
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 27) | private void InitializeComponent()

FILE: WinFormAnimation.Samples/Demo2.cs
  class Demo2 (line 6) | internal partial class Demo2 : UserControl
    method Demo2 (line 10) | public Demo2()
    method PlayButton (line 21) | private void PlayButton(object sender, EventArgs e)
    method StopButton (line 26) | private void StopButton(object sender, EventArgs e)
    method ResumeButton (line 31) | private void ResumeButton(object sender, EventArgs e)
    method PauseButton (line 36) | private void PauseButton(object sender, EventArgs e)
    method RepeatChecked (line 41) | private void RepeatChecked(object sender, EventArgs e)
    method ReverseChecked (line 47) | private void ReverseChecked(object sender, EventArgs e)

FILE: WinFormAnimation.Samples/Demo3.Designer.cs
  class Demo3 (line 3) | partial class Demo3
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 27) | private void InitializeComponent()

FILE: WinFormAnimation.Samples/Demo3.cs
  class Demo3 (line 8) | internal partial class Demo3 : UserControl
    method Demo3 (line 12) | public Demo3()
    method PlayButton (line 17) | private void PlayButton(object sender, EventArgs e)
    method StopButton (line 29) | private void StopButton(object sender, EventArgs e)
    method ResumeButton (line 34) | private void ResumeButton(object sender, EventArgs e)
    method PauseButton (line 39) | private void PauseButton(object sender, EventArgs e)

FILE: WinFormAnimation.Samples/Demo4.Designer.cs
  class Demo4 (line 3) | partial class Demo4
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 27) | private void InitializeComponent()

FILE: WinFormAnimation.Samples/Demo4.cs
  class Demo4 (line 8) | internal partial class Demo4 : UserControl
    method Demo4 (line 17) | public Demo4()
    method RunButton (line 22) | private void RunButton(object sender, EventArgs e)
    method Hit (line 42) | private void Hit(float value)
    method End (line 47) | private void End()
    method Round (line 63) | private float Round(decimal n)

FILE: WinFormAnimation.Samples/MainForm.Designer.cs
  class MainForm (line 3) | partial class MainForm
    method Dispose (line 14) | protected override void Dispose(bool disposing)
    method InitializeComponent (line 27) | private void InitializeComponent()

FILE: WinFormAnimation.Samples/MainForm.cs
  class MainForm (line 6) | internal partial class MainForm : Form
    method MainForm (line 8) | public MainForm()
    method FormShown (line 13) | private void FormShown(object sender, EventArgs e)

FILE: WinFormAnimation.Samples/Program.cs
  class Program (line 6) | internal static class Program
    method Main (line 11) | [STAThread]

FILE: WinFormAnimation.Samples/Properties/Resources.Designer.cs
  class Resources (line 22) | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resource...
    method Resources (line 31) | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Mic...

FILE: WinFormAnimation.Samples/Properties/Settings.Designer.cs
  class Settings (line 14) | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

FILE: WinFormAnimation/AnimationFunctions.cs
  class AnimationFunctions (line 8) | public static class AnimationFunctions
    method FromKnown (line 35) | public static Function FromKnown(KnownAnimationFunctions knownFunction)
    method CubicEaseIn (line 108) | public static float CubicEaseIn(float t, float b, float c, float d)
    method CubicEaseInOut (line 132) | public static float CubicEaseInOut(float t, float b, float c, float d)
    method CubicEaseOut (line 160) | public static float CubicEaseOut(float t, float b, float c, float d)
    method Linear (line 185) | public static float Linear(float t, float b, float c, float d)
    method CircularEaseInOut (line 208) | public static float CircularEaseInOut(float t, float b, float c, float d)
    method CircularEaseIn (line 236) | public static float CircularEaseIn(float t, float b, float c, float d)
    method CircularEaseOut (line 261) | public static float CircularEaseOut(float t, float b, float c, float d)
    method QuadraticEaseIn (line 287) | public static float QuadraticEaseIn(float t, float b, float c, float d)
    method QuadraticEaseOut (line 312) | public static float QuadraticEaseOut(float t, float b, float c, float d)
    method QuadraticEaseInOut (line 337) | public static float QuadraticEaseInOut(float t, float b, float c, floa...
    method QuarticEaseIn (line 363) | public static float QuarticEaseIn(float t, float b, float c, float d)
    method QuarticEaseOut (line 387) | public static float QuarticEaseOut(float t, float b, float c, float d)
    method QuarticEaseInOut (line 412) | public static float QuarticEaseInOut(float t, float b, float c, float d)
    method QuinticEaseInOut (line 438) | public static float QuinticEaseInOut(float t, float b, float c, float d)
    method QuinticEaseIn (line 464) | public static float QuinticEaseIn(float t, float b, float c, float d)
    method QuinticEaseOut (line 488) | public static float QuinticEaseOut(float t, float b, float c, float d)
    method SinusoidalEaseIn (line 513) | public static float SinusoidalEaseIn(float t, float b, float c, float d)
    method SinusoidalEaseOut (line 536) | public static float SinusoidalEaseOut(float t, float b, float c, float d)
    method SinusoidalEaseInOut (line 559) | public static float SinusoidalEaseInOut(float t, float b, float c, flo...
    method ExponentialEaseIn (line 582) | public static float ExponentialEaseIn(float t, float b, float c, float d)
    method ExponentialEaseOut (line 605) | public static float ExponentialEaseOut(float t, float b, float c, floa...
    method ExponentialEaseInOut (line 629) | public static float ExponentialEaseInOut(float t, float b, float c, fl...

FILE: WinFormAnimation/Animator.cs
  class Animator (line 12) | public class Animator : IAnimator
    type KnownProperties (line 17) | public enum KnownProperties
    method Animator (line 76) | public Animator()
    method Animator (line 87) | public Animator(FPSLimiterKnownValues fpsLimiter)
    method Animator (line 98) | public Animator(Path path)
    method Animator (line 112) | public Animator(Path path, FPSLimiterKnownValues fpsLimiter)
    method Animator (line 123) | public Animator(Path[] paths) : this(paths, FPSLimiterKnownValues.Limi...
    method Animator (line 136) | public Animator(Path[] paths, FPSLimiterKnownValues fpsLimiter)
    method Pause (line 187) | public virtual void Pause()
    method Play (line 204) | public virtual void Play(object targetObject, string propertyName)
    method Play (line 221) | public virtual void Play(object targetObject, string propertyName, Saf...
    method Play (line 249) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Play (line 270) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Resume (line 294) | public virtual void Resume()
    method Stop (line 305) | public virtual void Stop()
    method Play (line 326) | public virtual void Play(object targetObject, KnownProperties property)
    method Play (line 344) | public virtual void Play(object targetObject, KnownProperties property...
    method Play (line 355) | public virtual void Play(SafeInvoker<float> frameCallback)
    method Play (line 370) | public virtual void Play(SafeInvoker<float> frameCallback, SafeInvoker...
    method Elapsed (line 383) | private void Elapsed(ulong millSinceBeginning = 0)

FILE: WinFormAnimation/Animator2D.cs
  class Animator2D (line 12) | public class Animator2D : IAnimator
    type KnownProperties (line 17) | public enum KnownProperties
    method Animator2D (line 67) | public Animator2D()
    method Animator2D (line 78) | public Animator2D(FPSLimiterKnownValues fpsLimiter)
    method Animator2D (line 89) | public Animator2D(Path2D path)
    method Animator2D (line 103) | public Animator2D(Path2D path, FPSLimiterKnownValues fpsLimiter)
    method Animator2D (line 115) | public Animator2D(Path2D[] paths) : this(paths, FPSLimiterKnownValues....
    method Animator2D (line 128) | public Animator2D(Path2D[] paths, FPSLimiterKnownValues fpsLimiter)
    method Pause (line 232) | public virtual void Pause()
    method Play (line 250) | public virtual void Play(object targetObject, string propertyName)
    method Play (line 267) | public virtual void Play(object targetObject, string propertyName, Saf...
    method Play (line 297) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Play (line 317) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Resume (line 342) | public virtual void Resume()
    method Stop (line 354) | public virtual void Stop()
    method Play (line 370) | public void Play(object targetObject, KnownProperties property)
    method Play (line 388) | public void Play(object targetObject, KnownProperties property, SafeIn...
    method Play (line 399) | public void Play(SafeInvoker<Float2D> frameCallback)
    method Play (line 413) | public void Play(SafeInvoker<Float2D> frameCallback, SafeInvoker endCa...
    method InvokeFinisher (line 436) | private void InvokeFinisher()
    method InvokeSetter (line 451) | private void InvokeSetter()

FILE: WinFormAnimation/Animator3D.cs
  class Animator3D (line 12) | public class Animator3D : IAnimator
    type KnownProperties (line 17) | public enum KnownProperties
    method Animator3D (line 71) | public Animator3D()
    method Animator3D (line 82) | public Animator3D(FPSLimiterKnownValues fpsLimiter)
    method Animator3D (line 93) | public Animator3D(Path3D path)
    method Animator3D (line 107) | public Animator3D(Path3D path, FPSLimiterKnownValues fpsLimiter)
    method Animator3D (line 118) | public Animator3D(Path3D[] paths) : this(paths, FPSLimiterKnownValues....
    method Animator3D (line 131) | public Animator3D(Path3D[] paths, FPSLimiterKnownValues fpsLimiter)
    method Pause (line 260) | public virtual void Pause()
    method Play (line 279) | public virtual void Play(object targetObject, string propertyName)
    method Play (line 296) | public virtual void Play(object targetObject, string propertyName, Saf...
    method Play (line 326) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Play (line 346) | public virtual void Play<T>(T targetObject, Expression<Func<T, object>...
    method Resume (line 371) | public virtual void Resume()
    method Stop (line 384) | public virtual void Stop()
    method Play (line 401) | public void Play(object targetObject, KnownProperties property)
    method Play (line 418) | public void Play(object targetObject, KnownProperties property, SafeIn...
    method Play (line 429) | public void Play(SafeInvoker<Float3D> frameCallback)
    method Play (line 443) | public void Play(SafeInvoker<Float3D> frameCallback, SafeInvoker endCa...
    method InvokeFinisher (line 475) | private void InvokeFinisher()
    method InvokeSetter (line 490) | private void InvokeSetter()

FILE: WinFormAnimation/AnimatorStatus.cs
  type AnimatorStatus (line 6) | public enum AnimatorStatus

FILE: WinFormAnimation/FPSLimiterKnownValues.cs
  type FPSLimiterKnownValues (line 6) | public enum FPSLimiterKnownValues

FILE: WinFormAnimation/FloatExtensions.cs
  class FloatExtensions (line 8) | public static class FloatExtensions
    method ToFloat2D (line 15) | public static Float2D ToFloat2D(this Point point)
    method ToFloat2D (line 25) | public static Float2D ToFloat2D(this PointF point)
    method ToFloat2D (line 35) | public static Float2D ToFloat2D(this Size size)
    method ToFloat2D (line 45) | public static Float2D ToFloat2D(this SizeF size)
    method ToFloat3D (line 55) | public static Float3D ToFloat3D(this Color color)

FILE: WinFormAnimation/IAnimator.cs
  type IAnimator (line 9) | public interface IAnimator
    method Play (line 35) | void Play(object targetObject, string propertyName);
    method Play (line 49) | void Play(object targetObject, string propertyName, SafeInvoker endCal...
    method Play (line 63) | void Play<T>(T targetObject, Expression<Func<T, object>> propertySetter);
    method Play (line 80) | void Play<T>(T targetObject, Expression<Func<T, object>> propertySette...
    method Resume (line 85) | void Resume();
    method Stop (line 90) | void Stop();
    method Pause (line 95) | void Pause();

FILE: WinFormAnimation/KnownAnimationFunctions.cs
  type KnownAnimationFunctions (line 6) | public enum KnownAnimationFunctions

FILE: WinFormAnimation/Path.cs
  class Path (line 9) | public class Path
    method Path (line 14) | public Path() : this(default(float), default(float), default(ulong), 0...
    method Path (line 33) | public Path(float start, float end, ulong duration) : this(start, end,...
    method Path (line 55) | public Path(float start, float end, ulong duration, AnimationFunctions...
    method Path (line 78) | public Path(float start, float end, ulong duration, ulong delay) : thi...
    method Path (line 103) | public Path(float start, float end, ulong duration, ulong delay, Anima...
    method Reverse (line 148) | public Path Reverse()

FILE: WinFormAnimation/Path2D.cs
  class Path2D (line 9) | public class Path2D
    method Path2D (line 38) | public Path2D(
    method Path2D (line 74) | public Path2D(
    method Path2D (line 109) | public Path2D(
    method Path2D (line 141) | public Path2D(
    method Path2D (line 172) | public Path2D(Float2D start, Float2D end, ulong duration, ulong delay,...
    method Path2D (line 197) | public Path2D(Float2D start, Float2D end, ulong duration, ulong delay)
    method Path2D (line 222) | public Path2D(Float2D start, Float2D end, ulong duration, AnimationFun...
    method Path2D (line 244) | public Path2D(Float2D start, Float2D end, ulong duration)
    method Path2D (line 260) | public Path2D(Path x, Path y)
    method Reverse (line 293) | public Path2D Reverse()

FILE: WinFormAnimation/Path2DExtensions.cs
  class Path2DExtensions (line 8) | public static class Path2DExtensions
    method ContinueTo (line 17) | public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ul...
    method ContinueTo (line 30) | public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ul...
    method ContinueTo (line 44) | public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ul...
    method ContinueTo (line 58) | public static Path2D[] ContinueTo(this Path2D[] paths, Float2D end, ul...
    method ContinueTo (line 72) | public static Path2D[] ContinueTo(this Path2D[] paths, float endX, flo...
    method ContinueTo (line 86) | public static Path2D[] ContinueTo(this Path2D[] paths, float endX, flo...
    method ContinueTo (line 103) | public static Path2D[] ContinueTo(this Path2D[] paths, float endX, flo...
    method ContinueTo (line 119) | public static Path2D[] ContinueTo(this Path2D[] paths, float endX, flo...
    method ContinueTo (line 134) | public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong...
    method ContinueTo (line 147) | public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong...
    method ContinueTo (line 161) | public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong...
    method ContinueTo (line 175) | public static Path2D[] ContinueTo(this Path2D path, Float2D end, ulong...
    method ContinueTo (line 189) | public static Path2D[] ContinueTo(this Path2D path, float endX, float ...
    method ContinueTo (line 203) | public static Path2D[] ContinueTo(this Path2D path, float endX, float ...
    method ContinueTo (line 218) | public static Path2D[] ContinueTo(this Path2D path, float endX, float ...
    method ContinueTo (line 233) | public static Path2D[] ContinueTo(this Path2D path, float endX, float ...
    method ContinueTo (line 245) | public static Path2D[] ContinueTo(this Path2D[] paths, params Path2D[]...
    method ContinueTo (line 256) | public static Path2D[] ContinueTo(this Path2D path, params Path2D[] ne...
    method ToArray (line 266) | public static Path2D[] ToArray(this Path2D path)

FILE: WinFormAnimation/Path3D.cs
  class Path3D (line 9) | public class Path3D
    method Path3D (line 44) | public Path3D(
    method Path3D (line 91) | public Path3D(
    method Path3D (line 137) | public Path3D(
    method Path3D (line 180) | public Path3D(
    method Path3D (line 213) | public Path3D(Float3D start, Float3D end, ulong duration, ulong delay,...
    method Path3D (line 239) | public Path3D(Float3D start, Float3D end, ulong duration, ulong delay)
    method Path3D (line 265) | public Path3D(Float3D start, Float3D end, ulong duration, AnimationFun...
    method Path3D (line 288) | public Path3D(Float3D start, Float3D end, ulong duration)
    method Path3D (line 308) | public Path3D(Path x, Path y, Path z)
    method Reverse (line 348) | public Path3D Reverse()

FILE: WinFormAnimation/Path3DExtensions.cs
  class Path3DExtensions (line 8) | public static class Path3DExtensions
    method ContinueTo (line 17) | public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ul...
    method ContinueTo (line 30) | public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ul...
    method ContinueTo (line 44) | public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ul...
    method ContinueTo (line 58) | public static Path3D[] ContinueTo(this Path3D[] paths, Float3D end, ul...
    method ContinueTo (line 73) | public static Path3D[] ContinueTo(this Path3D[] paths, float endX, flo...
    method ContinueTo (line 88) | public static Path3D[] ContinueTo(this Path3D[] paths, float endX, flo...
    method ContinueTo (line 106) | public static Path3D[] ContinueTo(this Path3D[] paths, float endX, flo...
    method ContinueTo (line 125) | public static Path3D[] ContinueTo(this Path3D[] paths, float endX, flo...
    method ContinueTo (line 143) | public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong...
    method ContinueTo (line 156) | public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong...
    method ContinueTo (line 170) | public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong...
    method ContinueTo (line 184) | public static Path3D[] ContinueTo(this Path3D path, Float3D end, ulong...
    method ContinueTo (line 199) | public static Path3D[] ContinueTo(this Path3D path, float endX, float ...
    method ContinueTo (line 214) | public static Path3D[] ContinueTo(this Path3D path, float endX, float ...
    method ContinueTo (line 230) | public static Path3D[] ContinueTo(this Path3D path, float endX, float ...
    method ContinueTo (line 247) | public static Path3D[] ContinueTo(this Path3D path, float endX, float ...
    method ContinueTo (line 261) | public static Path3D[] ContinueTo(this Path3D[] paths, params Path3D[]...
    method ContinueTo (line 272) | public static Path3D[] ContinueTo(this Path3D path, params Path3D[] ne...
    method ToArray (line 282) | public static Path3D[] ToArray(this Path3D path)

FILE: WinFormAnimation/PathExtensions.cs
  class PathExtensions (line 8) | public static class PathExtensions
    method ContinueTo (line 17) | public static Path[] ContinueTo(this Path[] paths, float end, ulong du...
    method ContinueTo (line 30) | public static Path[] ContinueTo(this Path[] paths, float end, ulong du...
    method ContinueTo (line 44) | public static Path[] ContinueTo(this Path[] paths, float end, ulong du...
    method ContinueTo (line 58) | public static Path[] ContinueTo(this Path[] paths, float end, ulong du...
    method ContinueTo (line 72) | public static Path[] ContinueTo(this Path path, float end, ulong durat...
    method ContinueTo (line 85) | public static Path[] ContinueTo(this Path path, float end, ulong durat...
    method ContinueTo (line 98) | public static Path[] ContinueTo(this Path path, float end, ulong durat...
    method ContinueTo (line 112) | public static Path[] ContinueTo(this Path path, float end, ulong durat...
    method ContinueTo (line 125) | public static Path[] ContinueTo(this Path[] paths, params Path[] newPa...
    method ContinueTo (line 136) | public static Path[] ContinueTo(this Path path, params Path[] newPaths)
    method ToArray (line 146) | public static Path[] ToArray(this Path path)

FILE: WinFormAnimation/SafeInvoker.cs
  class SafeInvoker (line 11) | public class SafeInvoker
    method SafeInvoker (line 27) | public SafeInvoker(Action action, object targetControl) : this((Delega...
    method SafeInvoker (line 40) | protected SafeInvoker(Delegate action, object targetControl)
    method SafeInvoker (line 55) | public SafeInvoker(Action action) : this(action, null)
    method Invoke (line 92) | public virtual void Invoke()
    method Invoke (line 101) | protected void Invoke(object value)

FILE: WinFormAnimation/SafeInvoker`1.cs
  class SafeInvoker (line 9) | public class SafeInvoker<T> : SafeInvoker
    method SafeInvoker (line 20) | public SafeInvoker(Action<T> action, object targetControl) : base(acti...
    method SafeInvoker (line 30) | public SafeInvoker(Action<T> action) : this(action, null)
    method Invoke (line 38) | public void Invoke(T value)

FILE: WinFormAnimation/Timer.cs
  class Timer (line 11) | public class Timer
    method Timer (line 32) | public Timer(Action<ulong> callback, FPSLimiterKnownValues fpsKnownLim...
    method Timer (line 46) | public Timer(Action<ulong> callback, int fpsLimit)
    method Tick (line 80) | private void Tick()
    method GetTimeDifferenceAsMs (line 89) | private static long GetTimeDifferenceAsMs()
    method ThreadCycle (line 94) | private static void ThreadCycle()
    method ResetClock (line 126) | public void ResetClock()
    method Resume (line 134) | public void Resume()
    method Start (line 147) | public void Start()
    method Stop (line 160) | public void Stop()

FILE: WinFormAnimation/float2D.cs
  class Float2D (line 10) | public class Float2D : IConvertible, IEquatable<Float2D>, IEquatable<Poi...
    method Float2D (line 22) | public Float2D(float x, float y)
    method Float2D (line 31) | public Float2D() : this(default(float), default(float))
    method GetTypeCode (line 52) | public TypeCode GetTypeCode()
    method ToBoolean (line 69) | public bool ToBoolean(IFormatProvider provider)
    method ToByte (line 86) | public byte ToByte(IFormatProvider provider)
    method ToChar (line 103) | public char ToChar(IFormatProvider provider)
    method ToDateTime (line 121) | public DateTime ToDateTime(IFormatProvider provider)
    method ToDecimal (line 139) | public decimal ToDecimal(IFormatProvider provider)
    method ToDouble (line 157) | public double ToDouble(IFormatProvider provider)
    method ToInt16 (line 175) | public short ToInt16(IFormatProvider provider)
    method ToInt32 (line 192) | public int ToInt32(IFormatProvider provider)
    method ToInt64 (line 210) | public long ToInt64(IFormatProvider provider)
    method ToSByte (line 228) | public sbyte ToSByte(IFormatProvider provider)
    method ToSingle (line 246) | public float ToSingle(IFormatProvider provider)
    method ToUInt16 (line 263) | public ushort ToUInt16(IFormatProvider provider)
    method ToUInt32 (line 281) | public uint ToUInt32(IFormatProvider provider)
    method ToUInt64 (line 299) | public ulong ToUInt64(IFormatProvider provider)
    method ToString (line 315) | public string ToString(IFormatProvider provider)
    method ToType (line 334) | public object ToType(Type conversionType, IFormatProvider provider)
    method Equals (line 362) | public bool Equals(Float2D other)
    method Equals (line 374) | public bool Equals(Point other)
    method Equals (line 386) | public bool Equals(PointF other)
    method Equals (line 398) | public bool Equals(Size other)
    method Equals (line 410) | public bool Equals(SizeF other)
    method Equals (line 424) | public override bool Equals(object obj)
    method GetHashCode (line 455) | public override int GetHashCode()
    method ToString (line 556) | public override string ToString()
    method FromPoint (line 566) | public static Float2D FromPoint(Point point)
    method FromPoint (line 576) | public static Float2D FromPoint(PointF point)
    method FromSize (line 586) | public static Float2D FromSize(Size size)
    method FromSize (line 596) | public static Float2D FromSize(SizeF size)

FILE: WinFormAnimation/float3D.cs
  class Float3D (line 10) | public class Float3D : IConvertible, IEquatable<Float3D>, IEquatable<Color>
    method Float3D (line 24) | public Float3D(float x, float y, float z)
    method Float3D (line 34) | public Float3D() : this(default(float), default(float), default(float))
    method GetTypeCode (line 60) | public TypeCode GetTypeCode()
    method ToBoolean (line 78) | public bool ToBoolean(IFormatProvider provider)
    method ToByte (line 95) | public byte ToByte(IFormatProvider provider)
    method ToChar (line 112) | public char ToChar(IFormatProvider provider)
    method ToDateTime (line 130) | public DateTime ToDateTime(IFormatProvider provider)
    method ToDecimal (line 148) | public decimal ToDecimal(IFormatProvider provider)
    method ToDouble (line 166) | public double ToDouble(IFormatProvider provider)
    method ToInt16 (line 184) | public short ToInt16(IFormatProvider provider)
    method ToInt32 (line 201) | public int ToInt32(IFormatProvider provider)
    method ToInt64 (line 219) | public long ToInt64(IFormatProvider provider)
    method ToSByte (line 237) | public sbyte ToSByte(IFormatProvider provider)
    method ToSingle (line 255) | public float ToSingle(IFormatProvider provider)
    method ToUInt16 (line 272) | public ushort ToUInt16(IFormatProvider provider)
    method ToUInt32 (line 290) | public uint ToUInt32(IFormatProvider provider)
    method ToUInt64 (line 308) | public ulong ToUInt64(IFormatProvider provider)
    method ToString (line 324) | public string ToString(IFormatProvider provider)
    method ToType (line 343) | public object ToType(Type conversionType, IFormatProvider provider)
    method Equals (line 359) | public bool Equals(Color other)
    method Equals (line 371) | public bool Equals(Float3D other)
    method Equals (line 385) | public override bool Equals(object obj)
    method GetHashCode (line 404) | public override int GetHashCode()
    method ToString (line 467) | public override string ToString()
    method FromColor (line 477) | public static Float3D FromColor(Color color)
Condensed preview — 50 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (313K chars).
[
  {
    "path": ".gitignore",
    "chars": 1543,
    "preview": "# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)\n[Bb]in/\n[Oo]bj/\n\n# mstest test results\nTestResu"
  },
  {
    "path": "LICENSE",
    "chars": 1074,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Soroush\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "README.md",
    "chars": 7490,
    "preview": "# <img src=\"WinFormAnimation/Icon.png\" width=\"42\" alt=\"Icon\"> WinForm Animation Library [.Net3.5+]\n[![](https://img.shie"
  },
  {
    "path": "WinFormAnimation/AnimationFunctions.cs",
    "chars": 21401,
    "preview": "using System;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The functions gallery for animation\n    /// <"
  },
  {
    "path": "WinFormAnimation/Animator.cs",
    "chars": 16625,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Linq.Expressions;\nusing System.Reflecti"
  },
  {
    "path": "WinFormAnimation/Animator2D.cs",
    "chars": 15387,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq.Expressions;\nusing System.Reflection;\n\nnamespace WinF"
  },
  {
    "path": "WinFormAnimation/Animator3D.cs",
    "chars": 16864,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq.Expressions;\nusing System.Reflection;\n\nnamespace WinF"
  },
  {
    "path": "WinFormAnimation/AnimatorStatus.cs",
    "chars": 620,
    "preview": "namespace WinFormAnimation\n{\n    /// <summary>\n    ///     The possible statuses for an animator instance\n    /// </sum"
  },
  {
    "path": "WinFormAnimation/FPSLimiterKnownValues.cs",
    "chars": 1077,
    "preview": "namespace WinFormAnimation\n{\n    /// <summary>\n    ///     FPS limiter known values\n    /// </summary>\n    public enum "
  },
  {
    "path": "WinFormAnimation/FloatExtensions.cs",
    "chars": 2504,
    "preview": "using System.Drawing;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     Contains public extension methods abo"
  },
  {
    "path": "WinFormAnimation/IAnimator.cs",
    "chars": 3354,
    "preview": "using System;\nusing System.Linq.Expressions;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The base inter"
  },
  {
    "path": "WinFormAnimation/KnownAnimationFunctions.cs",
    "chars": 3191,
    "preview": "namespace WinFormAnimation\n{\n    /// <summary>\n    ///     Contains a list of all known animation functions\n    /// </s"
  },
  {
    "path": "WinFormAnimation/Path.cs",
    "chars": 5208,
    "preview": "using System;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The Path class is a representation of a line "
  },
  {
    "path": "WinFormAnimation/Path2D.cs",
    "chars": 10411,
    "preview": "using System;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The Path2D class is a representation of a lin"
  },
  {
    "path": "WinFormAnimation/Path2DExtensions.cs",
    "chars": 13142,
    "preview": "using System.Linq;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     Contains public extensions methods about"
  },
  {
    "path": "WinFormAnimation/Path3D.cs",
    "chars": 12228,
    "preview": "using System;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The Path3D class is a representation of a lin"
  },
  {
    "path": "WinFormAnimation/Path3DExtensions.cs",
    "chars": 14005,
    "preview": "using System.Linq;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     Contains public extensions methods about"
  },
  {
    "path": "WinFormAnimation/PathExtensions.cs",
    "chars": 6654,
    "preview": "using System.Linq;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     Contains public extensions methods about"
  },
  {
    "path": "WinFormAnimation/SafeInvoker.cs",
    "chars": 4485,
    "preview": "using System;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    /// "
  },
  {
    "path": "WinFormAnimation/SafeInvoker`1.cs",
    "chars": 1327,
    "preview": "using System;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The safe invoker class is a delegate referenc"
  },
  {
    "path": "WinFormAnimation/Timer.cs",
    "chars": 5041,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\n\nnamespace WinFormAnimation\n"
  },
  {
    "path": "WinFormAnimation/WinFormAnimation.csproj",
    "chars": 2084,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFrameworks>net4</"
  },
  {
    "path": "WinFormAnimation/float2D.cs",
    "chars": 25027,
    "preview": "using System;\nusing System.Drawing;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The Float2D class conta"
  },
  {
    "path": "WinFormAnimation/float3D.cs",
    "chars": 20218,
    "preview": "using System;\nusing System.Drawing;\n\nnamespace WinFormAnimation\n{\n    /// <summary>\n    ///     The Float3D class conta"
  },
  {
    "path": "WinFormAnimation/readme.txt",
    "chars": 1128,
    "preview": "\t\t\t\t\t\t          WinForm Animation Library\n\t\t    A simple library for animating controls/values in .Net\n        WinForm ("
  },
  {
    "path": "WinFormAnimation.Samples/Demo1.Designer.cs",
    "chars": 4510,
    "preview": "namespace WinFormAnimation.Samples\n{\n    partial class Demo1\n    {\n        /// <summary> \n        /// Required designer"
  },
  {
    "path": "WinFormAnimation.Samples/Demo1.cs",
    "chars": 834,
    "preview": "using System;\nusing System.Windows.Forms;\n\nnamespace WinFormAnimation.Samples\n{\n    internal partial class Demo1 : User"
  },
  {
    "path": "WinFormAnimation.Samples/Demo1.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/Demo2.Designer.cs",
    "chars": 6284,
    "preview": "namespace WinFormAnimation.Samples\n{\n    partial class Demo2\n    {\n        /// <summary> \n        /// Required designer"
  },
  {
    "path": "WinFormAnimation.Samples/Demo2.cs",
    "chars": 1507,
    "preview": "using System;\nusing System.Windows.Forms;\n\nnamespace WinFormAnimation.Samples\n{\n    internal partial class Demo2 : User"
  },
  {
    "path": "WinFormAnimation.Samples/Demo2.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/Demo3.Designer.cs",
    "chars": 4545,
    "preview": "namespace WinFormAnimation.Samples\n{\n    partial class Demo3\n    {\n        /// <summary> \n        /// Required designer"
  },
  {
    "path": "WinFormAnimation.Samples/Demo3.cs",
    "chars": 1200,
    "preview": "using System;\nusing System.Drawing;\nusing System.Linq;\nusing System.Windows.Forms;\n\nnamespace WinFormAnimation.Samples\n"
  },
  {
    "path": "WinFormAnimation.Samples/Demo3.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/Demo4.Designer.cs",
    "chars": 9784,
    "preview": "namespace WinFormAnimation.Samples\n{\n    partial class Demo4\n    {\n        /// <summary> \n        /// Required designer"
  },
  {
    "path": "WinFormAnimation.Samples/Demo4.cs",
    "chars": 2309,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Windows.Forms;\n\nnamespace WinFor"
  },
  {
    "path": "WinFormAnimation.Samples/Demo4.resx",
    "chars": 5890,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/MainForm.Designer.cs",
    "chars": 7129,
    "preview": "namespace WinFormAnimation.Samples\n{\n    partial class MainForm\n    {\n        /// <summary>\n        /// Required design"
  },
  {
    "path": "WinFormAnimation.Samples/MainForm.cs",
    "chars": 395,
    "preview": "using System;\nusing System.Windows.Forms;\n\nnamespace WinFormAnimation.Samples\n{\n    internal partial class MainForm : F"
  },
  {
    "path": "WinFormAnimation.Samples/MainForm.resx",
    "chars": 5696,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/Program.cs",
    "chars": 463,
    "preview": "using System;\nusing System.Windows.Forms;\n\nnamespace WinFormAnimation.Samples\n{\n    internal static class Program\n    {"
  },
  {
    "path": "WinFormAnimation.Samples/Properties/AssemblyInfo.cs",
    "chars": 1345,
    "preview": "using System.Reflection;\nusing System.Runtime.InteropServices;\n\n// General Information about an assembly is controlled "
  },
  {
    "path": "WinFormAnimation.Samples/Properties/Resources.Designer.cs",
    "chars": 3178,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "WinFormAnimation.Samples/Properties/Resources.resx",
    "chars": 6076,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The prim"
  },
  {
    "path": "WinFormAnimation.Samples/Properties/Settings.Designer.cs",
    "chars": 1079,
    "preview": "//------------------------------------------------------------------------------\n// <auto-generated>\n//     This code w"
  },
  {
    "path": "WinFormAnimation.Samples/Properties/Settings.settings",
    "chars": 240,
    "preview": "<?xml version='1.0' encoding='utf-8'?>\n<SettingsFile xmlns=\"http://schemas.microsoft.com/VisualStudio/2004/01/settings\""
  },
  {
    "path": "WinFormAnimation.Samples/WinFormAnimation.Samples.csproj",
    "chars": 5269,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microso"
  },
  {
    "path": "WinFormAnimation.Samples/app.config",
    "chars": 141,
    "preview": "<?xml version=\"1.0\"?>\n<configuration>\n<startup><supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.0\"/></star"
  },
  {
    "path": "WinFormAnimation.sln",
    "chars": 1511,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.24720.0\nMini"
  },
  {
    "path": "WinFormAnimation.sln.DotSettings",
    "chars": 414,
    "preview": "<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namesp"
  }
]

About this extraction

This page contains the full source code of the falahati/WinFormAnimation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 50 files (292.0 KB), approximately 66.5k tokens, and a symbol index with 311 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!