using LightGlue.Unity.Networking; using LightGlue.Unity.Python; using UnityEngine; namespace LightGlue.Unity.Roma { /// /// Roma 新场景一键启动器: /// - 启动广播发现 /// - 发现后配置 WiFi 图传并开启 /// - 启动 Roma Python(独立于 LightGlue_Deployment) /// - 启动图像显示与结果接收(复用 UDPResultReceiver 协议/端口) /// /// 约束:该脚本只应挂在 Roma 新场景中;用户不会同时运行旧场景与新场景。 /// public sealed class RomaSceneBootstrap : MonoBehaviour { [Header("Discovery + Control")] public RomaDeviceDiscoveryListener discovery; public RomaWifiCameraControlClient wifiControl; [Header("Python (RoMa)")] [Tooltip("Roma 专用 Python 进程控制器(需指向 LightGlue_Roma 工程目录与脚本)")] public PythonProcessController romaPythonController; [Header("Image Viewer (Python -> Unity)")] public RomaForwardedImageViewer forwardedViewer; [Header("Result Receiver (Python -> Unity)")] [Tooltip("复用现有 UDPResultReceiver 协议(0x0001/20字节),监听 pythonResultPort=12348(可在 Inspector 改)")] public bool enableResultReceiver = true; public string resultBindIp = "127.0.0.1"; public int resultPort = 12348; public int maxResultQueueSize = 10; public UDPResultReceiver ResultReceiver => _resultReceiver; private UDPResultReceiver _resultReceiver; private void OnEnable() { // 如果已存在持久化 RomaManager,则不再在场景里重复启动/绑定端口 if (RomaManager.Instance != null) { enabled = false; return; } Application.runInBackground = true; if (discovery == null) discovery = FindObjectOfType(); if (wifiControl == null) wifiControl = FindObjectOfType(); if (forwardedViewer == null) forwardedViewer = FindObjectOfType(); if (wifiControl != null && discovery != null) wifiControl.BindDiscovery(discovery); if (discovery != null && !discovery.IsListening) discovery.StartListening(); // 启动 Roma Python:这里不改旧工程逻辑,只调用 StartPython(Roma 控制器需在 Inspector 配好路径/脚本) if (romaPythonController != null && !romaPythonController.IsRunning) romaPythonController.StartPython(); if (enableResultReceiver) { try { _resultReceiver = new UDPResultReceiver(resultBindIp, resultPort, maxResultQueueSize); _resultReceiver.Start(); } catch (System.Exception ex) { Debug.LogError($"[RomaBootstrap] Start result receiver failed on {resultBindIp}:{resultPort}: {ex.Message}"); try { _resultReceiver?.Stop(); } catch { /* ignore */ } _resultReceiver = null; } } } private void OnDisable() { try { _resultReceiver?.Stop(); } catch { /* ignore */ } _resultReceiver = null; } /// /// Roma 场景侧提供一个“取最新结果”的便捷接口(与 Bridge.TryGetLatestResult 风格一致)。 /// public bool TryGetLatestResult(out LightGlueResult result) { result = default(LightGlueResult); if (_resultReceiver == null) return false; bool any = false; while (_resultReceiver.TryDequeueResult(out var r)) { result = r; any = true; } return any; } } }