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

SkeletonGraphic Inspector and Edtor, small fixes.

pharan 9 жил өмнө
parent
commit
fe02e78681

+ 13 - 6
spine-unity/Assets/spine-unity/Editor/Menus.cs

@@ -61,17 +61,24 @@ public class Menus {
 		Selection.activeObject = asset;
 	}
 
-	[MenuItem("GameObject/Create Other/Spine SkeletonRenderer")]
+	[MenuItem("GameObject/Spine/SkeletonRenderer", false, 10)]
 	static public void CreateSkeletonRendererGameObject () {
-		GameObject gameObject = new GameObject("New SkeletonRenderer", typeof(SkeletonRenderer));
-		EditorUtility.FocusProjectWindow();
-		Selection.activeObject = gameObject;
+		CreateSpineGameObject<SkeletonRenderer>("New SkeletonRenderer");
 	}
 
-	[MenuItem("GameObject/Create Other/Spine SkeletonAnimation")]
+	[MenuItem("GameObject/Spine/SkeletonAnimation", false, 10)]
 	static public void CreateSkeletonAnimationGameObject () {
-		GameObject gameObject = new GameObject("New SkeletonAnimation", typeof(SkeletonAnimation));
+		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);
 	}
 }

+ 1 - 1
spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs

@@ -59,7 +59,7 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
 		
 		if (wasAnimationNameChanged) {
 			if (!Application.isPlaying) {
-				component.state.ClearTrack(0);
+				if (component.state != null) component.state.ClearTrack(0);
 				component.skeleton.SetToSetupPose();
 			}
 

+ 5 - 1
spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs

@@ -138,7 +138,11 @@ public class SkeletonRendererInspector : Editor {
 				EditorGUILayout.PropertyField(immutableTriangles,
 					new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
 				EditorGUILayout.Space();
-				EditorGUILayout.PropertyField(zSpacing);
+
+				const float MinZSpacing = 0f;
+				const float MaxZSpacing = 0.1f;
+				EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);
+
 				EditorGUILayout.PropertyField(normals);
 				EditorGUILayout.PropertyField(tangents);
 				EditorGUILayout.PropertyField(front);

+ 7 - 2
spine-unity/Assets/spine-unity/Mesh Generation/Simple/ArraysSimpleMeshGenerator.cs

@@ -35,7 +35,7 @@ using System.Collections;
 namespace Spine.Unity {
 	public class ArraysSimpleMeshGenerator : ISimpleMeshGenerator {
 		#region Settings
-		protected float scale;
+		protected float scale = 1f;
 		public float Scale {
 			get { return scale; }
 			set { scale = value; }
@@ -53,6 +53,9 @@ namespace Spine.Unity {
 		private int[] triangles;
 		#endregion
 
+		private Mesh lastGeneratedMesh;
+		public Mesh LastGeneratedMesh {	get { return lastGeneratedMesh; } }
+
 		public Mesh GenerateMesh (Skeleton skeleton) {
 			int totalVertexCount = 0; // size of vertex arrays
 			int totalTriangleCount = 0; // size of index array
@@ -309,10 +312,12 @@ namespace Spine.Unity {
 			mesh.uv = uvs;
 
 			Vector3 meshBoundsExtents = (meshBoundsMax - meshBoundsMin) * scale;
-			mesh.bounds = new Bounds(meshBoundsMin + meshBoundsExtents * 0.5f, meshBoundsExtents);
+			Vector3 meshCenter = (meshBoundsMin * scale) + meshBoundsExtents * 0.5f;
+			mesh.bounds = new Bounds(meshCenter, meshBoundsExtents);
 
 			mesh.SetTriangles(triangles, 0);
 
+			lastGeneratedMesh = mesh;
 			return mesh;
 		}
 

+ 1 - 0
spine-unity/Assets/spine-unity/Mesh Generation/Simple/ISimpleMeshGenerator.cs

@@ -6,5 +6,6 @@
 	public interface ISimpleMeshGenerator {
 		float Scale { set; }
 		UnityEngine.Mesh GenerateMesh (Spine.Skeleton skeleton);
+		UnityEngine.Mesh LastGeneratedMesh { get; }
 	}
 }

+ 4 - 0
spine-unity/Assets/spine-unity/Modules/Mesh Generation Samples/VertexHelperSpineMeshGenerator.cs

@@ -45,6 +45,9 @@ namespace Spine.Unity {
 
 		public int CurrentVertexCount { get { return this.positions.Count; } }
 
+		private Mesh lastGeneratedMesh;
+		public Mesh LastGeneratedMesh {	get { return lastGeneratedMesh; } }
+
 		public Mesh GenerateMesh (Skeleton skeleton) {
 			skeletonColor.r = skeleton.r;
 			skeletonColor.g = skeleton.g;
@@ -59,6 +62,7 @@ namespace Spine.Unity {
 
 			Mesh currentMesh = doubleBufferedMesh.GetNextMesh();
 			FillMesh(currentMesh);
+			lastGeneratedMesh = currentMesh;
 			return currentMesh;
 		}
 

+ 9 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 78bba472871bc624f8930d51dea6dd3d
+folderAsset: yes
+timeCreated: 1455570938
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 204 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs

@@ -0,0 +1,204 @@
+using UnityEngine;
+using System.Collections;
+
+using UnityEditor;
+using Spine;
+
+[CustomEditor(typeof(SkeletonGraphic))]
+public class SkeletonGraphicInspector : Editor {
+	SerializedProperty material_, color_;
+	SerializedProperty skeletonDataAsset_, initialSkinName_;
+	SerializedProperty startingAnimation_, startingLoop_, timeScale_, freeze_;
+	SerializedProperty raycastTarget_;
+
+	SkeletonGraphic thisSkeletonGraphic;
+
+	void OnEnable () {
+		var so = this.serializedObject;
+		thisSkeletonGraphic = target as SkeletonGraphic;
+
+		// MaskableGraphic
+		material_ = so.FindProperty("m_Material");
+		color_ = so.FindProperty("m_Color");
+		raycastTarget_ = so.FindProperty("m_RaycastTarget");
+
+		// SkeletonRenderer
+		skeletonDataAsset_ = so.FindProperty("skeletonDataAsset");
+		initialSkinName_ = so.FindProperty("initialSkinName");
+
+		// SkeletonAnimation
+		startingAnimation_ = so.FindProperty("startingAnimation");
+		startingLoop_ = so.FindProperty("startingLoop");
+		timeScale_ = so.FindProperty("timeScale");
+		freeze_ = so.FindProperty("freeze");
+	}
+
+
+	public override void OnInspectorGUI () {
+
+		var s = thisSkeletonGraphic;
+		s.skeletonDataAsset = SkeletonGraphicInspector.ObjectField<SkeletonDataAsset>(skeletonDataAsset_);
+		s.material = SkeletonGraphicInspector.ObjectField<Material>(material_);
+
+		EditorGUI.BeginChangeCheck();
+		thisSkeletonGraphic.color = EditorGUILayout.ColorField(color_.displayName, color_.colorValue);
+		if (EditorGUI.EndChangeCheck())
+			SkeletonGraphicInspector.ForceUpdateHack(thisSkeletonGraphic.transform);
+
+		if (thisSkeletonGraphic.skeletonDataAsset == null) {
+			EditorGUILayout.HelpBox("You need to assign a SkeletonDataAsset first.", MessageType.Info);
+			serializedObject.ApplyModifiedProperties();
+			serializedObject.Update();
+			return;
+		}
+
+		EditorGUILayout.Space();
+		EditorGUILayout.PropertyField(initialSkinName_);
+		EditorGUILayout.Space();
+		EditorGUILayout.LabelField("Animation", EditorStyles.boldLabel);
+		EditorGUILayout.PropertyField(startingAnimation_);
+		s.startingLoop = SkeletonGraphicInspector.BoolField(startingLoop_);
+		s.timeScale = EditorGUILayout.FloatField(timeScale_.displayName, timeScale_.floatValue);
+		EditorGUILayout.Space();
+		s.freeze = SkeletonGraphicInspector.BoolField(freeze_);
+		EditorGUILayout.Space();
+		EditorGUILayout.LabelField("UI", EditorStyles.boldLabel);
+		s.raycastTarget = SkeletonGraphicInspector.BoolField(raycastTarget_);
+
+	}
+
+	#region HAX - Thanks, Unity
+	// colors weren't updating in realtime in the custom inspector.
+	// Why the hell do I have to do this??
+	/// <summary>Use this when scene repaint and proper explicit update methods don't work.</summary>
+	public static void ForceUpdateHack (Transform t) {
+		var origValue = t.localScale;
+		t.localScale = new Vector3(11f, 22f, 33f);
+		t.localScale = origValue;
+	}
+
+	// Hack for Unity 5.3 problem with PropertyField
+	public static T ObjectField<T> (SerializedProperty property) where T : UnityEngine.Object {
+		return (T)EditorGUILayout.ObjectField(property.displayName, property.objectReferenceValue, typeof(T), false);
+	}
+
+	public static bool BoolField (SerializedProperty property) {
+		return EditorGUILayout.Toggle(property.displayName, property.boolValue);
+	}
+	#endregion
+
+	#region Menus
+	// Add a menu item called "Double Mass" to a Rigidbody's context menu.
+	[MenuItem ("CONTEXT/SkeletonGraphic/Match RectTransform with Mesh Bounds")]
+	static void MatchRectTransformWithBounds (MenuCommand command) {
+		var skeletonGraphic = (SkeletonGraphic)command.context;
+		var mesh =  skeletonGraphic.SpineMeshGenerator.LastGeneratedMesh;
+
+		var bounds = mesh.bounds;
+		var size = bounds.size;
+		var center = bounds.center;
+		var p = new Vector2(
+			0.5f - (center.x / size.x),
+			0.5f - (center.y / size.y)
+		);
+
+		skeletonGraphic.rectTransform.sizeDelta = size;
+		skeletonGraphic.rectTransform.pivot = p;
+	}
+
+	public static Material DefaultSkeletonGraphicMaterial {
+		get {
+			var guids = AssetDatabase.FindAssets("SkeletonGraphicDefault t:material"); if (guids.Length <= 0) return null;
+			var firstAssetPath = AssetDatabase.GUIDToAssetPath(guids[0]); if (string.IsNullOrEmpty(firstAssetPath)) return null;
+			var firstMaterial = AssetDatabase.LoadAssetAtPath<Material>(firstAssetPath);
+			return firstMaterial;
+		}
+	}
+
+	[MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 10)]
+	static public void SkeletonGraphicCreateMenuItem () {
+		var parentGameObject = Selection.activeObject as GameObject;
+		var parentTransform = parentGameObject == null ? null : parentGameObject.GetComponent<RectTransform>();
+
+		if (parentTransform == null) {
+			Debug.LogWarning("Your new SkeletonGraphic will not be visible until it is placed under a Canvas");
+		}
+
+		var gameObject = NewSkeletonGraphicGameObject("New SkeletonGraphic");
+		gameObject.transform.SetParent(parentTransform, false);
+		EditorUtility.FocusProjectWindow();
+		Selection.activeObject = gameObject;
+		EditorGUIUtility.PingObject(Selection.activeObject);
+	}
+
+	[MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 0)]
+	static void InstantiateSkeletonGraphic () {
+		Object[] arr = Selection.objects;
+		foreach (Object o in arr) {
+			string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(o));
+			string skinName = EditorPrefs.GetString(guid + "_lastSkin", "");
+
+			InstantiateSkeletonGraphic((SkeletonDataAsset)o, skinName);
+			SceneView.RepaintAll();
+		}
+	}
+
+	[MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 0)]
+	static bool ValidateInstantiateSkeletonGraphic () {
+		Object[] arr = Selection.objects;
+
+		if (arr.Length == 0)
+			return false;
+
+		foreach (var selected in arr) {
+			if (selected.GetType() != typeof(SkeletonDataAsset))
+				return false;
+		}
+
+		return true;
+	}
+
+	public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, string skinName) {
+		return InstantiateSkeletonGraphic(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
+	}
+
+	public static SkeletonGraphic InstantiateSkeletonGraphic (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
+		string spineGameObjectName = string.Format("SkeletonGraphic ({0})", skeletonDataAsset.name.Replace("_SkeletonData", ""));
+		var go = NewSkeletonGraphicGameObject(spineGameObjectName);
+		var graphic = go.GetComponent<SkeletonGraphic>();
+		graphic.skeletonDataAsset = skeletonDataAsset;
+
+		SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
+
+		if (data == null) {
+			for (int i = 0; i < skeletonDataAsset.atlasAssets.Length; i++) {
+				string reloadAtlasPath = AssetDatabase.GetAssetPath(skeletonDataAsset.atlasAssets[i]);
+				skeletonDataAsset.atlasAssets[i] = (AtlasAsset)AssetDatabase.LoadAssetAtPath(reloadAtlasPath, typeof(AtlasAsset));
+			}
+
+			data = skeletonDataAsset.GetSkeletonData(true);
+		}
+
+		if (skin == null)
+			skin = data.DefaultSkin;
+
+		if (skin == null)
+			skin = data.Skins.Items[0];
+
+		graphic.Initialize(false);
+		graphic.Skeleton.SetSkin(skin);
+		graphic.initialSkinName = skin.Name;
+		graphic.Skeleton.UpdateWorldTransform();
+		graphic.UpdateMesh();
+
+		return graphic;
+	}
+
+	static GameObject NewSkeletonGraphicGameObject (string gameObjectName) {
+		var go = new GameObject(gameObjectName, typeof(RectTransform), typeof(CanvasRenderer), typeof(SkeletonGraphic));
+		var graphic = go.GetComponent<SkeletonGraphic>();
+		graphic.material = SkeletonGraphicInspector.DefaultSkeletonGraphicMaterial;
+		return go;
+	}
+	#endregion
+}

+ 12 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0d81cc76b52fcdf499b2db252a317726
+timeCreated: 1455570945
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 20 - 19
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs

@@ -34,20 +34,16 @@ using System.Collections;
 using UnityEngine.UI;
 using Spine;
 
-public delegate void SkeletonGraphicDelegate (SkeletonGraphic skeletonGraphic);
-
 [ExecuteInEditMode, RequireComponent(typeof(CanvasRenderer), typeof(RectTransform)), DisallowMultipleComponent]
 [AddComponentMenu("Spine/SkeletonGraphic (Unity UI Canvas)")]
 public class SkeletonGraphic : MaskableGraphic {
 
 	#region Inspector
-	[Header("Skeleton Renderer")]
 	public SkeletonDataAsset skeletonDataAsset;
 
 	[SpineSkin(dataField:"skeletonDataAsset")]
 	public string initialSkinName = "default";
 
-	[Header("Skeleton Animation")]
 	[SpineAnimation(dataField:"skeletonDataAsset")]
 	public string startingAnimation;
 	public bool startingLoop;
@@ -74,11 +70,13 @@ public class SkeletonGraphic : MaskableGraphic {
 			} else {
 				if (freeze) return;
 				skeleton.SetToSetupPose();
-				skeleton.PoseWithAnimation(startingAnimation, 0f, false);
+				if (!string.IsNullOrEmpty(startingAnimation)) {
+					skeleton.PoseWithAnimation(startingAnimation, 0f, false);
+				}
 			}
 		} else {
 			if (skeletonDataAsset != null)
-				Initialize(false);
+				Initialize(true);
 		}
 			
 	}
@@ -93,16 +91,11 @@ public class SkeletonGraphic : MaskableGraphic {
 	#endregion
 
 	#region Internals
-	protected Spine.Unity.ISimpleMeshGenerator spineMeshGenerator; // This is any object that can give you a mesh when you give it a skeleton to render.
-	protected Skeleton skeleton;
-	protected Spine.AnimationState state;
-
 	// This is used by the UI system to determine what to put in the MaterialPropertyBlock.
 	public override Texture mainTexture {
 		get { 
-			if (skeletonDataAsset == null) return null;
 			// Fail loudly when incorrectly set up.
-			return skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
+			return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
 		}
 	}
 
@@ -153,14 +146,22 @@ public class SkeletonGraphic : MaskableGraphic {
 	#endregion
 
 	#region API
+	protected Skeleton skeleton;
 	public Skeleton Skeleton { get { return skeleton; } }
-	public Spine.AnimationState AnimationState { get { return state; } }
 	public SkeletonData SkeletonData { get { return skeleton == null ? null : skeleton.data; } }
 	public bool IsValid { get { return skeleton != null; } }
 
-	public event SkeletonGraphicDelegate UpdateLocal;
-	public event SkeletonGraphicDelegate UpdateWorld;
-	public event SkeletonGraphicDelegate UpdateComplete;
+	protected Spine.AnimationState state;
+	public Spine.AnimationState AnimationState { get { return state; } }
+
+	// This is any object that can give you a mesh when you give it a skeleton to render.
+	protected Spine.Unity.ISimpleMeshGenerator spineMeshGenerator;
+	public Spine.Unity.ISimpleMeshGenerator SpineMeshGenerator { get { return this.spineMeshGenerator; } }
+
+	public delegate void UpdateDelegate (SkeletonGraphic skeletonGraphic);
+	public event UpdateDelegate UpdateLocal;
+	public event UpdateDelegate UpdateWorld;
+	public event UpdateDelegate UpdateComplete;
 
 	public void Clear () {
 		skeleton = null;
@@ -194,12 +195,12 @@ public class SkeletonGraphic : MaskableGraphic {
 			state.SetAnimation(0, startingAnimation, startingLoop);
 	}
 
-
 	public void UpdateMesh () {
-		//Debug.Log("update mesh");
 		if (this.IsValid) {
 			skeleton.SetColor(this.color);
-			spineMeshGenerator.Scale = canvas.referencePixelsPerUnit; // TODO: move this to a listener to of the canvas?
+			if (canvas != null)
+				spineMeshGenerator.Scale = canvas.referencePixelsPerUnit; // TODO: move this to a listener to of the canvas?
+			
 			canvasRenderer.SetMesh(spineMeshGenerator.GenerateMesh(skeleton));
 			this.UpdateMaterial();
 		}

+ 4 - 2
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs.meta

@@ -1,10 +1,12 @@
 fileFormatVersion: 2
 guid: d85b887af7e6c3f45a2e2d2920d641bc
-timeCreated: 1455074790
+timeCreated: 1455576193
 licenseType: Free
 MonoImporter:
   serializedVersion: 2
-  defaultReferences: []
+  defaultReferences:
+  - m_Material: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
+  - skeletonDataAsset: {instanceID: 0}
   executionOrder: 0
   icon: {instanceID: 0}
   userData: