From 86cfefe30dd79b6046cac81258db4a5d5371a0db Mon Sep 17 00:00:00 2001 From: pharan Date: Wed, 7 Dec 2016 04:56:33 +0800 Subject: [PATCH] [unity] Updated editors + OnSceneGUI. --- .../Editor/SkeletonDataAssetInspector.cs | 78 ++-- .../Editor/SkeletonRendererInspector.cs | 35 +- .../Editor/SpineEditorUtilities.cs | 364 ++++++++++++++---- .../Assets/spine-unity/Shaders/Bones.shader | 24 +- .../Assets/spine-unity/SkeletonExtensions.cs | 20 +- .../Editor/SkeletonUtilityInspector.cs | 31 +- 6 files changed, 386 insertions(+), 166 deletions(-) diff --git a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs index a8e370250..f4b385d58 100644 --- a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs @@ -41,6 +41,7 @@ using Spine; namespace Spine.Unity.Editor { using Event = UnityEngine.Event; + using Icons = SpineEditorUtilities.Icons; [CustomEditor(typeof(SkeletonDataAsset))] public class SkeletonDataAssetInspector : UnityEditor.Editor { @@ -135,7 +136,7 @@ namespace Spine.Unity.Editor { serializedObject.Update(); - EditorGUILayout.LabelField(new GUIContent(target.name + " (SkeletonDataAsset)", SpineEditorUtilities.Icons.spine), EditorStyles.whiteLargeLabel); + EditorGUILayout.LabelField(new GUIContent(target.name + " (SkeletonDataAsset)", Icons.spine), EditorStyles.whiteLargeLabel); if (m_skeletonData != null) { EditorGUILayout.LabelField("(Drag and Drop to instantiate.)", EditorStyles.miniLabel); } @@ -154,12 +155,12 @@ namespace Spine.Unity.Editor { // } } - EditorGUILayout.PropertyField(skeletonJSON, new GUIContent(skeletonJSON.displayName, SpineEditorUtilities.Icons.spine)); + EditorGUILayout.PropertyField(skeletonJSON, new GUIContent(skeletonJSON.displayName, Icons.spine)); EditorGUILayout.PropertyField(scale); } // if (m_skeletonData != null) { -// if (SpineInspectorUtility.CenteredButton(new GUIContent("Instantiate", SpineEditorUtilities.Icons.spine, "Creates a new Spine GameObject in the active scene using this Skeleton Data.\nYou can also instantiate by dragging the SkeletonData asset from Project view into Scene View."))) +// if (SpineInspectorUtility.CenteredButton(new GUIContent("Instantiate", Icons.spine, "Creates a new Spine GameObject in the active scene using this Skeleton Data.\nYou can also instantiate by dragging the SkeletonData asset from Project view into Scene View."))) // SpineEditorUtilities.ShowInstantiateContextMenu(this.m_skeletonDataAsset, Vector3.zero); // } @@ -212,7 +213,7 @@ namespace Spine.Unity.Editor { #if !SPINE_TK2D // Reimport Button using (new EditorGUI.DisabledGroupScope(skeletonJSON.objectReferenceValue == null)) { - if (GUILayout.Button(new GUIContent("Attempt Reimport", SpineEditorUtilities.Icons.warning))) { + if (GUILayout.Button(new GUIContent("Attempt Reimport", Icons.warning))) { DoReimport(); return; } @@ -223,7 +224,7 @@ namespace Spine.Unity.Editor { // List warnings. foreach (var line in warnings) - EditorGUILayout.LabelField(new GUIContent(line, SpineEditorUtilities.Icons.warning)); + EditorGUILayout.LabelField(new GUIContent(line, Icons.warning)); } if (!Application.isPlaying) @@ -233,10 +234,10 @@ namespace Spine.Unity.Editor { void DrawUnityTools () { #if SPINE_SKELETON_ANIMATOR using (new SpineInspectorUtility.BoxScope()) { - isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, new GUIContent("SkeletonAnimator", SpineEditorUtilities.Icons.unityIcon)); + isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, new GUIContent("SkeletonAnimator", Icons.unityIcon)); if (isMecanimExpanded) { EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(controller, new GUIContent("Controller", SpineEditorUtilities.Icons.controllerIcon)); + EditorGUILayout.PropertyField(controller, new GUIContent("Controller", Icons.controllerIcon)); if (controller.objectReferenceValue == null) { // Generate Mecanim Controller Button @@ -264,7 +265,7 @@ namespace Spine.Unity.Editor { #if SPINE_BAKING bool pre = isBakingExpanded; - isBakingExpanded = EditorGUILayout.Foldout(isBakingExpanded, new GUIContent("Baking", SpineEditorUtilities.Icons.unityIcon)); + isBakingExpanded = EditorGUILayout.Foldout(isBakingExpanded, new GUIContent("Baking", Icons.unityIcon)); if (pre != isBakingExpanded) EditorPrefs.SetBool(ShowBakingPrefsKey, isBakingExpanded); @@ -298,7 +299,7 @@ namespace Spine.Unity.Editor { // Bake Skin buttons. using (new GUILayout.HorizontalScope()) { - if (GUILayout.Button(new GUIContent("Bake All Skins", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150))) + if (GUILayout.Button(new GUIContent("Bake All Skins", Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150))) SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions); if (m_skeletonAnimation != null && m_skeletonAnimation.skeleton != null) { @@ -312,10 +313,10 @@ namespace Spine.Unity.Editor { skinName = m_skeletonAnimation.skeleton.Skin.Name; using (new GUILayout.VerticalScope()) { - if (GUILayout.Button(new GUIContent("Bake \"" + skinName + "\"", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250))) + if (GUILayout.Button(new GUIContent("Bake \"" + skinName + "\"", Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250))) SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new ExposedList(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions); using (new GUILayout.HorizontalScope()) { - GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50)); + GUILayout.Label(new GUIContent("Skins", Icons.skinsRoot), GUILayout.Width(50)); if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) { DrawSkinDropdown(); } @@ -391,12 +392,12 @@ namespace Spine.Unity.Editor { } void DrawAnimationList () { - showAnimationList = EditorGUILayout.Foldout(showAnimationList, new GUIContent(string.Format("Animations [{0}]", m_skeletonData.Animations.Count), SpineEditorUtilities.Icons.animationRoot)); + showAnimationList = EditorGUILayout.Foldout(showAnimationList, new GUIContent(string.Format("Animations [{0}]", m_skeletonData.Animations.Count), Icons.animationRoot)); if (!showAnimationList) return; if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) { - if (GUILayout.Button(new GUIContent("Setup Pose", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))) { + if (GUILayout.Button(new GUIContent("Setup Pose", Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))) { StopAnimation(); m_skeletonAnimation.skeleton.SetToSetupPose(); m_requireRefresh = true; @@ -422,13 +423,13 @@ namespace Spine.Unity.Editor { } else { GUILayout.Label("-", GUILayout.Width(24)); } - EditorGUILayout.LabelField(new GUIContent(animation.Name, SpineEditorUtilities.Icons.animation), new GUIContent(animation.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(animation.Duration * 30)) + ")").PadLeft(12, ' '))); + EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), new GUIContent(animation.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(animation.Duration * 30)) + ")").PadLeft(12, ' '))); } } } void DrawSlotList () { - showSlotList = EditorGUILayout.Foldout(showSlotList, new GUIContent("Slots", SpineEditorUtilities.Icons.slotRoot)); + showSlotList = EditorGUILayout.Foldout(showSlotList, new GUIContent("Slots", Icons.slotRoot)); if (!showSlotList) return; if (m_skeletonAnimation == null || m_skeletonAnimation.skeleton == null) return; @@ -440,10 +441,11 @@ namespace Spine.Unity.Editor { var defaultSkinAttachmentNames = new List(); var defaultSkin = m_skeletonData.Skins.Items[0]; Skin skin = m_skeletonAnimation.skeleton.Skin ?? defaultSkin; + var slotsItems = m_skeletonAnimation.skeleton.Slots.Items; for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--) { - Slot slot = m_skeletonAnimation.skeleton.Slots.Items[i]; - EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, SpineEditorUtilities.Icons.slot)); + Slot slot = slotsItems[i]; + EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot)); if (showAttachments) { EditorGUI.indentLevel++; @@ -470,15 +472,15 @@ namespace Spine.Unity.Editor { var type = attachment.GetType(); if (type == typeof(RegionAttachment)) - icon = SpineEditorUtilities.Icons.image; + icon = Icons.image; else if (type == typeof(MeshAttachment)) - icon = SpineEditorUtilities.Icons.mesh; + icon = Icons.mesh; else if (type == typeof(BoundingBoxAttachment)) - icon = SpineEditorUtilities.Icons.boundingBox; + icon = Icons.boundingBox; else if (type == typeof(PathAttachment)) - icon = SpineEditorUtilities.Icons.boundingBox; + icon = Icons.boundingBox; else - icon = SpineEditorUtilities.Icons.warning; + icon = Icons.warning; //JOHN: left todo: Icon for paths. Generic icon for unidentified attachments. // MITCH: left todo: Waterboard Nate @@ -491,9 +493,9 @@ namespace Spine.Unity.Editor { if (!defaultSkinAttachmentNames.Contains(attachmentName)) { Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect(); - skinPlaceHolderIconRect.width = SpineEditorUtilities.Icons.skinPlaceholder.width; - skinPlaceHolderIconRect.height = SpineEditorUtilities.Icons.skinPlaceholder.height; - GUI.DrawTexture(skinPlaceHolderIconRect, SpineEditorUtilities.Icons.skinPlaceholder); + skinPlaceHolderIconRect.width = Icons.skinPlaceholder.width; + skinPlaceHolderIconRect.height = Icons.skinPlaceholder.height; + GUI.DrawTexture(skinPlaceHolderIconRect, Icons.skinPlaceholder); } if (toggled != initialState) { @@ -698,7 +700,7 @@ namespace Spine.Unity.Editor { GameObject go = this.m_previewInstance; Bounds bounds = go.GetComponent().bounds; m_orthoGoal = bounds.size.y; - m_posGoal = bounds.center + new Vector3(0, 0, -10); + m_posGoal = bounds.center + new Vector3(0, 0, -10f); } void AdjustCameraGoals () { @@ -752,11 +754,8 @@ namespace Spine.Unity.Editor { if (drawHandles) { Handles.SetCamera(m_previewUtility.m_Camera); - foreach (var slot in m_skeletonAnimation.skeleton.Slots) { - var boundingBoxAttachment = slot.Attachment as BoundingBoxAttachment; - if (boundingBoxAttachment != null) - SpineEditorUtilities.DrawBoundingBox(slot, boundingBoxAttachment); - } + SpineHandles.DrawBoundingBoxes(m_skeletonAnimation.transform, m_skeletonAnimation.skeleton); + if (showAttachments) SpineHandles.DrawPaths(m_skeletonAnimation.transform, m_skeletonAnimation.skeleton); } go.GetComponent().enabled = false; @@ -772,9 +771,10 @@ namespace Spine.Unity.Editor { Repaint(); } else if (m_requireRefresh) { Repaint(); - } else { + } + //else { //only needed if using smooth menus - } + //} if (needToSerialize) { needToSerialize = false; @@ -794,7 +794,7 @@ namespace Spine.Unity.Editor { popRect.x += 4; popRect.height = 24; popRect.width = 40; - EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", SpineEditorUtilities.Icons.skinsRoot)); + EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", Icons.skinsRoot)); popRect.y += 11; popRect.width = 150; @@ -837,11 +837,11 @@ namespace Spine.Unity.Editor { for (int i = 0; i < m_animEvents.Count; i++) { float fr = m_animEventFrames[i]; var evRect = new Rect(barRect); - evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons.userEvent.width / 2), barRect.x, float.MaxValue); - evRect.width = SpineEditorUtilities.Icons.userEvent.width; - evRect.height = SpineEditorUtilities.Icons.userEvent.height; - evRect.y += SpineEditorUtilities.Icons.userEvent.height; - GUI.DrawTexture(evRect, SpineEditorUtilities.Icons.userEvent); + evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (Icons.userEvent.width / 2), barRect.x, float.MaxValue); + evRect.width = Icons.userEvent.width; + evRect.height = Icons.userEvent.height; + evRect.y += Icons.userEvent.height; + GUI.DrawTexture(evRect, Icons.userEvent); Event ev = Event.current; if (ev.type == EventType.Repaint) { diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs index 4039b26cf..c3fe1d03a 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs @@ -41,6 +41,8 @@ namespace Spine.Unity.Editor { [CanEditMultipleObjects] public class SkeletonRendererInspector : UnityEditor.Editor { protected static bool advancedFoldout; + protected static bool showBoneNames, showPaths, showShapes, showConstraints = true; + protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, separatorSlotNames, frontFacing, zSpacing, pmaVertexColors, clearStateOnDisable; protected SpineInspectorUtility.SerializedSortingProperties sortingProperties; protected bool isInspectingPrefab; @@ -226,18 +228,21 @@ namespace Spine.Unity.Editor { // More Render Options... using (new SpineInspectorUtility.BoxScope()) { + EditorGUI.BeginChangeCheck(); if (advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced")) { using (new SpineInspectorUtility.IndentScope()) { - SeparatorsField(separatorSlotNames); - EditorGUILayout.Space(); using (new SpineInspectorUtility.LabelWidthScope()) { // Optimization options EditorGUILayout.PropertyField(meshes, MeshesLabel); EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel); + EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel); EditorGUILayout.Space(); } + SeparatorsField(separatorSlotNames); + EditorGUILayout.Space(); + // Render options const float MinZSpacing = -0.1f; const float MaxZSpacing = 0f; @@ -245,18 +250,28 @@ namespace Spine.Unity.Editor { EditorGUILayout.Space(); using (new SpineInspectorUtility.LabelWidthScope()) { + EditorGUILayout.LabelField("Vertex Data", EditorStyles.boldLabel); EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel); - EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel); // Optional fields. May be disabled in SkeletonRenderer. if (normals != null) EditorGUILayout.PropertyField(normals, NormalsLabel); if (tangents != null) EditorGUILayout.PropertyField(tangents, TangentsLabel); if (frontFacing != null) EditorGUILayout.PropertyField(frontFacing); + + EditorGUILayout.Space(); + + EditorGUILayout.LabelField("Editor Preview", EditorStyles.boldLabel); + showBoneNames = EditorGUILayout.Toggle("Show Bone Names", showBoneNames); + showPaths = EditorGUILayout.Toggle("Show Paths", showPaths); + showShapes = EditorGUILayout.Toggle("Show Shapes", showShapes); + showConstraints = EditorGUILayout.Toggle("Show Constraints", showConstraints); } EditorGUILayout.Space(); } } + if (EditorGUI.EndChangeCheck()) + SceneView.RepaintAll(); } } @@ -290,6 +305,20 @@ namespace Spine.Unity.Editor { } } + public void OnSceneGUI () { + var skeletonRenderer = (SkeletonRenderer)target; + var skeleton = skeletonRenderer.skeleton; + var transform = skeletonRenderer.transform; + + if (skeleton == null) return; + + if (showPaths) SpineHandles.DrawPaths(transform, skeleton); + SpineHandles.DrawBones(transform, skeleton); + if (showConstraints) SpineHandles.DrawConstraints(transform, skeleton); + if (showBoneNames) SpineHandles.DrawBoneNames(transform, skeleton); + if (showShapes) SpineHandles.DrawBoundingBoxes(transform, skeleton); + } + public void DrawSkeletonUtilityButton (bool multi) { if (multi) { // Support multi-edit SkeletonUtility button. diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index 311b5d115..7ef91f7f8 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -76,37 +76,6 @@ namespace Spine.Unity.Editor { public static Texture2D unityIcon; public static Texture2D controllerIcon; - internal static Mesh _boneMesh; - public static Mesh BoneMesh { - get { - if (_boneMesh == null) { - _boneMesh = new Mesh(); - _boneMesh.vertices = new [] { - new Vector3(0, 0, 0), - new Vector3(-0.1f, 0.1f, 0), - new Vector3(0, 1, 0), - new Vector3(0.1f, 0.1f, 0) - }; - _boneMesh.uv = new Vector2[4]; - _boneMesh.triangles = new [] { 0, 1, 2, 2, 3, 0 }; - _boneMesh.RecalculateBounds(); - _boneMesh.RecalculateNormals(); - } - return _boneMesh; - } - } - - internal static Material _boneMaterial; - public static Material BoneMaterial { - get { - if (_boneMaterial == null) { - _boneMaterial = new Material(Shader.Find("Hidden/Spine/Bones")); - _boneMaterial.SetColor("_Color", new Color(0.4f, 0.4f, 0.4f, 0.25f)); - } - return _boneMaterial; - } - } - public static void Initialize () { skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png"); nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-null.png"); @@ -229,14 +198,12 @@ namespace Spine.Unity.Editor { showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, DEFAULT_SHOW_HIERARCHY_ICONS); } - EditorGUI.BeginChangeCheck(); showHierarchyIcons = EditorGUILayout.Toggle(new GUIContent("Show Hierarchy Icons", "Show relevant icons on GameObjects with Spine Components on them. Disable this if you have large, complex scenes."), showHierarchyIcons); if (EditorGUI.EndChangeCheck()) { EditorPrefs.SetBool(SHOW_HIERARCHY_ICONS_KEY, showHierarchyIcons); - HierarchyWindowChanged(); - } - + HierarchyWindowChanged(); + } EditorGUILayout.Separator(); @@ -252,6 +219,7 @@ namespace Spine.Unity.Editor { if (EditorGUI.EndChangeCheck()) EditorPrefs.SetFloat(DEFAULT_SCALE_KEY, defaultScale); + EditorGUI.BeginChangeCheck(); #if UNITY_5_3_OR_NEWER defaultShader = EditorGUILayout.DelayedTextField(new GUIContent("Default shader", "Default shader for materials auto-generated on import."), defaultShader); @@ -263,14 +231,13 @@ namespace Spine.Unity.Editor { GUILayout.Space(20); EditorGUILayout.LabelField("3rd Party Settings", EditorStyles.boldLabel); - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("TK2D"); - - if (GUILayout.Button("Enable", GUILayout.Width(64))) - EnableTK2D(); - if (GUILayout.Button("Disable", GUILayout.Width(64))) - DisableTK2D(); - GUILayout.EndHorizontal(); + using (new GUILayout.HorizontalScope()) { + EditorGUILayout.PrefixLabel("TK2D"); + if (GUILayout.Button("Enable", GUILayout.Width(64))) + EnableTK2D(); + if (GUILayout.Button("Disable", GUILayout.Width(64))) + DisableTK2D(); + } } #endregion @@ -1248,18 +1215,18 @@ namespace Spine.Unity.Editor { SkeletonAnimation newSkeletonAnimation = go.GetComponent(); newSkeletonAnimation.skeletonDataAsset = skeletonDataAsset; - { - bool requiresNormals = false; - foreach (AtlasAsset atlasAsset in skeletonDataAsset.atlasAssets) { - foreach (Material m in atlasAsset.materials) { - if (m.shader.name.Contains("Lit")) { - requiresNormals = true; - break; - } - } - } - newSkeletonAnimation.calculateNormals = requiresNormals; - } +// { +// bool requiresNormals = false; +// foreach (AtlasAsset atlasAsset in skeletonDataAsset.atlasAssets) { +// foreach (Material m in atlasAsset.materials) { +// if (m.shader.name.Contains("Lit")) { +// requiresNormals = true; +// break; +// } +// } +// } +// newSkeletonAnimation.calculateNormals = requiresNormals; +// } try { newSkeletonAnimation.Initialize(false); @@ -1404,24 +1371,182 @@ namespace Spine.Unity.Editor { } #endregion - #region Handles - static public void DrawBone (Matrix4x4 transformMatrix) { - SpineEditorUtilities.Icons.BoneMaterial.SetPass(0); - Graphics.DrawMeshNow(SpineEditorUtilities.Icons.BoneMesh, transformMatrix); + public static string GetPathSafeRegionName (AtlasRegion region) { + return region.name.Replace("/", "_"); + } + } + + public static class SpineHandles { + static Mesh _boneMesh; + public static Mesh BoneMesh { + get { + if (_boneMesh == null) { + _boneMesh = new Mesh { + vertices = new [] { + new Vector3(0, 0, 0), + new Vector3(-0.1f, 0.1f, 0), + new Vector3(0, 1, 0), + new Vector3(0.1f, 0.1f, 0) + }, + uv = new Vector2[4], + triangles = new [] { 0, 1, 2, 2, 3, 0 } + }; + _boneMesh.RecalculateBounds(); + _boneMesh.RecalculateNormals(); + } + return _boneMesh; + } + } + + static Mesh _arrowheadMesh; + public static Mesh ArrowheadMesh { + get { + if (_arrowheadMesh == null) { + _arrowheadMesh = new Mesh { + vertices = new [] { + new Vector3(0, 0), + new Vector3(-1f, 0.5f), + new Vector3(-1f, -0.5f) + }, + uv = new Vector2[3], + triangles = new [] { 0, 1, 2 } + }; + _arrowheadMesh.RecalculateBounds(); + _arrowheadMesh.RecalculateNormals(); + } + return _arrowheadMesh; + } + } + + static Material _boneMaterial; + public static Material BoneMaterial { + get { + if (_boneMaterial == null) { + _boneMaterial = new Material(Shader.Find("Hidden/Spine/Bones")); + _boneMaterial.SetColor("_Color", SpineHandles.BoneColor); + } + return _boneMaterial; + } + } + + static Material _ikMaterial; + public static Material IKMaterial { + get { + if (_ikMaterial == null) { + _ikMaterial = new Material(Shader.Find("Hidden/Spine/Bones")); + _ikMaterial.SetColor("_Color", SpineHandles.IkColor); + } + return _ikMaterial; + } + } + + static GUIStyle _boneNameStyle; + public static GUIStyle BoneNameStyle { + get { + if (_boneNameStyle == null) { + _boneNameStyle = new GUIStyle(EditorStyles.whiteMiniLabel); + _boneNameStyle.alignment = TextAnchor.MiddleCenter; + _boneNameStyle.stretchWidth = true; + _boneNameStyle.padding = new RectOffset(0, 0, 0, 0); + _boneNameStyle.contentOffset = new Vector2(-5f, 0f); + } + return _boneNameStyle; + } + } + + public static Color BoneColor { get { return new Color(0.8f, 0.8f, 0.8f, 0.4f); } } + public static Color PathColor { get { return new Color(254/255f, 127/255f, 0); } } + public static Color TransformContraintColor { get { return new Color(170/255f, 226/255f, 35/255f); } } + public static Color IkColor { get { return new Color(228/255f,90/255f,43/255f); } } + + static GUIStyle _pathNameStyle; + public static GUIStyle PathNameStyle { + get { + if (_pathNameStyle == null) { + _pathNameStyle = new GUIStyle(SpineHandles.BoneNameStyle); + _pathNameStyle.normal.textColor = SpineHandles.PathColor; + } + return _pathNameStyle; + } + } + + public static void DrawBoneNames (Transform transform, Skeleton skeleton) { + GUIStyle style = BoneNameStyle; + foreach (Bone b in skeleton.Bones) { + var pos = new Vector3(b.WorldX, b.WorldY, 0) + (new Vector3(b.A, b.C) * (b.Data.Length * 0.5f)); + pos = transform.TransformPoint(pos); + Handles.Label(pos, b.Data.Name, style); + } + } + + public static void DrawBones (Transform transform, Skeleton skeleton) { + float boneScale = 1.8f; // Draw the root bone largest; + DrawCrosshairs(skeleton.Bones.Items[0].GetWorldPosition(transform), 0.08f); + + foreach (Bone b in skeleton.Bones) { + DrawBone(transform, b, boneScale); + boneScale = 1f; + } + } + + static void DrawCrosshairs (Vector3 position, float scale) { + Handles.DrawLine(position + new Vector3(-scale, 0), position + new Vector3(scale, 0)); + Handles.DrawLine(position + new Vector3(0, -scale), position + new Vector3(0, scale)); + } + + public static void DrawBone (Transform transform, Bone b, float boneScale) { + Vector3 pos = new Vector3(b.WorldX, b.WorldY, 0); + float length = b.Data.Length; + if (length > 0) { + Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX - 90f); + Vector3 scale = Vector3.one * length * b.WorldScaleX; + const float mx = 2f; + scale.x = Mathf.Clamp(scale.x, -mx, mx); + SpineHandles.BoneMaterial.SetPass(0); + Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale)); + } else { + var wp = transform.TransformPoint(pos); + DrawBoneCircle(wp, SpineHandles.BoneColor, boneScale); + } + } + + static void DrawBoneCircle (Vector3 pos, Color outlineColor, float scale = 1f) { + Color o = Handles.color; + Handles.color = outlineColor; + float firstScale = 0.08f * scale; + Handles.DrawSolidDisc(pos, Vector3.back, firstScale); + const float Thickness = 0.03f; + float secondScale = firstScale - Thickness; + + if (secondScale > 0f) { + Handles.color = new Color(0.3f, 0.3f, 0.3f, 0.5f); + Handles.DrawSolidDisc(pos, Vector3.back, secondScale); + } + + Handles.color = o; + } + + public static void DrawPaths (Transform transform, Skeleton skeleton) { + foreach (Slot s in skeleton.DrawOrder) { + var p = s.Attachment as PathAttachment; + if (p != null) { + SpineHandles.DrawPath(s, p, transform, true); + } + } } static float[] pathVertexBuffer; - static public void DrawPath (Slot s, PathAttachment p, Transform t) { + public static void DrawPath (Slot s, PathAttachment p, Transform t, bool includeName) { int worldVerticesLength = p.WorldVerticesLength; if (pathVertexBuffer == null || pathVertexBuffer.Length < worldVerticesLength) pathVertexBuffer = new float[worldVerticesLength]; - + float[] pv = pathVertexBuffer; p.ComputeWorldVertices(s, pv); var ocolor = Handles.color; - Handles.color = new Color(254f/255f, 127f/255f, 0); // Path orange + Handles.color = SpineHandles.PathColor; Matrix4x4 m = t.localToWorldMatrix; const int step = 6; @@ -1445,38 +1570,50 @@ namespace Spine.Unity.Editor { } const float endCapSize = 0.05f; - var q = Quaternion.identity; - Handles.DotCap(0, m.MultiplyPoint(new Vector3(pv[2], pv[3])), q, endCapSize); -// if (!p.Closed) Handles.DotCap(0, m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])), q, endCapSize); + Vector3 firstPoint = m.MultiplyPoint(new Vector3(pv[2], pv[3])); + Handles.DotCap(0, firstPoint, Quaternion.identity, endCapSize * HandleUtility.GetHandleSize(firstPoint)); + // if (!p.Closed) Handles.DotCap(0, m.MultiplyPoint(new Vector3(pv[n - 4], pv[n - 3])), q, endCapSize); + if (includeName) Handles.Label(firstPoint + new Vector3(0,0.1f), p.Name, PathNameStyle); Handles.color = ocolor; } - static public void DrawCubicBezier (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { + internal static void DrawCubicBezier (Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { Handles.DrawBezier(p0, p3, p1, p2, Handles.color, Texture2D.whiteTexture, 2f); -// const float dotSize = 0.01f; -// Quaternion q = Quaternion.identity; -// Handles.DotCap(0, p0, q, dotSize); -// Handles.DotCap(0, p1, q, dotSize); -// Handles.DotCap(0, p2, q, dotSize); -// Handles.DotCap(0, p3, q, dotSize); -// Handles.DrawLine(p0, p1); -// Handles.DrawLine(p3, p2); + // const float dotSize = 0.01f; + // Quaternion q = Quaternion.identity; + // Handles.DotCap(0, p0, q, dotSize); + // Handles.DotCap(0, p1, q, dotSize); + // Handles.DotCap(0, p2, q, dotSize); + // Handles.DotCap(0, p3, q, dotSize); + // Handles.DrawLine(p0, p1); + // Handles.DrawLine(p3, p2); } - static public void DrawBoundingBox (Slot slot, BoundingBoxAttachment box) { + public static void DrawBoundingBoxes (Transform transform, Skeleton skeleton) { + foreach (var slot in skeleton.Slots) { + var bba = slot.Attachment as BoundingBoxAttachment; + if (bba != null) + SpineHandles.DrawBoundingBox(slot, bba, transform); + } + } + + public static void DrawBoundingBox (Slot slot, BoundingBoxAttachment box, Transform t) { if (box.Vertices.Length <= 0) return; // Handle cases where user creates a BoundingBoxAttachment but doesn't actually define it. var worldVerts = new float[box.Vertices.Length]; box.ComputeWorldVertices(slot, worldVerts); Handles.color = Color.green; - Vector3 lastVert = Vector3.back; - Vector3 vert = Vector3.back; - Vector3 firstVert = new Vector3(worldVerts[0], worldVerts[1], -1); + Vector3 lastVert = Vector3.zero; + Vector3 vert = Vector3.zero; + Vector3 firstVert = t.TransformPoint(new Vector3(worldVerts[0], worldVerts[1], 0)); for (int i = 0; i < worldVerts.Length; i += 2) { vert.x = worldVerts[i]; vert.y = worldVerts[i + 1]; + vert.z = 0; + + vert = t.TransformPoint(vert); if (i > 0) Handles.DrawLine(lastVert, vert); @@ -1486,10 +1623,75 @@ namespace Spine.Unity.Editor { Handles.DrawLine(lastVert, firstVert); } - #endregion - public static string GetPathSafeRegionName (AtlasRegion region) { - return region.name.Replace("/", "_"); + public static void DrawConstraints (Transform transform, Skeleton skeleton) { + Vector3 targetPos; + Vector3 pos; + bool active; + Color handleColor; + const float Thickness = 4f; + + handleColor = SpineHandles.TransformContraintColor; + foreach (var tc in skeleton.TransformConstraints) { + targetPos = tc.Target.GetWorldPosition(transform); + + if (tc.TranslateMix > 0) { + if (tc.TranslateMix != 1f) { + Handles.color = handleColor; + foreach (var b in tc.Bones) { + pos = b.GetWorldPosition(transform); + Handles.DrawDottedLine(targetPos, pos, Thickness); + } + } + SpineHandles.DrawBoneCircle(targetPos, handleColor, 1.3f); + Handles.color = handleColor; + SpineHandles.DrawCrosshairs(targetPos, 0.2f); + } + } + + handleColor = SpineHandles.IkColor; + foreach (var ikc in skeleton.IkConstraints) { + targetPos = ikc.Target.GetWorldPosition(transform); + var bones = ikc.Bones; + active = ikc.Mix > 0; + if (active) { + pos = bones.Items[0].GetWorldPosition(transform); + switch (bones.Count) { + case 1: { + Handles.color = handleColor; + Handles.DrawLine(targetPos, pos); + SpineHandles.DrawBoneCircle(targetPos, handleColor); + SpineHandles.DrawArrowhead(targetPos, bones.Items[0].WorldRotationX, 0.1f); + break; + } + case 2: { + Vector3 child = bones.Items[1].GetWorldPosition(transform); + Handles.color = handleColor; + Handles.DrawLine(child, pos); + Handles.DrawLine(targetPos, child); + SpineHandles.DrawBoneCircle(child, handleColor, 0.5f); + SpineHandles.DrawBoneCircle(pos, handleColor, 0.5f); + SpineHandles.DrawBoneCircle(targetPos, handleColor); + SpineHandles.DrawArrowhead(targetPos, bones.Items[1].WorldRotationX, 0.1f); + break; + } + } + } + //Handles.Label(targetPos, ikc.Data.Name, SpineHandles.BoneNameStyle); + } + + handleColor = SpineHandles.PathColor; + foreach (var pc in skeleton.PathConstraints) { + active = pc.TranslateMix > 0; + if (active) + foreach (var b in pc.Bones) + SpineHandles.DrawBoneCircle(b.GetWorldPosition(transform), handleColor, 1.2f); + } + } + + static void DrawArrowhead (Vector3 pos, float localRotation, float scale) { + SpineHandles.IKMaterial.SetPass(0); + Graphics.DrawMeshNow(SpineHandles.ArrowheadMesh, Matrix4x4.TRS(pos, Quaternion.Euler(0, 0, localRotation), new Vector3(scale, scale, scale))); } } diff --git a/spine-unity/Assets/spine-unity/Shaders/Bones.shader b/spine-unity/Assets/spine-unity/Shaders/Bones.shader index 055d9d329..933469419 100644 --- a/spine-unity/Assets/spine-unity/Shaders/Bones.shader +++ b/spine-unity/Assets/spine-unity/Shaders/Bones.shader @@ -18,7 +18,7 @@ Category { CGPROGRAM #pragma vertex vert #pragma fragment frag - #pragma multi_compile_particles +// #pragma multi_compile_particles #include "UnityCG.cginc" @@ -35,21 +35,20 @@ Category { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; - #ifdef SOFTPARTICLES_ON - float4 projPos : TEXCOORD1; - #endif +// #ifdef SOFTPARTICLES_ON +// float4 projPos : TEXCOORD1; +// #endif }; float4 _MainTex_ST; - v2f vert (appdata_t v) - { + v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); - #ifdef SOFTPARTICLES_ON - o.projPos = ComputeScreenPos (o.vertex); - COMPUTE_EYEDEPTH(o.projPos.z); - #endif +// #ifdef SOFTPARTICLES_ON +// o.projPos = ComputeScreenPos (o.vertex); +// COMPUTE_EYEDEPTH(o.projPos.z); +// #endif o.color = v.color; o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex); return o; @@ -57,9 +56,8 @@ Category { sampler2D_float _CameraDepthTexture; - fixed4 frag (v2f i) : SV_Target - { - return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord); + fixed4 frag (v2f i) : SV_Target { + return i.color * _Color * tex2D(_MainTex, i.texcoord); } ENDCG } diff --git a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs index 5fc793ad5..7773bf8ea 100644 --- a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs +++ b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs @@ -118,6 +118,12 @@ namespace Spine.Unity { return new Vector2(bone.worldX, bone.worldY); } + public static Vector2 GetSkeletonSpacePosition (this Bone bone, Vector2 boneLocal) { + Vector2 o; + bone.LocalToWorld(boneLocal.x, boneLocal.y, out o.x, out o.y); + return o; + } + public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) { return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY)); } @@ -142,15 +148,23 @@ namespace Spine.Unity { #region Attachments public static Material GetMaterial (this Attachment a) { + object rendererObject = null; var regionAttachment = a as RegionAttachment; if (regionAttachment != null) - return (Material)((AtlasRegion)regionAttachment.RendererObject).page.rendererObject; + rendererObject = regionAttachment.RendererObject; var meshAttachment = a as MeshAttachment; if (meshAttachment != null) - return (Material)((AtlasRegion)meshAttachment.RendererObject).page.rendererObject; + rendererObject = meshAttachment.RendererObject; - return null; + if (rendererObject == null) + return null; + + #if SPINE_TK2D + return (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject; + #else + return (Material)((AtlasRegion)rendererObject).page.rendererObject; + #endif } /// Fills a Vector2 buffer with local vertices. diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs index 3703bf4bd..57ccbbc60 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs @@ -46,8 +46,9 @@ namespace Spine.Unity.Editor { SkeletonUtility skeletonUtility; Skeleton skeleton; SkeletonRenderer skeletonRenderer; - Transform transform; + bool isPrefab; + //Transform transform; Dictionary> attachmentTable = new Dictionary>(); @@ -61,7 +62,7 @@ namespace Spine.Unity.Editor { skeletonUtility = (SkeletonUtility)target; skeletonRenderer = skeletonUtility.GetComponent(); skeleton = skeletonRenderer.skeleton; - transform = skeletonRenderer.transform; + //transform = skeletonRenderer.transform; if (skeleton == null) { skeletonRenderer.Initialize(false); @@ -74,31 +75,7 @@ namespace Spine.Unity.Editor { UpdateAttachments(); isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab; } - - void OnSceneGUI () { - if (skeleton == null) { - OnEnable(); - return; - } - - var m = transform.localToWorldMatrix; - foreach (Bone b in skeleton.Bones) { - Vector3 pos = new Vector3(b.WorldX, b.WorldY, 0); - Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX - 90f); - Vector3 scale = Vector3.one * b.Data.Length * b.WorldScaleX; - const float mx = 2f; - scale.x = Mathf.Clamp(scale.x, -mx, mx); - SpineEditorUtilities.DrawBone(m * Matrix4x4.TRS(pos, rot, scale)); - } - - if (showPaths) { - foreach (Slot s in skeleton.DrawOrder) { - var p = s.Attachment as PathAttachment; - if (p != null) SpineEditorUtilities.DrawPath(s, p, transform); - } - } - } - + public override void OnInspectorGUI () { bool requireRepaint = false;