diff --git a/RogueLibsCore/Hooks/HookExtensions.cs b/RogueLibsCore/Hooks/HookExtensions.cs index 57856116..e1f50fce 100644 --- a/RogueLibsCore/Hooks/HookExtensions.cs +++ b/RogueLibsCore/Hooks/HookExtensions.cs @@ -364,7 +364,7 @@ public static IEnumerable GetHooks(this StatusEffect instance) public static IEnumerable GetHooks(this Trait instance) => GetHooksShared(instance.GetHookControllerIfExists()); - public static TInterface Get(this MainGUI mainGUI) where TInterface : CustomUserInterface + public static TInterface Get(this MainGUI mainGUI) where TInterface : CustomUiBase { string uiName = typeof(TInterface).FullName; Transform? tr = mainGUI.transform.Find(uiName); diff --git a/RogueLibsCore/Hooks/UserInterfaces/CustomUiBase.cs b/RogueLibsCore/Hooks/UserInterfaces/CustomUiBase.cs new file mode 100644 index 00000000..07e4d21e --- /dev/null +++ b/RogueLibsCore/Hooks/UserInterfaces/CustomUiBase.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace RogueLibsCore +{ + public abstract class CustomUiBase : CustomUiElement, IHook + { + public MainGUI MainGUI { get; private set; } = null!; + protected Canvas canvas { get; private set; } = null!; + protected GraphicRaycaster graphicRaycaster { get; private set; } = null!; + protected CanvasGroup canvasGroup { get; private set; } = null!; + + object IHook.Instance => MainGUI; + MainGUI IHook.Instance => MainGUI; + void IHook.Initialize(object _) { } + + public override void Awake() + { + MainGUI = gameObject.GetComponentInParent(); + SetCenterPosition(gameObject, transform.parent, new Rect(960f, 540f, 1920f, 1080f)); + + canvas = gameObject.AddComponent(); + graphicRaycaster = gameObject.AddComponent(); + canvasGroup = gameObject.AddComponent(); + } + + } +} diff --git a/RogueLibsCore/Hooks/UserInterfaces/CustomUiElement.cs b/RogueLibsCore/Hooks/UserInterfaces/CustomUiElement.cs new file mode 100644 index 00000000..324411ab --- /dev/null +++ b/RogueLibsCore/Hooks/UserInterfaces/CustomUiElement.cs @@ -0,0 +1,67 @@ +using UnityEngine; + +namespace RogueLibsCore +{ + public abstract class CustomUiElement : MonoBehaviour + { + private RectTransform? _rect; + public RectTransform rect => _rect ??= GetComponent(); + + public abstract void Awake(); + + /// + /// Gets the currently used instance of . + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Usage of gc fields in SoR")] + // ReSharper disable once InconsistentNaming + public static GameController gc => GameController.gameController; + + public GameObject CreateElement(string gameObjectName, Vector2 position) + => CreateElement(transform, gameObjectName, position); + public GameObject CreateElement(string gameObjectName, Rect rectangle) + => CreateElement(transform, gameObjectName, rectangle); + public static GameObject CreateElement(Transform parent, string gameObjectName, Vector2 position) + => CreateElement(parent, gameObjectName, new Rect(position, new Vector2(100f, 100f))); + public static GameObject CreateElement(Transform parent, string gameObjectName, Rect rectangle) + { + GameObject go = new GameObject(gameObjectName, typeof(RectTransform)); + SetTopLeftCornerPosition(go, parent, rectangle); + return go; + } + + public TElement CreateElement(string gameObjectName, Vector2 position) where TElement : Component + => CreateElement(transform, gameObjectName, position); + public TElement CreateElement(string gameObjectName, Rect rectangle) where TElement : Component + => CreateElement(transform, gameObjectName, rectangle); + public static TElement CreateElement(Transform parent, string gameObjectName, Vector2 position) where TElement : Component + => CreateElement(parent, gameObjectName, new Rect(position, new Vector2(100f, 100f))); + public static TElement CreateElement(Transform parent, string gameObjectName, Rect rectangle) where TElement : Component + => CreateElement(parent, gameObjectName, rectangle).AddComponent(); + + protected static void SetTopLeftCornerPosition(GameObject go, Transform parent, Rect rectangle) + { + RectTransform rect = go.GetComponent(); + rect.SetParent(parent); + + rect.localScale = Vector3.one; + rect.anchorMin = new Vector2(0f, 1f); + rect.anchorMax = new Vector2(0f, 1f); + rect.pivot = new Vector2(0f, 1f); + rect.anchoredPosition = new Vector2(rectangle.x, -rectangle.y); + rect.sizeDelta = rectangle.size; + } + protected static void SetCenterPosition(GameObject go, Transform parent, Rect rectangle) + { + RectTransform rect = go.GetComponent(); + rect.SetParent(parent); + + rect.localScale = Vector3.one; + rect.anchorMin = new Vector2(0f, 1f); + rect.anchorMax = new Vector2(0f, 1f); + rect.pivot = new Vector2(0.5f, 0.5f); + rect.anchoredPosition = new Vector2(rectangle.x, -rectangle.y); + rect.sizeDelta = rectangle.size; + } + + } +} diff --git a/RogueLibsCore/Hooks/UserInterfaces/CustomUserInterface.cs b/RogueLibsCore/Hooks/UserInterfaces/CustomUserInterface.cs index 6130b733..0591cd2d 100644 --- a/RogueLibsCore/Hooks/UserInterfaces/CustomUserInterface.cs +++ b/RogueLibsCore/Hooks/UserInterfaces/CustomUserInterface.cs @@ -1,94 +1,90 @@ -using UnityEngine; -using UnityEngine.UI; +using System.Collections; +using UnityEngine; namespace RogueLibsCore { - public abstract class CustomUserInterface : CustomUiElement, IHook + public abstract class CustomUserInterface : CustomUiBase { - public MainGUI MainGUI { get; private set; } = null!; - protected Canvas canvas { get; private set; } = null!; - protected GraphicRaycaster graphicRaycaster { get; private set; } = null!; - public bool IsOpened => canvas.enabled; - public virtual bool LocksCamera => true; - - object IHook.Instance => MainGUI; - MainGUI IHook.Instance => MainGUI; - void IHook.Initialize(object _) { } - - /// - /// Gets the currently used instance of . - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Usage of gc fields in SoR")] - // ReSharper disable once InconsistentNaming - public static GameController gc => GameController.gameController; + public virtual Vector2? CameraLock => Vector2.zero; public sealed override void Awake() { - MainGUI = gameObject.GetComponentInParent(); - SetNormalizedPosition(gameObject, transform.parent, new Rect(0f, 0f, 1920f, 1080f)); - - canvas = gameObject.AddComponent(); + base.Awake(); canvas.enabled = false; - - graphicRaycaster = gameObject.AddComponent(); + graphicRaycaster.enabled = false; + canvasGroup.alpha = 0f; Setup(); } public abstract void Setup(); + private Coroutine? animatingCoroutine; public void ShowInterface() { if (canvas.enabled) return; - gc.audioHandler.Play(MainGUI.agent, "ShowInterface"); - canvas.enabled = true; + + if (animatingCoroutine is not null) + StopCoroutine(animatingCoroutine); + animatingCoroutine = StartCoroutine(WrapShowAnimation()); + OnOpened(); } public void HideInterface() { if (!canvas.enabled) return; - gc.audioHandler.Play(MainGUI.agent, "HideInterface"); - canvas.enabled = false; + + if (animatingCoroutine is not null) + StopCoroutine(animatingCoroutine); + animatingCoroutine = StartCoroutine(WrapHideAnimation()); + OnClosed(); } public abstract void OnOpened(); - public virtual void OnClosed() { } - - } - public abstract class CustomUiElement : MonoBehaviour - { - private RectTransform? _rect; - public RectTransform rect => _rect ??= GetComponent(); - - public abstract void Awake(); + public abstract void OnClosed(); - public static TElement Create(Transform parent, string gameObjectName, Rect rectangle) where TElement : Component + private IEnumerator WrapShowAnimation() { - GameObject go = new GameObject(gameObjectName, typeof(RectTransform)); - RectTransform rect = SetNormalizedPosition(go, parent, rectangle); - return go.AddComponent(); + canvas.enabled = true; + graphicRaycaster.enabled = false; + yield return ShowAnimation(); + animatingCoroutine = null; + graphicRaycaster.enabled = true; } - public static TImage Create(Transform parent, string gameObjectName, Vector2 position, byte[] spriteData, float scale = 1f) where TImage : Image + private IEnumerator WrapHideAnimation() { - Sprite sprite = RogueUtilities.ConvertToSprite(spriteData); - TImage img = Create(parent, gameObjectName, new Rect(position, sprite.rect.size * scale)); - img.sprite = sprite; - return img; + canvas.enabled = true; + graphicRaycaster.enabled = false; + yield return HideAnimation(); + animatingCoroutine = null; + canvas.enabled = false; } - protected static RectTransform SetNormalizedPosition(GameObject go, Transform parent, Rect rectangle) + protected virtual IEnumerator ShowAnimation() { - RectTransform rect = go.GetComponent(); - rect.SetParent(parent); + gc.audioHandler.Play(MainGUI.agent, "ShowInterface"); - rect.localScale = Vector3.one; - rect.anchorMin = new Vector2(0f, 1f); - rect.anchorMax = new Vector2(0f, 1f); - rect.pivot = new Vector2(0f, 1f); - rect.anchoredPosition = new Vector2(rectangle.x, -rectangle.y); - rect.sizeDelta = rectangle.size; + float x = canvasGroup.alpha; + while (x < 1f) + { + x = Mathf.Clamp01(x + 5f * Time.deltaTime); + canvasGroup.alpha = x; + rect.localScale = new Vector3(x, x, x); + yield return null; + } + } + protected virtual IEnumerator HideAnimation() + { + gc.audioHandler.Play(MainGUI.agent, "HideInterface"); - return rect; + float x = canvasGroup.alpha; + while (x > 0f) + { + x = Mathf.Clamp01(x - 5f * Time.deltaTime); + canvasGroup.alpha = x; + rect.localScale = new Vector3(x, x, x); + yield return null; + } } } diff --git a/RogueLibsCore/Hooks/UserInterfaces/CustomUserOverlay.cs b/RogueLibsCore/Hooks/UserInterfaces/CustomUserOverlay.cs new file mode 100644 index 00000000..60f17df9 --- /dev/null +++ b/RogueLibsCore/Hooks/UserInterfaces/CustomUserOverlay.cs @@ -0,0 +1,16 @@ +namespace RogueLibsCore +{ + public abstract class CustomUserOverlay : CustomUiBase + { + public sealed override void Awake() + { + base.Awake(); + canvas.enabled = true; + graphicRaycaster.enabled = true; + canvasGroup.alpha = 1f; + Setup(); + } + public abstract void Setup(); + + } +} diff --git a/RogueLibsCore/Patches/Patches_MainGUI.cs b/RogueLibsCore/Patches/Patches_MainGUI.cs index 9abcab15..e2bf6508 100644 --- a/RogueLibsCore/Patches/Patches_MainGUI.cs +++ b/RogueLibsCore/Patches/Patches_MainGUI.cs @@ -78,7 +78,8 @@ private static void HideInterfaces(MainGUI mainGUI) IHookController? controller = mainGUI.GetHookControllerIfExists(); if (controller is null) return; foreach (IHook hook in controller.GetHooks()) - (hook as CustomUserInterface)?.HideInterface(); + if (hook is CustomUserInterface ui) + ui.HideInterface(); } private static readonly FieldInfo openedInventoryField = AccessTools.Field(typeof(MainGUI), nameof(MainGUI.openedInventory)); @@ -112,7 +113,7 @@ private static bool GetIsCameraLocked(MainGUI mainGUI) if (mainGUI.openedInventory) return true; IHookController? controller = mainGUI.GetHookControllerIfExists(); if (controller is null) return false; - return controller.GetHooks().Any(static h => h is CustomUserInterface ui && ui.IsOpened && ui.LocksCamera); + return controller.GetHooks().Any(static h => h is CustomUserInterface ui && ui.IsOpened && ui.CameraLock is not null); } }