public override void OnInspectorGUI() { // Restore mesh part for undo logic after undo of "Add Parts Renderer". // Triggers regeneration and assignment of the mesh filter's mesh. if (component.GetComponent <MeshFilter>() && component.GetComponent <MeshFilter>().sharedMesh == null) { component.OnDisable(); component.OnEnable(); } var componentRenderers = component.partsRenderers; int totalParts; using (new SpineInspectorUtility.LabelWidthScope()) { bool componentEnabled = component.enabled; bool checkBox = EditorGUILayout.Toggle("Enable Separator", componentEnabled); if (checkBox != componentEnabled) { component.enabled = checkBox; } if (component.SkeletonRenderer.disableRenderingOnOverride && !component.enabled) { EditorGUILayout.HelpBox("By default, SkeletonRenderer's MeshRenderer is disabled while the SkeletonRenderSeparator takes over rendering. It is re-enabled when SkeletonRenderSeparator is disabled.", MessageType.Info); } EditorGUILayout.PropertyField(copyPropertyBlock_); EditorGUILayout.PropertyField(copyMeshRendererFlags_); } // SkeletonRenderer Box using (new SpineInspectorUtility.BoxScope(false)) { // Fancy SkeletonRenderer foldout reference field { EditorGUI.indentLevel++; EditorGUI.BeginChangeCheck(); var foldoutSkeletonRendererRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); EditorGUI.PropertyField(foldoutSkeletonRendererRect, skeletonRenderer_); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } if (component.SkeletonRenderer != null) { skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, ""); } EditorGUI.indentLevel--; } int separatorCount = 0; EditorGUI.BeginChangeCheck(); if (component.SkeletonRenderer != null) { // Separators from SkeletonRenderer { bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer; if (separatorNamesProp == null || skeletonRendererMismatch) { if (component.SkeletonRenderer != null) { skeletonRendererSerializedObject = new SerializedObject(component.SkeletonRenderer); separatorNamesProp = skeletonRendererSerializedObject.FindProperty("separatorSlotNames"); separatorNamesProp.isExpanded = true; } } if (separatorNamesProp != null) { if (skeletonRendererExpanded) { EditorGUI.indentLevel++; SkeletonRendererInspector.SeparatorsField(separatorNamesProp); EditorGUI.indentLevel--; } separatorCount = this.SkeletonRendererSeparatorCount; } } 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); } } if (EditorGUI.EndChangeCheck()) { skeletonRendererSerializedObject.ApplyModifiedProperties(); if (!Application.isPlaying) { slotsReapplyRequired = true; } } totalParts = separatorCount + 1; 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 using (new SpineInspectorUtility.BoxScope(false)) { EditorGUI.indentLevel++; 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; foreach (var r in componentRenderers) { 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)); if (GUILayout.Button(addMissingLabel, GUILayout.Height(40f))) { AddPartsRenderer(extraRenderersNeeded); DetectOrphanedPartsRenderers(component); partsRendererInitRequired = true; } } } 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? Undo.RegisterCompleteObjectUndo(component, "Clear Parts Renderers"); if (EditorUtility.DisplayDialog("Destroy Renderers", "Do you really want to destroy all the Parts Renderer GameObjects in the list?", "Destroy", "Cancel")) { foreach (var r in componentRenderers) { if (r != null) { Undo.DestroyObjectImmediate(r.gameObject); } } componentRenderers.Clear(); // Do you also want to destroy orphans? (You monster.) DetectOrphanedPartsRenderers(component); } } } // (Button) Add Part Renderer button if (GUILayout.Button("Add Parts Renderer")) { AddPartsRenderer(1); partsRendererInitRequired = true; } } } } serializedObject.ApplyModifiedProperties(); if (partsRendererInitRequired) { Undo.RegisterCompleteObjectUndo(component.GetComponent <MeshRenderer>(), "Add Parts Renderers"); component.OnEnable(); partsRendererInitRequired = false; } if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) { component.SkeletonRenderer.ReapplySeparatorSlotNames(); component.SkeletonRenderer.LateUpdate(); SceneView.RepaintAll(); slotsReapplyRequired = false; } }
public override void OnInspectorGUI() { // TODO: Add Undo support var componentRenderers = component.partsRenderers; int totalParts; bool componentEnabled = component.enabled; bool checkBox = EditorGUILayout.Toggle("Enable Separator", componentEnabled); if (checkBox != componentEnabled) { component.enabled = checkBox; } EditorGUILayout.PropertyField(copyPropertyBlock_); EditorGUILayout.PropertyField(copyMeshRendererFlags_); // SkeletonRenderer Box using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { // Fancy SkeletonRenderer foldout reference field { EditorGUI.indentLevel++; EditorGUI.BeginChangeCheck(); var foldoutSkeletonRendererRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); EditorGUI.PropertyField(foldoutSkeletonRendererRect, skeletonRenderer_); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } if (component.SkeletonRenderer != null) { skeletonRendererExpanded = EditorGUI.Foldout(foldoutSkeletonRendererRect, skeletonRendererExpanded, ""); } EditorGUI.indentLevel--; } int separatorCount = 0; EditorGUI.BeginChangeCheck(); if (component.SkeletonRenderer != null) { // Separators from SkeletonRenderer { bool skeletonRendererMismatch = skeletonRendererSerializedObject != null && skeletonRendererSerializedObject.targetObject != component.SkeletonRenderer; if (separatorNamesProp == null || skeletonRendererMismatch) { if (component.SkeletonRenderer != null) { skeletonRendererSerializedObject = new SerializedObject(component.SkeletonRenderer); separatorNamesProp = skeletonRendererSerializedObject.FindProperty("separatorSlotNames"); separatorNamesProp.isExpanded = true; } } if (separatorNamesProp != null) { if (skeletonRendererExpanded) { EditorGUI.indentLevel++; SkeletonRendererInspector.SeparatorsField(separatorNamesProp); EditorGUI.indentLevel--; } separatorCount = this.SkeletonRendererSeparatorCount; } } 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); } } if (EditorGUI.EndChangeCheck()) { skeletonRendererSerializedObject.ApplyModifiedProperties(); } totalParts = separatorCount + 1; 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 using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUI.indentLevel++; 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; foreach (var r in componentRenderers) { 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)); if (GUILayout.Button(addMissingLabel, GUILayout.Height(40f))) { AddPartsRenderer(extraRenderersNeeded); DetectOrphanedPartsRenderers(component); } } } 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); } } } // (Button) Add Part Renderer button if (GUILayout.Button("Add Parts Renderer")) { AddPartsRenderer(1); } } } } serializedObject.ApplyModifiedProperties(); }