Skip to content

Instantly share code, notes, and snippets.

@kalineh
Created April 8, 2019 07:17
Show Gist options
  • Save kalineh/49e4f68a04507033c047c977f6b0897c to your computer and use it in GitHub Desktop.
Save kalineh/49e4f68a04507033c047c977f6b0897c to your computer and use it in GitHub Desktop.
SpriteExporter.cs
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