Compare commits

...

14 Commits

Author SHA1 Message Date
max
b2a005356d Update MA_TextureAtlasserProInspectorView.cs 2022-11-09 20:51:48 +01:00
max
05b4ea9f80 Update MA_TextureAtlasserProInspectorView.cs
Fix 2020.2+ mesh input fields.
2021-04-08 23:51:05 +02:00
max
0933abdace Update MA_TextureAtlasserProInspectorView.cs 2021-04-03 17:09:27 +02:00
max
5d112a2ced Update MA_TextureAtlasserProInspectorView.cs
Dirty fix for 2020.2+ versions with reordable list.
2021-04-02 17:31:24 +02:00
max
650600fac3 Delete launch.json 2021-03-26 11:42:54 +01:00
max
b2ccdb2273 Copy over all UV channels.
The duplicate function now copies all 8 UV channels. So your lightmap UV's don't get lost!
2021-03-26 11:41:19 +01:00
max
df16ba6c05 Merge branch 'master' of https://github.com/maxartz15/MA_TextureAtlasser 2020-05-16 19:29:09 +02:00
max
a3c002cb17 Update MA_TextureUtils.cs
Bugfix: 2 pixel Y offset when combining textures.
2020-05-16 19:29:01 +02:00
max
0907259aa8
Update README.md 2020-04-21 02:28:41 +02:00
max
fa40b918d0
Update README.md 2020-04-20 22:43:13 +02:00
max
8ff2db7e87 Model groups.
Added model group support, you can now have multiple meshes in one export.
Removed OBJ and mesh replace export options.
Mesh replace didn't work, might get added again in the feature.
OBJ needs to be rewritten as well to support the multiple meshes, and Unity now has model export options in engine.
Version 1.8.0+ is now only supports Unity2018.3+.
2020-04-20 22:30:08 +02:00
max
3532465e69 Button labels, tooltips, icons.
First iteration, buttons now have optional tooltips and labels. By default the editor will load with them on, this can be changed in the settings.
2020-04-18 22:55:52 +02:00
max
6c2daebb56
Update README.md 2020-04-13 18:11:59 +02:00
max
696ef848e0 Bugfixes: Texture point scale.
Bugfixes: Texture point scale.
Test Unity2019.3.
2020-04-13 18:03:44 +02:00
30 changed files with 770 additions and 583 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 34f8bb860cb13ac49ab6602f84a27dfd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace MA_TextureAtlasserPro
{
[CustomEditor(typeof(MA_TextureAtlasserProSettings))]
[CanEditMultipleObjects]
public class MA_TextureAtlasserProSettingsEditor : Editor
{
GUIContent reloadButton = new GUIContent("Reload", "Update the editor with the changes made.");
public override void OnInspectorGUI()
{
GUILayout.BeginVertical();
DrawDefaultInspector();
GUILayout.Space(15);
if(GUILayout.Button(reloadButton, GUILayout.Height(40), GUILayout.ExpandWidth(true)))
{
//Update necessary systems.
MA_TextureAtlasserProGuiLoader.LoadEditorGui((MA_TextureAtlasserProSettings)this.target);
}
GUILayout.EndVertical();
}
}
}
#endif

View File

@ -1,8 +1,7 @@
fileFormatVersion: 2
guid: 64b4bb2ec0d18b142b6a5aa0c8dfb5c1
timeCreated: 1521838249
licenseType: Free
guid: 9850f2b069cfb36498e9601e4884071a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0

View File

@ -0,0 +1,15 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MA_TextureAtlasserPro
{
[System.Serializable]
public class MA_ModelGroup
{
public string name = "Model";
public List<Mesh> meshes = new List<Mesh>();
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f74ddc7d8c9c30429ec163b4fc801c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -15,7 +15,7 @@ namespace MA_TextureAtlasserPro
public List<MA_TextureAtlasserProQuad> textureQuads;
public MA_TextureAtlasserProQuad selectedTextureQuad;
private Rect editorWorkRect;
public bool showTextures = false;
public bool showTextures = true;
public MA_TextureAtlasserProExportSettings exportSettings;
//Data

View File

@ -50,9 +50,7 @@ namespace MA_TextureAtlasserPro
public enum ModelFormat
{
None,
UnityMeshPrefab,
ReplaceMesh,
Obj
UnityMeshPrefab
}
public enum TextureFormat

View File

@ -11,22 +11,28 @@ namespace MA_TextureAtlasserPro
public class MA_TextureAtlasserProQuad : ScriptableObject
{
//Editor
public bool isSelected = false; //Is this thing selected
public Rect rect; //The internal rect
public Rect guiRect; //The visual clamped and snapped rect
public bool debugMode = false; //Are we debugging, for showing some other things (like handles)
[HideInInspector]
public bool isSelected = false; //Is this thing selected
public Rect rect; //The internal rect
[HideInInspector]
public Rect guiRect; //The visual clamped and snapped rect
[HideInInspector]
public bool debugMode = false; //Are we debugging, for showing some other things (like handles)
private bool isDragging = false; //Are we editing the pos or size
private bool isDragging = false; //Are we editing the pos or size
private bool isDraggingRectHeigt = false;
[HideInInspector]
public Rect dragRectHeight;
private bool isDraggingRectWidth = false;
[HideInInspector]
public Rect dragRectWidth;
private bool isDraggingRectPos = false;
[HideInInspector]
public Rect dragRectPos;
//Data
public List<MA_TextureGroup> textureGroups;
public List<Mesh> meshes;
public List<MA_ModelGroup> modelGroups;
public void UpdateTextureQuad(Event e, Rect editorViewRect, Rect editorWorkRect, Vector2 zoomCoordsOrigin, bool useEvents, bool showTexture)
{

View File

@ -10,7 +10,10 @@ namespace MA_TextureAtlasserPro
[System.Serializable]
public class MA_TextureAtlasserProSettings : ScriptableObject
{
[Header("Hotkeys:")]
[Header("GUI (requires reload):")]
public MA_TextureAtlasserProGuiSettings editorGuiSettings = new MA_TextureAtlasserProGuiSettings();
[Header("HotKeys:")]
public bool useHotkeys = false;
public EventModifiers modifierKey = EventModifiers.Alt;
public KeyCode addQuadHotKey = KeyCode.Q;
@ -20,7 +23,6 @@ namespace MA_TextureAtlasserPro
public KeyCode zoomOutHotKey = KeyCode.Minus;
[Header("Duplication:")]
public bool copySelectedQuadData = true;
public string duplicatedQuadNamePrefix = "new ";
[Header("Selection")]
@ -36,5 +38,19 @@ namespace MA_TextureAtlasserPro
return false;
}
}
[System.Serializable]
public class MA_TextureAtlasserProGuiSettings
{
public MA_EditorGuiMode editorGuiMode = MA_EditorGuiMode.IconAndText;
public bool enableToolTips = true;
}
public enum MA_EditorGuiMode
{
IconAndText = 0,
Icon = 1,
Text = 2
}
}
#endif

View File

@ -0,0 +1,115 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
namespace MA_TextureAtlasserPro
{
public static class MA_TextureAtlasserProGuiLoader
{
private const string LOADICONPATH = "Assets/MA_ToolBox/MA_TextureAtlasserPro/Icons/";
public static GUIContent createAtlasGC;
public static GUIContent loadAtlasGC;
public static GUIContent exportAtlasGC;
public static GUIContent createQuadGC;
public static GUIContent removeQuadGC;
public static GUIContent duplicateQuadGC;
public static GUIContent showTexturesOnGC;
public static GUIContent showTexturesOffGC;
public static GUIContent dragHandleGC;
public static GUIContent editGC;
public static GUIContent createExportSettingsGC;
public static void LoadEditorGui(MA_TextureAtlasserProSettings settings)
{
createAtlasGC = new GUIContent();
loadAtlasGC = new GUIContent();
exportAtlasGC = new GUIContent();
createQuadGC = new GUIContent();
removeQuadGC = new GUIContent();
duplicateQuadGC = new GUIContent();
showTexturesOnGC = new GUIContent();
showTexturesOffGC = new GUIContent();
dragHandleGC = new GUIContent();
editGC = new GUIContent();
createExportSettingsGC = new GUIContent();
switch (settings.editorGuiSettings.editorGuiMode)
{
case MA_EditorGuiMode.IconAndText:
LoadIcons();
LoadText();
break;
case MA_EditorGuiMode.Icon:
LoadIcons();
break;
case MA_EditorGuiMode.Text:
LoadText();
break;
default:
LoadIcons();
break;
}
if(settings.editorGuiSettings.enableToolTips)
{
LoadToolTips(settings);
}
//Exceptions.
dragHandleGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "dragHandleIcon" + ".png");
dragHandleGC.text = "";
editGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "editIcon" + ".png");
editGC.text = "";
}
private static void LoadIcons()
{
createAtlasGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "createAtlasIcon" + ".png");
loadAtlasGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "loadAtlasIcon" + ".png");
exportAtlasGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "exportAtlasIcon" + ".png");
createQuadGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "createQuadIcon" + ".png");
removeQuadGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "removeQuadIcon" + ".png");
duplicateQuadGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "duplicateQuadIcon" + ".png");
showTexturesOnGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "showTexturesOnIcon" + ".png");
showTexturesOffGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "showTexturesOffIcon" + ".png");
createExportSettingsGC.image = (Texture)EditorGUIUtility.Load(LOADICONPATH + "createAtlasIcon" + ".png");
}
private static void LoadText()
{
createAtlasGC.text = "Create Atlas";
loadAtlasGC.text = "Load Atlas";
exportAtlasGC.text = "Export Atlas";
createQuadGC.text = "Create Quad";
removeQuadGC.text = "Remove Quad";
duplicateQuadGC.text = "Duplicate Quad";
showTexturesOnGC.text = "Hide Textures";
showTexturesOffGC.text = "Show Textures";
createExportSettingsGC.text = "Create Export Settings";
}
private static void LoadToolTips(MA_TextureAtlasserProSettings settings)
{
createAtlasGC.tooltip = "Opens the create atlas window.";
loadAtlasGC.tooltip = "Load an existing atlas.";
exportAtlasGC.tooltip = "Opens the export window.";
if (settings.useHotkeys)
{
createQuadGC.tooltip = string.Format("({0}+{1}), Creates a new quad.", settings.modifierKey, settings.addQuadHotKey);
removeQuadGC.tooltip = string.Format("({0}+{1}), Removes the selected quad.", settings.modifierKey, settings.removeQuadHotKey);
duplicateQuadGC.tooltip = string.Format("({0}+{1}), Duplicates the selected quad.", settings.modifierKey, settings.duplicateHotKey);
}
else
{
createQuadGC.tooltip = "Creates a new quad.";
removeQuadGC.tooltip = "Removes the selected quad.";
duplicateQuadGC.tooltip = "Duplicates the selected quad.";
}
showTexturesOnGC.tooltip = "Hides the preview of the first texture on the quads.";
showTexturesOffGC.tooltip = "Shows a preview of the first texture on the quads.";
createExportSettingsGC.tooltip = "Opens the create export settings window.";
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1547329de58c58d4eb6b272309da0c85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,37 +0,0 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
namespace MA_TextureAtlasserPro
{
public static class MA_TextureAtlasserProIcons
{
private const string LOADICONPATH = "Assets/MA_ToolBox/MA_TextureAtlasserPro/Icons/";
public static GUIContent createAtlasIcon;
public static GUIContent loadAtlasIcon;
public static GUIContent exportAtlasIcon;
public static GUIContent createQuadIcon;
public static GUIContent removeQuadIcon;
public static GUIContent duplicateQuadIcon;
public static GUIContent showTexturesOnIcon;
public static GUIContent showTexturesOffIcon;
public static GUIContent dragHandleIcon;
public static GUIContent editIcon;
public static void LoadIcons()
{
createAtlasIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "createAtlasIcon" + ".png"));
loadAtlasIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "loadAtlasIcon" + ".png"));
exportAtlasIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "exportAtlasIcon" + ".png"));
createQuadIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "createQuadIcon" + ".png"));
removeQuadIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "removeQuadIcon" + ".png"));
duplicateQuadIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "duplicateQuadIcon" + ".png"));
showTexturesOnIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "showTexturesOnIcon" + ".png"));
showTexturesOffIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "showTexturesOffIcon" + ".png"));
dragHandleIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "dragHandleIcon" + ".png"));
editIcon = new GUIContent("", (Texture)EditorGUIUtility.Load(LOADICONPATH + "editIcon" + ".png"));
}
}
}
#endif

View File

@ -5,6 +5,8 @@ using UnityEngine;
using UnityEditor;
using MA_Mesh;
using MA_Texture;
using MA_Toolbox.Utils.Editor;
using MA_Toolbox.Utils;
namespace MA_TextureAtlasserPro
{
@ -259,25 +261,16 @@ namespace MA_TextureAtlasserPro
}
}
public static void DuplicateTextureQuad(MA_TextureAtlasserProAtlas atlas, bool focus = true, bool copyData = false, string namePrefix = "new ")
public static void DuplicateTextureQuad(MA_TextureAtlasserProAtlas atlas, bool focus = true, string namePrefix = "new ")
{
if (atlas != null && atlas.selectedTextureQuad != null)
{
MA_TextureAtlasserProQuad q = CreateTextureQuad(atlas, namePrefix + atlas.selectedTextureQuad.name, atlas.selectedTextureQuad.rect, false);
//MA_TextureAtlasserProQuad q = CreateTextureQuad(atlas, namePrefix + atlas.selectedTextureQuad.name, atlas.selectedTextureQuad.rect, false);
MA_TextureAtlasserProQuad q = Object.Instantiate(atlas.selectedTextureQuad);
q.name = string.Format("{0}{1}", namePrefix, atlas.selectedTextureQuad.name);
atlas.textureQuads.Add(q);
if (copyData)
{
q.meshes = new List<Mesh>();
for (int i = 0; i < atlas.selectedTextureQuad.meshes.Count; i++)
{
q.meshes.Add(atlas.selectedTextureQuad.meshes[i]);
}
for (int i = 0; i < atlas.selectedTextureQuad.textureGroups.Count; i++)
{
q.textureGroups[i].texture = atlas.selectedTextureQuad.textureGroups[i].texture;
}
}
AssetDatabase.AddObjectToAsset(q, atlas);
if (focus)
{
@ -365,6 +358,12 @@ namespace MA_TextureAtlasserPro
if (!AssetDatabase.IsValidFolder(folderPath))
{
string parentPath = folderPath.Substring(0, folderPath.LastIndexOf('/'));
if(!AssetDatabase.IsValidFolder(parentPath))
{
CreateFolder(parentPath);
}
string folderName = folderPath.Substring(folderPath.LastIndexOf('/') + 1);
AssetDatabase.CreateFolder(parentPath, folderName);
@ -387,19 +386,16 @@ namespace MA_TextureAtlasserPro
}
#region Export
public static string[] ExportAtlasModels(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string material = null, string savePath = EXPORT_ASSET_PATH)
public static string[] ExportAtlasModels(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string materialPath = null, string savePath = EXPORT_ASSET_PATH)
{
switch (modelExportSettings.modelFormat)
{
case ModelFormat.None:
break;
case ModelFormat.ReplaceMesh:
ReplaceAtlasMesh(atlas, modelExportSettings, savePath: savePath);
break;
case ModelFormat.UnityMeshPrefab:
return ExportAtlasUnityMeshPrefab(atlas, modelExportSettings, material: material, savePath: savePath);
case ModelFormat.Obj:
return ExportAtlasObj(atlas, modelExportSettings, savePath: savePath);
return ExportAtlasUnityMeshPrefab(atlas, modelExportSettings, materialPath: materialPath, savePath: savePath);
//case ModelFormat.Obj:
// return ExportAtlasObj(atlas, modelExportSettings, savePath: savePath);
default:
break;
}
@ -407,103 +403,78 @@ namespace MA_TextureAtlasserPro
return null;
}
private static void ReplaceAtlasMesh(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string savePath = EXPORT_ASSET_PATH)
private static string[] ExportAtlasUnityMeshPrefab(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string materialPath = null, string savePath = EXPORT_ASSET_PATH)
{
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, modelExportSettings.uvChannel, modelExportSettings.uvFlipY, modelExportSettings.uvWrap);
EditorUtility.SetDirty(meshes[meshIndex]);
}
}
AssetDatabase.SaveAssets();
}
private static string[] ExportAtlasUnityMeshPrefab(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string material = null, string savePath = EXPORT_ASSET_PATH)
{
if (atlas == null || atlas.textureQuads == null)
return null;
}
List<string> assetPaths = new List<string>();
foreach (MA_TextureAtlasserProQuad quad in atlas.textureQuads)
{
//Export Mesh
if (quad.meshes != null)
{
for (int m = 0; m < quad.meshes.Count; m++)
{
if (quad.meshes[m] != null)
{
//Create new mesh
Mesh newMesh = new Mesh();
//Duplicate it from the current one
newMesh = MA_MeshUtils.MA_DuplicateMesh(quad.meshes[m]);
//Remap UV's
newMesh = MA_MeshUtils.MA_UVReMap(newMesh, atlas.textureAtlasSize, quad.guiRect, modelExportSettings.uvChannel, modelExportSettings.uvFlipY, modelExportSettings.uvWrap);
//Set name
string meshName = string.IsNullOrEmpty(quad.name) ? "" : quad.name + "-";
meshName += quad.meshes[m].name;
int n = m + 1;
meshName += "_" + n.ToString("#000");
newMesh.name = meshName;
//Save it
string asset = MA_MeshUtils.MA_SaveMeshPrefab(newMesh, meshName, savePath, materialPath: material);
assetPaths.Add(asset);
}
}
}
}
return assetPaths.ToArray();
}
private static string[] ExportAtlasObj(MA_TextureAtlasserProAtlas atlas, ModelExportSettings modelExportSettings, string savePath = EXPORT_ASSET_PATH)
{
if (atlas == null || atlas.textureQuads == null)
return null;
List<string> assetPaths = new List<string>();
//Directories.
string savePathPrefab = savePath + atlas.name + "/";
string savePathMeshes = savePathPrefab + "Meshes/";
CreateFolder(savePathPrefab);
CreateFolder(savePathMeshes);
foreach (MA_TextureAtlasserProQuad quad in atlas.textureQuads)
{
//Export Mesh
if (quad.meshes != null)
foreach (MA_ModelGroup mg in quad.modelGroups)
{
for (int m = 0; m < quad.meshes.Count; m++)
//Validate name.
if (string.IsNullOrEmpty(mg.name) || string.IsNullOrWhiteSpace(mg.name))
{
if (quad.meshes[m] != null)
{
//Create new mesh
Mesh newMesh = new Mesh();
//Duplicate it from the current one
newMesh = MA_MeshUtils.MA_DuplicateMesh(quad.meshes[m]);
//Remap UV's
newMesh = MA_MeshUtils.MA_UVReMap(newMesh, atlas.textureAtlasSize, quad.guiRect, modelExportSettings.uvChannel, modelExportSettings.uvFlipY, modelExportSettings.uvWrap);
//Save it
string meshName = string.IsNullOrEmpty(quad.name) ? "" : quad.name + "-";
meshName += quad.meshes[m].name;
int n = m + 1;
meshName += "_" + n.ToString("#000");
mg.name = MA_StringUtils.RandomAlphabetString(6);
Debug.LogWarning("No valid model name assigned!");
}
string asset = MA_MeshUtils.MeshToFile(newMesh, meshName, savePath);
assetPaths.Add(asset);
//Create new prefab asset.
string newPrefabPath = MA_PrefabUtils.CreatePrefab(mg.name, savePathPrefab);
GameObject newPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(newPrefabPath);
foreach (Mesh m in mg.meshes)
{
if(m != null)
{
//Validate name.
if (string.IsNullOrEmpty(m.name) || string.IsNullOrWhiteSpace(m.name))
{
m.name = MA_StringUtils.RandomAlphabetString(6);
Debug.LogWarning("No valid mesh name assigned!");
}
//Create new mesh.
//Duplicate it from the current one.
Mesh newMesh = MA_MeshUtils.MA_DuplicateMesh(m);
//Remap UV's.
newMesh = MA_MeshUtils.MA_UVReMap(newMesh, atlas.textureAtlasSize, quad.guiRect, modelExportSettings.uvChannel, modelExportSettings.uvFlipY, modelExportSettings.uvWrap);
//Set name.
newMesh.name = string.Format("{0}_{1}", mg.name, m.name);
//Save mesh.
string savedMeshPath = MA_MeshUtils.MA_SaveMeshAsset(newMesh, savePathMeshes);
//Load mesh.
Mesh savedMesh = AssetDatabase.LoadAssetAtPath<Mesh>(savedMeshPath);
//Load material.
Material savedMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
//Create gameObject.
GameObject newGameObject = new GameObject(m.name);
//Add mesh filter.
MeshFilter mf = newGameObject.AddComponent<MeshFilter>();
mf.mesh = savedMesh;
//Add mesh renderer.
MeshRenderer mr = newGameObject.AddComponent<MeshRenderer>();
mr.material = savedMaterial;
//Add to parent gameObject (prefab).
MA_PrefabUtils.AddChild(newPrefab, newGameObject);
Object.DestroyImmediate(newGameObject);
}
}
assetPaths.Add(newPrefabPath);
}
}
@ -528,10 +499,16 @@ namespace MA_TextureAtlasserPro
private static string[] ExportAtlasPNG(MA_TextureAtlasserProAtlas atlas, TextureExportSettings textureExportSettings, string savePath = EXPORT_ASSET_PATH, string tempPath = TEMP_ASSET_PATH)
{
if (atlas == null || atlas.textureQuads == null || atlas.textureGroupRegistration == null)
{
return null;
}
string[] assetPaths = new string[atlas.textureGroupRegistration.Count];
//Directories.
string savePathTextures = savePath + atlas.name + "/Textures/";
CreateFolder(savePathTextures);
//Create temp folder
CreateFolder(tempPath);
@ -582,25 +559,24 @@ namespace MA_TextureAtlasserPro
}
//Save it
newTexture.MA_Save2D(newTexture.name, savePath);
assetPaths[i] = (savePath + newTexture.name + '.' + textureExportSettings.textureFormat.ToString());
newTexture.MA_Save2D(newTexture.name, savePathTextures);
assetPaths[i] = (savePathTextures + newTexture.name + '.' + textureExportSettings.textureFormat.ToString());
//Set settings.
switch (textureExportSettings.textureType)
{
case TextureType.Default:
{
TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(savePath + newTexture.name + '.' + textureExportSettings.textureFormat.ToString());
TextureImporter textureImporter = (TextureImporter)AssetImporter.GetAtPath(savePathTextures + newTexture.name + '.' + textureExportSettings.textureFormat.ToString());
textureImporter.textureType = TextureImporterType.Default;
textureImporter.SaveAndReimport();
}
break;
case TextureType.Sprite:
SetAtlasSpriteSettings(atlas, textureExportSettings, savePath);
SetAtlasSpriteSettings(atlas, textureExportSettings, savePathTextures);
break;
case TextureType.SpriteSliced:
SetAtlasSpriteSettings(atlas, textureExportSettings, savePath);
SetAtlasSpriteSettings(atlas, textureExportSettings, savePathTextures);
break;
default:
break;
@ -616,7 +592,7 @@ namespace MA_TextureAtlasserPro
return assetPaths;
}
private static void SetAtlasSpriteSettings(MA_TextureAtlasserProAtlas atlas, TextureExportSettings textureExportSettings, string savePath = EXPORT_ASSET_PATH)
private static void SetAtlasSpriteSettings(MA_TextureAtlasserProAtlas atlas, TextureExportSettings textureExportSettings, string savePath)
{
//Foreach texture group
for (int i = 0; i < atlas.textureGroupRegistration.Count; i++)
@ -663,9 +639,13 @@ namespace MA_TextureAtlasserPro
public static string ExportAtlasMaterial(MA_TextureAtlasserProAtlas atlas, MaterialExportSettings materialExportSettings, string[] textures = null, string savePath = EXPORT_ASSET_PATH)
{
if (atlas == null || atlas.textureQuads == null || atlas.textureGroupRegistration == null)
{
return null;
}
string assetPath = "";
//Directories.
string savePathMaterial = savePath + atlas.name + "/Materials/";
CreateFolder(savePathMaterial);
Shader shader = materialExportSettings.shader;
if (shader)
@ -687,14 +667,16 @@ namespace MA_TextureAtlasserPro
}
}
assetPath = savePath + material.name + ".mat";
string assetPath = savePathMaterial + material.name + ".mat";
//Save material
AssetDatabase.CreateAsset(material, assetPath);
AssetDatabase.Refresh();
return assetPath;
}
return assetPath;
return null;
}
#endregion
}

View File

@ -4,161 +4,186 @@ using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using MA_Editor;
using MA_Toolbox.Utils;
namespace MA_TextureAtlasserPro
{
public class MA_TextureAtlasserProInspectorView : MA_TextureAtlasserProViewBase
{
private MA_TextureAtlasserProQuad lastSelectedQuad;
public class MA_TextureAtlasserProInspectorView : MA_TextureAtlasserProViewBase
{
private MA_TextureAtlasserProQuad lastSelectedQuad;
private bool isEditing = false;
private GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
bool useAddMeshButton = false;
private GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
private Vector2 scrollPos = Vector2.zero;
public MA_TextureAtlasserProInspectorView(MA_TextureAtlasserProWindow currentEditorWindow, string title) : base(currentEditorWindow, title)
{
}
{
public override void UpdateView(Event e, Rect editorViewRect)
{
//Update base derived class
base.UpdateView(e, editorViewRect);
}
if(isLoaded)
{
//Draw inspector
if(curWindow.textureAtlas != null && curWindow.textureAtlas.selectedTextureQuad != null)
{
//Change layout during layout event to prevent gui errors
if (e.type == EventType.Layout)
public override void UpdateView(Event e, Rect editorViewRect)
{
//Update base derived class
base.UpdateView(e, editorViewRect);
if (isLoaded)
{
//Draw inspector
if (curWindow.textureAtlas != null && curWindow.textureAtlas.selectedTextureQuad != null)
{
//Deselect GUI elements when we are focusing on a new quad
if (lastSelectedQuad != curWindow.textureAtlas.selectedTextureQuad)
{
if (curWindow.textureAtlas.selectedTextureQuad.meshes != null && curWindow.textureAtlas.selectedTextureQuad.meshes.Count == 0)
lastSelectedQuad = curWindow.textureAtlas.selectedTextureQuad;
GUI.FocusControl(null);
}
GUILayout.BeginArea(editorViewRect, EditorStyles.helpBox);
using (var scrollViewScope = new EditorGUILayout.ScrollViewScope(scrollPos, false, false))
{
scrollPos = scrollViewScope.scrollPosition;
GUILayout.BeginVertical(GUILayout.ExpandWidth(true));
GUILayout.Label("Quad Name");
curWindow.textureAtlas.selectedTextureQuad.name = EditorGUILayout.TextField(curWindow.textureAtlas.selectedTextureQuad.name);
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET / 2);
//Textures
GUILayout.BeginHorizontal();
GUILayout.Label("Textures", GUILayout.ExpandWidth(true));
if (GUILayout.Button(MA_TextureAtlasserProGuiLoader.editGC, EditorStyles.miniButton, GUILayout.Width(36), GUILayout.Height(15)))
{
useAddMeshButton = true;
isEditing = !isEditing;
}
GUILayout.EndHorizontal();
if (curWindow.textureAtlas.textureGroupRegistration == null || curWindow.textureAtlas.textureGroupRegistration.Count == 0)
{
if (GUILayout.Button("+", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
{
MA_TextureAtlasserProUtils.CreateTextureGroup(curWindow.textureAtlas, "New TextureGroup");
}
}
for (int i = 0; i < curWindow.textureAtlas.textureGroupRegistration.Count; i++)
{
if (isEditing)
{
curWindow.textureAtlas.textureGroupRegistration[i].name = curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].name = EditorGUILayout.TextField(curWindow.textureAtlas.textureGroupRegistration[i].name);
}
else
{
GUILayout.Label(curWindow.textureAtlas.textureGroupRegistration[i].name);
}
GUILayout.BeginHorizontal();
curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].texture = (Texture)EditorGUILayout.ObjectField(curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].texture, typeof(Texture), false);
if (isEditing && GUILayout.Button("-", EditorStyles.miniButtonLeft, GUILayout.ExpandWidth(false)))
{
MA_TextureAtlasserProUtils.RemoveTextureGroup(curWindow.textureAtlas, i);
}
if (isEditing && GUILayout.Button("+", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
{
MA_TextureAtlasserProUtils.CreateTextureGroup(curWindow.textureAtlas, "New TextureGroup");
}
GUILayout.EndHorizontal();
}
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET / 2);
//Models
GUILayout.Label("Models");
SerializedObject serializedObject = new SerializedObject(curWindow.textureAtlas.selectedTextureQuad);
serializedObject.Update();
if (curWindow.textureAtlas.selectedTextureQuad.modelGroups != null)
{
SerializedProperty modelGroupsSP = serializedObject.FindProperty("modelGroups");
for (int i = 0; i < curWindow.textureAtlas.selectedTextureQuad.modelGroups.Count; i++)
{
using (new GUILayout.VerticalScope(EditorStyles.helpBox))
{
using (new GUILayout.HorizontalScope())
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].name = EditorGUILayout.TextField(curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].name);
if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups.RemoveAt(i);
break;
}
}
SerializedProperty meshesSP = modelGroupsSP.GetArrayElementAtIndex(i).FindPropertyRelative("meshes");
#if UNITY_2020_2_OR_NEWER
meshesSP.isExpanded = EditorGUILayout.Foldout(meshesSP.isExpanded, "Meshes", true);
#else
EditorGUILayout.PropertyField(meshesSP, false, GUILayout.ExpandWidth(false), GUILayout.MaxWidth(editorViewRect.width * 0.5f));
#endif
if (meshesSP.isExpanded)
{
for (int j = 0; j < curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].meshes.Count; j++)
{
using (new GUILayout.HorizontalScope())
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].meshes[j] = (Mesh)EditorGUILayout.ObjectField(curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].meshes[j], typeof(Mesh), false);
if (GUILayout.Button("-", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].meshes.RemoveAt(j);
break;
}
}
}
}
if (GUILayout.Button("+", EditorStyles.miniButton))
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups[i].meshes.Add(null);
}
}
}
if (GUILayout.Button("+", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
{
curWindow.textureAtlas.selectedTextureQuad.modelGroups.Add(new MA_ModelGroup() { name = MA_StringUtils.RandomAlphabetString(6) });
}
}
else
{
useAddMeshButton = false;
curWindow.textureAtlas.selectedTextureQuad.modelGroups = new List<MA_ModelGroup>();
}
}
//Deselect GUI elements when we are focusing on a new quad
if (lastSelectedQuad != curWindow.textureAtlas.selectedTextureQuad)
{
lastSelectedQuad = curWindow.textureAtlas.selectedTextureQuad;
GUI.FocusControl(null);
}
serializedObject.ApplyModifiedProperties();
GUILayout.BeginArea(editorViewRect, EditorStyles.helpBox);
GUILayout.BeginVertical(GUILayout.ExpandWidth(true));
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET / 2);
GUILayout.Label("Quad Name");
curWindow.textureAtlas.selectedTextureQuad.name = EditorGUILayout.TextField(curWindow.textureAtlas.selectedTextureQuad.name);
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET / 2);
//Textures
GUILayout.BeginHorizontal();
GUILayout.Label("Textures", GUILayout.ExpandWidth(true));
if(GUILayout.Button(MA_TextureAtlasserProIcons.editIcon, EditorStyles.miniButton, GUILayout.Width(36), GUILayout.Height(15)))
{
isEditing = !isEditing;
}
GUILayout.EndHorizontal();
if(curWindow.textureAtlas.textureGroupRegistration == null || curWindow.textureAtlas.textureGroupRegistration.Count == 0)
{
if(GUILayout.Button("+", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
{
MA_TextureAtlasserProUtils.CreateTextureGroup(curWindow.textureAtlas, "New TextureGroup");
}
}
for (int i = 0; i < curWindow.textureAtlas.textureGroupRegistration.Count; i++)
{
if(isEditing)
{
curWindow.textureAtlas.textureGroupRegistration[i].name = curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].name = EditorGUILayout.TextField(curWindow.textureAtlas.textureGroupRegistration[i].name);
}
else
{
GUILayout.Label(curWindow.textureAtlas.textureGroupRegistration[i].name);
}
GUILayout.BeginHorizontal();
curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].texture = (Texture)EditorGUILayout.ObjectField(curWindow.textureAtlas.selectedTextureQuad.textureGroups[i].texture, typeof(Texture), false);
if(isEditing && GUILayout.Button("-", EditorStyles.miniButtonLeft, GUILayout.ExpandWidth(false)))
{
MA_TextureAtlasserProUtils.RemoveTextureGroup(curWindow.textureAtlas, i);
}
if(isEditing && GUILayout.Button("+", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
{
MA_TextureAtlasserProUtils.CreateTextureGroup(curWindow.textureAtlas, "New TextureGroup");
}
GUILayout.EndHorizontal();
}
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET / 2);
//Meshes
GUILayout.Label("Meshes");
if (useAddMeshButton)
{
if (GUILayout.Button("+", EditorStyles.miniButton, GUILayout.ExpandWidth(true)))
//x, y, w, h.
GUILayout.FlexibleSpace();
if (!MA_TextureAtlasserProUtils.IsPowerOfTwo((int)curWindow.textureAtlas.selectedTextureQuad.guiRect.width) || !MA_TextureAtlasserProUtils.IsPowerOfTwo((int)curWindow.textureAtlas.selectedTextureQuad.guiRect.height))
{
curWindow.textureAtlas.selectedTextureQuad.meshes.Add(null);
labelStyle.normal.textColor = Color.red;
}
else
{
labelStyle.normal.textColor = GUI.skin.label.normal.textColor;
}
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(), labelStyle);
}
if (curWindow.textureAtlas.selectedTextureQuad.meshes != null)
{
for (int i = 0; i < curWindow.textureAtlas.selectedTextureQuad.meshes.Count; i++)
{
GUILayout.BeginHorizontal();
curWindow.textureAtlas.selectedTextureQuad.meshes[i] = (Mesh)EditorGUILayout.ObjectField(curWindow.textureAtlas.selectedTextureQuad.meshes[i], typeof(Mesh), false);
if(GUILayout.Button("-", EditorStyles.miniButtonLeft, GUILayout.ExpandWidth(false)))
{
curWindow.textureAtlas.selectedTextureQuad.meshes.RemoveAt(i);
}
if(GUILayout.Button("+", EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)))
{
curWindow.textureAtlas.selectedTextureQuad.meshes.Insert(i + 1, null);
}
GUILayout.EndHorizontal();
}
}
else
{
curWindow.textureAtlas.selectedTextureQuad.meshes = new List<Mesh>();
}
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(), labelStyle);
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
GUILayout.EndArea();
}
}
if(curWindow.textureAtlas != null && curWindow.textureAtlas.selectedTextureQuad != null)
ProcessEvents(e, editorViewRect);
}
if (curWindow.textureAtlas != null && curWindow.textureAtlas.selectedTextureQuad != null)
ProcessEvents(e, editorViewRect);
}
protected override void ProcessEvents(Event e, Rect editorViewRect)
{
base.ProcessEvents(e, editorViewRect);
}
}
protected override void ProcessEvents(Event e, Rect editorViewRect)
{
base.ProcessEvents(e, editorViewRect);
}
}
}
#endif

View File

@ -25,45 +25,45 @@ namespace MA_TextureAtlasserPro
GUILayout.BeginArea(editorViewRect, EditorStyles.helpBox);
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
if(GUILayout.Button(MA_TextureAtlasserProIcons.createAtlasIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(GUILayout.Button(MA_TextureAtlasserProGuiLoader.createAtlasGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
MA_TextureAtlasserProCreateWindow.InitEditorWindow(curWindow);
}
if(GUILayout.Button(MA_TextureAtlasserProIcons.loadAtlasIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(GUILayout.Button(MA_TextureAtlasserProGuiLoader.loadAtlasGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
curWindow.textureAtlas = MA_TextureAtlasserProUtils.LoadTextureAtlas();
}
if(curWindow.textureAtlas != null)
{
if(GUILayout.Button(MA_TextureAtlasserProIcons.exportAtlasIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(GUILayout.Button(MA_TextureAtlasserProGuiLoader.exportAtlasGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
MA_TextureAtlasserProExportWindow.InitEditorWindow(curWindow);
//MA_TextureAtlasserProUtils.ExportAtlas(curWindow.textureAtlas);
}
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET);
if(curWindow.textureAtlas.showTextures && GUILayout.Button(MA_TextureAtlasserProIcons.showTexturesOnIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(curWindow.textureAtlas.showTextures && GUILayout.Button(MA_TextureAtlasserProGuiLoader.showTexturesOnGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
curWindow.textureAtlas.showTextures = false;
}
else if(!curWindow.textureAtlas.showTextures && GUILayout.Button(MA_TextureAtlasserProIcons.showTexturesOffIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
else if(!curWindow.textureAtlas.showTextures && GUILayout.Button(MA_TextureAtlasserProGuiLoader.showTexturesOffGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
curWindow.textureAtlas.showTextures = true;
}
GUILayout.Space(MA_TextureAtlasserProUtils.VIEW_OFFSET);
if(GUILayout.Button(MA_TextureAtlasserProIcons.createQuadIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(GUILayout.Button(MA_TextureAtlasserProGuiLoader.createQuadGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
MA_TextureAtlasserProUtils.CreateTextureQuad(curWindow.textureAtlas, "new Quad", new Rect(0, 0, 128, 128), curWindow.settings.autoFocus);
}
if(curWindow.textureAtlas.selectedTextureQuad != null && GUILayout.Button(MA_TextureAtlasserProIcons.removeQuadIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if(curWindow.textureAtlas.selectedTextureQuad != null && GUILayout.Button(MA_TextureAtlasserProGuiLoader.removeQuadGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
if(curWindow.textureAtlas.selectedTextureQuad != null)
MA_TextureAtlasserProUtils.RemoveTextureQuad(curWindow.textureAtlas, curWindow.settings.autoFocus);
}
if (curWindow.textureAtlas.selectedTextureQuad != null && GUILayout.Button(MA_TextureAtlasserProIcons.duplicateQuadIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if (curWindow.textureAtlas.selectedTextureQuad != null && GUILayout.Button(MA_TextureAtlasserProGuiLoader.duplicateQuadGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
if (curWindow.textureAtlas.selectedTextureQuad != null)
MA_TextureAtlasserProUtils.DuplicateTextureQuad(curWindow.textureAtlas, curWindow.settings.autoFocus, curWindow.settings.copySelectedQuadData, curWindow.settings.duplicatedQuadNamePrefix);
MA_TextureAtlasserProUtils.DuplicateTextureQuad(curWindow.textureAtlas, curWindow.settings.autoFocus, curWindow.settings.duplicatedQuadNamePrefix);
}
}

View File

@ -91,7 +91,7 @@ namespace MA_TextureAtlasserPro
e.Use();
}
//Hotkeys.
//HotKeys.
if (curWindow.settings.useHotkeys)
{
if(curWindow.textureAtlas != null)
@ -123,7 +123,7 @@ namespace MA_TextureAtlasserPro
if (curWindow.settings.GetHotKey(e, curWindow.settings.duplicateHotKey))
{
MA_TextureAtlasserProUtils.DuplicateTextureQuad(curWindow.textureAtlas, curWindow.settings.autoFocus, curWindow.settings.copySelectedQuadData, curWindow.settings.duplicatedQuadNamePrefix);
MA_TextureAtlasserProUtils.DuplicateTextureQuad(curWindow.textureAtlas, curWindow.settings.autoFocus, curWindow.settings.duplicatedQuadNamePrefix);
e.Use();
}
}
@ -145,9 +145,9 @@ namespace MA_TextureAtlasserPro
{
if(q.isSelected)
{
GUI.Button(new Rect(q.dragRectPos.x, q.dragRectPos.y, q.dragRectPos.width, q.dragRectPos.height), MA_TextureAtlasserProIcons.dragHandleIcon);
GUI.Button(new Rect(q.dragRectWidth.x, q.dragRectWidth.y, q.dragRectWidth.width, q.dragRectWidth.height), MA_TextureAtlasserProIcons.dragHandleIcon);
GUI.Button(new Rect(q.dragRectHeight.x, q.dragRectHeight.y, q.dragRectHeight.width, q.dragRectHeight.height), MA_TextureAtlasserProIcons.dragHandleIcon);
GUI.Button(new Rect(q.dragRectPos.x, q.dragRectPos.y, q.dragRectPos.width, q.dragRectPos.height), MA_TextureAtlasserProGuiLoader.dragHandleGC);
GUI.Button(new Rect(q.dragRectWidth.x, q.dragRectWidth.y, q.dragRectWidth.width, q.dragRectWidth.height), MA_TextureAtlasserProGuiLoader.dragHandleGC);
GUI.Button(new Rect(q.dragRectHeight.x, q.dragRectHeight.y, q.dragRectHeight.width, q.dragRectHeight.height), MA_TextureAtlasserProGuiLoader.dragHandleGC);
}
}
}

View File

@ -136,7 +136,7 @@ namespace MA_TextureAtlasserPro
{
GUILayout.BeginHorizontal(EditorStyles.helpBox, GUILayout.Height(44));
if (GUILayout.Button(MA_TextureAtlasserProIcons.createAtlasIcon, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
if (GUILayout.Button(MA_TextureAtlasserProGuiLoader.createExportSettingsGC, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true)))
{
MA_TextureAtlasserProCreateExportWindow.InitWindow(curWindow);
}
@ -154,40 +154,23 @@ namespace MA_TextureAtlasserPro
if (GUILayout.Button("Export", GUILayout.ExpandWidth(true), GUILayout.Height(37)))
{
bool export = false;
string[] textures = null;
string material = null;
string[] models = null;
if(curWindow.textureAtlas.exportSettings.modelExportSettings.modelFormat == ModelFormat.ReplaceMesh)
if (curWindow.textureAtlas.exportSettings.exportTextures)
{
if(EditorUtility.DisplayDialog("Replace original models?", "Are you sure you want to replace the original models, this can't be undone!", "Replace", "Cancel"))
{
export = true;
}
}
else
{
export = true;
textures = MA_TextureAtlasserProUtils.ExportAtlasTextures(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.textureExportSettings);
}
if(export)
if (curWindow.textureAtlas.exportSettings.exportMaterials)
{
string[] textures = null;
string material = null;
string[] models = null;
material = MA_TextureAtlasserProUtils.ExportAtlasMaterial(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.materialExportSettings, textures: textures);
}
if (curWindow.textureAtlas.exportSettings.exportTextures)
{
textures = MA_TextureAtlasserProUtils.ExportAtlasTextures(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.textureExportSettings);
}
if(curWindow.textureAtlas.exportSettings.exportMaterials)
{
material = MA_TextureAtlasserProUtils.ExportAtlasMaterial(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.materialExportSettings, textures: textures);
}
if(curWindow.textureAtlas.exportSettings.exportModels)
{
models = MA_TextureAtlasserProUtils.ExportAtlasModels(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.modelExportSettings, material: material);
}
if (curWindow.textureAtlas.exportSettings.exportModels)
{
models = MA_TextureAtlasserProUtils.ExportAtlasModels(curWindow.textureAtlas, curWindow.textureAtlas.exportSettings.modelExportSettings, materialPath: material);
}
}

View File

@ -34,7 +34,7 @@ namespace MA_TextureAtlasserPro
private void OnEnable()
{
//Load the icons
MA_TextureAtlasserProIcons.LoadIcons();
//MA_TextureAtlasserProGuiLoader.LoadEditorGui(thisWindow.settings.editorGuiSettings);
}
private static void GetCurrentWindow()
@ -59,6 +59,7 @@ namespace MA_TextureAtlasserPro
}
thisWindow.settings = MA_TextureAtlasserProUtils.LoadSettings();
MA_TextureAtlasserProGuiLoader.LoadEditorGui(thisWindow.settings);
thisWindow.workView = new MA_TextureAtlasserProWorkView(thisWindow, "workView");
thisWindow.menuView = new MA_TextureAtlasserProMenuView(thisWindow, "menuView");
thisWindow.inspectorView = new MA_TextureAtlasserProInspectorView(thisWindow, "inspectorView");

View File

@ -15,259 +15,165 @@ using UnityEditor;
namespace MA_Mesh
{
public static class MA_MeshUtils
{
public static string MA_SaveMeshAsset(Mesh mesh, string savePath)
{
if (string.IsNullOrEmpty(mesh.name))
{
mesh.name = UnityEngine.Random.Range(11111, 99999).ToString();
}
public static class MA_MeshUtils
{
public static string MA_SaveMeshAsset(Mesh mesh, string savePath)
{
if (string.IsNullOrEmpty(mesh.name))
{
mesh.name = UnityEngine.Random.Range(11111, 99999).ToString();
}
string assetPath = savePath + mesh.name + ".asset";
string assetPath = savePath + mesh.name + ".asset";
AssetDatabase.CreateAsset(mesh, assetPath);
AssetDatabase.SaveAssets();
AssetDatabase.CreateAsset(mesh, assetPath);
AssetDatabase.SaveAssets();
return assetPath;
}
return assetPath;
}
public static string MA_SaveMeshPrefab(Mesh mesh, string prefabName, string savePath, string materialPath)
{
string assetPath = null;
public static string MA_SaveMeshPrefab(Mesh mesh, string prefabName, string savePath, string materialPath)
{
string assetPath = null;
string meshAssetPath = MA_SaveMeshAsset(mesh, savePath);
Mesh meshAsset = AssetDatabase.LoadAssetAtPath<Mesh>(meshAssetPath);
string meshAssetPath = MA_SaveMeshAsset(mesh, savePath);
Mesh meshAsset = AssetDatabase.LoadAssetAtPath<Mesh>(meshAssetPath);
if (meshAsset != null)
{
GameObject gameObject = new GameObject
{
name = prefabName
};
if (meshAsset != null)
{
GameObject gameObject = new GameObject
{
name = prefabName
};
gameObject.AddComponent<MeshFilter>().mesh = meshAsset;
gameObject.AddComponent<MeshRenderer>();
gameObject.AddComponent<MeshFilter>().mesh = meshAsset;
gameObject.AddComponent<MeshRenderer>();
Material curMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (curMaterial != null)
{
gameObject.GetComponent<MeshRenderer>().material = curMaterial;
}
Material curMaterial = AssetDatabase.LoadAssetAtPath<Material>(materialPath);
if (curMaterial != null)
{
gameObject.GetComponent<MeshRenderer>().material = curMaterial;
}
if (string.IsNullOrEmpty(prefabName))
{
prefabName = UnityEngine.Random.Range(11111, 99999).ToString();
}
if (string.IsNullOrEmpty(prefabName))
{
prefabName = UnityEngine.Random.Range(11111, 99999).ToString();
}
assetPath = savePath + prefabName + ".prefab";
assetPath = savePath + prefabName + ".prefab";
#if UNITY_2018_3_OR_NEWER
PrefabUtility.SaveAsPrefabAsset(gameObject, assetPath);
UnityEngine.Object.DestroyImmediate(gameObject);
}
PrefabUtility.SaveAsPrefabAsset(gameObject, assetPath);
return assetPath;
}
#else
public static Mesh MA_DuplicateMesh(Mesh mesh)
{
Mesh newMesh = new Mesh
{
name = mesh.name,
bounds = mesh.bounds,
subMeshCount = mesh.subMeshCount
};
GameObject go = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
if (go != null)
{
PrefabUtility.ReplacePrefab(gameObject, go, ReplacePrefabOptions.ReplaceNameBased);
}
else
{
PrefabUtility.CreatePrefab(assetPath, gameObject, ReplacePrefabOptions.ReplaceNameBased);
}
newMesh.SetVertices(new List<Vector3>(mesh.vertices));
for (int i = 0; i < mesh.subMeshCount; i++)
{
newMesh.SetTriangles(mesh.GetTriangles(i), i);
}
newMesh.SetNormals(new List<Vector3>(mesh.normals));
for (int i = 0; i < 8; i++)
{
List<Vector2> uvs = new List<Vector2>();
mesh.GetUVs(i, uvs);
newMesh.SetUVs(i, uvs);
}
newMesh.SetTangents(new List<Vector4>(mesh.tangents));
newMesh.SetColors(new List<Color>(mesh.colors));
#endif
return newMesh;
}
UnityEngine.GameObject.DestroyImmediate(gameObject);
}
return assetPath;
}
public static Mesh MA_DuplicateMesh(Mesh mesh)
{
Mesh newMesh = new Mesh
{
name = mesh.name,
bounds = mesh.bounds,
subMeshCount = mesh.subMeshCount
};
newMesh.SetVertices(new List<Vector3>(mesh.vertices));
for (int i = 0; i < mesh.subMeshCount; i++)
{
newMesh.SetTriangles(mesh.GetTriangles(i), i);
}
newMesh.SetNormals(new List<Vector3>(mesh.normals));
newMesh.SetUVs(0, new List<Vector2>(mesh.uv));
newMesh.SetTangents(new List<Vector4>(mesh.tangents));
newMesh.SetColors(new List<Color>(mesh.colors));
return newMesh;
}
public static Mesh MA_ReMapUV(this Mesh mesh, Vector2 atlasSize, Vector2 textureSize, Vector2 texturePosition, int uvChannel = 0)
{
/*
public static Mesh MA_ReMapUV(this Mesh mesh, Vector2 atlasSize, Vector2 textureSize, Vector2 texturePosition, int uvChannel = 0)
{
/*
0 1
512 x 512
0 .5 = 1 / 512 * 256
0 .5 = 1 / 512 * 256
256 x 256
+ pos
*/
List<Vector2> uvs = new List<Vector2>();
List<Vector2> uvs = new List<Vector2>();
//Get UV's
mesh.GetUVs(uvChannel, uvs);
//Get UV's
mesh.GetUVs(uvChannel, uvs);
foreach (Vector2 uvCordinate in uvs)
{
float x = (uvCordinate.x / atlasSize.x * textureSize.x) + texturePosition.x;
float y = (uvCordinate.y / atlasSize.y * textureSize.y) + texturePosition.y;
uvCordinate.Set(x, y);
}
foreach (Vector2 uvCordinate in uvs)
{
float x = (uvCordinate.x / atlasSize.x * textureSize.x) + texturePosition.x;
float y = (uvCordinate.y / atlasSize.y * textureSize.y) + texturePosition.y;
uvCordinate.Set(x, y);
}
mesh.SetUVs(uvChannel, uvs);
mesh.SetUVs(uvChannel, uvs);
return mesh;
}
return mesh;
}
public static Mesh MA_UVReMap(this Mesh mesh, Vector2 atlasSize, Rect textureRect, int uvChannel = 0, bool flipY = true, bool wrap = true)
{
//Get UV's
List<Vector2> uvs = new List<Vector2>();
mesh.GetUVs(uvChannel, uvs);
public static Mesh MA_UVReMap(this Mesh mesh, Vector2 atlasSize, Rect textureRect, int uvChannel = 0, bool flipY = true, bool wrap = true)
{
//Get UV's
List<Vector2> uvs = new List<Vector2>();
mesh.GetUVs(uvChannel, uvs);
//Min and max bounds in 0-1 space.
float xMin, xMax, yMin, yMax;
xMin = (1f / atlasSize.x * textureRect.width);
xMax = (1f / atlasSize.x * textureRect.x);
yMin = (1f / atlasSize.y * textureRect.height);
//Min and max bounds in 0-1 space.
float xMin, xMax, yMin, yMax;
xMin = (1f / atlasSize.x * textureRect.width);
xMax = (1f / atlasSize.x * textureRect.x);
yMin = (1f / atlasSize.y * textureRect.height);
//Flip uv's if needed.
if (flipY)
{
yMax = (1f / atlasSize.y * (atlasSize.y - textureRect.height - textureRect.y));
}
else
{
yMax = (1f / atlasSize.y * textureRect.y);
}
//Flip uv's if needed.
if (flipY)
{
yMax = (1f / atlasSize.y * (atlasSize.y - textureRect.height - textureRect.y));
}
else
{
yMax = (1f / atlasSize.y * textureRect.y);
}
for (int i = 0; i < uvs.Count; i++)
{
float newX = uvs[i].x * xMin + xMax;
float newY = uvs[i].y * yMin + yMax;
for (int i = 0; i < uvs.Count; i++)
{
float newX = uvs[i].x * xMin + xMax;
float newY = uvs[i].y * yMin + yMax;
//Wrap the verts outside of the uv space around back into the uv space.
if (wrap)
{
newX = Wrap(newX, xMax, xMin + xMax);
newY = Wrap(newY, yMax, yMin + yMax);
}
//Wrap the verts outside of the uv space around back into the uv space.
if (wrap)
{
newX = Wrap(newX, xMax, xMin + xMax);
newY = Wrap(newY, yMax, yMin + yMax);
}
uvs[i] = new Vector2(newX, newY);
}
uvs[i] = new Vector2(newX, newY);
}
mesh.SetUVs(uvChannel, uvs);
mesh.SetUVs(uvChannel, uvs);
return mesh;
}
return mesh;
}
public static float Wrap(float val, float min, float max)
{
val -= (float)Math.Round((val - min) / (max - min)) * (max - min);
if (val < min)
val = val + max - min;
return val;
}
//Start http://wiki.unity3d.com/index.php?title=ObjExporter
public static string MeshToString(Mesh mesh)
{
int vertexOffset = 0;
int normalOffset = 0;
int uvOffset = 0;
Material material = new Material(Shader.Find("Standard"));
StringBuilder sb = new StringBuilder();
sb.Append("g ").Append(mesh.name).Append("\n");
foreach (Vector3 v in mesh.vertices)
{
//This is sort of ugly - inverting x-component since we're in
//a different coordinate system than "everyone" is "used to".
sb.Append(string.Format("v {0} {1} {2}\n", -v.x, v.y, v.z));
}
sb.Append("\n");
foreach (Vector3 v in mesh.normals)
{
sb.Append(string.Format("vn {0} {1} {2}\n", -v.x, v.y, v.z));
}
sb.Append("\n");
foreach (Vector3 v in mesh.uv)
{
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
}
for (int m = 0; m < mesh.subMeshCount; m++)
{
sb.Append("\n");
sb.Append("usemtl ").Append(material.name + m).Append("\n");
sb.Append("usemap ").Append(material.name + m).Append("\n");
// int[] triangles = mesh.GetTriangles(m);
// for (int i = 0; i < triangles.Length; i += 3)
// {
// sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", triangles[i]+1, triangles[i+1]+1, triangles[i+2]+1));
// }
int[] triangles = mesh.GetTriangles(m);
for (int i = 0; i < triangles.Length; i += 3)
{
//Because we inverted the x-component, we also needed to alter the triangle winding.
sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset));
}
}
//vertexOffset += mesh.vertices.Length;
//normalOffset += mesh.normals.Length;
//uvOffset += mesh.uv.Length;
return sb.ToString();
}
public static string MeshToFile(Mesh mesh, string filename, string savePath)
{
string assetPath = savePath + filename + ".obj";
using (StreamWriter sw = new StreamWriter(assetPath))
{
sw.Write(MeshToString(mesh));
}
AssetDatabase.Refresh();
return assetPath;
}
//End
}
//struct ObjMaterial
//{
// public string name;
// public string textureName;
//}
public static float Wrap(float val, float min, float max)
{
val -= (float)Math.Round((val - min) / (max - min)) * (max - min);
if (val < min)
val = val + max - min;
return val;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9946d57c8e1c3714183228268fff08a5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
//-
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace MA_Toolbox.Utils.Editor
{
public static class MA_PrefabUtils
{
public static string CreatePrefab(string prefabName, string savePath)
{
if(string.IsNullOrEmpty(prefabName) || string.IsNullOrWhiteSpace(prefabName))
{
Debug.LogError("Invalid prefab name.");
return null;
}
GameObject gameObject = new GameObject
{
name = prefabName
};
string assetPath = savePath + prefabName + ".prefab";
PrefabUtility.SaveAsPrefabAsset(gameObject, assetPath);
UnityEngine.Object.DestroyImmediate(gameObject);
return assetPath;
}
public static void AddChild(GameObject prefab, GameObject child)
{
GameObject p = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
child.transform.SetParent(p.transform);
PrefabUtility.ApplyPrefabInstance(p, InteractionMode.AutomatedAction);
UnityEngine.Object.DestroyImmediate(p);
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04e1a62b7d6bb434eb0314336ac94f8f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f38cac7c10bd77748ab01c8642751035
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,28 @@
//-
using UnityEditor;
using UnityEngine;
namespace MA_Toolbox.Utils
{
public static class MA_StringUtils
{
private const string ALPHABET = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
public static string RandomAlphabetString(int length)
{
string s = "";
for (int i = 0; i < length; i++)
{
s += RandomAlphabetChar();
}
return s;
}
public static char RandomAlphabetChar()
{
return ALPHABET[Random.Range(0, ALPHABET.Length)];
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc1a5e241141bb549b81ad11dfdc0962
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -161,17 +161,20 @@ namespace MA_Texture
{
Color[] newColors = new Color[newWidth * newHeight];
float ratioX = ((float)curWidth) / newWidth;
float ratioY = ((float)curHeight) / newHeight;
float ratioX = 1.0f / ((float)newWidth / (curWidth - 1));
float ratioY = 1.0f / ((float)newHeight / (curHeight - 1));
for (int y = 0; y < newHeight; y++)
for (int y = 0; y < newHeight; y++)
{
var thisY = Mathf.RoundToInt((ratioY * y) * curWidth);
var yw = y * newWidth;
int yFloor = Mathf.FloorToInt(y * ratioY);
var y1 = (yFloor + 1) * curWidth;
var yw = y * newWidth;
for (int x = 0; x < newWidth; x++)
for (int x = 0; x < newWidth; x++)
{
newColors[yw + x] = curColors[Mathf.RoundToInt(thisY + ratioX * x)];
int xFloor = Mathf.FloorToInt(x * ratioX);
newColors[yw + x] = curColors[Mathf.RoundToInt(y1 + xFloor)];
}
}
@ -196,7 +199,7 @@ namespace MA_Texture
if(flipY)
{
//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 - 1; y >= 0; y--)
{
texture.SetPixel(x + offsetX, y + (texture.height - offsetY - combineTexture.height), combineTexture.GetPixel(x, y));
}

View File

@ -2,8 +2,7 @@
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.ext.nunit": "1.0.0",
"com.unity.package-manager-ui": "2.2.0",
"com.unity.test-framework": "1.0.13",
"com.unity.test-framework": "1.1.9",
"com.unity.ugui": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",

View File

@ -3,7 +3,7 @@
--- !u!159 &1
EditorSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
serializedVersion: 9
m_ExternalVersionControlSupport: Hidden Meta Files
m_SerializationMode: 2
m_LineEndingsForNewScripts: 2
@ -16,10 +16,20 @@ EditorSettings:
m_EtcTextureFastCompressor: 1
m_EtcTextureNormalCompressor: 2
m_EtcTextureBestCompressor: 4
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp
m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref
m_ProjectGenerationRootNamespace:
m_CollabEditorSettings:
inProgressEnabled: 1
m_EnableTextureStreamingInEditMode: 1
m_EnableTextureStreamingInPlayMode: 1
m_AsyncShaderCompilation: 1
m_EnterPlayModeOptionsEnabled: 0
m_EnterPlayModeOptions: 3
m_ShowLightmapResolutionOverlay: 1
m_UseLegacyProbeSampleCount: 1
m_AssetPipelineMode: 1
m_CacheServerMode: 0
m_CacheServerEndpoint:
m_CacheServerNamespacePrefix: default
m_CacheServerEnableDownload: 1
m_CacheServerEnableUpload: 1

View File

@ -1,2 +1,2 @@
m_EditorVersion: 2019.2.13f1
m_EditorVersionWithRevision: 2019.2.13f1 (e20f6c7e5017)
m_EditorVersion: 2019.3.0f6
m_EditorVersionWithRevision: 2019.3.0f6 (27ab2135bccf)

View File

@ -1,4 +1,4 @@
[![Image](https://maxartz15.com/wp-content/uploads/2019/04/MA_TextureAtlas.png)]()
[![Image](https://maxartz15.com/wp-content/uploads/2020/04/MA_TextureAtlas2.png)](https://maxartz15.com/wp-content/uploads/2020/04/MA_TextureAtlas2.png)
# MA_TextureAtlasser
Texture atlas creator tool for Unity. <br> This tool is made to combine textures and/or remap the UVs for 3D models. The tool can also be used to make 2D sprite sheets. The visual editor gives you the ability to set and prioritize the sizes and positions in the texture atlas/sprite sheet.
@ -6,17 +6,16 @@ Texture atlas creator tool for Unity. <br> This tool is made to combine textures
- Automatically adjusts the UV's of the assigned meshes to match the new texture atlas.
### Download unitypackage
https://github.com/maxartz15/MA_TextureAtlasser/releases <br>
[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)]()
[![Github All Releases](https://img.shields.io/github/downloads/maxartz15/MA_TextureAtlasser/total.svg)](https://github.com/maxartz15/MA_TextureAtlasser/releases)
### Tested Unity versions
[![Image](https://img.shields.io/badge/Unity-2017.4-green)]() [![Image](https://img.shields.io/badge/Unity-2018.4-green)]() [![Image](https://img.shields.io/badge/Unity-2019.2-green)]()
### Unity versions
- Latest release requires Unity 2018.3 or higher.
- Releases before 1.8 should work with older Unity versions.
- Upgrading to 1.8+ will break existing atlasses.
## Export options
### Meshes
- UnityMesh (with prefab setup)
- OBJ
- Replace orginal (this will replace the orginal model, make sure to backup before doing this!)
### Textures
- PNG
- PNG (sliced) sprite sheet
@ -25,4 +24,4 @@ https://github.com/maxartz15/MA_TextureAtlasser/releases <br>
## Resources
[Youtube video](https://youtu.be/PBRKlopkZP0) <br>
[Website](https://maxartz15.com/ma-textureatlasser/)
[Website](https://maxartz15.com/ma_textureatlas/)