/**
     * Generic bezier spline sequence generator used to implement the time and
     * slice variants. Normally you would not use this function directly.
     */
    public static IEnumerator NewBezier(EaseFunction ease, Transform[] nodes, TransformToPositionFunction toVector3, float maxStep, IEnumerator steps)
    {
        // need at least two nodes to spline between
        if (nodes.Length >= 2)
        {
            // copy nodes array since Bezier is destructive
            Vector3[] points = new Vector3[nodes.Length];

            while (steps.MoveNext())
            {
                // re-initialize copy before each destructive call to Bezier
                for (int i = 0; i < nodes.Length; i++)
                {
                    points[i] = toVector3(nodes[i]);
                }

                yield return(Bezier(ease, points, (float)steps.Current, maxStep));
                // make sure last value is always generated
            }
        }
    }
    /**
     * Generic catmull-rom spline sequence generator used to implement the
     * Vector3[] and Transform[] variants. Normally you would not use this
     * function directly.
     */
    public static IEnumerator NewCatmullRom(Transform[] nodes, TransformToPositionFunction toVector3, int slices, bool loop)
    {
        // need at least two nodes to spline between
        if (nodes.Length >= 2)
        {
            // yield the first point explicitly, if looping the first point
            // will be generated again in the step for loop when interpolating
            // from last point back to the first point
            yield return(toVector3(nodes[0]));

            int last = nodes.Length - 1;
            for (int current = 0; loop || current < last; current++)
            {
                // wrap around when looping
                if (loop && current > last)
                {
                    current = 0;
                }

                // handle edge cases for looping and non-looping scenarios
                // when looping we wrap around, when not looping use start for previous
                // and end for next when you at the ends of the nodes array
                int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
                int start    = current;
                int end      = (current == last) ? ((loop) ? 0 : current) : current + 1;
                int next     = (end == last) ? ((loop) ? 0 : end) : end + 1;

                // adding one guarantees yielding at least the end point
                int stepCount = slices + 1;
                for (int step = 1; step <= stepCount; step++)
                {
                    yield return(CatmullRom(toVector3(nodes[previous]),
                                            toVector3(nodes[start]),
                                            toVector3(nodes[end]),
                                            toVector3(nodes[next]),
                                            step, stepCount));
                }
            }
        }
    }
	/**
	 * Generic catmull-rom spline sequence generator used to implement the
	 * Vector3[] and Transform[] variants. Normally you would not use this
	 * function directly.
	 */
	public static IEnumerator NewCatmullRom(Transform[] nodes, TransformToPositionFunction toVector3, int slices, bool loop)
	{
		// need at least two nodes to spline between
		if (nodes.Length >= 2) 
		{
			// yield the first point explicitly, if looping the first point
			// will be generated again in the step for loop when interpolating
			// from last point back to the first point
			yield return toVector3(nodes[0]);
			
			int last = nodes.Length - 1;
			for(int current = 0; loop || current < last; current++) 
			{
				// wrap around when looping
				if (loop && current > last)
				{
					current = 0;
				}
					
				// handle edge cases for looping and non-looping scenarios
				// when looping we wrap around, when not looping use start for previous
				// and end for next when you at the ends of the nodes array
				int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
				int start = current;
				int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
				int next = (end == last) ? ((loop) ? 0 : end) : end + 1;
				
				// adding one guarantees yielding at least the end point
				int stepCount = slices + 1;
				for (int step = 1; step <= stepCount; step++) 
				{
					yield return CatmullRom(toVector3(nodes[previous]),
					                 toVector3(nodes[start]),
					                 toVector3(nodes[end]),
					                 toVector3(nodes[next]),
					                 step, stepCount);
				}
			}
		}
	}
	/**
	 * Generic bezier spline sequence generator used to implement the time and
	 * slice variants. Normally you would not use this function directly.
	 */
	public static IEnumerator NewBezier(EaseFunction ease, Transform[] nodes, TransformToPositionFunction toVector3 , float maxStep, IEnumerator steps)
	{
		// need at least two nodes to spline between
		if (nodes.Length >= 2) 
		{
			// copy nodes array since Bezier is destructive
			Vector3[] points = new Vector3[nodes.Length];
			
			while(steps.MoveNext())
			{
				// re-initialize copy before each destructive call to Bezier
				for(int i = 0; i < nodes.Length; i++)
				{
					points[i] = toVector3(nodes[i]);
				}
				
				yield return Bezier(ease, points, (float)steps.Current, maxStep);
				// make sure last value is always generated
			}
		}
	}