/** * Modifies the PageController to use a rect defined by the bounds and the current camera transform */ public void UpdatePageRect() { // Y increases down the screen in GUI space, so top left is rect origin Vector3 topLeft = transform.position + pageBounds.center; topLeft.x -= pageBounds.extents.x; topLeft.y += pageBounds.extents.y; Vector3 bottomRight = transform.position + pageBounds.center; bottomRight.x += pageBounds.extents.x; bottomRight.y -= pageBounds.extents.y; Vector2 tl = Camera.main.WorldToScreenPoint(topLeft); Vector2 br = Camera.main.WorldToScreenPoint(bottomRight); PageController.ScreenRect screenRect = new PageController.ScreenRect(); screenRect.x1 = (tl.x / Screen.width); screenRect.y1 = 1f - (tl.y / Screen.height); screenRect.x2 = (br.x / Screen.width); screenRect.y2 = 1f - (br.y / Screen.height); PageController page = Game.GetInstance().pageController; page.pageRect = PageController.CalcPageRect(screenRect); page.layout = layout; }
/** * Sets the screen space rectangle used to display the story text. * The rectangle coordinates are in normalized screen space. e.g. x1 = 0 (left), y1 = 0 (top) x2 = 1 (right) y2 = 1 (bottom). * The origin is at the top left of the screen. * This method returns immediately but it queues an asynchronous command for later execution. * @param x1 Page rect left coordinate in normalized screen space coords [0..1] * @param y1 Page rect top coordinate in normalized screen space coords [0..1 * @param x2 Page rect right coordinate in normalized screen space coords [0..1] * @param y2 Page rect bottom coordinate in normalized screen space coords [0..1] * @param pageLayout Layout mode for positioning page within the rect. */ public static void SetPageRect(float x1, float y1, float x2, float y2, PageController.Layout pageLayout = PageController.Layout.FullSize) { PageController.ScreenRect screenRect = new PageController.ScreenRect(); screenRect.x1 = x1; screenRect.y1 = y1; screenRect.x2 = x2; screenRect.y2 = y2; SetPageRect(screenRect, pageLayout); }
/** * Display story page at the bottom of the screen. * This method returns immediately but it queues an asynchronous command for later execution. * @param scaleX Scales the width of the Page [0..1]. 1 = full screen width. * @param scaleY Scales the height of the Page [0..1]. 1 = full screen height. * @param pageLayout Controls how the Page is positioned and sized based on the displayed content. */ public static void SetPageBottom(float scaleX, float scaleY, PageController.Layout pageLayout) { PageController.ScreenRect screenRect = PageController.CalcScreenRect(new Vector2(scaleX, scaleY), PageController.PagePosition.Bottom); SetPageRect(screenRect, pageLayout); }
/** * Sets the screen space rectangle used to display the story text using a ScreenRect object. * This method returns immediately but it queues an asynchronous command for later execution. * @param screenRect A ScreenRect object which defines a rect in normalized screen space coordinates. */ public static void SetPageRect(PageController.ScreenRect screenRect, PageController.Layout pageLayout = PageController.Layout.FullSize) { CommandQueue commandQueue = Game.GetInstance().commandQueue; commandQueue.AddCommand(new Command.SetPageRect(screenRect, pageLayout)); }
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(); } } } }