Merge pull request #1 from goto01/master

Adding the scaling and export options.

Merging the changes made.
Sub-meshes export bug-fix.
Export window changes.
New texture scaling function.

(TODO: some old code cleanup.)
This commit is contained in:
max 2019-08-29 18:56:01 +02:00 committed by GitHub
commit 26a0f68454
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 247 additions and 50 deletions

View File

@ -53,7 +53,10 @@ namespace MA_TextureAtlasserPro
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.Label(this.name); var tempColor = GUI.backgroundColor;
GUI.backgroundColor = Color.white;
GUILayout.Label(this.name, GUI.skin.box);
GUI.backgroundColor = tempColor;
GUILayout.FlexibleSpace(); GUILayout.FlexibleSpace();
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();

View File

@ -315,6 +315,25 @@ namespace MA_TextureAtlasserPro
} }
} }
public static void ModifyMeshes(MA_TextureAtlasserProAtlas atlas)
{
if (atlas == null || atlas.textureQuads == null) return;
var quads = atlas.textureQuads;
for (var index = 0; index < quads.Count; index++)
{
var quad = quads[index];
if (quad.meshes == null) continue;
var meshes = quad.meshes;
for (var meshIndex = 0; meshIndex < quad.meshes.Count; meshIndex++)
{
if (meshes[meshIndex] == null) continue;
MA_MeshUtils.MA_UVReMap(meshes[meshIndex], atlas.textureAtlasSize, quad.guiRect);
EditorUtility.SetDirty(meshes[meshIndex]);
}
}
AssetDatabase.SaveAssets();
}
// public static void ExportAtlasTexturePNG(MA_TextureAtlasserProAtlas atlas, string savePath = EXPORTASSETPATH) // public static void ExportAtlasTexturePNG(MA_TextureAtlasserProAtlas atlas, string savePath = EXPORTASSETPATH)
// { // {
// if(atlas != null && atlas.textureQuads != null) // if(atlas != null && atlas.textureQuads != null)
@ -363,7 +382,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_Scale32D((int)q.guiRect.width, (int)q.guiRect.height); newTexturePart = newTexturePart.ScaleTexture((int)q.guiRect.width, (int)q.guiRect.height, true);
//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);
} }

View File

@ -7,8 +7,18 @@ using MA_Editor;
namespace MA_TextureAtlasserPro namespace MA_TextureAtlasserPro
{ {
public class MA_TextureAtlasserProExportWindow : EditorWindow public class MA_TextureAtlasserProExportWindow : EditorWindow
{ {
private const int WindowHeight = 215;
private enum ExportMode
{
None,
D3,
D2,
Meshes,
}
//Editor //Editor
private static MA_TextureAtlasserProExportWindow thisWindow; private static MA_TextureAtlasserProExportWindow thisWindow;
public static MA_TextureAtlasserProWindow curWindow; public static MA_TextureAtlasserProWindow curWindow;
@ -16,7 +26,11 @@ namespace MA_TextureAtlasserPro
//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 ExportMode _selectedExportMode;
private bool _showAdvancedEditor;
private bool exportObjDefault = false; private bool exportObjDefault = false;
private bool _replaceMeshes = false;
private bool exportPngDefault = false; private bool exportPngDefault = false;
private bool exportSprite = false; private bool exportSprite = false;
private bool exportSliceSprite = false; private bool exportSliceSprite = false;
@ -26,8 +40,8 @@ namespace MA_TextureAtlasserPro
{ {
GetCurrentWindow(); GetCurrentWindow();
thisWindow.minSize = new Vector2(420, 200); thisWindow.minSize = new Vector2(420, WindowHeight);
thisWindow.maxSize = new Vector2(420, 200); thisWindow.maxSize = new Vector2(420, WindowHeight);
thisWindow.titleContent.text = "MA_ExportTextureAtlas"; thisWindow.titleContent.text = "MA_ExportTextureAtlas";
@ -40,8 +54,8 @@ namespace MA_TextureAtlasserPro
GetCurrentWindow(); GetCurrentWindow();
thisWindow.minSize = new Vector2(420, 200); thisWindow.minSize = new Vector2(420, WindowHeight);
thisWindow.maxSize = new Vector2(420, 200); thisWindow.maxSize = new Vector2(420, WindowHeight);
thisWindow.titleContent.text = "MA_ExportTextureAtlas"; thisWindow.titleContent.text = "MA_ExportTextureAtlas";
@ -101,45 +115,13 @@ namespace MA_TextureAtlasserPro
{ {
//Export //Export
GUILayout.BeginVertical(); GUILayout.BeginVertical();
GUILayout.BeginHorizontal(EditorStyles.helpBox);
if (GUILayout.Button("3D", GUILayout.ExpandWidth(false))) DrawExportModeEditor();
{ DrawAdvancedEditor();
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); GUILayout.BeginHorizontal(EditorStyles.helpBox);
GUI.enabled = _selectedExportMode != ExportMode.None;
if (GUILayout.Button("Export", GUILayout.ExpandWidth(true), GUILayout.Height(37))) if (GUILayout.Button("Export", GUILayout.ExpandWidth(true), GUILayout.Height(37)))
{ {
if(exportObjDefault) if(exportObjDefault)
@ -147,6 +129,9 @@ namespace MA_TextureAtlasserPro
MA_TextureAtlasserProUtils.ExportAtlasMeshesObj(curWindow.textureAtlas); MA_TextureAtlasserProUtils.ExportAtlasMeshesObj(curWindow.textureAtlas);
} }
if (_replaceMeshes)
MA_TextureAtlasserProUtils.ModifyMeshes(curWindow.textureAtlas);
if(exportPngDefault) if(exportPngDefault)
{ {
if(exportSprite) if(exportSprite)
@ -160,6 +145,8 @@ namespace MA_TextureAtlasserPro
} }
} }
GUI.enabled = true;
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
GUILayout.EndVertical(); GUILayout.EndVertical();
} }
@ -187,6 +174,79 @@ namespace MA_TextureAtlasserPro
if(e.type == EventType.Repaint) if(e.type == EventType.Repaint)
isLoaded = true; isLoaded = true;
} }
private void DrawExportModeEditor()
{
GUILayout.BeginHorizontal(EditorStyles.helpBox);
GUILayout.FlexibleSpace();
var value = GUILayout.Toggle(_selectedExportMode == ExportMode.D3, "3D", EditorStyles.miniButtonLeft,
GUILayout.ExpandWidth(false));
if (value && _selectedExportMode != ExportMode.D3)
{
_selectedExportMode = ExportMode.D3;
exportObjDefault = true;
_replaceMeshes = false;
exportPngDefault = true;
exportSprite = false;
exportSliceSprite = false;
}
value = GUILayout.Toggle(_selectedExportMode == ExportMode.D2, "2D", EditorStyles.miniButtonMid,
GUILayout.ExpandWidth(false));
if (value && _selectedExportMode != ExportMode.D2)
{
_selectedExportMode = ExportMode.D2;
exportObjDefault = false;
_replaceMeshes = false;
exportPngDefault = true;
exportSprite = true;
exportSliceSprite = true;
}
value = GUILayout.Toggle(_selectedExportMode == ExportMode.Meshes, "Replace source meshes", EditorStyles.miniButtonRight,
GUILayout.ExpandWidth(false));
if (value && _selectedExportMode != ExportMode.Meshes)
{
_selectedExportMode = ExportMode.Meshes;
exportObjDefault = false;
_replaceMeshes = true;
exportPngDefault = true;
exportSprite = false;
exportSliceSprite = false;
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
private void DrawAdvancedEditor()
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
_showAdvancedEditor = EditorGUILayout.Foldout(_showAdvancedEditor, "Advanced editor");
if (!_showAdvancedEditor)
{
EditorGUILayout.EndVertical();
return;
}
GUILayout.Label("Meshes:", EditorStyles.miniBoldLabel);
EditorGUILayout.BeginHorizontal();
exportObjDefault = GUILayout.Toggle(exportObjDefault, "OBJ default.");
_replaceMeshes = GUILayout.Toggle(_replaceMeshes, "Replace meshes");
EditorGUILayout.EndHorizontal();
GUILayout.Label("Textures:", EditorStyles.miniBoldLabel);
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();
EditorGUILayout.EndVertical();
}
} }
} }
#endif #endif

View File

@ -9,6 +9,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEditor; using UnityEditor;
@ -39,12 +40,16 @@ namespace MA_Mesh
public static Mesh MA_DuplicateMesh(Mesh mesh) public static Mesh MA_DuplicateMesh(Mesh mesh)
{ {
Mesh newMesh = new Mesh(); Mesh newMesh = new Mesh();
newMesh.name = mesh.name;
newMesh.SetVertices(new List<Vector3>(mesh.vertices)); newMesh.SetVertices(new List<Vector3>(mesh.vertices));
newMesh.bounds = mesh.bounds;
newMesh.colors = mesh.colors.ToArray();
newMesh.subMeshCount = mesh.subMeshCount;
for (int i = 0; i < mesh.subMeshCount; i++) for (int i = 0; i < mesh.subMeshCount; i++)
{ {
newMesh.SetTriangles(mesh.GetTriangles(i), i); newMesh.SetTriangles(mesh.GetTriangles(i), i);
} }
newMesh.subMeshCount = mesh.subMeshCount;
newMesh.SetNormals(new List<Vector3>(mesh.normals)); newMesh.SetNormals(new List<Vector3>(mesh.normals));
newMesh.SetUVs(0, new List<Vector2>(mesh.uv)); newMesh.SetUVs(0, new List<Vector2>(mesh.uv));
newMesh.SetTangents(new List<Vector4>(mesh.tangents)); newMesh.SetTangents(new List<Vector4>(mesh.tangents));
@ -92,14 +97,14 @@ namespace MA_Mesh
{ {
if(flipY) if(flipY)
{ {
//Debug.Log("01" + uvs[i].x); uvs[i] = new Vector2((uvs[i].x / atlasSize.x * textureRect.width) + (1 / atlasSize.x * textureRect.x),
uvs[i] = new Vector2((uvs[i].x / atlasSize.x * textureRect.width) + (1 / atlasSize.x * textureRect.x), (uvs[i].y / atlasSize.y * textureRect.height) + (1 / atlasSize.y * (atlasSize.y - textureRect.height - textureRect.y))); (uvs[i].y / atlasSize.y * textureRect.height) + (1 / atlasSize.y * (atlasSize.y - textureRect.height - textureRect.y)));
//Debug.Log("02" + uvs[i].x);
} }
else else
{ {
//Debug.Log("01" + uvs[i].x); //Debug.Log("01" + uvs[i].x);
uvs[i] = new Vector2((uvs[i].x / atlasSize.x * textureRect.width) + (1 / atlasSize.x * textureRect.x), (uvs[i].y / atlasSize.y * textureRect.height) + (1 / atlasSize.y * textureRect.y)); uvs[i] = new Vector2((uvs[i].x / atlasSize.x * textureRect.width) + (1 / atlasSize.x * textureRect.x),
(uvs[i].y / atlasSize.y * textureRect.height) + (1 / atlasSize.y * textureRect.y));
//Debug.Log("02" + uvs[i].x); //Debug.Log("02" + uvs[i].x);
} }
} }
@ -176,7 +181,6 @@ namespace MA_Mesh
using (StreamWriter sw = new StreamWriter(savePath + filename + ".obj")) using (StreamWriter sw = new StreamWriter(savePath + filename + ".obj"))
{ {
sw.Write(MeshToString(mesh)); sw.Write(MeshToString(mesh));
Debug.Log(savePath + filename);
} }
} }
//End //End

View File

@ -44,6 +44,7 @@ namespace MA_Texture
// Copy the pixels from the RenderTexture to the new Texture // Copy the pixels from the RenderTexture to the new Texture
myTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0); myTexture2D.ReadPixels(new Rect(0, 0, tmp.width, tmp.height), 0, 0);
myTexture2D.Apply(); myTexture2D.Apply();
myTexture2D.name = texture.name;
// Reset the active RenderTexture // Reset the active RenderTexture
RenderTexture.active = previous; RenderTexture.active = previous;
@ -174,11 +175,18 @@ namespace MA_Texture
} }
} }
newTexture.name = texture.name; newTexture.name = texture.name;
newTexture.Apply(); newTexture.Apply();
return newTexture; return newTexture;
} }
public static Texture2D ScaleTexture(this Texture2D texture, int width, int height, bool bilinear)
{
TextureScaler.Scale(texture, width, height, bilinear);
return texture;
}
#endregion #endregion
#region combine #region combine
@ -191,7 +199,7 @@ namespace MA_Texture
//Y is 'flipped' because textures are made from left to right, bottom to top. We want to draw from left to right and top to bottom. //Y is 'flipped' because textures are made from left to right, bottom to top. We want to draw from left to right and top to bottom.
for (int y = combineTexture.height; y > 0; y--) for (int y = combineTexture.height; y > 0; y--)
{ {
texture.SetPixel(x + offsetX, texture.height - y - offsetY, combineTexture.GetPixel(x, texture.height - y)); texture.SetPixel(x + offsetX, y + (texture.height - offsetY - combineTexture.height), combineTexture.GetPixel(x, y));
} }
} }
else else

View File

@ -0,0 +1,103 @@
using System.Threading;
using UnityEngine;
namespace MA_Texture
{
public static class TextureScaler
{
public class ThreadData
{
public int start;
public int end;
public ThreadData (int s, int e) {
start = s;
end = e;
}
}
private static Color[] texColors;
private static Color[] newColors;
private static int w;
private static float ratioX;
private static float ratioY;
private static int w2;
private static int finishCount;
public static void Scale (Texture2D tex, int newWidth, int newHeight, bool useBilinear)
{
texColors = tex.GetPixels();
newColors = new Color[newWidth * newHeight];
if (useBilinear)
{
ratioX = 1.0f / ((float)newWidth / (tex.width-1));
ratioY = 1.0f / ((float)newHeight / (tex.height-1));
}
else {
ratioX = ((float)tex.width) / newWidth;
ratioY = ((float)tex.height) / newHeight;
}
w = tex.width;
w2 = newWidth;
finishCount = 0;
if (useBilinear)
{
BilinearScale(0, newHeight);
}
else
{
PointScale(0, newHeight);
}
tex.Resize(newWidth, newHeight);
tex.SetPixels(newColors);
tex.Apply();
texColors = null;
newColors = null;
}
public static void BilinearScale (int start, int end)
{
for (var y = start; y < end; y++)
{
int yFloor = (int)Mathf.Floor(y * ratioY);
var y1 = yFloor * w;
var y2 = (yFloor+1) * w;
var yw = y * w2;
for (var x = 0; x < w2; x++) {
int xFloor = (int)Mathf.Floor(x * ratioX);
var xLerp = x * ratioX-xFloor;
newColors[yw + x] = ColorLerpUnclamped(ColorLerpUnclamped(texColors[y1 + xFloor], texColors[y1 + xFloor+1], xLerp),
ColorLerpUnclamped(texColors[y2 + xFloor], texColors[y2 + xFloor+1], xLerp),
y*ratioY-yFloor);
}
}
finishCount++;
}
public static void PointScale (int start, int end)
{
for (var y = start; y < end; y++)
{
var thisY = (int)(ratioY * y) * w;
var yw = y * w2;
for (var x = 0; x < w2; x++) {
newColors[yw + x] = texColors[(int)(thisY + ratioX*x)];
}
}
finishCount++;
}
private static Color ColorLerpUnclamped (Color c1, Color c2, float value)
{
return new Color (c1.r + (c2.r - c1.r)*value,
c1.g + (c2.g - c1.g)*value,
c1.b + (c2.b - c1.b)*value,
c1.a + (c2.a - c1.a)*value);
}
}
}