using System; using System.Collections.Generic; using System.Linq; using Convai.Scripts.Runtime.Addons; using Convai.Scripts.Runtime.Core; using Convai.Scripts.Runtime.Extensions; using Convai.Scripts.Runtime.LoggerSystem; using UnityEngine; using UnityEngine.UI; namespace Convai.Scripts.Runtime.UI { /// /// Base class for chat UI components, providing common functionality and abstract methods to be implemented by derived /// classes. /// public abstract class ChatUIBase : MonoBehaviour, IChatUI { [SerializeField] protected GameObject recordingMarker; private readonly List _characters = new(); private float _markerInitialAlpha; private Image _recordingMarkerImage; [NonSerialized] protected GameObject UIInstance; /// /// Initializes the recording marker and subscribes to the OnPlayerSpeakingChanged event. /// protected virtual void Start() { SetupMarkerImage(); SetRecordingMarkerActive(true); ConvaiGRPCAPI.Instance.OnPlayerSpeakingChanged += OnPlayerSpeakingChanged; } /// /// Initializes the UI with the provided prefab. /// /// The UI prefab to instantiate. public abstract void Initialize(GameObject uiPrefab); /// /// Activates the UI instance if transcript UI status is active. /// public virtual void ActivateUI() { if (UISaveLoadSystem.Instance.TranscriptUIActiveStatus) { SetUIActive(true); UIStatusChange?.Invoke(true); } } /// /// Deactivates the UI instance. /// public virtual void DeactivateUI() { SetUIActive(false); UIStatusChange.Invoke(false); } /// /// Sends character text to the UI. /// /// The name of the character. /// The text to send. /// The color of the character's text. public abstract void SendCharacterText(string charName, string text, Color characterTextColor); /// /// Sends player text to the UI. /// /// The name of the player. /// The text to send. /// The color of the player's text. public abstract void SendPlayerText(string playerName, string text, Color playerTextColor); /// /// Retrieves the CanvasGroup component from the UI instance. /// /// The CanvasGroup component. public CanvasGroup GetCanvasGroup() { return UIInstance.GetComponent(); } public static event Action UIStatusChange; private void SetupMarkerImage() { if (recordingMarker == null) throw new NullReferenceException("Recording Marker Image cannot be null, please assign an image for it"); _recordingMarkerImage = recordingMarker.GetComponent(); if (_recordingMarkerImage == null) throw new NullReferenceException("Recording Marker does not have an Image Component attached, system cannot work without it"); _markerInitialAlpha = _recordingMarkerImage.color.a; } /// /// Adds a character to the list of known characters if it does not already exist. /// /// The character to add. public void AddCharacter(Character character) { if (!HasCharacter(character.characterName)) _characters.Add(character); } /// /// Checks if a character with the given name exists in the list of known characters. /// /// The name of the character to check. /// True if the character exists, false otherwise. public bool HasCharacter(string characterName) { return _characters.Any(character => character.characterName == characterName); } /// /// Handles the player speaking state change by updating the recording marker's visibility. /// /// Whether the player is currently speaking. private void OnPlayerSpeakingChanged(bool isSpeaking) { if (_recordingMarkerImage != null) _recordingMarkerImage = _recordingMarkerImage.WithColorValue(a: isSpeaking ? 1.0f : _markerInitialAlpha); else ConvaiLogger.Error("Image component not found on recording marker.", ConvaiLogger.LogCategory.Character); } /// /// Sets the active state of the recording marker. /// /// The active state to set. private void SetRecordingMarkerActive(bool active) { if (recordingMarker != null) recordingMarker.SetActive(active); else ConvaiLogger.Error("Recording marker GameObject is not assigned.", ConvaiLogger.LogCategory.Character); } /// /// Sets the active state of the UI instance. /// /// The active state to set. private void SetUIActive(bool active) { if (UIInstance != null) UIInstance.SetActive(active); else ConvaiLogger.Error("UI instance GameObject is not assigned.", ConvaiLogger.LogCategory.Character); } } }