public StoryboardObject ParseObjectLine(string line)
        {
            StoryboardObject obj = null;

            var data_arr = line.Split(',');

            if ((!Enum.TryParse <StoryboardObjectType>(data_arr[0], true, out var obj_type)) || !(obj_type == StoryboardObjectType.Background || obj_type == StoryboardObjectType.Animation || obj_type == StoryboardObjectType.Sprite))
            {
                Log.Warn($"Unknown/Unsupport Storyboard object type:" + data_arr[0]);
                return(null);
            }

            switch (obj_type)
            {
            case StoryboardObjectType.Background:
                obj = new StoryboardBackgroundObject();
                break;

            case StoryboardObjectType.Sprite:
                obj = new StoryboardObject();
                break;

            case StoryboardObjectType.Animation:
                obj = new StoryboardAnimation();
                break;

            default:
                break;
            }

            if (!(obj is StoryboardBackgroundObject))
            {
                obj.layer = (Layer)Enum.Parse(typeof(Layer), data_arr[1]);

                obj.OriginOffset = AnchorConvert.Convert((Anchor)Enum.Parse(typeof(Anchor), data_arr[2]));

                obj.ImageFilePath = data_arr[3].Trim().Trim('\"').ToString().Replace("/", "\\").ToLower();

                obj.BaseTransformResetAction += (x) => x.Postion = new Vector(data_arr[4].ToSigle(), data_arr[5].ToSigle());

                if (obj is StoryboardAnimation animation)
                {
                    ParseStoryboardAnimation(animation, data_arr);
                }
            }
            else
            {
                //For background object
                obj.ImageFilePath = data_arr[2].Trim().Trim('\"').ToString().Replace("/", "\\").ToLower();

                var position = data_arr.Length > 4 ? new Vector(data_arr[3].ToSigle(), data_arr[4].ToSigle()) : Vector.Zero;

                if (position != Vector.One)
                {
                    obj.BaseTransformResetAction += (x) => x.Postion = position + new Vector(320, 240);
                }
            }

            return(obj);
        }
        public static StoryboardObject Create(BinaryReader reader, StringCacheTable cache)
        {
            StoryboardObject obj = null;
            var id = reader.ReadByte();

            switch (id)
            {
            case 1:
                obj = new StoryboardAnimation();
                break;

            case 2:
                obj = new StoryboardBackgroundObject();

                //clean default commands because there will be added by binary file.
                foreach (var cmd in obj.CommandMap.Values.SelectMany(x => x).ToArray())
                {
                    obj.RemoveCommand(cmd);
                }

                break;

            default:
                obj = new StoryboardObject();
                break;
            }

            obj.OnDeserialize(reader, cache);
            return(obj);
        }