diff --git a/spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs b/spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs index a3739c491..681546923 100644 --- a/spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs +++ b/spine-unity/Assets/spine-unity/Modules/AttachmentTools/AttachmentTools.cs @@ -33,7 +33,7 @@ using System.Collections.Generic; namespace Spine.Unity.Modules.AttachmentTools { public static class AttachmentRegionExtensions { - #region Get + #region GetRegion /// /// Tries to get the region (image) of a renderable attachment. If the attachment is not renderable, it returns null. public static AtlasRegion GetRegion (this Attachment attachment) { @@ -58,8 +58,7 @@ namespace Spine.Unity.Modules.AttachmentTools { return meshAttachment.RendererObject as AtlasRegion; } #endregion - - #region Set + #region SetRegion /// /// Tries to set the region (image) of a renderable attachment. If the attachment is not renderable, nothing is applied. public static void SetRegion (this Attachment attachment, AtlasRegion region, bool updateOffset = true) { @@ -69,7 +68,7 @@ namespace Spine.Unity.Modules.AttachmentTools { var meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) - meshAttachment.SetRegion(region, updateOffset); + meshAttachment.SetRegion(region, updateOffset); } /// Sets the region (image) of a RegionAttachment diff --git a/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/Editor/BoundingBoxFollowerInspector.cs b/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/Editor/BoundingBoxFollowerInspector.cs index 80582077d..63e0bb211 100644 --- a/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/Editor/BoundingBoxFollowerInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/Editor/BoundingBoxFollowerInspector.cs @@ -33,6 +33,7 @@ using UnityEditor; namespace Spine.Unity.Editor { using Event = UnityEngine.Event; + using Icons = SpineEditorUtilities.Icons; [CustomEditor(typeof(BoundingBoxFollower))] public class BoundingBoxFollowerInspector : UnityEditor.Editor { @@ -43,7 +44,13 @@ namespace Spine.Unity.Editor { bool sceneRepaintRequired = false; bool debugIsExpanded; - readonly GUIContent AddBoneFollowerLabel = new GUIContent("Add Bone Follower", SpineEditorUtilities.Icons.bone); + GUIContent addBoneFollowerLabel; + GUIContent AddBoneFollowerLabel { + get { + if (addBoneFollowerLabel == null) addBoneFollowerLabel = new GUIContent("Add Bone Follower", Icons.bone); + return addBoneFollowerLabel; + } + } void OnEnable () { skeletonRenderer = serializedObject.FindProperty("skeletonRenderer"); @@ -73,7 +80,7 @@ namespace Spine.Unity.Editor { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollower to a separate child GameObject of the Spine GameObject.", MessageType.Warning); - if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", SpineEditorUtilities.Icons.boundingBox), GUILayout.Height(50f))) { + if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", Icons.boundingBox), GUILayout.Height(50f))) { AddBoundingBoxFollowerChild(sr, follower); DestroyImmediate(follower); return; @@ -127,7 +134,7 @@ namespace Spine.Unity.Editor { 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); + collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled); } sceneRepaintRequired |= EditorGUI.EndChangeCheck(); EditorGUI.indentLevel--; diff --git a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs index d9ae59846..3799e8f17 100644 --- a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs +++ b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs @@ -129,6 +129,15 @@ namespace Spine.Unity { m33 = 1 }; } + + public static void GetWorldToLocalMatrix (this Bone bone, out float ia, out float ib, out float ic, out float id) { + float a = bone.a, b = bone.b, c = bone.c, d = bone.d; + float invDet = 1 / (a * d - b * c); + ia = invDet * d; + ib = invDet * -b; + ic = invDet * -c; + id = invDet * a; + } #endregion #region Attachments @@ -144,16 +153,50 @@ namespace Spine.Unity { return null; } + /// Fills a Vector2 buffer with local vertices. + /// The VertexAttachment + /// Slot where the attachment belongs. + /// Correctly-sized buffer. Use attachment's .WorldVerticesLength to get the correct size. If null, a new Vector2[] of the correct size will be allocated. + public static Vector2[] GetLocalVertices (this VertexAttachment va, Slot slot, Vector2[] buffer) { + int floatsCount = va.worldVerticesLength; + int bufferTargetSize = floatsCount >> 1; + buffer = buffer ?? new Vector2[bufferTargetSize]; + if (buffer.Length < bufferTargetSize) throw new System.ArgumentException(string.Format("Vector2 buffer too small. {0} requires an array of size {1}. Use the attachment's .WorldVerticesLength to get the correct size.", va.Name, floatsCount), "buffer"); + + if (va.bones == null) { + var localVerts = va.vertices; + for (int i = 0; i < bufferTargetSize; i++) { + int j = i * 2; + buffer[i] = new Vector2(localVerts[j], localVerts[j+1]); + } + } else { + var floats = new float[floatsCount]; + va.ComputeWorldVertices(slot, floats); + + Bone sb = slot.bone; + float bwx = sb.worldX, bwy = sb.worldY, ia, ib, ic, id; + sb.GetWorldToLocalMatrix(out ia, out ib, out ic, out id); + + for (int i = 0; i < bufferTargetSize; i++) { + int j = i * 2; + float x = floats[j] - bwx, y = floats[j+1] - bwy; + buffer[i] = new Vector2(x * ia + y * ic, x * ib + y * id); + } + } + + return buffer; + } + /// Calculates world vertices and fills a Vector2 buffer. /// The VertexAttachment - /// Slot where + /// Slot where the attachment belongs. /// Correctly-sized buffer. Use attachment's .WorldVerticesLength to get the correct size. If null, a new Vector2[] of the correct size will be allocated. public static Vector2[] GetWorldVertices (this VertexAttachment a, Slot slot, Vector2[] buffer) { int worldVertsLength = a.worldVerticesLength; int bufferTargetSize = worldVertsLength >> 1; buffer = buffer ?? new Vector2[bufferTargetSize]; if (buffer.Length < bufferTargetSize) throw new System.ArgumentException(string.Format("Vector2 buffer too small. {0} requires an array of size {1}. Use the attachment's .WorldVerticesLength to get the correct size.", a.Name, worldVertsLength), "buffer"); - + var floats = new float[worldVertsLength]; a.ComputeWorldVertices(slot, floats); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index ae0d24c88..4436f79b6 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -68,7 +68,7 @@ namespace Spine.Unity { public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment box, Slot slot, GameObject gameObject, bool isTrigger = true) { if (box == null) return null; if (box.IsWeighted()) Debug.LogWarning("UnityEngine.PolygonCollider2D does not support weighted or animated points. Collider will not be animated. Please remove weights and animations from the bounding box in Spine editor."); - var verts = box.GetWorldVertices(slot, null); + var verts = box.GetLocalVertices(slot, null); var collider = gameObject.AddComponent(); collider.isTrigger = isTrigger; collider.SetPath(0, verts);