protected virtual void AddSpatialData(SpriterObject info, SpriterTimeline timeline, Spriter spriter, float deltaTime)
        {
            switch (timeline.ObjectType)
            {
            case SpriterObjectType.Sprite:
                FrameData.SpriteData.Add(info);
                break;

            case SpriterObjectType.Entity:
                SpriterAnimation newAnim       = spriter.Entities[info.EntityId].Animations[info.AnimationId];
                float            newTargetTime = info.T * newAnim.Length;
                GetFrameData(newAnim, newTargetTime, deltaTime, info);
                break;

            case SpriterObjectType.Point:
                info.PivotX = 0.0f;
                info.PivotY = 1.0f;
                FrameData.PointData[timeline.Name] = info;
                break;

            case SpriterObjectType.Box:
                FrameData.BoxData[timeline.ObjectId] = info;
                break;
            }
        }
        protected virtual SpriterObject GetObjectInfo(SpriterRef spriterRef, SpriterAnimation animation, float targetTime)
        {
            SpriterTimeline timeline = animation.Timelines[spriterRef.TimelineId];

            SpriterTimelineKey[] keys = timeline.Keys;
            SpriterTimelineKey   keyA = keys[spriterRef.KeyId];
            SpriterTimelineKey   keyB = keys.GetNextKey(keyA, animation.Looping);

            keyA.ObjectInfo.Name = timeline.Name;

            if (keyB == null)
            {
                return(Copy(keyA.ObjectInfo));
            }

            float factor = SpriterHelper.GetFactor(keyA, keyB, animation.Length, targetTime);

            return(Interpolate(keyA.ObjectInfo, keyB.ObjectInfo, factor, keyA.Spin));
        }
        private static void AddSpatialData(SpriterObject info, SpriterTimeline timeline, Spriter spriter, float targetTime, FrameData frameData)
        {
            switch (timeline.ObjectType)
            {
            case SpriterObjectType.Sprite:
                frameData.SpriteData.Add(info);
                break;

            case SpriterObjectType.Entity:
                SpriterAnimation newAnim       = spriter.Entities[info.EntityId].Animations[info.AnimationId];
                float            newTargetTime = info.T * newAnim.Length;
                UpdateFrameData(frameData, newAnim, newTargetTime, info);
                break;

            case SpriterObjectType.Point:
                frameData.PointData[timeline.Name] = info;
                break;

            case SpriterObjectType.Box:
                frameData.BoxData[timeline.ObjectId] = info;
                break;
            }
        }
        protected virtual void AddVariableAndTagData(SpriterAnimation animation, float targetTime)
        {
            if (animation.Meta == null)
            {
                return;
            }

            if (Config.VarsEnabled && animation.Meta.Varlines != null && animation.Meta.Varlines.Length > 0)
            {
                for (int i = 0; i < animation.Meta.Varlines.Length; ++i)
                {
                    SpriterVarline varline  = animation.Meta.Varlines[i];
                    SpriterVarDef  variable = animation.Entity.Variables[varline.Def];
                    FrameData.AnimationVars[variable.Name] = GetVariableValue(animation, variable, varline, targetTime);
                }
            }

            SpriterElement[] tags    = animation.Entity.Spriter.Tags;
            SpriterTagline   tagline = animation.Meta.Tagline;

            if (Config.TagsEnabled && tagline != null && tagline.Keys != null && tagline.Keys.Length > 0)
            {
                SpriterTaglineKey key = tagline.Keys.GetLastKey(targetTime);
                if (key != null && key.Tags != null)
                {
                    for (int i = 0; i < key.Tags.Length; ++i)
                    {
                        SpriterTag tag = key.Tags[i];
                        FrameData.AnimationTags.Add(tags[tag.TagId].Name);
                    }
                }
            }

            for (int i = 0; i < animation.Timelines.Length; ++i)
            {
                SpriterTimeline timeline = animation.Timelines[i];
                SpriterMeta     meta     = timeline.Meta;
                if (meta == null)
                {
                    continue;
                }

                SpriterObjectInfo objInfo = GetObjectInfo(animation, timeline.Name);

                if (Config.VarsEnabled && meta.Varlines != null && meta.Varlines.Length > 0)
                {
                    for (int j = 0; j < timeline.Meta.Varlines.Length; ++j)
                    {
                        SpriterVarline varline  = timeline.Meta.Varlines[j];
                        SpriterVarDef  variable = objInfo.Variables[varline.Def];
                        FrameData.AddObjectVar(objInfo.Name, variable.Name, GetVariableValue(animation, variable, varline, targetTime));
                    }
                }

                if (Config.TagsEnabled && meta.Tagline != null && meta.Tagline.Keys != null && meta.Tagline.Keys.Length > 0)
                {
                    SpriterTaglineKey key = tagline.Keys.GetLastKey(targetTime);
                    if (key != null && key.Tags != null)
                    {
                        for (int j = 0; j < key.Tags.Length; ++j)
                        {
                            SpriterTag tag = key.Tags[j];
                            FrameData.AddObjectTag(objInfo.Name, tags[tag.TagId].Name);
                        }
                    }
                }
            }
        }