using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.UI; using TMPro; using Unity.VisualScripting; using UnityEngine.InputSystem.Users; //using UnityEngine.Device; using UnityEngine.SceneManagement; using System; using UnityEngine.InputSystem.UI; using UnityEngine.InputSystem.Utilities; //using UnityEngine.Windows; public class PlayerInfo { public InputDevice Device { get; set; } public string ControlScheme { get; set; } } public class ModeSelection : MonoBehaviour { public Button primaryButton; public Button confirmButton; public Button firstButtonAI; public Button confirmButtonAI; // Game mode selection buttons and graphics public GameObject graphic1v1; public GameObject graphic1v1ai; public GameObject graphic2v2; public GameObject graphic3v3; public CharacterSelection CharacterSelectionScript; public CashSystemCharacterSelection cashSystemCharacterSelection; //[SerializeField] JoinPlayer joinPlayer; public GameObject selectionScreen; public GameObject modeSelectionScreen; // Player selection buttons for each game mode public Button[] playerButtons1v1; public Button[] playerButtons1v1ai; public Button[] playerButtons2v2; public Button[] playerButtons3v3; public Sprite[] characterImages; // Character prefabs public GameObject[] characterPrefabs; // Maximum number of players for each game mode public int maxPlayers1v1 = 2; public int maxPlayers2v2 = 4; public int maxPlayers3v3 = 6; // Input devices for player selection public Image characterImage; private string previousCharacterName = ""; public InputActionAsset existingInputAsset; public GameObject systemEvents; public GameObject systemEvents2; public Button[] playerButtons; public PlayerInput playerIncontrol; public InputAction.CallbackContext callbackContext; string controlScheme; public Dictionary selectedPlayersAI = new Dictionary(); public Dictionary selectedPlayerDevice = new Dictionary(); private int joinedPlayers = 0; private int maxPlayers = 2; // Set this to the maximum number of players you want to allow. private bool isMobile; public HomeSrceen homeScreen; public Button versusScreenBackButton; #if ENABLE_INPUT_SYSTEM private IDisposable onAnyButtonPressSubscription; #endif // Prevent duplicate scene loads private bool isLoadingGameScene = false; // Start is called before the first frame update void Start() { //initialize 1v1 graphic graphic1v1.SetActive(false); graphic1v1ai.SetActive(false); graphic2v2.SetActive(false); graphic3v3.SetActive(false); //graphic1v1.gameObject.transform.GetChild(1).GetChild(0).gameObject.SetActive(false); // This subscribes us to events that will fire if any button is pressed. We'll most certainly want to throw this away // when not in a selection screen (performance intensive)! #if ENABLE_INPUT_SYSTEM EnableJoinListener(); #endif } #if ENABLE_INPUT_SYSTEM private void EnableJoinListener() { if (!Application.isPlaying) return; if (onAnyButtonPressSubscription != null) return; Action handler = control => { if (control == null) return; HandleDeviceJoin(control.device); }; onAnyButtonPressSubscription = InputSystem.onAnyButtonPress.Call(handler); } private void DisableJoinListener() { if (!Application.isPlaying) return; if (onAnyButtonPressSubscription != null) { onAnyButtonPressSubscription.Dispose(); onAnyButtonPressSubscription = null; } } private void HandleDeviceJoin(InputDevice device) { if (device == null) return; if (joinedPlayers >= maxPlayers) { DisableJoinListener(); return; } if (!isActiveAndEnabled || modeSelectionScreen == null || !modeSelectionScreen.activeSelf) return; AddPlayer(device); if (joinedPlayers >= maxPlayers) { DisableJoinListener(); } } #endif private void OnEnable() { #if ENABLE_INPUT_SYSTEM if (!Application.isPlaying) return; EnableJoinListener(); #endif } private void OnDisable() { #if ENABLE_INPUT_SYSTEM if (!Application.isPlaying) return; DisableJoinListener(); #endif } public void SelectFirstButton() { primaryButton.Select(); } public void SelectFirstAIButton() { firstButtonAI.Select(); } void AddPlayer(InputDevice device) { //return if the gameobject is not modeselection screen if (!gameObject.activeSelf || !graphic1v1.gameObject.activeSelf || EventSystem.current.currentSelectedGameObject.name == "BackButton") { return; } if (graphic1v1.gameObject.activeSelf || graphic2v2.gameObject.activeSelf || graphic3v3.gameObject.activeSelf) { // Avoid running if the device is already paired to a player /*if (PlayerInput.all.Count > 0) {*/ foreach (var player in PlayerInput.all) { //InputUser inputUser = player.user; foreach (var playerDevice in player.devices) { if ((playerDevice.name.Contains("Keyboard") || playerDevice.name.Contains("Mouse")) && (device.name.Contains("Keyboard") || device.name.Contains("Mouse"))) { /*print(device.name); print("keyboard/mouse already added returned");*/ return; } if (device.name == playerDevice.name) { /*print(device.name); print("device already added");*/ return; } /*else if ((device.name.Contains("Keyboard") || device.name.Contains("Mouse")) && (playerDevice.name.Contains("Keyboard") || playerDevice.name.Contains("Mouse"))) return;*/ } } //} // Don't execute if not a gamepad or joystick or keyboard&mouse if (!device.name.Contains("Controller") && !device.name.Contains("Joystick") && !device.name.Contains("Gamepad") && !device.name.Contains("Keyboard") && !device.name.Contains("Mouse")) { print("if returned"); return; } //print("Adding player"); //var playerNumberToAdd = PlayerInput.all.Count + 1; if (device.name.Contains("Controller") || device.name.Contains("Gamepad")) controlScheme = "Gamepad"; else if (device.name.Contains("Joystick")) controlScheme = "Joystick"; else if (device.name.Contains("Keyboard") || device.name.Contains("Mouse")) controlScheme = "Keyboard&Mouse"; foreach (var button in playerButtons1v1) { //print (button.name); if (button.gameObject.GetComponent() == null) { PlayerInput buttonInput = button.gameObject.AddComponent(); buttonInput.actions = existingInputAsset; buttonInput.defaultControlScheme = controlScheme; buttonInput.neverAutoSwitchControlSchemes = true; buttonInput.notificationBehavior = PlayerNotifications.InvokeUnityEvents; buttonInput.uiInputModule = systemEvents.GetComponent(); buttonInput.uiInputModule.enabled = true; //buttonInput.uiInputModule.ActivateModule(); //buttonInput.uiInputModule.actionsAsset = existingInputAsset; InputUser myUser = buttonInput.user; //InputUser user = InputUser.PerformPairingWithDevice(device); InputUser.PerformPairingWithDevice(device, myUser); buttonInput.SwitchCurrentControlScheme(controlScheme, device); buttonInput.defaultActionMap = "UI"; buttonInput.SwitchCurrentActionMap("UI"); buttonInput.currentActionMap["Submit"].performed += OnSubmit; //buttonInput.gameObject.GetComponentInChildren().text = buttonInput.currentControlScheme.ToString();//this was about displaying the attached device to keyboard buttonInput.camera = GameObject.Find("Main Camera").GetComponent(); buttonInput.enabled = true; buttonInput.ActivateInput(); joinedPlayers++; return; } } } } public void On1v1aiClick() { foreach (var button in playerButtons1v1ai) { if (EventSystem.current.currentSelectedGameObject == button.gameObject) { //button.gameObject.GetComponent().PlayClickSound(); PlayerPrefs.SetString("selectedbuttonpvp", button.name); //print("sent button" + PlayerPrefs.GetString("selectedbuttonpvp")); modeSelectionScreen.SetActive(false); CharacterSelectionScript.selectCharacterButton.onClick.AddListener(onSelectionScreenSelectClick); CharacterSelectionScript.backButton.onClick.AddListener(onSelectionScreenBackClick); selectionScreen.SetActive(true); } } } /// /// Called when the Confirm button is clicked in 3v3 mode (Cash System) /// Wire this to the Confirm button's OnClick in the 3v3 graphic /// public void OnConfirmButton3v3() { Debug.Log("[ModeSelection] OnConfirmButton3v3 clicked"); // Check if we're in Cash System mode if (SelectionOptions.Instance != null && SelectionOptions.Instance.isCashSystemSelected) { // Delegate to CashSystemCharacterSelection if (cashSystemCharacterSelection != null) { cashSystemCharacterSelection.OnConfirmClicked(); } else { // Fallback - get from graphic3v3 CashSystemCharacterSelection cashSelection = graphic3v3.GetComponent(); if (cashSelection != null) { cashSelection.OnConfirmClicked(); } else { Debug.LogError("[ModeSelection] CashSystemCharacterSelection not found!"); } } } else { // Not in Cash System mode - use the original AI confirm handler Debug.Log("[ModeSelection] Not in Cash System mode, calling OnconfirmButtonAIClick"); OnconfirmButtonAIClick(); } } public void OnconfirmButtonAIClick() { if (selectedPlayersAI.Count != 2 || SelectionOptions.Instance == null) { Debug.LogWarning("Not enough players selected or SelectionOptions not initialized"); return; } // Guard against duplicate loads if (isLoadingGameScene || SceneLoader.IsLoading) return; // Disable input action and button to prevent double click #if ENABLE_INPUT_SYSTEM DisableJoinListener(); #endif if (confirmButtonAI != null) confirmButtonAI.interactable = false; // Check platform isMobile = UnityEngine.Application.platform == RuntimePlatform.Android || UnityEngine.Application.platform == RuntimePlatform.IPhonePlayer; if (!isMobile) { bool isKeyboardInput = Keyboard.current != null && Keyboard.current.enterKey.isPressed; bool isMouseClick = Mouse.current != null && Mouse.current.leftButton.isPressed; if (isKeyboardInput || isMouseClick) { SetupAIGame("Keyboard&Mouse", InputSystem.GetDevice()); } else { SetupAIGame("Gamepad", InputSystem.GetDevice()); } } else { SetupAIGame("Gamepad", InputSystem.GetDevice()); } } private void SetupAIGame(string controlScheme, InputDevice device) { SelectionOptions.Instance.selectedPlayersAI = selectedPlayersAI; SelectionOptions.Instance.activeDeviceforAI = device; SelectionOptions.Instance.controlSchemeforAI = controlScheme; //GameManager.Instance.ShowLoadingUI(); //GameManager.Instance.gameObject.GetComponent()?.UI_to_show_AfterLoading(1, "Game"); //GameManager.Instance.gameObject.GetComponent()?.InitializeLoading(); // Start the loading sequence StartCoroutine(LoadGameWithUI()); } private IEnumerator LoadGameWithUI() { // Guard against multiple loads if (isLoadingGameScene || SceneLoader.IsLoading) yield break; isLoadingGameScene = true; // Show loading UI GameManager.Instance.ShowLoadingUI(); // Load Game scene (Editor: built-in, Android: custom AssetBundle) // SceneLoader now handles everything automatically! var asyncLoad = SceneLoader.LoadSceneAsyncOnce("Movement Testing", LoadSceneMode.Single, allowSceneActivation: true); if (asyncLoad == null) { isLoadingGameScene = false; GameManager.Instance.HideLoadingUI(); yield break; } // IMPORTANT: Run the wait loop on GameManager so it survives scene changes // This coroutine (running on ModeSelection) will be destroyed when MenuScene unloads! GameManager.Instance.StartCoroutine(WaitForGameSceneLoad(asyncLoad)); // This coroutine will be destroyed here when the scene changes, which is fine // because WaitForGameSceneLoad is running on GameManager (DontDestroyOnLoad) } private static IEnumerator WaitForGameSceneLoad(SceneLoader.SceneLoadHandle asyncLoad) { // Wait until scene is fully loaded while (asyncLoad != null && !asyncLoad.isDone) { yield return null; } Debug.Log("[ModeSelection] Game scene loaded, hiding loading UI..."); if (GameManager.Instance != null) { GameManager.Instance.HideLoadingUI(); } } string GetKeyFromValue(Dictionary dictionary, string value) { foreach (KeyValuePair kvp in dictionary) { if (kvp.Value == value) { return kvp.Key; } } return null; // Return null if the value is not found } string GetNameFromValue(Dictionary dictionary, InputDevice device) { foreach (KeyValuePair kvp in dictionary) { if (kvp.Value.Device == device) { return kvp.Key; } } return null; // Return null if the value is not found } InputDevice GetDeviceFromValue(Dictionary dictionary, InputDevice device) { foreach (KeyValuePair kvp in dictionary) { if (kvp.Value.Device == device) { return kvp.Value.Device; } } return null; // Return null if the value is not found } //this will help selecting character while in ai mode public void onSelectionScreenSelectClick() { string selectedCharacterName = PlayerPrefs.GetString("selectedcharactername", ""); if (selectedCharacterName != "") { // Check if in Cash System mode if (SelectionOptions.Instance != null && SelectionOptions.Instance.isCashSystemSelected) { HandleCashSystemCharacterSelection(selectedCharacterName); return; } string selectedbuttonpvp = PlayerPrefs.GetString("selectedbuttonpvp"); if (!string.IsNullOrEmpty(selectedbuttonpvp)) { // Remove the previous character selection if it exists if (selectedbuttonpvp == "1.1ai" && selectedPlayersAI.ContainsValue("AI")) { print("removed characters " + GetKeyFromValue(selectedPlayersAI, "AI")); selectedPlayersAI.Remove(GetKeyFromValue(selectedPlayersAI, "AI")); } else if(selectedbuttonpvp == "1.2ai" && selectedPlayersAI.ContainsValue("PLAYER")){ print("removed characters " + GetKeyFromValue(selectedPlayersAI, "PLAYER")); selectedPlayersAI.Remove(GetKeyFromValue(selectedPlayersAI, "PLAYER")); } // Add the new character selection if (selectedbuttonpvp == "1.1ai") { selectedPlayersAI.Add(selectedCharacterName, "AI"); } else if (selectedbuttonpvp == "1.2ai") { selectedPlayersAI.Add(selectedCharacterName, "PLAYER"); } UpdatePlayerSelectButtons(selectedCharacterName); // Pass the selected character name PlayerPrefs.SetString("selectedcharactername", ""); // Deactivate the current screen selectionScreen.SetActive(false); // Activate the ModeScreen CharacterSelectionScript.modeScreen.SetActive(true); // Update the selected button foreach (var button in playerButtons1v1ai) { if (button.name == selectedbuttonpvp) { GameObject buttonCurrent = button.gameObject; print("button current" + buttonCurrent.name); buttonCurrent.GetComponent