You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.4 KiB
C#
159 lines
4.4 KiB
C#
using UnityEngine;
|
|
using TMPro;
|
|
using DG.Tweening;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
|
|
public enum NarrationID
|
|
{
|
|
Intro,
|
|
NewEmail,
|
|
ScanEmail,
|
|
CorrectReportChoice,
|
|
CorrectIgnoreChoice,
|
|
WrongIgnoreChoice,
|
|
Feedback,
|
|
GameEnd
|
|
}
|
|
|
|
public class NarrationPlayer : MonoBehaviour
|
|
{
|
|
public static NarrationPlayer Instance { get; private set; }
|
|
|
|
[Header("Narration Assets")]
|
|
public List<NarrationData> narrationDatabase;
|
|
|
|
[Header("Subtitle Settings")]
|
|
public TextMeshProUGUI subtitleText;
|
|
public float charDelay = 0.03f;
|
|
|
|
private AudioSource audioSource;
|
|
private Tween typewriterTween;
|
|
private Dictionary<NarrationID, NarrationData> narrationMap;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
audioSource = gameObject.AddComponent<AudioSource>();
|
|
audioSource.playOnAwake = false;
|
|
|
|
narrationMap = new Dictionary<NarrationID, NarrationData>();
|
|
foreach (var data in narrationDatabase)
|
|
{
|
|
if (data != null && !narrationMap.ContainsKey(data.narrationID))
|
|
narrationMap[data.narrationID] = data;
|
|
}
|
|
}
|
|
|
|
public void PlayNarration(NarrationID id, System.Action onComplete = null)
|
|
{
|
|
if (!narrationMap.TryGetValue(id, out var narrationData))
|
|
{
|
|
Debug.LogWarning($"Narration not found for: {id}");
|
|
return;
|
|
}
|
|
|
|
bool isArabic = LanguageManager.Instance.IsArabic;
|
|
AudioClip clip = isArabic ? narrationData.arabicClip : narrationData.englishClip;
|
|
|
|
if (clip == null)
|
|
{
|
|
Debug.LogWarning($"Missing audio clip for {id} in language: {(isArabic ? "Arabic" : "English")}");
|
|
return;
|
|
}
|
|
|
|
if (audioSource.isPlaying)
|
|
audioSource.Stop();
|
|
|
|
audioSource.clip = clip;
|
|
audioSource.Play();
|
|
|
|
if (!string.IsNullOrEmpty(narrationData.localizationKey))
|
|
{
|
|
string rawSubtitle = LanguageManager.Instance.GetLocalizedText(narrationData.localizationKey);
|
|
string subtitle = isArabic
|
|
? ArabicFixerHelper.FixPreservingTags(rawSubtitle)
|
|
: rawSubtitle;
|
|
|
|
// TMP settings per language
|
|
subtitleText.font = LanguageManager.Instance.GetCurrentFont();
|
|
subtitleText.fontSize = isArabic ? 26 : 36;
|
|
// subtitleText.alignment = isArabic ? TextAlignmentOptions.Right : TextAlignmentOptions.Left;
|
|
subtitleText.overflowMode = TextOverflowModes.Page;
|
|
subtitleText.isRightToLeftText = false; // MUST be false with ArabicFixer
|
|
|
|
AppendSubtitle(subtitle, isArabic);
|
|
}
|
|
|
|
if (onComplete != null)
|
|
StartCoroutine(InvokeAfterNarration(clip.length, onComplete));
|
|
}
|
|
|
|
private void AppendSubtitle(string fullText, bool isArabic)
|
|
{
|
|
typewriterTween?.Kill();
|
|
subtitleText.text = "";
|
|
|
|
if (isArabic)
|
|
{
|
|
StartCoroutine(ShowArabicByPages(fullText));
|
|
return;
|
|
}
|
|
|
|
int totalLength = fullText.Length;
|
|
int currentIndex = 0;
|
|
|
|
typewriterTween = DOTween.To(() => currentIndex, x =>
|
|
{
|
|
currentIndex = x;
|
|
subtitleText.text = fullText.Substring(0, currentIndex);
|
|
subtitleText.ForceMeshUpdate();
|
|
subtitleText.pageToDisplay = subtitleText.textInfo.pageCount;
|
|
}, totalLength, totalLength * charDelay).SetEase(Ease.Linear);
|
|
}
|
|
|
|
private IEnumerator ShowArabicByPages(string fullText)
|
|
{
|
|
subtitleText.text = fullText;
|
|
subtitleText.ForceMeshUpdate();
|
|
|
|
int totalPages = subtitleText.textInfo.pageCount;
|
|
|
|
for (int i = 1; i <= totalPages; i++)
|
|
{
|
|
subtitleText.pageToDisplay = i;
|
|
yield return new WaitForSeconds(5f); // Adjust delay per page
|
|
}
|
|
}
|
|
|
|
private IEnumerator InvokeAfterNarration(float delay, System.Action callback)
|
|
{
|
|
yield return new WaitForSeconds(delay);
|
|
callback?.Invoke();
|
|
}
|
|
|
|
public void StopNarration()
|
|
{
|
|
if (audioSource.isPlaying)
|
|
audioSource.Stop();
|
|
|
|
typewriterTween?.Kill();
|
|
}
|
|
|
|
public void ClearSubtitles()
|
|
{
|
|
typewriterTween?.Kill();
|
|
subtitleText.text = "";
|
|
}
|
|
|
|
public bool IsPlaying => audioSource.isPlaying;
|
|
}
|