| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- using UnityEngine;
- using UnityEngine.UI;
- using TMPro;
- using LightGlue.Unity.Game;
- using LightGlue.Unity.Networking;
- namespace LightGlue.Unity.UI
- {
- /// <summary>
- /// LightGlue算法结果UI控制器
- /// - 从HardwareToPythonUdpBridge获取算法结果
- /// - 实时显示相机位置、匹配数量、内点比例等信息
- /// </summary>
- public class LightGlueResultUIController : MonoBehaviour
- {
- [Header("结果来源")]
- [Tooltip("必须指定 LightGlueManager,由其统一分发算法结果。禁止直接从 Bridge 获取结果。")]
- public LightGlueManager manager;
- [Header("UI显示组件")]
- [Tooltip("结果有效性状态文本(显示Valid/Invalid)")]
- public Text isValidText;
- [Tooltip("匹配点数量文本")]
- public Text numMatchesText;
- [Tooltip("内点比例文本")]
- public Text inliersRatioText;
- [Tooltip("相机位置X坐标文本")]
- public Text cameraXText;
- [Tooltip("相机位置Y坐标文本")]
- public Text cameraYText;
- [Tooltip("结果状态文本(综合信息显示)")]
- public Text statusText;
- [Header("显示设置")]
- [Tooltip("更新频率(每秒更新次数,默认10次/秒)")]
- [Range(1, 60)]
- public int updateRate = 10;
- [Tooltip("是否显示无效结果(当isValid=false时)")]
- public bool showInvalidResults = true;
- [Tooltip("无效结果时的显示文本")]
- public string invalidResultText = "等待有效结果...";
- private float _updateInterval;
- private float _lastUpdateTime;
- private LightGlueResult _latestResult;
- private bool _hasResult = false;
- private void Start()
- {
- _updateInterval = 1.0f / updateRate;
- _lastUpdateTime = Time.time;
- // 结果来源:强制通过全局 LightGlueManager 获取
- if (manager == null)
- {
- manager = LightGlueManager.Instance;
- }
- if (manager == null)
- {
- Debug.LogError("[LightGlueResultUI] 未找到 LightGlueManager,无法获取算法结果。请在场景中放置 LightGlueSystem 预制并确保 LightGlueManager 存在。");
- }
- else
- {
- manager.OnResultUpdated += OnResultUpdated;
- if (manager.HasLatestResult)
- {
- OnResultUpdated(manager.LatestResult);
- }
- }
- }
- private void Update()
- {
- // 按指定频率更新
- if (Time.time - _lastUpdateTime < _updateInterval)
- return;
- _lastUpdateTime = Time.time;
- // 强制使用 Manager 分发的结果
- if (manager == null)
- return;
- if (_hasResult)
- {
- UpdateUI(_latestResult);
- }
- else if (!showInvalidResults)
- {
- ClearUI();
- }
- }
- /// <summary>
- /// 更新UI显示
- /// </summary>
- private void UpdateUI(LightGlueResult result)
- {
- // 显示结果有效性
- if (isValidText != null)
- {
- if (result.IsValid)
- {
- isValidText.text = "状态: 有效";
- isValidText.color = Color.green;
- }
- else
- {
- isValidText.text = "状态: 无效";
- isValidText.color = Color.red;
- }
- }
- // 显示匹配点数量
- if (numMatchesText != null)
- {
- numMatchesText.text = $"匹配点: {result.NumMatches}";
- }
- // 显示内点比例
- if (inliersRatioText != null)
- {
- inliersRatioText.text = $"内点比例: {result.InliersRatio:P1}";
- }
- // 显示相机位置(仅在有效时显示)
- if (result.IsValid)
- {
- if (cameraXText != null)
- {
- cameraXText.text = $"相机X: {result.CameraPosition.x:F1}";
- }
- if (cameraYText != null)
- {
- cameraYText.text = $"相机Y: {result.CameraPosition.y:F1}";
- }
- }
- else
- {
- if (cameraXText != null)
- {
- cameraXText.text = "相机X: --";
- }
- if (cameraYText != null)
- {
- cameraYText.text = "相机Y: --";
- }
- }
- // 显示综合状态信息
- if (statusText != null)
- {
- if (result.IsValid)
- {
- statusText.text = $"有效 | 匹配:{result.NumMatches} | 内点:{result.InliersRatio:P1} | 位置:({result.CameraPosition.x:F1}, {result.CameraPosition.y:F1})";
- statusText.color = Color.white;
- }
- else
- {
- statusText.text = showInvalidResults
- ? $"无效 | 匹配:{result.NumMatches} | {invalidResultText}"
- : invalidResultText;
- statusText.color = Color.yellow;
- }
- }
- }
- /// <summary>
- /// 清空UI显示
- /// </summary>
- private void ClearUI()
- {
- if (isValidText != null)
- isValidText.text = "状态: --";
- if (numMatchesText != null)
- numMatchesText.text = "匹配点: --";
- if (inliersRatioText != null)
- inliersRatioText.text = "内点比例: --";
- if (cameraXText != null)
- cameraXText.text = "相机X: --";
- if (cameraYText != null)
- cameraYText.text = "相机Y: --";
- if (statusText != null)
- {
- statusText.text = invalidResultText;
- statusText.color = Color.gray;
- }
- }
- /// <summary>
- /// 获取最新结果(供外部调用)
- /// </summary>
- public bool TryGetLatestResult(out LightGlueResult result)
- {
- if (_hasResult)
- {
- result = _latestResult;
- return true;
- }
- result = default(LightGlueResult);
- return false;
- }
- /// <summary>
- /// 检查是否有有效结果
- /// </summary>
- public bool HasValidResult()
- {
- return _hasResult && _latestResult.IsValid;
- }
- /// <summary>
- /// 由 LightGlueManager 触发的结果更新回调,仅做结果缓存,具体 UI 刷新仍由 Update 按频率驱动。
- /// </summary>
- private void OnResultUpdated(LightGlueResult result)
- {
- _latestResult = result;
- _hasResult = true;
- }
- private void OnDestroy()
- {
- if (manager != null)
- {
- manager.OnResultUpdated -= OnResultUpdated;
- }
- }
- }
- }
|