diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs index ddd1ff89d..fb597cb59 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAttributeDrawers.cs @@ -152,9 +152,24 @@ namespace Spine.Unity.Editor { Texture2D image = Icon; GUIStyle usedStyle = IsValueValid(property) ? EditorStyles.popup : ErrorPopupStyle; string propertyStringValue = (property.hasMultipleDifferentValues) ? SpineInspectorUtility.EmDash : property.stringValue; - if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : - SpineInspectorUtility.TempContent(propertyStringValue, image), usedStyle)) - Selector(property); + + if (!TargetAttribute.avoidGenericMenu) { + if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : + SpineInspectorUtility.TempContent(propertyStringValue, image), usedStyle)) + Selector(property); + } else { + SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false); + List contentList = new List(); + List valueList = new List(); + PopulatePopupList(ref contentList, ref valueList, image, property, TargetAttribute, skeletonData); + int currentIndex = valueList.IndexOf(propertyStringValue); + int previousIndex = currentIndex; + currentIndex = EditorGUI.Popup(position, currentIndex, contentList.ToArray()); + if (previousIndex != currentIndex) { + property.stringValue = valueList[currentIndex]; + property.serializedObject.ApplyModifiedProperties(); + } + } } public ISkeletonComponent GetTargetSkeletonComponent (SerializedProperty property) { @@ -192,6 +207,12 @@ namespace Spine.Unity.Editor { serializedProperty.serializedObject.ApplyModifiedProperties(); } + protected virtual void PopulatePopupList (ref List contentList, ref List valueList, + Texture2D image, SerializedProperty property, T targetAttribute, SkeletonData data) { + contentList.Add(new GUIContent ("Type Not Supported")); + valueList.Add(string.Empty); + } + public override float GetPropertyHeight (SerializedProperty property, GUIContent label) { return 18; } @@ -302,6 +323,25 @@ namespace Spine.Unity.Editor { } } + protected override void PopulatePopupList (ref List contentList, ref List valueList, + Texture2D image, SerializedProperty property, SpineSkin targetAttribute, SkeletonData data) { + + if (targetAttribute.includeNone) { + contentList.Add(new GUIContent(NoneStringConstant, image)); + valueList.Add(string.Empty); + } + + for (int i = 0; i < data.Skins.Count; i++) { + string name = data.Skins.Items[i].Name; + if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal)) { + bool isDefault = string.Equals(name, DefaultSkinName, StringComparison.Ordinal); + string choiceValue = TargetAttribute.defaultAsEmptyString && isDefault ? string.Empty : name; + contentList.Add(new GUIContent(name, image)); + valueList.Add(choiceValue); + } + } + } + } [CustomPropertyDrawer(typeof(SpineAnimation))] @@ -348,6 +388,24 @@ namespace Spine.Unity.Editor { } } + protected override void PopulatePopupList (ref List contentList, ref List valueList, + Texture2D image, SerializedProperty property, SpineAnimation targetAttribute, SkeletonData data) { + + ExposedList animations = data.Animations; + if (targetAttribute.includeNone) { + contentList.Add(new GUIContent(NoneString, image)); + valueList.Add(string.Empty); + } + + for (int i = 0; i < animations.Count; i++) { + string name = animations.Items[i].Name; + if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal)) { + contentList.Add(new GUIContent(name, image)); + valueList.Add(name); + } + } + } + } [CustomPropertyDrawer(typeof(SpineEvent))] diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/SpineAttributes.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/SpineAttributes.cs index 1ad9e0160..86170b5e5 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/SpineAttributes.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/SpineAttributes.cs @@ -33,12 +33,13 @@ using UnityEngine; namespace Spine.Unity { - [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = true, AllowMultiple = false)] public abstract class SpineAttributeBase : PropertyAttribute { public string dataField = ""; public string startsWith = ""; public bool includeNone = true; public bool fallbackToTextField = false; + public bool avoidGenericMenu = false; } public class SpineBone : SpineAttributeBase { @@ -103,11 +104,14 @@ namespace Spine.Unity { /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives) /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback. /// - public SpineAnimation (string startsWith = "", string dataField = "", bool includeNone = true, bool fallbackToTextField = false) { + public SpineAnimation (string startsWith = "", string dataField = "", + bool includeNone = true, bool fallbackToTextField = false, bool avoidGenericMenu = false) { + this.startsWith = startsWith; this.dataField = dataField; this.includeNone = includeNone; this.fallbackToTextField = fallbackToTextField; + this.avoidGenericMenu = avoidGenericMenu; } } @@ -205,12 +209,15 @@ namespace Spine.Unity { public bool defaultAsEmptyString = false; - public SpineSkin (string startsWith = "", string dataField = "", bool includeNone = false, bool fallbackToTextField = false, bool defaultAsEmptyString = false) { + public SpineSkin (string startsWith = "", string dataField = "", bool includeNone = false, + bool fallbackToTextField = false, bool defaultAsEmptyString = false, bool avoidGenericMenu = false) { + this.startsWith = startsWith; this.dataField = dataField; this.includeNone = includeNone; this.fallbackToTextField = fallbackToTextField; this.defaultAsEmptyString = defaultAsEmptyString; + this.avoidGenericMenu = avoidGenericMenu; } } diff --git a/spine-unity/Assets/Spine/package.json b/spine-unity/Assets/Spine/package.json index edc054335..36b034007 100644 --- a/spine-unity/Assets/Spine/package.json +++ b/spine-unity/Assets/Spine/package.json @@ -2,7 +2,7 @@ "name": "com.esotericsoftware.spine.spine-unity", "displayName": "spine-unity Runtime", "description": "This plugin provides the spine-unity runtime core.", - "version": "4.2.74", + "version": "4.2.75", "unity": "2018.3", "author": { "name": "Esoteric Software", diff --git a/spine-unity/Modules/com.esotericsoftware.spine.ui-toolkit/package.json b/spine-unity/Modules/com.esotericsoftware.spine.ui-toolkit/package.json index b1a46f600..c1e6f761b 100644 --- a/spine-unity/Modules/com.esotericsoftware.spine.ui-toolkit/package.json +++ b/spine-unity/Modules/com.esotericsoftware.spine.ui-toolkit/package.json @@ -1,7 +1,7 @@ { "name": "com.esotericsoftware.spine.ui-toolkit", "displayName": "Spine UI Toolkit [Experimental]", - "description": "This plugin provides UI Toolkit integration for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.2.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", + "description": "This plugin provides UI Toolkit integration for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.2.75 or newer.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)", "version": "4.2.0-preview.1", "unity": "2023.2", "author": { @@ -11,7 +11,7 @@ }, "dependencies": { "com.unity.modules.uielements": "1.0.0", - "com.esotericsoftware.spine.spine-unity": "4.2.21" + "com.esotericsoftware.spine.spine-unity": "4.2.75" }, "keywords": [ "spine",