XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using XFEEDToolBox.Controls;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Rendering;
using XFEEDToolBox.Views;

namespace XFEEDToolBox;

public partial class App
{
    // This fixture only displays original icon resources in an isolated offline
    // instance. It cannot bind a flight driver or read the player's Journal.
    private static async Task RunGameIconProbeAsync(string reportPath)
    {
        var directory = Path.GetDirectoryName(Path.GetFullPath(reportPath))!;
        Directory.CreateDirectory(directory);
        var samples = new List<object>();
        var refitSources = new List<string>();
        string? failure = null;
        static void Require(bool value, string message)
        {
            if (!value) throw new InvalidOperationException(message);
        }
        try
        {
            Require(ViewModel.OfflinePreview && Runtime.FlightDriver is null && Runtime.Journal.Sequence == 0,
                "Game icon fixture requires isolated --offline-preview.");
            MainWindow.AppWindow.Move(new(-30000, -30000));
            MainWindow.AppWindow.Resize(new(2560, 2200));
            MainWindow.AppWindow.Show(false);
            var shell = AppShellPage.Current!;
            shell.Navigate(typeof(CurrentSystemPage));
            await Task.Delay(200);
            var page = (CurrentSystemPage)shell.CurrentPage!;
            var types = new (int Kind, SystemLocationCategory Category, string Name)[]
            {
                (1, SystemLocationCategory.Star, "HIP 12099"),
                (19, SystemLocationCategory.Asteroid, "HIP 12099 A Belt Cluster 2"),
                (3, SystemLocationCategory.Planet, "HIP 12099 1"),
                (2, SystemLocationCategory.LandablePlanet, "HIP 12099 1 b"),
                (30, SystemLocationCategory.Settlement, "Jameson Crash Site"),
                (18, SystemLocationCategory.Station, "Ray Enterprise"),
                (14, SystemLocationCategory.Carrier, "SPACEBALL1 | L1NK"),
                (22, SystemLocationCategory.Signal, "$USS_DegradedEmissions;"),
                (23, SystemLocationCategory.PointOfInterest, "$MULTIPLAYER_SCENARIO42_TITLE;"),
                (0, SystemLocationCategory.PointOfInterest, "Interest point"),
                (15, SystemLocationCategory.Carrier, "Squadron carrier")
            };
            var places = types.Select((x, i) => new SystemLocation(i + 1, (ulong)i + 100, x.Name, "", x.Kind,
                x.Category, null, null, (i + 1) * 299792458d, i == 5, "icon-fixture-" + i)).ToArray();
            ViewModel.ApplyCurrentSystemSnapshot(new(1, "HIP 12099", 1, 1, DateTimeOffset.UtcNow, places));
            await Task.Delay(300);
            page.UpdateLayout();
            var list = Descendants(page).OfType<ListView>().Single();
            foreach (var row in ViewModel.CurrentSystemLocations)
            {
                var container = list.ContainerFromItem(row) as FrameworkElement;
                Require(container is not null, "Location fixture did not fit in its viewport.");
                var icon = Descendants(container).OfType<GameIcon>().First();
                var name = Descendants(container).OfType<TextBlock>().First(x => x.Text == row.Name);
                var distance = Descendants(container).OfType<TextBlock>().First(x => x.Text == row.Distance);
                var iconPosition = icon.TransformToVisual(page).TransformPoint(new());
                var namePosition = name.TransformToVisual(page).TransformPoint(new());
                var distancePosition = distance.TransformToVisual(page).TransformPoint(new());
                Require(icon.IconKey == row.IconKey && icon.ActualWidth > 0 && icon.ActualHeight > 0,
                    "Location's actual XAML icon binding did not load.");
                Require(iconPosition.X + icon.ActualWidth <= namePosition.X && namePosition.X + name.ActualWidth <= distancePosition.X,
                    "Location icon, name or distance overlaps.");
                samples.Add(new { row.Name, kind = row.Record.NativeKind, icon = icon.IconKey.ToString(),
                    iconX = iconPosition.X, iconY = iconPosition.Y, icon.ActualWidth, icon.ActualHeight,
                    nameX = namePosition.X, nameRight = namePosition.X + name.ActualWidth, distanceX = distancePosition.X });
            }
            await CapturePageAsync(page, Path.Combine(directory, "current-system-original-icons.png"));

            shell.Navigate(typeof(RefitPage));
            await Task.Delay(200);
            var refit = (RefitPage)shell.CurrentPage!;
            var categories = (ListView)refit.FindName("RefitCategoryList");
            foreach (var category in ViewModel.RefitCategories)
            {
                var container = categories.ContainerFromItem(category);
                var source = Descendants(container).OfType<Image>().Select(x => x.Source).OfType<SvgImageSource>().Single();
                Require(source.UriSource.AbsoluteUri == category.Icon, "Refit category did not bind its original game SVG.");
                refitSources.Add(source.UriSource.AbsoluteUri);
            }
            var tabs = (SelectorBar)refit.FindName("InspectorTabs");
            tabs.SelectedItem = tabs.Items[1];
            await Task.Delay(100);
            refit.UpdateLayout();
            Require(tabs.ActualHeight <= 100 && Descendants(tabs).OfType<ImageIcon>().All(x => x.ActualWidth <= 24 && x.ActualHeight <= 24),
                "Refit's engineer icon expanded the inspector tab instead of keeping its icon size.");
            await CapturePageAsync(refit, Path.Combine(directory, "refit-original-icons.png"));
            shell.Navigate(typeof(CurrentSystemPage));
            await Task.Delay(100);

            // Render the actual filter content without showing a Popup, which
            // could be repositioned by Windows onto the player's foreground.
            var filter = (Flyout)Descendants(page).OfType<DropDownButton>().Single().Flyout;
            var filterContent = (FrameworkElement)filter.Content;
            filter.Content = null;
            var panel = new StackPanel { Spacing = 16 };
            panel.Children.Add(new TextBlock { Text = "当前星系 · 游戏原始筛选图标", FontSize = 24 });
            panel.Children.Add(filterContent);
            var filterPage = new Page { Background = page.Background,
                Content = new Border { Padding = new(32), Child = panel, Background = (Brush)Current.Resources["PanelBrush"] } };
            MainWindow.AppWindow.Resize(new(900, 1450));
            MainWindow.Content = filterPage;
            await CapturePageAsync(filterPage, Path.Combine(directory, "current-system-filters.png"));
            Require(Descendants(filterContent).OfType<GameIcon>().Count() == 10, "A filter category has no original icon.");

            var grid = new Grid { ColumnSpacing = 16, RowSpacing = 10, Margin = new(28) };
            for (var column = 0; column < 6; column++) grid.ColumnDefinitions.Add(new());
            var icons = Enum.GetValues<GameUiIcon>();
            for (var index = 0; index < icons.Length; index++)
            {
                if (index % 6 == 0) grid.RowDefinitions.Add(new() { Height = GridLength.Auto });
                var card = new StackPanel { Spacing = 5, Margin = new(4), HorizontalAlignment = HorizontalAlignment.Stretch };
                card.Children.Add(new GameIcon { IconKey = icons[index], Width = 46, Height = 46, HorizontalAlignment = HorizontalAlignment.Center });
                card.Children.Add(new TextBlock { Text = icons[index].ToString(), FontSize = 12, TextAlignment = TextAlignment.Center,
                    MaxWidth = 180, TextWrapping = TextWrapping.Wrap, HorizontalAlignment = HorizontalAlignment.Center });
                Grid.SetColumn(card, index % 6); Grid.SetRow(card, index / 6); grid.Children.Add(card);
            }
            grid.RowDefinitions.Add(new() { Height = GridLength.Auto });
            var rating = new RatingControl { MaxRating = 5, Value = 3, ItemInfo = new RatingItemImageInfo {
                Image = new BitmapImage(new("ms-appx:///Assets/GameIcons/EngineeringGradeSelected.png")),
                UnsetImage = new BitmapImage(new("ms-appx:///Assets/GameIcons/EngineeringGradeEmpty.png")) } };
            Grid.SetRow(rating, grid.RowDefinitions.Count - 1); Grid.SetColumnSpan(rating, 6); grid.Children.Add(rating);
            var catalogue = new Page { Background = (Brush)Current.Resources["PanelBrush"], Content = grid };
            MainWindow.AppWindow.Resize(new(2200, 1800));
            MainWindow.Content = catalogue;
            await CapturePageAsync(catalogue, Path.Combine(directory, "game-icon-catalogue.png"));
            Require(Descendants(catalogue).OfType<GameIcon>().Count() == icons.Length, "Incomplete original icon catalogue.");
        }
        catch (Exception error) { failure = error.ToString(); }
        await File.WriteAllTextAsync(reportPath, JsonSerializer.Serialize(new { samples, refitSources, failure, uiError = ViewModel.ErrorMessage,
            fixtureOnly = true, gameChannelBound = Runtime.FlightDriver is not null, journalEvents = Runtime.Journal.Sequence },
            new JsonSerializerOptions { WriteIndented = true }));
        MainWindow.Close();
    }
}