Created
April 8, 2019 07:17
-
-
Save kalineh/49e4f68a04507033c047c977f6b0897c to your computer and use it in GitHub Desktop.
SpriteExporter.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.IO; | |
using System.Collections.Generic; | |
using UnityEngine; | |
// have a list of sprites | |
// with a list of sprite config | |
#if UNITY_EDITOR | |
using UnityEditor; | |
[CustomEditor(typeof(SpriteExporter))] | |
class SpriteExporterEditor | |
: Editor | |
{ | |
[MenuItem("Croppy/Export All Sprites")] | |
public static void MenuExportAll() | |
{ | |
var exporters = GameObject.FindObjectsOfType<SpriteExporter>(); | |
foreach (var exporter in exporters) | |
exporter.ExportAll(); | |
} | |
public override void OnInspectorGUI() | |
{ | |
var self = target as SpriteExporter; | |
GUILayout.BeginHorizontal(); | |
if (GUILayout.Button("Enable All")) | |
self.EnableAll(); | |
if (GUILayout.Button("Disable All")) | |
self.DisableAll(); | |
GUILayout.EndHorizontal(); | |
GUILayout.BeginHorizontal(); | |
if (GUILayout.Button("Export Singles")) | |
self.ExportSingles(); | |
if (GUILayout.Button("Export Batches")) | |
self.ExportBatches(); | |
if (GUILayout.Button("Export Turntables")) | |
self.ExportTurntables(); | |
GUILayout.EndHorizontal(); | |
if (GUILayout.Button("Export All")) | |
self.ExportAll(); | |
EditorGUILayout.Space(); | |
base.OnInspectorGUI(); | |
} | |
} | |
#endif | |
[System.Serializable] | |
public class SpriteExporterSettingSingle | |
{ | |
public GameObject obj; | |
public Sprite output; | |
// specific animation pose? | |
// specific material setting? | |
// camera override? | |
// postprocess override? | |
} | |
[System.Serializable] | |
public class SpriteExporterSettingBatch | |
{ | |
public GameObject root; | |
public Texture2D output; | |
} | |
[System.Serializable] | |
public class SpriteExporterSettingTurntable | |
{ | |
public GameObject obj; | |
public Texture2D output; | |
public int count; | |
} | |
public class SpriteExporter | |
: MonoBehaviour | |
{ | |
public Camera camera; | |
public List<SpriteExporterSettingSingle> singles; | |
public List<SpriteExporterSettingBatch> batches; | |
public List<SpriteExporterSettingTurntable> turntables; | |
public void ExportSingles() | |
{ | |
Debug.LogFormat("SpriteExporter: Exporting singles for {0}...", gameObject.name); | |
foreach (var single in singles) | |
ExportSingle(single); | |
} | |
public void ExportBatches() | |
{ | |
Debug.LogFormat("SpriteExporter: Exporting batches for {0}...", gameObject.name); | |
foreach (var batch in batches) | |
ExportBatch(batch); | |
} | |
public void ExportTurntables() | |
{ | |
Debug.LogFormat("SpriteExporter: Exporting turntables for {0}...", gameObject.name); | |
foreach (var turntable in turntables) | |
ExportTurntable(turntable); | |
} | |
public void ExportAll() | |
{ | |
ExportSingles(); | |
ExportBatches(); | |
ExportTurntables(); | |
} | |
public void DisableAll() | |
{ | |
foreach (var single in singles) | |
{ | |
if (single.obj != null) | |
single.obj.SetActive(false); | |
} | |
foreach (var batch in batches) | |
{ | |
if (batch.root != null) | |
batch.root.SetActive(false); | |
} | |
foreach (var turntable in turntables) | |
{ | |
if (turntable.obj != null) | |
turntable.obj.SetActive(false); | |
} | |
} | |
public void EnableAll() | |
{ | |
foreach (var single in singles) | |
{ | |
if (single.obj != null) | |
single.obj.SetActive(true); | |
} | |
foreach (var batch in batches) | |
{ | |
if (batch.root != null) | |
batch.root.SetActive(true); | |
} | |
foreach (var turntable in turntables) | |
{ | |
if (turntable.obj != null) | |
turntable.obj.SetActive(true); | |
} | |
} | |
public void ExportSingle(SpriteExporterSettingSingle single) | |
{ | |
var obj = single.obj; | |
var output = single.output; | |
if (obj == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportSingle: null object"); | |
return; | |
} | |
if (output == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportSingle: null output sprite"); | |
return; | |
} | |
var texture = output.texture; | |
var textureRect = output.textureRect; | |
if (textureRect.width != (float)((int)textureRect.width)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportSingle: width not integer value on {0}", obj.name); | |
return; | |
} | |
if (textureRect.height != (float)((int)textureRect.height)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportSingle: width not integer value on {0}", obj.name); | |
return; | |
} | |
var outputRect = new Rect(output.textureRect.x, output.textureRect.y, output.textureRect.width, output.textureRect.height); | |
var rt = new RenderTexture((int)outputRect.width, (int)outputRect.height, 0, RenderTextureFormat.ARGB32); | |
obj.gameObject.SetActive(true); | |
camera.targetTexture = rt; | |
camera.Render(); | |
RenderTexture.active = rt; | |
texture.ReadPixels(new Rect(0, 0, rt.width, rt.height), (int)outputRect.x, (int)outputRect.y); | |
texture.Apply(true, false); | |
RenderTexture.active = null; | |
obj.gameObject.SetActive(false); | |
var assetPath = AssetDatabase.GetAssetPath(output); | |
var writePath = Path.Combine(Application.dataPath.Replace("Assets", ""), assetPath); | |
File.WriteAllBytes(writePath, texture.EncodeToPNG()); | |
EditorUtility.SetDirty(texture); | |
EditorUtility.SetDirty(output); | |
AssetDatabase.SaveAssets(); | |
Debug.LogFormat("SpriteExporter.ExportSingle: exported {0}", obj.name); | |
} | |
public void ExportBatch(SpriteExporterSettingBatch batch) | |
{ | |
var root = batch.root; | |
var output = batch.output; | |
if (root == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: null object"); | |
return; | |
} | |
if (output == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: null output sprite"); | |
return; | |
} | |
var assetPath = AssetDatabase.GetAssetPath(output); | |
var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath); | |
var sprites = new List<Sprite>(); | |
foreach (var asset in assets) | |
{ | |
var sprite = asset as Sprite; | |
if (sprite != null) | |
sprites.Add(sprite); | |
} | |
if (sprites.Count < root.transform.childCount) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: mismatch between sprite count ({0}) and object child count ({1}) for {2}", sprites.Count, root.transform.childCount, root.name); | |
return; | |
} | |
root.gameObject.SetActive(true); | |
for (int i = 0; i < root.transform.childCount; ++i) | |
root.transform.GetChild(i).gameObject.SetActive(false); | |
for (int i = 0; i < root.transform.childCount; ++i) | |
{ | |
var child = root.transform.GetChild(i); | |
var obj = child.gameObject; | |
var sprite = sprites[i]; | |
var texture = sprite.texture; | |
var textureRect = sprite.textureRect; | |
if (textureRect.width != (float)((int)textureRect.width)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: width not integer value on {0}.{1}", root.name, child.name); | |
continue; | |
} | |
if (textureRect.height != (float)((int)textureRect.height)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: width not integer value on {0}.{1}", root.name, child.name); | |
return; | |
} | |
var outputRect = new Rect(sprite.textureRect.x, sprite.textureRect.y, sprite.textureRect.width, sprite.textureRect.height); | |
var rt = new RenderTexture((int)outputRect.width, (int)outputRect.height, 0, RenderTextureFormat.ARGB32); | |
child.gameObject.SetActive(true); | |
camera.targetTexture = rt; | |
camera.Render(); | |
RenderTexture.active = rt; | |
texture.ReadPixels(new Rect(0, 0, rt.width, rt.height), (int)outputRect.x, (int)outputRect.y); | |
texture.Apply(true, false); | |
RenderTexture.active = null; | |
child.gameObject.SetActive(false); | |
Debug.LogFormat("SpriteExporter.ExportBatch: exported {0}.{1}", root.name, child.name); | |
EditorUtility.SetDirty(texture); | |
EditorUtility.SetDirty(sprite); | |
} | |
var writePath = Path.Combine(Application.dataPath.Replace("Assets", ""), assetPath); | |
File.WriteAllBytes(writePath, output.EncodeToPNG()); | |
EditorUtility.SetDirty(output); | |
AssetDatabase.SaveAssets(); | |
} | |
public void ExportTurntable(SpriteExporterSettingTurntable turntable) | |
{ | |
var obj = turntable.obj; | |
var output = turntable.output; | |
if (obj == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: null object"); | |
return; | |
} | |
if (output == null) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: null output sprite"); | |
return; | |
} | |
var assetPath = AssetDatabase.GetAssetPath(output); | |
var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath); | |
var sprites = new List<Sprite>(); | |
foreach (var asset in assets) | |
{ | |
var sprite = asset as Sprite; | |
if (sprite != null) | |
sprites.Add(sprite); | |
} | |
if (sprites.Count < turntable.count) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: not enough sprites ({0} for turntable ({1}) for {2}", sprites.Count, turntable.count, obj.name); | |
return; | |
} | |
var camPosition = camera.transform.position; | |
var camRotation = camera.transform.rotation; | |
var camDistance = camera.transform.position.z; | |
var camHeight = camera.transform.position.y; | |
for (int i = 0; i < turntable.count; ++i) | |
{ | |
var sprite = sprites[i]; | |
var texture = sprite.texture; | |
var textureRect = sprite.textureRect; | |
if (textureRect.width != (float)((int)textureRect.width)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: width not integer value on {0}.{1}", obj.name, sprite.name); | |
continue; | |
} | |
if (textureRect.height != (float)((int)textureRect.height)) | |
{ | |
Debug.LogErrorFormat("SpriteExporter.ExportBatch: width not integer value on {0}.{1}", obj.name, sprite.name); | |
return; | |
} | |
var outputRect = new Rect(sprite.textureRect.x, sprite.textureRect.y, sprite.textureRect.width, sprite.textureRect.height); | |
var rt = new RenderTexture((int)outputRect.width, (int)outputRect.height, 0, RenderTextureFormat.ARGB32); | |
obj.gameObject.SetActive(true); | |
var orbit = 1.0f / (float)turntable.count * (float)i * Mathf.PI * 2.0f * Mathf.Rad2Deg; | |
camera.transform.position = Quaternion.Euler(0.0f, orbit, 0.0f) * (Vector3.forward * camDistance + Vector3.up * camHeight); | |
camera.transform.rotation = Quaternion.LookRotation(-camera.transform.position, Vector3.up); | |
Debug.DrawLine(camera.transform.position, camera.transform.position - camera.transform.forward * camDistance, Color.red, 5.0f); | |
Debug.DrawLine(camera.transform.position, camera.transform.position + Vector3.up, Color.green, 5.0f); | |
camera.targetTexture = rt; | |
camera.Render(); | |
RenderTexture.active = rt; | |
texture.ReadPixels(new Rect(0, 0, rt.width, rt.height), (int)outputRect.x, (int)outputRect.y); | |
texture.Apply(true, false); | |
RenderTexture.active = null; | |
obj.gameObject.SetActive(false); | |
Debug.LogFormat("SpriteExporter.ExportBatch: exported {0}.{1}", obj.name, i); | |
EditorUtility.SetDirty(texture); | |
EditorUtility.SetDirty(sprite); | |
} | |
camera.transform.position = camPosition; | |
camera.transform.rotation = camRotation; | |
var writePath = Path.Combine(Application.dataPath.Replace("Assets", ""), assetPath); | |
File.WriteAllBytes(writePath, output.EncodeToPNG()); | |
EditorUtility.SetDirty(output); | |
AssetDatabase.SaveAssets(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment