mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 17:26:01 +08:00
Spine Editor Utility Drag and Drop importer
This commit is contained in:
parent
a7bf0ca963
commit
8a68f5a75a
@ -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;
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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, assetPath + "/" + primaryName + "_Atlas.asset");
|
||||
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 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f834d5cd806ec4645915ac315edbdc60
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
Loading…
x
Reference in New Issue
Block a user