public CommonSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer, string templateListId, string previewTemplateId)
        {
            this.Widget        = widget;
            this.World         = world;
            this.WorldRenderer = worldRenderer;
            Editor             = widget.Parent.Get <EditorViewportControllerWidget>("MAP_EDITOR");
            Panel        = widget.Get <ScrollPanelWidget>(templateListId);
            ItemTemplate = Panel.Get <ScrollItemWidget>(previewTemplateId);
            Panel.Layout = new GridLayout(Panel);

            SearchTextField          = widget.Get <TextFieldWidget>("SEARCH_TEXTFIELD");
            SearchTextField.OnEscKey = () =>
            {
                SearchTextField.Text = "";
                SearchTextField.YieldKeyboardFocus();
                return(true);
            };

            var categorySelector = widget.Get <DropDownButtonWidget>("CATEGORIES_DROPDOWN");

            categorySelector.GetText = () =>
            {
                if (SelectedCategories.Count == 0)
                {
                    return("None");
                }

                if (!string.IsNullOrEmpty(searchFilter))
                {
                    return("Search Results");
                }

                if (SelectedCategories.Count == 1)
                {
                    return(SelectedCategories.First());
                }

                if (SelectedCategories.Count == allCategories.Length)
                {
                    return("All");
                }

                return("Multiple");
            };

            categorySelector.OnMouseDown = _ =>
            {
                if (SearchTextField != null)
                {
                    SearchTextField.YieldKeyboardFocus();
                }

                categorySelector.RemovePanel();
                categorySelector.AttachPanel(CreateCategoriesPanel(Panel));
            };
        }
Beispiel #2
0
 public void CloseChat()
 {
     chatChrome.Visible = false;
     chatText.YieldKeyboardFocus();
     chatOverlay.Visible = true;
     Ui.ResetTooltips();
 }
Beispiel #3
0
 public void CloseChat()
 {
     if (inDialog)
     {
         return;
     }
     chatChrome.Visible = false;
     chatText.YieldKeyboardFocus();
     chatOverlay.Visible = true;
 }
        public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat, Dictionary <string, MiniYaml> logicArgs)
        {
            this.orderManager = orderManager;
            this.modRules     = modData.DefaultRules;

            chatTraits = world.WorldActor.TraitsImplementing <INotifyChat>().ToArray();

            var players         = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot);
            var isObserver      = orderManager.LocalClient != null && orderManager.LocalClient.IsObserver;
            var isOnlyObserver  = isObserver && orderManager.LobbyInfo.Clients.All(c => c == orderManager.LocalClient || !c.IsObserver);
            var observersExist  = orderManager.LobbyInfo.Clients.Any(c => c.IsObserver);
            var alwaysDisabled  = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1;
            var disableTeamChat = alwaysDisabled || isOnlyObserver || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer)));
            var teamChat        = !disableTeamChat;

            tabCompletion.Commands = chatTraits.OfType <ChatCommands>().SelectMany(x => x.Commands.Keys).ToList();
            tabCompletion.Names    = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();

            var chatPanel = (ContainerWidget)widget;

            chatOverlay = chatPanel.GetOrNull <ContainerWidget>("CHAT_OVERLAY");
            if (chatOverlay != null)
            {
                chatOverlayDisplay  = chatOverlay.Get <ChatDisplayWidget>("CHAT_DISPLAY");
                chatOverlay.Visible = false;
            }

            chatChrome         = chatPanel.Get <ContainerWidget>("CHAT_CHROME");
            chatChrome.Visible = true;

            var chatMode = chatChrome.Get <ButtonWidget>("CHAT_MODE");

            chatMode.GetText = () => teamChat && !disableTeamChat ? "Team" : "All";
            chatMode.OnClick = () => teamChat ^= true;

            // Team chat is disabled if we are the only spectator
            // This changes as soon as a defeated player can talk in the spectator chat
            if (!alwaysDisabled && isOnlyObserver)
            {
                chatMode.IsDisabled = () =>
                {
                    if (world.IsGameOver)
                    {
                        return(true);
                    }

                    disableTeamChat = players.All(p => p.WinState == WinState.Undefined);
                    return(disableTeamChat);
                };
            }
            else if (!alwaysDisabled && world.LocalPlayer != null)
            {
                chatMode.IsDisabled = () =>
                {
                    if (world.IsGameOver)
                    {
                        return(true);
                    }

                    // Check if we are the only living team member
                    if (players.All(p => p.WinState != WinState.Undefined || !p.IsAlliedWith(world.LocalPlayer)))
                    {
                        disableTeamChat = true;
                        return(disableTeamChat);
                    }

                    // Still alive and nothing changed since the start
                    if (world.LocalPlayer.WinState == WinState.Undefined)
                    {
                        return(disableTeamChat);
                    }

                    // At this point our player is dead
                    // Allow to chat with existing spectators
                    if (observersExist)
                    {
                        disableTeamChat = false;
                        return(disableTeamChat);
                    }

                    // Or wait until another player died
                    disableTeamChat = players.All(p => p.WinState == WinState.Undefined);
                    return(disableTeamChat);
                };
            }
            else
            {
                chatMode.IsDisabled = () => disableTeamChat;
            }

            // Disable team chat after the game ended
            world.GameOver += () => disableTeamChat = true;

            chatText            = chatChrome.Get <TextFieldWidget>("CHAT_TEXTFIELD");
            chatText.MaxLength  = UnitOrders.ChatMessageMaxLength;
            chatText.OnEnterKey = () =>
            {
                var team = teamChat && !disableTeamChat;
                if (chatText.Text != "")
                {
                    if (!chatText.Text.StartsWith("/", StringComparison.Ordinal))
                    {
                        // This should never happen, but avoid a crash if it does somehow (chat will just stay open)
                        if (!isObserver && orderManager.LocalClient == null && world.LocalPlayer == null)
                        {
                            return(true);
                        }

                        var teamNumber = 0U;
                        if (team)
                        {
                            teamNumber = (isObserver || world.LocalPlayer.WinState != WinState.Undefined) ? uint.MaxValue : (uint)orderManager.LocalClient.Team;
                        }

                        orderManager.IssueOrder(Order.Chat(chatText.Text.Trim(), teamNumber));
                    }
                    else if (chatTraits != null)
                    {
                        var text = chatText.Text.Trim();
                        var from = world.IsReplay ? null : orderManager.LocalClient.Name;
                        foreach (var trait in chatTraits)
                        {
                            trait.OnChat(from, text);
                        }
                    }
                }

                chatText.Text = "";
                if (!isMenuChat)
                {
                    CloseChat();
                }

                return(true);
            };

            chatText.OnTabKey = () =>
            {
                var previousText = chatText.Text;
                chatText.Text           = tabCompletion.Complete(chatText.Text);
                chatText.CursorPosition = chatText.Text.Length;

                if (chatText.Text == previousText && !disableTeamChat)
                {
                    teamChat ^= true;
                }

                return(true);
            };

            chatText.OnEscKey = () =>
            {
                if (!isMenuChat)
                {
                    CloseChat();
                }
                else
                {
                    chatText.YieldKeyboardFocus();
                }

                return(true);
            };

            if (!isMenuChat)
            {
                var chatClose = chatChrome.Get <ButtonWidget>("CHAT_CLOSE");
                chatClose.OnClick += CloseChat;

                chatPanel.OnKeyPress = e =>
                {
                    if (e.Event == KeyInputEvent.Up)
                    {
                        return(false);
                    }

                    if (!chatChrome.IsVisible() && (e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER))
                    {
                        OpenChat();
                        return(true);
                    }

                    return(false);
                };
            }

            chatScrollPanel = chatChrome.Get <ScrollPanelWidget>("CHAT_SCROLLPANEL");
            chatTemplate    = chatScrollPanel.Get <ContainerWidget>("CHAT_TEMPLATE");
            chatScrollPanel.RemoveChildren();
            chatScrollPanel.ScrollToBottom();

            foreach (var chatLine in orderManager.ChatCache)
            {
                AddChatLine(chatLine.Name, chatLine.Color, chatLine.Text, chatLine.TextColor, true);
            }

            orderManager.AddChatLine += AddChatLineWrapper;

            chatText.IsDisabled = () => world.IsReplay && !Game.Settings.Debug.EnableDebugCommandsInReplays;

            if (!isMenuChat)
            {
                CloseChat();

                var keyListener = chatChrome.Get <LogicKeyListenerWidget>("KEY_LISTENER");
                keyListener.AddHandler(e =>
                {
                    if (e.Event == KeyInputEvent.Up || !chatText.IsDisabled())
                    {
                        return(false);
                    }

                    if ((e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER || e.Key == Keycode.ESCAPE) && e.Modifiers == Modifiers.None)
                    {
                        CloseChat();
                        return(true);
                    }

                    return(false);
                });
            }

            MiniYaml yaml;

            if (logicArgs.TryGetValue("ChatLineSound", out yaml))
            {
                chatLineSound = yaml.Value;
            }
        }
Beispiel #5
0
        public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat)
        {
            this.orderManager = orderManager;
            this.modRules     = modData.DefaultRules;

            chatTraits = world.WorldActor.TraitsImplementing <INotifyChat>().ToArray();

            var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot);

            disableTeamChat = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1 || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer)));
            teamChat        = !disableTeamChat;

            tabCompletion.Commands = chatTraits.OfType <ChatCommands>().SelectMany(x => x.Commands.Keys).ToList();
            tabCompletion.Names    = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();

            var chatPanel = (ContainerWidget)widget;

            chatOverlay = chatPanel.GetOrNull <ContainerWidget>("CHAT_OVERLAY");
            if (chatOverlay != null)
            {
                chatOverlayDisplay  = chatOverlay.Get <ChatDisplayWidget>("CHAT_DISPLAY");
                chatOverlay.Visible = false;
            }

            chatChrome         = chatPanel.Get <ContainerWidget>("CHAT_CHROME");
            chatChrome.Visible = true;

            var chatMode = chatChrome.Get <ButtonWidget>("CHAT_MODE");

            chatMode.GetText    = () => teamChat ? "Team" : "All";
            chatMode.OnClick    = () => teamChat ^= true;
            chatMode.IsDisabled = () => disableTeamChat;

            chatText            = chatChrome.Get <TextFieldWidget>("CHAT_TEXTFIELD");
            chatText.MaxLength  = UnitOrders.ChatMessageMaxLength;
            chatText.OnEnterKey = () =>
            {
                var team = teamChat && !disableTeamChat;
                if (chatText.Text != "")
                {
                    if (!chatText.Text.StartsWith("/", StringComparison.Ordinal))
                    {
                        orderManager.IssueOrder(Order.Chat(team, chatText.Text.Trim()));
                    }
                    else if (chatTraits != null)
                    {
                        var text = chatText.Text.Trim();
                        foreach (var trait in chatTraits)
                        {
                            trait.OnChat(orderManager.LocalClient.Name, text);
                        }
                    }
                }

                chatText.Text = "";
                if (!isMenuChat)
                {
                    CloseChat();
                }

                return(true);
            };

            chatText.OnTabKey = () =>
            {
                var previousText = chatText.Text;
                chatText.Text           = tabCompletion.Complete(chatText.Text);
                chatText.CursorPosition = chatText.Text.Length;

                if (chatText.Text == previousText)
                {
                    return(SwitchTeamChat());
                }
                else
                {
                    return(true);
                }
            };

            chatText.OnEscKey = () =>
            {
                if (!isMenuChat)
                {
                    CloseChat();
                }
                else
                {
                    chatText.YieldKeyboardFocus();
                }

                return(true);
            };

            if (!isMenuChat)
            {
                var chatClose = chatChrome.Get <ButtonWidget>("CHAT_CLOSE");
                chatClose.OnClick += CloseChat;

                chatPanel.OnKeyPress = e =>
                {
                    if (e.Event == KeyInputEvent.Up)
                    {
                        return(false);
                    }

                    if (!chatChrome.IsVisible() && (e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER))
                    {
                        OpenChat();
                        return(true);
                    }

                    return(false);
                };
            }

            chatScrollPanel = chatChrome.Get <ScrollPanelWidget>("CHAT_SCROLLPANEL");
            chatTemplate    = chatScrollPanel.Get <ContainerWidget>("CHAT_TEMPLATE");
            chatScrollPanel.RemoveChildren();
            chatScrollPanel.ScrollToBottom();

            foreach (var chatLine in orderManager.ChatCache)
            {
                AddChatLine(chatLine.Color, chatLine.Name, chatLine.Text, true);
            }

            orderManager.AddChatLine += AddChatLineWrapper;
            Game.BeforeGameStart     += UnregisterEvents;

            chatText.IsDisabled = () => world.IsReplay && !Game.Settings.Debug.EnableDebugCommandsInReplays;

            if (!isMenuChat)
            {
                CloseChat();

                var keyListener = chatChrome.Get <LogicKeyListenerWidget>("KEY_LISTENER");
                keyListener.AddHandler(e =>
                {
                    if (e.Event == KeyInputEvent.Up || !chatText.IsDisabled())
                    {
                        return(false);
                    }

                    if ((e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER || e.Key == Keycode.ESCAPE) && e.Modifiers == Modifiers.None)
                    {
                        CloseChat();
                        return(true);
                    }

                    return(false);
                });
            }
        }
Beispiel #6
0
        public ActorEditLogic(Widget widget, World world, WorldRenderer worldRenderer, Dictionary <string, MiniYaml> logicArgs)
        {
            this.worldRenderer  = worldRenderer;
            editorActorLayer    = world.WorldActor.Trait <EditorActorLayer>();
            editorActionManager = world.WorldActor.Trait <EditorActionManager>();

            editor         = widget.Parent.Get <EditorViewportControllerWidget>("MAP_EDITOR");
            actorEditPanel = editor.Get <BackgroundWidget>("ACTOR_EDIT_PANEL");

            typeLabel    = actorEditPanel.Get <LabelWidget>("ACTOR_TYPE_LABEL");
            actorIDField = actorEditPanel.Get <TextFieldWidget>("ACTOR_ID");

            initContainer   = actorEditPanel.Get("ACTOR_INIT_CONTAINER");
            buttonContainer = actorEditPanel.Get("BUTTON_CONTAINER");

            checkboxOptionTemplate = initContainer.Get("CHECKBOX_OPTION_TEMPLATE");
            sliderOptionTemplate   = initContainer.Get("SLIDER_OPTION_TEMPLATE");
            dropdownOptionTemplate = initContainer.Get("DROPDOWN_OPTION_TEMPLATE");
            initContainer.RemoveChildren();

            var deleteButton = actorEditPanel.Get <ButtonWidget>("DELETE_BUTTON");
            var cancelButton = actorEditPanel.Get <ButtonWidget>("CANCEL_BUTTON");
            var okButton     = actorEditPanel.Get <ButtonWidget>("OK_BUTTON");

            actorIDErrorLabel           = actorEditPanel.Get <LabelWidget>("ACTOR_ID_ERROR_LABEL");
            actorIDErrorLabel.IsVisible = () => actorIDStatus != ActorIDStatus.Normal;
            actorIDErrorLabel.GetText   = () => actorIDStatus == ActorIDStatus.Duplicate ?
                                          "Duplicate Actor ID" : "Enter an Actor ID";

            MiniYaml yaml;

            if (logicArgs.TryGetValue("EditPanelPadding", out yaml))
            {
                editPanelPadding = FieldLoader.GetValue <int>("EditPanelPadding", yaml.Value);
            }

            okButton.IsDisabled      = () => !IsValid() || !editActorPreview.IsDirty;
            okButton.OnClick         = Save;
            cancelButton.OnClick     = Cancel;
            deleteButton.OnClick     = Delete;
            actorEditPanel.IsVisible = () => CurrentActor != null &&
                                       editor.CurrentBrush == editor.DefaultBrush &&
                                       Game.RunTime > lastScrollTime + scrollVisibleTimeout;

            actorIDField.OnEscKey = () =>
            {
                actorIDField.YieldKeyboardFocus();
                return(true);
            };

            actorIDField.OnTextEdited = () =>
            {
                var actorId = actorIDField.Text.Trim();
                if (string.IsNullOrWhiteSpace(actorId))
                {
                    nextActorIDStatus = ActorIDStatus.Empty;
                    return;
                }

                // Check for duplicate actor ID
                if (CurrentActor.ID.Equals(actorId, StringComparison.OrdinalIgnoreCase))
                {
                    if (editorActorLayer[actorId] != null)
                    {
                        nextActorIDStatus = ActorIDStatus.Duplicate;
                        return;
                    }
                }

                SetActorID(actorId);
                nextActorIDStatus = ActorIDStatus.Normal;
            };

            actorIDField.OnLoseFocus = () =>
            {
                // Reset invalid IDs back to their starting value
                if (actorIDStatus != ActorIDStatus.Normal)
                {
                    SetActorID(initialActorID);
                }
            };
        }
Beispiel #7
0
        public override void Tick()
        {
            if (actorIDStatus != nextActorIDStatus)
            {
                if ((actorIDStatus & nextActorIDStatus) == 0)
                {
                    var offset = actorIDErrorLabel.Bounds.Height;
                    if (nextActorIDStatus == ActorIDStatus.Normal)
                    {
                        offset *= -1;
                    }

                    actorEditPanel.Bounds.Height += offset;
                    initContainer.Bounds.Y       += offset;
                    buttonContainer.Bounds.Y     += offset;
                }

                actorIDStatus = nextActorIDStatus;
            }

            var actor = editor.DefaultBrush.SelectedActor;

            if (actor != null)
            {
                var origin = worldRenderer.Viewport.WorldToViewPx(new int2(actor.Bounds.Right, actor.Bounds.Top));

                // If we scrolled, hide the edit box for a moment
                if (lastScrollPosition.X != origin.X || lastScrollPosition.Y != origin.Y)
                {
                    lastScrollTime     = Game.RunTime;
                    lastScrollPosition = origin;
                }

                // If we changed actor, move widgets
                if (CurrentActor != actor)
                {
                    lastScrollTime = 0;                     // Ensure visible
                    CurrentActor   = actor;

                    editActorPreview = new EditActorPreview(CurrentActor);

                    initialActorID = actorIDField.Text = actor.ID;

                    var font          = Game.Renderer.Fonts[typeLabel.Font];
                    var truncatedType = WidgetUtils.TruncateText(actor.DescriptiveName, typeLabel.Bounds.Width, font);
                    typeLabel.Text = truncatedType;

                    actorIDField.CursorPosition = actor.ID.Length;
                    nextActorIDStatus           = ActorIDStatus.Normal;

                    // Remove old widgets
                    var oldInitHeight = initContainer.Bounds.Height;
                    initContainer.Bounds.Height = 0;
                    initContainer.RemoveChildren();

                    // Add owner dropdown
                    var ownerContainer = dropdownOptionTemplate.Clone();
                    ownerContainer.Get <LabelWidget>("LABEL").GetText = () => "Owner";
                    var ownerDropdown = ownerContainer.Get <DropDownButtonWidget>("OPTION");
                    var selectedOwner = actor.Owner;

                    Action <EditorActorPreview, PlayerReference> updateOwner = (preview, reference) =>
                    {
                        preview.Owner = reference;
                        preview.ReplaceInit(new OwnerInit(reference.Name));
                    };

                    var ownerHandler = new EditorActorOptionActionHandle <PlayerReference>(updateOwner, actor.Owner);
                    editActorPreview.Add(ownerHandler);

                    Func <PlayerReference, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
                    {
                        var item = ScrollItemWidget.Setup(template, () => selectedOwner == option, () =>
                        {
                            selectedOwner = option;
                            updateOwner(CurrentActor, selectedOwner);
                            ownerHandler.OnChange(option);
                        });

                        item.Get <LabelWidget>("LABEL").GetText = () => option.Name;
                        item.GetColor = () => option.Color;
                        return(item);
                    };

                    ownerDropdown.GetText  = () => selectedOwner.Name;
                    ownerDropdown.GetColor = () => selectedOwner.Color;
                    ownerDropdown.OnClick  = () =>
                    {
                        var owners = editorActorLayer.Players.Players.Values.OrderBy(p => p.Name);
                        ownerDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, owners, setupItem);
                    };

                    initContainer.Bounds.Height += ownerContainer.Bounds.Height;
                    initContainer.AddChild(ownerContainer);

                    // Add new children for inits
                    var options = actor.Info.TraitInfos <IEditorActorOptions>()
                                  .SelectMany(t => t.ActorOptions(actor.Info, worldRenderer.World))
                                  .OrderBy(o => o.DisplayOrder);

                    foreach (var o in options)
                    {
                        if (o is EditorActorCheckbox)
                        {
                            var co = (EditorActorCheckbox)o;
                            var checkboxContainer = checkboxOptionTemplate.Clone();
                            checkboxContainer.Bounds.Y   = initContainer.Bounds.Height;
                            initContainer.Bounds.Height += checkboxContainer.Bounds.Height;

                            var checkbox = checkboxContainer.Get <CheckboxWidget>("OPTION");
                            checkbox.GetText = () => co.Name;

                            var editorActionHandle = new EditorActorOptionActionHandle <bool>(co.OnChange, co.GetValue(actor));
                            editActorPreview.Add(editorActionHandle);

                            checkbox.IsChecked = () => co.GetValue(actor);
                            checkbox.OnClick   = () =>
                            {
                                var newValue = co.GetValue(actor) ^ true;
                                co.OnChange(actor, newValue);
                                editorActionHandle.OnChange(newValue);
                            };

                            initContainer.AddChild(checkboxContainer);
                        }
                        else if (o is EditorActorSlider)
                        {
                            var so = (EditorActorSlider)o;
                            var sliderContainer = sliderOptionTemplate.Clone();
                            sliderContainer.Bounds.Y     = initContainer.Bounds.Height;
                            initContainer.Bounds.Height += sliderContainer.Bounds.Height;
                            sliderContainer.Get <LabelWidget>("LABEL").GetText = () => so.Name;

                            var slider = sliderContainer.Get <SliderWidget>("OPTION");
                            slider.MinimumValue = so.MinValue;
                            slider.MaximumValue = so.MaxValue;
                            slider.Ticks        = so.Ticks;

                            var editorActionHandle = new EditorActorOptionActionHandle <float>(so.OnChange, so.GetValue(actor));
                            editActorPreview.Add(editorActionHandle);

                            slider.GetValue  = () => so.GetValue(actor);
                            slider.OnChange += value => so.OnChange(actor, value);
                            slider.OnChange += value => editorActionHandle.OnChange(value);

                            initContainer.AddChild(sliderContainer);
                        }
                        else if (o is EditorActorDropdown)
                        {
                            var ddo = (EditorActorDropdown)o;
                            var dropdownContainer = dropdownOptionTemplate.Clone();
                            dropdownContainer.Bounds.Y   = initContainer.Bounds.Height;
                            initContainer.Bounds.Height += dropdownContainer.Bounds.Height;
                            dropdownContainer.Get <LabelWidget>("LABEL").GetText = () => ddo.Name;

                            var editorActionHandle = new EditorActorOptionActionHandle <string>(ddo.OnChange, ddo.GetValue(actor));
                            editActorPreview.Add(editorActionHandle);

                            var dropdown = dropdownContainer.Get <DropDownButtonWidget>("OPTION");
                            Func <KeyValuePair <string, string>, ScrollItemWidget, ScrollItemWidget> dropdownSetup = (option, template) =>
                            {
                                var item = ScrollItemWidget.Setup(template,
                                                                  () => ddo.GetValue(actor) == option.Key,
                                                                  () =>
                                {
                                    ddo.OnChange(actor, option.Key);
                                    editorActionHandle.OnChange(option.Key);
                                });

                                item.Get <LabelWidget>("LABEL").GetText = () => option.Value;
                                return(item);
                            };

                            dropdown.GetText = () => ddo.Labels[ddo.GetValue(actor)];
                            dropdown.OnClick = () => dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 270, ddo.Labels, dropdownSetup);

                            initContainer.AddChild(dropdownContainer);
                        }
                    }

                    actorEditPanel.Bounds.Height += initContainer.Bounds.Height - oldInitHeight;
                    buttonContainer.Bounds.Y     += initContainer.Bounds.Height - oldInitHeight;
                }

                // Set the edit panel to the right of the selection border.
                actorEditPanel.Bounds.X = origin.X + editPanelPadding;
                actorEditPanel.Bounds.Y = origin.Y;
            }
            else
            {
                // Selected actor is null, hide the border and edit panel.
                actorIDField.YieldKeyboardFocus();
                CurrentActor = null;
            }
        }
Beispiel #8
0
 public void CloseChat()
 {
     ChatOverlay.Visible = true;
     ChatChrome.Visible  = false;
     ChatText.YieldKeyboardFocus();
 }
        public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer)
        {
            world        = worldRenderer.World;
            this.modData = modData;
            panel        = widget;

            var colorPickerPalettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserColorPickerPalettes>()
                                      .SelectMany(p => p.ColorPickerPaletteNames)
                                      .ToArray();

            palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>()
                       .SelectMany(p => p.PaletteNames)
                       .Concat(colorPickerPalettes)
                       .ToArray();

            var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER");

            if (ticker != null)
            {
                ticker.OnTick = () =>
                {
                    if (animateFrames && currentSprites != null)
                    {
                        SelectNextFrame();
                    }
                };
            }

            var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR");

            if (sourceDropdown != null)
            {
                sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown);
                var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName);
                sourceDropdown.GetText = () => sourceName.Update(assetSource);
            }

            var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE");

            if (spriteWidget != null)
            {
                spriteWidget.GetSprite  = () => currentSprites != null ? currentSprites[currentFrame] : null;
                currentPalette          = spriteWidget.Palette;
                spriteScale             = spriteWidget.Scale;
                spriteWidget.GetPalette = () => currentPalette;
                spriteWidget.IsVisible  = () => !isVideoLoaded && !isLoadError && currentSprites != null;
                spriteWidget.GetScale   = () => spriteScale;
            }

            var playerWidget = panel.GetOrNull <VideoPlayerWidget>("PLAYER");

            if (playerWidget != null)
            {
                playerWidget.IsVisible = () => isVideoLoaded && !isLoadError;
            }

            var modelWidget = panel.GetOrNull <ModelWidget>("VOXEL");

            if (modelWidget != null)
            {
                modelWidget.GetVoxel         = () => currentVoxel;
                currentPalette               = modelWidget.Palette;
                modelScale                   = modelWidget.Scale;
                modelWidget.GetPalette       = () => currentPalette;
                modelWidget.GetPlayerPalette = () => currentPalette;
                modelWidget.GetRotation      = () => modelOrientation;
                modelWidget.IsVisible        = () => !isVideoLoaded && !isLoadError && currentVoxel != null;
                modelWidget.GetScale         = () => modelScale;
            }

            var errorLabelWidget = panel.GetOrNull("ERROR");

            if (errorLabelWidget != null)
            {
                errorLabelWidget.IsVisible = () => isLoadError;
            }

            var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR");

            if (paletteDropDown != null)
            {
                paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown, world);
                paletteDropDown.GetText     = () => currentPalette;
                paletteDropDown.IsVisible   = () => currentSprites != null || currentVoxel != null;
                panel.GetOrNull <LabelWidget>("PALETTE_DESC").IsVisible = () => currentSprites != null || currentVoxel != null;
            }

            var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>();

            colorManager.Color = Game.Settings.Player.Color;

            var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR");

            if (colorDropdown != null)
            {
                colorDropdown.IsDisabled  = () => !colorPickerPalettes.Contains(currentPalette);
                colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer);
                colorDropdown.IsVisible   = () => currentSprites != null || currentVoxel != null;
                panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => colorManager.Color;
            }

            filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT");
            filenameInput.OnTextEdited = () => ApplyFilter();
            filenameInput.OnEscKey     = _ =>
            {
                if (string.IsNullOrEmpty(filenameInput.Text))
                {
                    filenameInput.YieldKeyboardFocus();
                }
                else
                {
                    filenameInput.Text = "";
                    filenameInput.OnTextEdited();
                }

                return(true);
            };

            var frameContainer = panel.GetOrNull("FRAME_SELECTOR");

            if (frameContainer != null)
            {
                frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) ||
                                           (isVideoLoaded && player != null && player.Video != null && player.Video.FrameCount > 1) ||
                                           currentSoundFormat != null;
            }

            frameSlider = panel.GetOrNull <SliderWidget>("FRAME_SLIDER");
            if (frameSlider != null)
            {
                frameSlider.OnChange += x =>
                {
                    if (!isVideoLoaded)
                    {
                        currentFrame = (int)Math.Round(x);
                    }
                };

                frameSlider.GetValue = () =>
                {
                    if (isVideoLoaded)
                    {
                        return(player.Video.CurrentFrameIndex);
                    }

                    if (currentSound != null)
                    {
                        return(currentSound.SeekPosition * currentSoundFormat.SampleRate);
                    }

                    return(currentFrame);
                };

                frameSlider.IsDisabled = () => isVideoLoaded || currentSoundFormat != null;
            }

            var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT");

            if (frameText != null)
            {
                frameText.GetText = () =>
                {
                    if (isVideoLoaded)
                    {
                        return($"{player.Video.CurrentFrameIndex + 1} / {player.Video.FrameCount}");
                    }

                    if (currentSoundFormat != null)
                    {
                        return($"{Math.Round(currentSoundFormat.LengthInSeconds, 3)} sec");
                    }

                    return($"{currentFrame} / {currentSprites.Length - 1}");
                };
            }

            var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY");

            if (playButton != null)
            {
                playButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Play();
                    }
                    else if (currentSoundFormat != null)
                    {
                        if (currentSound != null)
                        {
                            Game.Sound.StopSound(currentSound);
                        }

                        currentSound = Game.Sound.Play(currentSoundFormat, Game.Sound.SoundVolume);
                    }
                    else
                    {
                        animateFrames = true;
                    }
                };

                playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames || currentSoundFormat != null;
            }

            var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE");

            if (pauseButton != null)
            {
                pauseButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Pause();
                    }
                    else
                    {
                        animateFrames = false;
                    }
                };

                pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : (animateFrames && currentSoundFormat == null);
            }

            var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP");

            if (stopButton != null)
            {
                stopButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Stop();
                    }
                    else if (currentSound != null)
                    {
                        Game.Sound.StopSound(currentSound);
                    }
                    else
                    {
                        currentFrame  = 0;
                        animateFrames = false;
                    }

                    if (frameSlider != null)
                    {
                        frameSlider.Value = 0;
                    }
                };
            }

            var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT");

            if (nextButton != null)
            {
                nextButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        nextButton.OnClick = SelectNextFrame;
                    }
                };

                nextButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null;
            }

            var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV");

            if (prevButton != null)
            {
                prevButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        SelectPreviousFrame();
                    }
                };

                prevButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null;
            }

            var spriteScaleSlider = panel.GetOrNull <SliderWidget>("SPRITE_SCALE_SLIDER");

            if (spriteScaleSlider != null)
            {
                spriteScaleSlider.OnChange += x => spriteScale = x;
                spriteScaleSlider.GetValue  = () => spriteScale;
                spriteScaleSlider.IsVisible = () => currentSprites != null;
                panel.GetOrNull <LabelWidget>("SPRITE_SCALE").IsVisible = () => currentSprites != null;
            }

            var voxelContainer = panel.GetOrNull("VOXEL_SELECTOR");

            if (voxelContainer != null)
            {
                voxelContainer.IsVisible = () => currentVoxel != null;
            }

            var rollSlider = panel.GetOrNull <SliderWidget>("ROLL_SLIDER");

            if (rollSlider != null)
            {
                rollSlider.OnChange += x =>
                {
                    var roll = (int)x;
                    modelOrientation = modelOrientation.WithRoll(new WAngle(roll));
                };

                rollSlider.GetValue = () => modelOrientation.Roll.Angle;
            }

            var pitchSlider = panel.GetOrNull <SliderWidget>("PITCH_SLIDER");

            if (pitchSlider != null)
            {
                pitchSlider.OnChange += x =>
                {
                    var pitch = (int)x;
                    modelOrientation = modelOrientation.WithPitch(new WAngle(pitch));
                };

                pitchSlider.GetValue = () => modelOrientation.Pitch.Angle;
            }

            var yawSlider = panel.GetOrNull <SliderWidget>("YAW_SLIDER");

            if (yawSlider != null)
            {
                yawSlider.OnChange += x =>
                {
                    var yaw = (int)x;
                    modelOrientation = modelOrientation.WithYaw(new WAngle(yaw));
                };

                yawSlider.GetValue = () => modelOrientation.Yaw.Angle;
            }

            var modelScaleSlider = panel.GetOrNull <SliderWidget>("MODEL_SCALE_SLIDER");

            if (modelScaleSlider != null)
            {
                modelScaleSlider.OnChange += x => modelScale = x;
                modelScaleSlider.GetValue  = () => modelScale;
                modelScaleSlider.IsVisible = () => currentVoxel != null;
                panel.GetOrNull <LabelWidget>("MODEL_SCALE").IsVisible = () => currentVoxel != null;
            }

            var assetBrowserModData = modData.Manifest.Get <AssetBrowser>();

            allowedSpriteExtensions = assetBrowserModData.SpriteExtensions;
            allowedModelExtensions  = assetBrowserModData.ModelExtensions;
            allowedAudioExtensions  = assetBrowserModData.AudioExtensions;
            allowedVideoExtensions  = assetBrowserModData.VideoExtensions;
            allowedExtensions       = allowedSpriteExtensions
                                      .Union(allowedModelExtensions)
                                      .Union(allowedAudioExtensions)
                                      .Union(allowedVideoExtensions)
                                      .ToArray();

            acceptablePackages = modData.ModFiles.MountedPackages.Where(p =>
                                                                        p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant())));

            assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST");
            template  = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE");
            PopulateAssetList();

            var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON");

            if (closeButton != null)
            {
                closeButton.OnClick = () =>
                {
                    ClearLoadedAssets();
                    Ui.CloseWindow();
                    onExit();
                }
            }
            ;
        }

        void SelectNextFrame()
        {
            currentFrame++;
            if (currentFrame >= currentSprites.Length)
            {
                currentFrame = 0;
            }
        }

        void SelectPreviousFrame()
        {
            currentFrame--;
            if (currentFrame < 0)
            {
                currentFrame = currentSprites.Length - 1;
            }
        }

        Dictionary <string, bool> assetVisByName = new Dictionary <string, bool>();

        bool FilterAsset(string filename)
        {
            var filter = filenameInput.Text;

            if (string.IsNullOrWhiteSpace(filter))
            {
                return(true);
            }

            if (filename.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)
            {
                return(true);
            }

            return(false);
        }

        void ApplyFilter()
        {
            assetVisByName.Clear();
            assetList.Layout.AdjustChildren();
            assetList.ScrollToTop();

            // Select the first visible
            var firstVisible = assetVisByName.FirstOrDefault(kvp => kvp.Value);

            if (firstVisible.Key != null && modData.DefaultFileSystem.TryGetPackageContaining(firstVisible.Key, out var package, out var filename))
            {
                LoadAsset(package, filename);
            }
        }

        void AddAsset(ScrollPanelWidget list, string filepath, IReadOnlyPackage package, ScrollItemWidget template)
        {
            var item = ScrollItemWidget.Setup(template,
                                              () => currentFilename == filepath && currentPackage == package,
                                              () => { LoadAsset(package, filepath); });

            var label = item.Get <LabelWithTooltipWidget>("TITLE");

            WidgetUtils.TruncateLabelToTooltip(label, filepath);
            label.GetTooltipText = () => $"{filepath}\n{package.Name}";

            item.IsVisible = () =>
            {
                if (assetVisByName.TryGetValue(filepath, out var visible))
                {
                    return(visible);
                }

                visible = FilterAsset(filepath);
                assetVisByName.Add(filepath, visible);
                return(visible);
            };

            list.AddChild(item);
        }

        bool LoadAsset(IReadOnlyPackage package, string filename)
        {
            ClearLoadedAssets();

            if (string.IsNullOrEmpty(filename))
            {
                return(false);
            }

            if (!package.Contains(filename))
            {
                return(false);
            }

            isLoadError = false;

            try
            {
                currentPackage  = package;
                currentFilename = filename;
                var prefix = "";

                if (modData.DefaultFileSystem is OpenRA.FileSystem.FileSystem fs)
                {
                    prefix = fs.GetPrefix(package);
                    if (prefix != null)
                    {
                        prefix += "|";
                    }
                }

                var fileExtension = Path.GetExtension(filename.ToLowerInvariant());
                if (allowedSpriteExtensions.Contains(fileExtension))
                {
                    currentSprites = world.Map.Rules.Sequences.SpriteCache[prefix + filename];
                    currentFrame   = 0;

                    if (frameSlider != null)
                    {
                        frameSlider.MaximumValue = (float)currentSprites.Length - 1;
                        frameSlider.Ticks        = currentSprites.Length;
                    }

                    currentVoxel = null;
                }
                else if (allowedModelExtensions.Contains(fileExtension))
                {
                    var voxelName = Path.GetFileNameWithoutExtension(filename);
                    currentVoxel   = world.ModelCache.GetModel(voxelName);
                    currentSprites = null;
                }
                else if (allowedAudioExtensions.Contains(fileExtension))
                {
                    // Mute music so it doesn't interfere with the current asset.
                    MuteSounds();

                    currentAudioStream = Game.ModData.DefaultFileSystem.Open(prefix + filename);
                    foreach (var modDataSoundLoader in Game.ModData.SoundLoaders)
                    {
                        if (modDataSoundLoader.TryParseSound(currentAudioStream, out currentSoundFormat))
                        {
                            if (frameSlider != null)
                            {
                                frameSlider.MaximumValue = currentSoundFormat.LengthInSeconds * currentSoundFormat.SampleRate;
                                frameSlider.Ticks        = 0;
                            }

                            break;
                        }
                    }
                }
                else if (allowedVideoExtensions.Contains(fileExtension))
                {
                    // Mute music so it doesn't interfere with the current asset.
                    MuteSounds();

                    var video = VideoLoader.GetVideo(Game.ModData.DefaultFileSystem.Open(filename), true, Game.ModData.VideoLoaders);
                    if (video != null)
                    {
                        player = panel.Get <VideoPlayerWidget>("PLAYER");
                        player.Load(prefix + filename);
                        player.DrawOverlay = false;
                        isVideoLoaded      = true;

                        if (frameSlider != null)
                        {
                            frameSlider.MaximumValue = (float)player.Video.FrameCount - 1;
                            frameSlider.Ticks        = 0;
                        }
                    }
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                isLoadError = true;
                Log.AddChannel("assetbrowser", "assetbrowser.log");
                Log.Write("assetbrowser", "Error reading {0}:{3} {1}{3}{2}", filename, ex.Message, ex.StackTrace, Environment.NewLine);

                return(false);
            }

            return(true);
        }

        bool ShowSourceDropdown(DropDownButtonWidget dropdown)
        {
            var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName);
            Func <IReadOnlyPackage, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                                                  () => assetSource == source,
                                                  () => { assetSource = source; PopulateAssetList(); });

                item.Get <LabelWidget>("LABEL").GetText = () => sourceName.Update(source);
                return(item);
            };

            var sources = new[] { (IReadOnlyPackage)null }.Concat(acceptablePackages);

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem);
            return(true);
        }

        void PopulateAssetList()
        {
            assetList.RemoveChildren();

            var files = new SortedList <string, List <IReadOnlyPackage> >();

            if (assetSource != null)
            {
                foreach (var content in assetSource.Contents)
                {
                    files.Add(content, new List <IReadOnlyPackage> {
                        assetSource
                    });
                }
            }
            else
            {
                foreach (var mountedPackage in modData.ModFiles.MountedPackages)
                {
                    foreach (var content in mountedPackage.Contents)
                    {
                        if (!files.ContainsKey(content))
                        {
                            files.Add(content, new List <IReadOnlyPackage> {
                                mountedPackage
                            });
                        }
                        else
                        {
                            files[content].Add(mountedPackage);
                        }
                    }
                }
            }

            foreach (var file in files.OrderBy(s => s.Key))
            {
                if (!allowedExtensions.Any(ext => file.Key.EndsWith(ext, true, CultureInfo.InvariantCulture)))
                {
                    continue;
                }

                foreach (var package in file.Value)
                {
                    AddAsset(assetList, file.Key, package, template);
                }
            }
        }

        bool ShowPaletteDropdown(DropDownButtonWidget dropdown, World world)
        {
            Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (name, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                                                  () => currentPalette == name,
                                                  () => currentPalette = name);
                item.Get <LabelWidget>("LABEL").GetText = () => name;

                return(item);
            };

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, palettes, setupItem);
            return(true);
        }

        string GetSourceDisplayName(IReadOnlyPackage source)
        {
            if (source == null)
            {
                return("All Packages");
            }

            // Packages that are explicitly mounted in the filesystem use their explicit mount name
            var fs   = (OpenRA.FileSystem.FileSystem)modData.DefaultFileSystem;
            var name = fs.GetPrefix(source);

            // Fall back to the path relative to the mod, engine, or support dir
            if (name == null)
            {
                name = source.Name;
                var compare = Platform.CurrentPlatform == PlatformType.Windows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
                if (name.StartsWith(modData.Manifest.Package.Name, compare))
                {
                    name = "$" + modData.Manifest.Id + "/" + name.Substring(modData.Manifest.Package.Name.Length + 1);
                }
                else if (name.StartsWith(Platform.EngineDir, compare))
                {
                    name = "./" + name.Substring(Platform.EngineDir.Length);
                }
                else if (name.StartsWith(Platform.SupportDir, compare))
                {
                    name = "^" + name.Substring(Platform.SupportDir.Length);
                }
            }

            if (name.Length > 18)
            {
                name = "..." + name.Substring(name.Length - 15);
            }

            return(name);
        }

        // Mute/UnMute code copied from MissionBrowserLogic.
        float cachedMusicVolume;
        void MuteSounds()
        {
            if (Game.Sound.MusicVolume > 0)
            {
                cachedMusicVolume      = Game.Sound.MusicVolume;
                Game.Sound.MusicVolume = 0;
            }
        }

        void UnMuteSounds()
        {
            if (cachedMusicVolume > 0)
            {
                Game.Sound.MusicVolume = cachedMusicVolume;
            }
        }

        void ClearLoadedAssets()
        {
            if (currentSound != null)
            {
                Game.Sound.StopSound(currentSound);
            }

            currentSprites = null;
            currentFrame   = 0;

            currentVoxel = null;

            currentSound       = null;
            currentSoundFormat = null;
            currentAudioStream?.Dispose();
            currentAudioStream = null;

            player?.Stop();
            player        = null;
            isVideoLoaded = false;

            // Just in case we're switching away from a type of asset that forced the music to mute.
            UnMuteSounds();
        }
    }
        public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer)
        {
            world        = worldRenderer.World;
            this.modData = modData;
            panel        = widget;

            var colorPickerPalettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserColorPickerPalettes>()
                                      .SelectMany(p => p.ColorPickerPaletteNames)
                                      .ToArray();

            palettes = world.WorldActor.TraitsImplementing <IProvidesAssetBrowserPalettes>()
                       .SelectMany(p => p.PaletteNames)
                       .Concat(colorPickerPalettes)
                       .ToArray();

            var ticker = panel.GetOrNull <LogicTickerWidget>("ANIMATION_TICKER");

            if (ticker != null)
            {
                ticker.OnTick = () =>
                {
                    if (animateFrames && currentSprites != null)
                    {
                        SelectNextFrame();
                    }
                };
            }

            var sourceDropdown = panel.GetOrNull <DropDownButtonWidget>("SOURCE_SELECTOR");

            if (sourceDropdown != null)
            {
                sourceDropdown.OnMouseDown = _ => ShowSourceDropdown(sourceDropdown);
                var sourceName = new CachedTransform <IReadOnlyPackage, string>(GetSourceDisplayName);
                sourceDropdown.GetText = () => sourceName.Update(assetSource);
            }

            var spriteWidget = panel.GetOrNull <SpriteWidget>("SPRITE");

            if (spriteWidget != null)
            {
                spriteWidget.GetSprite  = () => currentSprites != null ? currentSprites[currentFrame] : null;
                currentPalette          = spriteWidget.Palette;
                spriteScale             = spriteWidget.Scale;
                spriteWidget.GetPalette = () => currentPalette;
                spriteWidget.IsVisible  = () => !isVideoLoaded && !isLoadError && currentSprites != null;
                spriteWidget.GetScale   = () => spriteScale;
            }

            var playerWidget = panel.GetOrNull <VideoPlayerWidget>("PLAYER");

            if (playerWidget != null)
            {
                playerWidget.IsVisible = () => isVideoLoaded && !isLoadError;
            }

            var modelWidget = panel.GetOrNull <ModelWidget>("VOXEL");

            if (modelWidget != null)
            {
                modelWidget.GetVoxel         = () => currentVoxel;
                currentPalette               = modelWidget.Palette;
                modelScale                   = modelWidget.Scale;
                modelWidget.GetPalette       = () => currentPalette;
                modelWidget.GetPlayerPalette = () => currentPalette;
                modelWidget.GetRotation      = () => modelOrientation;
                modelWidget.IsVisible        = () => !isVideoLoaded && !isLoadError && currentVoxel != null;
                modelWidget.GetScale         = () => modelScale;
            }

            var errorLabelWidget = panel.GetOrNull("ERROR");

            if (errorLabelWidget != null)
            {
                errorLabelWidget.IsVisible = () => isLoadError;
            }

            var paletteDropDown = panel.GetOrNull <DropDownButtonWidget>("PALETTE_SELECTOR");

            if (paletteDropDown != null)
            {
                paletteDropDown.OnMouseDown = _ => ShowPaletteDropdown(paletteDropDown);
                paletteDropDown.GetText     = () => currentPalette;
                paletteDropDown.IsVisible   = () => currentSprites != null || currentVoxel != null;
                panel.GetOrNull <LabelWidget>("PALETTE_DESC").IsVisible = () => currentSprites != null || currentVoxel != null;
            }

            var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>();

            colorManager.Color = Game.Settings.Player.Color;

            var colorDropdown = panel.GetOrNull <DropDownButtonWidget>("COLOR");

            if (colorDropdown != null)
            {
                colorDropdown.IsDisabled  = () => !colorPickerPalettes.Contains(currentPalette);
                colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer);
                colorDropdown.IsVisible   = () => currentSprites != null || currentVoxel != null;
                panel.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => colorManager.Color;
            }

            filenameInput = panel.Get <TextFieldWidget>("FILENAME_INPUT");
            filenameInput.OnTextEdited = () => ApplyFilter();
            filenameInput.OnEscKey     = _ =>
            {
                if (string.IsNullOrEmpty(filenameInput.Text))
                {
                    filenameInput.YieldKeyboardFocus();
                }
                else
                {
                    filenameInput.Text = "";
                    filenameInput.OnTextEdited();
                }

                return(true);
            };

            var frameContainer = panel.GetOrNull("FRAME_SELECTOR");

            if (frameContainer != null)
            {
                frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) ||
                                           (isVideoLoaded && player != null && player.Video != null && player.Video.FrameCount > 1) ||
                                           currentSoundFormat != null;
            }

            frameSlider = panel.GetOrNull <SliderWidget>("FRAME_SLIDER");
            if (frameSlider != null)
            {
                frameSlider.OnChange += x =>
                {
                    if (!isVideoLoaded)
                    {
                        currentFrame = (int)Math.Round(x);
                    }
                };

                frameSlider.GetValue = () =>
                {
                    if (isVideoLoaded)
                    {
                        return(player.Video.CurrentFrameIndex);
                    }

                    if (currentSound != null)
                    {
                        return(currentSound.SeekPosition * currentSoundFormat.SampleRate);
                    }

                    return(currentFrame);
                };

                frameSlider.IsDisabled = () => isVideoLoaded || currentSoundFormat != null;
            }

            var frameText = panel.GetOrNull <LabelWidget>("FRAME_COUNT");

            if (frameText != null)
            {
                frameText.GetText = () =>
                {
                    if (isVideoLoaded)
                    {
                        return($"{player.Video.CurrentFrameIndex + 1} / {player.Video.FrameCount}");
                    }

                    if (currentSoundFormat != null)
                    {
                        return($"{Math.Round(currentSoundFormat.LengthInSeconds, 3)} sec");
                    }

                    return($"{currentFrame} / {currentSprites.Length - 1}");
                };
            }

            var playButton = panel.GetOrNull <ButtonWidget>("BUTTON_PLAY");

            if (playButton != null)
            {
                playButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Play();
                    }
                    else if (currentSoundFormat != null)
                    {
                        if (currentSound != null)
                        {
                            Game.Sound.StopSound(currentSound);
                        }

                        currentSound = Game.Sound.Play(currentSoundFormat, Game.Sound.SoundVolume);
                    }
                    else
                    {
                        animateFrames = true;
                    }
                };

                playButton.IsVisible = () => isVideoLoaded ? player.Paused : !animateFrames || currentSoundFormat != null;
            }

            var pauseButton = panel.GetOrNull <ButtonWidget>("BUTTON_PAUSE");

            if (pauseButton != null)
            {
                pauseButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Pause();
                    }
                    else
                    {
                        animateFrames = false;
                    }
                };

                pauseButton.IsVisible = () => isVideoLoaded ? !player.Paused : (animateFrames && currentSoundFormat == null);
            }

            var stopButton = panel.GetOrNull <ButtonWidget>("BUTTON_STOP");

            if (stopButton != null)
            {
                stopButton.OnClick = () =>
                {
                    if (isVideoLoaded)
                    {
                        player.Stop();
                    }
                    else if (currentSound != null)
                    {
                        Game.Sound.StopSound(currentSound);
                    }
                    else
                    {
                        currentFrame  = 0;
                        animateFrames = false;
                    }

                    if (frameSlider != null)
                    {
                        frameSlider.Value = 0;
                    }
                };
            }

            var nextButton = panel.GetOrNull <ButtonWidget>("BUTTON_NEXT");

            if (nextButton != null)
            {
                nextButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        nextButton.OnClick = SelectNextFrame;
                    }
                };

                nextButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null;
            }

            var prevButton = panel.GetOrNull <ButtonWidget>("BUTTON_PREV");

            if (prevButton != null)
            {
                prevButton.OnClick = () =>
                {
                    if (!isVideoLoaded)
                    {
                        SelectPreviousFrame();
                    }
                };

                prevButton.IsVisible = () => !isVideoLoaded && currentSoundFormat == null;
            }

            var spriteScaleSlider = panel.GetOrNull <SliderWidget>("SPRITE_SCALE_SLIDER");

            if (spriteScaleSlider != null)
            {
                spriteScaleSlider.OnChange += x => spriteScale = x;
                spriteScaleSlider.GetValue  = () => spriteScale;
                spriteScaleSlider.IsVisible = () => currentSprites != null;
                panel.GetOrNull <LabelWidget>("SPRITE_SCALE").IsVisible = () => currentSprites != null;
            }

            var voxelContainer = panel.GetOrNull("VOXEL_SELECTOR");

            if (voxelContainer != null)
            {
                voxelContainer.IsVisible = () => currentVoxel != null;
            }

            var rollSlider = panel.GetOrNull <SliderWidget>("ROLL_SLIDER");

            if (rollSlider != null)
            {
                rollSlider.OnChange += x =>
                {
                    var roll = (int)x;
                    modelOrientation = modelOrientation.WithRoll(new WAngle(roll));
                };

                rollSlider.GetValue = () => modelOrientation.Roll.Angle;
            }

            var pitchSlider = panel.GetOrNull <SliderWidget>("PITCH_SLIDER");

            if (pitchSlider != null)
            {
                pitchSlider.OnChange += x =>
                {
                    var pitch = (int)x;
                    modelOrientation = modelOrientation.WithPitch(new WAngle(pitch));
                };

                pitchSlider.GetValue = () => modelOrientation.Pitch.Angle;
            }

            var yawSlider = panel.GetOrNull <SliderWidget>("YAW_SLIDER");

            if (yawSlider != null)
            {
                yawSlider.OnChange += x =>
                {
                    var yaw = (int)x;
                    modelOrientation = modelOrientation.WithYaw(new WAngle(yaw));
                };

                yawSlider.GetValue = () => modelOrientation.Yaw.Angle;
            }

            var modelScaleSlider = panel.GetOrNull <SliderWidget>("MODEL_SCALE_SLIDER");

            if (modelScaleSlider != null)
            {
                modelScaleSlider.OnChange += x => modelScale = x;
                modelScaleSlider.GetValue  = () => modelScale;
                modelScaleSlider.IsVisible = () => currentVoxel != null;
                panel.GetOrNull <LabelWidget>("MODEL_SCALE").IsVisible = () => currentVoxel != null;
            }

            var assetBrowserModData = modData.Manifest.Get <AssetBrowser>();

            allowedSpriteExtensions = assetBrowserModData.SpriteExtensions;
            allowedModelExtensions  = assetBrowserModData.ModelExtensions;
            allowedAudioExtensions  = assetBrowserModData.AudioExtensions;
            allowedVideoExtensions  = assetBrowserModData.VideoExtensions;
            allowedExtensions       = allowedSpriteExtensions
                                      .Union(allowedModelExtensions)
                                      .Union(allowedAudioExtensions)
                                      .Union(allowedVideoExtensions)
                                      .ToArray();

            acceptablePackages = modData.ModFiles.MountedPackages.Where(p =>
                                                                        p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant())));

            assetList = panel.Get <ScrollPanelWidget>("ASSET_LIST");
            template  = panel.Get <ScrollItemWidget>("ASSET_TEMPLATE");
            PopulateAssetList();

            var closeButton = panel.GetOrNull <ButtonWidget>("CLOSE_BUTTON");

            if (closeButton != null)
            {
                closeButton.OnClick = () =>
                {
                    ClearLoadedAssets();
                    Ui.CloseWindow();
                    onExit();
                }
            }
            ;
        }

        void SelectNextFrame()
        {
            currentFrame++;
            if (currentFrame >= currentSprites.Length)
            {
                currentFrame = 0;
            }
        }

        void SelectPreviousFrame()
        {
            currentFrame--;
            if (currentFrame < 0)
            {
                currentFrame = currentSprites.Length - 1;
            }
        }
        Func <bool> InitPanel(Widget panel)
        {
            hotkeyList        = panel.Get <ScrollPanelWidget>("HOTKEY_LIST");
            hotkeyList.Layout = new GridLayout(hotkeyList);
            headerTemplate    = hotkeyList.Get("HEADER");
            template          = hotkeyList.Get("TEMPLATE");
            emptyListMessage  = panel.Get("HOTKEY_EMPTY_LIST");
            remapDialog       = panel.Get("HOTKEY_REMAP_DIALOG");

            foreach (var hd in modData.Hotkeys.Definitions)
            {
                contexts.UnionWith(hd.Contexts);
            }

            filterInput = panel.Get <TextFieldWidget>("FILTER_INPUT");
            filterInput.OnTextEdited = () => InitHotkeyList();
            filterInput.OnEscKey     = _ =>
            {
                if (string.IsNullOrEmpty(filterInput.Text))
                {
                    filterInput.YieldKeyboardFocus();
                }
                else
                {
                    filterInput.Text = "";
                    filterInput.OnTextEdited();
                }

                return(true);
            };

            var contextDropdown = panel.GetOrNull <DropDownButtonWidget>("CONTEXT_DROPDOWN");

            if (contextDropdown != null)
            {
                contextDropdown.OnMouseDown = _ => ShowContextDropdown(contextDropdown);
                var contextName = new CachedTransform <string, string>(GetContextDisplayName);
                contextDropdown.GetText = () => contextName.Update(currentContext);
            }

            if (logicArgs.TryGetValue("HotkeyGroups", out var hotkeyGroupsYaml))
            {
                foreach (var hg in hotkeyGroupsYaml.Nodes)
                {
                    var typesNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Types");
                    if (typesNode != null)
                    {
                        hotkeyGroups.Add(hg.Key, FieldLoader.GetValue <HashSet <string> >("Types", typesNode.Value.Value));
                    }
                }

                InitHotkeyRemapDialog(panel);
                InitHotkeyList();
            }

            return(() =>
            {
                hotkeyEntryWidget.Key =
                    selectedHotkeyDefinition != null ?
                    modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue() :
                    Hotkey.Invalid;

                hotkeyEntryWidget.ForceYieldKeyboardFocus();

                return false;
            });
        }
        public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat, Dictionary <string, MiniYaml> logicArgs)
        {
            this.orderManager = orderManager;
            modRules          = modData.DefaultRules;
            this.isMenuChat   = isMenuChat;
            this.world        = world;

            var chatTraits      = world.WorldActor.TraitsImplementing <INotifyChat>().ToArray();
            var players         = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot);
            var isObserver      = orderManager.LocalClient != null && orderManager.LocalClient.IsObserver;
            var alwaysDisabled  = world.IsReplay || world.LobbyInfo.NonBotClients.Count() == 1;
            var disableTeamChat = alwaysDisabled || (world.LocalPlayer != null && !players.Any(p => p.IsAlliedWith(world.LocalPlayer)));
            var teamChat        = !disableTeamChat;

            tabCompletion.Commands = chatTraits.OfType <ChatCommands>().SelectMany(x => x.Commands.Keys).ToList();
            tabCompletion.Names    = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();

            if (logicArgs.TryGetValue("Templates", out var templateIds))
            {
                foreach (var item in templateIds.Nodes)
                {
                    var key = FieldLoader.GetValue <TextNotificationPool>("key", item.Key);
                    templates[key] = Ui.LoadWidget(item.Value.Value, null, new WidgetArgs());
                }
            }

            var chatPanel = (ContainerWidget)widget;

            chatOverlay = chatPanel.GetOrNull <ContainerWidget>("CHAT_OVERLAY");
            if (chatOverlay != null)
            {
                chatOverlayDisplay  = chatOverlay.Get <TextNotificationsDisplayWidget>("CHAT_DISPLAY");
                chatOverlay.Visible = false;
            }

            chatChrome         = chatPanel.Get <ContainerWidget>("CHAT_CHROME");
            chatChrome.Visible = true;

            var chatMode = chatChrome.Get <ButtonWidget>("CHAT_MODE");

            chatMode.GetText = () => teamChat && !disableTeamChat ? "Team" : "All";
            chatMode.OnClick = () => teamChat ^= true;

            // Enable teamchat if we are a player and die,
            // or disable it when we are the only one left in the team
            if (!alwaysDisabled && world.LocalPlayer != null)
            {
                chatMode.IsDisabled = () =>
                {
                    if (world.IsGameOver || !chatEnabled)
                    {
                        return(true);
                    }

                    // The game is over for us, join spectator team chat
                    if (world.LocalPlayer.WinState != WinState.Undefined)
                    {
                        disableTeamChat = false;
                        return(disableTeamChat);
                    }

                    // If team chat isn't already disabled, check if we are the only living team member
                    if (!disableTeamChat)
                    {
                        disableTeamChat = players.All(p => p.WinState != WinState.Undefined || !p.IsAlliedWith(world.LocalPlayer));
                    }

                    return(disableTeamChat);
                };
            }
            else
            {
                chatMode.IsDisabled = () => disableTeamChat || !chatEnabled;
            }

            // Disable team chat after the game ended
            world.GameOver += () => disableTeamChat = true;

            chatText            = chatChrome.Get <TextFieldWidget>("CHAT_TEXTFIELD");
            chatText.MaxLength  = UnitOrders.ChatMessageMaxLength;
            chatText.OnEnterKey = _ =>
            {
                var team = teamChat && !disableTeamChat;
                if (chatText.Text != "")
                {
                    if (!chatText.Text.StartsWith("/", StringComparison.Ordinal))
                    {
                        // This should never happen, but avoid a crash if it does somehow (chat will just stay open)
                        if (!isObserver && orderManager.LocalClient == null && world.LocalPlayer == null)
                        {
                            return(true);
                        }

                        var teamNumber = 0U;
                        if (team)
                        {
                            teamNumber = (isObserver || world.LocalPlayer.WinState != WinState.Undefined) ? uint.MaxValue : (uint)orderManager.LocalClient.Team;
                        }

                        orderManager.IssueOrder(Order.Chat(chatText.Text.Trim(), teamNumber));
                    }
                    else if (chatTraits != null)
                    {
                        var text = chatText.Text.Trim();
                        var from = world.IsReplay ? null : orderManager.LocalClient.Name;
                        foreach (var trait in chatTraits)
                        {
                            trait.OnChat(from, text);
                        }
                    }
                }

                chatText.Text = "";
                if (!isMenuChat)
                {
                    CloseChat();
                }

                return(true);
            };

            chatText.OnTabKey = e =>
            {
                if (!chatMode.Key.IsActivatedBy(e) || chatMode.IsDisabled())
                {
                    chatText.Text           = tabCompletion.Complete(chatText.Text);
                    chatText.CursorPosition = chatText.Text.Length;
                }
                else
                {
                    chatMode.OnKeyPress(e);
                }

                return(true);
            };

            chatText.OnEscKey = _ =>
            {
                if (!isMenuChat)
                {
                    CloseChat();
                }
                else
                {
                    chatText.YieldKeyboardFocus();
                }

                return(true);
            };

            chatDisabledLabel = new CachedTransform <int, string>(x => x > 0 ? $"Chat available in {x} seconds..." : "Chat Disabled");

            if (!isMenuChat)
            {
                var openTeamChatKey = new HotkeyReference();
                if (logicArgs.TryGetValue("OpenTeamChatKey", out var hotkeyArg))
                {
                    openTeamChatKey = modData.Hotkeys[hotkeyArg.Value];
                }

                var openGeneralChatKey = new HotkeyReference();
                if (logicArgs.TryGetValue("OpenGeneralChatKey", out hotkeyArg))
                {
                    openGeneralChatKey = modData.Hotkeys[hotkeyArg.Value];
                }

                var chatClose = chatChrome.Get <ButtonWidget>("CHAT_CLOSE");
                chatClose.OnClick += CloseChat;

                chatPanel.OnKeyPress = e =>
                {
                    if (e.Event == KeyInputEvent.Up)
                    {
                        return(false);
                    }

                    if (!chatChrome.IsVisible() && (openTeamChatKey.IsActivatedBy(e) || openGeneralChatKey.IsActivatedBy(e)))
                    {
                        teamChat = !disableTeamChat && !openGeneralChatKey.IsActivatedBy(e);

                        OpenChat();
                        return(true);
                    }

                    return(false);
                };
            }

            chatScrollPanel = chatChrome.Get <ScrollPanelWidget>("CHAT_SCROLLPANEL");
            chatScrollPanel.RemoveChildren();
            chatScrollPanel.ScrollToBottom();

            foreach (var notification in orderManager.NotificationsCache)
            {
                if (IsNotificationEligible(notification))
                {
                    AddNotification(notification, true);
                }
            }

            orderManager.AddTextNotification += AddNotificationWrapper;

            chatText.IsDisabled = () => !chatEnabled || (world.IsReplay && !Game.Settings.Debug.EnableDebugCommandsInReplays);

            if (!isMenuChat)
            {
                CloseChat();

                var keyListener = chatChrome.Get <LogicKeyListenerWidget>("KEY_LISTENER");
                keyListener.AddHandler(e =>
                {
                    if (e.Event == KeyInputEvent.Up || !chatText.IsDisabled())
                    {
                        return(false);
                    }

                    if ((e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER || e.Key == Keycode.ESCAPE) && e.Modifiers == Modifiers.None)
                    {
                        CloseChat();
                        return(true);
                    }

                    return(false);
                });
            }

            if (logicArgs.TryGetValue("ChatLineSound", out var yaml))
            {
                chatLineSound = yaml.Value;
            }
        }