Skip to content

Instantly share code, notes, and snippets.

@sukedon
Last active August 2, 2018 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sukedon/e4ca8a21350b6a22cdcd8bae595c7513 to your computer and use it in GitHub Desktop.
Save sukedon/e4ca8a21350b6a22cdcd8bae595c7513 to your computer and use it in GitHub Desktop.
SpritePackerとSpriteAtlasを自動変換するスクリプト
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityEngine.U2D;
public static class AtlasConverterModel
{
public static string DefaultOutputPath = "Resources/SpriteAtlas";
/// <returns>key:SpritePackerのタグ名,value:そのタグがついてる画像パス一覧 のdictを返却</returns>
public static Dictionary <string, List <string> > FetchTexturePackerTagGroup()
{
var source = Application.dataPath;
string projectPath = Application.dataPath.Replace("Assets", "");
List <string> paths = Directory.GetFiles(source, "*.*", SearchOption.AllDirectories)
.Where(path => path.EndsWith(".png") || path.EndsWith(".jpg"))
.Select(path => path.Replace(projectPath, ""))
.Select(path => path.Replace("\\", Path.AltDirectorySeparatorChar.ToString()))
.ToList();
var dict = new Dictionary <string, List <string> >();
for (int i = 0; i < paths.Count; i++)
{
var path = paths[i];
var importer = AssetImporter.GetAtPath(path);
if (importer == null)
{
Debug.LogWarning("importerがnullporter:" + path);
continue;
}
var textureImporter = importer as TextureImporter;
if (textureImporter == null)
{
Debug.LogWarning("textureImporterがnullporter:" + path);
continue;
}
var tag = textureImporter.spritePackingTag;
if (string.IsNullOrEmpty(tag))
{
Debug.LogWarning("packingtag is not defined:" + path);
continue;
}
if (dict.ContainsKey(tag))
{
dict[tag].Add(path);
}
else
{
dict.Add(tag, new List <string>());
dict[tag].Add(path);
}
EditorUtility.DisplayProgressBar("アトラス変換", "テクスチャのタグを取得中 " + (i + 1) + " / " + paths.Count, (float) i / paths.Count);
}
EditorUtility.ClearProgressBar();
return dict;
}
public static void GenerateAtlas(string outputDirFromAssets, Dictionary <string, List <string> > dict)
{
var atlases = dict.Keys.ToList();
var outputDir = "Assets/" + outputDirFromAssets;
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
AssetDatabase.Refresh();
}
for (int i = 0; i < atlases.Count; i++)
{
EditorUtility.DisplayProgressBar("アトラス変換", "アトラスを作成中 " + (i + 1) + " / " + atlases.Count, (float) i / atlases.Count);
var atlasName = atlases[i] + ".spriteatlas";
var atlas = CreateAtlas(atlasName, outputDir);
var sprites = dict[atlases[i]];
AddSpritesToAtlas(sprites.ToArray(), atlas);
}
EditorUtility.ClearProgressBar();
}
private static void AddSpritesToAtlas(string[] spritePaths, SpriteAtlas atlas)
{
List <Object> sprites = new List <Object>();
for (int i = 0; i < spritePaths.Length; i++)
{
Sprite sprite = AssetDatabase.LoadAssetAtPath <Sprite>(spritePaths[i]);
if (IsPackable(sprite)) {
sprites.Add(sprite);
}
}
AddPackAtlas(atlas, sprites.ToArray());
}
private static bool IsPackable(Object o)
{
return o != null && (o.GetType() == typeof(Sprite) || o.GetType() == typeof(Texture2D) || (o.GetType() == typeof(DefaultAsset) && ProjectWindowUtil.IsFolder(o.GetInstanceID())));
}
private static void AddPackAtlas(SpriteAtlas atlas, Object[] spt)
{
MethodInfo methodInfo = System.Type
.GetType("UnityEditor.U2D.SpriteAtlasExtensions, UnityEditor")
.GetMethod("Add", BindingFlags.Public | BindingFlags.Static);
if (methodInfo != null) {
methodInfo.Invoke(null, new object[] { atlas, spt });
}
else {
Debug.Log("methodInfo is null");
}
PackAtlas(atlas);
}
private static void PackAtlas(SpriteAtlas atlas)
{
System.Type
.GetType("UnityEditor.U2D.SpriteAtlasUtility, UnityEditor")
.GetMethod("PackAtlases", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, new object[] { new[] { atlas }, EditorUserBuildSettings.activeBuildTarget });
}
/// <summary>
///
/// </summary>
/// <param name="atlasName"></param>
/// <param name="root">Resourceフォルダを含む必要あり</param>
/// <param name="dir"></param>
/// <returns></returns>
private static SpriteAtlas CreateAtlas(string atlasName, string dir)
{
string yaml =
@"%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!687078895 &4343727234628468602
SpriteAtlas:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: New Sprite Atlas
m_EditorData:
textureSettings:
serializedVersion: 2
anisoLevel: 1
compressionQuality: 50
maxTextureSize: 2048
textureCompression: 0
filterMode: 1
generateMipMaps: 0
readable: 0
crunchedCompression: 0
sRGB: 1
platformSettings: []
packingParameters:
serializedVersion: 2
padding: 4
blockOffset: 1
allowAlphaSplitting: 0
enableRotation: 1
enableTightPacking: 1
variantMultiplier: 1
packables: []
bindAsDefault: 1
m_MasterAtlas: {fileID: 0}
m_PackedSprites: []
m_PackedSpriteNamesToIndex: []
m_Tag: New Sprite Atlas
m_IsVariant: 0
";
AssetDatabase.Refresh();
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
AssetDatabase.Refresh();
}
string filePath = dir + "/" + atlasName;
if (File.Exists(filePath))
{
File.Delete(filePath);
AssetDatabase.Refresh();
}
FileStream fs = new FileStream(filePath, FileMode.CreateNew);
byte[] bytes = new UTF8Encoding().GetBytes(yaml);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
AssetDatabase.Refresh();
var saPath = dir + "/" + atlasName;
SpriteAtlas atlas = AssetDatabase.LoadAssetAtPath <SpriteAtlas>(saPath);
return atlas;
}
public static void AllocateAtlasNameToTextureTag()
{
var source = Application.dataPath;
string projectPath = Application.dataPath.Replace("Assets", "");
List <string> paths = Directory.GetFiles(source, "*.*", SearchOption.AllDirectories)
.Where(path => path.EndsWith(".spriteatlas"))
.Select(path => path.Replace(projectPath, ""))
.Select(path => path.Replace("\\", Path.AltDirectorySeparatorChar.ToString()))
.ToList();
for (int i = 0; i < paths.Count; i++)
{
var atlas = AssetDatabase.LoadAssetAtPath <SpriteAtlas>(paths[i]);
Debug.Log("=============");
Debug.Log("Atlas ==> " + atlas.name);
MethodInfo methodInfo = System.Type
.GetType("UnityEditor.U2D.SpriteAtlasExtensions, UnityEditor")
.GetMethod("GetPackables", BindingFlags.NonPublic | BindingFlags.Static);
var packablesObj = methodInfo.Invoke(null, new object[] { atlas });
Object[] packables = (Object[]) packablesObj;
for (int j = 0; j < packables.Length; j++)
{
EditorUtility.DisplayProgressBar("アトラス->タグ取得", paths[i] + " " + j + "/" + packables.Length, (float) j / packables.Length);
var sprite = packables[j] as Sprite;
var texture = packables[j] as Texture;
if (sprite == null && texture == null)
{
continue;
}
var assetPath = (sprite != null) ? AssetDatabase.GetAssetPath(sprite) : AssetDatabase.GetAssetPath(texture);
var textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (!textureImporter)
{
continue;
}
textureImporter.spritePackingTag = atlas.name;
AssetDatabase.Refresh();
}
}
EditorUtility.ClearProgressBar();
}
}
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class AtlasConverterWindow : EditorWindow
{
private static string AssetPath = "";
private static string OutputPath = "";
private string _inputError = "";
private static Dictionary <string, List <string> > _dict;
[MenuItem("Tools/SpriterPacker <-> SpriteAtlas 変換")]
public static void Open()
{
var window = GetWindow <AtlasConverterWindow>();
}
private void OnGUI()
{
GUILayout.Label("SpritePackerとSpriteAtlasを変換するツール");
DrawToAtlasTitle();
DrawInput();
GUILayout.Label("");
DrawToPackerTitle();
DrawToPackerButton();
}
private void DrawToAtlasTitle()
{
DrawLine("[SpriterPacker -> SpriteAtlas 変換]", Color.green);
}
private void DrawToPackerTitle()
{
DrawLine("[SpriteAtlas -> SpritePacker 変換]", Color.green);
GUILayout.Label("スプライトアトラスで設定した画像を、各画像のタグに反映させます");
}
private void DrawLine(string content, Color color)
{
using (new EditorGUILayout.HorizontalScope())
{
var style = new GUIStyle(EditorStyles.label)
{
normal = { textColor = color }
};
GUILayout.Label(content, style);
GUILayout.FlexibleSpace();
}
}
private void DrawInput()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label("出力先のフォルダ名(Assets以下)");
OutputPath = GUILayout.TextField(OutputPath, GUILayout.Width(200f));
if (string.IsNullOrEmpty(OutputPath))
{
OutputPath = AtlasConverterModel.DefaultOutputPath;
}
if (GUILayout.Button("出力"))
{
if (string.IsNullOrEmpty(OutputPath))
{
_inputError = "出力先を入力してください(Assets直下は非推奨)";
}
else
{
_inputError = "";
_dict = AtlasConverterModel.FetchTexturePackerTagGroup();
AtlasConverterModel.GenerateAtlas(OutputPath, _dict);
}
}
GUILayout.FlexibleSpace();
}
if (!string.IsNullOrEmpty(_inputError))
{
DrawLine(_inputError, Color.red);
}
}
private void DrawToPackerButton()
{
if (GUILayout.Button("出力"))
{
AtlasConverterModel.AllocateAtlasNameToTextureTag();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment