|
@@ -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 {
|
|
|
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+
|