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);
}
}