using System.Collections.Generic; using UnityEngine; using TMPro; public class ObjectiveManager : MonoBehaviour { [System.Serializable] public class Objective { [TextArea] public string text; public bool completed; } public static ObjectiveManager Instance { get; private set; } [Header("UI")] public TextMeshProUGUI objectiveText; // Assign a TMP Text in Canvas [Tooltip("Prefix/suffix for visual flair")] public string prefix = "Objective: "; public string completedPrefix = "✔ "; public string incompletePrefix = "• "; [Header("Data")] public List objectives = new List(); public int activeIndex = 0; // Which objective is currently shown public bool autoAdvanceOnComplete = true; public List _queuedNextObjectives = null; private int _queuedNextStartIndex = 0; void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; } void Start() => RefreshUI(); // ----- Public API ----- public void SetSingle(string text) { objectives.Clear(); objectives.Add(new Objective { text = text, completed = false }); activeIndex = 0; RefreshUI(); } public void SetList(IEnumerable list, int startIndex = 0) { objectives.Clear(); foreach (var s in list) objectives.Add(new Objective { text = s, completed = false }); activeIndex = Mathf.Clamp(startIndex, 0, Mathf.Max(0, objectives.Count - 1)); RefreshUI(); } public void SetActive(int index) { activeIndex = Mathf.Clamp(index, 0, Mathf.Max(0, objectives.Count - 1)); RefreshUI(); } public void MarkComplete(int index) { if (index < 0 || index >= objectives.Count) return; objectives[index].completed = true; if (autoAdvanceOnComplete && index == activeIndex) Advance(); Debug.Log("Mark Completed"); RefreshUI(); } public void QueueNextList(IEnumerable list, int startIndex = 0) { _queuedNextObjectives = (list != null) ? new List(list) : null; _queuedNextStartIndex = startIndex; } public void Advance() { // If there is a next objective in the current list, just move to it. if (activeIndex + 1 < objectives.Count) { activeIndex++; RefreshUI(); return; } // We are at (or beyond) the last item of the current list. // If a next list was queued, switch to it now. if (_queuedNextObjectives != null && _queuedNextObjectives.Count > 0) { SetList(_queuedNextObjectives, _queuedNextStartIndex); _queuedNextObjectives = null; _queuedNextStartIndex = 0; RefreshUI(); return; } // No queued list—stay on the last item. RefreshUI(); } //public void Advance() //{ // // Jump to next incomplete objective if any // for (int i = activeIndex + 1; i < objectives.Count; i++) // { // if (!objectives[i].completed) // { // activeIndex = i; // RefreshUI(); // return; // } // } // // --- Only when EVERYTHING is completed, switch to queued next list (if any) // bool allCompleted = objectives.Count == 0 || objectives.TrueForAll(o => o.completed); // if (allCompleted && _queuedNextObjectives != null && _queuedNextObjectives.Count > 0) // { // SetList(_queuedNextObjectives, _queuedNextStartIndex); // _queuedNextObjectives = null; // _queuedNextStartIndex = 0; // RefreshUI(); // return; // } // // Nothing left → keep last shown as completed // RefreshUI(); //} //public void Advance() //{ // // Jump to next incomplete objective if any // for (int i = activeIndex + 1; i < objectives.Count; i++) // { // if (!objectives[i].completed) { activeIndex = i; RefreshUI(); return; } // } // // Nothing left → keep last shown as completed // RefreshUI(); //} public void RefreshUI() { if (objectiveText == null) return; if (objectives.Count == 0) { objectiveText.text = ""; return; } var o = objectives[Mathf.Clamp(activeIndex, 0, objectives.Count - 1)]; var statePrefix = o.completed ? completedPrefix : incompletePrefix; objectiveText.text = prefix + statePrefix + o.text; } }