402 lines
16 KiB
C#
402 lines
16 KiB
C#
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.Events;
|
||
|
|
using UnityEngine.EventSystems;
|
||
|
|
|
||
|
|
namespace Michsky.UI.Reach
|
||
|
|
{
|
||
|
|
public class PanelManager : MonoBehaviour
|
||
|
|
{
|
||
|
|
// Content
|
||
|
|
public List<PanelItem> panels = new List<PanelItem>();
|
||
|
|
|
||
|
|
// Settings
|
||
|
|
public int currentPanelIndex = 0;
|
||
|
|
private int currentButtonIndex = 0;
|
||
|
|
private int newPanelIndex;
|
||
|
|
public bool cullPanels = true;
|
||
|
|
[SerializeField] private bool initializeButtons = true;
|
||
|
|
[SerializeField] private bool useCooldownForHotkeys = false;
|
||
|
|
[SerializeField] private bool bypassAnimationOnEnable = false;
|
||
|
|
[SerializeField] private UpdateMode updateMode = UpdateMode.UnscaledTime;
|
||
|
|
[SerializeField] private PanelMode panelMode = PanelMode.SubPanel;
|
||
|
|
[Range(0.75f, 2)] public float animationSpeed = 1;
|
||
|
|
|
||
|
|
// Events
|
||
|
|
[System.Serializable] public class PanelChangeCallback : UnityEvent<int> { }
|
||
|
|
public PanelChangeCallback onPanelChanged;
|
||
|
|
|
||
|
|
// Helpers
|
||
|
|
Animator currentPanel;
|
||
|
|
Animator nextPanel;
|
||
|
|
|
||
|
|
PanelButton currentButton;
|
||
|
|
PanelButton nextButton;
|
||
|
|
|
||
|
|
const string panelFadeIn = "Panel In";
|
||
|
|
const string panelFadeOut = "Panel Out";
|
||
|
|
const string animSpeedKey = "AnimSpeed";
|
||
|
|
|
||
|
|
bool isInitialized = false;
|
||
|
|
public float cachedStateLength = 1;
|
||
|
|
[HideInInspector] public int managerIndex;
|
||
|
|
|
||
|
|
public enum PanelMode { MainPanel, SubPanel }
|
||
|
|
public enum UpdateMode { DeltaTime, UnscaledTime }
|
||
|
|
|
||
|
|
[System.Serializable]
|
||
|
|
public class PanelItem
|
||
|
|
{
|
||
|
|
[Tooltip("[Required] This is the variable that you use to call specific panels.")]
|
||
|
|
public string panelName = "My Panel";
|
||
|
|
[Tooltip("[Required] Main panel object.")]
|
||
|
|
public Animator panelObject;
|
||
|
|
[Tooltip("[Optional] If you want the panel manager to have tabbing capability, you can assign a panel button here.")]
|
||
|
|
public PanelButton panelButton;
|
||
|
|
[Tooltip("[Optional] Alternate panel button variable that supports standard buttons instead of panel buttons.")]
|
||
|
|
public ButtonManager altPanelButton;
|
||
|
|
[Tooltip("[Optional] This is the object that will be selected as the current UI object on panel activation. Useful for gamepad navigation.")]
|
||
|
|
public GameObject firstSelected;
|
||
|
|
[Tooltip("[Optional] Enables or disables child hotkeys depending on the panel state to avoid conflict between hotkeys.")]
|
||
|
|
public Transform hotkeyParent;
|
||
|
|
[HideInInspector] public GameObject latestSelected;
|
||
|
|
[HideInInspector] public HotkeyEvent[] hotkeys;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Awake()
|
||
|
|
{
|
||
|
|
if (panels.Count == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (panelMode == PanelMode.MainPanel) { cachedStateLength = ReachUIInternalTools.GetAnimatorClipLength(panels[currentPanelIndex].panelObject, "MainPanel_In"); }
|
||
|
|
else if (panelMode == PanelMode.SubPanel) { cachedStateLength = ReachUIInternalTools.GetAnimatorClipLength(panels[currentPanelIndex].panelObject, "SubPanel_In"); }
|
||
|
|
|
||
|
|
if (ControllerManager.instance != null)
|
||
|
|
{
|
||
|
|
managerIndex = ControllerManager.instance.panels.Count;
|
||
|
|
ControllerManager.instance.panels.Add(this);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void OnEnable()
|
||
|
|
{
|
||
|
|
if (!isInitialized) { InitializePanels(); }
|
||
|
|
if (ControllerManager.instance != null) { ControllerManager.instance.currentManagerIndex = managerIndex; }
|
||
|
|
|
||
|
|
if (bypassAnimationOnEnable)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < panels.Count; i++)
|
||
|
|
{
|
||
|
|
if (panels[i].panelObject == null)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (currentPanelIndex == i)
|
||
|
|
{
|
||
|
|
panels[i].panelObject.gameObject.SetActive(true);
|
||
|
|
panels[i].panelObject.enabled = true;
|
||
|
|
panels[i].panelObject.Play("Panel Instant In");
|
||
|
|
}
|
||
|
|
|
||
|
|
else
|
||
|
|
{
|
||
|
|
panels[i].panelObject.gameObject.SetActive(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
else if (isInitialized && !bypassAnimationOnEnable && nextPanel == null)
|
||
|
|
{
|
||
|
|
currentPanel.enabled = true;
|
||
|
|
currentPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
currentPanel.Play(panelFadeIn);
|
||
|
|
if (currentButton != null) { currentButton.SetSelected(true); }
|
||
|
|
}
|
||
|
|
|
||
|
|
else if (isInitialized && !bypassAnimationOnEnable && nextPanel != null)
|
||
|
|
{
|
||
|
|
nextPanel.enabled = true;
|
||
|
|
nextPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
nextPanel.Play(panelFadeIn);
|
||
|
|
if (nextButton != null) { nextButton.SetSelected(true); }
|
||
|
|
}
|
||
|
|
|
||
|
|
StopCoroutine("DisablePreviousPanel");
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
}
|
||
|
|
|
||
|
|
public void InitializePanels()
|
||
|
|
{
|
||
|
|
if (panels.Count == 0) { return; }
|
||
|
|
if (panels[currentPanelIndex].panelButton != null)
|
||
|
|
{
|
||
|
|
currentButton = panels[currentPanelIndex].panelButton;
|
||
|
|
currentButton.SetSelected(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
currentPanel = panels[currentPanelIndex].panelObject;
|
||
|
|
currentPanel.enabled = true;
|
||
|
|
currentPanel.gameObject.SetActive(true);
|
||
|
|
|
||
|
|
currentPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
currentPanel.Play(panelFadeIn);
|
||
|
|
|
||
|
|
onPanelChanged.Invoke(currentPanelIndex);
|
||
|
|
|
||
|
|
for (int i = 0; i < panels.Count; i++)
|
||
|
|
{
|
||
|
|
if (panels[i].panelObject == null) { continue; }
|
||
|
|
if (i != currentPanelIndex && cullPanels) { panels[i].panelObject.gameObject.SetActive(false); }
|
||
|
|
if (initializeButtons)
|
||
|
|
{
|
||
|
|
string tempName = panels[i].panelName;
|
||
|
|
if (panels[i].panelButton != null) { panels[i].panelButton.onClick.AddListener(() => OpenPanel(tempName)); }
|
||
|
|
if (panels[i].altPanelButton != null) { panels[i].altPanelButton.onClick.AddListener(() => OpenPanel(tempName)); }
|
||
|
|
}
|
||
|
|
if (panels[i].hotkeyParent != null)
|
||
|
|
{
|
||
|
|
panels[i].hotkeys = panels[i].hotkeyParent.GetComponentsInChildren<HotkeyEvent>();
|
||
|
|
if (useCooldownForHotkeys) { foreach (HotkeyEvent he in panels[i].hotkeys) { he.useCooldown = true; } }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
|
||
|
|
isInitialized = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OpenFirstPanel()
|
||
|
|
{
|
||
|
|
OpenPanelByIndex(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OpenPanel(string newPanel)
|
||
|
|
{
|
||
|
|
bool catchedPanel = false;
|
||
|
|
|
||
|
|
for (int i = 0; i < panels.Count; i++)
|
||
|
|
{
|
||
|
|
if (panels[i].panelName == newPanel)
|
||
|
|
{
|
||
|
|
newPanelIndex = i;
|
||
|
|
catchedPanel = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!catchedPanel)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("There is no panel named '" + newPanel + "' in the panel list.", this);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (newPanelIndex != currentPanelIndex)
|
||
|
|
{
|
||
|
|
if (cullPanels) { StopCoroutine("DisablePreviousPanel"); }
|
||
|
|
if (ControllerManager.instance != null) { ControllerManager.instance.currentManagerIndex = managerIndex; }
|
||
|
|
|
||
|
|
currentPanel = panels[currentPanelIndex].panelObject;
|
||
|
|
|
||
|
|
if (panels[currentPanelIndex].hotkeyParent != null) { foreach (HotkeyEvent he in panels[currentPanelIndex].hotkeys) { he.enabled = false; } }
|
||
|
|
if (panels[currentPanelIndex].panelButton != null) { currentButton = panels[currentPanelIndex].panelButton; }
|
||
|
|
if (ControllerManager.instance != null && EventSystem.current.currentSelectedGameObject != null) { panels[currentPanelIndex].latestSelected = EventSystem.current.currentSelectedGameObject; }
|
||
|
|
|
||
|
|
currentPanelIndex = newPanelIndex;
|
||
|
|
nextPanel = panels[currentPanelIndex].panelObject;
|
||
|
|
nextPanel.gameObject.SetActive(true);
|
||
|
|
|
||
|
|
currentPanel.enabled = true;
|
||
|
|
nextPanel.enabled = true;
|
||
|
|
|
||
|
|
currentPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
nextPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
|
||
|
|
currentPanel.Rebind();
|
||
|
|
currentPanel.Play(panelFadeOut);
|
||
|
|
|
||
|
|
nextPanel.Rebind();
|
||
|
|
nextPanel.Play(panelFadeIn);
|
||
|
|
|
||
|
|
if (cullPanels) { StartCoroutine("DisablePreviousPanel"); }
|
||
|
|
if (panels[currentPanelIndex].hotkeyParent != null) { foreach (HotkeyEvent he in panels[currentPanelIndex].hotkeys) { he.enabled = true; } }
|
||
|
|
|
||
|
|
currentButtonIndex = newPanelIndex;
|
||
|
|
|
||
|
|
if (ControllerManager.instance != null && panels[currentPanelIndex].latestSelected != null) { ControllerManager.instance.SelectUIObject(panels[currentPanelIndex].latestSelected); }
|
||
|
|
else if (ControllerManager.instance != null && panels[currentPanelIndex].latestSelected == null) { ControllerManager.instance.SelectUIObject(panels[currentPanelIndex].firstSelected); }
|
||
|
|
|
||
|
|
if (currentButton != null) { currentButton.SetSelected(false); }
|
||
|
|
if (panels[currentButtonIndex].panelButton != null)
|
||
|
|
{
|
||
|
|
nextButton = panels[currentButtonIndex].panelButton;
|
||
|
|
nextButton.SetSelected(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
onPanelChanged.Invoke(currentPanelIndex);
|
||
|
|
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void OpenPanelByIndex(int panelIndex)
|
||
|
|
{
|
||
|
|
if (panelIndex > panels.Count || panelIndex < 0)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("Index '" + panelIndex.ToString() + "' doesn't exist.", this);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < panels.Count; i++)
|
||
|
|
{
|
||
|
|
if (panels[i].panelName == panels[panelIndex].panelName)
|
||
|
|
{
|
||
|
|
OpenPanel(panels[panelIndex].panelName);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void NextPanel()
|
||
|
|
{
|
||
|
|
if (currentPanelIndex <= panels.Count - 2)
|
||
|
|
{
|
||
|
|
OpenPanelByIndex(currentPanelIndex + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void PreviousPanel()
|
||
|
|
{
|
||
|
|
if (currentPanelIndex >= 1)
|
||
|
|
{
|
||
|
|
OpenPanelByIndex(currentPanelIndex - 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ShowCurrentPanel()
|
||
|
|
{
|
||
|
|
if (nextPanel == null)
|
||
|
|
{
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
|
||
|
|
currentPanel.enabled = true;
|
||
|
|
currentPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
currentPanel.Play(panelFadeIn);
|
||
|
|
}
|
||
|
|
|
||
|
|
else
|
||
|
|
{
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
|
||
|
|
nextPanel.enabled = true;
|
||
|
|
nextPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
nextPanel.Play(panelFadeIn);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void HideCurrentPanel()
|
||
|
|
{
|
||
|
|
if (nextPanel == null)
|
||
|
|
{
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
|
||
|
|
currentPanel.enabled = true;
|
||
|
|
currentPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
currentPanel.Play(panelFadeOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
else
|
||
|
|
{
|
||
|
|
StopCoroutine("DisableAnimators");
|
||
|
|
StartCoroutine("DisableAnimators");
|
||
|
|
|
||
|
|
nextPanel.enabled = true;
|
||
|
|
nextPanel.SetFloat(animSpeedKey, animationSpeed);
|
||
|
|
nextPanel.Play(panelFadeOut);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ShowCurrentButton()
|
||
|
|
{
|
||
|
|
if (nextButton == null) { currentButton.SetSelected(true); }
|
||
|
|
else { nextButton.SetSelected(true); }
|
||
|
|
}
|
||
|
|
|
||
|
|
public void HideCurrentButton()
|
||
|
|
{
|
||
|
|
if (nextButton == null) { currentButton.SetSelected(false); }
|
||
|
|
else { nextButton.SetSelected(false); }
|
||
|
|
}
|
||
|
|
|
||
|
|
public void AddNewItem()
|
||
|
|
{
|
||
|
|
PanelItem panel = new PanelItem();
|
||
|
|
|
||
|
|
if (panels.Count != 0 && panels[panels.Count - 1].panelObject != null)
|
||
|
|
{
|
||
|
|
int tempIndex = panels.Count - 1;
|
||
|
|
|
||
|
|
GameObject tempPanel = panels[tempIndex].panelObject.transform.parent.GetChild(tempIndex).gameObject;
|
||
|
|
GameObject newPanel = Instantiate(tempPanel, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
|
||
|
|
|
||
|
|
newPanel.transform.SetParent(panels[tempIndex].panelObject.transform.parent, false);
|
||
|
|
newPanel.gameObject.name = "New Panel " + tempIndex.ToString();
|
||
|
|
|
||
|
|
panel.panelName = "New Panel " + tempIndex.ToString();
|
||
|
|
panel.panelObject = newPanel.GetComponent<Animator>();
|
||
|
|
|
||
|
|
if (panels[tempIndex].panelButton != null)
|
||
|
|
{
|
||
|
|
GameObject tempButton = panels[tempIndex].panelButton.transform.parent.GetChild(tempIndex).gameObject;
|
||
|
|
GameObject newButton = Instantiate(tempButton, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
|
||
|
|
|
||
|
|
newButton.transform.SetParent(panels[tempIndex].panelButton.transform.parent, false);
|
||
|
|
newButton.gameObject.name = "New Panel " + tempIndex.ToString();
|
||
|
|
|
||
|
|
panel.panelButton = newButton.GetComponent<PanelButton>();
|
||
|
|
}
|
||
|
|
|
||
|
|
else if (panels[tempIndex].altPanelButton != null)
|
||
|
|
{
|
||
|
|
GameObject tempButton = panels[tempIndex].altPanelButton.transform.parent.GetChild(tempIndex).gameObject;
|
||
|
|
GameObject newButton = Instantiate(tempButton, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
|
||
|
|
|
||
|
|
newButton.transform.SetParent(panels[tempIndex].panelButton.transform.parent, false);
|
||
|
|
newButton.gameObject.name = "New Panel " + tempIndex.ToString();
|
||
|
|
|
||
|
|
panel.altPanelButton = newButton.GetComponent<ButtonManager>();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
panels.Add(panel);
|
||
|
|
}
|
||
|
|
|
||
|
|
IEnumerator DisablePreviousPanel()
|
||
|
|
{
|
||
|
|
if (updateMode == UpdateMode.UnscaledTime) { yield return new WaitForSecondsRealtime(cachedStateLength * animationSpeed); }
|
||
|
|
else { yield return new WaitForSeconds(cachedStateLength * animationSpeed); }
|
||
|
|
|
||
|
|
for (int i = 0; i < panels.Count; i++)
|
||
|
|
{
|
||
|
|
if (i == currentPanelIndex)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
panels[i].panelObject.gameObject.SetActive(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
IEnumerator DisableAnimators()
|
||
|
|
{
|
||
|
|
if (updateMode == UpdateMode.UnscaledTime) { yield return new WaitForSecondsRealtime(cachedStateLength * animationSpeed); }
|
||
|
|
else { yield return new WaitForSeconds(cachedStateLength * animationSpeed); }
|
||
|
|
|
||
|
|
if (currentPanel != null) { currentPanel.enabled = false; }
|
||
|
|
if (nextPanel != null) { nextPanel.enabled = false; }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|