diff --git a/Assets/Prefabs/Menus/OptionsMenu.prefab b/Assets/Prefabs/Menus/OptionsMenu.prefab index d65f968..276ebf3 100644 Binary files a/Assets/Prefabs/Menus/OptionsMenu.prefab and b/Assets/Prefabs/Menus/OptionsMenu.prefab differ diff --git a/Assets/Scripts/MenuSystem/Menu.cs b/Assets/Scripts/MenuSystem/Menu.cs index 5a5272c..bc8fb1a 100644 --- a/Assets/Scripts/MenuSystem/Menu.cs +++ b/Assets/Scripts/MenuSystem/Menu.cs @@ -1,27 +1,27 @@ -using UnityEngine; +using UnityEngine; public abstract class Menu : Menu where T : Menu { - public static T Instance { get; private set; } + public static T Instance { get; private set; } - protected virtual void Awake() - { - Instance = (T)this; - } + protected virtual void Awake() + { + Instance = (T)this; + } - protected virtual void OnDestroy() - { - Instance = null; + protected virtual void OnDestroy() + { + Instance = null; } - protected static void Open() + protected static void Open() { if (Instance == null) - MenuManager.Instance.CreateInstance(); + MenuManager.Instance.CreateInstance(); else - Instance.gameObject.SetActive(true); + Instance.gameObject.SetActive(true); - MenuManager.Instance.OpenMenu(Instance); + MenuManager.Instance.OpenMenu(Instance, Instance.animInTime); } protected static void Close() @@ -32,7 +32,7 @@ protected static void Close() return; } - MenuManager.Instance.CloseMenu(Instance); + MenuManager.Instance.CloseMenu(Instance, Instance.animOutTime); } public override void OnBackPressed() @@ -47,7 +47,13 @@ public abstract class Menu : MonoBehaviour public bool DestroyWhenClosed = true; [Tooltip("Disable menus that are under this one in the stack")] - public bool DisableMenusUnderneath = true; + public bool DisableMenusUnderneath = true; + + [Tooltip("Time to animate this menu in")] + public float animInTime = 0f; + + [Tooltip("Time to animate this menu out")] + public float animOutTime = 0f; public abstract void OnBackPressed(); -} +} diff --git a/Assets/Scripts/MenuSystem/MenuManager.cs b/Assets/Scripts/MenuSystem/MenuManager.cs index fa54685..3e149fd 100644 --- a/Assets/Scripts/MenuSystem/MenuManager.cs +++ b/Assets/Scripts/MenuSystem/MenuManager.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections; +using System.Collections.Generic; using System.Reflection; using UnityEngine; @@ -18,7 +20,7 @@ private void Awake() { Instance = this; - MainMenu.Show(); + MainMenu.Show(); } private void OnDestroy() @@ -33,28 +35,36 @@ public void CreateInstance() where T : Menu Instantiate(prefab, transform); } - public void OpenMenu(Menu instance) + public void OpenMenu(Menu instance, float animInTime) { - // De-activate top menu if (menuStack.Count > 0) { - if (instance.DisableMenusUnderneath) - { - foreach (var menu in menuStack) - { - menu.gameObject.SetActive(false); - - if (menu.DisableMenusUnderneath) - break; - } - } - var topCanvas = instance.GetComponent(); var previousCanvas = menuStack.Peek().GetComponent(); - topCanvas.sortingOrder = previousCanvas.sortingOrder + 1; + topCanvas.sortingOrder = previousCanvas.sortingOrder + 1; } - menuStack.Push(instance); + StartCoroutine(DeactivateMenusUnder(instance, animInTime)); + } + + private IEnumerator DeactivateMenusUnder(Menu instance, float waitTime) + { + yield return new WaitForSeconds(waitTime); + + //De-activate previous top menu + if (instance.DisableMenusUnderneath) + { + foreach (var menu in menuStack) + { + if (menu == instance) + continue; + + menu.gameObject.SetActive(false); + + if (menu.DisableMenusUnderneath) + break; + } + } } private T GetPrefab() where T : Menu @@ -74,41 +84,50 @@ private T GetPrefab() where T : Menu throw new MissingReferenceException("Prefab not found for type " + typeof(T)); } - public void CloseMenu(Menu menu) - { - if (menuStack.Count == 0) - { - Debug.LogErrorFormat(menu, "{0} cannot be closed because menu stack is empty", menu.GetType()); - return; - } - - if (menuStack.Peek() != menu) - { - Debug.LogErrorFormat(menu, "{0} cannot be closed because it is not on top of stack", menu.GetType()); - return; - } - - CloseTopMenu(); - } + public void CloseMenu(Menu topMenu, float animOutTime) + { + if (menuStack.Count == 0) + { + Debug.LogErrorFormat(topMenu, "{0} cannot be closed because menu stack is empty", topMenu.GetType()); + return; + } + + if (menuStack.Peek() != topMenu) + { + Debug.LogErrorFormat(topMenu, "{0} cannot be closed because it is not on top of stack", topMenu.GetType()); + return; + } + + menuStack.Pop(); + + StartCoroutine(CloseTopMenu(topMenu, animOutTime)); - public void CloseTopMenu() + ReactivateOldMenu(); + } + + private IEnumerator CloseTopMenu(Menu instance, float waitTime) { - var instance = menuStack.Pop(); + yield return new WaitForSeconds(waitTime); - if (instance.DestroyWhenClosed) - Destroy(instance.gameObject); - else - instance.gameObject.SetActive(false); + if (instance == null) + yield break; + + if (instance.DestroyWhenClosed) + Destroy(instance.gameObject); + else + instance.gameObject.SetActive(false); + } - // Re-activate top menu - // If a re-activated menu is an overlay we need to activate the menu under it - foreach (var menu in menuStack) - { + private void ReactivateOldMenu() + { + // If a re-activated menu is an overlay we need to activate the menu under it + foreach (var menu in menuStack) + { menu.gameObject.SetActive(true); - if (menu.DisableMenusUnderneath) - break; - } + if (menu.DisableMenusUnderneath) + break; + } } private void Update() diff --git a/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs b/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs new file mode 100644 index 0000000..49c2841 --- /dev/null +++ b/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs @@ -0,0 +1,82 @@ +using UnityEngine; + +public abstract class SimpleMenuScaleInOut : Menu where T : SimpleMenuScaleInOut +{ + readonly Vector3 START_SCALE = Vector3.one * .25f; + + private bool animatingIn = false; + private float currentAnimInTime = 0; + private bool animatingOut = false; + private float currentAnimOutTime = 0; + + // Prefab should have one child to scale + private Transform visualRoot; + + protected override void Awake() + { + base.Awake(); + + visualRoot = transform.GetChild(0); + visualRoot.localScale = START_SCALE; + } + + public static void Show() + { + Open(); + + if (Instance.animInTime > 0) + { + Instance.animatingIn = true; + Instance.currentAnimInTime = 0; + } + } + + public static void Hide() + { + Close(); + + if (Instance.animOutTime > 0) + { + Instance.animatingOut = true; + Instance.currentAnimOutTime = 0; + } + } + + public override void OnBackPressed() + { + Close(); + + if (Instance.animOutTime > 0) + { + Instance.animatingOut = true; + Instance.currentAnimOutTime = 0; + } + } + + private void Update() + { + if (animatingIn) + { + ScaleVisuals(ref Instance.animatingIn, ref currentAnimInTime, animInTime, START_SCALE, Vector3.one); + } + + if (animatingOut) + { + ScaleVisuals(ref Instance.animatingOut, ref currentAnimOutTime, animOutTime, Vector3.one, START_SCALE); + } + } + + private void ScaleVisuals(ref bool isAnimating, ref float curAnimTime, float totalAnimTime, Vector3 startScale, Vector3 endScale) + { + curAnimTime += Time.deltaTime; + if (curAnimTime >= totalAnimTime) + { + curAnimTime = totalAnimTime; + isAnimating = false; + } + + float percent = curAnimTime / totalAnimTime; + + visualRoot.localScale = Vector3.Lerp(startScale, endScale, percent); + } +} diff --git a/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs.meta b/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs.meta new file mode 100644 index 0000000..0e90d59 --- /dev/null +++ b/Assets/Scripts/MenuSystem/SimpleMenuScaleInOut.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2320601fd68b30244b9c8dea62ad7aab +timeCreated: 1504133741 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Menus/OptionsMenu.cs b/Assets/Scripts/Menus/OptionsMenu.cs index 9182e45..bab3249 100644 --- a/Assets/Scripts/Menus/OptionsMenu.cs +++ b/Assets/Scripts/Menus/OptionsMenu.cs @@ -1,6 +1,6 @@ using UnityEngine.UI; -public class OptionsMenu : SimpleMenu +public class OptionsMenu : SimpleMenuScaleInOut { public Slider Slider;