private static void CreateDialog(string text, Character speaker, IEnumerable <string> options, int[] closingOptions, string spriteIdentifier = null, ConversationAction actionInstance = null, UInt16?actionId = null, bool fadeToBlack = false, DialogTypes dialogType = DialogTypes.Regular, bool continueConversation = false) { Debug.Assert(actionInstance == null || actionId == null); shouldFadeToBlack = fadeToBlack; if (lastMessageBox != null && !lastMessageBox.Closed && GUIMessageBox.MessageBoxes.Contains(lastMessageBox)) { if (actionId != null && lastMessageBox.UserData is Pair <string, ushort> userData) { if (userData.Second == actionId) { return; } lastMessageBox.UserData = new Pair <string, ushort>("ConversationAction", actionId.Value); } GUIListBox conversationList = lastMessageBox.FindChild("conversationlist", true) as GUIListBox; Debug.Assert(conversationList != null); // gray out the last text block if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement) { if (lastElement.FindChild("text", true) is GUITextBlock textLayout) { textLayout.OverrideTextColor(Color.DarkGray * 0.8f); } } List <GUIButton> extraButtons = CreateConversation(conversationList, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier)); AssignActionsToButtons(extraButtons, lastMessageBox); RecalculateLastMessage(conversationList, true); conversationList.ScrollToEnd(0.5f); lastMessageBox.SetBackgroundIcon(EventSet.GetEventSprite(spriteIdentifier)); return; } var(relative, min) = GetSizes(dialogType); GUIMessageBox messageBox = new GUIMessageBox(string.Empty, string.Empty, new string[0], relativeSize: relative, minSize: min, type: GUIMessageBox.Type.InGame, backgroundIcon: EventSet.GetEventSprite(spriteIdentifier)) { UserData = "ConversationAction" }; lastMessageBox = messageBox; messageBox.InnerFrame.ClearChildren(); messageBox.AutoClose = false; GUI.Style.Apply(messageBox.InnerFrame, "DialogBox"); if (actionInstance != null) { lastActiveAction = actionInstance; actionInstance.dialogBox = messageBox; } else { messageBox.UserData = new Pair <string, UInt16>("ConversationAction", actionId.Value); } int padding = GUI.IntScale(16); GUIListBox listBox = new GUIListBox(new RectTransform(messageBox.InnerFrame.Rect.Size - new Point(padding * 2), messageBox.InnerFrame.RectTransform, Anchor.Center), style: null) { KeepSpaceForScrollBar = true, HoverCursor = CursorState.Default, UserData = "conversationlist" }; List <GUIButton> buttons = CreateConversation(listBox, text, speaker, options, string.IsNullOrWhiteSpace(spriteIdentifier)); AssignActionsToButtons(buttons, messageBox); RecalculateLastMessage(listBox, false); messageBox.InnerFrame.RectTransform.MinSize = new Point(0, Math.Max(listBox.RectTransform.MinSize.Y + padding * 2, (int)(100 * GUI.yScale))); var shadow = new GUIFrame(new RectTransform(messageBox.InnerFrame.Rect.Size + new Point(padding * 4), messageBox.InnerFrame.RectTransform, Anchor.Center), style: "OuterGlow") { Color = Color.Black * 0.7f }; shadow.SetAsFirstChild(); void RecalculateLastMessage(GUIListBox conversationList, bool append) { if (conversationList.Content.Children.LastOrDefault() is GUILayoutGroup lastElement) { GUILayoutGroup textLayout = lastElement.GetChild <GUILayoutGroup>(); if (lastElement.Rect.Size.Y < textLayout.Rect.Size.Y && !append) { lastElement.RectTransform.MinSize = textLayout.Rect.Size; } if (textLayout != null) { int textHeight = textLayout.Children.Sum(c => c.Rect.Height); textLayout.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, textHeight); textLayout.Recalculate(); } int sumHeight = lastElement.Children.Sum(c => c.Rect.Height); lastElement.RectTransform.MaxSize = new Point(lastElement.RectTransform.MaxSize.X, sumHeight); lastElement.Recalculate(); conversationList.RecalculateChildren(); if (!append || textLayout == null) { return; } foreach (GUIComponent child in textLayout.Children) { conversationList.UpdateScrollBarSize(); float wait = conversationList.BarSize < 1.0f ? 0.5f : 0.0f; if (child is GUITextBlock) { child.FadeIn(wait, 0.5f); } if (child is GUIButton btn) { btn.FadeIn(wait, 1.0f); btn.TextBlock.FadeIn(wait, 0.5f); } } } } void AssignActionsToButtons(List <GUIButton> optionButtons, GUIMessageBox target) { if (!options.Any()) { GUIButton closeButton = new GUIButton(new RectTransform(Vector2.One, target.InnerFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest) { MaxSize = new Point(GUI.IntScale(24)), MinSize = new Point(24), AbsoluteOffset = new Point(GUI.IntScale(48), GUI.IntScale(16)) }, style: "GUIButtonVerticalArrow") { UserData = "ContinueButton", IgnoreLayoutGroups = true, Bounce = true, OnClicked = (btn, userdata) => { if (actionInstance != null) { actionInstance.selectedOption = 0; } else if (actionId.HasValue) { SendResponse(actionId.Value, 0); } if (!continueConversation) { target.Close(); } else { btn.Frame.FadeOut(0.33f, true); } return(true); } }; closeButton.Children.ForEach(child => child.SpriteEffects = SpriteEffects.FlipVertically); closeButton.Frame.FadeIn(0.5f, 0.5f); closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down); } for (int i = 0; i < optionButtons.Count; i++) { optionButtons[i].UserData = i; optionButtons[i].OnClicked += (btn, userdata) => { int selectedOption = (userdata as int?) ?? 0; if (actionInstance != null) { actionInstance.selectedOption = selectedOption; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } btn.ExternalHighlight = true; return(true); } if (actionId.HasValue) { SendResponse(actionId.Value, selectedOption); btn.CanBeFocused = false; btn.ExternalHighlight = true; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } return(true); } //should not happen return(false); }; if (closingOptions.Contains(i)) { optionButtons[i].OnClicked += target.Close; } } } }
void AssignActionsToButtons(List <GUIButton> optionButtons, GUIMessageBox target) { if (!options.Any()) { GUIButton closeButton = new GUIButton(new RectTransform(Vector2.One, target.InnerFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest) { MaxSize = new Point(GUI.IntScale(24)), MinSize = new Point(24), AbsoluteOffset = new Point(GUI.IntScale(48), GUI.IntScale(16)) }, style: "GUIButtonVerticalArrow") { UserData = "ContinueButton", IgnoreLayoutGroups = true, Bounce = true, OnClicked = (btn, userdata) => { if (actionInstance != null) { actionInstance.selectedOption = 0; } else if (actionId.HasValue) { SendResponse(actionId.Value, 0); } if (!continueConversation) { target.Close(); } else { btn.Frame.FadeOut(0.33f, true); } return(true); } }; double allowCloseTime = Timing.TotalTime + 0.5; closeButton.Children.ForEach(child => child.SpriteEffects = SpriteEffects.FlipVertically); closeButton.Frame.FadeIn(0.5f, 0.5f); closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down); InputType?closeInput = null; if (GameMain.Config.KeyBind(InputType.Use).MouseButton == MouseButton.None) { closeInput = InputType.Use; } else if (GameMain.Config.KeyBind(InputType.Select).MouseButton == MouseButton.None) { closeInput = InputType.Select; } if (closeInput.HasValue) { closeButton.ToolTip = TextManager.ParseInputTypes($"{TextManager.Get("Close")} ([InputType.{closeInput.Value}])"); closeButton.OnAddedToGUIUpdateList += (GUIComponent component) => { if (Timing.TotalTime > allowCloseTime && PlayerInput.KeyHit(closeInput.Value)) { GUIButton btn = component as GUIButton; btn?.OnClicked(btn, btn.UserData); btn?.Flash(GUI.Style.Green); } }; } } for (int i = 0; i < optionButtons.Count; i++) { optionButtons[i].UserData = i; optionButtons[i].OnClicked += (btn, userdata) => { int selectedOption = (userdata as int?) ?? 0; if (actionInstance != null) { actionInstance.selectedOption = selectedOption; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } btn.ExternalHighlight = true; return(true); } if (actionId.HasValue) { SendResponse(actionId.Value, selectedOption); btn.CanBeFocused = false; btn.ExternalHighlight = true; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } return(true); } //should not happen return(false); }; if (closingOptions.Contains(i)) { optionButtons[i].OnClicked += target.Close; } } }
void AssignActionsToButtons(List <GUIButton> optionButtons, GUIMessageBox target) { if (!options.Any()) { GUIButton closeButton = new GUIButton(new RectTransform(Vector2.One, target.InnerFrame.RectTransform, Anchor.BottomRight, scaleBasis: ScaleBasis.Smallest) { MaxSize = new Point(GUI.IntScale(24)), MinSize = new Point(24), AbsoluteOffset = new Point(GUI.IntScale(48), GUI.IntScale(16)) }, style: "GUIButtonVerticalArrow") { UserData = "ContinueButton", IgnoreLayoutGroups = true, Bounce = true, OnClicked = (btn, userdata) => { if (actionInstance != null) { actionInstance.selectedOption = 0; } else if (actionId.HasValue) { SendResponse(actionId.Value, 0); } if (!continueConversation) { target.Close(); } else { btn.Frame.FadeOut(0.33f, true); } return(true); } }; closeButton.Children.ForEach(child => child.SpriteEffects = SpriteEffects.FlipVertically); closeButton.Frame.FadeIn(0.5f, 0.5f); closeButton.SlideIn(0.5f, 0.33f, 16, SlideDirection.Down); } for (int i = 0; i < optionButtons.Count; i++) { optionButtons[i].UserData = i; optionButtons[i].OnClicked += (btn, userdata) => { int selectedOption = (userdata as int?) ?? 0; if (actionInstance != null) { actionInstance.selectedOption = selectedOption; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } btn.ExternalHighlight = true; return(true); } if (actionId.HasValue) { SendResponse(actionId.Value, selectedOption); btn.CanBeFocused = false; btn.ExternalHighlight = true; foreach (GUIButton otherButton in optionButtons) { otherButton.CanBeFocused = false; if (otherButton != btn) { otherButton.TextBlock.OverrideTextColor(Color.DarkGray * 0.8f); } } return(true); } //should not happen return(false); }; if (closingOptions.Contains(i)) { optionButtons[i].OnClicked += target.Close; } } }