Пример #1
0
        void OnEnable()
        {
            skeletonUtility  = (SkeletonUtility)target;
            skeletonRenderer = skeletonUtility.skeletonRenderer;
            skeletonGraphic  = skeletonUtility.skeletonGraphic;
            skeleton         = skeletonUtility.Skeleton;

            if (skeleton == null)
            {
                if (skeletonRenderer != null)
                {
                    skeletonRenderer.Initialize(false);
                    skeletonRenderer.LateUpdate();
                }
                else if (skeletonGraphic != null)
                {
                    skeletonGraphic.Initialize(false);
                    skeletonGraphic.LateUpdate();
                }
                skeleton = skeletonUtility.Skeleton;
            }

            if ((skeletonRenderer != null && !skeletonRenderer.valid) ||
                (skeletonGraphic != null && !skeletonGraphic.IsValid))
            {
                return;
            }

#if !NEW_PREFAB_SYSTEM
            isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
#endif
        }
Пример #2
0
        public static void ReinitializeComponent(SkeletonRenderer component)
        {
            if (component == null)
            {
                return;
            }
            if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset))
            {
                return;
            }

            var            stateComponent    = component as IAnimationStateComponent;
            AnimationState oldAnimationState = null;

            if (stateComponent != null)
            {
                oldAnimationState = stateComponent.AnimationState;
            }

            component.Initialize(true);             // implicitly clears any subscribers

            if (oldAnimationState != null)
            {
                stateComponent.AnimationState.AssignEventSubscribersFrom(oldAnimationState);
            }

#if BUILT_IN_SPRITE_MASK_COMPONENT
            SpineMaskUtilities.EditorAssignSpriteMaskMaterials(component);
#endif
            component.LateUpdate();
        }
        /// <summary>Adds a SkeletonRenderSeparator and child SkeletonPartsRenderer GameObjects to a given SkeletonRenderer.</summary>
        /// <returns>The to skeleton renderer.</returns>
        /// <param name="skeletonRenderer">The target SkeletonRenderer or SkeletonAnimation.</param>
        /// <param name="sortingLayerID">Sorting layer to be used for the parts renderers.</param>
        /// <param name="extraPartsRenderers">Number of additional SkeletonPartsRenderers on top of the ones determined by counting the number of separator slots.</param>
        /// <param name="sortingOrderIncrement">The integer to increment the sorting order per SkeletonPartsRenderer to separate them.</param>
        /// <param name="baseSortingOrder">The sorting order value of the first SkeletonPartsRenderer.</param>
        /// <param name="addMinimumPartsRenderers">If set to <c>true</c>, a minimum number of SkeletonPartsRenderer GameObjects (determined by separatorSlots.Count + 1) will be added.</param>
        public static SkeletonRenderSeparator AddToSkeletonRenderer(SkeletonRenderer skeletonRenderer, int sortingLayerID = 0, int extraPartsRenderers = 0, int sortingOrderIncrement = DefaultSortingOrderIncrement, int baseSortingOrder = 0, bool addMinimumPartsRenderers = true)
        {
            if (skeletonRenderer == null)
            {
                Debug.Log("Tried to add SkeletonRenderSeparator to a null SkeletonRenderer reference.");
                return(null);
            }

            var srs = skeletonRenderer.gameObject.AddComponent <SkeletonRenderSeparator>();

            srs.skeletonRenderer = skeletonRenderer;

            skeletonRenderer.Initialize(false);
            int count = extraPartsRenderers;

            if (addMinimumPartsRenderers)
            {
                count = extraPartsRenderers + skeletonRenderer.separatorSlots.Count + 1;
            }

            var skeletonRendererTransform = skeletonRenderer.transform;
            var componentRenderers        = srs.partsRenderers;

            for (int i = 0; i < count; i++)
            {
                var spr = SkeletonPartsRenderer.NewPartsRendererGameObject(skeletonRendererTransform, i.ToString());
                var mr  = spr.MeshRenderer;
                mr.sortingLayerID = sortingLayerID;
                mr.sortingOrder   = baseSortingOrder + (i * sortingOrderIncrement);
                componentRenderers.Add(spr);
            }

            return(srs);
        }
Пример #4
0
        public static SkeletonRenderSeparator AddToSkeletonRenderer(SkeletonRenderer skeletonRenderer, int sortingLayerID = 0, int extraPartsRenderers = 0, int sortingOrderIncrement = 5, int baseSortingOrder = 0, bool addMinimumPartsRenderers = true)
        {
            if (skeletonRenderer == null)
            {
                return(null);
            }
            SkeletonRenderSeparator skeletonRenderSeparator = skeletonRenderer.gameObject.AddComponent <SkeletonRenderSeparator>();

            skeletonRenderSeparator.skeletonRenderer = skeletonRenderer;
            skeletonRenderer.Initialize(overwrite: false);
            int num = extraPartsRenderers;

            if (addMinimumPartsRenderers)
            {
                num = extraPartsRenderers + skeletonRenderer.separatorSlots.Count + 1;
            }
            Transform transform = skeletonRenderer.transform;
            List <SkeletonPartsRenderer> list = skeletonRenderSeparator.partsRenderers;

            for (int i = 0; i < num; i++)
            {
                SkeletonPartsRenderer skeletonPartsRenderer = SkeletonPartsRenderer.NewPartsRendererGameObject(transform, i.ToString());
                MeshRenderer          meshRenderer          = skeletonPartsRenderer.MeshRenderer;
                meshRenderer.sortingLayerID = sortingLayerID;
                meshRenderer.sortingOrder   = baseSortingOrder + i * sortingOrderIncrement;
                list.Add(skeletonPartsRenderer);
            }
            return(skeletonRenderSeparator);
        }
Пример #5
0
        protected void ApplyModifiedMeshParameters(SkeletonRenderer skeletonRenderer)
        {
            if (skeletonRenderer == null)
            {
                return;
            }
            if (!skeletonRenderer.valid)
            {
                return;
            }

            if (!isInspectingPrefab)
            {
                if (wasInitParameterChanged)
                {
                    wasInitParameterChanged = false;
                    if (!Application.isPlaying)
                    {
                        skeletonRenderer.Initialize(true);
                        skeletonRenderer.LateUpdate();
                        requireRepaint = true;
                    }
                }
            }
        }
Пример #6
0
 protected virtual void Awake()
 {
     RenderCanvas     = GetComponent <RenderCanvas>();
     MeshRenderer     = GetComponent <MeshRenderer>();
     MeshFilter       = GetComponent <MeshFilter>();
     SkeletonRenderer = GetComponent <SkeletonRenderer>();
     SkeletonRenderer.Initialize(false);
 }
    public void HandleReset(SkeletonRenderer renderer)
    {
        if (slotName == null || slotName == "")
        {
            return;
        }

        hasReset = true;

        ClearColliders();
        colliderTable.Clear();

        if (skeletonRenderer.skeleton == null)
        {
            skeletonRenderer.OnRebuild -= HandleReset;
            skeletonRenderer.Initialize(false);
            skeletonRenderer.OnRebuild += HandleReset;
        }


        var skeleton = skeletonRenderer.skeleton;

        slot = skeleton.FindSlot(slotName);
        int slotIndex = skeleton.FindSlotIndex(slotName);

        foreach (var skin in skeleton.Data.Skins)
        {
            List <string> attachmentNames = new List <string>();
            skin.FindNamesForSlot(slotIndex, attachmentNames);

            foreach (var name in attachmentNames)
            {
                var attachment = skin.GetAttachment(slotIndex, name);
                if (attachment is BoundingBoxAttachment)
                {
                    var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)attachment, gameObject, true);
                    collider.enabled   = false;
                    collider.hideFlags = HideFlags.HideInInspector;
                    colliderTable.Add((BoundingBoxAttachment)attachment, collider);
                    attachmentNameTable.Add((BoundingBoxAttachment)attachment, name);
                }
            }
        }

        if (colliderTable.Count == 0)
        {
            valid = false;
        }
        else
        {
            valid = true;
        }

        if (!valid)
        {
            Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
        }
    }
Пример #8
0
 static void EditorForceInitializeComponent(SkeletonRenderer component)
 {
     if (component == null)
     {
         return;
     }
     if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset))
     {
         return;
     }
     component.Initialize(true);
     component.LateUpdate();
 }
Пример #9
0
    void OnEnable()
    {
        skeletonUtility  = GetComponent <SkeletonUtility>();
        skeletonRenderer = skeletonUtility.GetComponent <SkeletonRenderer>();
        skeleton         = skeletonRenderer.Skeleton;

        if (skeleton == null)
        {
            skeletonRenderer.Initialize(false);
            skeletonRenderer.LateUpdate();
            skeleton = skeletonRenderer.skeleton;
        }
    }
Пример #10
0
        void OnSelectionChange()
        {
                #if UNITY_2019_1_OR_NEWER
            SceneView.duringSceneGui -= this.OnSceneGUI;
            SceneView.duringSceneGui += this.OnSceneGUI;
                #else
            SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
            SceneView.onSceneGUIDelegate += this.OnSceneGUI;
                #endif

            bool noSkeletonRenderer = false;

            var selectedObject = Selection.activeGameObject;
            if (selectedObject == null)
            {
                noSkeletonRenderer = true;
            }
            else
            {
                var selectedSkeletonRenderer = selectedObject.GetComponent <SkeletonRenderer>();
                if (selectedSkeletonRenderer == null)
                {
                    noSkeletonRenderer = true;
                }
                else if (skeletonRenderer != selectedSkeletonRenderer)
                {
                    bone = null;
                    if (skeletonRenderer != null && skeletonRenderer.SkeletonDataAsset != selectedSkeletonRenderer.SkeletonDataAsset)
                    {
                        boneName = null;
                    }

                    skeletonRenderer = selectedSkeletonRenderer;
                    skeletonRenderer.Initialize(false);
                    skeletonRenderer.LateUpdate();
                    skeleton = skeletonRenderer.skeleton;
#if NEW_PREFAB_SYSTEM
                    isPrefab = false;
#else
                    isPrefab |= PrefabUtility.GetPrefabType(selectedObject) == PrefabType.Prefab;
#endif
                    UpdateAttachments();
                }
            }

            if (noSkeletonRenderer)
            {
                Clear();
            }
            Repaint();
        }
Пример #11
0
 private void OnEnable()
 {
     if (skeletonRenderer == null)
     {
         skeletonRenderer = GetComponent <SkeletonRenderer>();
     }
     if (skeletonRenderer == null)
     {
         UnityEngine.Debug.LogError("skeletonRenderer == null");
         return;
     }
     skeletonRenderer.Initialize(overwrite: false);
     SetCustomMaterialOverrides();
     SetCustomSlotMaterials();
 }
Пример #12
0
        /// <summary>Adds a SkeletonRenderSeparator and child SkeletonPartsRenderer GameObjects to a given SkeletonRenderer.</summary>
        /// <returns>The to skeleton renderer.</returns>
        /// <param name="skeletonRenderer">The target SkeletonRenderer or SkeletonAnimation.</param>
        /// <param name="sortingLayerID">Sorting layer to be used for the parts renderers.</param>
        /// <param name="extraPartsRenderers">Number of additional SkeletonPartsRenderers on top of the ones determined by counting the number of separator slots.</param>
        /// <param name="sortingOrderIncrement">The integer to increment the sorting order per SkeletonPartsRenderer to separate them.</param>
        /// <param name="baseSortingOrder">The sorting order value of the first SkeletonPartsRenderer.</param>
        /// <param name="addMinimumPartsRenderers">If set to <c>true</c>, a minimum number of SkeletonPartsRenderer GameObjects (determined by separatorSlots.Count + 1) will be added.</param>
        public static SkeletonRenderSeparator AddToSkeletonRenderer(SkeletonRenderer skeletonRenderer, int sortingLayerID = 0, int extraPartsRenderers = 0, int sortingOrderIncrement = DefaultSortingOrderIncrement, int baseSortingOrder = 0, bool addMinimumPartsRenderers = true)
        {
            if (skeletonRenderer == null)
            {
                Debug.Log("Tried to add SkeletonRenderSeparator to a null SkeletonRenderer reference.");
                return(null);
            }

            var srs = skeletonRenderer.gameObject.AddComponent <SkeletonRenderSeparator>();

            srs.skeletonRenderer = skeletonRenderer;

            skeletonRenderer.Initialize(false);
            int count = extraPartsRenderers;

            if (addMinimumPartsRenderers)
            {
                count = extraPartsRenderers + skeletonRenderer.separatorSlots.Count + 1;
            }

            var skeletonRendererTransform = skeletonRenderer.transform;
            var componentRenderers        = srs.partsRenderers;

            for (int i = 0; i < count; i++)
            {
                var spr = SkeletonPartsRenderer.NewPartsRendererGameObject(skeletonRendererTransform, i.ToString());
                var mr  = spr.MeshRenderer;
                mr.sortingLayerID = sortingLayerID;
                mr.sortingOrder   = baseSortingOrder + (i * sortingOrderIncrement);
                componentRenderers.Add(spr);
            }

            srs.OnEnable();

                        #if UNITY_EDITOR
            // Make sure editor updates properly in edit mode.
            if (!Application.isPlaying)
            {
                skeletonRenderer.enabled = false;
                skeletonRenderer.enabled = true;
                skeletonRenderer.LateUpdate();
            }
                        #endif

            return(srs);
        }
        public static void ReinitializeComponent(SkeletonRenderer component)
        {
            if (component == null)
            {
                return;
            }
            if (!SkeletonDataAssetIsValid(component.SkeletonDataAsset))
            {
                return;
            }
            component.Initialize(true);

                #if BUILT_IN_SPRITE_MASK_COMPONENT
            SpineMaskUtilities.EditorAssignSpriteMaskMaterials(component);
                #endif
            component.LateUpdate();
        }
Пример #14
0
        void OnSelectionChange()
        {
            SceneView.onSceneGUIDelegate -= this.OnSceneGUI;
            SceneView.onSceneGUIDelegate += this.OnSceneGUI;

            bool noSkeletonRenderer = false;

            var selectedObject = Selection.activeGameObject;

            if (selectedObject == null)
            {
                noSkeletonRenderer = true;
            }
            else
            {
                var selectedSkeletonRenderer = selectedObject.GetComponent <SkeletonRenderer>();
                if (selectedSkeletonRenderer == null)
                {
                    noSkeletonRenderer = true;
                }
                else if (skeletonRenderer != selectedSkeletonRenderer)
                {
                    bone = null;
                    if (skeletonRenderer != null && skeletonRenderer.SkeletonDataAsset != selectedSkeletonRenderer.SkeletonDataAsset)
                    {
                        boneName = null;
                    }

                    skeletonRenderer = selectedSkeletonRenderer;
                    skeletonRenderer.Initialize(false);
                    skeletonRenderer.LateUpdate();
                    skeleton = skeletonRenderer.skeleton;
#pragma warning disable
                    isPrefab |= PrefabUtility.GetPrefabType(selectedObject) == PrefabType.Prefab;
#pragma warning restore
                    UpdateAttachments();
                }
            }

            if (noSkeletonRenderer)
            {
                Clear();
            }
            Repaint();
        }
        void OnEnable()
        {
            skeletonUtility  = (SkeletonUtility)target;
            skeletonRenderer = skeletonUtility.GetComponent <SkeletonRenderer>();
            skeleton         = skeletonRenderer.skeleton;
            transform        = skeletonRenderer.transform;

            if (skeleton == null)
            {
                skeletonRenderer.Initialize(false);
                skeletonRenderer.LateUpdate();

                skeleton = skeletonRenderer.skeleton;
            }

            UpdateAttachments();
            isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
        }
	void OnEnable () {
		skeletonUtility = (SkeletonUtility)target;
		skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
		skeleton = skeletonRenderer.skeleton;
		transform = skeletonRenderer.transform;

		if (skeleton == null) {
			skeletonRenderer.Initialize(false);
			skeletonRenderer.LateUpdate();

			skeleton = skeletonRenderer.skeleton;
		}

		UpdateAttachments();

		if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
			isPrefab = true;

	}
Пример #17
0
        void OnEnable()
        {
            skeletonUtility  = (SkeletonUtility)target;
            skeletonRenderer = skeletonUtility.GetComponent <SkeletonRenderer>();
            skeleton         = skeletonRenderer.Skeleton;

            if (skeleton == null)
            {
                skeletonRenderer.Initialize(false);
                skeletonRenderer.LateUpdate();
                skeleton = skeletonRenderer.skeleton;
            }

            if (!skeletonRenderer.valid)
            {
                return;
            }

            isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
        }
        protected virtual void DrawInspectorGUI()
        {
            // JOHN: todo: support multiediting.
            SkeletonRenderer component = (SkeletonRenderer)target;

            using (new EditorGUILayout.HorizontalScope()) {
                EditorGUILayout.PropertyField(skeletonDataAsset);
                const string ReloadButtonLabel = "Reload";
                float        reloadWidth       = GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20;
                if (GUILayout.Button(ReloadButtonLabel, GUILayout.Width(reloadWidth)))
                {
                    if (component.skeletonDataAsset != null)
                    {
                        foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
                        {
                            if (aa != null)
                            {
                                aa.Reset();
                            }
                        }
                        component.skeletonDataAsset.Reset();
                    }
                    component.Initialize(true);
                }
            }

            if (!component.valid)
            {
                component.Initialize(true);
                component.LateUpdate();
                if (!component.valid)
                {
                    return;
                }
            }

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

            if (isInspectingPrefab)
            {
                meshFilter.sharedMesh = null;
            }
                        #endif

            // Initial skin name.
            {
                string[] skins     = new string[component.skeleton.Data.Skins.Count];
                int      skinIndex = 0;
                for (int i = 0; i < skins.Length; i++)
                {
                    string skinNameString = component.skeleton.Data.Skins.Items[i].Name;
                    skins[i] = skinNameString;
                    if (skinNameString == initialSkinName.stringValue)
                    {
                        skinIndex = i;
                    }
                }
                skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
                initialSkinName.stringValue = skins[skinIndex];
            }

            EditorGUILayout.Space();

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

            // More Render Options...
            using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
                EditorGUI.indentLevel++;
                advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
                if (advancedFoldout)
                {
                    EditorGUI.indentLevel++;
                    SeparatorsField(separatorSlotNames);
                    EditorGUILayout.PropertyField(meshes,
                                                  new GUIContent("Render MeshAttachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
                    EditorGUILayout.PropertyField(immutableTriangles,
                                                  new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
                    EditorGUILayout.Space();

                    const float MinZSpacing = -0.1f;
                    const float MaxZSpacing = 0f;
                    EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);

                    // Optional fields. May be disabled in SkeletonRenderer.
                    if (normals != null)
                    {
                        EditorGUILayout.PropertyField(normals, new GUIContent("Add Normals"));
                    }
                    if (tangents != null)
                    {
                        EditorGUILayout.PropertyField(tangents, new GUIContent("Solve Tangents"));
                    }
                    if (frontFacing != null)
                    {
                        EditorGUILayout.PropertyField(frontFacing);
                    }

                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
        }
    protected virtual void DrawInspectorGUI()
    {
        SkeletonRenderer component = (SkeletonRenderer)target;

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(skeletonDataAsset);
        float reloadWidth = GUI.skin.label.CalcSize(new GUIContent("Reload")).x + 20;

        if (GUILayout.Button("Reload", GUILayout.Width(reloadWidth)))
        {
            if (component.skeletonDataAsset != null)
            {
                foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
                {
                    if (aa != null)
                    {
                        aa.Reset();
                    }
                }

                component.skeletonDataAsset.Reset();
            }
            component.Initialize(true);
        }
        EditorGUILayout.EndHorizontal();

        if (!component.valid)
        {
            component.Initialize(true);
            component.LateUpdate();
            if (!component.valid)
            {
                return;
            }
        }

        // Initial skin name.
        {
            String[] skins     = new String[component.skeleton.Data.Skins.Count];
            int      skinIndex = 0;
            for (int i = 0; i < skins.Length; i++)
            {
                String name = component.skeleton.Data.Skins.Items[i].Name;
                skins[i] = name;
                if (name == initialSkinName.stringValue)
                {
                    skinIndex = i;
                }
            }

            skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
            initialSkinName.stringValue = skins[skinIndex];
        }

        EditorGUILayout.Space();

        // Sorting Layers
        {
            var renderer = component.GetComponent <Renderer>();
            if (renderer != null)
            {
                EditorGUI.BeginChangeCheck();

                if (EditorGUILayoutSortingLayerField != null && sortingLayerIDProperty != null)
                {
                    EditorGUILayoutSortingLayerField.Invoke(null, new object[] { new GUIContent("Sorting Layer"), sortingLayerIDProperty, EditorStyles.popup });
                }
                else
                {
                    renderer.sortingLayerID = EditorGUILayout.IntField("Sorting Layer ID", renderer.sortingLayerID);
                }

                renderer.sortingOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder);

                if (EditorGUI.EndChangeCheck())
                {
                    rendererSerializedObject.ApplyModifiedProperties();
                    EditorUtility.SetDirty(renderer);
                }
            }
        }

        // More Render Options...
        {
            advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
            if (advancedFoldout)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(submeshSeparators, true);
                EditorGUILayout.Space();
                EditorGUILayout.PropertyField(meshes,
                                              new GUIContent("Render Mesh Attachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
                EditorGUILayout.PropertyField(immutableTriangles,
                                              new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
                EditorGUILayout.Space();

                const float MinZSpacing = -0.1f;
                const float MaxZSpacing = 0f;
                EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);

                EditorGUILayout.PropertyField(normals);
                EditorGUILayout.PropertyField(tangents);
                EditorGUILayout.PropertyField(front);
                EditorGUILayout.Separator();
                EditorGUI.indentLevel--;
            }
        }
    }
        protected virtual void DrawInspectorGUI()
        {
            SkeletonRenderer component = (SkeletonRenderer)target;

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(skeletonDataAsset);
            float reloadWidth = GUI.skin.label.CalcSize(new GUIContent("Reload")).x + 20;

            if (GUILayout.Button("Reload", GUILayout.Width(reloadWidth)))
            {
                if (component.skeletonDataAsset != null)
                {
                    foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets)
                    {
                        if (aa != null)
                        {
                            aa.Reset();
                        }
                    }

                    component.skeletonDataAsset.Reset();
                }
                component.Initialize(true);
            }
            EditorGUILayout.EndHorizontal();

            if (!component.valid)
            {
                component.Initialize(true);
                component.LateUpdate();
                if (!component.valid)
                {
                    return;
                }
            }

            // Initial skin name.
            {
                String[] skins     = new String[component.skeleton.Data.Skins.Count];
                int      skinIndex = 0;
                for (int i = 0; i < skins.Length; i++)
                {
                    String skinNameString = component.skeleton.Data.Skins.Items[i].Name;
                    skins[i] = skinNameString;
                    if (skinNameString == initialSkinName.stringValue)
                    {
                        skinIndex = i;
                    }
                }

                skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
                initialSkinName.stringValue = skins[skinIndex];
            }

            EditorGUILayout.Space();

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

            // More Render Options...
            {
                using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
                    EditorGUI.indentLevel++;
                    advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
                    if (advancedFoldout)
                    {
                        EditorGUI.indentLevel++;
                        SeparatorsField(separatorSlotNames);
                        EditorGUILayout.PropertyField(meshes,
                                                      new GUIContent("Render Mesh Attachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
                        EditorGUILayout.PropertyField(immutableTriangles,
                                                      new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
                        EditorGUILayout.Space();

                        const float MinZSpacing = -0.1f;
                        const float MaxZSpacing = 0f;
                        EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);

                        if (normals != null)
                        {
                            EditorGUILayout.PropertyField(normals);
                            EditorGUILayout.PropertyField(tangents);
                        }

                        if (front != null)
                        {
                            EditorGUILayout.PropertyField(front);
                        }
                        EditorGUI.indentLevel--;
                    }
                    EditorGUI.indentLevel--;
                }
            }
        }