using System.Security.Cryptography; using System.Text.Json; using Microsoft.UI.Xaml.Media; using Windows.Foundation; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Navigation; using XFEEDToolBox.Core.Rendering; using XFEEDToolBox.Core.Services; using XFEEDToolBox.Views; namespace XFEEDToolBox; public partial class App { private static async Task RunLocalSystemMapProbeAsync(string directory) { Directory.CreateDirectory(directory); var args=Environment.GetCommandLineArgs();var recording=GetArgument(args,"--system-map-snapshot"); var recorded=recording is not null;string? recordingHash=null,failure=null; var checks=new List();var captures=new List();var states=new List();var failedChecks=0;var unconfirmedChecks=0; var size=MainWindow.AppWindow.Size;var search=ViewModel.CurrentSystemSearch; var selected=ViewModel.SelectedSystemLocation?.Record.Identity; bool[] ReadFilters()=>[ViewModel.ShowSystemStars,ViewModel.ShowSystemAsteroids,ViewModel.ShowSystemPlanets,ViewModel.ShowSystemLandablePlanets,ViewModel.ShowSystemSettlements,ViewModel.ShowSystemStations,ViewModel.ShowSystemCarriers,ViewModel.ShowSystemPoints,ViewModel.ShowSystemSignals,ViewModel.ShowSystemOther]; void SetFilters(bool[] value) { ViewModel.ShowSystemStars=value[0];ViewModel.ShowSystemAsteroids=value[1];ViewModel.ShowSystemPlanets=value[2];ViewModel.ShowSystemLandablePlanets=value[3]; ViewModel.ShowSystemSettlements=value[4];ViewModel.ShowSystemStations=value[5];ViewModel.ShowSystemCarriers=value[6];ViewModel.ShowSystemPoints=value[7];ViewModel.ShowSystemSignals=value[8];ViewModel.ShowSystemOther=value[9]; } var filters=ReadFilters(); void Check(string id,bool? passed,string evidence) {if(passed==false)failedChecks++;if(passed is null)unconfirmedChecks++;checks.Add(new{id,status=passed is null?"unconfirmed":passed.Value?"passed":"failed",evidence});} void Require(bool passed,string message){if(!passed)throw new InvalidOperationException(message);} CurrentSystemSnapshot? source=null;CurrentSystemPage? page=null; object? Bounds(FrameworkElement? element) { if(page is null||element is null||element.ActualWidth<=0||element.ActualHeight<=0)return null; try{var point=element.TransformToVisual(page).TransformPoint(new(0,0));return new{element.Name,x=point.X,y=point.Y,width=element.ActualWidth,height=element.ActualHeight,right=point.X+element.ActualWidth,bottom=point.Y+element.ActualHeight};} catch(ArgumentException){return null;}catch(InvalidOperationException){return null;} } bool Visible(FrameworkElement element) { DependencyObject? current=element; while(current is not null) {if(current is UIElement ui&&ui.Visibility!=Visibility.Visible)return false;if(ReferenceEquals(current,page))break;current=VisualTreeHelper.GetParent(current);} return element.ActualWidth>0&&element.ActualHeight>0; } bool Fits(FrameworkElement child,FrameworkElement container) { if(child.ActualWidth<=0||child.ActualHeight<=0)return false; var at=child.TransformToVisual(container).TransformPoint(new(0,0)); return at.X>=-1&&at.Y>=-1&&at.X+child.ActualWidth<=container.ActualWidth+1&&at.Y+child.ActualHeight<=container.ActualHeight+1; } static bool Overlaps(FrameworkElement first,FrameworkElement second,FrameworkElement relativeTo) { var a=first.TransformToVisual(relativeTo).TransformPoint(new(0,0));var b=second.TransformToVisual(relativeTo).TransformPoint(new(0,0)); return a.Xb.X+1&&a.Yb.Y+1; } void RecordedLabel() { if(!recorded||source is null)return; ViewModel.CurrentSystemStatus=$"录制目录核验 · {source.ObservedAt.ToLocalTime():yyyy-MM-dd HH:mm:ss zzz} · {ViewModel.CurrentSystemLocations.Count}/{source.Locations.Count} 个地点"; ViewModel.SystemControlAvailability="录制目录核验 · 未连接游戏驾驶接口。"; ViewModel.SystemFlightStatus="录制目录核验 · 仅验证浏览交互,不启动驾驶。"; } static bool ProjectionChanged(LocalSystemProjection[] before,LocalSystemProjection[] after) { var old=before.ToDictionary(point=>point.Node.Location.Identity); return after.Any(point=>old.TryGetValue(point.Node.Location.Identity,out var previous)&& (Math.Abs(point.X-previous.X)>.1||Math.Abs(point.Y-previous.Y)>.1||Math.Abs(point.Depth-previous.Depth)>.001)); } async Task<(string? GpuHash,LocalSystemProjection[] Projections,LocalSystemCamera Camera)> Capture(string name) { Require(page is not null,"The system page is not available.");RecordedLabel();page!.UpdateLayout();await Task.Delay(100); var map=page.MapForProbe;map.RenderNowForProbe(); var snapshot=ViewModel.CurrentSystemSceneSnapshot??throw new InvalidOperationException("The current system snapshot disappeared."); var rows=ViewModel.CurrentSystemLocations.Select(row=>row.Record).ToArray(); var projections=map.ProjectedLocations.ToArray();var camera=map.CameraState; var actual=snapshot.Locations.GroupBy(row=>row.Identity).ToDictionary(group=>group.Key,group=>group.First()); var expected=new LocalSystemScene(snapshot,null,map.ViewOrientationForProbe).Nodes.ToDictionary(node=>node.Location.Identity); var fromSource=rows.All(row=>actual.TryGetValue(row.Identity,out var known)&&known==row) &&projections.All(point=>actual.TryGetValue(point.Node.Location.Identity,out var known)&&known==point.Node.Location &&expected.TryGetValue(point.Node.Location.Identity,out var node)&&(point.Node.Position-node.Position).Length<1e-9); string? gpuHash=null;object? gpu=null;IDisposable? frozen=null; try { var frame=map.CapturePixelsForProbe();gpuHash=Convert.ToHexString(SHA256.HashData(frame.Pixels)); gpu=new{frame.Width,frame.Height,sha256=gpuHash,bytes=frame.Pixels.Length,source="actual-D3D11-readback"}; frozen=await map.FreezeForXamlProbeAsync();page.UpdateLayout();await Task.Delay(60); var path=Path.Combine(directory,name+".png");await CapturePageAsync(page,path);captures.Add(path); } catch(Exception error) { Check("gpu-"+name,false,error.ToString()); var path=Path.Combine(directory,name+"-fallback.png");await CapturePageAsync(page,path);captures.Add(path); } finally{frozen?.Dispose();} FrameworkElement Find(string id)=>(FrameworkElement)(page.FindName(id)??throw new InvalidOperationException("Missing system page element: "+id)); var list=Find("LocationsList");var card=Find("DestinationCard");var scene=Find("SceneLayout"); var viewport=Find("ViewportHost");var actions=Find("DestinationActions"); var detail=((card as Border)?.Child as Grid)?.Children.OfType().FirstOrDefault(element=>element!=actions); var toolbar=Descendants(viewport).OfType().FirstOrDefault(panel=>panel.Children.OfType