Spine Editor Utility Drag and Drop importer

This commit is contained in:
Fenrisul 2014-07-25 10:38:52 -07:00
parent a7bf0ca963
commit 8a68f5a75a
3 changed files with 216 additions and 61 deletions

View File

@ -80,8 +80,10 @@ public class SkeletonDataAssetInspector : Editor {
EditorGUILayout.PropertyField(skeletonJSON); EditorGUILayout.PropertyField(skeletonJSON);
EditorGUILayout.PropertyField(scale); EditorGUILayout.PropertyField(scale);
if(EditorGUI.EndChangeCheck()){ if(EditorGUI.EndChangeCheck()){
m_previewUtility.Cleanup(); if(m_previewUtility != null){
m_previewUtility = null; m_previewUtility.Cleanup();
m_previewUtility = null;
}
} }
SkeletonData skeletonData = asset.GetSkeletonData(asset.atlasAsset == null || asset.skeletonJSON == null); SkeletonData skeletonData = asset.GetSkeletonData(asset.atlasAsset == null || asset.skeletonJSON == null);
@ -262,7 +264,8 @@ public class SkeletonDataAssetInspector : Editor {
public override bool HasPreviewGUI () public override bool HasPreviewGUI ()
{ {
return true; //TODO: validate json data
return skeletonJSON.objectReferenceValue != null;
} }
Texture m_previewTex = new Texture(); Texture m_previewTex = new Texture();
@ -584,10 +587,14 @@ public class SkeletonDataAssetInspector : Editor {
this.m_previewUtility.m_Camera.transform.position = m_posGoal; this.m_previewUtility.m_Camera.transform.position = m_posGoal;
this.m_previewUtility.BeginStaticPreview(new Rect(0,0,width,height)); this.m_previewUtility.BeginStaticPreview(new Rect(0,0,width,height));
this.DoRenderPreview(false); this.DoRenderPreview(false);
Handles.SetCamera(this.m_previewUtility.m_Camera);
Handles.BeginGUI(); //TODO: Figure out why this is throwing errors on first attempt
GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill); // if(m_previewUtility != null){
Handles.EndGUI(); // Handles.SetCamera(this.m_previewUtility.m_Camera);
// Handles.BeginGUI();
// GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill);
// Handles.EndGUI();
// }
tex = this.m_previewUtility.EndStaticPreview(); tex = this.m_previewUtility.EndStaticPreview();
return tex; return tex;
} }

View File

@ -1,4 +1,6 @@
using UnityEngine; #pragma warning disable 0219
using UnityEngine;
using UnityEditor; using UnityEditor;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
@ -7,7 +9,7 @@ using System.Text;
using Spine; using Spine;
[InitializeOnLoad] [InitializeOnLoad]
public static class SpineEditorUtilities { public class SpineEditorUtilities : AssetPostprocessor {
public static class Icons{ public static class Icons{
public static Texture2D skeleton; public static Texture2D skeleton;
@ -122,10 +124,12 @@ public static class SpineEditorUtilities {
} }
[MenuItem("Assets/Spine/Ingest")] [MenuItem("Assets/Spine/Ingest")]
static void IngestSpineProject(){ static void IngestSpineProjectFromSelection(){
TextAsset spineJson = null; TextAsset spineJson = null;
TextAsset atlasText = null; TextAsset atlasText = null;
List<TextAsset> spineJsonList = new List<TextAsset>();
foreach(UnityEngine.Object o in Selection.objects){ foreach(UnityEngine.Object o in Selection.objects){
if(o.GetType() != typeof(TextAsset)) if(o.GetType() != typeof(TextAsset))
continue; continue;
@ -150,58 +154,190 @@ public static class SpineEditorUtilities {
string atlasPath = assetPath + "/" + primaryName + ".atlas.txt"; string atlasPath = assetPath + "/" + primaryName + ".atlas.txt";
atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset)); atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
} }
AtlasAsset atlasAsset = IngestSpineAtlas(atlasText);
IngestSpineProject(spineJson, atlasAsset);
}
static void OnPostprocessAllAssets(string[] imported, string[] deleted, string[] moved, string[] movedFromAssetPaths){
//debug
// return;
AtlasAsset sharedAtlas = null;
System.Array.Sort<string>(imported);
foreach(string str in imported){
if(Path.GetExtension(str).ToLower() == ".json"){
TextAsset spineJson = (TextAsset)AssetDatabase.LoadAssetAtPath(str, typeof(TextAsset));
if(IsSpineJSON(spineJson)){
if(sharedAtlas != null){
string spinePath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson));
string atlasPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(sharedAtlas));
if(spinePath != atlasPath)
sharedAtlas = null;
}
SkeletonDataAsset data = AutoIngestSpineProject(spineJson, sharedAtlas);
if(data == null)
continue;
sharedAtlas = data.atlasAsset;
SkeletonAnimation anim = SpawnAnimatedSkeleton(data);
string dir = Path.GetDirectoryName(Path.GetDirectoryName(AssetDatabase.GetAssetPath(data)));
string prefabPath = Path.Combine(dir, data.skeletonJSON.name + ".prefab").Replace("\\", "/");
PrefabUtility.CreatePrefab(prefabPath, anim.gameObject, ReplacePrefabOptions.ReplaceNameBased);
if(EditorApplication.isPlaying)
GameObject.Destroy(anim.gameObject);
else
GameObject.DestroyImmediate(anim.gameObject);
}
}
}
}
static bool IsSpineJSON(TextAsset asset){
object obj = Json.Deserialize( new StringReader(asset.text));
if(obj == null){
Debug.LogError("Is not valid JSON");
return false;
}
Dictionary<string, object> root = (Dictionary<string, object>)obj;
if(!root.ContainsKey("skeleton"))
return false;
Dictionary<string, object> skeletonInfo = (Dictionary<string, object>)root["skeleton"];
string spineVersion = (string)skeletonInfo["spine"];
//TODO: reject old versions
return true;
}
static SkeletonDataAsset AutoIngestSpineProject(TextAsset spineJson, Object atlasSource = null){
TextAsset atlasText = null;
AtlasAsset atlasAsset = null;
if(atlasSource != null){
if(atlasSource.GetType() == typeof(TextAsset)){
atlasText = (TextAsset)atlasSource;
}
else if(atlasSource.GetType() == typeof(AtlasAsset)){
atlasAsset = (AtlasAsset)atlasSource;
}
}
if(atlasText == null && atlasAsset == null){
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(spineJson));
if(atlasText == null){
string atlasPath = assetPath + "/" + primaryName + ".atlas.txt";
atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
if(atlasText == null){
//can't find atlas, likely because using a shared atlas
bool abort = !EditorUtility.DisplayDialog("Atlas not Found", "Expecting " + spineJson.name + ".atlas\n" + "Press OK to select Atlas", "OK", "Abort");
if(abort){
//do nothing, let it error later
}
else{
string path = EditorUtility.OpenFilePanel( "Find Atlas source...", Path.GetDirectoryName(Application.dataPath) + "/" + assetPath, "txt");
if(path != ""){
path = path.Replace("\\", "/");
path = path.Replace(Application.dataPath.Replace("\\", "/"), "Assets");
atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset));
// Debug.Log("Atlas Path: " + path);
}
}
}
}
}
if(atlasAsset == null)
atlasAsset = IngestSpineAtlas(atlasText);
return IngestSpineProject(spineJson, atlasAsset);
}
static AtlasAsset IngestSpineAtlas(TextAsset atlasText){
if(atlasText == null){
Debug.LogWarning("Atlas source cannot be null!");
return null;
}
string primaryName = Path.GetFileNameWithoutExtension(atlasText.name).Replace(".atlas", "");
string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(atlasText));
string atlasPath = assetPath + "/" + primaryName + "_Atlas.asset";
if(File.Exists(atlasPath))
return (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
AtlasAsset atlasAsset = AtlasAsset.CreateInstance<AtlasAsset>();
atlasAsset.atlasFile = atlasText;
if(spineJson != null && atlasText != null){ string[] atlasLines = atlasText.text.Split('\n');
List<string> pageFiles = new List<string>();
for(int i = 0; i < atlasLines.Length-1; i++){
if(atlasLines[i].Length == 0)
pageFiles.Add(atlasLines[i+1]);
}
atlasAsset.materials = new Material[pageFiles.Count];
for(int i = 0; i < pageFiles.Count; i++){
string texturePath = assetPath + "/" + pageFiles[i];
Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
AssetPreview.GetMiniTypeThumbnail(typeof(bool)); TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath);
texImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor;
AtlasAsset atlasAsset = AtlasAsset.CreateInstance<AtlasAsset>(); texImporter.mipmapEnabled = false;
atlasAsset.atlasFile = atlasText; EditorUtility.SetDirty(texImporter);
AssetDatabase.ImportAsset(texturePath);
string[] atlasLines = atlasText.text.Split('\n');
List<string> pageFiles = new List<string>();
for(int i = 0; i < atlasLines.Length-1; i++){
if(atlasLines[i].Length == 0)
pageFiles.Add(atlasLines[i+1]);
}
atlasAsset.materials = new Material[pageFiles.Count];
for(int i = 0; i < pageFiles.Count; i++){
string texturePath = assetPath + "/" + pageFiles[i];
Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
TextureImporter texImporter = (TextureImporter)TextureImporter.GetAtPath(texturePath);
texImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor;
texImporter.mipmapEnabled = false;
EditorUtility.SetDirty(texImporter);
AssetDatabase.ImportAsset(texturePath);
AssetDatabase.SaveAssets();
string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]);
//because this looks silly
if(pageName == primaryName && pageFiles.Count == 1)
pageName = "Material";
string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat";
Material mat = new Material(Shader.Find(defaultShader));
mat.mainTexture = texture;
AssetDatabase.CreateAsset(mat, materialPath);
AssetDatabase.SaveAssets();
atlasAsset.materials[i] = mat;
}
AssetDatabase.CreateAsset(atlasAsset, assetPath + "/" + primaryName + "_Atlas.asset");
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]);
//because this looks silly
if(pageName == primaryName && pageFiles.Count == 1)
pageName = "Material";
string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat";
Material mat = new Material(Shader.Find(defaultShader));
mat.mainTexture = texture;
AssetDatabase.CreateAsset(mat, materialPath);
AssetDatabase.SaveAssets();
atlasAsset.materials[i] = mat;
}
AssetDatabase.CreateAsset(atlasAsset, atlasPath);
AssetDatabase.SaveAssets();
return (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
}
static SkeletonDataAsset IngestSpineProject(TextAsset spineJson, AtlasAsset atlasAsset = null){
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(spineJson));
if(spineJson != null && atlasAsset != null){
SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>(); SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
skelDataAsset.atlasAsset = atlasAsset; skelDataAsset.atlasAsset = atlasAsset;
skelDataAsset.skeletonJSON = spineJson; skelDataAsset.skeletonJSON = spineJson;
@ -213,10 +349,12 @@ public static class SpineEditorUtilities {
AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset"); AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset");
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
return skelDataAsset;
} }
else{ else{
EditorUtility.DisplayDialog("Error!", "Atlas file not found in selection!", "OK"); EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and Atlas TextAsset", "OK");
return; return null;
} }
} }
@ -288,3 +426,5 @@ public static class SpineEditorUtilities {
} }

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f834d5cd806ec4645915ac315edbdc60
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData: