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