using System.Collections; using OctoCore.Navigation.Data; using OctoCore.UI; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.UI; namespace OctoCore.Navigation { /// /// Main menu manager. /// Handles Play, Quit and optional extra buttons. /// Relies on OctoCore.Navigation for scene loading. /// public class OctoMainMenu : MonoBehaviour { [Header("Scene Settings")] [SerializeField, Tooltip("First scene to load on Play")] private OctoSceneData _firstSceneData; [Header("UI Settings")] [SerializeField, Tooltip("Optional panel to show/hide (options, credits...)")] private GameObject _optionalPanel; [SerializeField] private GameObject _loadingScreen; [SerializeField] private GameObject _loadingWheel; [SerializeField] private Button _optionalPanelFirstButton; [SerializeField] private Button _mainPanelDefaultButton; private bool _isLoading = false; void Awake() { // Hide optional panel on start if assigned if (_optionalPanel) _optionalPanel.SetActive(false); // Make sure cursor is visible in main menu Cursor.visible = true; Cursor.lockState = CursorLockMode.None; } void Update() { if (_isLoading && _loadingWheel) _loadingWheel.transform.Rotate(0, 0, -200f * Time.deltaTime); } /// /// Load the first scene. Called by the Play button. /// public void OnPlayButton() { if (!OctoCore.Instance) { Debug.LogError("[OctoMainMenu] OctoCore instance not found"); return; } if (_firstSceneData == null) { Debug.LogError("[OctoMainMenu] FirstSceneData is null"); return; } _ = PlayRoutine(); } private async Awaitable PlayRoutine() { _isLoading = true; if (_loadingScreen) _loadingScreen.SetActive(true); await System.Threading.Tasks.Task.Delay(2000); #if !UNITY_EDITOR Shader.WarmupAllShaders(); #endif _isLoading = false; OctoCore.Instance.Navigation.LoadScene(_firstSceneData); } /// /// Quit the application. Called by the Quit button. /// public void OnQuitButton() { Application.Quit(); #if UNITY_EDITOR UnityEditor.EditorApplication.isPlaying = false; #endif } /// /// Toggle an optional panel (options, credits...). Called by any extra button. /// public void OnTogglePanel() { if (_optionalPanel) { bool newState = !_optionalPanel.activeSelf; _optionalPanel.SetActive(newState); } } public void SelectMainDefaultButton() { StartCoroutine(SelectAfterFrame(_mainPanelDefaultButton)); } public void SelectDebugFirstButton() { StartCoroutine(SelectAfterFrame(_optionalPanelFirstButton)); } private IEnumerator SelectAfterFrame(Button button) { MultiTargetButton.ClearPersistence(); EventSystem.current.SetSelectedGameObject(button.gameObject); // Ignore mouse hover for 0.1s so it doesn't steal selection OctoMainMenu.IgnoreMouseUntil = Time.time + 0.1f; yield break; } // Exposed so MultiTargetButton can check before activating on hover public static float IgnoreMouseUntil = 0f; public void ClearButtonPersistence() { MultiTargetButton.ClearPersistence(); } } }