public virtual void OnGUI() { if (mode == Mode.Idle) { return; } PageStyle pageStyle = Game.GetInstance().activePageStyle; if (pageStyle == null) { return; } GUIStyle boxStyle = pageStyle.boxStyle; GUIStyle headerStyle = pageStyle.GetScaledHeaderStyle(); GUIStyle footerStyle = pageStyle.GetScaledFooterStyle(); GUIStyle sayStyle = pageStyle.GetScaledSayStyle(); GUIStyle optionStyle = pageStyle.GetScaledOptionStyle(); GUIStyle optionAlternateStyle = pageStyle.GetScaledOptionAlternateStyle(); Rect outerRect; Layout tempLayout; Game game = Game.GetInstance(); if (mode == Mode.Choose && game.centerChooseMenu) { // Position the Choose menu in middle of screen // The width is controlled by game.chooseMenuWidth // The height is automatically fitted to the text content Vector2 pageScale = new Vector2(game.chooseMenuWidth, 0.5f); PageController.ScreenRect screenRect = PageController.CalcScreenRect(pageScale, PageController.PagePosition.Middle); outerRect = PageController.CalcPageRect(screenRect); tempLayout = PageController.Layout.FitToMiddle; } else { outerRect = pageRect; tempLayout = layout; } Rect originalRect = outerRect; Rect innerRect = CalcInnerRect(outerRect); // Calculate height of each section float headerHeight = CalcHeaderHeight(innerRect.width); float footerHeight = CalcFooterHeight(innerRect.width); float storyHeight = CalcStoryHeight(innerRect.width); float optionsHeight = CalcOptionsHeight(innerRect.width); float contentHeight = headerHeight + footerHeight + storyHeight + optionsHeight; // Adjust outer rect position based on alignment settings switch (tempLayout) { case Layout.FullSize: outerRect.height = Mathf.Max(outerRect.height, contentHeight + (boxStyle.padding.top + boxStyle.padding.bottom)); outerRect.y = Mathf.Min(outerRect.y, Screen.height - outerRect.height); break; case Layout.FitToTop: outerRect.height = contentHeight + (boxStyle.padding.top + boxStyle.padding.bottom); outerRect.y = originalRect.yMin; break; case Layout.FitToMiddle: outerRect.height = contentHeight + (boxStyle.padding.top + boxStyle.padding.bottom); outerRect.y = originalRect.center.y - outerRect.height / 2; break; case Layout.FitToBottom: outerRect.height = contentHeight + (boxStyle.padding.top + boxStyle.padding.bottom); outerRect.y = originalRect.yMax - outerRect.height; break; } innerRect = CalcInnerRect(outerRect); // Draw box Rect boxRect = outerRect; boxRect.height = contentHeight + (boxStyle.padding.top + boxStyle.padding.bottom); if (tempLayout == Layout.FullSize) { boxRect.height = Mathf.Max(boxRect.height, originalRect.height); } GUI.Box(boxRect, "", boxStyle); // Draw header label Rect headerRect = innerRect; headerRect.height = headerHeight; if (headerHeight > 0) { GUI.Label(headerRect, headerText, headerStyle); } // Draw say label Rect storyRect = innerRect; storyRect.y += headerHeight; storyRect.height = storyHeight; GUI.Label(storyRect, displayedStoryText, sayStyle); // Draw footer label Rect footerRect = innerRect; footerRect.y += storyHeight; footerRect.height = footerHeight; if (footerHeight > 0) { GUI.Label(footerRect, footerText, footerStyle); } if (!FinishedWriting()) { return; } // Input handling if (mode == Mode.Say) { // Player can continue by clicking anywhere if (quickContinueTimer == 0 && (Input.GetMouseButtonUp(0) || Input.anyKeyDown) && continueAction != null) { deferredAction = continueAction; } } else if (mode == Mode.Choose) { // Draw option buttons Rect buttonRect = innerRect; buttonRect.y += headerHeight + storyHeight; bool alternateRow = false; foreach (Option option in options) { GUIContent buttonContent = new GUIContent(option.optionText); buttonRect.height = optionStyle.CalcHeight(buttonContent, innerRect.width); // Select style for odd/even colored rows GUIStyle style; if (alternateRow) { style = optionAlternateStyle; } else { style = optionStyle; } alternateRow = !alternateRow; if (GUI.Button(buttonRect, buttonContent, style)) { if (option.optionAction != null) { // We can't execute the option action yet because OnGUI // may be called multiple times during a frame, and it's // not permitted to modify GUI elements within a frame. // We defer executing the action until OnGUI has completed. deferredAction = option.optionAction; break; } } buttonRect.y += buttonRect.height; } } if (Event.current.type == EventType.Repaint) { if (deferredAction != null) { Game.GetInstance().PlayButtonClick(); Action tempAction = deferredAction; displayedStoryText = ""; originalStoryText = ""; deferredAction = null; if (mode == Mode.Choose) { options.Clear(); // Reset to idle, but calling action may set this again mode = Mode.Idle; CommandQueue commandQueue = Game.GetInstance().commandQueue; commandQueue.CallCommandMethod(tempAction); } else if (mode == Mode.Say) { // Reset to idle, but calling action may set this again mode = Mode.Idle; // Execute next command tempAction(); } } } }