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).
This commit is contained in:
max 2019-07-16 14:12:32 +02:00
parent 09f7c488b9
commit 7f17793af0
5 changed files with 185 additions and 20 deletions

View File

@ -363,7 +363,7 @@ namespace MA_TextureAtlasserPro
//Create new texture part //Create new texture part
Texture2D newTexturePart = (Texture2D)MA_Texture.MA_TextureUtils.ConvertToReadableTexture(q.textureGroups[i].texture); Texture2D newTexturePart = (Texture2D)MA_Texture.MA_TextureUtils.ConvertToReadableTexture(q.textureGroups[i].texture);
//Scale it //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 //Add it
newTexture = newTexture.MA_Combine2D(newTexturePart, (int)q.guiRect.x, (int)q.guiRect.y); newTexture = newTexture.MA_Combine2D(newTexturePart, (int)q.guiRect.x, (int)q.guiRect.y);
} }
@ -371,12 +371,79 @@ namespace MA_TextureAtlasserPro
//Save it //Save it
newTexture.MA_Save2D("MA_" + newTexture.name, savePath); newTexture.MA_Save2D("MA_" + newTexture.name, savePath);
TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(savePath + "MA_" + newTexture.name + ".png");
textureImporter.textureType = TextureImporterType.Default;
textureImporter.SaveAndReimport();
} }
//Refresh //Refresh
AssetDatabase.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> spriteMetaData = new List<SpriteMetaData>();
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 #endif

View File

@ -13,6 +13,8 @@ namespace MA_TextureAtlasserPro
private bool isEditing = false; private bool isEditing = false;
private GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
public MA_TextureAtlasserProInspectorView(MA_TextureAtlasserProWindow currentEditorWindow, string title) : base(currentEditorWindow, title) public MA_TextureAtlasserProInspectorView(MA_TextureAtlasserProWindow currentEditorWindow, string title) : base(currentEditorWindow, title)
{ {
@ -115,8 +117,17 @@ namespace MA_TextureAtlasserPro
} }
GUILayout.FlexibleSpace(); 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("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.EndVertical();
GUILayout.EndArea(); GUILayout.EndArea();

View File

@ -14,15 +14,20 @@ namespace MA_TextureAtlasserPro
public static MA_TextureAtlasserProWindow curWindow; public static MA_TextureAtlasserProWindow curWindow;
//Data //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")] [MenuItem("MA_ToolKit/MA_TextureAtlasserPro/Export Atlas")]
private static void Init() private static void Init()
{ {
GetCurrentWindow(); GetCurrentWindow();
thisWindow.minSize = new Vector2(500,160); thisWindow.minSize = new Vector2(420, 200);
thisWindow.maxSize = new Vector2(500,160); thisWindow.maxSize = new Vector2(420, 200);
thisWindow.titleContent.text = "MA_ExportTextureAtlas"; thisWindow.titleContent.text = "MA_ExportTextureAtlas";
@ -35,8 +40,8 @@ namespace MA_TextureAtlasserPro
GetCurrentWindow(); GetCurrentWindow();
thisWindow.minSize = new Vector2(500,160); thisWindow.minSize = new Vector2(420, 200);
thisWindow.maxSize = new Vector2(500,160); thisWindow.maxSize = new Vector2(420, 200);
thisWindow.titleContent.text = "MA_ExportTextureAtlas"; thisWindow.titleContent.text = "MA_ExportTextureAtlas";
@ -94,18 +99,68 @@ namespace MA_TextureAtlasserPro
if(curWindow != null && curWindow.textureAtlas != null) if(curWindow != null && curWindow.textureAtlas != null)
{ {
//Export options
GUILayout.Box("Note: No custom export options right now.. :<", EditorStyles.helpBox);
//Export //Export
GUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.BeginVertical();
GUILayout.BeginHorizontal(EditorStyles.helpBox);
GUILayout.Label("Meshes: OBJ | Textures: PNG"); if (GUILayout.Button("3D", GUILayout.ExpandWidth(false)))
if(GUILayout.Button("Export Atlas", GUILayout.ExpandWidth(true), GUILayout.Height(37)))
{ {
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(); GUILayout.EndVertical();
} }
else if(curWindow == null) else if(curWindow == null)

View File

@ -155,6 +155,30 @@ namespace MA_Texture
return 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 #endregion
#region combine #region combine

View File

@ -1,13 +1,21 @@
[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)]()
# MA_TextureAtlasser # MA_TextureAtlasser
Texture atlas creator for Unity Texture atlas creator for Unity
You can combine textures and/or remap the UVs for the 3D models. [![Image](https://maxartz15.com/wp-content/uploads/2019/04/MA_TextureAtlas.png)]()
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.
https://youtu.be/PBRKlopkZP0 You can combine textures and/or remap the UVs 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 Download the UnityPackage here: https://github.com/maxartz15/MA_TextureAtlasser/releases
[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)]()
For more information: https://maxartz15.com/ma_textureatlas/ For more information: https://maxartz15.com/ma_textureatlas/