Ejemplo n.º 1
0
        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();
        }
    }
Ejemplo n.º 2
0
        public CommonSelectorLogic(Widget widget, World world, WorldRenderer worldRenderer, string templateListId, string previewTemplateId)
        {
            Widget        = widget;
            World         = world;
            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 = _ =>
            {
                if (string.IsNullOrEmpty(SearchTextField.Text))
                {
                    SearchTextField.YieldKeyboardFocus();
                }
                else
                {
                    SearchTextField.Text = "";
                    SearchTextField.OnTextEdited();
                }

                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 = _ =>
            {
                SearchTextField?.YieldKeyboardFocus();

                categorySelector.RemovePanel();
                categorySelector.AttachPanel(CreateCategoriesPanel(Panel));
            };
        }
Ejemplo n.º 3
0
        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;
            });
        }