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 private 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() { CancelInvoke(nameof(scoreBarActivator)); SceneOutcomeManager.Instance.progressbarCanvasGroup.alpha = 1; 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; } //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; // private AudioSource audioSource; // private Tween typewriterTween; // private Dictionary narrationMap; // private void Awake() // { // if (Instance != null && Instance != this) // { // Destroy(gameObject); // return; // } // Instance = this; //// DontDestroyOnLoad(gameObject); // 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) // { // 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 ? 39 : 50; // // 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; //}