mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
778bd123fd
@ -70,6 +70,77 @@ public class AtlasAsset : ScriptableObject {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite GenerateSprite (string name, out Material material) {
|
||||
AtlasRegion region = atlas.FindRegion(name);
|
||||
|
||||
Sprite sprite = null;
|
||||
material = null;
|
||||
|
||||
if (region != null) {
|
||||
//sprite.rect
|
||||
}
|
||||
|
||||
return sprite;
|
||||
}
|
||||
|
||||
public Mesh GenerateMesh(string name, Mesh mesh, out Material material, float scale = 0.01f){
|
||||
AtlasRegion region = atlas.FindRegion(name);
|
||||
material = null;
|
||||
if (region != null) {
|
||||
if (mesh == null) {
|
||||
mesh = new Mesh();
|
||||
mesh.name = name;
|
||||
}
|
||||
|
||||
Vector3[] verts = new Vector3[4];
|
||||
Vector2[] uvs = new Vector2[4];
|
||||
Color[] colors = new Color[4]{Color.white, Color.white, Color.white, Color.white};
|
||||
int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
|
||||
|
||||
float left, right, top, bottom;
|
||||
left = region.width / -2f;
|
||||
right = left * -1f;
|
||||
top = region.height / 2f;
|
||||
bottom = top * -1;
|
||||
|
||||
verts[0] = new Vector3(left, bottom, 0) * scale;
|
||||
verts[1] = new Vector3(left, top, 0) * scale;
|
||||
verts[2] = new Vector3(right, top, 0) * scale;
|
||||
verts[3] = new Vector3(right, bottom, 0) * scale;
|
||||
float u, v, u2, v2;
|
||||
u = region.u;
|
||||
v = region.v;
|
||||
u2 = region.u2;
|
||||
v2 = region.v2;
|
||||
|
||||
if (!region.rotate) {
|
||||
uvs[0] = new Vector2(u, v2);
|
||||
uvs[1] = new Vector2(u, v);
|
||||
uvs[2] = new Vector2(u2, v);
|
||||
uvs[3] = new Vector2(u2, v2);
|
||||
} else {
|
||||
uvs[0] = new Vector2(u2, v2);
|
||||
uvs[1] = new Vector2(u, v2);
|
||||
uvs[2] = new Vector2(u, v);
|
||||
uvs[3] = new Vector2(u2, v);
|
||||
}
|
||||
|
||||
mesh.triangles = new int[0];
|
||||
mesh.vertices = verts;
|
||||
mesh.uv = uvs;
|
||||
mesh.colors = colors;
|
||||
mesh.triangles = triangles;
|
||||
mesh.RecalculateNormals();
|
||||
mesh.RecalculateBounds();
|
||||
|
||||
material = (Material)region.page.rendererObject;
|
||||
} else {
|
||||
mesh = null;
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class MaterialsTextureLoader : TextureLoader {
|
||||
|
||||
@ -34,6 +34,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
@ -42,13 +43,43 @@ using Spine;
|
||||
[CustomEditor(typeof(AtlasAsset))]
|
||||
public class AtlasAssetInspector : Editor {
|
||||
private SerializedProperty atlasFile, materials;
|
||||
private AtlasAsset atlasAsset;
|
||||
private List<bool> baked;
|
||||
private List<GameObject> bakedObjects;
|
||||
|
||||
void OnEnable () {
|
||||
SpineEditorUtilities.ConfirmInitialization();
|
||||
atlasFile = serializedObject.FindProperty("atlasFile");
|
||||
materials = serializedObject.FindProperty("materials");
|
||||
atlasAsset = (AtlasAsset)target;
|
||||
UpdateBakedList();
|
||||
}
|
||||
|
||||
void UpdateBakedList () {
|
||||
AtlasAsset asset = (AtlasAsset)target;
|
||||
baked = new List<bool>();
|
||||
bakedObjects = new List<GameObject>();
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
Atlas atlas = asset.GetAtlas();
|
||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
|
||||
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
AtlasRegion region = regions[i];
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||
baked.Add(prefab != null);
|
||||
bakedObjects.Add(prefab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
override public void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
AtlasAsset asset = (AtlasAsset)target;
|
||||
@ -72,22 +103,71 @@ public class AtlasAssetInspector : Editor {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (atlasFile.objectReferenceValue != null) {
|
||||
Atlas atlas = asset.GetAtlas();
|
||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||
EditorGUILayout.LabelField("Regions");
|
||||
EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
|
||||
EditorGUI.indentLevel++;
|
||||
AtlasPage lastPage = null;
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
EditorGUILayout.LabelField(regions[i].name);
|
||||
if (lastPage != regions[i].page) {
|
||||
if (lastPage != null) {
|
||||
EditorGUILayout.Separator();
|
||||
EditorGUILayout.Separator();
|
||||
}
|
||||
lastPage = regions[i].page;
|
||||
Material mat = ((Material)lastPage.rendererObject);
|
||||
if (mat != null) {
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
} else {
|
||||
EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
|
||||
}
|
||||
}
|
||||
GUILayout.BeginHorizontal();
|
||||
{
|
||||
//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
|
||||
bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft(" " + regions[i].name, baked[i]);
|
||||
if(baked[i]){
|
||||
EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
|
||||
}
|
||||
if (result && !baked[i]) {
|
||||
//bake
|
||||
baked[i] = true;
|
||||
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
|
||||
EditorGUIUtility.PingObject(bakedObjects[i]);
|
||||
} else if (!result && baked[i]) {
|
||||
//unbake
|
||||
bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
|
||||
switch (unbakeResult) {
|
||||
case true:
|
||||
//delete
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
|
||||
AssetDatabase.DeleteAsset(bakedPrefabPath);
|
||||
baked[i] = false;
|
||||
break;
|
||||
case false:
|
||||
//do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
|
||||
if (serializedObject.ApplyModifiedProperties() ||
|
||||
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
|
||||
) {
|
||||
|
||||
@ -856,6 +856,7 @@ public static class SkeletonBaker {
|
||||
var ev = events[i];
|
||||
|
||||
AnimationEvent ae = new AnimationEvent();
|
||||
//TODO: Deal with Mecanim's zero-time missed event
|
||||
ae.time = frames[i];
|
||||
ae.functionName = ev.Data.Name;
|
||||
ae.messageOptions = eventOptions;
|
||||
@ -1457,4 +1458,4 @@ public static class SkeletonBaker {
|
||||
|
||||
return GetPathRecurse(b.Parent) + "/" + b.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +426,9 @@ public class SpineEditorUtilities : AssetPostprocessor {
|
||||
|
||||
|
||||
static bool CheckForValidAtlas (string atlasPath) {
|
||||
|
||||
return false;
|
||||
//////////////DEPRECATED - always check for new atlas data now
|
||||
/*
|
||||
string dir = Path.GetDirectoryName(atlasPath);
|
||||
TextAsset textAsset = (TextAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(TextAsset));
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(dir);
|
||||
@ -438,12 +440,37 @@ public class SpineEditorUtilities : AssetPostprocessor {
|
||||
var obj = AssetDatabase.LoadAssetAtPath(localPath, typeof(Object));
|
||||
if (obj is AtlasAsset) {
|
||||
var atlasAsset = (AtlasAsset)obj;
|
||||
if (atlasAsset.atlasFile == textAsset)
|
||||
if (atlasAsset.atlasFile == textAsset) {
|
||||
|
||||
|
||||
Atlas atlas = atlasAsset.GetAtlas();
|
||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
AtlasRegion region = regions[i];
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||
|
||||
if (prefab != null) {
|
||||
Debug.Log("Updating: " + region.name);
|
||||
BakeRegion(atlasAsset, region);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
static List<AtlasAsset> MultiAtlasDialog (List<string> requiredPaths, string initialDirectory, string header = "") {
|
||||
@ -657,9 +684,14 @@ public class SpineEditorUtilities : AssetPostprocessor {
|
||||
|
||||
AtlasAsset atlasAsset = (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
|
||||
|
||||
List<Material> vestigialMaterials = new List<Material>();
|
||||
|
||||
if (atlasAsset == null)
|
||||
atlasAsset = AtlasAsset.CreateInstance<AtlasAsset>();
|
||||
else {
|
||||
foreach (Material m in atlasAsset.materials)
|
||||
vestigialMaterials.Add(m);
|
||||
}
|
||||
|
||||
atlasAsset.atlasFile = atlasText;
|
||||
|
||||
@ -702,6 +734,8 @@ public class SpineEditorUtilities : AssetPostprocessor {
|
||||
if (mat == null) {
|
||||
mat = new Material(Shader.Find(defaultShader));
|
||||
AssetDatabase.CreateAsset(mat, materialPath);
|
||||
} else {
|
||||
vestigialMaterials.Remove(mat);
|
||||
}
|
||||
|
||||
mat.mainTexture = texture;
|
||||
@ -712,16 +746,96 @@ public class SpineEditorUtilities : AssetPostprocessor {
|
||||
atlasAsset.materials[i] = mat;
|
||||
}
|
||||
|
||||
for (int i = 0; i < vestigialMaterials.Count; i++)
|
||||
AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(vestigialMaterials[i]));
|
||||
|
||||
if (AssetDatabase.GetAssetPath(atlasAsset) == "")
|
||||
AssetDatabase.CreateAsset(atlasAsset, atlasPath);
|
||||
else
|
||||
atlasAsset.Reset();
|
||||
|
||||
EditorUtility.SetDirty(atlasAsset);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
|
||||
//iterate regions and bake marked
|
||||
Atlas atlas = atlasAsset.GetAtlas();
|
||||
FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
|
||||
List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
|
||||
bool hasBakedRegions = false;
|
||||
for (int i = 0; i < regions.Count; i++) {
|
||||
AtlasRegion region = regions[i];
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||
|
||||
if (prefab != null) {
|
||||
BakeRegion(atlasAsset, region, false);
|
||||
hasBakedRegions = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasBakedRegions) {
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
return (AtlasAsset)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(AtlasAsset));
|
||||
}
|
||||
|
||||
public static GameObject BakeRegion (AtlasAsset atlasAsset, AtlasRegion region, bool autoSave = true) {
|
||||
Atlas atlas = atlasAsset.GetAtlas();
|
||||
string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
|
||||
string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
|
||||
string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
|
||||
string bakedPrefabPath = Path.Combine(bakedDirPath, GetPathSafeRegionName(region) + ".prefab").Replace("\\", "/");
|
||||
|
||||
GameObject prefab = (GameObject)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(GameObject));
|
||||
GameObject root;
|
||||
Mesh mesh;
|
||||
bool isNewPrefab = false;
|
||||
|
||||
if (!Directory.Exists(bakedDirPath))
|
||||
Directory.CreateDirectory(bakedDirPath);
|
||||
|
||||
if (prefab == null) {
|
||||
root = new GameObject("temp", typeof(MeshFilter), typeof(MeshRenderer));
|
||||
prefab = (GameObject)PrefabUtility.CreatePrefab(bakedPrefabPath, root);
|
||||
isNewPrefab = true;
|
||||
Object.DestroyImmediate(root);
|
||||
}
|
||||
|
||||
mesh = (Mesh)AssetDatabase.LoadAssetAtPath(bakedPrefabPath, typeof(Mesh));
|
||||
|
||||
Material mat = null;
|
||||
mesh = atlasAsset.GenerateMesh(region.name, mesh, out mat);
|
||||
if (isNewPrefab) {
|
||||
AssetDatabase.AddObjectToAsset(mesh, prefab);
|
||||
prefab.GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(mesh);
|
||||
EditorUtility.SetDirty(prefab);
|
||||
|
||||
if (autoSave) {
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
|
||||
prefab.GetComponent<MeshRenderer>().sharedMaterial = mat;
|
||||
|
||||
return prefab;
|
||||
}
|
||||
|
||||
public static string GetPathSafeRegionName (AtlasRegion region) {
|
||||
return region.name.Replace("/", "_");
|
||||
}
|
||||
|
||||
static SkeletonDataAsset IngestSpineProject (TextAsset spineJson, params AtlasAsset[] atlasAssets) {
|
||||
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
|
||||
string assetPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(spineJson));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user