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 narrationDatabase; [Header("Subtitle Settings")] public TextMeshProUGUI subtitleText; public float charDelay = 0.03f; public float lineGroupDelay = 2.5f; // Fallback if no custom delay provided public AudioSource audioSource; private Tween typewriterTween; private Dictionary narrationMap; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; audioSource = gameObject.AddComponent(); audioSource.playOnAwake = false; narrationMap = new Dictionary(); 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) { InstructionManager.Instance.instructionBG.SetActive(true); SceneOutcomeManager.Instance.progressbarCanvasGroup.alpha = 0; 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; subtitleText.font = LanguageManager.Instance.GetCurrentFont(); subtitleText.fontSize = isArabic ? 38 : 50; subtitleText.overflowMode = isArabic ? TextOverflowModes.Page : TextOverflowModes.Overflow; subtitleText.isRightToLeftText = false; AppendSubtitle(subtitle, isArabic, narrationData); } Invoke(nameof(scoreBarActivator), clip.length); if (onComplete != null) StartCoroutine(InvokeAfterNarration(clip.length, onComplete)); } void scoreBarActivator() { Debug.Log("ScoreBarActivator"); CancelInvoke(nameof(scoreBarActivator)); if (SceneOutcomeManager.Instance.phishingEmailClicked == false) { Debug.Log("phishingEmailClicked == false"); SceneOutcomeManager.Instance.progressbarCanvasGroup.alpha = 1; InstructionManager.Instance.instructionBG.SetActive(false); } else { Debug.Log("phishingEmailClicked == true"); InstructionManager.Instance.instructionBG.SetActive(false); } } private void AppendSubtitle(string fullText, bool isArabic, NarrationData narrationData) { typewriterTween?.Kill(); subtitleText.text = ""; if (isArabic) { StartCoroutine(ShowArabicByPages(fullText, narrationData)); } else { StartCoroutine(ShowLinesWithCustomDelay(fullText, narrationData)); } } private IEnumerator ShowLinesWithCustomDelay(string fullText, NarrationData narrationData) { subtitleText.text = ""; string[] lines = fullText.Split(new[] { '\n' }, System.StringSplitOptions.RemoveEmptyEntries); int length = lines.Length; for (int i = 0; i < length; i++) { subtitleText.text = lines[i]; subtitleText.ForceMeshUpdate(); float delay = (narrationData != null && i < narrationData.lineDelays.Count) ? narrationData.lineDelays[i] : lineGroupDelay; yield return new WaitForSeconds(delay); } //if (length > 1) // SceneOutcomeManager.Instance.progressbarCanvasGroup.alpha = 1; } private IEnumerator ShowArabicByPages(string fullText, NarrationData narrationData) { subtitleText.text = fullText; subtitleText.ForceMeshUpdate(); int totalPages = subtitleText.textInfo.pageCount; for (int i = 1; i <= totalPages; i++) { subtitleText.pageToDisplay = i; float delay = (narrationData != null && (i - 1) < narrationData.arabicLineDelays.Count) ? narrationData.arabicLineDelays[(i - 1)] : lineGroupDelay; Debug.Log("arabic delay is: " + delay); yield return new WaitForSeconds(delay); } //SceneOutcomeManager.Instance.progressbarCanvasGroup.alpha = 1; } 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(); StopAllCoroutines(); } public void ClearSubtitles() { typewriterTween?.Kill(); subtitleText.text = ""; StopAllCoroutines(); } public bool IsPlaying => audioSource.isPlaying; }