using UnityEngine; using UnityEngine.SceneManagement; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; public class TaskButtonManager : MonoBehaviour { [Header("UDP Settings")] [SerializeField] private int udpPort = 5555; [SerializeField] private bool enableUDPControl = true; private UdpClient udpClient; private Thread udpListenerThread; private bool isListening = false; private string pendingSceneName = null; private string pendingTimerCommand = null; private readonly object sceneLock = new object(); private readonly object timerLock = new object(); private readonly object notesLock = new object(); private TaskTimer taskTimer; private NotesDisplay notesDisplay; private string pendingNotesText = null; private void Start() { // Find TaskTimer in the scene taskTimer = FindObjectOfType(); // Find NotesDisplay in the scene notesDisplay = FindObjectOfType(); if (enableUDPControl) { StartUDPListener(); } } private void Update() { // Check for pending UDP scene changes (must be done on main thread) lock (sceneLock) { if (!string.IsNullOrEmpty(pendingSceneName)) { LoadSceneByName(pendingSceneName); pendingSceneName = null; } } // Check for pending timer commands (must be done on main thread) lock (timerLock) { if (!string.IsNullOrEmpty(pendingTimerCommand)) { if (taskTimer != null) { taskTimer.ProcessTimerCommand(pendingTimerCommand); } else { Debug.LogWarning("TaskTimer not found in scene. Cannot process timer command."); } pendingTimerCommand = null; } } // Check for pending notes updates (must be done on main thread) lock (notesLock) { if (!string.IsNullOrEmpty(pendingNotesText)) { if (notesDisplay != null) { notesDisplay.SetNotes(pendingNotesText); } else { Debug.LogWarning("NotesDisplay not found in scene. Cannot display notes text."); } pendingNotesText = null; } } // VR Tasks (Keys 1-4) if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1)) LoadSceneByName("VR-Task1"); else if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2)) LoadSceneByName("VR -Task2"); else if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3)) LoadSceneByName("VR -Task3"); else if (Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4)) LoadSceneByName("VR -Task4"); // AR Tasks (Keys 5-8) else if (Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5)) LoadSceneByName("AR-Task1"); else if (Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6)) LoadSceneByName("AR-Task2"); else if (Input.GetKeyDown(KeyCode.Alpha7) || Input.GetKeyDown(KeyCode.Keypad7)) LoadSceneByName("AR-Task3"); else if (Input.GetKeyDown(KeyCode.Alpha8) || Input.GetKeyDown(KeyCode.Keypad8)) LoadSceneByName("AR-Task4"); // Lobby (Key L or 0) else if (Input.GetKeyDown(KeyCode.L) || Input.GetKeyDown(KeyCode.Alpha0) || Input.GetKeyDown(KeyCode.Keypad0)) LoadSceneByName("Lobby"); } private void StartUDPListener() { try { isListening = true; udpClient = new UdpClient(udpPort); udpListenerThread = new Thread(new ThreadStart(ListenForUDPCommands)); udpListenerThread.IsBackground = true; udpListenerThread.Start(); Debug.Log($"UDP Listener started on port {udpPort}"); } catch (System.Exception e) { Debug.LogError($"Failed to start UDP listener: {e.Message}"); } } private void ListenForUDPCommands() { IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udpPort); while (isListening) { try { byte[] data = udpClient.Receive(ref remoteEndPoint); string message = Encoding.UTF8.GetString(data); ProcessUDPCommand(message); } catch (System.Exception e) { if (isListening) { Debug.LogError($"UDP receive error: {e.Message}"); } } } } private void ProcessUDPCommand(string message) { Debug.Log($"Received UDP command: {message}"); if (string.IsNullOrEmpty(message)) return; // Parse command format: COMMAND:Parameter (Parameter may contain additional colons) int separatorIndex = message.IndexOf(':'); if (separatorIndex > 0 && separatorIndex < message.Length - 1) { string commandType = message.Substring(0, separatorIndex).Trim().ToUpper(); string parameter = message.Substring(separatorIndex + 1); // keep raw to preserve spaces/colons if (commandType == "SWITCH") { // Scene switching command lock (sceneLock) { pendingSceneName = parameter; } Debug.Log($"Scheduled scene switch to: {parameter}"); } else if (commandType == "TIMER") { // Timer control command lock (timerLock) { pendingTimerCommand = parameter; } Debug.Log($"Scheduled timer command: {parameter}"); } else if (commandType == "NOTES") { // Notes display command lock (notesLock) { pendingNotesText = parameter; } Debug.Log($"Scheduled notes update: {parameter}"); } else { Debug.LogWarning($"Unknown UDP command type: {commandType}. Expected: SWITCH, TIMER or NOTES"); } } else { Debug.LogWarning($"Invalid UDP command format: {message}. Expected format: COMMAND:Parameter (e.g., SWITCH:SceneName, TIMER:START or NOTES:Your text)"); } } private void LoadSceneByName(string sceneName) { Debug.Log($"Loading scene: {sceneName}"); SceneManager.LoadScene(sceneName); } private void OnDestroy() { StopUDPListener(); } private void OnApplicationQuit() { StopUDPListener(); } private void StopUDPListener() { isListening = false; if (udpClient != null) { udpClient.Close(); udpClient = null; } if (udpListenerThread != null && udpListenerThread.IsAlive) { udpListenerThread.Abort(); udpListenerThread = null; } Debug.Log("UDP Listener stopped"); } }