/// <summary>
        /// returns two key frame index, which is included in the specified time.
        /// </summary>
        public void CalculateKeyFrameIndex(float localTime, AnimPlayMode mode,
                                           out int index1, out int index2,
                                           out float interpolateTime)
        {
            index1          = 0; // first key frame index
            index2          = 0; // second key frame index
            interpolateTime = 0.0f;

            //  Calculate first key frame index
            if (HasTime)
            {
                index1 = GetKeyFrameIndex(localTime);
            }
            else
            {
                index1 = (int)(localTime / KeyInterval);
            }

            //  Calculate second key frame index by play mode
            switch (mode)
            {
            case AnimPlayMode.Once:         //  Just play once
            {
                //  if index1 is last index
                index2 = (index1 >= KeyCount - 1 ? index1 : index1 + 1);
            }
            break;

            case AnimPlayMode.Repeat:       //  Play looping
            {
                //  if index1 is last index, index2 must be begin (looping)
                index2 = (index1 >= KeyCount - 1 ? 0 : index1 + 1);
            }
            break;

            default:
                throw new NotSupportedException("Not supported play mode");
            }

            if (index1 >= KeyCount - 1)
            {
                index1 = index2 = KeyCount - 1;

                interpolateTime = 1.0f;
            }
            else
            {
                if (HasTime)
                {
                    interpolateTime = (localTime - Time[index1]) /
                                      (Time[index2] - Time[index1]);
                }
                else
                {
                    interpolateTime = HelperMath.CalculateModulo(localTime, KeyInterval)
                                      / KeyInterval;
                }
            }
        }
        /// <summary>
        /// gets texture coordinates by the time flow.
        /// </summary>
        /// <param name="time">defined time</param>
        /// <param name="uv1">texture coordinates 1</param>
        /// <param name="uv2">texture coordinates 2</param>
        public void GetUV(float time, out Vector2 uv1, out Vector2 uv2)
        {
            uint  x = 0, y = 0, idx = 0;
            float u = 0.0f, v = 0.0f;

            if (IsRepeat)
            {
                time = HelperMath.CalculateModulo(time, duration);
            }

            if (IsRandomMode)
            {
                idx = (uint)HelperMath.Randomi() % Count;
            }
            else
            {
                if (IsUseStaticTime)
                {
                    //  Calculate index by static interval time
                    idx = (uint)(time * rInterval);

                    if (idx >= Count)
                    {
                        idx = Count - 1;
                    }
                }
                else
                {
                    uint start = 0;
                    uint end   = Count - 1;

                    //  Calculate index by dynamic interval time
                    do
                    {
                        idx = (start + end) / 2;

                        if (TimeTable[(int)idx] > time)
                        {
                            end = idx - 1;
                        }
                        else
                        {
                            start = idx + 1;
                        }
                    } while (start < end);
                }
            }

            idx += StartIndex;

            y = idx / (uint)lineCount;
            v = y * heightFactor;

            x = idx % (uint)lineCount;
            u = x * widthFactor;

            uv1 = new Vector2(u, v);
            uv2 = new Vector2(u + widthFactor, v + heightFactor);
        }
        /// <summary>
        /// calculates the key frame of the animation of the specified time.
        /// </summary>
        /// <param name="time">animation time</param>
        /// <returns>Matrix of the animation key frame</returns>
        public Matrix GetKeyFrameMatrix(float time)
        {
            if (KeyFrameSequence == null)
            {
                throw new InvalidOperationException("Sequence is not set.");
            }

            // Don't do anything if the timeScaleFactor is 0. (default scale is 1.0)
            if (ScaleFactor != 0.0f)
            {
                //  Accumulate animation local time
                localTime += (float)(ScaleFactor * time);

                switch (PlayMode)
                {
                case AnimPlayMode.Once:         //  Just play once
                {
                    if (localTime > KeyFrameSequence.Duration)
                    {
                        localTime = KeyFrameSequence.Duration;
                    }
                }
                break;

                case AnimPlayMode.Repeat:       //  Play looping
                {
                    //  Calculate time remainder after local time looping
                    if (localTime > Duration)
                    {
                        localTime = HelperMath.CalculateModulo(localTime,
                                                               KeyFrameSequence.Duration);
                    }
                }
                break;

                default:
                    throw new NotSupportedException("Not supported play mode");
                }

                return(KeyFrameSequence.GetInterpolateMatrix(localTime, PlayMode));
            }

            return(Matrix.Identity);
        }