From 7f17793af0e9fd7b2574eb98a3f47dcd3408e1d6 Mon Sep 17 00:00:00 2001 From: max Date: Tue, 16 Jul 2019 14:12:32 +0200 Subject: [PATCH] Fixed gray texture on export. Fixed gray texture on export bug, it was caused by the texture scale function (during upscaling), right now it's required to have the texture dimensions be a power of 2 width/height. Optional OBJ/PNG/sprite export options. Chanaged readme. TODO: Cleanup export code. Make proper scale options (bilinear & point). --- .../Utils/MA_TextureAtlasserProUtils.cs | 69 +++++++++++++++- .../MA_TextureAtlasserProInspectorView.cs | 13 ++- .../MA_TextureAtlasserProExportWindow.cs | 79 ++++++++++++++++--- .../TextureUtils/MA_TextureUtils.cs | 24 ++++++ README.md | 20 +++-- 5 files changed, 185 insertions(+), 20 deletions(-) diff --git a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Utils/MA_TextureAtlasserProUtils.cs b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Utils/MA_TextureAtlasserProUtils.cs index d567e62..130e3eb 100644 --- a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Utils/MA_TextureAtlasserProUtils.cs +++ b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Utils/MA_TextureAtlasserProUtils.cs @@ -363,7 +363,7 @@ namespace MA_TextureAtlasserPro //Create new texture part Texture2D newTexturePart = (Texture2D)MA_Texture.MA_TextureUtils.ConvertToReadableTexture(q.textureGroups[i].texture); //Scale it - newTexturePart = newTexturePart.MA_Scale2D((int)q.guiRect.width, (int)q.guiRect.height); + newTexturePart = newTexturePart.MA_Scale32D((int)q.guiRect.width, (int)q.guiRect.height); //Add it newTexture = newTexture.MA_Combine2D(newTexturePart, (int)q.guiRect.x, (int)q.guiRect.y); } @@ -371,12 +371,79 @@ namespace MA_TextureAtlasserPro //Save it newTexture.MA_Save2D("MA_" + newTexture.name, savePath); + + TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(savePath + "MA_" + newTexture.name + ".png"); + textureImporter.textureType = TextureImporterType.Default; + textureImporter.SaveAndReimport(); } //Refresh AssetDatabase.Refresh(); } } + + public static void ExportAtlasSpritesPNG(MA_TextureAtlasserProAtlas atlas, bool sliceSprites = true, string savePath = EXPORTASSETPATH) + { + if (atlas != null && atlas.textureQuads != null && atlas.textureGroupRegistration != null) + { + ExportAtlasTexturesPNG(atlas, savePath); + + //Foreach texture group + for (int i = 0; i < atlas.textureGroupRegistration.Count; i++) + { + //Convert + string textureName = "MA_" + atlas.name + "_" + atlas.textureGroupRegistration[i].name + ".png"; + TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(savePath + textureName); + textureImporter.textureType = TextureImporterType.Sprite; + textureImporter.alphaIsTransparency = true; + + //Slice sprites. + if (sliceSprites) + { + textureImporter.spriteImportMode = SpriteImportMode.None; //Reset it to update? + textureImporter.spriteImportMode = SpriteImportMode.Multiple; + List spriteMetaData = new List(); + + foreach (MA_TextureAtlasserProQuad q in atlas.textureQuads) + { + if (q.textureGroups != null && q.textureGroups[i].texture != null) + { + //Create new SpriteMetaData. + SpriteMetaData smd = new SpriteMetaData(); + + smd.name = q.name; + smd.rect = new Rect(q.guiRect.x, atlas.textureAtlasSize.y - q.guiRect.y - q.guiRect.height, q.guiRect.width, q.guiRect.height); + + spriteMetaData.Add(smd); + } + } + + textureImporter.spritesheet = spriteMetaData.ToArray(); + } + else + { + textureImporter.spriteImportMode = SpriteImportMode.Single; + } + + + textureImporter.SaveAndReimport(); + } + + //Refresh + AssetDatabase.Refresh(); + } + } + + public static bool IsPowerOfTwo(int value) + { + //While x is even and > 1 + while (((value % 2) == 0) && value > 1) + { + value /= 2; + } + + return (value == 1); + } } } #endif \ No newline at end of file diff --git a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Views/MA_TextureAtlasserProInspectorView.cs b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Views/MA_TextureAtlasserProInspectorView.cs index 6c9f7b6..8156894 100644 --- a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Views/MA_TextureAtlasserProInspectorView.cs +++ b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Views/MA_TextureAtlasserProInspectorView.cs @@ -13,6 +13,8 @@ namespace MA_TextureAtlasserPro private bool isEditing = false; + private GUIStyle labelStyle = new GUIStyle(GUI.skin.label); + public MA_TextureAtlasserProInspectorView(MA_TextureAtlasserProWindow currentEditorWindow, string title) : base(currentEditorWindow, title) { @@ -115,8 +117,17 @@ namespace MA_TextureAtlasserPro } GUILayout.FlexibleSpace(); + if(!MA_TextureAtlasserProUtils.IsPowerOfTwo((int)curWindow.textureAtlas.selectedTextureQuad.guiRect.width) || !MA_TextureAtlasserProUtils.IsPowerOfTwo((int)curWindow.textureAtlas.selectedTextureQuad.guiRect.height)) + { + labelStyle.normal.textColor = Color.red; + } + else + { + labelStyle.normal.textColor = Color.black; + } + GUILayout.Label("x " + curWindow.textureAtlas.selectedTextureQuad.guiRect.x.ToString() + ", y " + curWindow.textureAtlas.selectedTextureQuad.guiRect.y.ToString()); - GUILayout.Label("w " + curWindow.textureAtlas.selectedTextureQuad.guiRect.width.ToString() + ", h " + curWindow.textureAtlas.selectedTextureQuad.guiRect.height.ToString()); + GUILayout.Label("w " + curWindow.textureAtlas.selectedTextureQuad.guiRect.width.ToString() + ", h " + curWindow.textureAtlas.selectedTextureQuad.guiRect.height.ToString(), labelStyle); GUILayout.EndVertical(); GUILayout.EndArea(); diff --git a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Windows/MA_TextureAtlasserProExportWindow.cs b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Windows/MA_TextureAtlasserProExportWindow.cs index fc3d31a..ecf7f76 100644 --- a/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Windows/MA_TextureAtlasserProExportWindow.cs +++ b/MA_ToolBox/MA_TextureAtlasserPro/Scripts/Editor/Windows/MA_TextureAtlasserProExportWindow.cs @@ -14,15 +14,20 @@ namespace MA_TextureAtlasserPro public static MA_TextureAtlasserProWindow curWindow; //Data - private static bool isLoaded = false; //Make sure we wait a frame at the start to setup and don't draw. + private static bool isLoaded = false; //Make sure we wait a frame at the start to setup and don't draw. + + private bool exportObjDefault = false; + private bool exportPngDefault = false; + private bool exportSprite = false; + private bool exportSliceSprite = false; [MenuItem("MA_ToolKit/MA_TextureAtlasserPro/Export Atlas")] private static void Init() { GetCurrentWindow(); - thisWindow.minSize = new Vector2(500,160); - thisWindow.maxSize = new Vector2(500,160); + thisWindow.minSize = new Vector2(420, 200); + thisWindow.maxSize = new Vector2(420, 200); thisWindow.titleContent.text = "MA_ExportTextureAtlas"; @@ -35,8 +40,8 @@ namespace MA_TextureAtlasserPro GetCurrentWindow(); - thisWindow.minSize = new Vector2(500,160); - thisWindow.maxSize = new Vector2(500,160); + thisWindow.minSize = new Vector2(420, 200); + thisWindow.maxSize = new Vector2(420, 200); thisWindow.titleContent.text = "MA_ExportTextureAtlas"; @@ -94,18 +99,68 @@ namespace MA_TextureAtlasserPro if(curWindow != null && curWindow.textureAtlas != null) { - //Export options - GUILayout.Box("Note: No custom export options right now.. :<", EditorStyles.helpBox); - //Export - GUILayout.BeginVertical(EditorStyles.helpBox); + GUILayout.BeginVertical(); + GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label("Meshes: OBJ | Textures: PNG"); - if(GUILayout.Button("Export Atlas", GUILayout.ExpandWidth(true), GUILayout.Height(37))) + if (GUILayout.Button("3D", GUILayout.ExpandWidth(false))) { - MA_TextureAtlasserProUtils.ExportAtlas(curWindow.textureAtlas); + exportObjDefault = true; + exportPngDefault = true; + exportSprite = false; + exportSliceSprite = false; } + if (GUILayout.Button("2D", GUILayout.ExpandWidth(false))) + { + exportObjDefault = false; + exportPngDefault = true; + exportSprite = true; + exportSliceSprite = true; + } + + GUILayout.EndHorizontal(); + + GUILayout.Label("Meshes:"); + exportObjDefault = GUILayout.Toggle(exportObjDefault, "OBJ default."); + + GUILayout.Label("Textures:"); + GUILayout.BeginHorizontal(); + exportPngDefault = GUILayout.Toggle(exportPngDefault, "PNG default."); + if(exportPngDefault) + { + exportSprite = GUILayout.Toggle(exportSprite, "Sprite."); + if (exportSprite) + { + exportSliceSprite = GUILayout.Toggle(exportSliceSprite, "Slice sprites."); + } + } + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(EditorStyles.helpBox); + + if (GUILayout.Button("Export", GUILayout.ExpandWidth(true), GUILayout.Height(37))) + { + if(exportObjDefault) + { + MA_TextureAtlasserProUtils.ExportAtlasMeshesObj(curWindow.textureAtlas); + } + + if(exportPngDefault) + { + if(exportSprite) + { + MA_TextureAtlasserProUtils.ExportAtlasSpritesPNG(curWindow.textureAtlas, exportSliceSprite); + } + else + { + MA_TextureAtlasserProUtils.ExportAtlasTexturesPNG(curWindow.textureAtlas); + } + } + } + + GUILayout.EndHorizontal(); GUILayout.EndVertical(); } else if(curWindow == null) diff --git a/MA_ToolBox/MA_Utilities/TextureUtils/MA_TextureUtils.cs b/MA_ToolBox/MA_Utilities/TextureUtils/MA_TextureUtils.cs index 3ed79c7..e344c1e 100644 --- a/MA_ToolBox/MA_Utilities/TextureUtils/MA_TextureUtils.cs +++ b/MA_ToolBox/MA_Utilities/TextureUtils/MA_TextureUtils.cs @@ -155,6 +155,30 @@ namespace MA_Texture return texture; } + + public static Texture2D MA_Scale32D(this Texture2D texture, int width, int height) + { + float ratioWidth = (float)width / texture.width; + float ratioHeight = (float)height / texture.height; + + Texture2D newTexture = new Texture2D(width, height); + + for (int x = 0; x < width; x++) + { + int posX = Mathf.FloorToInt(x / ratioWidth); + for (int y = 0; y < height; y++) + { + int posY = Mathf.FloorToInt(y / ratioHeight); + Color pixel = texture.GetPixel(posX, posY); + newTexture.SetPixel(x, y, new Color(pixel.r, pixel.g, pixel.b, pixel.a)); + } + } + + newTexture.name = texture.name; + + newTexture.Apply(); + return newTexture; + } #endregion #region combine diff --git a/README.md b/README.md index b639f8d..29cb7f5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,21 @@ -[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)]() - # MA_TextureAtlasser Texture atlas creator for Unity -You can combine textures and/or remap the UV’s for the 3D models. -By having full control over the size and position of the textures that are being placed in the atlas you will never stand for surprises when exporting. This will cost some more time than auto-generating your texture atlases but you know whats going on and which models/textures are getting priority. +[![Image](https://maxartz15.com/wp-content/uploads/2019/04/MA_TextureAtlas.png)]() -https://youtu.be/PBRKlopkZP0 +You can combine textures and/or remap the UV’s for the 3D models. +By having full control over the size and position of the textures that are being placed in the atlas you will never stand for surprises when exporting. This will cost some more time than auto-generating your texture atlases but you know whats going on and which models/textures are getting priority. The tool can also be used to make 2D sprite sheets. + +- Combine textures/sprites. +- Automatically adjusts the UV's of the assigned meshes to match the new texture atlas. +- Exports meshes as OBJ. +- Exports texture atlas as PNG. +- Exports texture atlas as a (sliced) sprite sheet. + +[Example video](https://youtu.be/PBRKlopkZP0) Download the UnityPackage here: https://github.com/maxartz15/MA_TextureAtlasser/releases -For more information: https://maxartz15.com/ma_textureatlas/ +[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)]() + +For more information: https://maxartz15.com/ma_textureatlas/ \ No newline at end of file