diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index 41474c240..af9583d10 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -711,21 +711,26 @@ namespace Spine.Unity.Editor { try { obj = Json.Deserialize(new StringReader(asset.text)); } catch (System.Exception) { + } + if (obj == null) { Debug.LogError("Is not valid JSON"); return false; } - Dictionary root = (Dictionary)obj; + var root = obj as Dictionary; + if (root == null) { + Debug.LogError("Parser returned an incorrect type."); + return false; + } if (!root.ContainsKey("skeleton")) return false; - Dictionary skeletonInfo = (Dictionary)root["skeleton"]; - - string spineVersion = (string)skeletonInfo["spine"]; - //TODO: reject old versions +// var skeletonInfo = (Dictionary)root["skeleton"]; +// string spineVersion = (string)skeletonInfo["spine"]; + // TODO: Warn users of old version incompatibility. return true; } diff --git a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs index fbf2a5945..759490c66 100644 --- a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs @@ -2,52 +2,134 @@ * SkeletonRendererCustomMaterialsInspector created by Lost Polygon * Full irrevocable rights and permissions granted to Esoteric Software *****************************************************************************/ -using UnityEngine; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using UnityEditor; +using UnityEngine; using Spine.Unity.Modules; namespace Spine.Unity.Editor { + + // This script is not intended for use with code. See the readme.txt file in SkeletonRendererCustomMaterials folder to learn more. [CustomEditor(typeof(SkeletonRendererCustomMaterials))] public class SkeletonRendererCustomMaterialsInspector : UnityEditor.Editor { + List componentCustomMaterialOverrides, _customMaterialOverridesPrev; + List componentCustomSlotMaterials, _customSlotMaterialsPrev; + SkeletonRendererCustomMaterials component; + + const BindingFlags PrivateInstance = BindingFlags.Instance | BindingFlags.NonPublic; + MethodInfo RemoveCustomMaterialOverrides, RemoveCustomSlotMaterials, SetCustomMaterialOverrides, SetCustomSlotMaterials; #region SkeletonRenderer context menu - [MenuItem ("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials")] + [MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials")] static void AddSkeletonRendererCustomMaterials (MenuCommand menuCommand) { var skeletonRenderer = (SkeletonRenderer)menuCommand.context; var newComponent = skeletonRenderer.gameObject.AddComponent(); Undo.RegisterCreatedObjectUndo(newComponent, "Add Basic Serialized Custom Materials"); } - [MenuItem ("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials", true)] + [MenuItem("CONTEXT/SkeletonRenderer/Add Basic Serialized Custom Materials", true)] static bool AddSkeletonRendererCustomMaterials_Validate (MenuCommand menuCommand) { var skeletonRenderer = (SkeletonRenderer)menuCommand.context; return (skeletonRenderer.GetComponent() == null); } #endregion - public override void OnInspectorGUI() { - var component = (SkeletonRendererCustomMaterials)target; + void OnEnable () { + Type cm = typeof(SkeletonRendererCustomMaterials); + RemoveCustomMaterialOverrides = cm.GetMethod("RemoveCustomMaterialOverrides", PrivateInstance); + RemoveCustomSlotMaterials = cm.GetMethod("RemoveCustomSlotMaterials", PrivateInstance); + SetCustomMaterialOverrides = cm.GetMethod("SetCustomMaterialOverrides", PrivateInstance); + SetCustomSlotMaterials = cm.GetMethod("SetCustomSlotMaterials", PrivateInstance); + } + + public override void OnInspectorGUI () { + component = (SkeletonRendererCustomMaterials)target; var skeletonRenderer = component.skeletonRenderer; - // Draw the default inspector and reapply overrides on any change - EditorGUI.BeginChangeCheck(); - { - DrawDefaultInspector(); + // 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; + componentCustomSlotMaterials = cm.GetField("customSlotMaterials", PrivateInstance).GetValue(component) as List; + if (componentCustomMaterialOverrides == null) { + Debug.Log("Reflection failed."); + return; + } } - if (EditorGUI.EndChangeCheck()) { - component.ReapplyOverrides(); + + // 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 (GUILayout.Button(new GUIContent("Clear and Reapply Changes", "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) { if (skeletonRenderer != null) { skeletonRenderer.CustomMaterialOverride.Clear(); skeletonRenderer.CustomSlotMaterials.Clear(); - component.ReapplyOverrides(); + RemoveCustomMaterials(); + SetCustomMaterials(); skeletonRenderer.LateUpdate(); } } } + + void RemoveCustomMaterials () { + RemoveCustomMaterialOverrides.Invoke(component, null); + RemoveCustomSlotMaterials.Invoke(component, null); + } + + void SetCustomMaterials () { + SetCustomMaterialOverrides.Invoke(component, null); + SetCustomSlotMaterials.Invoke(component, null); + } + + static List CopyList (List list) { + return list.GetRange(0, list.Count); + } } } \ No newline at end of file diff --git a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/SkeletonRendererCustomMaterials.cs b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/SkeletonRendererCustomMaterials.cs index a7bfe507d..3bac55b10 100644 --- a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/SkeletonRendererCustomMaterials.cs +++ b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/SkeletonRendererCustomMaterials.cs @@ -13,12 +13,8 @@ namespace Spine.Unity.Modules { #region Inspector public SkeletonRenderer skeletonRenderer; - - [SerializeField] - private List customSlotMaterials = new List(); - - [SerializeField] - private List customMaterialOverrides = new List(); + [SerializeField] List customSlotMaterials = new List(); + [SerializeField] List customMaterialOverrides = new List(); #if UNITY_EDITOR void Reset () { @@ -45,22 +41,12 @@ namespace Spine.Unity.Modules { #endif #endregion - public List CustomSlotMaterials { get { return customSlotMaterials; } } - public List CustomMaterialOverrides { get { return customMaterialOverrides; } } - - public void ReapplyOverrides () { + void SetCustomSlotMaterials () { if (skeletonRenderer == null) { Debug.LogError("skeletonRenderer == null"); return; } - RemoveCustomMaterialOverrides(); - RemoveCustomSlotMaterials(); - SetCustomMaterialOverrides(); - SetCustomSlotMaterials(); - } - - void SetCustomSlotMaterials () { for (int i = 0; i < customSlotMaterials.Count; i++) { SlotMaterialOverride slotMaterialOverride = customSlotMaterials[i]; if (slotMaterialOverride.overrideDisabled || string.IsNullOrEmpty(slotMaterialOverride.slotName)) @@ -72,6 +58,11 @@ namespace Spine.Unity.Modules { } void RemoveCustomSlotMaterials () { + if (skeletonRenderer == null) { + Debug.LogError("skeletonRenderer == null"); + return; + } + for (int i = 0; i < customSlotMaterials.Count; i++) { SlotMaterialOverride slotMaterialOverride = customSlotMaterials[i]; if (string.IsNullOrEmpty(slotMaterialOverride.slotName)) @@ -92,6 +83,11 @@ namespace Spine.Unity.Modules { } void SetCustomMaterialOverrides () { + if (skeletonRenderer == null) { + Debug.LogError("skeletonRenderer == null"); + return; + } + for (int i = 0; i < customMaterialOverrides.Count; i++) { AtlasMaterialOverride atlasMaterialOverride = customMaterialOverrides[i]; if (atlasMaterialOverride.overrideDisabled) @@ -102,6 +98,11 @@ namespace Spine.Unity.Modules { } void RemoveCustomMaterialOverrides () { + if (skeletonRenderer == null) { + Debug.LogError("skeletonRenderer == null"); + return; + } + for (int i = 0; i < customMaterialOverrides.Count; i++) { AtlasMaterialOverride atlasMaterialOverride = customMaterialOverrides[i]; Material currentMaterial; @@ -116,7 +117,7 @@ namespace Spine.Unity.Modules { } } - // OnEnable applies the overrides at runtime and when the editor loads. + // OnEnable applies the overrides at runtime, and when the editor loads. void OnEnable () { if (skeletonRenderer == null) skeletonRenderer = GetComponent(); @@ -126,13 +127,12 @@ namespace Spine.Unity.Modules { return; } - skeletonRenderer.Initialize(false); + skeletonRenderer.Initialize(false); SetCustomMaterialOverrides(); SetCustomSlotMaterials(); } - - // OnDisable removes the overrides at runtime and in the editor when the component is disabled or destroyed. + // OnDisable removes the overrides at runtime, and in the editor when the component is disabled or destroyed. void OnDisable () { if (skeletonRenderer == null) { Debug.LogError("skeletonRenderer == null"); @@ -144,21 +144,27 @@ namespace Spine.Unity.Modules { } [Serializable] - public class MaterialOverride { + public struct SlotMaterialOverride : IEquatable { public bool overrideDisabled; - } - [Serializable] - public class SlotMaterialOverride : MaterialOverride { [SpineSlot] public string slotName; public Material material; + + public bool Equals (SlotMaterialOverride other) { + return overrideDisabled == other.overrideDisabled && slotName == other.slotName && material == other.material; + } } [Serializable] - public class AtlasMaterialOverride : MaterialOverride { + public struct AtlasMaterialOverride : IEquatable { + public bool overrideDisabled; public Material originalMaterial; public Material replacementMaterial; + + public bool Equals (AtlasMaterialOverride other) { + return overrideDisabled == other.overrideDisabled && originalMaterial == other.originalMaterial && replacementMaterial == other.replacementMaterial; + } } } } \ No newline at end of file