예제 #1
0
        public static List <Sprite> GenerateAtlas(ImportContext ctx, List <Layer> layers, string atlasPath)
        {
            var file     = ctx.file;
            var settings = ctx.settings;
            var path     = atlasPath;

            var images = file.frames
                         .Select(frame => {
                var cels  = frame.cels.Values.OrderBy(it => it.layerIndex).ToList();
                var image = new FrameImage(file.width, file.height);

                foreach (var cel in cels)
                {
                    var layer = file.FindLayer(cel.layerIndex);
                    if (!layers.Contains(layer))
                    {
                        continue;
                    }

                    for (int cy = 0; cy < cel.height; ++cy)
                    {
                        for (int cx = 0; cx < cel.width; ++cx)
                        {
                            var c = cel.GetPixelRaw(cx, cy);
                            if (c.a != 0f)
                            {
                                var x = cx + cel.x;
                                var y = cy + cel.y;

                                var lastColor = image.GetPixel(x, y);
                                // blending
                                var color = Color.Lerp(lastColor, c, c.a);
                                color.a   = lastColor.a + c.a * (1 - lastColor.a);
                                color.r  /= color.a;
                                color.g  /= color.a;
                                color.b  /= color.a;

                                image.SetPixel(x, y, color);

                                // expand image area
                                image.minx = Mathf.Min(image.minx, x);
                                image.miny = Mathf.Min(image.miny, y);

                                image.maxx = Mathf.Max(image.maxx, x);
                                image.maxy = Mathf.Max(image.maxy, y);
                            }
                        }
                    }
                }

                if (image.minx == int.MaxValue)
                {
                    image.minx = image.maxx = image.miny = image.maxy = 0;
                }

                return(image);
            })
                         .ToList();

            var packList = images.Select(image => new PackData {
                width = image.finalWidth, height = image.finalHeight
            }).ToList();
            var packResult = PackAtlas(packList);

            if (packResult.imageSize > 2048)
            {
                Debug.LogWarning("Generate atlas size is larger than 2048, this might force Unity to compress the image.");
            }

            var texture     = new Texture2D(packResult.imageSize, packResult.imageSize);
            var transparent = new Color(0, 0, 0, 0);

            for (int y = 0; y < texture.height; ++y)
            {
                for (int x = 0; x < texture.width; ++x)
                {
                    texture.SetPixel(x, y, transparent);
                }
            }

            Vector2 oldPivotNorm = settings.PivotRelativePos;

            var metaList = new List <SpriteMetaData>();

            for (int i = 0; i < images.Count; ++i)
            {
                var pos   = packResult.positions[i];
                var image = images[i];

                for (int y = image.miny; y <= image.maxy; ++y)
                {
                    for (int x = image.minx; x <= image.maxx; ++x)
                    {
                        int texX = (x - image.minx) + pos.x;
                        int texY = -(y - image.miny) + pos.y + image.finalHeight - 1;
                        texture.SetPixel(texX, texY, image.GetPixel(x, y));
                    }
                }

                var metadata = new SpriteMetaData();
                metadata.name      = ctx.fileNameNoExt + "_" + i;
                metadata.alignment = (int)SpriteAlignment.Custom;
                metadata.rect      = new Rect(pos.x, pos.y, image.finalWidth, image.finalHeight);

                // calculate relative pivot
                var oldPivotTex  = Vector2.Scale(oldPivotNorm, new Vector2(file.width, file.height));
                var newPivotTex  = oldPivotTex - new Vector2(image.minx, file.height - image.maxy - 1);
                var newPivotNorm = Vector2.Scale(newPivotTex, new Vector2(1.0f / image.finalWidth, 1.0f / image.finalHeight));
                metadata.pivot = newPivotNorm;

                ctx.spriteCropPositions.Add(new Vector2(image.minx, file.height - image.maxy - 1));

                metaList.Add(metadata);
            }

            var bytes = texture.EncodeToPNG();

            File.WriteAllBytes(path, bytes);

            // Import texture
            AssetDatabase.Refresh();
            var importer = AssetImporter.GetAtPath(path) as TextureImporter;

            importer.textureType         = TextureImporterType.Sprite;
            importer.spritePixelsPerUnit = settings.ppu;
            importer.mipmapEnabled       = false;
            importer.filterMode          = FilterMode.Point;
            importer.textureCompression  = TextureImporterCompression.Uncompressed;

            importer.spritesheet      = metaList.ToArray();
            importer.spriteImportMode = SpriteImportMode.Multiple;
            importer.maxTextureSize   = 4096;

            EditorUtility.SetDirty(importer);
            importer.SaveAndReimport();

            return(GetAtlasSprites(path));
        }
예제 #2
0
        public static List <Sprite> GenerateAtlas(ImportContext ctx, List <Layer> layers, bool densePacked = true, int border = 8)
        {
            var file = ctx.file;

            var images = file.frames
                         .Select(frame => {
                var cels  = frame.cels.Values.OrderBy(it => it.layerIndex).ToList();
                var image = new FrameImage(file.width, file.height);

                foreach (var cel in cels)
                {
                    var layer = file.FindLayer(cel.layerIndex);
                    if (!layers.Contains(layer))
                    {
                        continue;
                    }

                    for (int cy = 0; cy < cel.height; ++cy)
                    {
                        for (int cx = 0; cx < cel.width; ++cx)
                        {
                            var c      = cel.GetPixelRaw(cx, cy);
                            var cAlpha = BlendeModeAnalysis.DocColor.rgba_geta(c);
                            if (cAlpha != 0f)
                            {
                                var x = cx + cel.x;
                                var y = cy + cel.y;
                                if (0 <= x && x < file.width &&
                                    0 <= y && y < file.height)       // Aseprite allows some pixels out of bounds to be kept, ignore them
                                {
                                    var lastColor = image.GetPixel(x, y);
                                    // blending
                                    //var color = FunctionBoost.Color_Lerp(lastColor, c, c.Af);
                                    //color.Af = lastColor.Af + c.Af * (1 - lastColor.Af);
                                    //color.Rf /= color.Af;
                                    //color.Gf /= color.Af;
                                    //color.Bf /= color.Af;
                                    var color = BlendeModeAnalysis.GetBlendFunc(layer.blendMode)(
                                        lastColor, c, cAlpha);

                                    image.SetPixel(x, y, color);

                                    // expand image area
                                    image.minx = Mathf.Min(image.minx, x);
                                    image.miny = Mathf.Min(image.miny, y);

                                    image.maxx = Mathf.Max(image.maxx, x);
                                    image.maxy = Mathf.Max(image.maxy, y);
                                }
                            }
                        }
                    }
                }

                if (image.minx == int.MaxValue)
                {
                    image.minx = image.maxx = image.miny = image.maxy = 0;
                }

                if (!densePacked)       // override image border for sparsely packed atlas
                {
                    image.minx = image.miny = 0;
                    image.maxx = file.width - 1;
                    image.maxy = file.height - 1;
                }

                return(image);
            })
                         .ToList();

            var packList = images.Select(image => new PackData {
                width = image.finalWidth, height = image.finalHeight
            }).ToList();
            var packResult = PackAtlas(packList, border);

            if (packResult.imageSize > 2048)
            {
                Log.Warnning("Generate atlas size is larger than 2048 !");
            }

            var textureData = new Color[packResult.imageSize * packResult.imageSize];

            // build image
            for (int i = 0; i < images.Count; ++i)
            {
                var pos   = packResult.positions[i];
                var image = images[i];
                for (int y = image.miny; y <= image.maxy; ++y)
                {
                    for (int x = image.minx; x <= image.maxx; ++x)
                    {
                        //int texX = (x - image.minx) + pos.x;
                        //int texY = -(y - image.miny) + pos.y + image.finalHeight - 1;
                        //textureData[texX + texY * packResult.imageSize] = image.GetPixel(x, y);
                        int texX = (x - image.minx) + pos.x;
                        int texY = (y - image.miny) + pos.y;
                        textureData[texX + texY * packResult.imageSize] = BlendeModeAnalysis.ConvertTo(image.GetPixel(x, y));
                    }
                }
            }
            var texture = Image.NewImageData(packResult.imageSize, packResult.imageSize);

            texture.SetPixels(textureData);
            var textureImage = Graphics.NewImage(texture);

            textureImage.SetFilter(FilterMode.Nearest, FilterMode.Nearest);
            // build image end

            Vector2 oldPivotNorm = Vector2.Zero;

            var metaList = new List <Sprite>(images.Count);

            for (int i = 0; i < images.Count; ++i)
            {
                var   pos      = packResult.positions[i];
                var   image    = images[i];
                float duration = file.frames[i].duration;

                var metadata = new Sprite();
                metadata.frame     = file.frames[i];
                metadata.image     = textureImage;
                metadata.duration  = duration * 0.001f;
                metadata.name      = ctx.fileNameNoExt + "_" + i;
                metadata.alignment = SpriteAlignment.Custom;
                metadata.rect      = new RectangleF(pos.x, pos.y, image.finalWidth, image.finalHeight);
                metadata.quad      = Graphics.NewQuad(pos.x, pos.y, image.finalWidth, image.finalHeight, packResult.imageSize, packResult.imageSize);

                // calculate relative pivot
                metadata.imgQuadOffset = new Vector2(image.minx, image.miny);

                //ctx.spriteCropPositions.Add(new Vector2(image.minx, file.height - image.maxy - 1));

                metaList.Add(metadata);
            }

            return(metaList);
        }