From 1a084d48ddda6783a9ba46544b763d6ec4f4f2b6 Mon Sep 17 00:00:00 2001 From: Neil Sarkar Date: Sun, 19 Jul 2020 20:47:04 -0700 Subject: [PATCH] Include TidyBehaviour to ensure we clean up references in editor --- Runtime/Navigation/NavigationController.cs | 7 +- Runtime/Navigation/NavigationScreen.cs | 35 +++++----- Runtime/PrefabApplier.cs | 77 +++++++++++----------- Runtime/TidyBehaviour.cs | 46 +++++++++++++ Runtime/TidyBehaviour.cs.meta | 11 ++++ Runtime/Views/View.cs | 2 +- 6 files changed, 121 insertions(+), 57 deletions(-) create mode 100644 Runtime/TidyBehaviour.cs create mode 100644 Runtime/TidyBehaviour.cs.meta diff --git a/Runtime/Navigation/NavigationController.cs b/Runtime/Navigation/NavigationController.cs index 9e5ce8d..928bf77 100644 --- a/Runtime/Navigation/NavigationController.cs +++ b/Runtime/Navigation/NavigationController.cs @@ -1,5 +1,6 @@ using UnityEngine; -public class NavigationController : MonoBehaviour { - -} \ No newline at end of file +namespace VioletUI { + public class NavigationController : TidyBehaviour { + } +} diff --git a/Runtime/Navigation/NavigationScreen.cs b/Runtime/Navigation/NavigationScreen.cs index 66acd97..fa3e131 100644 --- a/Runtime/Navigation/NavigationScreen.cs +++ b/Runtime/Navigation/NavigationScreen.cs @@ -4,24 +4,27 @@ using UnityEditor; #endif -public class NavigationScreen : MonoBehaviour { -#if UNITY_EDITOR - public static bool IsSavingPrefab; +namespace VioletUI { + + public class NavigationScreen : TidyBehaviour { + #if UNITY_EDITOR + public static bool IsSavingPrefab; - public void StartEditing() { - IsSavingPrefab = false; - try { - PrefabUtility.UnpackPrefabInstance(gameObject, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction); - } catch (ArgumentException e) { - UnityEngine.Debug.LogWarning($"VioletUI: Couldn't unpack prefab for {name}. Make sure the NavigationScreen is a prefab. {e}"); + public void StartEditing() { + IsSavingPrefab = false; + try { + PrefabUtility.UnpackPrefabInstance(gameObject, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction); + } catch (ArgumentException e) { + UnityEngine.Debug.LogWarning($"VioletUI: Couldn't unpack prefab for {name}. Make sure the NavigationScreen is a prefab. {e}"); + } + gameObject.SetActive(true); } - gameObject.SetActive(true); - } - public void StopEditing() { - IsSavingPrefab = true; - PrefabUtility.SaveAsPrefabAssetAndConnect(gameObject, $"Assets/Implementation/Menus/{name}.prefab", InteractionMode.AutomatedAction); - gameObject.SetActive(false); + public void StopEditing() { + IsSavingPrefab = true; + PrefabUtility.SaveAsPrefabAssetAndConnect(gameObject, $"Assets/Implementation/Menus/{name}.prefab", InteractionMode.AutomatedAction); + gameObject.SetActive(false); + } + #endif } -#endif } \ No newline at end of file diff --git a/Runtime/PrefabApplier.cs b/Runtime/PrefabApplier.cs index 43a6214..bbe73ee 100644 --- a/Runtime/PrefabApplier.cs +++ b/Runtime/PrefabApplier.cs @@ -15,49 +15,52 @@ /// It does this by hooking into the scene save event, so when the designer saves the scene /// all the prefab overrides will be automatically applied. /// -[ExecuteAlways] -public class PrefabApplier : MonoBehaviour { - void OnDestroy() { - EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; - } - - // tried this in Awake and OnDestroy but apparently these get blown away - // when the project recompiles sooo why not here! - void Update() { - EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; - EditorSceneManager.sceneSaved += EditorSceneManager_sceneSaved; - } +namespace VioletUI { - bool isAutosaving = false; + [ExecuteAlways] + public class PrefabApplier : TidyBehaviour { + void OnDestroy() { + EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; + } - void EditorSceneManager_sceneSaved(Scene scene) { - if (Application.isPlaying) { return; } - if (isAutosaving) { - isAutosaving = false; - return; + // tried this in Awake and OnDestroy but apparently these get blown away + // when the project recompiles sooo why not here! + void Update() { + EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; + EditorSceneManager.sceneSaved += EditorSceneManager_sceneSaved; } - UpdatePrefabs(); - } - [Button, GUIColor(0.898f, 0.745f, 0.935f)] - public void UpdatePrefabs() { - bool hasChanges = false; - foreach (Transform child in transform) { - if (PrefabUtility.HasPrefabInstanceAnyOverrides(child.gameObject, false)) { - PrefabUtility.ApplyPrefabInstance(child.gameObject, InteractionMode.AutomatedAction); - hasChanges = true; + bool isAutosaving = false; + + void EditorSceneManager_sceneSaved(Scene scene) { + if (Application.isPlaying) { return; } + if (isAutosaving) { + isAutosaving = false; + return; } + UpdatePrefabs(); } - if (!hasChanges) { return; } + + [Button, GUIColor(0.898f, 0.745f, 0.935f)] + public void UpdatePrefabs() { + bool hasChanges = false; + foreach (Transform child in transform) { + if (PrefabUtility.HasPrefabInstanceAnyOverrides(child.gameObject, false)) { + PrefabUtility.ApplyPrefabInstance(child.gameObject, InteractionMode.AutomatedAction); + hasChanges = true; + } + } + if (!hasChanges) { return; } - var scene = SceneManager.GetActiveScene(); - EditorSceneManager.MarkSceneDirty(scene); - isAutosaving = true; - EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; - EditorSceneManager.SaveScene(scene); - EditorSceneManager.sceneSaved += EditorSceneManager_sceneSaved; - isAutosaving = false; + var scene = SceneManager.GetActiveScene(); + EditorSceneManager.MarkSceneDirty(scene); + isAutosaving = true; + EditorSceneManager.sceneSaved -= EditorSceneManager_sceneSaved; + EditorSceneManager.SaveScene(scene); + EditorSceneManager.sceneSaved += EditorSceneManager_sceneSaved; + isAutosaving = false; + } } -} -#endif \ No newline at end of file + #endif +} \ No newline at end of file diff --git a/Runtime/TidyBehaviour.cs b/Runtime/TidyBehaviour.cs new file mode 100644 index 0000000..68aa439 --- /dev/null +++ b/Runtime/TidyBehaviour.cs @@ -0,0 +1,46 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.Diagnostics; +using System.Reflection; + +namespace VioletUI { + + public class TidyBehaviour : MonoBehaviour { + protected virtual void OnDestroy() { + ReleaseReferences(); + } + + [Conditional("UNITY_EDITOR")] + void ReleaseReferences() { + foreach (FieldInfo field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + Type fieldType = field.FieldType; + + if (typeof(IList).IsAssignableFrom(fieldType)) { + IList list = field.GetValue(this) as IList; + list?.Clear(); + } else if (typeof(IDictionary).IsAssignableFrom(fieldType)) { + IDictionary dictionary = field.GetValue(this) as IDictionary; + dictionary?.Clear(); + } + + if (!fieldType.IsPrimitive) { + field.SetValue(this, null); + } + } + + foreach (PropertyInfo property in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { + Type fieldType = property.PropertyType; + + if (typeof(IList).IsAssignableFrom(fieldType)) { + IList list = property.GetValue(this) as IList; + list?.Clear(); + } else if (typeof(IDictionary).IsAssignableFrom(fieldType)) { + IDictionary dictionary = property.GetValue(this) as IDictionary; + dictionary?.Clear(); + } + } + } + } +} \ No newline at end of file diff --git a/Runtime/TidyBehaviour.cs.meta b/Runtime/TidyBehaviour.cs.meta new file mode 100644 index 0000000..8758320 --- /dev/null +++ b/Runtime/TidyBehaviour.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 834f13d68f5694cbd96e71c6699b24d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Views/View.cs b/Runtime/Views/View.cs index 1a97bc2..c4ad967 100644 --- a/Runtime/Views/View.cs +++ b/Runtime/Views/View.cs @@ -4,7 +4,7 @@ namespace VioletUI { [ExecuteAlways] - public abstract class View : MonoBehaviour, IView where TState : IState { + public abstract class View : TidyBehaviour, IView where TState : IState { public abstract TState State { get; } public abstract TState LastState { get; } [NonSerialized] public int Index;