From 46ee116ee397b144d74a620168a4356d7cf8d96a Mon Sep 17 00:00:00 2001 From: pharan Date: Thu, 24 Mar 2016 00:35:19 +0800 Subject: [PATCH] RenderSeparator update. --- .../Arrays/ArraysSubmeshedMeshGenerator.cs | 4 +- .../ISubmeshedMeshGenerator.cs | 2 +- .../Editor/SkeletonGraphicInspector.cs | 10 +- .../Editor/SkeletonPartsRendererInspector.cs | 22 ++-- .../SkeletonRenderSeparatorInspector.cs | 122 ++++++++++-------- .../SkeletonRenderSeparator.cs | 55 ++++---- 6 files changed, 114 insertions(+), 101 deletions(-) diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Arrays/ArraysSubmeshedMeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/Arrays/ArraysSubmeshedMeshGenerator.cs index 2dd4c3903..6c9ef8d57 100644 --- a/spine-unity/Assets/spine-unity/Mesh Generation/Arrays/ArraysSubmeshedMeshGenerator.cs +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Arrays/ArraysSubmeshedMeshGenerator.cs @@ -119,7 +119,7 @@ namespace Spine.Unity.MeshGeneration { startSlot = submeshStartSlotIndex, endSlot = i, firstVertexIndex = submeshFirstVertex, - separatedBySlot = separatedBySlot + forceSeparate = separatedBySlot } ); @@ -147,7 +147,7 @@ namespace Spine.Unity.MeshGeneration { startSlot = submeshStartSlotIndex, endSlot = drawOrderCount, firstVertexIndex = submeshFirstVertex, - separatedBySlot = false + forceSeparate = false } ); diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs index 3662f3aac..285653ad7 100644 --- a/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs +++ b/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs @@ -51,7 +51,7 @@ namespace Spine.Unity.MeshGeneration { // Vertex index offset. Used by submesh generation if part of a bigger mesh. public int firstVertexIndex; - public bool separatedBySlot; + public bool forceSeparate; /// The number of slots in this SubmeshInstruction's range. Not necessarily the number of attachments. public int SlotCount { get { return endSlot - startSlot; } } diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs index 639b9af05..3f80d3efc 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs @@ -36,10 +36,10 @@ using UnityEngine; using UnityEditor; using Spine; -namespace Spine.Unity { +namespace Spine.Unity.Editor { [CustomEditor(typeof(SkeletonGraphic))] - public class SkeletonGraphicInspector : Editor { + public class SkeletonGraphicInspector : UnityEditor.Editor { SerializedProperty material_, color_; SerializedProperty skeletonDataAsset_, initialSkinName_; SerializedProperty startingAnimation_, startingLoop_, timeScale_, freeze_; @@ -133,7 +133,7 @@ namespace Spine.Unity { } } - [MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 10)] + [MenuItem("GameObject/Spine/SkeletonGraphic (UnityUI)", false, 15)] static public void SkeletonGraphicCreateMenuItem () { var parentGameObject = Selection.activeObject as GameObject; var parentTransform = parentGameObject == null ? null : parentGameObject.GetComponent(); @@ -149,7 +149,7 @@ namespace Spine.Unity { EditorGUIUtility.PingObject(Selection.activeObject); } - [MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 10)] + [MenuItem("Assets/Spine/Instantiate (UnityUI)", false, 20)] 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, 10)] + [MenuItem("Assets/Spine/Instantiate (UnityUI)", true, 20)] static bool ValidateInstantiateSkeletonGraphic () { Object[] arr = Selection.objects; diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs index fe9afbd72..15db2ef77 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs @@ -3,17 +3,19 @@ using System.Collections; using UnityEditor; using Spine.Unity; -[CustomEditor(typeof(SkeletonPartsRenderer))] -public class SkeletonRenderPartInspector : Editor { - SpineInspectorUtility.SerializedSortingProperties sortingProperties; +namespace Spine.Unity.Editor { + [CustomEditor(typeof(SkeletonPartsRenderer))] + public class SkeletonRenderPartInspector : UnityEditor.Editor { + SpineInspectorUtility.SerializedSortingProperties sortingProperties; - void OnEnable () { - var component = target as Component; - sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(component.GetComponent()); + void OnEnable () { + sortingProperties = new SpineInspectorUtility.SerializedSortingProperties((target as Component).GetComponent()); + } + + public override void OnInspectorGUI () { + DrawDefaultInspector(); + SpineInspectorUtility.SortingPropertyFields(sortingProperties, true); + } } - public override void OnInspectorGUI () { - DrawDefaultInspector(); - SpineInspectorUtility.SortingPropertyFields(sortingProperties, true); - } } diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs index 3ce84e85a..95eb165f4 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs @@ -1,20 +1,22 @@ using UnityEngine; using UnityEditor; -namespace Spine.Unity { +using Spine.Unity; + +namespace Spine.Unity.Editor { [CustomEditor(typeof(SkeletonRenderSeparator))] - public class SkeletonRenderSeparatorInspector : Editor { + public class SkeletonRenderSeparatorInspector : UnityEditor.Editor { SkeletonRenderSeparator component; // Properties SerializedProperty skeletonRenderer_, copyPropertyBlock_, copyMeshRendererFlags_, partsRenderers_; + static bool partsRenderersExpanded = false; // For separator field. SerializedObject skeletonRendererSerializedObject; SerializedProperty separatorNamesProp; - bool separatorExpanded = true; - System.Func Plural = SpineInspectorUtility.Pluralize; + static bool skeletonRendererExpanded = true; void OnEnable () { if (component == null) @@ -23,14 +25,28 @@ namespace Spine.Unity { skeletonRenderer_ = serializedObject.FindProperty("skeletonRenderer"); copyPropertyBlock_ = serializedObject.FindProperty("copyPropertyBlock"); copyMeshRendererFlags_ = serializedObject.FindProperty("copyMeshRendererFlags"); + + var partsRenderers = component.partsRenderers; partsRenderers_ = serializedObject.FindProperty("partsRenderers"); - partsRenderers_.isExpanded = true; + partsRenderers_.isExpanded = partsRenderersExpanded || // last state + partsRenderers.Contains(null) || // null items found + partsRenderers.Count < 1 || // no parts renderers + (skeletonRenderer_.objectReferenceValue != null && SkeletonRendererSeparatorCount + 1 > partsRenderers.Count); // not enough parts renderers + } + + int SkeletonRendererSeparatorCount { + get { + if (Application.isPlaying) { + return component.SkeletonRenderer.separatorSlots.Count; + } else { + return separatorNamesProp == null ? 0 : separatorNamesProp.arraySize; + } + } } public override void OnInspectorGUI () { // TODO: Add Undo support var componentRenderers = component.partsRenderers; - int separatorCount = 0; int totalParts; bool componentEnabled = component.enabled; @@ -42,6 +58,7 @@ namespace Spine.Unity { EditorGUILayout.PropertyField(copyPropertyBlock_); EditorGUILayout.PropertyField(copyMeshRendererFlags_); + // SkeletonRenderer Box using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { // Fancy SkeletonRenderer foldout reference field { @@ -52,14 +69,15 @@ namespace Spine.Unity { if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties(); if (component.SkeletonRenderer != null) { - separatorExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, separatorExpanded, ""); + skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, ""); } EditorGUI.indentLevel--; } + int separatorCount = 0; EditorGUI.BeginChangeCheck(); if (component.SkeletonRenderer != null) { - // SubmeshSeparators from SkeletonRenderer + // Separators from SkeletonRenderer { bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer; if (separatorNamesProp == null || skeletonRendererMismatch) { @@ -71,21 +89,16 @@ namespace Spine.Unity { } if (separatorNamesProp != null) { - if (separatorExpanded) { + if (skeletonRendererExpanded) { EditorGUI.indentLevel++; SkeletonRendererInspector.SeparatorsField(separatorNamesProp); EditorGUI.indentLevel--; } - - if (Application.isPlaying) - separatorCount = component.SkeletonRenderer.separatorSlots.Count; - else - separatorCount = separatorNamesProp.arraySize; - + separatorCount = this.SkeletonRendererSeparatorCount; } } - if (separatorCount == 0) { + if (SkeletonRendererSeparatorCount == 0) { EditorGUILayout.HelpBox("Separators are empty. Change the size to 1 and choose a slot if you want the render to be separated.", MessageType.Info); } } @@ -93,8 +106,8 @@ namespace Spine.Unity { skeletonRendererSerializedObject.ApplyModifiedProperties(); totalParts = separatorCount + 1; - var counterStyle = separatorExpanded ? EditorStyles.label : EditorStyles.miniLabel; - EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", Plural(separatorCount, "separator", "separators"), Plural(totalParts, "part", "parts") ), counterStyle); + var counterStyle = skeletonRendererExpanded ? EditorStyles.label : EditorStyles.miniLabel; + EditorGUILayout.LabelField(string.Format("{0}: separates into {1}.", SpineInspectorUtility.Pluralize(separatorCount, "separator", "separators"), SpineInspectorUtility.Pluralize(totalParts, "part", "parts") ), counterStyle); } // Parts renderers @@ -103,6 +116,11 @@ namespace Spine.Unity { EditorGUILayout.PropertyField(this.partsRenderers_, true); EditorGUI.indentLevel--; + // Null items warning + bool nullItemsFound = componentRenderers.Contains(null); + if (nullItemsFound) + EditorGUILayout.HelpBox("Some items in the parts renderers list are null and may cause problems.\n\nYou can right-click on that element and choose 'Delete Array Element' to remove it.", MessageType.Warning); + // (Button) Match Separators count if (separatorNamesProp != null) { int currentRenderers = 0; @@ -110,39 +128,40 @@ namespace Spine.Unity { if (r != null) currentRenderers++; } - int extraRenderersNeeded = totalParts - currentRenderers; if (component.enabled && component.SkeletonRenderer != null && extraRenderersNeeded > 0) { EditorGUILayout.HelpBox(string.Format("Insufficient parts renderers. Some parts will not be rendered."), MessageType.Warning); string addMissingLabel = string.Format("Add the missing renderer{1} ({0}) ", extraRenderersNeeded, SpineInspectorUtility.PluralThenS(extraRenderersNeeded)); - //var addMissingContentButtonContent = new GUIContent("Add", GUIUtility.) if (GUILayout.Button(addMissingLabel, GUILayout.Height(40f))) { AddPartsRenderer(extraRenderersNeeded); DetectOrphanedPartsRenderers(component); } } } - - using (new EditorGUILayout.HorizontalScope()) { - // (Button) Destroy Renderers button - if (componentRenderers.Count > 0) { - if (GUILayout.Button("Clear Parts Renderers")) { - // Do you really want to destroy all? - if (EditorUtility.DisplayDialog("Destroy Renderers", "Do you really want to destroy all the Parts Renderer GameObjects in the list? (Undo will not work.)", "Destroy", "Cancel")) { - foreach (var r in componentRenderers) { - if (r != null) - DestroyImmediate(r.gameObject, allowDestroyingAssets: false); + + if (partsRenderers_.isExpanded != partsRenderersExpanded) partsRenderersExpanded = partsRenderers_.isExpanded; + if (partsRenderers_.isExpanded) { + using (new EditorGUILayout.HorizontalScope()) { + // (Button) Destroy Renderers button + if (componentRenderers.Count > 0) { + if (GUILayout.Button("Clear Parts Renderers")) { + // Do you really want to destroy all? + if (EditorUtility.DisplayDialog("Destroy Renderers", "Do you really want to destroy all the Parts Renderer GameObjects in the list? (Undo will not work.)", "Destroy", "Cancel")) { + foreach (var r in componentRenderers) { + if (r != null) + DestroyImmediate(r.gameObject, allowDestroyingAssets: false); + } + componentRenderers.Clear(); + // Do you also want to destroy orphans? (You monster.) + DetectOrphanedPartsRenderers(component); } - componentRenderers.Clear(); - // Do you also want to destroy orphans? (You monster.) - DetectOrphanedPartsRenderers(component); } } - } - // (Button) Add Part Renderer button - if (GUILayout.Button("Add (1) Parts Renderer")) - AddPartsRenderer(1); + // (Button) Add Part Renderer button + if (GUILayout.Button("Add Parts Renderer")) + AddPartsRenderer(1); + } } } @@ -151,7 +170,7 @@ namespace Spine.Unity { public void AddPartsRenderer (int count) { var componentRenderers = component.partsRenderers; - bool emptyFound = componentRenderers.Exists(x => x == null); + bool emptyFound = componentRenderers.Contains(null); if (emptyFound) { bool userClearEntries = EditorUtility.DisplayDialog("Empty entries found", "Null entries found. Do you want to remove null entries before adding the new renderer? ", "Clear Empty Entries", "Don't Clear"); if (userClearEntries) componentRenderers.RemoveAll(x => x == null); @@ -164,20 +183,17 @@ namespace Spine.Unity { EditorGUIUtility.PingObject(smr); // increment renderer sorting order. - if (index != 0) { - var prev = componentRenderers[index - 1]; - if (prev != null) { - var prevMeshRenderer = prev.GetComponent(); - var currentMeshRenderer = smr.GetComponent(); - if (prevMeshRenderer != null && currentMeshRenderer != null) { - int prevSortingLayer = prevMeshRenderer.sortingLayerID; - int prevSortingOrder = prevMeshRenderer.sortingOrder; + if (index == 0) continue; + var prev = componentRenderers[index - 1]; if (prev == null) continue; - currentMeshRenderer.sortingLayerID = prevSortingLayer; - currentMeshRenderer.sortingOrder = prevSortingOrder + SkeletonRenderSeparator.DefaultSortingOrderIncrement; - } - } - } + var prevMeshRenderer = prev.GetComponent(); + var currentMeshRenderer = smr.GetComponent(); + if (prevMeshRenderer == null || currentMeshRenderer == null) continue; + + int prevSortingLayer = prevMeshRenderer.sortingLayerID; + int prevSortingOrder = prevMeshRenderer.sortingOrder; + currentMeshRenderer.sortingLayerID = prevSortingLayer; + currentMeshRenderer.sortingOrder = prevSortingOrder + SkeletonRenderSeparator.DefaultSortingOrderIncrement; } } @@ -188,9 +204,8 @@ namespace Spine.Unity { var orphans = new System.Collections.Generic.List(); foreach (var r in children) { - if (!component.partsRenderers.Contains(r)) { + if (!component.partsRenderers.Contains(r)) orphans.Add(r); - } } if (orphans.Count > 0) { @@ -202,7 +217,6 @@ namespace Spine.Unity { } } - #region SkeletonRenderer Context Menu Item [MenuItem ("CONTEXT/SkeletonRenderer/Add Skeleton Render Separator")] static void AddRenderSeparatorComponent (MenuCommand cmd) { diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs index 21053876e..29bee2a67 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs @@ -5,8 +5,8 @@ using Spine.Unity; namespace Spine.Unity { - [HelpURL("")] [ExecuteInEditMode] + [HelpURL("https://github.com/pharan/spine-unity-docs/blob/master/SkeletonRenderSeparator.md")] public class SkeletonRenderSeparator : MonoBehaviour { public const int DefaultSortingOrderIncrement = 5; @@ -17,7 +17,7 @@ namespace Spine.Unity { get { return skeletonRenderer; } set { if (skeletonRenderer != null) - skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender; + skeletonRenderer.GenerateMeshOverride -= HandleRender; skeletonRenderer = value; this.enabled = false; // Disable if nulled. @@ -26,6 +26,7 @@ namespace Spine.Unity { MeshRenderer mainMeshRenderer; public bool copyPropertyBlock = false; + [Tooltip("Copies MeshRenderer flags into ")] public bool copyMeshRendererFlags = false; public List partsRenderers = new List(); @@ -42,13 +43,28 @@ namespace Spine.Unity { if (block == null) block = new MaterialPropertyBlock(); mainMeshRenderer = skeletonRenderer.GetComponent(); - skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender; - skeletonRenderer.GenerateMeshOverride += SeparateSkeletonRender; + skeletonRenderer.GenerateMeshOverride -= HandleRender; + skeletonRenderer.GenerateMeshOverride += HandleRender; + + if (copyMeshRendererFlags) { + bool useLightProbes = mainMeshRenderer.useLightProbes; + bool receiveShadows = mainMeshRenderer.receiveShadows; + + for (int i = 0; i < partsRenderers.Count; i++) { + var currentRenderer = partsRenderers[i]; + if (currentRenderer == null) continue; // skip null items. + + var mr = currentRenderer.MeshRenderer; + mr.useLightProbes = useLightProbes; + mr.receiveShadows = receiveShadows; + } + } + } void OnDisable () { if (skeletonRenderer == null) return; - skeletonRenderer.GenerateMeshOverride -= SeparateSkeletonRender; + skeletonRenderer.GenerateMeshOverride -= HandleRender; #if UNITY_EDITOR skeletonRenderer.LateUpdate(); @@ -60,7 +76,7 @@ namespace Spine.Unity { MaterialPropertyBlock block; - void SeparateSkeletonRender (SkeletonRenderer.SmartMesh.Instruction instruction) { + void HandleRender (SkeletonRenderer.SmartMesh.Instruction instruction) { int rendererCount = partsRenderers.Count; if (rendererCount <= 0) return; @@ -75,24 +91,11 @@ namespace Spine.Unity { var currentRenderer = partsRenderers[rendererIndex]; bool skeletonRendererCalculateNormals = skeletonRenderer.calculateNormals; - - bool useLightProbes = false; - bool receiveShadows = false; - - if (copyMeshRendererFlags) { - useLightProbes = mainMeshRenderer.useLightProbes; - receiveShadows = mainMeshRenderer.receiveShadows; - } for (int i = 0, start = 0; i <= lastSubmeshInstruction; i++) { - if (submeshInstructionsItems[i].separatedBySlot) { + if (submeshInstructionsItems[i].forceSeparate) { currentRenderer.RenderParts(instruction.submeshInstructions, start, i + 1); currentRenderer.MeshGenerator.GenerateNormals = skeletonRendererCalculateNormals; - if (copyMeshRendererFlags) { - var mr = currentRenderer.MeshRenderer; - mr.useLightProbes = useLightProbes; - mr.receiveShadows = receiveShadows; - } if (copyPropertyBlock) currentRenderer.SetPropertyBlock(block); @@ -107,19 +110,13 @@ namespace Spine.Unity { } else if (i == lastSubmeshInstruction) { currentRenderer.RenderParts(instruction.submeshInstructions, start, i + 1); currentRenderer.MeshGenerator.GenerateNormals = skeletonRendererCalculateNormals; - if (copyMeshRendererFlags) { - var mr = currentRenderer.MeshRenderer; - mr.useLightProbes = useLightProbes; - mr.receiveShadows = receiveShadows; - } if (copyPropertyBlock) currentRenderer.SetPropertyBlock(block); - - rendererIndex++; } } - - // Too many renderers. Clear the rest. + + // If too many renderers. Clear the rest. + rendererIndex++; if (rendererIndex < rendererCount - 1) { for (int i = rendererIndex; i < rendererCount; i++) { currentRenderer = partsRenderers[i];