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);

            if (GUI.InputBlockingMenuOpen)
            {
                if (actionId.HasValue)
                {
                    SendIgnore(actionId.Value);
                }
                return;
            }

            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();
Esempio n. 2
0
        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;
                    }
                }
            }
        }