예제 #1
0
        public override void Process(ImportContext ctx, Layer layer)
        {
            var eventFrames = new HashSet <int>();
            var file        = ctx.file;

            for (int i = 0; i < file.frames.Count; ++i)
            {
                bool isEvent = file.frames[i].cels.ContainsKey(layer.index);
                if (isEvent)
                {
                    eventFrames.Add(i);
                }
            }

            LayerParamType paramType = layer.GetParamType(1);

            foreach (var frametag in file.frameTags)
            {
                var clip   = ctx.generatedClips[frametag];
                var events = new List <AnimationEvent>(clip.events);

                var time = 0.0f;
                for (int f = frametag.from; f <= frametag.to; ++f)
                {
                    if (eventFrames.Contains(f))
                    {
                        var evt = new AnimationEvent {
                            time           = time,
                            functionName   = layer.GetParamString(0),
                            messageOptions = SendMessageOptions.DontRequireReceiver
                        };

                        // Debug.Log(paramType + ", " + layer.metaInfo.ParamCount);

                        if (paramType == LayerParamType.String)
                        {
                            evt.stringParameter = layer.GetParamString(1);
                        }
                        else if (paramType == LayerParamType.Number)
                        {
                            var fval = layer.GetParamFloat(1);
                            if (fval == Math.Floor(fval))
                            {
                                evt.intParameter = (int)fval;
                            }
                            else
                            {
                                evt.floatParameter = fval;
                            }
                        }

                        events.Add(evt);
                    }

                    time += file.frames[f].duration * 1e-3f;
                }

                events.Sort((lhs, rhs) => lhs.time.CompareTo(rhs.time));
                AnimationUtility.SetAnimationEvents(clip, events.ToArray());
                EditorUtility.SetDirty(clip);
            }
        }
예제 #2
0
        public static ASEFile Parse(byte[] bytes)
        {
            var stream = new MemoryStream(bytes);

            using (var reader = new BinaryReader(stream)) {
                var file = new ASEFile();

                reader.ReadDWord(); // File size
                _CheckMagicNumber(reader.ReadWord(), 0xA5E0);

                var frameCount = reader.ReadWord();

                file.width  = reader.ReadWord();
                file.height = reader.ReadWord();

                var colorDepth = reader.ReadWord();

                if (colorDepth != 32)
                {
                    _Error("Non RGBA color mode isn't supported yet");
                }

                reader.ReadDWord(); // Flags
                reader.ReadWord();  // Deprecated speed
                _CheckMagicNumber(reader.ReadDWord(), 0);
                _CheckMagicNumber(reader.ReadDWord(), 0);

                reader.ReadBytes(4);
                reader.ReadWord();
                reader.ReadBytes(2);
                reader.ReadBytes(92);
                int readLayerIndex = 0;

                UserDataAcceptor lastUserdataAcceptor = null;

                for (int i = 0; i < frameCount; ++i)
                {
                    var frame = new Frame();
                    frame.frameID = i;

                    reader.ReadDWord(); // frameBytes
                    _CheckMagicNumber(reader.ReadWord(), 0xF1FA);

                    var chunkCount = reader.ReadWord();

                    frame.duration = reader.ReadWord();

                    reader.ReadBytes(6);

                    for (int j = 0; j < chunkCount; ++j)
                    {
                        var chunkBytes = reader.ReadDWord(); // 4
                        var chunkType  = reader.ReadWord();  // 2

                        switch (chunkType)
                        {
                        case CHUNK_LAYER: {
                            var layer = new Layer();
                            var flags = reader.ReadWord();

                            layer.visible = (flags & 0x1) != 0;

                            var layerType = reader.ReadWord();
                            reader.ReadWord(); // childLevel

                            reader.ReadWord();
                            reader.ReadWord();

                            layer.blendMode = (BlendMode)reader.ReadWord();
                            layer.opacity   = reader.ReadByte() / 255.0f;
                            reader.ReadBytes(3);

                            layer.layerName = reader.ReadUTF8();

                            if (layerType == 0 && layer.visible && !layer.layerName.StartsWith("//"))
                            {
                                layer.index = readLayerIndex;
                                layer.type  = layer.layerName.StartsWith("@") ? LayerType.Meta : LayerType.Content;
                                if (layer.type == LayerType.Meta)
                                {
                                    MetaLayerParser.Parse(layer);
                                }

                                file.layers.Add(layer);
                            }

                            ++readLayerIndex;

                            lastUserdataAcceptor = layer;
                        } break;

                        case CHUNK_CEL: {
                            var cel = new Cel();

                            cel.layerIndex = reader.ReadWord();          // 2
                            cel.x          = reader.ReadInt16();         // 2
                            cel.y          = reader.ReadInt16();         // 2
                            cel.opacity    = reader.ReadByte() / 255.0f; // 1
                            cel.type       = (CelType)reader.ReadWord(); // 2
                            reader.ReadBytes(7);                         // 7

                            switch (cel.type)
                            {
                            case CelType.Raw: {
                                cel.width       = reader.ReadWord(); // 2
                                cel.height      = reader.ReadWord(); // 2
                                cel.colorBuffer = ToColorBufferRGBA(reader.ReadBytes(chunkBytes - 6 - 16 - 4));

                                _Assert(cel.width * cel.height == cel.colorBuffer.Length, "Color buffer size incorrect");
                            } break;

                            case CelType.Linked: {
                                cel.linkedCel = reader.ReadWord();
                            } break;

                            case CelType.Compressed: {
                                cel.width       = reader.ReadWord();
                                cel.height      = reader.ReadWord();
                                cel.colorBuffer = ToColorBufferRGBA(
                                    reader.ReadCompressedBytes(chunkBytes - 6 - 16 - 4));
                                _Assert(cel.width * cel.height == cel.colorBuffer.Length, "Color buffer size incorrect");
                            } break;
                            }

                            if (file.FindLayer(cel.layerIndex) != null)
                            {
                                frame.cels.Add(cel.layerIndex, cel);
                            }

                            lastUserdataAcceptor = cel;
                        } break;

                        case CHUNK_FRAME_TAGS: {
                            var count = reader.ReadWord();
                            reader.ReadBytes(8);

                            for (int c = 0; c < count; ++c)
                            {
                                var frameTag = new FrameTag();

                                frameTag.from = reader.ReadWord();
                                frameTag.to   = reader.ReadWord();
                                reader.ReadByte();
                                reader.ReadBytes(8);
                                reader.ReadBytes(3);
                                reader.ReadByte();

                                frameTag.name = reader.ReadUTF8();

                                if (frameTag.name.StartsWith("//")) // Commented tags are ignored
                                {
                                    continue;
                                }

                                var originalName = frameTag.name;

                                var tagIdx      = frameTag.name.IndexOf('#');
                                var nameInvalid = false;
                                if (tagIdx != -1)
                                {
                                    frameTag.name = frameTag.name.Substring(0, tagIdx).Trim();
                                    var possibleProperties = originalName.Substring(tagIdx).Split(' ');
                                    foreach (var possibleProperty in possibleProperties)
                                    {
                                        if (possibleProperty.Length > 1 && possibleProperty[0] == '#')
                                        {
                                            frameTag.properties.Add(possibleProperty.Substring(1));
                                        }
                                        else
                                        {
                                            nameInvalid = true;
                                        }
                                    }
                                }

                                if (nameInvalid)
                                {
                                    Debug.LogWarning("Invalid name: " + originalName);
                                }

                                file.frameTags.Add(frameTag);
                            }
                        } break;

                        case CHUNK_USERDATA: {
                            var flags    = reader.ReadDWord();
                            var hasText  = (flags & 0x01) != 0;
                            var hasColor = (flags & 0x02) != 0;

                            if (hasText)
                            {
                                lastUserdataAcceptor.userData = reader.ReadUTF8();
                            }

                            if (hasColor)
                            {
                                reader.ReadBytes(4);
                            }
                        } break;

                        default: {
                            reader.ReadBytes(chunkBytes - 6);
                        } break;
                        }
                    }

                    file.frames.Add(frame);
                }

                // Post process: eliminate reference cels
                for (int f = 0; f < file.frames.Count; ++f)
                {
                    var frame = file.frames[f];
                    foreach (var pair in frame.cels)
                    {
                        var layerID = pair.Key;
                        var cel     = pair.Value;
                        if (cel.type == CelType.Linked)
                        {
                            cel.type = CelType.Raw;

                            var src = file.frames[cel.linkedCel].cels[layerID];

                            cel.x           = src.x;
                            cel.y           = src.y;
                            cel.width       = src.width;
                            cel.height      = src.height;
                            cel.colorBuffer = src.colorBuffer;
                            cel.opacity     = src.opacity;
                            cel.userData    = src.userData;
                        }
                    }
                }

                return(file);
            }
        }
예제 #3
0
        static void _Parse(Lexer lexer, Layer layer)
        {
            layer.actionName = _Expect(lexer, TKN_ID);

            if (!_SkipSpaces(lexer))
            {
                return;
            }

            if (lexer.Token != TKN_LEFT)
            {
                _ErrorUnexpected(lexer, TKN_LEFT);
            }

            while (true)
            {
                if (!_SkipSpaces(lexer))
                {
                    _ErrorEOF(lexer, TKN_RIGHT, TKN_NUMBER, TKN_STRING);
                }

                bool isParam = false;
                if (lexer.Token == TKN_STRING)
                {
                    var param = new LayerParam();
                    param.type        = LayerParamType.String;
                    param.stringValue = lexer.TokenContents.Substring(1, lexer.TokenContents.Length - 2);
                    layer.parameters.Add(param);
                    isParam = true;
                }
                else if (lexer.Token == TKN_NUMBER)
                {
                    var param = new LayerParam();
                    param.type        = LayerParamType.Number;
                    param.numberValue = double.Parse(lexer.TokenContents);
                    layer.parameters.Add(param);
                    isParam = true;
                }
                else if (lexer.Token == TKN_RIGHT)
                {
                    break;
                }
                else
                {
                    _ErrorUnexpected(lexer, TKN_RIGHT, TKN_NUMBER, TKN_STRING);
                }

                if (isParam)
                {
                    if (!_SkipSpaces(lexer))
                    {
                        _ErrorEOF(lexer, TKN_COMMA, TKN_RIGHT);
                    }
                    if (lexer.Token == TKN_RIGHT)
                    {
                        break;
                    }
                    if (lexer.Token != TKN_COMMA)
                    {
                        _ErrorUnexpected(lexer, TKN_COMMA, TKN_RIGHT);
                    }
                }
            }

            if (_SkipSpaces(lexer))
            {
                Debug.LogWarning("Invalid content after layer definition finished: " + lexer.Token + "/" + lexer.TokenContents);
            }
        }
예제 #4
0
        public override void Process(ImportContext ctx, Layer layer)
        {
            // the name of the data variable should be the first parameter. eg @data("leg l")
            string dataName = layer.GetParamString(0);

            var file = ctx.file;

            var importer    = AssetImporter.GetAtPath(ctx.atlasPath) as TextureImporter;
            var spriteSheet = importer.spritesheet;

            // each tag represents a different animation.  look at each frame of each tag.  store coordinates of any visible pixels.
            // these represent the data points.
            foreach (var tag in ctx.file.frameTags)
            {
                string  animName      = tag.name;
                Vector3 distance      = Vector3.zero;
                var     frameDataList = new FrameDataList {
                    frames = new List <FrameData>()
                };
                int numFrames = tag.to - tag.from + 1;

                for (int i = tag.from, j = 0; i <= tag.to; ++i, j++)
                {
                    var frameData = new FrameData {
                        frame = j, coords = new List <Vector2>()
                    };
                    Cel cel;
                    file.frames[i].cels.TryGetValue(layer.index, out cel);

                    if (cel != null)
                    {
                        int pixelCount = 0;

                        for (int y = 0; y < cel.height; ++y)
                        {
                            for (int x = 0; x < cel.width; ++x)
                            {
                                // tex coords relative to full texture boundaries
                                int texX = cel.x + x;
                                int texY = -(cel.y + y) + file.height - 1;

                                // store position of any visible pixels
                                var pxl = cel.GetPixelRaw(x, y);
                                if (pxl.a > 0.1f)
                                {
                                    // start the coordinate of the pixel on the layer (from bottom left corner)
                                    Vector2 coord = new Vector2(texX, texY);

                                    // default pixel origin is bottom left.  if centered, add half a pixel in x and y directions
                                    if (ctx.settings.pixelOrigin == PixelOrigin.Center)
                                    {
                                        coord += new Vector2(0.5f, 0.5f);
                                    }

                                    // calculate position in relation to pivot
                                    Vector2 pivot    = spriteSheet[i].pivot;
                                    Vector2 pivotPxl = new Vector2(pivot.x * spriteSheet[i].rect.width, pivot.y * spriteSheet[i].rect.height);

                                    // get coordinate relative to pivot
                                    coord -= ctx.spriteCropPositions[i];
                                    coord -= pivotPxl;

                                    // if calculating "prev pivot" data, and this is first pixel (should only be one), then store its distance
                                    if (dataName == "prev pivot" && pixelCount == 0)
                                    {
                                        // coord is distance from pivot.  negate to make positive, and round to get rid of float errors
                                        distance += new Vector3(-Mathf.Round(coord.x), -Mathf.Round(coord.y), 0);
                                    }

                                    // points are all relative to the sprite's bounding rectangle, which is 1 by 1 in both dimensions
                                    // regardless of sprite size.  So (0.5, 0.5) would be the center of the sprite.
                                    // it's ok for points to be outside the bounding rectangle.  they'll just be less than 0, or greater than 1.
                                    // WHY? so if the sprite is transformed, everything stays relative. You can multiply points by the transforms
                                    // to get their position relative to the transform.
                                    // NOTE: spriteSheet[i].rect.width/height are in pixels
                                    coord = new Vector2(coord.x / spriteSheet[i].rect.width, coord.y / spriteSheet[i].rect.height);

                                    frameData.coords.Add(coord);
                                    ++pixelCount;
                                }
                            }
                        }

                        if (pixelCount > 0)
                        {
                            frameDataList.frames.Add(frameData);
                        }
                    }
                }

                // if we've collected all the data for this animation, save it in appropriate dictionary spot
                if (frameDataList.frames.Count > 0)
                {
                    if (ctx.animData.animDict.ContainsKey(animName))
                    {
                        ctx.animData.animDict[animName].frameDict.Add(dataName, frameDataList);
                        if (dataName == "prev pivot")
                        {
                            ctx.animData.animDict[animName].distance = distance;
                        }
                    }
                    else
                    {
                        ctx.animData.animDict.Add(animName, new AnimList {
                            numFrames = numFrames,
                            distance  = distance,
                            frameDict = new FrameDictionary()
                            {
                                {
                                    dataName,
                                    frameDataList
                                }
                            }
                        });
                    }
//                    Debug.Log(ctx.animData.data["run e"]);
                }
            }

//            Debug.Log(data);
        }