LargeCenteredButton() 공개 정적인 메소드

public static LargeCenteredButton ( GUIContent content, bool sideSpace = true ) : bool
content UnityEngine.GUIContent
sideSpace bool
리턴 bool
예제 #1
0
        public override void OnInspectorGUI()
        {
            if (isPrefab)
            {
                GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
                return;
            }

            if (!skeletonRenderer.valid)
            {
                GUILayout.Label(new GUIContent("Spine Component invalid. Check Skeleton Data Asset.", Icons.warning));
                return;
            }

            skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField("Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);

            bool hasRootBone = skeletonUtility.boneRoot != null;

            using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
                if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
                {
                    SpawnHierarchyContextMenu();
                }
            }

            if (hasRootBone)
            {
                if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy")))
                {
                    Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
                    Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
                    skeletonUtility.boneRoot = null;
                }
            }
        }
 public void DrawSkeletonUtilityButton(bool multi)
 {
     if (multi)
     {
         // Support multi-edit SkeletonUtility button.
         //	EditorGUILayout.Space();
         //	bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30));
         //	foreach (var t in targets) {
         //		var component = t as Component;
         //		if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null)
         //			component.gameObject.AddComponent<SkeletonUtility>();
         //	}
     }
     else
     {
         EditorGUILayout.Space();
         var component = (Component)target;
         if (component.GetComponent <SkeletonUtility>() == null)
         {
             if (SpineInspectorUtility.LargeCenteredButton(SkeletonUtilityButtonContent))
             {
                 component.gameObject.AddComponent <SkeletonUtility>();
             }
         }
     }
 }
예제 #3
0
        public override void OnInspectorGUI()
        {
#if !NEW_PREFAB_SYSTEM
            if (isPrefab)
            {
                GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
                return;
            }
#endif

            serializedObject.Update();

            if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
                (skeletonGraphic != null && !skeletonGraphic.IsValid))
            {
                GUILayout.Label(new GUIContent("Spine Component invalid. Check Skeleton Data Asset.", Icons.warning));
                return;
            }

            EditorGUILayout.PropertyField(serializedObject.FindProperty("boneRoot"), SpineInspectorUtility.TempContent("Skeleton Root"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("flipBy180DegreeRotation"), SpineInspectorUtility.TempContent("Flip by Rotation", null,
                                                                                                                                      "If true, Skeleton.ScaleX and Skeleton.ScaleY are followed " +
                                                                                                                                      "by 180 degree rotation. If false, negative Transform scale is used. " +
                                                                                                                                      "Note that using negative scale is consistent with previous behaviour (hence the default), " +
                                                                                                                                      "however causes serious problems with rigidbodies and physics. Therefore, it is recommended to " +
                                                                                                                                      "enable this parameter where possible. When creating hinge chains for a chain of skeleton bones " +
                                                                                                                                      "via SkeletonUtilityBone, it is mandatory to have this parameter enabled."));

            bool hasRootBone = skeletonUtility.boneRoot != null;

            if (!hasRootBone)
            {
                EditorGUILayout.HelpBox("No hierarchy found. Use Spawn Hierarchy to generate GameObjects for bones.", MessageType.Info);
            }

            using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
                if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
                {
                    SpawnHierarchyContextMenu();
                }
            }

            if (hasRootBone)
            {
                if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy")))
                {
                    Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
                    Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
                    skeletonUtility.boneRoot = null;
                }
            }

            serializedObject.ApplyModifiedProperties();
        }
        public override void OnInspectorGUI()
        {
                        #if !NEW_PREFAB_SYSTEM
            if (isPrefab)
            {
                GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
                return;
            }
                        #endif

            if (!skeletonRenderer.valid)
            {
                GUILayout.Label(new GUIContent("Spine Component invalid. Check Skeleton Data Asset.", Icons.warning));
                return;
            }

            EditorGUILayout.PropertyField(serializedObject.FindProperty("boneRoot"), SpineInspectorUtility.TempContent("Skeleton Root"));

            bool hasRootBone = skeletonUtility.boneRoot != null;

            if (!hasRootBone)
            {
                EditorGUILayout.HelpBox("No hierarchy found. Use Spawn Hierarchy to generate GameObjects for bones.", MessageType.Info);
            }

            using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
                if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
                {
                    SpawnHierarchyContextMenu();
                }
            }

            if (hasRootBone)
            {
                if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy")))
                {
                    Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
                    Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
                    skeletonUtility.boneRoot = null;
                }
            }
        }
예제 #5
0
        void OnGUI()
        {
            so = so ?? new SerializedObject(this);

            EditorGUIUtility.wideMode = true;
            EditorGUILayout.LabelField("Spine Skeleton Prefab Baking", EditorStyles.boldLabel);

            const string BakingWarningMessage = "\nSkeleton baking is not the primary use case for Spine skeletons." +
                                                "\nUse baking if you have specialized uses, such as simplified skeletons with movement driven by physics." +

                                                "\n\nBaked Skeletons do not support the following:" +
                                                "\n\tDisabled rotation or scale inheritance" +
                                                "\n\tLocal Shear" +
                                                "\n\tAll Constraint types" +
                                                "\n\tWeighted mesh verts with more than 4 bound bones" +

                                                "\n\nBaked Animations do not support the following:" +
                                                "\n\tMesh Deform Keys" +
                                                "\n\tColor Keys" +
                                                "\n\tDraw Order Keys" +

                                                "\n\nAnimation Curves are sampled at 60fps and are not realtime." +
                                                "\nConstraint animations are also baked into animation curves." +
                                                "\nSee SkeletonBaker.cs comments for full details.\n";

            EditorGUILayout.HelpBox(BakingWarningMessage, MessageType.Info, true);

            EditorGUI.BeginChangeCheck();
            var skeletonDataAssetProperty = so.FindProperty("skeletonDataAsset");

            EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("SkeletonDataAsset", Icons.spine));
            if (EditorGUI.EndChangeCheck())
            {
                so.ApplyModifiedProperties();
                DataAssetChanged();
            }
            EditorGUILayout.Space();

            if (skeletonDataAsset == null)
            {
                return;
            }
            var skeletonData = skeletonDataAsset.GetSkeletonData(false);

            if (skeletonData == null)
            {
                return;
            }
            bool hasExtraSkins = skeletonData.Skins.Count > 1;

            using (new SpineInspectorUtility.BoxScope(false)) {
                EditorGUILayout.LabelField(skeletonDataAsset.name, EditorStyles.boldLabel);
                using (new SpineInspectorUtility.IndentScope()) {
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bones: " + skeletonData.Bones.Count, Icons.bone));
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Slots: " + skeletonData.Slots.Count, Icons.slotRoot));

                    if (hasExtraSkins)
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: " + skeletonData.Skins.Count, Icons.skinsRoot));
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Current skin attachments: " + (bakeSkin == null ? 0 : bakeSkin.Attachments.Count), Icons.skinPlaceholder));
                    }
                    else if (skeletonData.Skins.Count == 1)
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Skins: 1 (only default Skin)", Icons.skinsRoot));
                    }

                    int totalAttachments = 0;
                    foreach (var s in skeletonData.Skins)
                    {
                        totalAttachments += s.Attachments.Count;
                    }
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Total Attachments: " + totalAttachments, Icons.genericAttachment));
                }
            }
            using (new SpineInspectorUtility.BoxScope(false)) {
                EditorGUILayout.LabelField("Animations", EditorStyles.boldLabel);
                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Animations: " + skeletonData.Animations.Count, Icons.animation));

                using (new SpineInspectorUtility.IndentScope()) {
                    bakeAnimations = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake Animations", Icons.animationRoot), bakeAnimations);
                    using (new EditorGUI.DisabledScope(!bakeAnimations)) {
                        using (new SpineInspectorUtility.IndentScope()) {
                            bakeIK           = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake IK", Icons.constraintIK), bakeIK);
                            bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup(SpineInspectorUtility.TempContent("Event Options", Icons.userEvent), bakeEventOptions);
                        }
                    }
                }
            }
            EditorGUILayout.Space();

            if (!string.IsNullOrEmpty(skinToBake) && UnityEngine.Event.current.type == EventType.Repaint)
            {
                bakeSkin = skeletonData.FindSkin(skinToBake) ?? skeletonData.DefaultSkin;
            }

            var prefabIcon = EditorGUIUtility.FindTexture("PrefabModel Icon");

            if (hasExtraSkins)
            {
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(so.FindProperty("skinToBake"));
                if (EditorGUI.EndChangeCheck())
                {
                    so.ApplyModifiedProperties();
                    Repaint();
                }

                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake Skeleton with Skin ({0})", (bakeSkin == null ? "default" : bakeSkin.Name)), prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList <Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
                }

                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
            else
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Bake Skeleton", prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList <Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
        }
        public override void OnInspectorGUI()
        {
            bool requireRepaint = false;

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

            if (isPrefab)
            {
                GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
                return;
            }

            if (!skeletonRenderer.valid)
            {
                GUILayout.Label(new GUIContent("Spine Component invalid. Check Skeleton Data Asset.", Icons.warning));
                return;
            }

            skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField("Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);

            using (new EditorGUI.DisabledGroupScope(skeletonUtility.boneRoot != null)) {
                if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
                {
                    SpawnHierarchyContextMenu();
                }
            }

            using (new SpineInspectorUtility.BoxScope()) {
                debugSkeleton = EditorGUILayout.Foldout(debugSkeleton, "Debug Skeleton");

                if (debugSkeleton)
                {
                    EditorGUI.BeginChangeCheck();
                    skeleton.FlipX  = EditorGUILayout.ToggleLeft("skeleton.FlipX", skeleton.FlipX);
                    skeleton.FlipY  = EditorGUILayout.ToggleLeft("skeleton.FlipY", skeleton.FlipY);
                    requireRepaint |= EditorGUI.EndChangeCheck();

//					foreach (var t in skeleton.IkConstraints)
//						EditorGUILayout.LabelField(t.Data.Name + " " + t.Mix + " " + t.Target.Data.Name);

                    showSlots.target = EditorGUILayout.Foldout(showSlots.target, SlotsRootLabel);
                    if (showSlots.faded > 0)
                    {
                        using (new EditorGUILayout.FadeGroupScope(showSlots.faded)) {
                            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(new GUIContent(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       = (attachment is MeshAttachment) ? Icons.mesh : Icons.image;
                                    bool isAttached = (attachment == slot.Attachment);
                                    bool swap       = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment);
                                    if (isAttached != swap)
                                    {
                                        slot.Attachment = isAttached ? null : attachment;
                                        requireRepaint  = true;
                                    }
                                    GUI.contentColor = Color.white;
                                }
                            }
                        }
                    }
                }

                if (showSlots.isAnimating)
                {
                    Repaint();
                }
            }

            if (requireRepaint)
            {
                skeletonRenderer.LateUpdate();
                SceneView.RepaintAll();
            }
        }
예제 #7
0
        override public void OnInspectorGUI()
        {
            serializedObject.Update();
            atlasAsset = atlasAsset ?? (AtlasAsset)target;
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(atlasFile);
            EditorGUILayout.PropertyField(materials, true);
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
                atlasAsset.Clear();
                atlasAsset.GetAtlas();
            }


            if (materials.arraySize == 0)
            {
                EditorGUILayout.LabelField(new GUIContent("Error:  Missing materials", SpineEditorUtilities.Icons.warning));
                return;
            }

            for (int i = 0; i < materials.arraySize; i++)
            {
                SerializedProperty prop = materials.GetArrayElementAtIndex(i);
                Material           mat  = (Material)prop.objectReferenceValue;
                if (mat == null)
                {
                    EditorGUILayout.LabelField(new GUIContent("Error:  Materials cannot be null", SpineEditorUtilities.Icons.warning));
                    return;
                }
            }

            EditorGUILayout.Space();
            if (atlasFile.objectReferenceValue != null)
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel))
                {
                    var atlas = atlasAsset.GetAtlas();
                    foreach (var m in atlasAsset.materials)
                    {
                        UpdateSpriteSlices(m.mainTexture, atlas);
                    }
                }
            }

                        #if REGION_BAKING_MESH
            if (atlasFile.objectReferenceValue != null)
            {
                Atlas              atlas   = asset.GetAtlas();
                FieldInfo          field   = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
                List <AtlasRegion> regions = (List <AtlasRegion>)field.GetValue(atlas);
                EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
                EditorGUI.indentLevel++;
                AtlasPage lastPage = null;
                for (int i = 0; i < regions.Count; i++)
                {
                    if (lastPage != regions[i].page)
                    {
                        if (lastPage != null)
                        {
                            EditorGUILayout.Separator();
                            EditorGUILayout.Separator();
                        }
                        lastPage = regions[i].page;
                        Material mat = ((Material)lastPage.rendererObject);
                        if (mat != null)
                        {
                            GUILayout.BeginHorizontal();
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
                                EditorGUI.EndDisabledGroup();
                            }
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
                        }
                    }
                    GUILayout.BeginHorizontal();
                    {
                        //EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
                        bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft("    " + regions[i].name, baked[i]);
                        if (baked[i])
                        {
                            EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
                        }
                        if (result && !baked[i])
                        {
                            //bake
                            baked[i]        = true;
                            bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
                            EditorGUIUtility.PingObject(bakedObjects[i]);
                        }
                        else if (!result && baked[i])
                        {
                            //unbake
                            bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
                            switch (unbakeResult)
                            {
                            case true:
                                //delete
                                string atlasAssetPath    = AssetDatabase.GetAssetPath(atlasAsset);
                                string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
                                string bakedDirPath      = Path.Combine(atlasAssetDirPath, atlasAsset.name);
                                string bakedPrefabPath   = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
                                AssetDatabase.DeleteAsset(bakedPrefabPath);
                                baked[i] = false;
                                break;

                            case false:
                                //do nothing
                                break;
                            }
                        }
                    }
                    GUILayout.EndHorizontal();
                }
                EditorGUI.indentLevel--;

                                #if BAKE_ALL_BUTTON
                // Check state
                bool allBaked   = true;
                bool allUnbaked = true;
                for (int i = 0; i < regions.Count; i++)
                {
                    allBaked   &= baked[i];
                    allUnbaked &= !baked[i];
                }

                if (!allBaked && GUILayout.Button("Bake All"))
                {
                    for (int i = 0; i < regions.Count; i++)
                    {
                        if (!baked[i])
                        {
                            baked[i]        = true;
                            bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
                        }
                    }
                }
                else if (!allUnbaked && GUILayout.Button("Unbake All"))
                {
                    bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
                    switch (unbakeResult)
                    {
                    case true:
                        //delete
                        for (int i = 0; i < regions.Count; i++)
                        {
                            if (baked[i])
                            {
                                string atlasAssetPath    = AssetDatabase.GetAssetPath(atlasAsset);
                                string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
                                string bakedDirPath      = Path.Combine(atlasAssetDirPath, atlasAsset.name);
                                string bakedPrefabPath   = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
                                AssetDatabase.DeleteAsset(bakedPrefabPath);
                                baked[i] = false;
                            }
                        }
                        break;

                    case false:
                        //do nothing
                        break;
                    }
                }
                                #endif
            }
                        #else
            if (atlasFile.objectReferenceValue != null)
            {
                EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
                int baseIndent = EditorGUI.indentLevel;

                var       regions  = AtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
                AtlasPage lastPage = null;
                for (int i = 0; i < regions.Count; i++)
                {
                    if (lastPage != regions[i].page)
                    {
                        if (lastPage != null)
                        {
                            EditorGUILayout.Separator();
                            EditorGUILayout.Separator();
                        }
                        lastPage = regions[i].page;
                        Material mat = ((Material)lastPage.rendererObject);
                        if (mat != null)
                        {
                            EditorGUI.indentLevel = baseIndent;
                            using (new GUILayout.HorizontalScope())
                                using (new EditorGUI.DisabledGroupScope(true))
                                    EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
                            EditorGUI.indentLevel = baseIndent + 1;
                        }
                        else
                        {
                            EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
                        }
                    }

                    EditorGUILayout.LabelField(new GUIContent(regions[i].name, SpineEditorUtilities.Icons.image));
                }
                EditorGUI.indentLevel = baseIndent;
            }
                        #endif

            if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
            {
                atlasAsset.Clear();
            }
        }
        public override void OnInspectorGUI()
        {
                        #if !NEW_PREFAB_SYSTEM
            bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
                        #else
            bool isInspectingPrefab = false;
                        #endif

            // Try to auto-assign SkeletonRenderer field.
            if (skeletonRenderer.objectReferenceValue == null)
            {
                var foundSkeletonRenderer = follower.GetComponentInParent <SkeletonRenderer>();
                if (foundSkeletonRenderer != null)
                {
                    Debug.Log("BoundingBoxFollower automatically assigned: " + foundSkeletonRenderer.gameObject.name);
                }
                else if (Event.current.type == EventType.Repaint)
                {
                    Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollower's 'Skeleton Renderer' field in the inspector.");
                }

                skeletonRenderer.objectReferenceValue = foundSkeletonRenderer;
                serializedObject.ApplyModifiedProperties();
            }

            var skeletonRendererValue = skeletonRenderer.objectReferenceValue as SkeletonRenderer;
            if (skeletonRendererValue != null && skeletonRendererValue.gameObject == follower.gameObject)
            {
                using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
                    EditorGUILayout.HelpBox("It's ideal to add BoundingBoxFollower to a separate child GameObject of the Spine GameObject.", MessageType.Warning);

                    if (GUILayout.Button(new GUIContent("Move BoundingBoxFollower to new GameObject", Icons.boundingBox), GUILayout.Height(50f)))
                    {
                        AddBoundingBoxFollowerChild(skeletonRendererValue, follower);
                        DestroyImmediate(follower);
                        return;
                    }
                }
                EditorGUILayout.Space();
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(skeletonRenderer);
            EditorGUILayout.PropertyField(slotName, new GUIContent("Slot"));
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
                                #if !NEW_PREFAB_SYSTEM
                if (!isInspectingPrefab)
                {
                    rebuildRequired = true;
                }
                                #endif
            }

            using (new SpineInspectorUtility.LabelWidthScope(150f)) {
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(isTrigger);
                bool triggerChanged = EditorGUI.EndChangeCheck();

                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(clearStateOnDisable, new GUIContent(clearStateOnDisable.displayName, "Enable this if you are pooling your Spine GameObject"));
                bool clearStateChanged = EditorGUI.EndChangeCheck();

                if (clearStateChanged || triggerChanged)
                {
                    serializedObject.ApplyModifiedProperties();
                    if (triggerChanged)
                    {
                        foreach (var col in follower.colliderTable.Values)
                        {
                            col.isTrigger = isTrigger.boolValue;
                        }
                    }
                }
            }

            if (isInspectingPrefab)
            {
                follower.colliderTable.Clear();
                follower.nameTable.Clear();
                EditorGUILayout.HelpBox("BoundingBoxAttachments cannot be previewed in prefabs.", MessageType.Info);

                // How do you prevent components from being saved into the prefab? No such HideFlag. DontSaveInEditor | DontSaveInBuild does not work. DestroyImmediate does not work.
                var collider = follower.GetComponent <PolygonCollider2D>();
                if (collider != null)
                {
                    Debug.LogWarning("Found BoundingBoxFollower collider components in prefab. These are disposed and regenerated at runtime.");
                }
            }
            else
            {
                using (new SpineInspectorUtility.BoxScope()) {
                    if (debugIsExpanded = EditorGUILayout.Foldout(debugIsExpanded, "Debug Colliders"))
                    {
                        EditorGUI.indentLevel++;
                        EditorGUILayout.LabelField(string.Format("Attachment Names ({0} PolygonCollider2D)", follower.colliderTable.Count));
                        EditorGUI.BeginChangeCheck();
                        foreach (var kp in follower.nameTable)
                        {
                            string attachmentName = kp.Value;
                            var    collider       = follower.colliderTable[kp.Key];
                            bool   isPlaceholder  = attachmentName != kp.Key.Name;
                            collider.enabled = EditorGUILayout.ToggleLeft(new GUIContent(!isPlaceholder ? attachmentName : string.Format("{0} [{1}]", attachmentName, kp.Key.Name), isPlaceholder ? Icons.skinPlaceholder : Icons.boundingBox), collider.enabled);
                        }
                        sceneRepaintRequired |= EditorGUI.EndChangeCheck();
                        EditorGUI.indentLevel--;
                    }
                }
            }

            bool hasBoneFollower = follower.GetComponent <BoneFollower>() != null;
            if (!hasBoneFollower)
            {
                bool buttonDisabled = follower.Slot == null;
                using (new EditorGUI.DisabledGroupScope(buttonDisabled)) {
                    addBoneFollower |= SpineInspectorUtility.LargeCenteredButton(AddBoneFollowerLabel, true);
                    EditorGUILayout.Space();
                }
            }


            if (Event.current.type == EventType.Repaint)
            {
                if (addBoneFollower)
                {
                    var boneFollower = follower.gameObject.AddComponent <BoneFollower>();
                    boneFollower.skeletonRenderer = skeletonRendererValue;
                    boneFollower.SetBone(follower.Slot.Data.BoneData.Name);
                    addBoneFollower = false;
                }

                if (sceneRepaintRequired)
                {
                    SceneView.RepaintAll();
                    sceneRepaintRequired = false;
                }

                if (rebuildRequired)
                {
                    follower.Initialize();
                    rebuildRequired = false;
                }
            }
        }
        override public void OnInspectorGUI()
        {
            if (serializedObject.isEditingMultipleObjects)
            {
                DrawDefaultInspector();
                return;
            }

            serializedObject.Update();
            atlasAsset = (atlasAsset == null) ? (SpineAtlasAsset)target : atlasAsset;
            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(atlasFile);
            EditorGUILayout.PropertyField(materials, true);
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
                atlasAsset.Clear();
                atlasAsset.GetAtlas();
            }

            if (materials.arraySize == 0)
            {
                EditorGUILayout.HelpBox("No materials", MessageType.Error);
                return;
            }

            for (int i = 0; i < materials.arraySize; i++)
            {
                SerializedProperty prop = materials.GetArrayElementAtIndex(i);
                var material            = (Material)prop.objectReferenceValue;
                if (material == null)
                {
                    EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error);
                    return;
                }
            }

            EditorGUILayout.Space();
            if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Set Mipmap Bias to " + SpinePreferences.DEFAULT_MIPMAPBIAS, tooltip: "This may help textures with mipmaps be less blurry when used for 2D sprites.")))
            {
                foreach (var m in atlasAsset.materials)
                {
                    var    texture     = m.mainTexture;
                    string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID());
                    var    importer    = (TextureImporter)TextureImporter.GetAtPath(texturePath);
                    importer.mipMapBias = SpinePreferences.DEFAULT_MIPMAPBIAS;
                    EditorUtility.SetDirty(texture);
                }
                Debug.Log("Texture mipmap bias set to " + SpinePreferences.DEFAULT_MIPMAPBIAS);
            }

            EditorGUILayout.Space();
            if (atlasFile.objectReferenceValue != null)
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpriteSlicesLabel))
                {
                    var atlas = atlasAsset.GetAtlas();
                    foreach (var m in atlasAsset.materials)
                    {
                        UpdateSpriteSlices(m.mainTexture, atlas);
                    }
                }
            }

            EditorGUILayout.Space();

                        #if REGION_BAKING_MESH
            if (atlasFile.objectReferenceValue != null)
            {
                Atlas              atlas   = asset.GetAtlas();
                FieldInfo          field   = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
                List <AtlasRegion> regions = (List <AtlasRegion>)field.GetValue(atlas);
                EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
                EditorGUI.indentLevel++;
                AtlasPage lastPage = null;
                for (int i = 0; i < regions.Count; i++)
                {
                    if (lastPage != regions[i].page)
                    {
                        if (lastPage != null)
                        {
                            EditorGUILayout.Separator();
                            EditorGUILayout.Separator();
                        }
                        lastPage = regions[i].page;
                        Material mat = ((Material)lastPage.rendererObject);
                        if (mat != null)
                        {
                            GUILayout.BeginHorizontal();
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
                                EditorGUI.EndDisabledGroup();
                            }
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
                        }
                    }
                    GUILayout.BeginHorizontal();
                    {
                        //EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
                        bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft("    " + regions[i].name, baked[i]);
                        if (baked[i])
                        {
                            EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
                        }
                        if (result && !baked[i])
                        {
                            //bake
                            baked[i]        = true;
                            bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
                            EditorGUIUtility.PingObject(bakedObjects[i]);
                        }
                        else if (!result && baked[i])
                        {
                            //unbake
                            bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
                            switch (unbakeResult)
                            {
                            case true:
                                //delete
                                string atlasAssetPath    = AssetDatabase.GetAssetPath(atlasAsset);
                                string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
                                string bakedDirPath      = Path.Combine(atlasAssetDirPath, atlasAsset.name);
                                string bakedPrefabPath   = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
                                AssetDatabase.DeleteAsset(bakedPrefabPath);
                                baked[i] = false;
                                break;

                            case false:
                                //do nothing
                                break;
                            }
                        }
                    }
                    GUILayout.EndHorizontal();
                }
                EditorGUI.indentLevel--;

                                #if BAKE_ALL_BUTTON
                // Check state
                bool allBaked   = true;
                bool allUnbaked = true;
                for (int i = 0; i < regions.Count; i++)
                {
                    allBaked   &= baked[i];
                    allUnbaked &= !baked[i];
                }

                if (!allBaked && GUILayout.Button("Bake All"))
                {
                    for (int i = 0; i < regions.Count; i++)
                    {
                        if (!baked[i])
                        {
                            baked[i]        = true;
                            bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
                        }
                    }
                }
                else if (!allUnbaked && GUILayout.Button("Unbake All"))
                {
                    bool unbakeResult = EditorUtility.DisplayDialog("Delete All Baked Regions", "Are you sure you want to unbake all region prefabs? This cannot be undone.", "Yes", "Cancel");
                    switch (unbakeResult)
                    {
                    case true:
                        //delete
                        for (int i = 0; i < regions.Count; i++)
                        {
                            if (baked[i])
                            {
                                string atlasAssetPath    = AssetDatabase.GetAssetPath(atlasAsset);
                                string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
                                string bakedDirPath      = Path.Combine(atlasAssetDirPath, atlasAsset.name);
                                string bakedPrefabPath   = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
                                AssetDatabase.DeleteAsset(bakedPrefabPath);
                                baked[i] = false;
                            }
                        }
                        break;

                    case false:
                        //do nothing
                        break;
                    }
                }
                                #endif
            }
                        #else
            if (atlasFile.objectReferenceValue != null)
            {
                int baseIndent = EditorGUI.indentLevel;

                var regions      = SpineAtlasAssetInspector.GetRegions(atlasAsset.GetAtlas());
                int regionsCount = regions.Count;
                using (new EditorGUILayout.HorizontalScope()) {
                    EditorGUILayout.LabelField("Atlas Regions", EditorStyles.boldLabel);
                    EditorGUILayout.LabelField(string.Format("{0} regions total", regionsCount));
                }
                AtlasPage lastPage = null;
                for (int i = 0; i < regionsCount; i++)
                {
                    if (lastPage != regions[i].page)
                    {
                        if (lastPage != null)
                        {
                            EditorGUILayout.Separator();
                            EditorGUILayout.Separator();
                        }
                        lastPage = regions[i].page;
                        Material mat = ((Material)lastPage.rendererObject);
                        if (mat != null)
                        {
                            EditorGUI.indentLevel = baseIndent;
                            using (new GUILayout.HorizontalScope())
                                using (new EditorGUI.DisabledGroupScope(true))
                                    EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
                            EditorGUI.indentLevel = baseIndent + 1;
                        }
                        else
                        {
                            EditorGUILayout.HelpBox("Page missing material!", MessageType.Warning);
                        }
                    }

                    string    regionName = regions[i].name;
                    Texture2D icon       = SpineEditorUtilities.Icons.image;
                    if (regionName.EndsWith(" "))
                    {
                        regionName = string.Format("'{0}'", regions[i].name);
                        icon       = SpineEditorUtilities.Icons.warning;
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon, "Region name ends with whitespace. This may cause errors. Please check your source image filenames."));
                    }
                    else
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(regionName, icon));
                    }
                }
                EditorGUI.indentLevel = baseIndent;
            }
                        #endif

            if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
            {
                atlasAsset.Clear();
            }
        }
        public override void OnInspectorGUI()
        {
            component = (SkeletonRendererCustomMaterials)target;
            var skeletonRenderer = component.skeletonRenderer;

            // Draw the default inspector
            DrawDefaultInspector();

            if (serializedObject.isEditingMultipleObjects)
            {
                return;
            }

            if (componentCustomMaterialOverrides == null)
            {
                Type cm = typeof(SkeletonRendererCustomMaterials);
                componentCustomMaterialOverrides = cm.GetField("customMaterialOverrides", PrivateInstance).GetValue(component) as List <SkeletonRendererCustomMaterials.AtlasMaterialOverride>;
                componentCustomSlotMaterials     = cm.GetField("customSlotMaterials", PrivateInstance).GetValue(component) as List <SkeletonRendererCustomMaterials.SlotMaterialOverride>;
                if (componentCustomMaterialOverrides == null)
                {
                    Debug.Log("Reflection failed.");
                    return;
                }
            }

            // Fill with current values at start
            if (_customMaterialOverridesPrev == null || _customSlotMaterialsPrev == null)
            {
                _customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
                _customSlotMaterialsPrev     = CopyList(componentCustomSlotMaterials);
            }

            // Compare new values with saved. If change is detected:
            // store new values, restore old values, remove overrides, restore new values, restore overrides.

            // 1. Store new values
            var customMaterialOverridesNew = CopyList(componentCustomMaterialOverrides);
            var customSlotMaterialsNew     = CopyList(componentCustomSlotMaterials);

            // Detect changes
            if (!_customMaterialOverridesPrev.SequenceEqual(customMaterialOverridesNew) ||
                !_customSlotMaterialsPrev.SequenceEqual(customSlotMaterialsNew))
            {
                // 2. Restore old values
                componentCustomMaterialOverrides.Clear();
                componentCustomSlotMaterials.Clear();
                componentCustomMaterialOverrides.AddRange(_customMaterialOverridesPrev);
                componentCustomSlotMaterials.AddRange(_customSlotMaterialsPrev);

                // 3. Remove overrides
                RemoveCustomMaterials();

                // 4. Restore new values
                componentCustomMaterialOverrides.Clear();
                componentCustomSlotMaterials.Clear();
                componentCustomMaterialOverrides.AddRange(customMaterialOverridesNew);
                componentCustomSlotMaterials.AddRange(customSlotMaterialsNew);

                // 5. Restore overrides
                SetCustomMaterials();

                if (skeletonRenderer != null)
                {
                    skeletonRenderer.LateUpdate();
                }
            }

            _customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides);
            _customSlotMaterialsPrev     = CopyList(componentCustomSlotMaterials);

            if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Clear and Reapply Changes", "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component.")))
            {
                if (skeletonRenderer != null)
                {
                                        #if SPINE_OPTIONAL_MATERIALOVERRIDE
                    skeletonRenderer.CustomMaterialOverride.Clear();
                                        #endif
                    skeletonRenderer.CustomSlotMaterials.Clear();
                    RemoveCustomMaterials();
                    SetCustomMaterials();
                    skeletonRenderer.LateUpdate();
                }
            }
        }
        void OnGUI()
        {
            so = so ?? new SerializedObject(this);

            EditorGUIUtility.wideMode = true;
            EditorGUILayout.LabelField("Spine SpriteAtlas Import", EditorStyles.boldLabel);

            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUI.BeginChangeCheck();
                var spriteAtlasAssetProperty = so.FindProperty("spriteAtlasAsset");
                EditorGUILayout.PropertyField(spriteAtlasAssetProperty, new GUIContent("SpriteAtlas", EditorGUIUtility.IconContent("SpriteAtlas Icon").image));
                if (EditorGUI.EndChangeCheck())
                {
                    so.ApplyModifiedProperties();
                    if (spriteAtlasAsset != null)
                    {
                        if (AssetUtility.SpriteAtlasSettingsNeedAdjustment(spriteAtlasAsset))
                        {
                            AssetUtility.AdjustSpriteAtlasSettings(spriteAtlasAsset);
                        }
                        GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
                    }
                }

                var spineSpriteAtlasAssetProperty = so.FindProperty("spineSpriteAtlasAsset");
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(spineSpriteAtlasAssetProperty, new GUIContent("SpineSpriteAtlasAsset", EditorGUIUtility.IconContent("ScriptableObject Icon").image));
                if (spineSpriteAtlasAssetProperty.objectReferenceValue == null)
                {
                    spineSpriteAtlasAssetProperty.objectReferenceValue = spineSpriteAtlasAsset = FindSpineSpriteAtlasAsset(spriteAtlasAsset);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    so.ApplyModifiedProperties();
                }
                EditorGUILayout.Space();

                using (new EditorGUI.DisabledScope(spineSpriteAtlasAsset == null)) {
                    if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Load regions by entering Play mode")))
                    {
                        GenerateAssetsFromSpriteAtlas(spriteAtlasAsset);
                        SpineSpriteAtlasAsset.UpdateByStartingEditorPlayMode();
                    }
                }

                using (new SpineInspectorUtility.BoxScope()) {
                    if (spriteAtlasAsset == null)
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please assign SpriteAtlas file.", Icons.warning), GUILayout.Height(46));
                    }
                    else if (spineSpriteAtlasAsset == null || spineSpriteAtlasAsset.RegionsNeedLoading)
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Please hit 'Load regions ..' to load\nregion info. Play mode is started\nand stopped automatically.", Icons.warning), GUILayout.Height(54));
                    }
                    else
                    {
                        EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("SpriteAtlas imported\nsuccessfully.", Icons.spine), GUILayout.Height(46));
                    }
                }
            }

            bool isAtlasComplete   = (spineSpriteAtlasAsset != null && !spineSpriteAtlasAsset.RegionsNeedLoading);
            bool canImportSkeleton = (spriteAtlasAsset != null && skeletonDataFile != null);

            using (new SpineInspectorUtility.BoxScope()) {
                using (new EditorGUI.DisabledScope(!isAtlasComplete)) {
                    var skeletonDataAssetProperty = so.FindProperty("skeletonDataFile");
                    EditorGUI.BeginChangeCheck();
                    EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("Skeleton json/skel file", Icons.spine));
                    if (EditorGUI.EndChangeCheck())
                    {
                        so.ApplyModifiedProperties();
                    }
                    EditorGUILayout.Space();
                }
                using (new EditorGUI.DisabledScope(!canImportSkeleton)) {
                    if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Import Skeleton")))
                    {
                        //AssetUtility.IngestSpriteAtlas(spriteAtlasAsset, null);
                        string   skeletonPath = AssetDatabase.GetAssetPath(skeletonDataFile);
                        string[] skeletons    = new string[] { skeletonPath };
                        AssetUtility.ImportSpineContent(skeletons, null);
                    }
                }
            }
        }
        void OnGUI()
        {
            so = so ?? new SerializedObject(this);

            EditorGUIUtility.wideMode = true;
            EditorGUILayout.LabelField("Spine Skeleton Prefab Baking", EditorStyles.boldLabel);

            const string BakingWarningMessage = "\nThe main use of Baking is to export Spine projects to be used without the Spine Runtime (ie: for sale on the Asset Store, or background objects that are animated only with a wind noise generator)" +

                                                "\n\nBaking does not support the following:" +
                                                "\n\tDisabled transform inheritance" +
                                                "\n\tShear" +
                                                "\n\tColor Keys" +
                                                "\n\tDraw Order Keys" +
                                                "\n\tAll Constraint types" +

                                                "\n\nCurves are sampled at 60fps and are not realtime." +
                                                "\nPlease read SkeletonBaker.cs comments for full details.\n";

            EditorGUILayout.HelpBox(BakingWarningMessage, MessageType.Info, true);

            EditorGUI.BeginChangeCheck();
            var skeletonDataAssetProperty = so.FindProperty("skeletonDataAsset");

            EditorGUILayout.PropertyField(skeletonDataAssetProperty, SpineInspectorUtility.TempContent("SkeletonDataAsset", Icons.spine));
            if (EditorGUI.EndChangeCheck())
            {
                so.ApplyModifiedProperties();
                DataAssetChanged();
            }
            EditorGUILayout.Space();

            if (skeletonDataAsset == null)
            {
                return;
            }
            var skeletonData = skeletonDataAsset.GetSkeletonData(false);

            if (skeletonData == null)
            {
                return;
            }

            using (new SpineInspectorUtility.BoxScope(false)) {
                EditorGUILayout.LabelField(skeletonDataAsset.name, EditorStyles.boldLabel);
                using (new SpineInspectorUtility.IndentScope()) {
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bones: " + skeletonData.Bones.Count, Icons.bone));

                    int totalAttachments = 0;
                    foreach (var s in skeletonData.Skins)
                    {
                        totalAttachments += s.Attachments.Count;
                    }

                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Total Attachments: " + totalAttachments, Icons.genericAttachment));
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Current skin attachments: " + (bakeSkin == null ? 0 : bakeSkin.Attachments.Count), Icons.skinPlaceholder));
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Animations: " + skeletonData.Animations.Count, Icons.animation));
                }
            }
            using (new SpineInspectorUtility.BoxScope(false)) {
                EditorGUILayout.LabelField("Settings", EditorStyles.boldLabel);
                using (new SpineInspectorUtility.IndentScope()) {
                    bakeAnimations   = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake Animations", Icons.animationRoot), bakeAnimations);
                    bakeIK           = EditorGUILayout.Toggle(SpineInspectorUtility.TempContent("Bake IK", Icons.constraintIK), bakeIK);
                    bakeEventOptions = (SendMessageOptions)EditorGUILayout.EnumPopup(SpineInspectorUtility.TempContent("Event Options", Icons.userEvent), bakeEventOptions);
                }
            }
            EditorGUILayout.Space();

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(so.FindProperty("skinToBake"));
            if (EditorGUI.EndChangeCheck())
            {
                so.ApplyModifiedProperties();
                Repaint();
            }

            if (!string.IsNullOrEmpty(skinToBake) && UnityEngine.Event.current.type == EventType.Repaint)
            {
                bakeSkin = skeletonData.FindSkin(skinToBake) ?? skeletonData.DefaultSkin;
            }

            var prefabIcon = EditorGUIUtility.FindTexture("PrefabModel Icon");

            if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake Skin ({0})", (bakeSkin == null ? "default" : bakeSkin.Name)), prefabIcon)))
            {
                SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList <Skin>(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
            }


            if (skeletonData.Skins.Count > 1)
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
        }