void OnGUI()
        {
            so = so ?? new SerializedObject(this);

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

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

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

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

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

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

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

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

            if (skeletonData == null)
            {
                return;
            }

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

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

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

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

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

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

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


            if (skeletonData.Skins.Count > 1)
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
        }
Ejemplo n.º 2
0
        void OnGUI()
        {
            so = so ?? new SerializedObject(this);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent(string.Format("Bake All ({0} skins)", skeletonData.Skins.Count), prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
            else
            {
                if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Bake Skeleton", prefabIcon)))
                {
                    SkeletonBaker.BakeToPrefab(skeletonDataAsset, new ExposedList <Skin>(new[] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
                }
            }
        }
Ejemplo n.º 3
0
		static List<AtlasRegion> GetRegions (Atlas atlas) {
			FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions");
			return (List<AtlasRegion>)regionsField.GetValue(atlas);
		}
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            SerializedProperty = property;

            if (property.propertyType != SerializedPropertyType.String)
            {
                EditorGUI.LabelField(position, "ERROR:", "May only apply to type string");
                return;
            }

            SerializedProperty dataField = property.FindBaseOrSiblingProperty(TargetAttribute.dataField);

            if (dataField != null)
            {
                var objectReferenceValue = dataField.objectReferenceValue;
                if (objectReferenceValue is SkeletonDataAsset)
                {
                    skeletonDataAsset = (SkeletonDataAsset)objectReferenceValue;
                }
                else if (objectReferenceValue is IHasSkeletonDataAsset)
                {
                    var hasSkeletonDataAsset = (IHasSkeletonDataAsset)objectReferenceValue;
                    if (hasSkeletonDataAsset != null)
                    {
                        skeletonDataAsset = hasSkeletonDataAsset.SkeletonDataAsset;
                    }
                }
                else if (objectReferenceValue != null)
                {
                    EditorGUI.LabelField(position, "ERROR:", "Invalid reference type");
                    return;
                }
            }
            else if (property.serializedObject.targetObject is Component)
            {
                var component            = (Component)property.serializedObject.targetObject;
                var hasSkeletonDataAsset = component.GetComponentInChildren(typeof(IHasSkeletonDataAsset)) as IHasSkeletonDataAsset;
                if (hasSkeletonDataAsset != null)
                {
                    skeletonDataAsset = hasSkeletonDataAsset.SkeletonDataAsset;
                }
            }

            if (skeletonDataAsset == null)
            {
                if (TargetAttribute.fallbackToTextField)
                {
                    EditorGUI.PropertyField(position, property);                     //EditorGUI.TextField(position, label, property.stringValue);
                }
                else
                {
                    EditorGUI.LabelField(position, "ERROR:", "Must have reference to a SkeletonDataAsset");
                }

                skeletonDataAsset = property.serializedObject.targetObject as SkeletonDataAsset;
                if (skeletonDataAsset == null)
                {
                    return;
                }
            }

            position = EditorGUI.PrefixLabel(position, label);

            var image = Icon;
            var propertyStringValue = (property.hasMultipleDifferentValues) ? SpineInspectorUtility.EmDash : property.stringValue;

            if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : SpineInspectorUtility.TempContent(propertyStringValue, image), EditorStyles.popup))
            {
                Selector(property);
            }
        }
        public static void SetSeparatorSlotNames(SkeletonRenderer skeletonRenderer, string[] newSlotNames)
        {
            var field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);

            field.SetValue(skeletonRenderer, newSlotNames);
        }
Ejemplo n.º 6
0
        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)
                {
                    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);

            if (!TargetIsValid)
            {
                return;
            }

            // More Render Options...
            using (new SpineInspectorUtility.BoxScope()) {
                if (advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced"))
                {
                    using (new SpineInspectorUtility.IndentScope()) {
                        SeparatorsField(separatorSlotNames);
                        EditorGUILayout.Space();

                        using (new SpineInspectorUtility.LabelWidthScope()) {
                            // Optimization options
                            EditorGUILayout.PropertyField(meshes, MeshesLabel);
                            EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel);
                            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.PropertyField(pmaVertexColors, PMAVertexColorsLabel);
                            EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel);

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

                        EditorGUILayout.Space();
                    }
                }
            }
        }
        public override void OnInspectorGUI()
        {
#pragma warning disable
            bool isInspectingPrefab = (PrefabUtility.GetPrefabType(target) == PrefabType.Prefab);
#pragma warning restore
            // Try to auto-assign SkeletonRenderer field.
            if (skeletonRenderer.objectReferenceValue == null)
            {
                var foundSkeletonRenderer = follower.GetComponentInParent <SkeletonRenderer>();
                if (foundSkeletonRenderer != null)
                {
                    Debug.Log("BoundingBoxFollower automatically assigned: " + foundSkeletonRenderer.gameObject.name);
                }
                else if (Event.current.type == EventType.Repaint)
                {
                    Debug.Log("No Spine GameObject detected. Make sure to set this GameObject as a child of the Spine GameObject; or set BoundingBoxFollower's 'Skeleton Renderer' field in the inspector.");
                }

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

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

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

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

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

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

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

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

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

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


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

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

                if (rebuildRequired)
                {
                    follower.Initialize();
                    rebuildRequired = false;
                }
            }
        }
        override public void OnInspectorGUI()
        {
            // Multi-Editing
            if (serializedObject.isEditingMultipleObjects)
            {
                OnInspectorGUIMulti();
                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();

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

            // Main Serialized Fields
            using (var changeCheck = new EditorGUI.ChangeCheckScope()) {
                using (new SpineInspectorUtility.BoxScope())
                    DrawSkeletonDataFields();

                using (new SpineInspectorUtility.BoxScope()) {
                    DrawAtlasAssetsFields();
                    HandleAtlasAssetsNulls();
                }

                if (changeCheck.changed)
                {
                    if (serializedObject.ApplyModifiedProperties())
                    {
                        this.Clear();
                        this.InitializeEditor();
                        return;
                    }
                }
            }

            // Unity Quirk: Some code depends on valid preview. If preview is initialized elsewhere, this can cause contents to change between Layout and Repaint events, causing GUILayout control count errors.
            if (warnings.Count <= 0)
            {
                preview.Initialize(targetSkeletonDataAsset, this.LastSkinName);
            }

            if (targetSkeletonData != 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
                // Draw 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

                DrawWarningList();
            }

            if (!Application.isPlaying)
            {
                serializedObject.ApplyModifiedProperties();
            }
        }
        void DrawAnimationList()
        {
            showAnimationList = EditorGUILayout.Foldout(showAnimationList, SpineInspectorUtility.TempContent(string.Format("Animations [{0}]", targetSkeletonData.Animations.Count), Icons.animationRoot));
            if (!showAnimationList)
            {
                return;
            }

            bool isPreviewWindowOpen = preview.IsValid;

            if (isPreviewWindowOpen)
            {
                if (GUILayout.Button(SpineInspectorUtility.TempContent("Setup Pose", Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18)))
                {
                    preview.ClearAnimationSetupPose();
                    preview.RefreshOnNextUpdate();
                }
            }
            else
            {
                EditorGUILayout.HelpBox("Animations can be previewed if you expand the Preview window below.", MessageType.Info);
            }

            EditorGUILayout.LabelField("Name", "      Duration");
            bool  nonessential = targetSkeletonData.ImagesPath != null;            // Currently the only way to determine if skeleton data has nonessential data. (Spine 3.6)
            float fps          = targetSkeletonData.Fps;

            if (nonessential && fps == 0)
            {
                fps = 30;
            }

            var activeTrack = preview.ActiveTrack;

            foreach (Animation animation in targetSkeletonData.Animations)
            {
                using (new GUILayout.HorizontalScope()) {
                    if (isPreviewWindowOpen)
                    {
                        bool active = activeTrack != null && activeTrack.Animation == animation;
                        //bool sameAndPlaying = active && activeTrack.TimeScale > 0f;
                        if (GUILayout.Button("\u25BA", active ? activePlayButtonStyle : idlePlayButtonStyle, GUILayout.Width(24)))
                        {
                            preview.PlayPauseAnimation(animation.Name, true);
                            activeTrack = preview.ActiveTrack;
                        }
                    }
                    else
                    {
                        GUILayout.Label("-", GUILayout.Width(24));
                    }
                    string frameCountString = (fps > 0) ? ("(" + (Mathf.RoundToInt(animation.Duration * fps)) + ")").PadLeft(12, ' ') : string.Empty;
                    EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s" + frameCountString));
                }
            }
        }
        void OnGUI()
        {
            so = so ?? new SerializedObject(this);

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

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

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

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

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

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

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

            serializedObject.Update();
            atlasAsset = (atlasAsset == null) ? (SpineSpriteAtlasAsset)target : atlasAsset;

            if (atlasAsset.RegionsNeedLoading)
            {
                if (GUILayout.Button(SpineInspectorUtility.TempContent("Load regions by entering Play mode"), GUILayout.Height(20)))
                {
                    EditorApplication.isPlaying = true;
                }
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(atlasFile);
            EditorGUILayout.PropertyField(materials, true);
            if (EditorGUI.EndChangeCheck())
            {
                serializedObject.ApplyModifiedProperties();
                atlasAsset.Clear();
                atlasAsset.GetAtlas();
                atlasAsset.updateRegionsInPlayMode = true;
            }

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

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

            if (atlasFile.objectReferenceValue != null)
            {
                int baseIndent = EditorGUI.indentLevel;

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

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

            if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
            {
                atlasAsset.Clear();
            }
        }
		public override void OnInspectorGUI () {
			animationNameProperty = animationNameProperty ?? serializedObject.FindProperty("animationName");
			string animationName = animationNameProperty.stringValue;

			Animation animation = null;
			if (ThisSkeletonDataAsset != null) {
				var skeletonData = ThisSkeletonDataAsset.GetSkeletonData(true);
				if (skeletonData != null) {
					animation = skeletonData.FindAnimation(animationName);
				}
			} 
			bool animationNotFound = (animation == null);

			if (changeNextFrame) {
				changeNextFrame = false;
				
				if (ThisSkeletonDataAsset != lastSkeletonDataAsset) {
					preview.Clear();
					preview.Initialize(Repaint, ThisSkeletonDataAsset, LastSkinName);

					if (animationNotFound) {
						animationNameProperty.stringValue = "";
						preview.ClearAnimationSetupPose();
					}
				}

				preview.ClearAnimationSetupPose();

				if (!string.IsNullOrEmpty(animationNameProperty.stringValue))
					preview.PlayPauseAnimation(animationNameProperty.stringValue, true);
			}
			lastSkeletonDataAsset = ThisSkeletonDataAsset;

			//EditorGUILayout.HelpBox(AnimationReferenceAssetEditor.InspectorHelpText, MessageType.Info, true);
			EditorGUILayout.Space();
			EditorGUI.BeginChangeCheck();
			DrawDefaultInspector();
			if (EditorGUI.EndChangeCheck()) {
				changeNextFrame = true;
			}

			// Draw extra info below default inspector.
			EditorGUILayout.Space();
			if (ThisSkeletonDataAsset == null) {
				EditorGUILayout.HelpBox("SkeletonDataAsset is missing.", MessageType.Error);
			} else if (string.IsNullOrEmpty(animationName)) {
				EditorGUILayout.HelpBox("No animation selected.", MessageType.Warning);
			} else if (animationNotFound) {
				EditorGUILayout.HelpBox(string.Format("Animation named {0} was not found for this Skeleton.", animationNameProperty.stringValue), MessageType.Warning);
			} else {
				using (new SpineInspectorUtility.BoxScope()) {
					if (!string.Equals(SpineEditorUtilities.GetPathSafeName(animationName), ThisAnimationReferenceAsset.name, System.StringComparison.OrdinalIgnoreCase))
						EditorGUILayout.HelpBox("Animation name value does not match this asset's name. Inspectors using this asset may be misleading.", MessageType.None);

					EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(animationName, SpineEditorUtilities.Icons.animation));
					if (animation != null) {
						EditorGUILayout.LabelField(string.Format("Timelines: {0}", animation.Timelines.Count));
						EditorGUILayout.LabelField(string.Format("Duration: {0} sec", animation.Duration));
					}
				}
			}
		}
        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--;
                }
            }
        }
        public override void OnInspectorGUI()
        {
                        #if !NEW_PREFAB_SYSTEM
            if (isPrefab)
            {
                GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
                return;
            }
                        #endif

            serializedObject.Update();

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

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

            bool hasRootBone = skeletonUtility.boneRoot != null;

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

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

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

            serializedObject.ApplyModifiedProperties();
        }
        public override void OnInspectorGUI()
        {
            if (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;
            }

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

                        // 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;
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(mode);
            if (EditorGUI.EndChangeCheck())
            {
                containsOverrides = mode.enumValueIndex == 1;
                containsFollows   = mode.enumValueIndex == 0;
            }

            using (new EditorGUI.DisabledGroupScope(multiObject)) {
                string str = boneName.stringValue;
                if (str == "")
                {
                    str = "<None>";
                }
                if (multiObject)
                {
                    str = "<Multiple>";
                }

                using (new GUILayout.HorizontalScope()) {
                    EditorGUILayout.PrefixLabel("Bone");
                    if (GUILayout.Button(str, EditorStyles.popup))
                    {
                        BoneSelectorContextMenu(str, ((SkeletonUtilityBone)target).hierarchy.skeletonRenderer.skeleton.Bones, "<None>", TargetBoneSelected);
                    }
                }
            }

            EditorGUILayout.PropertyField(zPosition);
            EditorGUILayout.PropertyField(position);
            EditorGUILayout.PropertyField(rotation);
            EditorGUILayout.PropertyField(scale);

            using (new EditorGUI.DisabledGroupScope(containsFollows)) {
                EditorGUILayout.PropertyField(overrideAlpha);
                EditorGUILayout.PropertyField(parentReference);
            }

            EditorGUILayout.Space();

            using (new GUILayout.HorizontalScope()) {
                EditorGUILayout.Space();
                using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0)) {
                    if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Child Bone", Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24)))
                    {
                        BoneSelectorContextMenu("", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
                    }
                }
                using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides)) {
                    if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Override", Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24)))
                    {
                        SpawnOverride();
                    }
                }
                EditorGUILayout.Space();
            }
            EditorGUILayout.Space();
            using (new GUILayout.HorizontalScope()) {
                EditorGUILayout.Space();
                using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || !canCreateHingeChain)) {
                    if (GUILayout.Button(SpineInspectorUtility.TempContent("Create 3D Hinge Chain", Icons.hingeChain), GUILayout.MinWidth(120), GUILayout.Height(24)))
                    {
                        CreateHingeChain();
                    }
                    if (GUILayout.Button(SpineInspectorUtility.TempContent("Create 2D Hinge Chain", Icons.hingeChain), GUILayout.MinWidth(120), GUILayout.Height(24)))
                    {
                        CreateHingeChain2D();
                    }
                }
                EditorGUILayout.Space();
            }

            using (new EditorGUI.DisabledGroupScope(multiObject || boundingBoxTable.Count == 0)) {
                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bounding Boxes", Icons.boundingBox), EditorStyles.boldLabel);

                foreach (var entry in boundingBoxTable)
                {
                    Slot slot          = entry.Key;
                    var  boundingBoxes = entry.Value;

                    EditorGUI.indentLevel++;
                    EditorGUILayout.LabelField(slot.Data.Name);
                    EditorGUI.indentLevel++;
                    {
                        foreach (var box in boundingBoxes)
                        {
                            using (new GUILayout.HorizontalScope()) {
                                GUILayout.Space(30);
                                string buttonLabel = box.IsWeighted() ? box.Name + " (!)" : box.Name;
                                if (GUILayout.Button(buttonLabel, GUILayout.Width(200)))
                                {
                                    utilityBone.bone.Skeleton.UpdateWorldTransform();
                                    var bbTransform = utilityBone.transform.Find("[BoundingBox]" + box.Name);                                     // Use FindChild in older versions of Unity.
                                    if (bbTransform != null)
                                    {
                                        var originalCollider = bbTransform.GetComponent <PolygonCollider2D>();
                                        if (originalCollider != null)
                                        {
                                            SkeletonUtility.SetColliderPointsLocal(originalCollider, slot, box);
                                        }
                                        else
                                        {
                                            SkeletonUtility.AddBoundingBoxAsComponent(box, slot, bbTransform.gameObject);
                                        }
                                    }
                                    else
                                    {
                                        var newPolygonCollider = SkeletonUtility.AddBoundingBoxGameObject(null, box, slot, utilityBone.transform);
                                        bbTransform = newPolygonCollider.transform;
                                    }
                                    EditorGUIUtility.PingObject(bbTransform);
                                }
                            }
                        }
                    }
                    EditorGUI.indentLevel--;
                    EditorGUI.indentLevel--;
                }
            }

            BoneFollowerInspector.RecommendRigidbodyButton(utilityBone);

            serializedObject.ApplyModifiedProperties();
        }
Ejemplo n.º 17
0
        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.Space();

                    // Optimization options
                    SpineInspectorUtility.PropertyFieldWideLabel(meshes,
                                                                 new GUIContent("Render MeshAttachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments"));
                    SpineInspectorUtility.PropertyFieldWideLabel(immutableTriangles,
                                                                 new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
                    EditorGUILayout.Space();

                    // Render options
                    const float MinZSpacing = -0.1f;
                    const float MaxZSpacing = 0f;
                    EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing);
                    EditorGUILayout.Space();
                    SpineInspectorUtility.PropertyFieldWideLabel(pmaVertexColors,
                                                                 new GUIContent("PMA Vertex Colors", "Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader."));

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

                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
        }
Ejemplo n.º 18
0
        // MITCH: left todo:  Implement preview panning

        /*
         * static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
         * {
         *      int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
         *      UnityEngine.Event current = UnityEngine.Event.current;
         *      switch (current.GetTypeForControl(controlID))
         *      {
         *      case EventType.MouseDown:
         *              if (position.Contains(current.mousePosition) && (position.width > 50f))
         *              {
         *                      GUIUtility.hotControl = controlID;
         *                      current.Use();
         *                      EditorGUIUtility.SetWantsMouseJumping(1);
         *              }
         *              return scrollPosition;
         *
         *      case EventType.MouseUp:
         *              if (GUIUtility.hotControl == controlID)
         *              {
         *                      GUIUtility.hotControl = 0;
         *              }
         *              EditorGUIUtility.SetWantsMouseJumping(0);
         *              return scrollPosition;
         *
         *      case EventType.MouseMove:
         *              return scrollPosition;
         *
         *      case EventType.MouseDrag:
         *              if (GUIUtility.hotControl == controlID)
         *              {
         *                      scrollPosition -= (Vector2) (((current.delta * (!current.shift ? ((float) 1) : ((float) 3))) / Mathf.Min(position.width, position.height)) * 140f);
         *                      scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
         *                      current.Use();
         *                      GUI.changed = true;
         *              }
         *              return scrollPosition;
         *      }
         *      return scrollPosition;
         * }
         */

        public override GUIContent GetPreviewTitle()
        {
            return(SpineInspectorUtility.TempContent("Preview"));
        }
        protected override void DrawInspectorGUI(bool multi)
        {
            base.DrawInspectorGUI(multi);
            if (!TargetIsValid)
            {
                return;
            }
            bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);

            if (multi)
            {
                foreach (var o in targets)
                {
                    TrySetAnimation(o, multi);
                }

                EditorGUILayout.Space();
                if (!sameData)
                {
                    EditorGUILayout.DelayedTextField(animationName);
                }
                else
                {
                    EditorGUI.BeginChangeCheck();
                    EditorGUILayout.PropertyField(animationName);
                    wasAnimationNameChanged |= EditorGUI.EndChangeCheck();                     // Value used in the next update.
                }
                EditorGUILayout.PropertyField(loop);
                EditorGUILayout.PropertyField(timeScale);
                EditorGUILayout.PropertyField(ignoreTimeScale);
                foreach (var o in targets)
                {
                    var component = o as SkeletonAnimation;
                    component.timeScale = Mathf.Max(component.timeScale, 0);
                }
            }
            else
            {
                TrySetAnimation(target, multi);

                EditorGUILayout.Space();
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.PropertyField(animationName);
                wasAnimationNameChanged |= EditorGUI.EndChangeCheck();                 // Value used in the next update.
                EditorGUILayout.PropertyField(loop, LoopLabel);
                EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
                EditorGUILayout.PropertyField(ignoreTimeScale, IgnoreTimeScaleLabel);
                var component = (SkeletonAnimation)target;
                component.timeScale = Mathf.Max(component.timeScale, 0);
            }

            if (!isInspectingPrefab)
            {
                if (requireRepaint)
                {
                    SceneView.RepaintAll();
                    requireRepaint = false;
                }

                DrawSkeletonUtilityButton(multi);
            }
        }
Ejemplo n.º 20
0
        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();
            }
        }
Ejemplo n.º 21
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
                            EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(160f));
                            EditorGUILayout.LabelField("Flip", GUILayout.MaxWidth(EditorGUIUtility.labelWidth - 20f));
                            skeleton.FlipX = EditorGUILayout.ToggleLeft(".FlipX", skeleton.FlipX, GUILayout.MaxWidth(70f));
                            skeleton.FlipY = EditorGUILayout.ToggleLeft(".FlipY", skeleton.FlipY, GUILayout.MaxWidth(70f));
                            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);

                                        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;
                                        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);
                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 = skeletonRenderer.separatorSlotNames;
                                    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();
        }
Ejemplo n.º 22
0
 void DrawUnityTools()
 {
                 #if SPINE_SKELETON_ANIMATOR
     using (new SpineInspectorUtility.BoxScope()) {
         isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", SpineInspectorUtility.UnityIcon <SceneAsset>()));
         if (isMecanimExpanded)
         {
             EditorGUI.indentLevel++;
             EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", SpineInspectorUtility.UnityIcon <Animator>()));
             if (controller.objectReferenceValue == null)
             {
                 // Generate Mecanim Controller Button
                 using (new GUILayout.HorizontalScope()) {
                     GUILayout.Space(EditorGUIUtility.labelWidth);
                     if (GUILayout.Button(SpineInspectorUtility.TempContent("Generate Mecanim Controller"), GUILayout.Height(20)))
                     {
                         SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
                     }
                 }
                 EditorGUILayout.HelpBox("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation.\nIt is not required.", MessageType.Info);
             }
             else
             {
                 // Update AnimationClips button.
                 using (new GUILayout.HorizontalScope()) {
                     GUILayout.Space(EditorGUIUtility.labelWidth);
                     if (GUILayout.Button(SpineInspectorUtility.TempContent("Force Update AnimationClips"), GUILayout.Height(20)))
                     {
                         SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset);
                     }
                 }
             }
             EditorGUI.indentLevel--;
         }
     }
                 #endif
 }
        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();
                }
            }
        }
Ejemplo n.º 24
0
        void DrawAnimationList()
        {
            showAnimationList = EditorGUILayout.Foldout(showAnimationList, SpineInspectorUtility.TempContent(string.Format("Animations [{0}]", m_skeletonData.Animations.Count), Icons.animationRoot));
            if (!showAnimationList)
            {
                return;
            }

            if (m_skeletonAnimation != null && m_skeletonAnimation.state != null)
            {
                if (GUILayout.Button(SpineInspectorUtility.TempContent("Setup Pose", Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18)))
                {
                    StopAnimation();
                    m_skeletonAnimation.skeleton.SetToSetupPose();
                    m_requireRefresh = true;
                }
            }
            else
            {
                EditorGUILayout.HelpBox("Animations can be previewed if you expand the Preview window below.", MessageType.Info);
            }

            EditorGUILayout.LabelField("Name", "      Duration");
            bool  nonessential = m_skeletonData.ImagesPath != null;
            float fps          = m_skeletonData.Fps;

            if (nonessential && fps == 0)
            {
                fps = 30;
            }
            foreach (Spine.Animation animation in m_skeletonData.Animations)
            {
                using (new GUILayout.HorizontalScope()) {
                    if (m_skeletonAnimation != null && m_skeletonAnimation.state != null)
                    {
                        var activeTrack = m_skeletonAnimation.state.GetCurrent(0);
                        if (activeTrack != null && activeTrack.Animation == animation)
                        {
                            if (GUILayout.Button("\u25BA", activePlayButtonStyle, GUILayout.Width(24)))
                            {
                                StopAnimation();
                            }
                        }
                        else
                        {
                            if (GUILayout.Button("\u25BA", idlePlayButtonStyle, GUILayout.Width(24)))
                            {
                                PlayAnimation(animation.Name, true);
                            }
                        }
                    }
                    else
                    {
                        GUILayout.Label("-", GUILayout.Width(24));
                    }
                    string frameCountString = (fps > 0) ? ("(" + (Mathf.RoundToInt(animation.Duration * fps)) + ")").PadLeft(12, ' ') : string.Empty;
                    EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s" + frameCountString));
                }
            }
        }
        public static string[] GetSeparatorSlotNames(SkeletonRenderer skeletonRenderer)
        {
            var field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName);

            return(field.GetValue(skeletonRenderer) as string[]);
        }
Ejemplo n.º 26
0
        void DrawSlotList()
        {
            showSlotList = EditorGUILayout.Foldout(showSlotList, SpineInspectorUtility.TempContent("Slots", Icons.slotRoot));

            if (!showSlotList)
            {
                return;
            }
            if (m_skeletonAnimation == null || m_skeletonAnimation.skeleton == null)
            {
                return;
            }

            EditorGUI.indentLevel++;
            showAttachments = EditorGUILayout.ToggleLeft("Show Attachments", showAttachments);
            var  slotAttachments            = new List <Attachment>();
            var  slotAttachmentNames        = new List <string>();
            var  defaultSkinAttachmentNames = new List <string>();
            var  defaultSkin = m_skeletonData.Skins.Items[0];
            Skin skin        = m_skeletonAnimation.skeleton.Skin ?? defaultSkin;
            var  slotsItems  = m_skeletonAnimation.skeleton.Slots.Items;

            for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--)
            {
                Slot slot = slotsItems[i];
                EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot));
                if (showAttachments)
                {
                    EditorGUI.indentLevel++;
                    slotAttachments.Clear();
                    slotAttachmentNames.Clear();
                    defaultSkinAttachmentNames.Clear();

                    skin.FindNamesForSlot(i, slotAttachmentNames);
                    skin.FindAttachmentsForSlot(i, slotAttachments);

                    if (skin != defaultSkin)
                    {
                        defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
                        defaultSkin.FindNamesForSlot(i, slotAttachmentNames);
                        defaultSkin.FindAttachmentsForSlot(i, slotAttachments);
                    }
                    else
                    {
                        defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames);
                    }

                    for (int a = 0; a < slotAttachments.Count; a++)
                    {
                        Attachment attachment     = slotAttachments[a];
                        string     attachmentName = slotAttachmentNames[a];
                        Texture2D  icon           = Icons.GetAttachmentIcon(attachment);
                        bool       initialState   = slot.Attachment == attachment;
                        bool       toggled        = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachmentName, icon), slot.Attachment == attachment);

                        if (!defaultSkinAttachmentNames.Contains(attachmentName))
                        {
                            Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect();
                            skinPlaceHolderIconRect.width  = Icons.skinPlaceholder.width;
                            skinPlaceHolderIconRect.height = Icons.skinPlaceholder.height;
                            GUI.DrawTexture(skinPlaceHolderIconRect, Icons.skinPlaceholder);
                        }

                        if (toggled != initialState)
                        {
                            slot.Attachment  = toggled ? attachment : null;
                            m_requireRefresh = true;
                        }
                    }
                    EditorGUI.indentLevel--;
                }
            }
            EditorGUI.indentLevel--;
        }
Ejemplo n.º 27
0
		override public void OnInspectorGUI () {
			if (serializedObject.isEditingMultipleObjects) {
				DrawDefaultInspector();
				return;
			}

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

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

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

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

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

			EditorGUILayout.Space();

			#if REGION_BAKING_MESH
			if (atlasFile.objectReferenceValue != null) {
				Atlas atlas = asset.GetAtlas();
				FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
				List<AtlasRegion> regions = (List<AtlasRegion>)field.GetValue(atlas);
				EditorGUILayout.LabelField(new GUIContent("Region Baking", SpineEditorUtilities.Icons.unityIcon));
				EditorGUI.indentLevel++;
				AtlasPage lastPage = null;
				for (int i = 0; i < regions.Count; i++) {
					if (lastPage != regions[i].page) {
						if (lastPage != null) {
							EditorGUILayout.Separator();
							EditorGUILayout.Separator();
						}
						lastPage = regions[i].page;
						Material mat = ((Material)lastPage.rendererObject);
						if (mat != null) {
							GUILayout.BeginHorizontal();
							{
								EditorGUI.BeginDisabledGroup(true);
								EditorGUILayout.ObjectField(mat, typeof(Material), false, GUILayout.Width(250));
								EditorGUI.EndDisabledGroup();
							}
							GUILayout.EndHorizontal();

						} else {
							EditorGUILayout.LabelField(new GUIContent("Page missing material!", SpineEditorUtilities.Icons.warning));
						}
					}
					GUILayout.BeginHorizontal();
					{
						//EditorGUILayout.ToggleLeft(baked[i] ? "" : regions[i].name, baked[i]);
						bool result = baked[i] ? EditorGUILayout.ToggleLeft("", baked[i], GUILayout.Width(24)) : EditorGUILayout.ToggleLeft("    " + regions[i].name, baked[i]);
						if(baked[i]){
							EditorGUILayout.ObjectField(bakedObjects[i], typeof(GameObject), false, GUILayout.Width(250));
						}
						if (result && !baked[i]) {
							//bake
							baked[i] = true;
							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
							EditorGUIUtility.PingObject(bakedObjects[i]);
						} else if (!result && baked[i]) {
							//unbake
							bool unbakeResult = EditorUtility.DisplayDialog("Delete Baked Region", "Do you want to delete the prefab for " + regions[i].name, "Yes", "Cancel");
							switch (unbakeResult) {
							case true:
								//delete
								string atlasAssetPath = AssetDatabase.GetAssetPath(atlasAsset);
								string atlasAssetDirPath = Path.GetDirectoryName(atlasAssetPath);
								string bakedDirPath = Path.Combine(atlasAssetDirPath, atlasAsset.name);
								string bakedPrefabPath = Path.Combine(bakedDirPath, SpineEditorUtilities.GetPathSafeRegionName(regions[i]) + ".prefab").Replace("\\", "/");
								AssetDatabase.DeleteAsset(bakedPrefabPath);
								baked[i] = false;
								break;
							case false:
								//do nothing
								break;
							}
						}
					}
					GUILayout.EndHorizontal();
				}
				EditorGUI.indentLevel--;

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

				if (!allBaked && GUILayout.Button("Bake All")) {
					for (int i = 0; i < regions.Count; i++) {
						if (!baked[i]) {
							baked[i] = true;
							bakedObjects[i] = SpineEditorUtilities.BakeRegion(atlasAsset, regions[i]);
						}
					}

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

				}
				#endif
				
			}
			#else
			if (atlasFile.objectReferenceValue != null) {
				
				
				int baseIndent = EditorGUI.indentLevel;

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

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

			if (serializedObject.ApplyModifiedProperties() || SpineInspectorUtility.UndoRedoPerformed(Event.current))
				atlasAsset.Clear();
		}
Ejemplo n.º 28
0
        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();
                }
            }
        }
        public override void OnInspectorGUI()
        {
            component = (SkeletonRendererCustomMaterials)target;
            var skeletonRenderer = component.skeletonRenderer;

            // Draw the default inspector
            DrawDefaultInspector();

            if (serializedObject.isEditingMultipleObjects)
            {
                return;
            }

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

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

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

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

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

                // 3. Remove overrides
                RemoveCustomMaterials();

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

                // 5. Restore overrides
                SetCustomMaterials();

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

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

            if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component.")))
            {
                if (skeletonRenderer != null)
                {
                                        #if SPINE_OPTIONAL_MATERIALOVERRIDE
                    skeletonRenderer.CustomMaterialOverride.Clear();
                                        #endif
                    skeletonRenderer.CustomSlotMaterials.Clear();
                    RemoveCustomMaterials();
                    SetCustomMaterials();
                    skeletonRenderer.LateUpdate();
                }
            }
        }
Ejemplo n.º 30
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();

            bool wasChanged = EditorGUI.EndChangeCheck();

            if (wasChanged)
            {
                serializedObject.ApplyModifiedProperties();
            }
        }