using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using KairoEngine.Core; using Sirenix.OdinInspector; using KairoEngine.UI; using KairoEngine.StorySystem; namespace KairoEngine.StorySystem.UI { [HideMonoScript] public class StoryViewUI : SerializedMonoBehaviour, IUiSystemElement { public string storyName = "Storyline"; public Transform panel; [BoxGroup("Story Lines")]public bool showLines = false; [BoxGroup("Story Lines")] public bool skipEmptyLines = true; [BoxGroup("Story Lines"), ShowIf("@showLines")] public bool showMultipleLines = true; [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public bool destroyLinesAfterPath = true; [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public GameObject storyLinePrefab; [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public Transform lineContainer; [BoxGroup("Story Lines"), ShowIf("@showLines && !showMultipleLines")] public StoryViewText lineText; [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public ScrollRect scrollRect = null; [BoxGroup("Story Branches")] public bool showBranches = true; [BoxGroup("Story Branches"), ShowIf("@showBranches")] public bool hidePanelAfterChoice = true; [BoxGroup("Story Branches"), ShowIf("@showBranches")] public GameObject storyBranchPrefab; [BoxGroup("Story Branches"), ShowIf("@showBranches")] public Transform branchContainer; [BoxGroup("Story Branches"), ShowIf("@showBranches")] public int prePopulateButtons = 0; [BoxGroup("Portraits")] public bool usePortraits = false; [BoxGroup("Portraits"), ShowIf("@usePortraits")] public Image portraitImage; [BoxGroup("Portraits"), ShowIf("@usePortraits")] public GameObject portraitContainer; [BoxGroup("Portraits"), ShowInInspector, PropertySpace(4,2), ShowIf("@usePortraits")] public Dictionary portraits = new Dictionary(); private List buttons; private StoryStepData lastBranch; private List lines = new List(); private bool isVisible = false; void Awake() { // Test if all variables are present if(panel == null) Debug.LogError("Panel is missing in StoryViewUI", this.gameObject); if(showLines && storyLinePrefab == null) Debug.LogError("StoryViewUI is missing a Story line Prefab", this.gameObject); if(showLines && lineContainer == null) Debug.LogError("StoryViewUI is missing a Story line Container", this.gameObject); if(showBranches && storyBranchPrefab == null) Debug.LogError("StoryViewUI is missing a Story Branch Prefab", this.gameObject); if(showBranches && branchContainer == null) Debug.LogError("StoryViewUI is missing a Story Branch Container", this.gameObject); } void Start() { if(buttons != null) { for (int i = 0; i < buttons.Count; i++) Destroy(buttons[i]); buttons.Clear(); } else buttons = new List(); //GameObject[] oldButtons = null; //if(branchContainer != null) oldButtons = branchContainer.gameObject.GetComponentsInChildren(); // if(oldButtons != null) // { // for (int i = 0; i < oldButtons.Length; i++) Destroy(oldButtons[i]); // } for (int i = 0; i < prePopulateButtons; i++) { GameObject obj = Instantiate(storyBranchPrefab, branchContainer); obj.name = obj.name.Replace("(Clone)", ""); obj.SetActive(false); buttons.Add(obj); } } void OnEnable() { EventManager.broadcast.StartListening(storyName, OnStoryStep); UiManager.RegisterElement("StoryView", this, this.transform, isVisible); } void OnDisable() { EventManager.broadcast.StopListening(storyName, OnStoryStep); UiManager.UnregisterElement(this); } private void OnStoryStep(StoryStepData storyStep) { if(skipEmptyLines) { if(storyStep.text == "" && storyStep.branches == null) return; } switch (storyStep.category) { case StoryStepType.Line: if(showLines) ShowStoryLine(storyStep); break; case StoryStepType.Branch: if(showBranches) ShowStoryBranch(storyStep); break; case StoryStepType.Path: ShowStoryPath(storyStep); break; default: break; } } private void ShowStoryLine(StoryStepData storyStep) { if(showLines == false) return; ShowPanel(); if(showMultipleLines) { GameObject obj = Instantiate(storyLinePrefab, lineContainer); obj.name = obj.name.Replace("(Clone)", ""); StoryViewText line = obj.GetComponent(); line.Setup(storyStep); lines.Add(obj); StartCoroutine(AutoScroll()); } else lineText.Setup(storyStep); if(usePortraits) ShowPortrait(storyStep); } private void ShowStoryBranch(StoryStepData storyStep) { if(buttons != null) { for (int i = 0; i < buttons.Count; i++) { //Destroy(buttons[i]); buttons[i].SetActive(false); } } buttons = new List(); ShowPanel(); for (int i = 0; i < storyStep.branches.Count; i++) { GameObject obj; if(buttons.Count > i) { obj = buttons[i]; obj.SetActive(true); } else { obj = Instantiate(storyBranchPrefab, branchContainer); obj.name = obj.name.Replace("(Clone)", ""); } StoryViewButton btn = obj.GetComponent(); btn.Init(storyName, storyStep, i, this); buttons.Add(obj); StartCoroutine(AutoScroll()); } lastBranch = storyStep; } private void ShowStoryPath(StoryStepData storyStep) { if(lastBranch == null) return; if(hidePanelAfterChoice) Hide(); foreach (var btn in buttons) Destroy(btn); buttons = new List(); lastBranch = null; if(destroyLinesAfterPath) foreach (var line in lines) Destroy(line); } private void ShowPortrait(StoryStepData storyStep) { var s = storyStep.text; var name = s.IndexOf(" ") > -1 ? s.Substring(0,s.IndexOf(" ")) : s; if (name.EndsWith(":")) { name = name.Remove(name.Length - 1, 1); foreach(KeyValuePair keyValue in portraits) { string key = keyValue.Key; if(key == name) { Sprite sprite = keyValue.Value; portraitImage.sprite = sprite; portraitContainer.SetActive(true); return; } } } portraitContainer.SetActive(false); } public void ButtonClicked(StoryStepData storyStep) { //Debug.Log("Button clicked"); if(hidePanelAfterChoice) UiManager.HideElement(this); } public void Show() { isVisible = true; ShowPanel(); } public void Hide() { isVisible = false; panel.gameObject.SetActive(false); } public bool IsVisible() => isVisible; private void ShowPanel() { if(isVisible) panel.gameObject.SetActive(true); } private IEnumerator AutoScroll() { if(lineContainer != null) LayoutRebuilder.ForceRebuildLayoutImmediate(lineContainer.GetComponent()); yield return new WaitForEndOfFrame(); yield return new WaitForEndOfFrame(); if(scrollRect != null) scrollRect.verticalNormalizedPosition = 0; } } }