Inheritance: UnityEditor.Editor
Esempio n. 1
0
        // Window GUI
        void OnGUI()
        {
            bool requireRepaint = false;

            if (staticLostValues)
            {
                Clear();
                OnSelectionChange();
                staticLostValues = false;
                requireRepaint   = true;
            }

            if (SlotsRootLabel == null)
            {
                SlotsRootLabel                = new GUIContent("Slots", Icons.slotRoot);
                SkeletonRootLabel             = new GUIContent("Skeleton", Icons.skeleton);
                BoldFoldoutStyle              = new GUIStyle(EditorStyles.foldout);
                BoldFoldoutStyle.fontStyle    = FontStyle.Bold;
                BoldFoldoutStyle.stretchWidth = true;
                BoldFoldoutStyle.fixedWidth   = 0;
            }


            EditorGUILayout.Space();
            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.ObjectField(SpineInspectorUtility.TempContent("Debug Selection", Icons.spine), skeletonRenderer, typeof(SkeletonRenderer), true);
            EditorGUI.EndDisabledGroup();

            if (skeleton == null || skeletonRenderer == null)
            {
                EditorGUILayout.HelpBox("No SkeletonRenderer Spine GameObject selected.", MessageType.Info);
                return;
            }

            if (isPrefab)
            {
                EditorGUILayout.HelpBox("SkeletonDebug only debugs Spine GameObjects in the scene.", MessageType.Warning);
                return;
            }

            if (!skeletonRenderer.valid)
            {
                EditorGUILayout.HelpBox("Spine Component is invalid. Check SkeletonData Asset.", MessageType.Error);
                return;
            }

            if (activeSkin != skeleton.Skin)
            {
                UpdateAttachments();
            }

            scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

            using (new SpineInspectorUtility.BoxScope(false)) {
                if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Skeleton.SetToSetupPose()")))
                {
                    skeleton.SetToSetupPose();
                    requireRepaint = true;
                }

                EditorGUI.BeginChangeCheck();
                EditorGUILayout.LabelField("Scene View", EditorStyles.boldLabel);
                using (new SpineInspectorUtility.LabelWidthScope()) {
                    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);
                }
                requireRepaint |= EditorGUI.EndChangeCheck();


                // Skeleton
                showSkeleton.target = EditorGUILayout.Foldout(showSkeleton.target, SkeletonRootLabel, BoldFoldoutStyle);
                if (showSkeleton.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showSkeleton.faded)) {
                            EditorGUI.BeginChangeCheck();

                            EditorGUI.BeginDisabledGroup(true);
                            FalseDropDown(".Skin", skeleton.Skin != null ? skeletonRenderer.Skeleton.Skin.Name : "<None>", Icons.skin);
                            EditorGUI.EndDisabledGroup();

                            // Flip
                            skeleton.ScaleX = EditorGUILayout.DelayedFloatField(".ScaleX", skeleton.ScaleX);
                            skeleton.ScaleY = EditorGUILayout.DelayedFloatField(".ScaleY", skeleton.ScaleY);
                            //EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(160f));
                            ////EditorGUILayout.LabelField("Scale", GUILayout.Width(EditorGUIUtility.labelWidth - 20f));
                            //GUILayout.EndHorizontal();

                            // Color
                            skeleton.SetColor(EditorGUILayout.ColorField(".R .G .B .A", skeleton.GetColor()));

                            requireRepaint |= EditorGUI.EndChangeCheck();
                        }
                    }
                }

                // Bone
                showInspectBoneTree.target = EditorGUILayout.Foldout(showInspectBoneTree.target, SpineInspectorUtility.TempContent("Bone", Icons.bone), BoldFoldoutStyle);
                if (showInspectBoneTree.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showInspectBoneTree.faded)) {
                            showBoneNames = EditorGUILayout.Toggle("Show Bone Names", showBoneNames);
                            if (bpo == null)
                            {
                                bpo = new SerializedObject(this).FindProperty("boneName");
                            }
                            EditorGUILayout.PropertyField(bpo, SpineInspectorUtility.TempContent("Bone"));
                            if (!string.IsNullOrEmpty(bpo.stringValue))
                            {
                                if (bone == null || bone.Data.Name != bpo.stringValue)
                                {
                                    bone = skeleton.FindBone(bpo.stringValue);
                                }

                                if (bone != null)
                                {
                                    using (new EditorGUI.DisabledGroupScope(true)) {
                                        var wm = EditorGUIUtility.wideMode;
                                        EditorGUIUtility.wideMode = true;
                                        EditorGUILayout.Slider("Local Rotation", ViewRound(bone.Rotation), -180f, 180f);
                                        EditorGUILayout.Vector2Field("Local Position", RoundVector2(bone.X, bone.Y));
                                        EditorGUILayout.Vector2Field("Local Scale", RoundVector2(bone.ScaleX, bone.ScaleY));
                                        EditorGUILayout.Vector2Field("Local Shear", RoundVector2(bone.ShearX, bone.ShearY));

                                        EditorGUILayout.Space();

                                        var boneParent = bone.Parent;
                                        if (boneParent != null)
                                        {
                                            FalseDropDown("Parent", boneParent.Data.Name, Icons.bone);
                                        }

                                        const string RoundFormat = "0.##";
                                        var          lw          = EditorGUIUtility.labelWidth;
                                        var          fw          = EditorGUIUtility.fieldWidth;
                                        EditorGUIUtility.labelWidth *= 0.25f;
                                        EditorGUIUtility.fieldWidth *= 0.5f;
                                        EditorGUILayout.LabelField("LocalToWorld");

                                        EditorGUILayout.BeginHorizontal();
                                        EditorGUILayout.Space();
                                        EditorGUILayout.TextField(".A", bone.A.ToString(RoundFormat));
                                        EditorGUILayout.TextField(".B", bone.B.ToString(RoundFormat));
                                        EditorGUILayout.EndHorizontal();
                                        EditorGUILayout.BeginHorizontal();
                                        EditorGUILayout.Space();
                                        EditorGUILayout.TextField(".C", bone.C.ToString(RoundFormat));
                                        EditorGUILayout.TextField(".D", bone.D.ToString(RoundFormat));
                                        EditorGUILayout.EndHorizontal();

                                        EditorGUIUtility.labelWidth = lw * 0.5f;
                                        EditorGUILayout.BeginHorizontal();
                                        EditorGUILayout.Space();
                                        EditorGUILayout.Space();
                                        EditorGUILayout.TextField(".WorldX", bone.WorldX.ToString(RoundFormat));
                                        EditorGUILayout.TextField(".WorldY", bone.WorldY.ToString(RoundFormat));
                                        EditorGUILayout.EndHorizontal();

                                        EditorGUIUtility.labelWidth = lw;
                                        EditorGUIUtility.fieldWidth = fw;
                                        EditorGUIUtility.wideMode   = wm;
                                    }
                                }
                                requireRepaint = true;
                            }
                            else
                            {
                                bone = null;
                            }
                        }
                    }
                }

                // Slots
                int preSlotsIndent = EditorGUI.indentLevel;
                showSlotsTree.target = EditorGUILayout.Foldout(showSlotsTree.target, SlotsRootLabel, BoldFoldoutStyle);
                if (showSlotsTree.faded > 0)
                {
                    using (new EditorGUILayout.FadeGroupScope(showSlotsTree.faded)) {
                        if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Skeleton.SetSlotsToSetupPose()")))
                        {
                            skeleton.SetSlotsToSetupPose();
                            requireRepaint = true;
                        }

                        int baseIndent = EditorGUI.indentLevel;
                        foreach (KeyValuePair <Slot, List <Attachment> > pair in attachmentTable)
                        {
                            Slot slot = pair.Key;

                            using (new EditorGUILayout.HorizontalScope()) {
                                EditorGUI.indentLevel = baseIndent + 1;
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false));
                                EditorGUI.BeginChangeCheck();
                                Color c = EditorGUILayout.ColorField(new Color(slot.R, slot.G, slot.B, slot.A), GUILayout.Width(60));
                                if (EditorGUI.EndChangeCheck())
                                {
                                    slot.SetColor(c);
                                    requireRepaint = true;
                                }
                            }

                            foreach (var attachment in pair.Value)
                            {
                                GUI.contentColor      = slot.Attachment == attachment ? Color.white : Color.grey;
                                EditorGUI.indentLevel = baseIndent + 2;
                                var  icon       = Icons.GetAttachmentIcon(attachment);
                                bool isAttached = (attachment == slot.Attachment);
                                bool swap       = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachment.Name, icon), attachment == slot.Attachment);
                                if (isAttached != swap)
                                {
                                    slot.Attachment = isAttached ? null : attachment;
                                    requireRepaint  = true;
                                }
                                GUI.contentColor = Color.white;
                            }
                        }
                    }
                }
                EditorGUI.indentLevel = preSlotsIndent;

                // Constraints
                const string NoneText = "<none>";
                showConstraintsTree.target = EditorGUILayout.Foldout(showConstraintsTree.target, SpineInspectorUtility.TempContent("Constraints", Icons.constraintRoot), BoldFoldoutStyle);
                if (showConstraintsTree.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showConstraintsTree.faded)) {
                            const float MixMin = 0f;
                            const float MixMax = 1f;
                            EditorGUI.BeginChangeCheck();
                            showConstraints = EditorGUILayout.Toggle("Show Constraints", showConstraints);
                            requireRepaint |= EditorGUI.EndChangeCheck();

                            EditorGUILayout.Space();

                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("IK Constraints ({0})", skeleton.IkConstraints.Count), Icons.constraintIK), EditorStyles.boldLabel);
                            using (new SpineInspectorUtility.IndentScope()) {
                                if (skeleton.IkConstraints.Count > 0)
                                {
                                    foreach (var c in skeleton.IkConstraints)
                                    {
                                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintIK));
                                        FalseDropDown("Goal", c.Data.Target.Name, Icons.bone, true);
                                        using (new EditorGUI.DisabledGroupScope(true)) {
                                            EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Data.Uniform", tooltip: "Uniformly scales a bone when Ik stretches or compresses."), c.Data.Uniform);
                                        }

                                        EditorGUI.BeginChangeCheck();
                                        c.Mix           = EditorGUILayout.Slider("Mix", c.Mix, MixMin, MixMax);
                                        c.BendDirection = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bend Clockwise", tooltip: "IkConstraint.BendDirection == 1 if clockwise; -1 if counterclockwise."), c.BendDirection > 0) ? 1 : -1;
                                        c.Compress      = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Compress", tooltip: "Compress single bone IK when the target too close. Not applied when parent bone has nonuniform scale."), c.Compress);
                                        c.Stretch       = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Stretch", tooltip: "Stretch the parent bone when the target is out of range. Not applied when parent bone has nonuniform scale."), c.Stretch);
                                        if (EditorGUI.EndChangeCheck())
                                        {
                                            requireRepaint = true;
                                        }

                                        EditorGUILayout.Space();
                                    }
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(NoneText);
                                }
                            }

                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("Transform Constraints ({0})", skeleton.TransformConstraints.Count), Icons.constraintTransform), EditorStyles.boldLabel);
                            using (new SpineInspectorUtility.IndentScope()) {
                                if (skeleton.TransformConstraints.Count > 0)
                                {
                                    foreach (var c in skeleton.TransformConstraints)
                                    {
                                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintTransform));
                                        EditorGUI.BeginDisabledGroup(true);
                                        FalseDropDown("Goal", c.Data.Target.Name, Icons.bone);
                                        EditorGUI.EndDisabledGroup();

                                        EditorGUI.BeginChangeCheck();
                                        c.TranslateMix = EditorGUILayout.Slider("TranslateMix", c.TranslateMix, MixMin, MixMax);
                                        c.RotateMix    = EditorGUILayout.Slider("RotateMix", c.RotateMix, MixMin, MixMax);
                                        c.ScaleMix     = EditorGUILayout.Slider("ScaleMix", c.ScaleMix, MixMin, MixMax);
                                        c.ShearMix     = EditorGUILayout.Slider("ShearMix", c.ShearMix, MixMin, MixMax);
                                        if (EditorGUI.EndChangeCheck())
                                        {
                                            requireRepaint = true;
                                        }

                                        EditorGUILayout.Space();
                                    }
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(NoneText);
                                }
                            }

                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("Path Constraints ({0})", skeleton.PathConstraints.Count), Icons.constraintPath), EditorStyles.boldLabel);

                            EditorGUI.BeginChangeCheck();
                            showPaths       = EditorGUILayout.Toggle("Show Paths", showPaths);
                            requireRepaint |= EditorGUI.EndChangeCheck();

                            using (new SpineInspectorUtility.IndentScope()) {
                                if (skeleton.PathConstraints.Count > 0)
                                {
                                    foreach (var c in skeleton.PathConstraints)
                                    {
                                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintPath));
                                        EditorGUI.BeginDisabledGroup(true);
                                        FalseDropDown("Path Slot", c.Data.Target.Name, Icons.slot);
                                        var activeAttachment = c.Target.Attachment;
                                        FalseDropDown("Active Path", activeAttachment != null ? activeAttachment.Name : "<None>", activeAttachment is PathAttachment ? Icons.path : null);
                                        EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode);
                                        EditorGUILayout.LabelField("SpacingMode." + c.Data.SpacingMode);
                                        EditorGUILayout.LabelField("RotateMode." + c.Data.RotateMode);
                                        EditorGUI.EndDisabledGroup();

                                        EditorGUI.BeginChangeCheck();
                                        c.RotateMix    = EditorGUILayout.Slider("RotateMix", c.RotateMix, MixMin, MixMax);
                                        c.TranslateMix = EditorGUILayout.Slider("TranslateMix", c.TranslateMix, MixMin, MixMax);
                                        c.Position     = EditorGUILayout.FloatField("Position", c.Position);
                                        c.Spacing      = EditorGUILayout.FloatField("Spacing", c.Spacing);
                                        if (EditorGUI.EndChangeCheck())
                                        {
                                            requireRepaint = true;
                                        }

                                        EditorGUILayout.Space();
                                    }
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(NoneText);
                                }
                            }
                        }
                    }
                }

                showDrawOrderTree.target = EditorGUILayout.Foldout(showDrawOrderTree.target, SpineInspectorUtility.TempContent("Draw Order and Separators", Icons.slotRoot), BoldFoldoutStyle);

                //var separatorSlotNamesField =
                //SpineInspectorUtility.ge
                if (showDrawOrderTree.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showDrawOrderTree.faded)) {
                            const string SeparatorString = "------------- v SEPARATOR v -------------";

                            if (Application.isPlaying)
                            {
                                foreach (var slot in skeleton.DrawOrder)
                                {
                                    if (skeletonRenderer.separatorSlots.Contains(slot))
                                    {
                                        EditorGUILayout.LabelField(SeparatorString);
                                    }
                                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false));
                                }
                            }
                            else
                            {
                                foreach (var slot in skeleton.DrawOrder)
                                {
                                    var slotNames = SkeletonRendererInspector.GetSeparatorSlotNames(skeletonRenderer);
                                    for (int i = 0, n = slotNames.Length; i < n; i++)
                                    {
                                        if (string.Equals(slotNames[i], slot.Data.Name, System.StringComparison.Ordinal))
                                        {
                                            EditorGUILayout.LabelField(SeparatorString);
                                            break;
                                        }
                                    }
                                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false));
                                }
                            }
                        }
                    }
                }

                showEventDataTree.target = EditorGUILayout.Foldout(showEventDataTree.target, SpineInspectorUtility.TempContent("Events", Icons.userEvent), BoldFoldoutStyle);
                if (showEventDataTree.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showEventDataTree.faded)) {
                            if (skeleton.Data.Events.Count > 0)
                            {
                                foreach (var e in skeleton.Data.Events)
                                {
                                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(e.Name, Icons.userEvent));
                                }
                            }
                            else
                            {
                                EditorGUILayout.LabelField(NoneText);
                            }
                        }
                    }
                }

                showDataTree.target = EditorGUILayout.Foldout(showDataTree.target, SpineInspectorUtility.TempContent("Data Counts", Icons.spine), BoldFoldoutStyle);
                if (showDataTree.faded > 0)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.FadeGroupScope(showDataTree.faded)) {
                            using (new SpineInspectorUtility.LabelWidthScope()) {
                                var skeletonData = skeleton.Data;
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bones", Icons.bone, "Skeleton.Data.Bones"), new GUIContent(skeletonData.Bones.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Slots", Icons.slotRoot, "Skeleton.Data.Slots"), new GUIContent(skeletonData.Slots.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins", Icons.skinsRoot, "Skeleton.Data.Skins"), new GUIContent(skeletonData.Skins.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Events", Icons.userEvent, "Skeleton.Data.Events"), new GUIContent(skeletonData.Events.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("IK Constraints", Icons.constraintIK, "Skeleton.Data.IkConstraints"), new GUIContent(skeletonData.IkConstraints.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Transform Constraints", Icons.constraintTransform, "Skeleton.Data.TransformConstraints"), new GUIContent(skeletonData.TransformConstraints.Count.ToString()));
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Path Constraints", Icons.constraintPath, "Skeleton.Data.PathConstraints"), new GUIContent(skeletonData.PathConstraints.Count.ToString()));
                            }
                        }
                    }
                }

                if (IsAnimating(showSlotsTree, showSkeleton, showConstraintsTree, showDrawOrderTree, showEventDataTree, showInspectBoneTree, showDataTree))
                {
                    Repaint();
                }
            }

            if (requireRepaint)
            {
                skeletonRenderer.LateUpdate();
                Repaint();
                SceneView.RepaintAll();
            }

            EditorGUILayout.EndScrollView();
        }
Esempio n. 2
0
        public override void OnInspectorGUI()
        {
            if (UnityEngine.Event.current.type == EventType.Layout)
            {
                if (forceReloadQueued)
                {
                    forceReloadQueued = false;
                    foreach (var c in targets)
                    {
                        SpineEditorUtilities.ReloadSkeletonDataAssetAndComponent(c as SkeletonGraphic);
                    }
                }
                else
                {
                    foreach (var c in targets)
                    {
                        var component = c as SkeletonGraphic;
                        if (!component.IsValid)
                        {
                            SpineEditorUtilities.ReinitializeComponent(component);
                            if (!component.IsValid)
                            {
                                continue;
                            }
                        }
                    }
                }
            }

            bool wasChanged = false;

            EditorGUI.BeginChangeCheck();

            using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
                SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
                if (GUILayout.Button(ReloadButtonString, ReloadButtonStyle, ReloadButtonWidth))
                {
                    forceReloadQueued = true;
                }
            }

            EditorGUILayout.PropertyField(material);
            EditorGUILayout.PropertyField(color);

            if (thisSkeletonGraphic.skeletonDataAsset == null)
            {
                EditorGUILayout.HelpBox("You need to assign a SkeletonDataAsset first.", MessageType.Info);
                serializedObject.ApplyModifiedProperties();
                serializedObject.Update();
                return;
            }

            string errorMessage = null;

            if (SpineEditorUtilities.Preferences.componentMaterialWarning &&
                MaterialChecks.IsMaterialSetupProblematic(thisSkeletonGraphic, ref errorMessage))
            {
                EditorGUILayout.HelpBox(errorMessage, MessageType.Error, true);
            }

            bool isSingleRendererOnly = (!allowMultipleCanvasRenderers.hasMultipleDifferentValues && allowMultipleCanvasRenderers.boolValue == false);
            bool isSeparationEnabledButNotMultipleRenderers =
                isSingleRendererOnly && (!enableSeparatorSlots.hasMultipleDifferentValues && enableSeparatorSlots.boolValue == true);
            bool meshRendersIncorrectlyWithSingleRenderer =
                isSingleRendererOnly && SkeletonHasMultipleSubmeshes();

            if (isSeparationEnabledButNotMultipleRenderers || meshRendersIncorrectlyWithSingleRenderer)
            {
                meshGeneratorSettings.isExpanded = true;
            }

            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUILayout.PropertyField(meshGeneratorSettings, SpineInspectorUtility.TempContent("Advanced..."), includeChildren: true);
                SkeletonRendererInspector.advancedFoldout = meshGeneratorSettings.isExpanded;

                if (meshGeneratorSettings.isExpanded)
                {
                    EditorGUILayout.Space();
                    using (new SpineInspectorUtility.IndentScope()) {
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.PropertyField(allowMultipleCanvasRenderers, SpineInspectorUtility.TempContent("Multiple CanvasRenderers"));

                        if (GUILayout.Button(new GUIContent("Trim Renderers", "Remove currently unused CanvasRenderer GameObjects. These will be regenerated whenever needed."),
                                             EditorStyles.miniButton, GUILayout.Width(100f)))
                        {
                            foreach (var skeletonGraphic in targets)
                            {
                                ((SkeletonGraphic)skeletonGraphic).TrimRenderers();
                            }
                        }
                        EditorGUILayout.EndHorizontal();

                        EditorGUILayout.PropertyField(updateWhenInvisible);

                        // warning box
                        if (isSeparationEnabledButNotMultipleRenderers)
                        {
                            using (new SpineInspectorUtility.BoxScope()) {
                                meshGeneratorSettings.isExpanded = true;
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("'Multiple Canvas Renderers' must be enabled\nwhen 'Enable Separation' is enabled.", Icons.warning), GUILayout.Height(42), GUILayout.Width(340));
                            }
                        }
                        else if (meshRendersIncorrectlyWithSingleRenderer)
                        {
                            using (new SpineInspectorUtility.BoxScope()) {
                                meshGeneratorSettings.isExpanded = true;
                                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("This mesh uses multiple atlas pages. You\n" +
                                                                                             "need to enable 'Multiple Canvas Renderers'\n" +
                                                                                             "for correct rendering. Consider packing\n" +
                                                                                             "attachments to a single atlas page if possible.", Icons.warning), GUILayout.Height(60), GUILayout.Width(340));
                            }
                        }
                    }

                    EditorGUILayout.Space();
                    SeparatorsField(separatorSlotNames, enableSeparatorSlots, updateSeparatorPartLocation);
                }
            }

            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(initialSkinName);
            {
                var rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
                EditorGUI.PrefixLabel(rect, SpineInspectorUtility.TempContent("Initial Flip"));
                rect.x    += EditorGUIUtility.labelWidth;
                rect.width = 30f;
                SpineInspectorUtility.ToggleLeft(rect, initialFlipX, SpineInspectorUtility.TempContent("X", tooltip: "initialFlipX"));
                rect.x += 35f;
                SpineInspectorUtility.ToggleLeft(rect, initialFlipY, SpineInspectorUtility.TempContent("Y", tooltip: "initialFlipY"));
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Animation", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(startingAnimation);
            EditorGUILayout.PropertyField(startingLoop);
            EditorGUILayout.PropertyField(timeScale);
            EditorGUILayout.PropertyField(unscaledTime, SpineInspectorUtility.TempContent(unscaledTime.displayName, tooltip: "If checked, this will use Time.unscaledDeltaTime to make this update independent of game Time.timeScale. Instance SkeletonGraphic.timeScale will still be applied."));
            EditorGUILayout.Space();
            EditorGUILayout.PropertyField(freeze);
            EditorGUILayout.Space();
            SkeletonRendererInspector.SkeletonRootMotionParameter(targets);
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("UI", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(raycastTarget);

            EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
            EditorGUILayout.PrefixLabel("Match RectTransform with Mesh");
            if (GUILayout.Button("Match", EditorStyles.miniButton, GUILayout.Width(65f)))
            {
                foreach (var skeletonGraphic in targets)
                {
                    MatchRectTransformWithBounds((SkeletonGraphic)skeletonGraphic);
                }
            }
            EditorGUILayout.EndHorizontal();

            if (TargetIsValid && !isInspectingPrefab)
            {
                EditorGUILayout.Space();
                if (SpineInspectorUtility.CenteredButton(new GUIContent("Add Skeleton Utility", Icons.skeletonUtility), 21, true, 200f))
                {
                    foreach (var t in targets)
                    {
                        var component = t as Component;
                        if (component.GetComponent <SkeletonUtility>() == null)
                        {
                            component.gameObject.AddComponent <SkeletonUtility>();
                        }
                    }
                }
            }

            wasChanged |= EditorGUI.EndChangeCheck();

            if (wasChanged)
            {
                serializedObject.ApplyModifiedProperties();
                slotsReapplyRequired = true;
            }

            if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint)
            {
                foreach (var target in targets)
                {
                    var skeletonGraphic = (SkeletonGraphic)target;
                    skeletonGraphic.ReapplySeparatorSlotNames();
                    skeletonGraphic.LateUpdate();
                    SceneView.RepaintAll();
                }
                slotsReapplyRequired = false;
            }
        }