Spine.Unity namespace and some editor tweaks.

This commit is contained in:
pharan 2016-03-19 16:54:43 +08:00
parent 50a0960a7d
commit 9e8fdeef6c
9 changed files with 1226 additions and 1174 deletions

View File

@ -28,126 +28,124 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
//#define BAKE_ALL_BUTTON
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.IO;
using UnityEditor;
using UnityEngine;
using Spine;
namespace Spine.Unity {
[CustomEditor(typeof(AtlasAsset))]
public class AtlasAssetInspector : Editor {
private SerializedProperty atlasFile, materials;
private AtlasAsset atlasAsset;
private List<bool> baked;
private List<GameObject> bakedObjects;
[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 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);
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);
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;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
override public void OnInspectorGUI () {
serializedObject.Update();
AtlasAsset asset = (AtlasAsset)target;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(atlasFile);
EditorGUILayout.PropertyField(materials, true);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
if (materials.arraySize == 0) {
EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning));
return;
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
Material mat = (Material)prop.objectReferenceValue;
if (mat == null) {
EditorGUILayout.LabelField(new GUIContent("Error: Materials cannot be null", SpineEditorUtilities.Icons.warning));
if (materials.arraySize == 0) {
EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning));
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(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
EditorGUI.indentLevel++;
AtlasPage lastPage = null;
for (int i = 0; i < regions.Count; i++) {
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));
}
for (int i = 0; i < materials.arraySize; i++) {
SerializedProperty prop = materials.GetArrayElementAtIndex(i);
Material mat = (Material)prop.objectReferenceValue;
if (mat == null) {
EditorGUILayout.LabelField(new GUIContent("Error: Materials cannot be null", SpineEditorUtilities.Icons.warning));
return;
}
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 (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(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
EditorGUI.indentLevel++;
AtlasPage lastPage = null;
for (int i = 0; i < regions.Count; i++) {
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));
}
}
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) {
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);
@ -160,18 +158,62 @@ public class AtlasAssetInspector : Editor {
case false:
//do nothing
break;
}
}
}
GUILayout.EndHorizontal();
}
GUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
}
EditorGUI.indentLevel--;
if (serializedObject.ApplyModifiedProperties() ||
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
) {
asset.Reset();
#if BAKE_ALL_BUTTON
// Check state
bool allBaked = true;
bool allUnbaked = true;
for (int i = 0; i < regions.Count; i++) {
allBaked &= baked[i];
allUnbaked &= !baked[i];
}
if (!allBaked && GUILayout.Button("Bake All")) {
for (int i = 0; i < regions.Count; i++) {
if (!baked[i]) {
baked[i] = true;
bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
}
}
} else if (!allUnbaked && GUILayout.Button("Unbake All")) {
bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
switch (unbakeResult) {
case true:
//delete
for (int i = 0; i < regions.Count; i++) {
if (baked[i]) {
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;
}
}
#endif
}
if (serializedObject.ApplyModifiedProperties() ||
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
) {
asset.Reset();
}
}
}
}

View File

@ -28,57 +28,57 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using Spine;
public class Menus {
[MenuItem("Assets/Create/Spine Atlas")]
static public void CreateAtlas () {
CreateAsset<AtlasAsset>("New Atlas");
}
[MenuItem("Assets/Create/Spine SkeletonData")]
static public void CreateSkeletonData () {
CreateAsset<SkeletonDataAsset>("New SkeletonData");
}
static private void CreateAsset <T> (String name) where T : ScriptableObject {
var dir = "Assets/";
var selected = Selection.activeObject;
if (selected != null) {
var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID());
if (assetDir.Length > 0 && Directory.Exists(assetDir))
dir = assetDir + "/";
namespace Spine.Unity {
public static class Menus {
[MenuItem("Assets/Create/Spine Atlas")]
static public void CreateAtlas () {
CreateAsset<AtlasAsset>("New Atlas");
}
ScriptableObject asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, dir + name + ".asset");
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () {
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
}
[MenuItem("Assets/Create/Spine SkeletonData")]
static public void CreateSkeletonData () {
CreateAsset<SkeletonDataAsset>("New SkeletonData");
}
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () {
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
}
static private void CreateAsset <T> (String name) where T : ScriptableObject {
var dir = "Assets/";
var selected = Selection.activeObject;
if (selected != null) {
var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID());
if (assetDir.Length > 0 && Directory.Exists(assetDir))
dir = assetDir + "/";
}
ScriptableObject asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, dir + name + ".asset");
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = asset;
}
static public void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
var parentGameObject = Selection.activeObject as GameObject;
var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
static public void CreateSkeletonRendererGameObject () {
CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
}
var gameObject = new GameObject("New SkeletonRenderer", typeof(T));
gameObject.transform.SetParent(parentTransform, false);
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
EditorGUIUtility.PingObject(Selection.activeObject);
[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
static public void CreateSkeletonAnimationGameObject () {
CreateSpineGameObject<SkeletonAnimation>("New SkeletonAnimation");
}
static public void CreateSpineGameObject<T> (string name) where T : MonoBehaviour {
var parentGameObject = Selection.activeObject as GameObject;
var parentTransform = parentGameObject == null ? null : parentGameObject.transform;
var gameObject = new GameObject("New SkeletonRenderer", typeof(T));
gameObject.transform.SetParent(parentTransform, false);
EditorUtility.FocusProjectWindow();
Selection.activeObject = gameObject;
EditorGUIUtility.PingObject(Selection.activeObject);
}
}
}

View File

@ -28,83 +28,85 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using UnityEditor;
using UnityEngine;
using Spine;
[CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale, autoReset;
protected bool m_isPrefab;
protected bool wasAnimationNameChanged;
namespace Spine.Unity {
[CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale, autoReset;
protected bool m_isPrefab;
protected bool wasAnimationNameChanged;
protected override void OnEnable () {
base.OnEnable();
animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale");
protected override void OnEnable () {
base.OnEnable();
animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale");
if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
m_isPrefab = true;
}
protected override void DrawInspectorGUI () {
base.DrawInspectorGUI();
SkeletonAnimation component = (SkeletonAnimation)target;
if (!component.valid)
return;
if (wasAnimationNameChanged) {
if (!Application.isPlaying) {
if (component.state != null) component.state.ClearTrack(0);
component.skeleton.SetToSetupPose();
}
Spine.Animation animationToUse = component.skeleton.Data.FindAnimation(animationName.stringValue);
if (!Application.isPlaying) {
if (animationToUse != null) animationToUse.Apply(component.skeleton, 0f, 0f, false, null);
component.Update();
component.LateUpdate();
SceneView.RepaintAll();
} else {
if (animationToUse != null)
component.state.SetAnimation(0, animationToUse, loop.boolValue);
else
component.state.ClearTrack(0);
}
wasAnimationNameChanged = false;
if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
m_isPrefab = true;
}
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
if (Application.isPlaying) {
TrackEntry current = component.state.GetCurrent(0);
if (current != null) {
if (component.AnimationName != animationName.stringValue) {
animationName.stringValue = current.Animation.Name;
protected override void DrawInspectorGUI () {
base.DrawInspectorGUI();
SkeletonAnimation component = (SkeletonAnimation)target;
if (!component.valid)
return;
if (wasAnimationNameChanged) {
if (!Application.isPlaying) {
if (component.state != null) component.state.ClearTrack(0);
component.skeleton.SetToSetupPose();
}
Spine.Animation animationToUse = component.skeleton.Data.FindAnimation(animationName.stringValue);
if (!Application.isPlaying) {
if (animationToUse != null) animationToUse.Apply(component.skeleton, 0f, 0f, false, null);
component.Update();
component.LateUpdate();
SceneView.RepaintAll();
} else {
if (animationToUse != null)
component.state.SetAnimation(0, animationToUse, loop.boolValue);
else
component.state.ClearTrack(0);
}
wasAnimationNameChanged = false;
}
// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
if (Application.isPlaying) {
TrackEntry current = component.state.GetCurrent(0);
if (current != null) {
if (component.AnimationName != animationName.stringValue) {
animationName.stringValue = current.Animation.Name;
}
}
}
}
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName);
wasAnimationNameChanged |= EditorGUI.EndChangeCheck();
EditorGUILayout.PropertyField(loop);
EditorGUILayout.PropertyField(timeScale);
component.timeScale = Math.Max(component.timeScale, 0);
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(animationName);
wasAnimationNameChanged |= EditorGUI.EndChangeCheck();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(loop);
EditorGUILayout.PropertyField(timeScale);
component.timeScale = Math.Max(component.timeScale, 0);
if (!m_isPrefab) {
if (component.GetComponent<SkeletonUtility>() == null) {
if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
component.gameObject.AddComponent<SkeletonUtility>();
EditorGUILayout.Space();
if (!m_isPrefab) {
if (component.GetComponent<SkeletonUtility>() == null) {
if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
component.gameObject.AddComponent<SkeletonUtility>();
}
}
}
}

View File

@ -1,5 +1,3 @@
/*****************************************************************************
* SkeletonAnimatorInspector created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
@ -7,37 +5,38 @@
using System;
using UnityEditor;
using UnityEngine;
using Spine;
[CustomEditor(typeof(SkeletonAnimator))]
public class SkeletonAnimatorInspector : SkeletonRendererInspector {
protected SerializedProperty layerMixModes;
protected bool isPrefab;
protected override void OnEnable () {
base.OnEnable();
layerMixModes = serializedObject.FindProperty("layerMixModes");
namespace Spine.Unity {
[CustomEditor(typeof(SkeletonAnimator))]
public class SkeletonAnimatorInspector : SkeletonRendererInspector {
protected SerializedProperty layerMixModes;
protected bool isPrefab;
protected override void OnEnable () {
base.OnEnable();
layerMixModes = serializedObject.FindProperty("layerMixModes");
if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
isPrefab = true;
}
if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
isPrefab = true;
}
protected override void DrawInspectorGUI () {
base.DrawInspectorGUI();
protected override void DrawInspectorGUI () {
base.DrawInspectorGUI();
EditorGUILayout.PropertyField(layerMixModes, true);
EditorGUILayout.PropertyField(layerMixModes, true);
SkeletonAnimator component = (SkeletonAnimator)target;
if (!component.valid)
return;
SkeletonAnimator component = (SkeletonAnimator)target;
if (!component.valid)
return;
EditorGUILayout.Space();
EditorGUILayout.Space();
if (!isPrefab) {
if (component.GetComponent<SkeletonUtility>() == null) {
if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
component.gameObject.AddComponent<SkeletonUtility>();
if (!isPrefab) {
if (component.GetComponent<SkeletonUtility>() == null) {
if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
component.gameObject.AddComponent<SkeletonUtility>();
}
}
}
}
}
}
}

View File

@ -33,118 +33,121 @@ using System;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(SkeletonRenderer))]
public class SkeletonRendererInspector : Editor {
protected static bool advancedFoldout;
namespace Spine.Unity {
[CustomEditor(typeof(SkeletonRenderer))]
public class SkeletonRendererInspector : Editor {
protected static bool advancedFoldout;
protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators, front, zSpacing;
protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators, front, zSpacing;
protected SpineInspectorUtility.SerializedSortingProperties sortingProperties;
protected SpineInspectorUtility.SerializedSortingProperties sortingProperties;
protected virtual void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
initialSkinName = serializedObject.FindProperty("initialSkinName");
normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents");
meshes = serializedObject.FindProperty("renderMeshes");
immutableTriangles = serializedObject.FindProperty("immutableTriangles");
submeshSeparators = serializedObject.FindProperty("submeshSeparators");
front = serializedObject.FindProperty("frontFacing");
zSpacing = serializedObject.FindProperty("zSpacing");
protected virtual void OnEnable () {
SpineEditorUtilities.ConfirmInitialization();
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
initialSkinName = serializedObject.FindProperty("initialSkinName");
normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents");
meshes = serializedObject.FindProperty("renderMeshes");
immutableTriangles = serializedObject.FindProperty("immutableTriangles");
submeshSeparators = serializedObject.FindProperty("submeshSeparators");
front = serializedObject.FindProperty("frontFacing");
zSpacing = serializedObject.FindProperty("zSpacing");
var renderer = ((SkeletonRenderer)target).GetComponent<Renderer>();
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(renderer);
}
var renderer = ((SkeletonRenderer)target).GetComponent<Renderer>();
sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(renderer);
}
protected virtual void DrawInspectorGUI () {
SkeletonRenderer component = (SkeletonRenderer)target;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(skeletonDataAsset);
float reloadWidth = GUI.skin.label.CalcSize(new GUIContent("Reload")).x + 20;
if (GUILayout.Button("Reload", GUILayout.Width(reloadWidth))) {
if (component.skeletonDataAsset != null) {
foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) {
if (aa != null)
aa.Reset();
protected virtual void DrawInspectorGUI () {
SkeletonRenderer component = (SkeletonRenderer)target;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(skeletonDataAsset);
float reloadWidth = GUI.skin.label.CalcSize(new GUIContent("Reload")).x + 20;
if (GUILayout.Button("Reload", GUILayout.Width(reloadWidth))) {
if (component.skeletonDataAsset != null) {
foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) {
if (aa != null)
aa.Reset();
}
component.skeletonDataAsset.Reset();
}
component.skeletonDataAsset.Reset();
component.Initialize(true);
}
component.Initialize(true);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndHorizontal();
if (!component.valid) {
component.Initialize(true);
component.LateUpdate();
if (!component.valid)
return;
}
// Initial skin name.
{
String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0;
for (int i = 0; i < skins.Length; i++) {
String skinNameString = component.skeleton.Data.Skins.Items[i].Name;
skins[i] = skinNameString;
if (skinNameString == initialSkinName.stringValue)
skinIndex = i;
if (!component.valid) {
component.Initialize(true);
component.LateUpdate();
if (!component.valid)
return;
}
skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
initialSkinName.stringValue = skins[skinIndex];
}
EditorGUILayout.Space();
// Sorting Layers
{
SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);
}
// More Render Options...
{
advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
if(advancedFoldout) {
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(submeshSeparators, true);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(meshes,
new GUIContent("Render Mesh Attachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
EditorGUILayout.PropertyField(immutableTriangles,
new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
EditorGUILayout.Space();
const float MinZSpacing = -0.1f;
const float MaxZSpacing = 0f;
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);
if (normals != null) {
EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents);
// Initial skin name.
{
String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0;
for (int i = 0; i < skins.Length; i++) {
String skinNameString = component.skeleton.Data.Skins.Items[i].Name;
skins[i] = skinNameString;
if (skinNameString == initialSkinName.stringValue)
skinIndex = i;
}
if (front != null) {
EditorGUILayout.PropertyField(front);
}
skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
initialSkinName.stringValue = skins[skinIndex];
}
EditorGUILayout.Separator();
EditorGUI.indentLevel--;
EditorGUILayout.Space();
// Sorting Layers
{
SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);
}
// More Render Options...
{
advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
if(advancedFoldout) {
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(submeshSeparators, true);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(meshes,
new GUIContent("Render Mesh Attachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
EditorGUILayout.PropertyField(immutableTriangles,
new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
EditorGUILayout.Space();
const float MinZSpacing = -0.1f;
const float MaxZSpacing = 0f;
EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);
if (normals != null) {
EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents);
}
if (front != null) {
EditorGUILayout.PropertyField(front);
}
EditorGUILayout.Separator();
EditorGUI.indentLevel--;
}
}
}
}
override public void OnInspectorGUI () {
serializedObject.Update();
DrawInspectorGUI();
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying)
((SkeletonRenderer)target).Initialize(true);
override public void OnInspectorGUI () {
serializedObject.Update();
DrawInspectorGUI();
if (serializedObject.ApplyModifiedProperties() ||
(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying)
((SkeletonRenderer)target).Initialize(true);
}
}
}
}
}
}

View File

@ -34,59 +34,62 @@ using System.Collections;
using UnityEditor;
using System.Reflection;
public static class SpineInspectorUtility {
#region Sorting Layer Field Helpers
static readonly GUIContent SortingLayerLabel = new GUIContent("Sorting Layer");
static readonly GUIContent OrderInLayerLabel = new GUIContent("Order in Layer");
namespace Spine.Unity {
public static class SpineInspectorUtility {
static MethodInfo m_SortingLayerFieldMethod;
static MethodInfo SortingLayerFieldMethod {
get {
if (m_SortingLayerFieldMethod == null)
m_SortingLayerFieldMethod = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new System.Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
#region Sorting Layer Field Helpers
static readonly GUIContent SortingLayerLabel = new GUIContent("Sorting Layer");
static readonly GUIContent OrderInLayerLabel = new GUIContent("Order in Layer");
return m_SortingLayerFieldMethod;
}
}
static MethodInfo m_SortingLayerFieldMethod;
static MethodInfo SortingLayerFieldMethod {
get {
if (m_SortingLayerFieldMethod == null)
m_SortingLayerFieldMethod = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new System.Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
public struct SerializedSortingProperties {
public SerializedObject renderer;
public SerializedProperty sortingLayerID;
public SerializedProperty sortingOrder;
public SerializedSortingProperties (Renderer r) {
renderer = new SerializedObject(r);
sortingLayerID = renderer.FindProperty("m_SortingLayerID");
sortingOrder = renderer.FindProperty("m_SortingOrder");
}
public void ApplyModifiedProperties () {
renderer.ApplyModifiedProperties();
}
}
public static void SortingPropertyFields (SerializedSortingProperties prop, bool applyModifiedProperties) {
if (applyModifiedProperties) {
EditorGUI.BeginChangeCheck();
SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder);
if(EditorGUI.EndChangeCheck()) {
prop.ApplyModifiedProperties();
EditorUtility.SetDirty(prop.renderer.targetObject);
return m_SortingLayerFieldMethod;
}
} else {
SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder);
}
}
public static void SortingPropertyFields (SerializedProperty m_SortingLayerID, SerializedProperty m_SortingOrder) {
if (SpineInspectorUtility.SortingLayerFieldMethod != null && m_SortingLayerID != null) {
SpineInspectorUtility.SortingLayerFieldMethod.Invoke(null, new object[] { SortingLayerLabel, m_SortingLayerID, EditorStyles.popup } );
} else {
EditorGUILayout.PropertyField(m_SortingLayerID);
}
EditorGUILayout.PropertyField(m_SortingOrder, OrderInLayerLabel);
public struct SerializedSortingProperties {
public SerializedObject renderer;
public SerializedProperty sortingLayerID;
public SerializedProperty sortingOrder;
public SerializedSortingProperties (Renderer r) {
renderer = new SerializedObject(r);
sortingLayerID = renderer.FindProperty("m_SortingLayerID");
sortingOrder = renderer.FindProperty("m_SortingOrder");
}
public void ApplyModifiedProperties () {
renderer.ApplyModifiedProperties();
}
}
public static void SortingPropertyFields (SerializedSortingProperties prop, bool applyModifiedProperties) {
if (applyModifiedProperties) {
EditorGUI.BeginChangeCheck();
SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder);
if(EditorGUI.EndChangeCheck()) {
prop.ApplyModifiedProperties();
EditorUtility.SetDirty(prop.renderer.targetObject);
}
} else {
SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder);
}
}
public static void SortingPropertyFields (SerializedProperty m_SortingLayerID, SerializedProperty m_SortingOrder) {
if (SpineInspectorUtility.SortingLayerFieldMethod != null && m_SortingLayerID != null) {
SpineInspectorUtility.SortingLayerFieldMethod.Invoke(null, new object[] { SortingLayerLabel, m_SortingLayerID, EditorStyles.popup } );
} else {
EditorGUILayout.PropertyField(m_SortingLayerID);
}
EditorGUILayout.PropertyField(m_SortingOrder, OrderInLayerLabel);
}
#endregion
}
#endregion
}

View File

@ -149,7 +149,7 @@ namespace Spine.Unity {
EditorGUIUtility.PingObject(Selection.activeObject);
}
[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 0)]
[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 10)]
static void InstantiateSkeletonGraphic () {
Object[] arr = Selection.objects;
foreach (Object o in arr) {
@ -161,7 +161,7 @@ namespace Spine.Unity {
}
}
[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 0)]
[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 10)]
static bool ValidateInstantiateSkeletonGraphic () {
Object[] arr = Selection.objects;

View File

@ -212,7 +212,7 @@ namespace Spine.Unity {
spineMeshGenerator.Scale = canvas.referencePixelsPerUnit; // TODO: move this to a listener to of the canvas?
canvasRenderer.SetMesh(spineMeshGenerator.GenerateMesh(skeleton));
this.UpdateMaterial();
//this.UpdateMaterial(); // TODO: This allocates memory.
}
}
#endregion