Refactor TaskButtonManager and TaskTimer to streamline timer command handling

This commit is contained in:
tom.hempel
2025-10-21 18:27:33 +02:00
parent 8274e78d1b
commit fb002a6096
2 changed files with 53 additions and 129 deletions

View File

@ -15,10 +15,16 @@ public class TaskButtonManager : MonoBehaviour
private Thread udpListenerThread; private Thread udpListenerThread;
private bool isListening = false; private bool isListening = false;
private string pendingSceneName = null; private string pendingSceneName = null;
private string pendingTimerCommand = null;
private readonly object sceneLock = new object(); private readonly object sceneLock = new object();
private readonly object timerLock = new object();
private TaskTimer taskTimer;
private void Start() private void Start()
{ {
// Find TaskTimer in the scene
taskTimer = FindObjectOfType<TaskTimer>();
if (enableUDPControl) if (enableUDPControl)
{ {
StartUDPListener(); StartUDPListener();
@ -37,6 +43,23 @@ public class TaskButtonManager : MonoBehaviour
} }
} }
// 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;
}
}
// VR Tasks (Keys 1-4) // VR Tasks (Keys 1-4)
if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1)) if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1))
LoadSceneByName("VR-Task1"); LoadSceneByName("VR-Task1");
@ -108,20 +131,39 @@ public class TaskButtonManager : MonoBehaviour
if (string.IsNullOrEmpty(message)) if (string.IsNullOrEmpty(message))
return; return;
// Parse command format: SWITCH:SceneName // Parse command format: COMMAND:Parameter
string[] parts = message.Split(':'); string[] parts = message.Split(':');
if (parts.Length == 2 && parts[0].Trim().ToUpper() == "SWITCH") if (parts.Length >= 2)
{ {
string sceneName = parts[1].Trim(); string commandType = parts[0].Trim().ToUpper();
lock (sceneLock) string parameter = parts[1].Trim();
if (commandType == "SWITCH")
{ {
pendingSceneName = sceneName; // 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
{
Debug.LogWarning($"Unknown UDP command type: {commandType}. Expected: SWITCH or TIMER");
} }
Debug.Log($"Scheduled scene switch to: {sceneName}");
} }
else else
{ {
Debug.LogWarning($"Invalid UDP command format: {message}. Expected format: SWITCH:SceneName"); Debug.LogWarning($"Invalid UDP command format: {message}. Expected format: COMMAND:Parameter (e.g., SWITCH:SceneName or TIMER:START)");
} }
} }

View File

@ -2,10 +2,6 @@ using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using TMPro; using TMPro;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class TaskTimer : MonoBehaviour public class TaskTimer : MonoBehaviour
{ {
@ -20,8 +16,6 @@ public class TaskTimer : MonoBehaviour
public float warningThreshold = 30f; public float warningThreshold = 30f;
[Header("UDP Control Settings")] [Header("UDP Control Settings")]
[SerializeField] private int udpPort = 5555;
[SerializeField] private bool enableUDPControl = true;
[Tooltip("If enabled, timer will only start via UDP command (ignores autoStart)")] [Tooltip("If enabled, timer will only start via UDP command (ignores autoStart)")]
[SerializeField] private bool waitForUDPStart = false; [SerializeField] private bool waitForUDPStart = false;
@ -45,21 +39,9 @@ public class TaskTimer : MonoBehaviour
private float timeRemaining; private float timeRemaining;
private bool isRunning; private bool isRunning;
// UDP infrastructure
private UdpClient udpClient;
private Thread udpListenerThread;
private bool isListening = false;
private string pendingCommand = null;
private readonly object commandLock = new object();
private void Start() private void Start()
{ {
timeRemaining = taskDuration; timeRemaining = taskDuration;
if (enableUDPControl)
{
StartUDPListener();
}
// Only auto-start if not waiting for UDP command // Only auto-start if not waiting for UDP command
if (autoStart && !waitForUDPStart) if (autoStart && !waitForUDPStart)
@ -72,16 +54,6 @@ public class TaskTimer : MonoBehaviour
private void Update() private void Update()
{ {
// Check for pending UDP commands (must be done on main thread)
lock (commandLock)
{
if (!string.IsNullOrEmpty(pendingCommand))
{
ProcessTimerCommand(pendingCommand);
pendingCommand = null;
}
}
if (!isRunning) if (!isRunning)
return; return;
@ -189,72 +161,11 @@ public class TaskTimer : MonoBehaviour
return 1f - (timeRemaining / taskDuration); return 1f - (timeRemaining / taskDuration);
} }
// UDP Control Methods // Public method to process timer commands (called from UDP listener in TaskButtonManager)
private void StartUDPListener() public void ProcessTimerCommand(string command)
{
try
{
isListening = true;
udpClient = new UdpClient(udpPort);
udpListenerThread = new Thread(new ThreadStart(ListenForUDPCommands));
udpListenerThread.IsBackground = true;
udpListenerThread.Start();
Debug.Log($"TaskTimer: UDP Listener started on port {udpPort}");
}
catch (System.Exception e)
{
Debug.LogError($"TaskTimer: 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($"TaskTimer: UDP receive error: {e.Message}");
}
}
}
}
private void ProcessUDPCommand(string message)
{
Debug.Log($"TaskTimer: Received UDP command: {message}");
if (string.IsNullOrEmpty(message))
return;
// Parse command format: TIMER:COMMAND (e.g., TIMER:START, TIMER:PAUSE, TIMER:RESET, TIMER:RESUME)
string[] parts = message.Split(':');
if (parts.Length == 2 && parts[0].Trim().ToUpper() == "TIMER")
{
string command = parts[1].Trim().ToUpper();
lock (commandLock)
{
pendingCommand = command;
}
Debug.Log($"TaskTimer: Scheduled command: {command}");
}
else
{
Debug.LogWarning($"TaskTimer: Invalid UDP command format: {message}. Expected format: TIMER:COMMAND (e.g., TIMER:START)");
}
}
private void ProcessTimerCommand(string command)
{ {
command = command.ToUpper();
switch (command) switch (command)
{ {
case "START": case "START":
@ -274,34 +185,5 @@ public class TaskTimer : MonoBehaviour
break; break;
} }
} }
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("TaskTimer: UDP Listener stopped");
}
} }