Reuse canvas scenes across viewport and interaction metadata changes

This commit is contained in:
2026-11-09 21:46:58 +08:00
parent bb5bc9d8e9
commit 732c15f7bf
5 changed files with 69 additions and 5 deletions
@@ -0,0 +1,27 @@
import {fault} from '../canvas-core/values.ts';
import type {Document,Registry} from '../canvas-core/types.ts';
import type {SessionSnapshot,ViewState} from '../canvas-core/gestures.ts';
import type {DocumentQueries} from '../canvas-core/queries.ts';
import {createGeometryProjectionCache} from './geometry-cache.ts';
import {projectCanvas} from './projection.ts';
import type {RendererCatalog} from './renderers.ts';
/** One view's derived scene. Viewport/tool/mode and task status do not change scene inputs. */
export function createSceneProjection(){
let geometry=createGeometryProjectionCache();
type Inputs={owner:object;document:Document;registry:Registry;catalog:RendererCatalog;canvasId:ViewState['canvasId'];selection:ViewState['selection'];preview:NonNullable<SessionSnapshot['gesture']>['preview']|undefined;edgeId:string|undefined;path:NonNullable<SessionSnapshot['connectionGesture']>['path']|undefined};
let previous:Inputs|undefined,value:ReturnType<typeof projectCanvas>|undefined;
return Object.freeze({
project(owner:object,document:Document,view:ViewState,sessions:SessionSnapshot,registry:Registry,catalog:RendererCatalog,queries?:DocumentQueries){
if(queries&&queries.document!==document)throw fault('stale_query_snapshot');
if(queries&&queries.registry!==registry)throw fault('query_registry_changed');
const preview=sessions.gesture?.preview,connection=sessions.connectionGesture;
const next:Inputs={owner,document,registry,catalog,canvasId:view.canvasId,selection:view.selection,preview:preview?.size?preview:undefined,edgeId:connection?.target.id,path:connection?.path};
if(previous&&Object.keys(next).every(key=>Object.is(next[key as keyof Inputs],previous![key as keyof Inputs])))return value!;
// Read the captured session, not a newer live gesture during an older React render.
const result=projectCanvas(document,view.canvasId,registry,view.selection,id=>next.preview?.get(id),connection,catalog,{queries,geometry,owner});
previous=next;value=result;return result;
},
clear(){previous=undefined;value=undefined;geometry=createGeometryProjectionCache();},
});
}