CenteredButton() 공개 정적인 메소드

public static CenteredButton ( GUIContent content, float height = 20f, bool sideSpace = true ) : bool
content UnityEngine.GUIContent
height float
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;
                }
            }
        }
예제 #2
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();
        }
		internal static void RecommendRigidbodyButton (Component component) {
			bool hasCollider2D = component.GetComponent<Collider2D>() != null || component.GetComponent<BoundingBoxFollower>() != null;
			bool hasCollider3D = !hasCollider2D && component.GetComponent<Collider>();
			bool missingRigidBody = (hasCollider2D && component.GetComponent<Rigidbody2D>() == null) || (hasCollider3D && component.GetComponent<Rigidbody>() == null);
			if (missingRigidBody) {
				using (new SpineInspectorUtility.BoxScope()) {
					EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning);
					var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody);
					string rbLabel = string.Format("Add {0}", rbType.Name);
					var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Physics body parent of the attached collider.");
					if (SpineInspectorUtility.CenteredButton(rbContent)) component.gameObject.AddComponent(rbType);
				}
			}
		}
        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;
                }
            }
        }
        void HandleAtlasAssetsNulls()
        {
            bool hasNulls = false;

            foreach (var a in targetSkeletonDataAsset.atlasAssets)
            {
                if (a == null)
                {
                    hasNulls = true;
                    break;
                }
            }
            if (hasNulls)
            {
                if (targetSkeletonDataAsset.atlasAssets.Length == 1)
                {
                    EditorGUILayout.HelpBox("Atlas array cannot have null entries!", MessageType.None);
                }
                else
                {
                    EditorGUILayout.HelpBox("Atlas array should not have null entries!", MessageType.Error);
                    if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Remove null entries")))
                    {
                        var trimmedAtlasAssets = new List <AtlasAsset>();
                        foreach (var a in targetSkeletonDataAsset.atlasAssets)
                        {
                            if (a != null)
                            {
                                trimmedAtlasAssets.Add(a);
                            }
                        }
                        targetSkeletonDataAsset.atlasAssets = trimmedAtlasAssets.ToArray();
                        serializedObject.Update();
                    }
                }
            }
        }
        override public void OnInspectorGUI()
        {
            if (serializedObject.isEditingMultipleObjects)
            {
                using (new SpineInspectorUtility.BoxScope()) {
                    EditorGUILayout.LabelField("SkeletonData", EditorStyles.boldLabel);
                    EditorGUILayout.PropertyField(skeletonJSON, SpineInspectorUtility.TempContent(skeletonJSON.displayName, Icons.spine));
                    EditorGUILayout.PropertyField(scale);
                }

                using (new SpineInspectorUtility.BoxScope()) {
                    EditorGUILayout.LabelField("Atlas", EditorStyles.boldLabel);
                                        #if !SPINE_TK2D
                    EditorGUILayout.PropertyField(atlasAssets, true);
                                        #else
                    using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
                        EditorGUILayout.PropertyField(atlasAssets, true);
                    }
                    EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
                    EditorGUILayout.PropertyField(spriteCollection, true);
                                        #endif
                }

                using (new SpineInspectorUtility.BoxScope()) {
                    EditorGUILayout.LabelField("Mix Settings", EditorStyles.boldLabel);
                    SpineInspectorUtility.PropertyFieldWideLabel(defaultMix, DefaultMixLabel, 160);
                    EditorGUILayout.Space();
                }
                return;
            }

            {
                // Lazy initialization because accessing EditorStyles values in OnEnable during a recompile causes UnityEditor to throw null exceptions. (Unity 5.3.5)
                idlePlayButtonStyle = idlePlayButtonStyle ?? new GUIStyle(EditorStyles.miniButton);
                if (activePlayButtonStyle == null)
                {
                    activePlayButtonStyle = new GUIStyle(idlePlayButtonStyle);
                    activePlayButtonStyle.normal.textColor = Color.red;
                }
            }

            serializedObject.Update();

            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(target.name + " (SkeletonDataAsset)", Icons.spine), EditorStyles.whiteLargeLabel);
            if (m_skeletonData != null)
            {
                EditorGUILayout.LabelField("(Drag and Drop to instantiate.)", EditorStyles.miniLabel);
            }

            EditorGUI.BeginChangeCheck();

            // SkeletonData
            using (new SpineInspectorUtility.BoxScope()) {
                using (new EditorGUILayout.HorizontalScope()) {
                    EditorGUILayout.LabelField("SkeletonData", EditorStyles.boldLabel);
                    if (m_skeletonData != null)
                    {
                        var    sd = m_skeletonData;
                        string m  = string.Format("{8} - {0} {1}\nBones: {2}\nConstraints: \n {5} IK \n {6} Path \n {7} Transform\n\nSlots: {3}\nSkins: {4}\n\nAnimations: {9}",
                                                  sd.Version, string.IsNullOrEmpty(sd.Version) ? "" : "export          ", sd.Bones.Count, sd.Slots.Count, sd.Skins.Count, sd.IkConstraints.Count, sd.PathConstraints.Count, sd.TransformConstraints.Count, skeletonJSON.objectReferenceValue.name, sd.Animations.Count);
                        EditorGUILayout.LabelField(GUIContent.none, new GUIContent(Icons.info, m), GUILayout.Width(30f));
                    }
                }

                EditorGUILayout.PropertyField(skeletonJSON, SpineInspectorUtility.TempContent(skeletonJSON.displayName, Icons.spine));
                EditorGUILayout.PropertyField(scale);
            }

//			if (m_skeletonData != null) {
//				if (SpineInspectorUtility.CenteredButton(new GUIContent("Instantiate", Icons.spine, "Creates a new Spine GameObject in the active scene using this Skeleton Data.\nYou can also instantiate by dragging the SkeletonData asset from Project view into Scene View.")))
//					SpineEditorUtilities.ShowInstantiateContextMenu(this.m_skeletonDataAsset, Vector3.zero);
//			}

            // Atlas
            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUILayout.LabelField("Atlas", EditorStyles.boldLabel);
                                #if !SPINE_TK2D
                EditorGUILayout.PropertyField(atlasAssets, true);
                                #else
                using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
                    EditorGUILayout.PropertyField(atlasAssets, true);
                }
                EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
                EditorGUILayout.PropertyField(spriteCollection, true);
                                #endif

                {
                    bool hasNulls = false;
                    foreach (var a in m_skeletonDataAsset.atlasAssets)
                    {
                        if (a == null)
                        {
                            hasNulls = true;
                            break;
                        }
                    }
                    if (hasNulls)
                    {
                        if (m_skeletonDataAsset.atlasAssets.Length == 1)
                        {
                            EditorGUILayout.HelpBox("Atlas array cannot have null entries!", MessageType.None);
                        }
                        else
                        {
                            EditorGUILayout.HelpBox("Atlas array should not have null entries!", MessageType.Error);
                            if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Remove null entries")))
                            {
                                var trimmedAtlasAssets = new List <AtlasAsset>();
                                foreach (var a in m_skeletonDataAsset.atlasAssets)
                                {
                                    if (a != null)
                                    {
                                        trimmedAtlasAssets.Add(a);
                                    }
                                }
                                m_skeletonDataAsset.atlasAssets = trimmedAtlasAssets.ToArray();
                                serializedObject.Update();
                            }
                        }
                    }
                }
            }

            if (EditorGUI.EndChangeCheck())
            {
                if (serializedObject.ApplyModifiedProperties())
                {
                    if (m_previewUtility != null)
                    {
                        m_previewUtility.Cleanup();
                        m_previewUtility = null;
                    }
                    m_skeletonDataAsset.Clear();
                    m_skeletonData = null;
                    OnEnable();                     // Should call RepopulateWarnings.
                    return;
                }
            }

            // Some code depends on the existence of m_skeletonAnimation instance.
            // If m_skeletonAnimation is lazy-instantiated elsewhere, this can cause contents to change between Layout and Repaint events, causing GUILayout control count errors.
            InitPreview();

            if (m_skeletonData != null)
            {
                GUILayout.Space(20f);

                using (new SpineInspectorUtility.BoxScope(false)) {
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Mix Settings", Icons.animationRoot), EditorStyles.boldLabel);
                    DrawAnimationStateInfo();
                    EditorGUILayout.Space();
                }

                EditorGUILayout.LabelField("Preview", EditorStyles.boldLabel);
                DrawAnimationList();
                EditorGUILayout.Space();
                DrawSlotList();
                EditorGUILayout.Space();
                DrawUnityTools();
            }
            else
            {
                                #if !SPINE_TK2D
                // Reimport Button
                using (new EditorGUI.DisabledGroupScope(skeletonJSON.objectReferenceValue == null)) {
                    if (GUILayout.Button(SpineInspectorUtility.TempContent("Attempt Reimport", Icons.warning)))
                    {
                        DoReimport();
                    }
                }
                                #else
                EditorGUILayout.HelpBox("Couldn't load SkeletonData.", MessageType.Error);
                                #endif

                // List warnings.
                foreach (var line in warnings)
                {
                    EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(line, Icons.warning));
                }
            }

            if (!Application.isPlaying)
            {
                serializedObject.ApplyModifiedProperties();
            }
        }
        protected virtual void DrawInspectorGUI(bool multi)
        {
            // Initialize.
            if (Event.current.type == EventType.Layout)
            {
                if (forceReloadQueued)
                {
                    forceReloadQueued = false;
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            EditorForceReloadSkeletonDataAssetAndComponent(c as SkeletonRenderer);
                        }
                    }
                    else
                    {
                        EditorForceReloadSkeletonDataAssetAndComponent(target as SkeletonRenderer);
                    }
                }
                else
                {
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            var component = c as SkeletonRenderer;
                            if (!component.valid)
                            {
                                EditorForceInitializeComponent(component);
                                if (!component.valid)
                                {
                                    continue;
                                }
                            }
                        }
                    }
                    else
                    {
                        var component = (SkeletonRenderer)target;
                        if (!component.valid)
                        {
                            EditorForceInitializeComponent(component);
                        }
                    }
                }

                                #if BUILT_IN_SPRITE_MASK_COMPONENT
                if (setMaskNoneMaterialsQueued)
                {
                    setMaskNoneMaterialsQueued = false;
                    foreach (var c in targets)
                    {
                        EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.None);
                    }
                }
                if (setInsideMaskMaterialsQueued)
                {
                    setInsideMaskMaterialsQueued = false;
                    foreach (var c in targets)
                    {
                        EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask);
                    }
                }
                if (setOutsideMaskMaterialsQueued)
                {
                    setOutsideMaskMaterialsQueued = false;
                    foreach (var c in targets)
                    {
                        EditorSetMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask);
                    }
                }

                if (deleteInsideMaskMaterialsQueued)
                {
                    deleteInsideMaskMaterialsQueued = false;
                    foreach (var c in targets)
                    {
                        EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleInsideMask);
                    }
                }
                if (deleteOutsideMaskMaterialsQueued)
                {
                    deleteOutsideMaskMaterialsQueued = false;
                    foreach (var c in targets)
                    {
                        EditorDeleteMaskMaterials(c as SkeletonRenderer, SpriteMaskInteraction.VisibleOutsideMask);
                    }
                }
                                #endif

#if NO_PREFAB_MESH
                if (isInspectingPrefab)
                {
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            var        component  = (SkeletonRenderer)c;
                            MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                            if (meshFilter != null && meshFilter.sharedMesh != null)
                            {
                                meshFilter.sharedMesh = null;
                            }
                        }
                    }
                    else
                    {
                        var        component  = (SkeletonRenderer)target;
                        MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                        if (meshFilter != null && meshFilter.sharedMesh != null)
                        {
                            meshFilter.sharedMesh = null;
                        }
                    }
                }
#endif
            }

            bool valid = TargetIsValid;

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

                if (valid)
                {
                    EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
                }
            }
            else
            {
                var component = (SkeletonRenderer)target;

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

                if (component.skeletonDataAsset == null)
                {
                    EditorGUILayout.HelpBox("Skeleton Data Asset required", MessageType.Warning);
                    return;
                }

                if (!SkeletonDataAssetIsValid(component.skeletonDataAsset))
                {
                    EditorGUILayout.HelpBox("Skeleton Data Asset error. Please check Skeleton Data Asset.", MessageType.Error);
                    return;
                }

                if (valid)
                {
                    EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
                }
            }

            EditorGUILayout.Space();

            // Sorting Layers
            SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);

            if (maskInteraction != null)
            {
                EditorGUILayout.PropertyField(maskInteraction, MaskInteractionLabel);
            }

            if (!valid)
            {
                return;
            }

            string errorMessage = null;
            if (MaterialChecks.IsMaterialSetupProblematic((SkeletonRenderer)this.target, ref errorMessage))
            {
                EditorGUILayout.HelpBox(errorMessage, MessageType.Error, true);
            }

            // More Render Options...
            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUI.BeginChangeCheck();

                EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
                advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
                if (advancedFoldout)
                {
                    EditorGUILayout.Space();
                    if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
                    {
                        SkeletonDebugWindow.Init();
                    }
                }
                else
                {
                    EditorGUILayout.Space();
                }
                EditorGUILayout.EndHorizontal();

                if (advancedFoldout)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.HorizontalScope()) {
                            SpineInspectorUtility.ToggleLeftLayout(initialFlipX);
                            SpineInspectorUtility.ToggleLeftLayout(initialFlipY);
                            EditorGUILayout.Space();
                        }

                        EditorGUILayout.Space();
                        EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel);
                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            // Optimization options
                            if (singleSubmesh != null)
                            {
                                EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
                            }
                                                        #if PER_MATERIAL_PROPERTY_BLOCKS
                            if (fixDrawOrder != null)
                            {
                                EditorGUILayout.PropertyField(fixDrawOrder, FixDrawOrderLabel);
                            }
                                                        #endif
                            if (immutableTriangles != null)
                            {
                                EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
                            }
                            EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);
                            EditorGUILayout.Space();
                        }

                        SeparatorsField(separatorSlotNames);
                        EditorGUILayout.Space();

                        // Render options
                        const float MinZSpacing = -0.1f;
                        const float MaxZSpacing = 0f;
                        EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
                        EditorGUILayout.Space();

                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon <MeshFilter>()), EditorStyles.boldLabel);
                            if (pmaVertexColors != null)
                            {
                                EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
                            }
                            EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);

                            // Optional fields. May be disabled in SkeletonRenderer.
                            if (normals != null)
                            {
                                EditorGUILayout.PropertyField(normals, NormalsLabel);
                            }
                            if (tangents != null)
                            {
                                EditorGUILayout.PropertyField(tangents, TangentsLabel);
                            }
                        }

                                                #if BUILT_IN_SPRITE_MASK_COMPONENT
                        EditorGUILayout.Space();
                        if (maskMaterialsNone.arraySize > 0 || maskMaterialsInside.arraySize > 0 || maskMaterialsOutside.arraySize > 0)
                        {
                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Mask Interaction Materials", SpineInspectorUtility.UnityIcon <SpriteMask>()), EditorStyles.boldLabel);
                            bool differentMaskModesSelected = maskInteraction.hasMultipleDifferentValues;
                            int  activeMaskInteractionValue = differentMaskModesSelected ? -1 : maskInteraction.intValue;

                            bool ignoredParam = true;
                            MaskMaterialsEditingField(ref setMaskNoneMaterialsQueued, ref ignoredParam, maskMaterialsNone, MaskMaterialsNoneLabel,
                                                      differentMaskModesSelected, allowDelete: false, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.None);
                            MaskMaterialsEditingField(ref setInsideMaskMaterialsQueued, ref deleteInsideMaskMaterialsQueued, maskMaterialsInside, MaskMaterialsInsideLabel,
                                                      differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleInsideMask);
                            MaskMaterialsEditingField(ref setOutsideMaskMaterialsQueued, ref deleteOutsideMaskMaterialsQueued, maskMaterialsOutside, MaskMaterialsOutsideLabel,
                                                      differentMaskModesSelected, allowDelete: true, isActiveMaterial: activeMaskInteractionValue == (int)SpriteMaskInteraction.VisibleOutsideMask);
                        }
                                                #endif

                        EditorGUILayout.Space();

                        if (valid && !isInspectingPrefab)
                        {
                            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
                            {
                                var component = (Component)target;
                                if (component.GetComponent <SkeletonUtility>() == null)
                                {
                                    if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
                                    {
                                        component.gameObject.AddComponent <SkeletonUtility>();
                                    }
                                }
                            }
                        }

                        EditorGUILayout.Space();
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    SceneView.RepaintAll();
                }
            }
        }
예제 #8
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();
        }
예제 #9
0
        public override void OnInspectorGUI()
        {
            EditorGUI.BeginChangeCheck();

            EditorGUILayout.PropertyField(skeletonDataAsset);
            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;
            }
            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUILayout.PropertyField(meshGeneratorSettings, SpineInspectorUtility.TempContent("Advanced..."), includeChildren: true);
                SkeletonRendererInspector.advancedFoldout = meshGeneratorSettings.isExpanded;
            }

            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();
            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>();
                        }
                    }
                }
            }

            bool wasChanged = EditorGUI.EndChangeCheck();

            if (wasChanged)
            {
                serializedObject.ApplyModifiedProperties();
            }
        }
예제 #10
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;
            }
        }
예제 #11
0
        protected virtual void DrawInspectorGUI(bool multi)
        {
            // Initialize.
            if (Event.current.type == EventType.Layout)
            {
                if (forceReloadQueued)
                {
                    forceReloadQueued = false;
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            EditorForceReloadSkeletonDataAssetAndComponent(c as SkeletonRenderer);
                        }
                    }
                    else
                    {
                        EditorForceReloadSkeletonDataAssetAndComponent(target as SkeletonRenderer);
                    }
                }
                else
                {
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            var component = c as SkeletonRenderer;
                            if (!component.valid)
                            {
                                EditorForceInitializeComponent(component);
                                if (!component.valid)
                                {
                                    continue;
                                }
                            }
                        }
                    }
                    else
                    {
                        var component = (SkeletonRenderer)target;
                        if (!component.valid)
                        {
                            EditorForceInitializeComponent(component);
                        }
                    }
                }

                                #if NO_PREFAB_MESH
                if (isInspectingPrefab)
                {
                    if (multi)
                    {
                        foreach (var c in targets)
                        {
                            var        component  = (SkeletonRenderer)c;
                            MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                            if (meshFilter != null && meshFilter.sharedMesh != null)
                            {
                                meshFilter.sharedMesh = null;
                            }
                        }
                    }
                    else
                    {
                        var        component  = (SkeletonRenderer)target;
                        MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                        if (meshFilter != null && meshFilter.sharedMesh != null)
                        {
                            meshFilter.sharedMesh = null;
                        }
                    }
                }
                                #endif
            }

            bool valid = TargetIsValid;

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

                if (valid)
                {
                    EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
                }
            }
            else
            {
                var component = (SkeletonRenderer)target;

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

                if (component.skeletonDataAsset == null)
                {
                    EditorGUILayout.HelpBox("Skeleton Data Asset required", MessageType.Warning);
                    return;
                }

                if (!SkeletonDataAssetIsValid(component.skeletonDataAsset))
                {
                    EditorGUILayout.HelpBox("Skeleton Data Asset error. Please check Skeleton Data Asset.", MessageType.Error);
                    return;
                }

                if (valid)
                {
                    EditorGUILayout.PropertyField(initialSkinName, SpineInspectorUtility.TempContent("Initial Skin"));
                }
            }

            EditorGUILayout.Space();

            // Sorting Layers
            SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);

            if (!valid)
            {
                return;
            }

            // More Render Options...
            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUI.BeginChangeCheck();

                EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
                advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
                if (advancedFoldout)
                {
                    EditorGUILayout.Space();
                    if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
                    {
                        SkeletonDebugWindow.Init();
                    }
                }
                else
                {
                    EditorGUILayout.Space();
                }
                EditorGUILayout.EndHorizontal();

                if (advancedFoldout)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.HorizontalScope()) {
                            SpineInspectorUtility.ToggleLeftLayout(initialFlipX);
                            SpineInspectorUtility.ToggleLeftLayout(initialFlipY);
                            EditorGUILayout.Space();
                        }

                        EditorGUILayout.Space();
                        EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel);
                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            // Optimization options
                            if (singleSubmesh != null)
                            {
                                EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
                            }
                            if (immutableTriangles != null)
                            {
                                EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
                            }
                            EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);
                            EditorGUILayout.Space();
                        }

                        SeparatorsField(separatorSlotNames);
                        EditorGUILayout.Space();

                        // Render options
                        const float MinZSpacing = -0.1f;
                        const float MaxZSpacing = 0f;
                        EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
                        EditorGUILayout.Space();

                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon <MeshFilter>()), EditorStyles.boldLabel);
                            if (pmaVertexColors != null)
                            {
                                EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
                            }
                            EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);

                            // Optional fields. May be disabled in SkeletonRenderer.
                            if (normals != null)
                            {
                                EditorGUILayout.PropertyField(normals, NormalsLabel);
                            }
                            if (tangents != null)
                            {
                                EditorGUILayout.PropertyField(tangents, TangentsLabel);
                            }
                        }

                        EditorGUILayout.Space();

                        if (valid && !isInspectingPrefab)
                        {
                            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
                            {
                                var component = (Component)target;
                                if (component.GetComponent <SkeletonUtility>() == null)
                                {
                                    if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
                                    {
                                        component.gameObject.AddComponent <SkeletonUtility>();
                                    }
                                }
                            }
                        }

                        EditorGUILayout.Space();
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    SceneView.RepaintAll();
                }
            }
        }
        protected virtual void DrawInspectorGUI(bool multi)
        {
            bool valid             = TargetIsValid;
            var  reloadWidth       = GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20);
            var  reloadButtonStyle = EditorStyles.miniButtonRight;

            if (multi)
            {
                using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
                    SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
                    if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth))
                    {
                        foreach (var c in targets)
                        {
                            var component = c as SkeletonRenderer;
                            if (component.skeletonDataAsset != null)
                            {
                                foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
                                {
                                    if (aa != null)
                                    {
                                        aa.Clear();
                                    }
                                }
                                component.skeletonDataAsset.Clear();
                            }
                            component.Initialize(true);
                        }
                    }
                }

                foreach (var c in targets)
                {
                    var component = c as SkeletonRenderer;
                    if (!component.valid)
                    {
                        if (Event.current.type == EventType.Layout)
                        {
                            component.Initialize(true);
                            component.LateUpdate();
                        }
                        if (!component.valid)
                        {
                            continue;
                        }
                    }

                                        #if NO_PREFAB_MESH
                    if (isInspectingPrefab)
                    {
                        MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                        if (meshFilter != null)
                        {
                            meshFilter.sharedMesh = null;
                        }
                    }
                                        #endif
                }

                if (valid)
                {
                    EditorGUILayout.PropertyField(initialSkinName);
                }
            }
            else
            {
                var component = (SkeletonRenderer)target;

                if (!component.valid && Event.current.type == EventType.Layout)
                {
                    component.Initialize(true);
                    // component.LateUpdate();
                }

                using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) {
                    SpineInspectorUtility.PropertyFieldFitLabel(skeletonDataAsset, SkeletonDataAssetLabel);
                    if (component.valid)
                    {
                        if (GUILayout.Button(ReloadButtonLabel, reloadButtonStyle, reloadWidth))
                        {
                            if (component.skeletonDataAsset != null)
                            {
                                foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
                                {
                                    if (aa != null)
                                    {
                                        aa.Clear();
                                    }
                                }
                                component.skeletonDataAsset.Clear();
                            }
                            component.Initialize(true);
                        }
                    }
                }

                if (component.skeletonDataAsset == null)
                {
                    EditorGUILayout.HelpBox("Skeleton Data Asset required", MessageType.Warning);
                    return;
                }

                                #if NO_PREFAB_MESH
                if (isInspectingPrefab)
                {
                    MeshFilter meshFilter = component.GetComponent <MeshFilter>();
                    if (meshFilter != null)
                    {
                        meshFilter.sharedMesh = null;
                    }
                }
                                #endif

                // Initial skin name.
                if (component.valid)
                {
                    var skeletonDataSkins = component.skeleton.Data.Skins;
                    int skinCount         = skeletonDataSkins.Count;
                    if (loadedSkinList != skeletonDataSkins)
                    {
                        skins          = new GUIContent[skinCount];
                        loadedSkinList = skeletonDataSkins;
                        for (int i = 0; i < skins.Length; i++)
                        {
                            string skinNameString = skeletonDataSkins.Items[i].Name;
                            skins[i] = new GUIContent(skinNameString, Icons.skin);
                        }
                    }

                    int skinIndex = 0;
                    for (int i = 0; i < skins.Length; i++)
                    {
                        string skinNameString = skeletonDataSkins.Items[i].Name;
                        if (skinNameString == initialSkinName.stringValue)
                        {
                            skinIndex = i;
                        }
                    }

                    skinIndex = EditorGUILayout.Popup(SpineInspectorUtility.TempContent("Initial Skin"), skinIndex, skins);
                    if (skins.Length > 0)                     // Support attachmentless/skinless SkeletonData.
                    {
                        initialSkinName.stringValue = skins[skinIndex].text;
                    }
                }
            }

            EditorGUILayout.Space();

            // Sorting Layers
            //SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true);

            if (!TargetIsValid)
            {
                return;
            }
            // More Render Options...
            using (new SpineInspectorUtility.BoxScope()) {
                EditorGUI.BeginChangeCheck();

                EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
                advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
                if (advancedFoldout)
                {
                    EditorGUILayout.Space();
                    if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
                    {
                        SkeletonDebugWindow.Init();
                    }
                }
                else
                {
                    EditorGUILayout.Space();
                }
                EditorGUILayout.EndHorizontal();

                if (advancedFoldout)
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        using (new EditorGUILayout.HorizontalScope()) {
                            initialFlipX.boolValue = EditorGUILayout.ToggleLeft(initialFlipX.displayName, initialFlipX.boolValue, GUILayout.Width(120f));
                            initialFlipY.boolValue = EditorGUILayout.ToggleLeft(initialFlipY.displayName, initialFlipY.boolValue, GUILayout.Width(120f));
                            EditorGUILayout.Space();
                        }

                        EditorGUILayout.Space();
                        EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel);
                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            // Optimization options
                            if (singleSubmesh != null)
                            {
                                EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
                            }
                            //if (meshes != null) EditorGUILayout.PropertyField(meshes, MeshesLabel);
                            if (immutableTriangles != null)
                            {
                                EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
                            }
                            EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);
                            EditorGUILayout.Space();
                        }

                        SeparatorsField(separatorSlotNames);
                        EditorGUILayout.Space();

                        // Render options
                        const float MinZSpacing = -0.1f;
                        const float MaxZSpacing = 0f;
                        EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing, ZSpacingLabel);
                        EditorGUILayout.Space();

                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", SpineInspectorUtility.UnityIcon <MeshFilter>()), EditorStyles.boldLabel);
                            if (pmaVertexColors != null)
                            {
                                EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
                            }
                            EditorGUILayout.PropertyField(tintBlack, TintBlackLabel);

                            // Optional fields. May be disabled in SkeletonRenderer.
                            if (normals != null)
                            {
                                EditorGUILayout.PropertyField(normals, NormalsLabel);
                            }
                            if (tangents != null)
                            {
                                EditorGUILayout.PropertyField(tangents, TangentsLabel);
                            }
                        }

                        EditorGUILayout.Space();

                        if (TargetIsValid && !isInspectingPrefab)
                        {
                            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
                            {
                                var component = (Component)target;
                                if (component.GetComponent <SkeletonUtility>() == null)
                                {
                                    if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
                                    {
                                        component.gameObject.AddComponent <SkeletonUtility>();
                                    }
                                }
                            }
                        }

                        EditorGUILayout.Space();
                    }
                }

                if (EditorGUI.EndChangeCheck())
                {
                    SceneView.RepaintAll();
                }
            }
        }