using TMPro; using UnityEngine; namespace InteractiveVideo { /// /// Optional UI: shows the selected object's name, current action and track id (confidence in debug mode). /// Purely a listener on the tracking manager; the core system works without it. /// [AddComponentMenu("Interactive Video/Video Object Info Panel")] public sealed class VideoObjectInfoPanel : MonoBehaviour { [SerializeField] private VideoTrackingManager trackingManager; [Tooltip("Root that is shown/hidden. Defaults to this GameObject.")] [SerializeField] private GameObject panelRoot; [Header("Texts (any may be left empty)")] [SerializeField] private TMP_Text nameText; [SerializeField] private TMP_Text actionText; [SerializeField] private TMP_Text trackIdText; [SerializeField] private TMP_Text confidenceText; [Header("Behaviour")] [SerializeField] private bool hideWhenNothingSelected = true; [SerializeField] private bool showConfidence; [SerializeField] private string notVisibleActionText = "(not visible right now)"; [SerializeField] private string noActionText = "-"; private string _lastName, _lastAction, _lastTrackId, _lastConfidence; private bool _lastShown = true; // children start active in the scene; first Refresh() may hide them private void Awake() { if (panelRoot == null) panelRoot = gameObject; } private void OnEnable() { if (trackingManager == null) trackingManager = FindAnyObjectByType(); if (trackingManager != null) { trackingManager.SelectionChanged += Refresh; trackingManager.FrameChanged += OnFrameChanged; trackingManager.TrackingLoaded += OnTrackingLoaded; } _lastName = _lastAction = _lastTrackId = _lastConfidence = null; Refresh(); } private void OnDisable() { if (trackingManager != null) { trackingManager.SelectionChanged -= Refresh; trackingManager.FrameChanged -= OnFrameChanged; trackingManager.TrackingLoaded -= OnTrackingLoaded; } } private void OnFrameChanged(long frame) => Refresh(); private void OnTrackingLoaded(TrackingData data) => Refresh(); /// Re-reads the selection and updates the texts (only touching texts whose content changed). public void Refresh() { if (trackingManager == null || !trackingManager.HasSelection) { Show(!hideWhenNothingSelected); if (!hideWhenNothingSelected) SetTexts("", "", "", ""); return; } string trackId = trackingManager.SelectedTrackId; TrackedObject def = trackingManager.GetDefinition(trackId); string displayName = def != null && !string.IsNullOrEmpty(def.Name) ? def.Name : trackId; string action, confidence; if (trackingManager.TryGetSelectedObject(out var state) && state.Visible) { action = string.IsNullOrEmpty(state.Action) ? noActionText : Capitalise(state.Action); confidence = showConfidence ? $"{state.Confidence:P0}" : ""; } else { action = notVisibleActionText; confidence = ""; } Show(true); SetTexts(displayName, action, trackId, confidence); } private void Show(bool shown) { if (panelRoot != null && panelRoot != gameObject && panelRoot.activeSelf != shown) panelRoot.SetActive(shown); else if (panelRoot == gameObject && _lastShown != shown) { // Cannot deactivate ourselves (we would stop receiving events); toggle the children instead. for (int i = 0; i < transform.childCount; i++) transform.GetChild(i).gameObject.SetActive(shown); var graphic = GetComponent(); if (graphic != null) graphic.enabled = shown; } _lastShown = shown; } private void SetTexts(string displayName, string action, string trackId, string confidence) { if (nameText != null && _lastName != displayName) nameText.text = displayName; if (actionText != null && _lastAction != action) actionText.text = action; if (trackIdText != null && _lastTrackId != trackId) trackIdText.text = trackId; if (confidenceText != null && _lastConfidence != confidence) { confidenceText.text = confidence; confidenceText.gameObject.SetActive(!string.IsNullOrEmpty(confidence)); } _lastName = displayName; _lastAction = action; _lastTrackId = trackId; _lastConfidence = confidence; } private static string Capitalise(string s) => string.IsNullOrEmpty(s) ? s : char.ToUpperInvariant(s[0]) + s.Substring(1); } }