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 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(); 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(); 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.UtcNow0&¤t.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(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