using System.Numerics; using XFEEDToolBox.Core.Galaxy; namespace XFEEDToolBox.Controls; public sealed partial class GalaxyMapView { private readonly GalaxyOriginalFrameFadeState originalFrameFadeState=new(); private Microsoft.UI.Dispatching.DispatcherQueueTimer? originalFrameFadeTimer; private double originalFrameFadeAt; private GalaxyOriginalFrameFade? originalFrameFade; private bool originalFrameFadeProbeManual; internal int FrameFadedStarsForProbe {get;private set;} internal float? FrameFadeTransitionForProbe=>originalFrameFadeState.CurrentTransition; private bool HasOriginalFrameFadeInputs=>loaded&&pageActive&&CatalogueSelection is{OriginalViewMode:not null} selection&& double.IsFinite(selection.Descriptor.InnerRadius)&&selection.Descriptor.InnerRadius<=float.MaxValue; private void PrepareOriginalFrameFade() { if(!HasOriginalFrameFadeInputs){StopOriginalFrameFade();return;} if(!originalFrameFadeState.IsActive) {originalFrameFadeState.Activate();originalFrameFadeAt=MonotonicMilliseconds;} if(originalFrameFadeTimer is null) { originalFrameFadeTimer=DispatcherQueue.CreateTimer();originalFrameFadeTimer.Interval=TimeSpan.FromMilliseconds(16); originalFrameFadeTimer.Tick+=(_,_)=> { if(!HasOriginalFrameFadeInputs){StopOriginalFrameFade();return;} var now=MonotonicMilliseconds;var elapsed=(now-originalFrameFadeAt)/1000;originalFrameFadeAt=now; AdvanceOriginalFrameFade(elapsed); }; } if(!originalFrameFadeProbeManual&&!originalFrameFadeTimer.IsRunning) {originalFrameFadeAt=MonotonicMilliseconds;originalFrameFadeTimer.Start();} originalFrameFade=originalFrameFadeState.TryCreateForCamera(Camera,(float)CatalogueSelection!.Descriptor.InnerRadius,out var fade)?fade:null; } private void AdvanceOriginalFrameFade(double elapsedSeconds) { if(!HasOriginalFrameFadeInputs)return; var before=originalFrameFadeState.CurrentTransition; if(!GalaxyOriginalFrameFadeClock.TryFromElapsedSeconds(elapsedSeconds,out var frameValue)|| !originalFrameFadeState.TryAdvanceForCamera(Camera,(float)CatalogueSelection!.Descriptor.InnerRadius,CatalogueSelection.OriginalViewMode,frameValue)) {originalFrameFade=null;Invalidate();return;} originalFrameFade=originalFrameFadeState.TryCreateForCamera(Camera,(float)CatalogueSelection.Descriptor.InnerRadius,out var fade)?fade:null; if(before!=originalFrameFadeState.CurrentTransition)Invalidate(); else originalFrameFadeTimer?.Stop(); } private void StopOriginalFrameFade() {originalFrameFadeTimer?.Stop();originalFrameFadeState.Deactivate();originalFrameFade=null;originalFrameFadeAt=0;} private float PointFrameOpacity(Sample sample) { // Read the current profile's copied tables, never a cached cell row's // membership. D50 presence is independent of its consumed pending bit. if(originalFrameFade is not{} fade||CatalogueSelection is not{} selection|| !selection.TryFrameFadeFlags(sample.System,out var bypass,out var far))return 1; var p=sample.System.Position; return fade.Alpha(new((float)p.X,(float)p.Y,(float)p.Z),bypass,far); } private float? CurrentOriginalSize(GalacticSystem system)=>CatalogueSelection is{} selection ?selection.OriginalSize(system):system.OriginalAppearance?.ActiveSize; internal void AdvanceOriginalFrameFadeForProbe(double elapsedSeconds,int ticks) { var args=Environment.GetCommandLineArgs(); if(!args.Contains("--offline-preview")||!args.Contains("--probe-galaxy-rework")||ticks is <0 or >4096) throw new InvalidOperationException("仅允许独立离线星图验收推进原淡出时钟。"); PrepareOriginalFrameFade();for(var i=0;i