Эх сурвалжийг харах

Spine Editor Utility Drag and Drop importer

Fenrisul 11 жил өмнө
parent
commit
8a68f5a75a

+ 14 - 7
spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs

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

+ 183 - 43
spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs

@@ -1,4 +1,6 @@
-using UnityEngine;
+#pragma warning disable 0219
+
+using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System.Collections.Generic;
@@ -7,7 +9,7 @@ using System.Text;
 using Spine;
 
 [InitializeOnLoad]
-public static class SpineEditorUtilities {
+public class SpineEditorUtilities : AssetPostprocessor {
 
 	public static class Icons{
 		public static Texture2D skeleton;
@@ -122,10 +124,12 @@ public static class SpineEditorUtilities {
 	}
 	
 	[MenuItem("Assets/Spine/Ingest")]
-	static void IngestSpineProject(){
+	static void IngestSpineProjectFromSelection(){
 		TextAsset spineJson = null;
 		TextAsset atlasText = null;
-		
+
+		List<TextAsset> spineJsonList = new List<TextAsset>();
+
 		foreach(UnityEngine.Object o in Selection.objects){
 			if(o.GetType() != typeof(TextAsset))
 				continue;
@@ -150,58 +154,190 @@ public static class SpineEditorUtilities {
 			string atlasPath = assetPath + "/" + primaryName + ".atlas.txt";
 			atlasText = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
 		}
-		
-		if(spineJson != null && atlasText != null){
-			
-			AssetPreview.GetMiniTypeThumbnail(typeof(bool));
-			
-			AtlasAsset atlasAsset = AtlasAsset.CreateInstance<AtlasAsset>();
-			atlasAsset.atlasFile = atlasText;
 
+		AtlasAsset atlasAsset = IngestSpineAtlas(atlasText);
 
+		IngestSpineProject(spineJson, atlasAsset);
+	}
 
-			
-			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]);
+	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);
+				}
 			}
+		}
+	}
 
-			atlasAsset.materials = new Material[pageFiles.Count];
+	static bool IsSpineJSON(TextAsset asset){
+		object obj = Json.Deserialize( new StringReader(asset.text));
+		if(obj == null){
+			Debug.LogError("Is not valid JSON");
+			return false;
+		}
 
-			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();
+		Dictionary<string, object> root = (Dictionary<string, object>)obj;
+
+		if(!root.ContainsKey("skeleton"))
+			return false;
 
-				string pageName = Path.GetFileNameWithoutExtension(pageFiles[i]);
+		Dictionary<string, object> skeletonInfo = (Dictionary<string, object>)root["skeleton"];
 
-				//because this looks silly
-				if(pageName == primaryName && pageFiles.Count == 1)
-					pageName = "Material";
+		string spineVersion = (string)skeletonInfo["spine"];
 
-				string materialPath = assetPath + "/" + primaryName + "_" + pageName + ".mat";
+		//TODO:  reject old versions
+
+		return true;
+
+	}
 
-				Material mat = new Material(Shader.Find(defaultShader));
+	static SkeletonDataAsset AutoIngestSpineProject(TextAsset spineJson, Object atlasSource = null){
+		TextAsset atlasText = null;
+		AtlasAsset atlasAsset = null;
 
-				mat.mainTexture = texture;
-				
-				AssetDatabase.CreateAsset(mat, materialPath);
-				AssetDatabase.SaveAssets();
-				
-				atlasAsset.materials[i] = mat;
+		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));
 			
-			AssetDatabase.CreateAsset(atlasAsset, assetPath + "/" + primaryName + "_Atlas.asset");
+			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;
+		
+		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, 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>();
 			skelDataAsset.atlasAsset = atlasAsset;
 			skelDataAsset.skeletonJSON = spineJson;
@@ -213,10 +349,12 @@ public static class SpineEditorUtilities {
 
 			AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset");
 			AssetDatabase.SaveAssets();
+
+			return skelDataAsset;
 		}
 		else{
-			EditorUtility.DisplayDialog("Error!", "Atlas file not found in selection!", "OK");
-			return;
+			EditorUtility.DisplayDialog("Error!", "Must specify both Spine JSON and Atlas TextAsset", "OK");
+			return null;
 		}
 	}
 
@@ -288,3 +426,5 @@ public static class SpineEditorUtilities {
 
 
 }
+
+

+ 8 - 0
spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs.meta

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