protected override void Initialize() { RegisterReplaceHandler <SpriteSet>(BinaryFile.Load <SpriteSet>); RegisterExportHandler <SpriteSet>(filePath => Data.Save(filePath)); RegisterCustomHandler("Export All", () => { using (var folderBrowseDialog = new VistaFolderBrowserDialog()) { folderBrowseDialog.Description = "Select a folder to save sprites to."; folderBrowseDialog.UseDescriptionForTitle = true; if (folderBrowseDialog.ShowDialog() != DialogResult.OK) { return; } foreach (var pair in SpriteCropper.Crop(Data)) { pair.Value.Save(Path.Combine(folderBrowseDialog.SelectedPath, $"{pair.Key.Name}.png")); } } }, Keys.Control | Keys.Shift | Keys.E); base.Initialize(); }
protected override void InitializeCore() { RegisterReplaceHandler <SpriteSet>(BinaryFile.Load <SpriteSet>); RegisterExportHandler <SpriteSet>((path) => Data.Save(path)); RegisterCustomHandler("Export All", () => { using (var saveFileDialog = new SaveFileDialog()) { saveFileDialog.AutoUpgradeEnabled = true; saveFileDialog.CheckPathExists = true; saveFileDialog.Title = "Select a folder to export textures to."; saveFileDialog.FileName = "Enter into a directory and press Save"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { var outputDirectory = Path.GetDirectoryName(saveFileDialog.FileName); foreach (var sprite in SpriteCropper.Crop(Data)) { sprite.Value.Save(Path.Combine(outputDirectory, sprite.Key.Name + ".png")); } } } }, Keys.Control | Keys.Shift | Keys.E); RegisterDataUpdateHandler(() => { var data = new SpriteSet(); data.Format = Format; data.Endianness = Endianness; data.Sprites.AddRange(Sprites.Data); data.TextureSet.Textures.AddRange(Textures.Data.Textures); return(data); }); }
private static void WriteCroppedTexture(UncroppedStanding standing, SpriteCropper cropper) { var cropRect = cropper.cropRect; var cropped = new Texture2D(cropRect.width, cropRect.height, TextureFormat.RGBA32, false); var texture = cropper.sprite.texture; var pixels = texture.GetPixels(cropRect.x, cropRect.y, cropRect.width, cropRect.height); cropped.SetPixels(pixels); cropped.Apply(); var bytes = cropped.EncodeToPNG(); var fileName = cropper.sprite.name + ".png"; var absoluteOutputPath = Path.Combine(standing.absoluteOutputDirectory, fileName); Directory.CreateDirectory(Path.GetDirectoryName(absoluteOutputPath)); File.WriteAllBytes(absoluteOutputPath, bytes); var assetPath = Path.Combine(standing.outputDirectory, fileName); AssetDatabase.ImportAsset(assetPath); var importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; if (importer.textureType != TextureImporterType.Sprite) { importer.textureType = TextureImporterType.Sprite; importer.SaveAndReimport(); } }
private static void GenerateMetadata(UncroppedStanding standing, SpriteCropper cropper) { var meta = CreateInstance <SpriteWithOffset>(); meta.offset = (cropper.cropRect.center - cropper.boundRect.center) / cropper.sprite.pixelsPerUnit; var path = Path.Combine(standing.outputDirectory, cropper.sprite.name + ".png"); meta.sprite = AssetDatabase.LoadAssetAtPath <Sprite>(path); AssetDatabase.CreateAsset(meta, Path.Combine(standing.outputDirectory, cropper.sprite.name + ".asset")); }
private static void WriteCropResult(UncroppedStanding standing, SpriteCropper cropper) { var uncropped = cropper.sprite.texture; var cropRect = cropper.cropRect; var cropped = new Texture2D(cropRect.width, cropRect.height, TextureFormat.RGBA32, false); var pixels = uncropped.GetPixels(cropRect.x, cropRect.y, cropRect.width, cropRect.height); cropped.SetPixels(pixels); cropped.Apply(); var bytes = cropped.EncodeToPNG(); File.WriteAllBytes(Path.Combine(standing.absoluteOutputDirectory, cropper.sprite.name + ".png"), bytes); }
private static void GenerateMetaData(UncroppedStanding standing, SpriteCropper cropper) { var cropRect = cropper.cropRect; var uncropped = cropper.sprite.texture; var outputDir = Path.Combine("Assets", standing.outputDirectory); var cropped = AssetDatabase.LoadAssetAtPath <Sprite>( Path.Combine(outputDir, cropper.sprite.name + ".png")); var meta = CreateInstance <SpriteWithOffset>(); meta.offset = (cropRect.center - new Vector2(uncropped.width, uncropped.height) / 2.0f) / cropper.sprite.pixelsPerUnit; meta.sprite = cropped; AssetDatabase.CreateAsset(meta, Path.Combine(outputDir, cropper.sprite.name + ".asset")); }
private static void DrawPreview(SpriteCropper cropper) { var sprite = cropper.sprite; var height = EditorGUIUtility.currentViewWidth / sprite.texture.width * sprite.texture.height; var rect = EditorGUILayout.GetControlRect(false, height); EditorGUI.DrawTextureTransparent(rect, sprite.texture); var cropRectInt = cropper.cropRect; var cropRect = new Rect( (float)cropRectInt.x / sprite.texture.width, (float)cropRectInt.y / sprite.texture.height, (float)cropRectInt.width / sprite.texture.width, (float)cropRectInt.height / sprite.texture.height ); EditorUtils.DrawPreviewCropFrame(rect, cropRect, Color.red); }
protected override void Initialize() { AddReplaceHandler <SpriteSet>(BinaryFile.Load <SpriteSet>); AddExportHandler <SpriteSet>(filePath => Data.Save(filePath)); AddDirtyCustomHandler("Add dummy sprite", () => { Data.Sprites.Add(new Sprite { Name = "DUMMY", ResolutionMode = ResolutionMode.HDTV720 }); return(true); }, Keys.None, CustomHandlerFlags.Repopulate); AddCustomHandlerSeparator(); AddCustomHandler("Export All", () => { using (var folderBrowseDialog = new VistaFolderBrowserDialog()) { folderBrowseDialog.Description = "Select a folder to save sprites to."; folderBrowseDialog.UseDescriptionForTitle = true; if (folderBrowseDialog.ShowDialog() != DialogResult.OK) { return; } foreach (var pair in SpriteCropper.Crop(Data)) { pair.Value.Save(Path.Combine(folderBrowseDialog.SelectedPath, $"{pair.Key.Name}.png")); } } }, Keys.Control | Keys.Shift | Keys.E); AddCustomHandlerSeparator(); AddDirtyCustomHandler("Scale all sprites", () => { string input = "2.0"; while (true) { using (var inputDialog = new InputDialog { WindowTitle = "Scale all sprites", Input = input }) { if (inputDialog.ShowDialog() != DialogResult.OK) { break; } if (float.TryParse(inputDialog.Input, NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out float factor)) { foreach (var sprite in Data.Sprites) { sprite.Width *= factor; sprite.Height *= factor; sprite.X *= factor; sprite.Y *= factor; } return(true); } else { MessageBox.Show("Invalid factor.", Program.Name, MessageBoxButtons.OK, MessageBoxIcon.Error); } input = inputDialog.Input; } } return(false); }); AddDirtyCustomHandler("Set all resolution modes to...", () => { string input = "HDTV720"; while (true) { using (var inputDialog = new InputDialog { WindowTitle = "Set all resolution modes", Input = input }) { if (inputDialog.ShowDialog() != DialogResult.OK) { break; } if (!Enum.TryParse(input = inputDialog.Input, true, out ResolutionMode mode)) { MessageBox.Show("Please enter a valid resolution mode.", Program.Name, MessageBoxButtons.OK, MessageBoxIcon.Error); continue; } foreach (var sprite in Data.Sprites) { sprite.ResolutionMode = mode; } return(true); } } return(false); }); base.Initialize(); }
protected override void Initialize() { RegisterReplaceHandler <SpriteSet>(BinaryFile.Load <SpriteSet>); RegisterExportHandler <SpriteSet>(filePath => Data.Save(filePath)); RegisterCustomHandler("Export All", () => { using (var folderBrowseDialog = new VistaFolderBrowserDialog()) { folderBrowseDialog.Description = "Select a folder to save sprites to."; folderBrowseDialog.UseDescriptionForTitle = true; if (folderBrowseDialog.ShowDialog() != DialogResult.OK) { return; } foreach (var pair in SpriteCropper.Crop(Data)) { pair.Value.Save(Path.Combine(folderBrowseDialog.SelectedPath, $"{pair.Key.Name}.png")); } } }, Keys.Control | Keys.Shift | Keys.E); RegisterCustomHandler("Set all resolution modes to...", () => { string input = "HDTV720"; while (true) { using (var inputDialog = new InputDialog { WindowTitle = "Set all resolution modes", Input = input }) { if (inputDialog.ShowDialog() != DialogResult.OK) { break; } if (!Enum.TryParse(input = inputDialog.Input, out ResolutionMode mode)) { MessageBox.Show("Please enter a valid resolution mode.", "Miku Miku Model", MessageBoxButtons.OK, MessageBoxIcon.Error); continue; } foreach (var sprite in Data.Sprites) { sprite.ResolutionMode = mode; } IsDirty = true; break; } } }); RegisterCustomHandler("Scale all sprites...", () => { string input = "2.0"; while (true) { using (var inputDialog = new InputDialog { WindowTitle = "Scale all sprites", Input = input }) { if (inputDialog.ShowDialog() != DialogResult.OK) { break; } double dfactor; if (Double.TryParse(input, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowThousands, System.Globalization.CultureInfo.InvariantCulture, out dfactor)) { float factor = (float)dfactor; foreach (var sprite in Data.Sprites) { sprite.Width = sprite.Width * factor; sprite.Height = sprite.Height * factor; sprite.X = sprite.X * factor; sprite.Y = sprite.Y * factor; } IsDirty = true; } else { MessageBox.Show("Invalid factor.", "Miku Miku Model", MessageBoxButtons.OK, MessageBoxIcon.Error); } break; } } }); base.Initialize(); }
public static void AutoCrop(SpriteCropper cropper) { var texture = cropper.sprite.texture; var colors = texture.GetPixels(); var boundRect = cropper.boundRect; int left = Math.Max(0, boundRect.xMin); int right = Math.Min(texture.width, boundRect.xMax); int bottom = Math.Max(0, boundRect.yMin); int top = Math.Min(texture.height, boundRect.yMax); bool hasPixel = false; int minX = int.MaxValue; int maxX = int.MinValue; int minY = int.MaxValue; int maxY = int.MinValue; for (var i = bottom; i < top; ++i) { bool hasPixelInRow = false; for (var j = left; j < right; ++j) { var color = colors[texture.width * i + j]; if (color.a > cropper.autoCropAlpha) { hasPixelInRow = true; minX = Math.Min(minX, j); break; } } if (!hasPixelInRow) { continue; } for (var j = right - 1; j >= left; --j) { var color = colors[texture.width * i + j]; if (color.a > cropper.autoCropAlpha) { maxX = Math.Max(maxX, j); break; } } hasPixel = true; minY = Math.Min(minY, i); maxY = Math.Max(maxY, i); } if (hasPixel) { int padding = cropper.autoCropPadding; int x1 = Math.Max(left, minX - padding); int x2 = Math.Min(right, maxX + padding + 1); int y1 = Math.Max(bottom, minY - padding); int y2 = Math.Min(top, maxY + padding + 1); RoundWithBounds(ref x1, ref x2, left, right); RoundWithBounds(ref y1, ref y2, bottom, top); cropper.cropRect = new RectInt(x1, y1, x2 - x1, y2 - y1); } else { // Empty image var center = Vector2Int.RoundToInt(boundRect.center); cropper.cropRect = new RectInt(center.x - 2, center.y - 2, 4, 4); } EditorUtility.SetDirty(cropper); }
public static void AutoCrop(SpriteCropper cropper) { var sprite = cropper.sprite; var texture = sprite.texture; var width = texture.width; var height = texture.height; var colors = texture.GetPixels(); // scan from bottom to top int minX = width - 1, maxX = 0; int minY = -1, maxY = -1; for (var i = 0; i < height; i++) { var hasPixel = false; for (var j = 0; j < width; j++) { var color = colors[width * i + j]; if (color.a > cropper.autoCropAlpha) { hasPixel = true; minX = Math.Min(minX, j); maxX = Math.Max(maxX, j); } } if (hasPixel && minY == -1) { minY = i; } } // scan from top to bottom for (var i = height - 1; i >= 0; i--) { var hasPixel = false; for (var j = 0; j < width; j++) { var color = colors[width * i + j]; if (color.a > cropper.autoCropAlpha) { hasPixel = true; } } if (hasPixel && maxY == -1) { maxY = i; } } if (minY == -1 || maxY == -1) { // empty image cropper.cropRect = new RectInt(0, 0, 1, 1); } else { var padding = cropper.autoCropPadding; var x1 = Math.Max(0, minX - padding); var y1 = Math.Max(0, minY - padding); var x2 = Math.Min(maxX + padding, width - 1); var y2 = Math.Min(maxY + padding, height - 1); // try to round to 4 var cw = RoundToFour(x2 - x1 + 1); var ch = RoundToFour(y2 - y1 + 1); if (x1 + cw > width) { x1 = width - cw; } if (y1 + ch > height) { y1 = height - ch; } x2 = x1 + cw - 1; y2 = y1 + ch - 1; // restrain in range x1 = Math.Max(0, x1); y1 = Math.Max(0, y1); cropper.cropRect = new RectInt(x1, y1, x2 - x1 + 1, y2 - y1 + 1); } EditorUtility.SetDirty(cropper); }
public static List <GameObject> SplitSpriteByInPieces(SpriteRenderer spriteToCrop, SplitType splitType, float intersectPercentage, bool cutsHorizontally, Vector3 extraRotation) { List <GameObject> splittedSprites = new List <GameObject>(); int splitHorizontal = Random.Range(0, 2); switch (splitType) { case SplitType.TWO: if (intersectPercentage <= 0 || intersectPercentage >= 1f) { intersectPercentage = .5f; } if (cutsHorizontally) { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, 1f, 0f, intersectPercentage, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, 1f, intersectPercentage, 1, extraRotation)); } else { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, intersectPercentage, 0f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, intersectPercentage, 1f, 0f, 1f, extraRotation)); } break; case SplitType.FOUR: if (intersectPercentage <= 0 || intersectPercentage >= 1f) { intersectPercentage = .5f; } if (cutsHorizontally) { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, 0f, intersectPercentage, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, 0f, intersectPercentage, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, intersectPercentage, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, intersectPercentage, 1f, extraRotation)); } else { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, intersectPercentage, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, intersectPercentage, 1f, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, intersectPercentage, .5f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, intersectPercentage, 1f, .5f, 1f, extraRotation)); } break; case SplitType.EIGHT: if (splitHorizontal == 0) { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .25f, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .25f, .5f, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, .75f, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .75f, 1f, 0f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .25f, .5f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .25f, .5f, .5f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, .75f, .5f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .75f, 1f, .5f, 1f, extraRotation)); } else { splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, 0f, .25f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, .25f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, .5f, .75f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, 0f, .5f, .75f, 1f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, 0f, .25f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, .25f, .5f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, .5f, .75f, extraRotation)); splittedSprites.Add(SpriteCropper.CropSprite(spriteToCrop, .5f, 1f, .75f, 1f, extraRotation)); } break; } return(splittedSprites); }