StoryViewUI.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using KairoEngine.Core;
  6. using Sirenix.OdinInspector;
  7. using KairoEngine.UI;
  8. using KairoEngine.StorySystem;
  9. namespace KairoEngine.StorySystem.UI
  10. {
  11. [HideMonoScript]
  12. public class StoryViewUI : SerializedMonoBehaviour, IUiSystemElement
  13. {
  14. public string storyName = "Storyline";
  15. public Transform panel;
  16. [BoxGroup("Story Lines")]public bool showLines = false;
  17. [BoxGroup("Story Lines")] public bool skipEmptyLines = true;
  18. [BoxGroup("Story Lines"), ShowIf("@showLines")] public bool showMultipleLines = true;
  19. [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public bool destroyLinesAfterPath = true;
  20. [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public GameObject storyLinePrefab;
  21. [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public Transform lineContainer;
  22. [BoxGroup("Story Lines"), ShowIf("@showLines && !showMultipleLines")] public StoryViewText lineText;
  23. [BoxGroup("Story Lines"), ShowIf("@showLines && showMultipleLines")] public ScrollRect scrollRect = null;
  24. [BoxGroup("Story Branches")] public bool showBranches = true;
  25. [BoxGroup("Story Branches"), ShowIf("@showBranches")] public bool hidePanelAfterChoice = true;
  26. [BoxGroup("Story Branches"), ShowIf("@showBranches")] public GameObject storyBranchPrefab;
  27. [BoxGroup("Story Branches"), ShowIf("@showBranches")] public Transform branchContainer;
  28. [BoxGroup("Story Branches"), ShowIf("@showBranches")] public int prePopulateButtons = 0;
  29. [BoxGroup("Portraits")] public bool usePortraits = false;
  30. [BoxGroup("Portraits"), ShowIf("@usePortraits")] public Image portraitImage;
  31. [BoxGroup("Portraits"), ShowIf("@usePortraits")] public GameObject portraitContainer;
  32. [BoxGroup("Portraits"), ShowInInspector, PropertySpace(4,2), ShowIf("@usePortraits")]
  33. public Dictionary<string, Sprite> portraits = new Dictionary<string, Sprite>();
  34. private List<GameObject> buttons;
  35. private StoryStepData lastBranch;
  36. private List<GameObject> lines = new List<GameObject>();
  37. private bool isVisible = false;
  38. void Awake()
  39. {
  40. // Test if all variables are present
  41. if(panel == null) Debug.LogError("Panel is missing in StoryViewUI", this.gameObject);
  42. if(showLines && storyLinePrefab == null) Debug.LogError("StoryViewUI is missing a Story line Prefab", this.gameObject);
  43. if(showLines && lineContainer == null) Debug.LogError("StoryViewUI is missing a Story line Container", this.gameObject);
  44. if(showBranches && storyBranchPrefab == null) Debug.LogError("StoryViewUI is missing a Story Branch Prefab", this.gameObject);
  45. if(showBranches && branchContainer == null) Debug.LogError("StoryViewUI is missing a Story Branch Container", this.gameObject);
  46. }
  47. void Start()
  48. {
  49. if(buttons != null)
  50. {
  51. for (int i = 0; i < buttons.Count; i++) Destroy(buttons[i]);
  52. buttons.Clear();
  53. }
  54. else buttons = new List<GameObject>();
  55. //GameObject[] oldButtons = null;
  56. //if(branchContainer != null) oldButtons = branchContainer.gameObject.GetComponentsInChildren<GameObject>();
  57. // if(oldButtons != null)
  58. // {
  59. // for (int i = 0; i < oldButtons.Length; i++) Destroy(oldButtons[i]);
  60. // }
  61. for (int i = 0; i < prePopulateButtons; i++)
  62. {
  63. GameObject obj = Instantiate(storyBranchPrefab, branchContainer);
  64. obj.name = obj.name.Replace("(Clone)", "");
  65. obj.SetActive(false);
  66. buttons.Add(obj);
  67. }
  68. }
  69. void OnEnable()
  70. {
  71. EventManager.broadcast.StartListening(storyName, OnStoryStep);
  72. UiManager.RegisterElement("StoryView", this, this.transform, isVisible);
  73. }
  74. void OnDisable()
  75. {
  76. EventManager.broadcast.StopListening(storyName, OnStoryStep);
  77. UiManager.UnregisterElement(this);
  78. }
  79. private void OnStoryStep(StoryStepData storyStep)
  80. {
  81. if(skipEmptyLines)
  82. {
  83. if(storyStep.text == "" && storyStep.branches == null) return;
  84. }
  85. switch (storyStep.category)
  86. {
  87. case StoryStepType.Line:
  88. if(showLines) ShowStoryLine(storyStep);
  89. break;
  90. case StoryStepType.Branch:
  91. if(showBranches) ShowStoryBranch(storyStep);
  92. break;
  93. case StoryStepType.Path:
  94. ShowStoryPath(storyStep);
  95. break;
  96. default:
  97. break;
  98. }
  99. }
  100. private void ShowStoryLine(StoryStepData storyStep)
  101. {
  102. if(showLines == false) return;
  103. ShowPanel();
  104. if(showMultipleLines)
  105. {
  106. GameObject obj = Instantiate(storyLinePrefab, lineContainer);
  107. obj.name = obj.name.Replace("(Clone)", "");
  108. StoryViewText line = obj.GetComponent<StoryViewText>();
  109. line.Setup(storyStep);
  110. lines.Add(obj);
  111. StartCoroutine(AutoScroll());
  112. }
  113. else lineText.Setup(storyStep);
  114. if(usePortraits) ShowPortrait(storyStep);
  115. }
  116. private void ShowStoryBranch(StoryStepData storyStep)
  117. {
  118. if(buttons != null)
  119. {
  120. for (int i = 0; i < buttons.Count; i++)
  121. {
  122. //Destroy(buttons[i]);
  123. buttons[i].SetActive(false);
  124. }
  125. }
  126. buttons = new List<GameObject>();
  127. ShowPanel();
  128. for (int i = 0; i < storyStep.branches.Count; i++)
  129. {
  130. GameObject obj;
  131. if(buttons.Count > i)
  132. {
  133. obj = buttons[i];
  134. obj.SetActive(true);
  135. }
  136. else
  137. {
  138. obj = Instantiate(storyBranchPrefab, branchContainer);
  139. obj.name = obj.name.Replace("(Clone)", "");
  140. }
  141. StoryViewButton btn = obj.GetComponent<StoryViewButton>();
  142. btn.Init(storyName, storyStep, i, this);
  143. buttons.Add(obj);
  144. StartCoroutine(AutoScroll());
  145. }
  146. lastBranch = storyStep;
  147. }
  148. private void ShowStoryPath(StoryStepData storyStep)
  149. {
  150. if(lastBranch == null) return;
  151. if(hidePanelAfterChoice) Hide();
  152. foreach (var btn in buttons) Destroy(btn);
  153. buttons = new List<GameObject>();
  154. lastBranch = null;
  155. if(destroyLinesAfterPath) foreach (var line in lines) Destroy(line);
  156. }
  157. private void ShowPortrait(StoryStepData storyStep)
  158. {
  159. var s = storyStep.text;
  160. var name = s.IndexOf(" ") > -1
  161. ? s.Substring(0,s.IndexOf(" "))
  162. : s;
  163. if (name.EndsWith(":"))
  164. {
  165. name = name.Remove(name.Length - 1, 1);
  166. foreach(KeyValuePair<string, Sprite> keyValue in portraits)
  167. {
  168. string key = keyValue.Key;
  169. if(key == name)
  170. {
  171. Sprite sprite = keyValue.Value;
  172. portraitImage.sprite = sprite;
  173. portraitContainer.SetActive(true);
  174. return;
  175. }
  176. }
  177. }
  178. portraitContainer.SetActive(false);
  179. }
  180. public void ButtonClicked(StoryStepData storyStep)
  181. {
  182. //Debug.Log("Button clicked");
  183. if(hidePanelAfterChoice) UiManager.HideElement(this);
  184. }
  185. public void Show()
  186. {
  187. isVisible = true;
  188. ShowPanel();
  189. }
  190. public void Hide()
  191. {
  192. isVisible = false;
  193. panel.gameObject.SetActive(false);
  194. }
  195. public bool IsVisible() => isVisible;
  196. private void ShowPanel()
  197. {
  198. if(isVisible) panel.gameObject.SetActive(true);
  199. }
  200. private IEnumerator AutoScroll()
  201. {
  202. if(lineContainer != null)
  203. LayoutRebuilder.ForceRebuildLayoutImmediate(lineContainer.GetComponent<RectTransform>());
  204. yield return new WaitForEndOfFrame();
  205. yield return new WaitForEndOfFrame();
  206. if(scrollRect != null) scrollRect.verticalNormalizedPosition = 0;
  207. }
  208. }
  209. }