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)); }
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); }