Browse Source

[spine-unity] Clarify BoundingBoxFollower behavior in editor. (#630)

John 9 years ago
parent
commit
d6dc425817

+ 59 - 42
spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs

@@ -32,28 +32,30 @@ using UnityEngine;
 using System.Collections.Generic;
 
 namespace Spine.Unity {
+
 	[ExecuteInEditMode]
 	public class BoundingBoxFollower : MonoBehaviour {
-		
+		#region Inspector
 		public SkeletonRenderer skeletonRenderer;
-
 		[SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
 		public string slotName;
+		#endregion
 
 		Slot slot;
 		BoundingBoxAttachment currentAttachment;
-		PolygonCollider2D currentCollider;
 		string currentAttachmentName;
+		PolygonCollider2D currentCollider;
+
 		bool valid = false;
 		bool hasReset;
 
-		public Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
-		public Dictionary<BoundingBoxAttachment, string> attachmentNameTable = new Dictionary<BoundingBoxAttachment, string>();
+		public readonly Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
+		public readonly Dictionary<BoundingBoxAttachment, string> attachmentNameTable = new Dictionary<BoundingBoxAttachment, string>();
 
-		public string CurrentAttachmentName { get { return currentAttachmentName; } }
+		public Slot Slot { get { return slot; } }
 		public BoundingBoxAttachment CurrentAttachment { get { return currentAttachment; } }
+		public string CurrentAttachmentName { get { return currentAttachmentName; } }
 		public PolygonCollider2D CurrentCollider { get { return currentCollider; } }
-		public Slot Slot { get { return slot; } }
 
 		void OnEnable () {
 			ClearColliders();
@@ -62,74 +64,91 @@ namespace Spine.Unity {
 				skeletonRenderer = GetComponentInParent<SkeletonRenderer>();
 
 			if (skeletonRenderer != null) {
-				skeletonRenderer.OnRebuild -= HandleReset;
-				skeletonRenderer.OnRebuild += HandleReset;
+				skeletonRenderer.OnRebuild -= HandleRebuild;
+				skeletonRenderer.OnRebuild += HandleRebuild;
 
 				if (hasReset)
-					HandleReset(skeletonRenderer);
+					HandleRebuild(skeletonRenderer);
 			}
 		}
 
 		void OnDisable () {
-			skeletonRenderer.OnRebuild -= HandleReset;
+			skeletonRenderer.OnRebuild -= HandleRebuild;
 		}
 
 		void Start () {
 			if (!hasReset && skeletonRenderer != null)
-				HandleReset(skeletonRenderer);
+				HandleRebuild(skeletonRenderer);
 		}
 
-		public void HandleReset (SkeletonRenderer renderer) {
+		public void HandleRebuild (SkeletonRenderer renderer) {
 			if (string.IsNullOrEmpty(slotName))
 				return;
 
 			hasReset = true;
-
 			ClearColliders();
 			colliderTable.Clear();
 
 			if (skeletonRenderer.skeleton == null) {
-				skeletonRenderer.OnRebuild -= HandleReset;
+				skeletonRenderer.OnRebuild -= HandleRebuild;
 				skeletonRenderer.Initialize(false);
-				skeletonRenderer.OnRebuild += HandleReset;
+				skeletonRenderer.OnRebuild += HandleRebuild;
 			}
 
 			var skeleton = skeletonRenderer.skeleton;
 			slot = skeleton.FindSlot(slotName);
 			int slotIndex = skeleton.FindSlotIndex(slotName);
 
-			foreach (var skin in skeleton.Data.Skins) {
-				var attachmentNames = new List<string>();
-				skin.FindNamesForSlot(slotIndex, attachmentNames);
-
-				foreach (var attachmentName in attachmentNames) {
-					var attachment = skin.GetAttachment(slotIndex, attachmentName);
-					var boundingBoxAttachment = attachment as BoundingBoxAttachment;
-					if (boundingBoxAttachment != null) {
-						var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(boundingBoxAttachment, gameObject, true);
-						bbCollider.enabled = false;
-						bbCollider.hideFlags = HideFlags.HideInInspector;
-						colliderTable.Add(boundingBoxAttachment, bbCollider);
-						attachmentNameTable.Add(boundingBoxAttachment, attachmentName);
+			if (this.gameObject.activeInHierarchy) {
+				foreach (var skin in skeleton.Data.Skins) {
+					var attachmentNames = new List<string>();
+					skin.FindNamesForSlot(slotIndex, attachmentNames);
+
+					foreach (var attachmentName in attachmentNames) {
+						var attachment = skin.GetAttachment(slotIndex, attachmentName);
+						var boundingBoxAttachment = attachment as BoundingBoxAttachment;
+						if (boundingBoxAttachment != null) {
+							var bbCollider = SkeletonUtility.AddBoundingBoxAsComponent(boundingBoxAttachment, gameObject, true);
+							bbCollider.enabled = false;
+							bbCollider.hideFlags = HideFlags.NotEditable;
+							colliderTable.Add(boundingBoxAttachment, bbCollider);
+							attachmentNameTable.Add(boundingBoxAttachment, attachmentName);
+						}
 					}
 				}
 			}
 
+#if UNITY_EDITOR
 			valid = colliderTable.Count != 0;
-
-			if (!valid)
-				Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
+			if (!valid) {
+				if (this.gameObject.activeInHierarchy)
+					Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
+				else 
+					Debug.LogWarning("Bounding Box Follower tried to rebuild as a prefab.");
+			}
+#endif
+				
 		}
 
 		void ClearColliders () {
 			var colliders = GetComponents<PolygonCollider2D>();
+			if (colliders.Length == 0) return;
+
+#if UNITY_EDITOR
 			if (Application.isPlaying) {
-				foreach (var c in colliders)
-					Destroy(c);
+				foreach (var c in colliders) {
+					if (c != null)
+						Destroy(c);
+				}
 			} else {
 				foreach (var c in colliders)
 					DestroyImmediate(c);
 			}
+#else
+			foreach (var c in colliders)
+				if (c != null)
+					Destroy(c);
+#endif
 
 			colliderTable.Clear();
 			attachmentNameTable.Clear();
@@ -139,21 +158,19 @@ namespace Spine.Unity {
 			if (!skeletonRenderer.valid)
 				return;
 
-			if (slot != null) {
-				if (slot.Attachment != currentAttachment)
-					SetCurrent((BoundingBoxAttachment)slot.Attachment);
-			}
+			if (slot != null && slot.Attachment != currentAttachment)
+				SetCurrent((BoundingBoxAttachment)slot.Attachment);
 		}
 
 		void SetCurrent (BoundingBoxAttachment attachment) {
-			if (currentCollider)
+			if (currentCollider != null)
 				currentCollider.enabled = false;
 
-			if (attachment != null) {
+			if (attachment == null) {
+				currentCollider = null;
+			} else {
 				currentCollider = colliderTable[attachment];
 				currentCollider.enabled = true;
-			} else {
-				currentCollider = null;
 			}
 
 			currentAttachment = attachment;

+ 44 - 22
spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/Editor/BoundingBoxFollowerInspector.cs

@@ -31,7 +31,6 @@
 
 using UnityEngine;
 using UnityEditor;
-using System.Collections;
 
 namespace Spine.Unity.Editor {
 	
@@ -39,7 +38,8 @@ namespace Spine.Unity.Editor {
 	public class BoundingBoxFollowerInspector : UnityEditor.Editor {
 		SerializedProperty skeletonRenderer, slotName;
 		BoundingBoxFollower follower;
-		bool needToReset = false;
+		bool rebuildRequired = false;
+		bool addBoneFollower = false;
 
 		void OnEnable () {
 			skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
@@ -48,41 +48,63 @@ namespace Spine.Unity.Editor {
 		}
 
 		public override void OnInspectorGUI () {
-			if (needToReset) {
-				follower.HandleReset(null);
-				needToReset = false;
+			bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
+			bool repaintEvent = UnityEngine.Event.current.type == EventType.Repaint;
+
+			if (rebuildRequired) {
+				follower.HandleRebuild(null);
+				rebuildRequired = false;
 			}
+
 			EditorGUI.BeginChangeCheck();
 			EditorGUILayout.PropertyField(skeletonRenderer);
 			EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
-
-			if (EditorGUI.EndChangeCheck()){
+			if (EditorGUI.EndChangeCheck()) {
 				serializedObject.ApplyModifiedProperties();
-				needToReset = true;
+				if (!isInspectingPrefab)
+					rebuildRequired = true;
 			}
 
-			bool hasBone = follower.GetComponent<BoneFollower>() != null;
-
-			EditorGUI.BeginDisabledGroup(hasBone || follower.Slot == null);
-			{
+			bool hasBoneFollower = follower.GetComponent<BoneFollower>() != null;
+			using (new EditorGUI.DisabledGroupScope(hasBoneFollower || follower.Slot == null)) {
 				if (GUILayout.Button(new GUIContent("Add Bone Follower", SpineEditorUtilities.Icons.bone))) {
-					var boneFollower = follower.gameObject.AddComponent<BoneFollower>();
-					boneFollower.boneName = follower.Slot.Data.BoneData.Name;
+					addBoneFollower = true;
 				}
 			}
-			EditorGUI.EndDisabledGroup();
 
+			if (isInspectingPrefab) {
+				follower.colliderTable.Clear();
+				follower.attachmentNameTable.Clear();
+				EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);
+
+				// How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
+				var collider = follower.GetComponent<PolygonCollider2D>();
+				if (collider != null) Debug.LogWarning("Found BoundingBoxFollower collider components in prefab. These are disposed and regenerated at runtime.");
 
+			} else {				
+				EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count), EditorStyles.boldLabel);
+				EditorGUI.BeginChangeCheck();
+				foreach (var kp in follower.attachmentNameTable) {
+					string attachmentName = kp.Value;
+					var collider = follower.colliderTable[kp.Key];
+					bool isPlaceholder = attachmentName != kp.Key.Name;
+					collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : attachmentName + " [" + kp.Key.Name + "]", isPlaceholder ? SpineEditorUtilities.Icons.skinPlaceholder : SpineEditorUtilities.Icons.boundingBox), collider.enabled);
+				}
+				if (EditorGUI.EndChangeCheck()) {
+					SceneView.RepaintAll();
+				}
 
-			//GUILayout.Space(20);
-			GUILayout.Label("Attachment Names", EditorStyles.boldLabel);
-			foreach (var kp in follower.attachmentNameTable) {
-				string name = kp.Value;
-				var collider = follower.colliderTable[kp.Key];
-				bool isPlaceholder = name != kp.Key.Name;
-				collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? name : name + " [" + kp.Key.Name + "]", isPlaceholder ? SpineEditorUtilities.Icons.skinPlaceholder : SpineEditorUtilities.Icons.boundingBox), collider.enabled);
+				if (!Application.isPlaying)
+					EditorGUILayout.HelpBox("\nAt runtime, BoundingBoxFollower enables and disables PolygonCollider2Ds based on the currently active attachment in the slot.\n\nCheckboxes in Edit Mode are only for preview. Checkbox states are not saved.\n", MessageType.Info);
+			}
+
+			if (addBoneFollower && repaintEvent) {
+				var boneFollower = follower.gameObject.AddComponent<BoneFollower>();
+				boneFollower.boneName = follower.Slot.Data.BoneData.Name;
+				addBoneFollower = false;
 			}
 		}
+
 	}
 
 }