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 XFEEDToolBox.Controls;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Outfitting;
using XFEEDToolBox.Views;

namespace XFEEDToolBox;
public partial class App
{
    private static async Task<object> RunPreviewLayoutProbeAsync(string directory)
    {
        void Require(bool value,string message){if(!value)throw new InvalidOperationException(message);}
        Require(ViewModel.OfflinePreview,"Layout probe must use an isolated offline directory.");
        MainWindow.AppWindow.Move(new(-30000,-30000));MainWindow.AppWindow.Resize(new(2900,1600));MainWindow.AppWindow.Show(false);
        var shell=AppShellPage.Current!;shell.Navigate(typeof(MainPage));await Task.Delay(150);
        var home=(MainPage)shell.CurrentPage!;var preview=(ShipModelView)home.FindName("ShipSchematic");var card=(Border)home.FindName("CurrentShipCard");
        ViewModel.HomeShipType="anaconda";ViewModel.Ship="巨蟒";ViewModel.ShipOriginalName="Anaconda";ViewModel.HomeShipDetail="41 个模块 · 装配已读取";
        card.StartBringIntoView(new BringIntoViewOptions{AnimationDesired=false});await Task.Delay(200);
        async Task Ready(ShipModelView model){await Task.Delay(150);var until=DateTime.UtcNow.AddSeconds(25);while((!model.IsRendering||model.Frames<2)&&DateTime.UtcNow<until)await Task.Delay(60);Require(model.IsRendering,"Model did not start: "+model.RenderError);}
        await Ready(preview);
        preview.FitToViewport=false;await Ready(preview);var before=await preview.CaptureFrameAtAsync(12);
        using(await preview.FreezeForXamlProbeAsync(12))await CaptureRefinementElementAsync(card,Path.Combine(directory,"home-before.png"));
        preview.FitToViewport=true;await Ready(preview);var after=await preview.CaptureFrameAtAsync(12);
        using(await preview.FreezeForXamlProbeAsync(12))await CaptureRefinementElementAsync(card,Path.Combine(directory,"home-after.png"));
        await SaveModelFrameAsync(before,Path.Combine(directory,"home-model-before.png"));await SaveModelFrameAsync(after,Path.Combine(directory,"home-model-after.png"));
        var framing=new List<object>();
        foreach(var type in new[]{"anaconda","cutter","sidewinder"})
        {
            ViewModel.HomeShipType=type;await Ready(preview);
            foreach(var seconds in new[]{0d,24,48})
            {
                var frame=await preview.CaptureFrameAtAsync(seconds);framing.Add(new{type,seconds,size=new[]{frame.Width,frame.Height},bounds=MeasureHologramFrame(frame)});
            }
        }
        var responsiveWindows=new List<object>();
        ViewModel.HomeShipType="anaconda";await Ready(preview);
        foreach(var scenario in new[]{(name:"narrow",width:950,height:1500),(name:"ultrawide",width:3600,height:1080)})
        {
            MainWindow.AppWindow.Resize(new(scenario.width,scenario.height));MainWindow.AppWindow.Show(false);
            var details=(StackPanel)home.FindName("ShipDetails");
            (double page,double width,double height,int row) previous=default;var stable=0;
            var deadline=DateTime.UtcNow.AddSeconds(8);
            while(stable<4&&DateTime.UtcNow<deadline)
            {
                await Task.Delay(90);home.UpdateLayout();
                var current=(page:home.ActualWidth,width:preview.ActualWidth,height:preview.ActualHeight,row:Grid.GetRow(details));
                stable=current==previous&&current.width>0&&current.height>0?stable+1:0;previous=current;
            }
            Require(stable>=4,"Dashboard size did not stabilize for "+scenario.name);
            Require(Grid.GetRow(details)==(home.ActualWidth<700?1:0),"Ship details did not follow the responsive layout for "+scenario.name);
            card.StartBringIntoView(new BringIntoViewOptions{AnimationDesired=false});await Task.Delay(180);await Ready(preview);
            var frame=await preview.CaptureFrameAtAsync(12);var bounds=MeasureHologramFrame(frame);
            var measured=JsonSerializer.SerializeToElement(bounds);
            Require(measured.GetProperty("marginOnEverySide").GetBoolean(),"Model glow was clipped at "+scenario.name);
            var scale=home.XamlRoot.RasterizationScale;
            Require(Math.Abs(frame.Width-preview.ActualWidth*scale)<=2&&Math.Abs(frame.Height-preview.ActualHeight*scale)<=2,"GPU frame retained a stale viewport at "+scenario.name);
            var modelOrigin=preview.TransformToVisual(card).TransformPoint(new(0,0));
            var detailsOrigin=details.TransformToVisual(card).TransformPoint(new(0,0));
            Require(Grid.GetRow(details)==1?modelOrigin.Y+preview.ActualHeight<=detailsOrigin.Y+1:modelOrigin.X+preview.ActualWidth<=detailsOrigin.X+1,"Ship details overlap the preview at "+scenario.name);
            var modelPath=Path.Combine(directory,"home-"+scenario.name+"-model.png");
            var cardPath=Path.Combine(directory,"home-"+scenario.name+"-card.png");
            await SaveModelFrameAsync(frame,modelPath);
            using(await preview.FreezeForXamlProbeAsync(12))await CaptureRefinementElementAsync(card,cardPath);
            responsiveWindows.Add(new{scenario.name,requestedWindow=new[]{scenario.width,scenario.height},actualWindow=new[]{MainWindow.AppWindow.Size.Width,MainWindow.AppWindow.Size.Height},pageWidth=home.ActualWidth,
                previewSize=new[]{preview.ActualWidth,preview.ActualHeight},gpuSize=new[]{frame.Width,frame.Height},detailsRow=Grid.GetRow(details),modelPath,cardPath,bounds});
        }
        MainWindow.AppWindow.Resize(new(2900,1600));MainWindow.AppWindow.Show(false);await Task.Delay(250);
        var fixture=GetArgument(Environment.GetCommandLineArgs(),"--refit-fixture")!;
        using var fixtureJson=JsonDocument.Parse(await File.ReadAllTextAsync(fixture));
        var document=(fixtureJson.RootElement.TryGetProperty("document",out var wrapped)?wrapped:fixtureJson.RootElement)
            .Deserialize<ShipRefitDocument>(ToolboxSettings.JsonOptions)!;
        shell.Navigate(typeof(RefitPage));await Task.Delay(180);ViewModel.LoadRefitProbeDocument(document);await Task.Delay(350);
        var refit=(RefitPage)shell.CurrentPage!;var background=(ShipModelView)refit.FindName("RefitShipModel");await Ready(background);
        var panels=new[]{"CategoryPanel","SlotPanel","InspectorPanel"}.Select(name=>(Border)refit.FindName(name)).ToArray();
        var brushes=panels.Select(panel=>(SolidColorBrush)panel.Background).ToArray();
        Require(brushes.All(brush=>brush.Color.A==80),"Refit panels did not apply the shared 31% opacity brush.");
        using(await background.FreezeForXamlProbeAsync(12))
        {
            foreach(var panel in panels)panel.Background=new SolidColorBrush(Windows.UI.Color.FromArgb(255,17,29,43));
            await CapturePageAsync(refit,Path.Combine(directory,"refit-before.png"));
            for(var i=0;i<panels.Length;i++)panels[i].Background=brushes[i];
            MainWindow.AppWindow.Show(false);await Task.Delay(60);await CapturePageAsync(refit,Path.Combine(directory,"refit-after.png"));
        }
        return new{refitPanelAlpha=80,refitPanelOpacity=80/255d,homeBefore=MeasureHologramFrame(before),homeAfter=MeasureHologramFrame(after),framing,responsiveWindows,gameActionsInvoked=false};
    }
}