@vibecook/ice 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/chunk-5S7GSXJG.js +6003 -0
- package/dist/chunk-5S7GSXJG.js.map +1 -0
- package/dist/chunk-BCJ47SX7.js +550 -0
- package/dist/chunk-BCJ47SX7.js.map +1 -0
- package/dist/chunk-FIAXPNNY.js +1446 -0
- package/dist/chunk-FIAXPNNY.js.map +1 -0
- package/dist/devtools.js +417 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom.js +41 -0
- package/dist/dom.js.map +1 -0
- package/dist/index.js +450 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.js +63 -0
- package/dist/kernel.js.map +1 -0
- package/dist/r3f.js +1101 -0
- package/dist/r3f.js.map +1 -0
- package/dist/react.js +440 -0
- package/dist/react.js.map +1 -0
- package/dist/types/packages/core/src/boot/hmr.d.ts +12 -0
- package/dist/types/packages/core/src/catalog/camera-derived.d.ts +144 -0
- package/dist/types/packages/core/src/catalog/gesture.d.ts +254 -0
- package/dist/types/packages/core/src/catalog/graph.d.ts +55 -0
- package/dist/types/packages/core/src/catalog/index.d.ts +32 -0
- package/dist/types/packages/core/src/catalog/pointer.d.ts +111 -0
- package/dist/types/packages/core/src/catalog/scene.d.ts +34 -0
- package/dist/types/packages/core/src/catalog/selection-presence.d.ts +53 -0
- package/dist/types/packages/core/src/catalog/settings-resources.d.ts +46 -0
- package/dist/types/packages/core/src/doc/autosave.d.ts +69 -0
- package/dist/types/packages/core/src/doc/bootstrap.d.ts +74 -0
- package/dist/types/packages/core/src/doc/broadcast-relay.d.ts +52 -0
- package/dist/types/packages/core/src/doc/channels.d.ts +49 -0
- package/dist/types/packages/core/src/doc/doc-commit-sink.d.ts +22 -0
- package/dist/types/packages/core/src/doc/doc-kit.d.ts +50 -0
- package/dist/types/packages/core/src/doc/envelope.d.ts +36 -0
- package/dist/types/packages/core/src/doc/migrate.d.ts +69 -0
- package/dist/types/packages/core/src/doc/version-gate.d.ts +49 -0
- package/dist/types/packages/core/src/engine/commit-sink.d.ts +61 -0
- package/dist/types/packages/core/src/engine/engine.d.ts +62 -0
- package/dist/types/packages/core/src/engine/frame-info.d.ts +16 -0
- package/dist/types/packages/core/src/engine/instantiate.d.ts +45 -0
- package/dist/types/packages/core/src/engine/pipeline.d.ts +17 -0
- package/dist/types/packages/core/src/engine/reflectors.d.ts +56 -0
- package/dist/types/packages/core/src/facade/create-canvas-engine.d.ts +120 -0
- package/dist/types/packages/core/src/guards/dev.d.ts +2 -0
- package/dist/types/packages/core/src/guards/guarded-tx.d.ts +51 -0
- package/dist/types/packages/core/src/guards/live-writer.d.ts +33 -0
- package/dist/types/packages/core/src/guards/resource-writer.d.ts +17 -0
- package/dist/types/packages/core/src/helpers/phase-set.d.ts +70 -0
- package/dist/types/packages/core/src/helpers/version-stamps.d.ts +55 -0
- package/dist/types/packages/core/src/index.d.ts +63 -0
- package/dist/types/packages/core/src/input/measure-queue.d.ts +30 -0
- package/dist/types/packages/core/src/input/queue.d.ts +60 -0
- package/dist/types/packages/core/src/interaction/install.d.ts +58 -0
- package/dist/types/packages/core/src/nav/nested-canvas.d.ts +62 -0
- package/dist/types/packages/core/src/ops/cascade.d.ts +18 -0
- package/dist/types/packages/core/src/ops/claims.d.ts +15 -0
- package/dist/types/packages/core/src/ops/gestures.d.ts +10 -0
- package/dist/types/packages/core/src/ops/point-pick.d.ts +42 -0
- package/dist/types/packages/core/src/ops/port-geometry.d.ts +17 -0
- package/dist/types/packages/core/src/ops/selection.d.ts +14 -0
- package/dist/types/packages/core/src/presence/index.d.ts +7 -0
- package/dist/types/packages/core/src/presence/presence-kit.d.ts +39 -0
- package/dist/types/packages/core/src/presence/publish.d.ts +14 -0
- package/dist/types/packages/core/src/presence/remote-cursors.d.ts +18 -0
- package/dist/types/packages/core/src/schema/meta.d.ts +43 -0
- package/dist/types/packages/core/src/schema/prefab.d.ts +69 -0
- package/dist/types/packages/core/src/settings/defaults.d.ts +56 -0
- package/dist/types/packages/core/src/systems/camera-sim.d.ts +19 -0
- package/dist/types/packages/core/src/systems/chrome.d.ts +48 -0
- package/dist/types/packages/core/src/systems/cleanup.d.ts +19 -0
- package/dist/types/packages/core/src/systems/l0-input.d.ts +31 -0
- package/dist/types/packages/core/src/systems/l1-pick.d.ts +44 -0
- package/dist/types/packages/core/src/systems/l1-wires.d.ts +30 -0
- package/dist/types/packages/core/src/systems/l2-arbitrate.d.ts +40 -0
- package/dist/types/packages/core/src/systems/l2-recognize.d.ts +45 -0
- package/dist/types/packages/core/src/systems/l3-behave.d.ts +24 -0
- package/dist/types/packages/core/src/systems/l3-claim.d.ts +26 -0
- package/dist/types/packages/core/src/systems/l3-connect.d.ts +57 -0
- package/dist/types/packages/core/src/systems/l3-draw.d.ts +21 -0
- package/dist/types/packages/core/src/systems/l3-drop.d.ts +21 -0
- package/dist/types/packages/core/src/systems/l3-marquee.d.ts +35 -0
- package/dist/types/packages/core/src/systems/l3-ports.d.ts +30 -0
- package/dist/types/packages/core/src/systems/l3-resize.d.ts +17 -0
- package/dist/types/packages/core/src/systems/l3-snap.d.ts +19 -0
- package/dist/types/packages/core/src/systems/l4-cursor.d.ts +24 -0
- package/dist/types/packages/core/src/systems/measure-ingest.d.ts +26 -0
- package/dist/types/packages/core/src/tools/define-tool.d.ts +79 -0
- package/dist/types/packages/core/src/widget/define-widget.d.ts +124 -0
- package/dist/types/packages/core/src/widget/equip.d.ts +14 -0
- package/dist/types/packages/core/src/widget/mount-store.d.ts +47 -0
- package/dist/types/packages/core/src/widget/props.d.ts +98 -0
- package/dist/types/packages/core/src/widget/spawn.d.ts +30 -0
- package/dist/types/packages/devtools/src/index.d.ts +8 -0
- package/dist/types/packages/devtools/src/panel.d.ts +48 -0
- package/dist/types/packages/dom/src/host.d.ts +24 -0
- package/dist/types/packages/dom/src/index.d.ts +19 -0
- package/dist/types/packages/dom/src/loop.d.ts +11 -0
- package/dist/types/packages/dom/src/measure-adapter.d.ts +31 -0
- package/dist/types/packages/dom/src/measure-wiring.d.ts +49 -0
- package/dist/types/packages/dom/src/planes.d.ts +33 -0
- package/dist/types/packages/dom/src/pointer-adapter.d.ts +48 -0
- package/dist/types/packages/dom/src/reflectors/chrome.d.ts +33 -0
- package/dist/types/packages/dom/src/reflectors/cursor.d.ts +21 -0
- package/dist/types/packages/dom/src/reflectors/dom-widgets.d.ts +54 -0
- package/dist/types/packages/dom/src/reflectors/graybox.d.ts +31 -0
- package/dist/types/packages/dom/src/reflectors/grid.d.ts +63 -0
- package/dist/types/packages/dom/src/reflectors/plane-transform.d.ts +38 -0
- package/dist/types/packages/dom/src/reflectors/remote-cursors.d.ts +20 -0
- package/dist/types/packages/dom/src/reflectors/wires.d.ts +88 -0
- package/dist/types/packages/ice/src/devtools.d.ts +1 -0
- package/dist/types/packages/ice/src/dom.d.ts +1 -0
- package/dist/types/packages/ice/src/index.d.ts +1 -0
- package/dist/types/packages/ice/src/kernel.d.ts +1 -0
- package/dist/types/packages/ice/src/r3f.d.ts +1 -0
- package/dist/types/packages/ice/src/react.d.ts +1 -0
- package/dist/types/packages/kernel/src/anchors.d.ts +18 -0
- package/dist/types/packages/kernel/src/bezier.d.ts +38 -0
- package/dist/types/packages/kernel/src/coords.d.ts +67 -0
- package/dist/types/packages/kernel/src/eviction.d.ts +23 -0
- package/dist/types/packages/kernel/src/index.d.ts +13 -0
- package/dist/types/packages/kernel/src/shapes.d.ts +22 -0
- package/dist/types/packages/kernel/src/snap.d.ts +44 -0
- package/dist/types/packages/kernel/src/spatial-index.d.ts +16 -0
- package/dist/types/packages/kernel/src/zoom-bands.d.ts +19 -0
- package/dist/types/packages/r3f/src/bridge.d.ts +68 -0
- package/dist/types/packages/r3f/src/composite-material.d.ts +17 -0
- package/dist/types/packages/r3f/src/compositor-pass.d.ts +83 -0
- package/dist/types/packages/r3f/src/dev-write-trap.d.ts +30 -0
- package/dist/types/packages/r3f/src/gl-root.d.ts +21 -0
- package/dist/types/packages/r3f/src/gl-router.d.ts +60 -0
- package/dist/types/packages/r3f/src/index.d.ts +16 -0
- package/dist/types/packages/r3f/src/island-state.d.ts +68 -0
- package/dist/types/packages/r3f/src/island.d.ts +13 -0
- package/dist/types/packages/r3f/src/pool.d.ts +56 -0
- package/dist/types/packages/r3f/src/resource-registry.d.ts +30 -0
- package/dist/types/packages/r3f/src/use-island-frame.d.ts +24 -0
- package/dist/types/packages/react/src/engine-context.d.ts +31 -0
- package/dist/types/packages/react/src/hooks.d.ts +40 -0
- package/dist/types/packages/react/src/index.d.ts +14 -0
- package/dist/types/packages/react/src/infinite-canvas.d.ts +71 -0
- package/dist/types/packages/react/src/keymap.d.ts +42 -0
- package/dist/types/packages/react/src/use-commit.d.ts +35 -0
- package/dist/types/packages/react/src/use-presence.d.ts +23 -0
- package/dist/types/packages/react/src/use-tool.d.ts +4 -0
- package/dist/types/packages/react/src/widget-root.d.ts +33 -0
- package/package.json +112 -0
package/dist/r3f.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../r3f/src/island-state.ts","../../r3f/src/dev-write-trap.ts","../../r3f/src/bridge.ts","../../r3f/src/compositor-pass.ts","../../r3f/src/gl-root.tsx","../../r3f/src/composite-material.ts","../../r3f/src/island.tsx","../../r3f/src/use-island-frame.ts","../../r3f/src/pool.ts","../../r3f/src/resource-registry.ts","../../r3f/src/gl-router.ts"],"sourcesContent":["/**\n * Module-side island render state (design-004 §3 fix #3: ZERO render→ECS\n * writes — v1 kept this as an ECS component `R3FRenderState` and wrote it\n * from inside `useFrame`, which the engine laws ban; band/generation/paint\n * bookkeeping now lives here, outside the world entirely).\n *\n * One entry per GL widget the compositor has ever touched this session.\n * Entries OUTLIVE island unmount (cull) — that is the retention decoupling:\n * a culled widget's entry keeps its `fboGeneration`/`paintedAt` so re-entry\n * composites from the retained texture (phase Warm) instead of re-waking.\n * Entries die only on entity death, world reset, or `drop()`.\n *\n * Pure state + counters; no three.js, no ECS, no timing — the GLViews frame\n * pass reads/writes it synchronously.\n */\nimport type { IslandPhase } from \"@ice/kernel\";\n\n/** Resolution + band an island's FBO was last painted at (v1 `paintedAt`). */\nexport interface PaintedAt {\n readonly w: number;\n readonly h: number;\n readonly dpr: number;\n /** The zoom BAND painted at (not live zoom) — hysteresis compares against it. */\n readonly band: number;\n}\n\nexport interface IslandRenderState {\n phase: IslandPhase;\n /** Bumped by dirt (props Tier-3, size dirt, manual invalidate). */\n paintGeneration: number;\n /** Generation last painted into the FBO; -1 = no valid texture (fresh or evicted). */\n fboGeneration: number;\n paintedAt: PaintedAt;\n /** Live `useIslandFrame` subscriptions (animation signal while > 0). */\n animRefs: number;\n /** The widget type declared `animated` (repaint every visible frame). */\n animatedDecl: boolean;\n /**\n * Monotonic stamp of the last repaint — the stagger's FAIRNESS key. Without\n * it, more Hot islands than maxRepaintsPerFrame starves the same island\n * every pass (5 Hot vs cap 4 froze the shapes card, 2026-07-12).\n */\n lastPaintSeq: number;\n /**\n * Composite-quad scale (lift-on-hold): scales the CARD on the canvas —\n * texture, rounded alpha corners and all — instead of the scene content\n * (which the card-sized frustum would crop into hard corners, 2026-07-12\n * field report). ≠1 also pops render order over neighbors.\n */\n compositeScale: number;\n}\n\nconst FRESH_PAINTED_AT: PaintedAt = { w: 0, h: 0, dpr: 1, band: 0 };\n\nexport interface IslandStateStore {\n /** Get-or-create (Cold, unpainted). */\n ensure(key: number): IslandRenderState;\n get(key: number): IslandRenderState | undefined;\n all(): IterableIterator<[number, IslandRenderState]>;\n /** Island dirt: the next frame pass must repaint this island. */\n bumpPaint(key: number): void;\n markPainted(key: number, at: PaintedAt): void;\n /** FBO released (eviction/death): the quad hides until first repaint. */\n markEvicted(key: number): void;\n addAnimRef(key: number): void;\n removeAnimRef(key: number): void;\n /** Animation signal: declared `animated` OR any live `useIslandFrame`. */\n isAnimating(key: number): boolean;\n setAnimatedDecl(key: number, animated: boolean): void;\n drop(key: number): void;\n clear(): void;\n}\n\nexport function createIslandStateStore(): IslandStateStore {\n const entries = new Map<number, IslandRenderState>();\n let paintSeq = 0;\n\n const ensure = (key: number): IslandRenderState => {\n let s = entries.get(key);\n if (s === undefined) {\n s = {\n phase: \"Cold\",\n paintGeneration: 0,\n fboGeneration: -1,\n paintedAt: FRESH_PAINTED_AT,\n animRefs: 0,\n animatedDecl: false,\n lastPaintSeq: 0,\n compositeScale: 1,\n };\n entries.set(key, s);\n }\n return s;\n };\n\n return {\n ensure,\n get: (key) => entries.get(key),\n all: () => entries.entries(),\n bumpPaint(key) {\n ensure(key).paintGeneration += 1;\n },\n markPainted(key, at) {\n const s = ensure(key);\n s.fboGeneration = s.paintGeneration;\n s.paintedAt = at;\n s.lastPaintSeq = ++paintSeq;\n },\n markEvicted(key) {\n const s = entries.get(key);\n if (s !== undefined) s.fboGeneration = -1;\n },\n addAnimRef(key) {\n ensure(key).animRefs += 1;\n },\n removeAnimRef(key) {\n const s = entries.get(key);\n if (s !== undefined && s.animRefs > 0) s.animRefs -= 1;\n },\n isAnimating(key) {\n const s = entries.get(key);\n return s !== undefined && (s.animatedDecl || s.animRefs > 0);\n },\n setAnimatedDecl(key, animated) {\n ensure(key).animatedDecl = animated;\n },\n drop(key) {\n entries.delete(key);\n },\n clear() {\n entries.clear();\n },\n };\n}\n","/**\n * The zero-render→ECS-writes DEV assertion (M7 exit criterion; design-004 §3\n * fix #3). While a compositor frame pass runs — including island paints and\n * `useIslandFrame` callbacks — every world mutation throws with attribution.\n *\n * strata 0.4.0 (petition 4 LANDED): one persistent `world.devOnWrite`\n * registration + an armed flag. The hook is DEV-only, synchronous, and\n * PRE-MUTATION with throws propagating to the mutator's caller — so a throw\n * while armed is a clean veto whose stack names the offender. Fired from\n * strata's internal chokepoints, it covers every route the old own-property\n * mutator shadows could miss: bound/destructured method references, document\n * transactions, sync/attach drains, undo echoes, and any mutator added\n * upstream later. (Raw `batch.col()` column pokes remain the documented\n * carve-out — no chokepoint exists by design.)\n *\n * `enabled` is the app-side production gate the 0.4.0 notes ask for: in an\n * un-shimmed browser production bundle strata's own DEV flag can evaluate\n * true, so registration is gated HERE (default off; demos/traces opt in).\n */\nimport type { World } from \"@ice/core\";\n\nexport interface RenderWriteTrap {\n /** Arm the trap (begin twice without end is a bug — throws). */\n begin(): void;\n /** Disarm; always call in `finally`. */\n end(): void;\n /** Unregister the hook entirely (bridge teardown). */\n dispose(): void;\n readonly enabled: boolean;\n}\n\nexport function createRenderWriteTrap(world: World, enabled: boolean): RenderWriteTrap {\n let armed = false;\n let unregister: (() => void) | null = null;\n\n if (enabled) {\n unregister = world.devOnWrite((kind) => {\n if (!armed) return;\n throw new Error(\n `ice: world mutation (${kind}) during the GL render pass — the render path never writes ECS (design-004 §3). Move the write to a system, an input fact, or an app op OUTSIDE useIslandFrame/render.`,\n );\n });\n }\n\n return {\n enabled,\n begin() {\n if (!enabled) return;\n if (armed) throw new Error(\"ice: render write trap begin() while already armed.\");\n armed = true;\n },\n end() {\n armed = false;\n },\n dispose() {\n armed = false;\n unregister?.();\n unregister = null;\n },\n };\n}\n","/**\n * The GL bridge — the engine↔R3F seam (design-004 §3, two-level invalidation).\n *\n * Owns everything ENGINE-facing: the module-side island state, the island\n * registry (scene+camera handles the frame pass iterates), per-island dirt\n * observers, the `r3fInvalidator` reflector, `useIslandFrame` callbacks, the\n * render write trap, and entity-death cleanup. Everything GL-facing (FBO\n * pool, quads, the actual passes) lives in `GLViews`, whose lifetime is the\n * Canvas/context's — the bridge outlives Canvas remounts (HMR) and carries\n * the invalidation wiring across them.\n *\n * Two-level invalidation, mechanized:\n * - COMPOSITE dirt (cheap — re-run the frame pass, sample cached textures):\n * camera/viewport via the reflector; per-island Position/StackZ Tier-3;\n * island enter/exit via register/unregister. All call `requestFrame()`.\n * - ISLAND dirt (expensive — repaint the FBO): per-island props-group and\n * Size Tier-3 → `bumpPaint()` + `requestFrame()`; the animation signal\n * (declared `animated` / live `useIslandFrame` refs) and band crossings\n * are evaluated IN the frame pass (band repaints suppressed while\n * `Camera.gesturing`; the gesture-end camera write re-fires the reflector,\n * so the once-at-gesture-end repaint needs no extra machinery).\n *\n * Runtime-three-free (type-only imports): unit tests drive the bridge with a\n * real world and fake scene/camera handles, no GL context.\n */\nimport type { OrthographicCamera, Scene } from \"three\";\nimport {\n Camera,\n PrefabId,\n Position,\n Size,\n StackZ,\n Viewport,\n widgets,\n type Engine,\n type Entity,\n} from \"@ice/core\";\nimport { createIslandStateStore, type IslandStateStore } from \"./island-state\";\nimport { createRenderWriteTrap, type RenderWriteTrap } from \"./dev-write-trap\";\n\nexport interface IslandHandle {\n readonly scene: Scene;\n readonly camera: OrthographicCamera;\n}\n\n/** `useIslandFrame` callback: dt in ms, fired only on frames its island paints. */\nexport type IslandFrameCallback = (dtMs: number) => void;\n\nexport interface GLBridgeOpts {\n /** Arm the zero-render→ECS-writes trap (DEV builds / traces). Default false. */\n readonly devAssertRenderWrites?: boolean;\n}\n\nexport interface GLBridge {\n readonly engine: Engine;\n readonly state: IslandStateStore;\n readonly renderAssert: RenderWriteTrap;\n /**\n * Island mount (the `<Island>` component): registers the scene/camera pair,\n * stamps `animatedDecl` from the widget type, and arms the per-island dirt\n * observers. The returned cleanup removes handle + observers ONLY — state\n * and any pooled FBO survive (retention is decoupled from cull; they die on\n * entity death, reset, or eviction).\n */\n registerIsland(entity: Entity, handle: IslandHandle): () => void;\n islandFor(entity: Entity): IslandHandle | undefined;\n islands(): IterableIterator<[Entity, IslandHandle]>;\n /** Subscribe a paint-time callback; holds an animation ref while live. */\n addFrameCallback(entity: Entity, cb: IslandFrameCallback): () => void;\n frameCallbacksFor(entity: Entity): readonly IslandFrameCallback[];\n /** Composite invalidation — schedule a frame pass (coalesced). */\n requestFrame(): void;\n /** Island invalidation — this island must repaint (props/size/manual dirt). */\n bumpPaint(entity: Entity): void;\n /** Composite-quad lift scale (1 = rest). Scales the CARD on the canvas, corners intact. */\n setCompositeScale(entity: Entity, scale: number): void;\n /** GLViews wires R3F's demand-loop `invalidate` here (null on unmount). */\n setInvalidate(fn: (() => void) | null): void;\n /** Tear down reflector + observers + state (doc close / app teardown). */\n uninstall(): void;\n}\n\nexport function createGLBridge(engine: Engine, opts: GLBridgeOpts = {}): GLBridge {\n const world = engine.world;\n const state = createIslandStateStore();\n const islands = new Map<Entity, IslandHandle>();\n const frameCbs = new Map<Entity, Set<IslandFrameCallback>>();\n const renderAssert = createRenderWriteTrap(world, opts.devAssertRenderWrites === true);\n\n // --- composite invalidation plumbing --------------------------------------\n let invalidate: (() => void) | null = null;\n let pending = false; // a requestFrame that arrived before GLViews mounted\n const requestFrame = (): void => {\n if (invalidate !== null) invalidate();\n else pending = true;\n };\n\n // Camera (pan/zoom/gesturing edges) + viewport (resize/dpr) are the global\n // composite dirt sources; everything entity-shaped is observed per island\n // (only GL widgets wake the canvas — a static GL board ignores DOM churn).\n const removeReflector = engine.registerReflector({\n name: \"r3fInvalidator\",\n observe: { resources: [Camera, Viewport] },\n flush: () => requestFrame(),\n });\n\n // Death/reset: drop state so the frame pass releases the pooled FBO on its\n // next reconcile (the bridge is three-free — it never touches the pool).\n const removeWorldObserver = world.observe({\n onDestroy: (e) => {\n if (state.get(e as Entity) !== undefined) {\n state.drop(e as Entity);\n frameCbs.delete(e as Entity);\n requestFrame();\n }\n },\n onReset: () => {\n state.clear();\n frameCbs.clear();\n requestFrame();\n },\n });\n\n return {\n engine,\n state,\n renderAssert,\n\n registerIsland(entity, handle) {\n islands.set(entity, handle);\n const s = state.ensure(entity);\n\n // `animated` declaration comes from the widget type (design-004 §3\n // animation contract — explicit opt-in; plain useFrame is unattributable).\n const type = world.get(entity, PrefabId)?.id;\n const widget = typeof type === \"string\" ? widgets.get(type) : undefined;\n state.setAnimatedDecl(entity, widget?.animated === true);\n\n // Per-island dirt (Tier-3, equality-suppressed, fired at notify()):\n const unsubs: (() => void)[] = [\n // island dirt — content resolution/props changed, FBO stale:\n world.reactive.observeValue(entity, Size, () => {\n state.bumpPaint(entity);\n requestFrame();\n }),\n // composite dirt — quad transform/order changed, texture still good:\n world.reactive.observeValue(entity, Position, () => requestFrame()),\n world.reactive.observeValue(entity, StackZ, () => requestFrame()),\n ];\n for (const group of widget?.groups ?? []) {\n unsubs.push(\n world.reactive.observeValue(entity, group.component, () => {\n state.bumpPaint(entity);\n requestFrame();\n }),\n );\n }\n\n // A re-entering island with a retained FBO composites immediately\n // (Warm); a fresh one is Waking — either way the pass must run.\n if (s.fboGeneration < 0) state.bumpPaint(entity);\n requestFrame();\n\n return () => {\n for (const u of unsubs) u();\n islands.delete(entity);\n requestFrame(); // exit dirt: the quad may need to hide/recompose\n };\n },\n\n islandFor: (entity) => islands.get(entity),\n islands: () => islands.entries(),\n\n addFrameCallback(entity, cb) {\n let set = frameCbs.get(entity);\n if (set === undefined) {\n set = new Set();\n frameCbs.set(entity, set);\n }\n set.add(cb);\n state.addAnimRef(entity);\n requestFrame(); // the island turns Hot next pass\n return () => {\n set.delete(cb);\n state.removeAnimRef(entity);\n };\n },\n\n frameCallbacksFor(entity) {\n const set = frameCbs.get(entity);\n return set === undefined ? [] : [...set];\n },\n\n requestFrame,\n bumpPaint(entity) {\n state.bumpPaint(entity);\n requestFrame();\n },\n\n setCompositeScale(entity, scale) {\n const s = state.ensure(entity);\n if (s.compositeScale === scale) return; // change-only — no idle churn\n s.compositeScale = scale;\n requestFrame(); // composite-level only: no island repaint needed\n },\n\n setInvalidate(fn) {\n invalidate = fn;\n if (fn !== null && pending) {\n pending = false;\n fn();\n }\n },\n\n uninstall() {\n removeReflector();\n removeWorldObserver();\n renderAssert.dispose();\n islands.clear();\n frameCbs.clear();\n state.clear();\n invalidate = null;\n },\n };\n}\n","/**\n * The compositor frame pass (design-004 §3) — ONE function, dependency-\n * injected so the M7 exit traces (FBO budget under zoom/cull storms, zero\n * render→ECS writes) run headlessly with fakes while `GLViews` binds it to\n * the real renderer/pool/quads.\n *\n * Order per invalidation (v1 Compositor.useFrame, re-cut law-clean):\n * 1. camera/viewport read → composite frustum (kernel — Law 13) + dynamic\n * DPR (min(dpr,1) while `Camera.gesturing`, restore on idle);\n * 2. phase update per island-state entry (kernel `computeIslandPhase`,\n * module-side state ONLY — no ECS writes anywhere in the pass);\n * 3. `useIslandFrame` callbacks for Hot islands (paint-attributed — this\n * is why plain `useFrame` is not the contract);\n * 4. paint pass, Waking-first, staggered by `maxRepaintsPerFrame`; band\n * repaints suppressed while gesturing (the composite's bilinear stretch\n * is the accepted transient) and picked up on the first idle pass;\n * 5. eviction to budget (kernel `selectEvictions`; Hot/Waking immune);\n * 6. quad reconcile: transform from Position/Size (kernel Y-flip), texture\n * from the pool, `StackZ` render order with grabbed widgets on top\n * (design-004 §1: renderOrder-top within P2 suffices), `pool.touch` on\n * every composited quad (still-Warm textures must not look LRU-stale);\n * 7. composite render to the backbuffer;\n * 8. self-sustain report (`anyHot`/`pendingPaints` → caller invalidates).\n *\n * The world is READ ONLY here (reads outside the tick are verified-\n * unrestricted); the caller arms the render write trap around the whole pass.\n */\nimport {\n computeIslandPhase,\n compositeCameraFrustum,\n fboPixelSize,\n isOutOfBand,\n selectBand,\n selectEvictions,\n worldRectToComposite,\n type EvictionCandidate,\n} from \"@ice/kernel\";\nimport { Camera, Grab, Position, Size, StackZ, Viewport, Visible, type Entity, type World } from \"@ice/core\";\nimport type { GLBridge } from \"./bridge\";\n\n/** Render order far above any sane StackZ — the grabbed quad draws last. */\nconst GRABBED_RENDER_ORDER = 1e9;\n\n// --- injected surfaces (GLViews binds three.js; traces bind fakes) ----------\n\nexport interface TargetLike {\n /** Opaque texture handle threaded to the quad (three: `.texture`). */\n readonly texture: unknown;\n}\n\nexport interface PoolLike {\n acquire(key: number, worldW: number, worldH: number, effectiveDpr: number): TargetLike;\n get(key: number): TargetLike | null;\n touch(key: number): void;\n release(key: number): void;\n bytesUsed(): number;\n entryInfos(): readonly { key: number; bytes: number; lastUsedMs: number }[];\n}\n\nexport interface QuadLike {\n setTransform(x: number, y: number, sx: number, sy: number): void;\n setTexture(t: unknown): void;\n setVisible(v: boolean): void;\n setRenderOrder(n: number): void;\n}\n\nexport interface QuadsLike {\n ensure(key: number): QuadLike;\n remove(key: number): void;\n keys(): readonly number[];\n}\n\nexport interface GlLike {\n setRenderTarget(t: TargetLike | null): void;\n /** Clear the CURRENT target to transparent black. */\n clear(): void;\n render(scene: object, camera: object): void;\n setPixelRatio(n: number): void;\n getPixelRatio(): number;\n}\n\nexport interface CompCameraLike {\n setFrustum(f: { left: number; right: number; top: number; bottom: number; x: number; y: number }): void;\n /**\n * The ACTUAL camera object handed to `gl.render` for the composite pass —\n * three's renderer instanceof-checks it, so this must be the real\n * `OrthographicCamera`, NOT this adapter. (Field bug 2026-07-10: the pass\n * rendered with the adapter itself; three threw \"camera is not an instance\n * of THREE.Camera\" every frame and P2 never composited. The headless fakes\n * couldn't catch it — both types erase to `object` and the fake render is\n * a no-op.)\n */\n readonly raw: object;\n}\n\nexport interface IslandCameraLike {\n setFrustum(halfW: number, halfH: number): void;\n}\n\nexport interface PassContext {\n readonly world: World;\n readonly bridge: GLBridge;\n readonly pool: PoolLike;\n readonly quads: QuadsLike;\n readonly gl: GlLike;\n readonly compCamera: CompCameraLike;\n /** Adapt an island's ortho camera (three or fake) for frustum writes. */\n readonly islandCamera: (entity: Entity) => IslandCameraLike | undefined;\n readonly compositeScene: object;\n readonly maxFboBytes: number;\n readonly maxRepaintsPerFrame: number;\n readonly dtMs: number;\n}\n\nexport interface PassStats {\n repainted: number;\n /** Paint-needing islands deferred by the stagger cap — caller re-invalidates. */\n pendingPaints: number;\n evicted: number;\n fboBytes: number;\n anyHot: boolean;\n}\n\nexport function runCompositorPass(ctx: PassContext): PassStats {\n const { world, bridge, pool, quads, gl } = ctx;\n const stats: PassStats = { repainted: 0, pendingPaints: 0, evicted: 0, fboBytes: 0, anyHot: false };\n\n const cam = world.getResource(Camera);\n const vp = world.getResource(Viewport);\n if (cam === undefined || vp === undefined || vp.w === 0) return stats;\n\n // 1. composite camera + dynamic DPR ---------------------------------------\n ctx.compCamera.setFrustum(compositeCameraFrustum(cam, vp.w, vp.h));\n const idleDpr = vp.dpr > 0 ? vp.dpr : 1;\n const targetDpr = cam.gesturing ? Math.min(idleDpr, 1) : idleDpr;\n if (gl.getPixelRatio() !== targetDpr) gl.setPixelRatio(targetDpr);\n\n // 2. phases (module-side state only) --------------------------------------\n // `active` is the M8 nested-canvas input — always true until then.\n const phaseOf = (e: number): ReturnType<typeof computeIslandPhase> => {\n const alive = world.isAlive(e as Entity);\n const visible = alive && world.hasTag(e as Entity, Visible) && bridge.islandFor(e as Entity) !== undefined;\n const s = bridge.state.get(e);\n const hasFbo = s !== undefined && s.fboGeneration >= 0 && pool.get(e) !== null;\n return computeIslandPhase(true, visible, bridge.state.isAnimating(e), hasFbo);\n };\n for (const [e, s] of bridge.state.all()) {\n s.phase = phaseOf(e);\n if (s.phase === \"Hot\") stats.anyHot = true;\n }\n\n // 3+4. paint pass (Waking first, staggered) --------------------------------\n const band = selectBand(cam.zoom);\n const effectiveDpr = gl.getPixelRatio() * band;\n const toPaint: Entity[] = [];\n for (const [e, s] of bridge.state.all()) {\n if (bridge.islandFor(e as Entity) === undefined) continue; // unmounted: retained texture only\n const wantsPhase = s.phase === \"Hot\" || s.phase === \"Waking\";\n const genDirty = s.paintGeneration > s.fboGeneration;\n const bandStale = !cam.gesturing && s.fboGeneration >= 0 && isOutOfBand(cam.zoom, s.paintedAt.band);\n if (wantsPhase || genDirty || bandStale) toPaint.push(e as Entity);\n }\n // Order: never-painted first (cold paints jump the queue), then LEAST\n // RECENTLY PAINTED — the fairness key. Insertion order starved the same\n // island every pass once Hot count exceeded the stagger cap (five Hot vs\n // cap four froze the shapes card at boot, 2026-07-12 field report).\n toPaint.sort((a, b) => {\n const sa = bridge.state.get(a);\n const sb = bridge.state.get(b);\n const coldA = sa !== undefined && sa.fboGeneration < 0 ? 0 : 1;\n const coldB = sb !== undefined && sb.fboGeneration < 0 ? 0 : 1;\n if (coldA !== coldB) return coldA - coldB;\n return (sa?.lastPaintSeq ?? 0) - (sb?.lastPaintSeq ?? 0);\n });\n\n const cap = Math.max(1, ctx.maxRepaintsPerFrame);\n for (const e of toPaint) {\n if (stats.repainted >= cap) {\n stats.pendingPaints = toPaint.length - stats.repainted;\n break;\n }\n const handle = bridge.islandFor(e);\n const s = bridge.state.get(e);\n const size = world.isAlive(e) ? world.get(e, Size) : undefined;\n if (handle === undefined || s === undefined || size === undefined || size.w <= 0 || size.h <= 0) continue;\n\n // Hot content ticks exactly when it paints — the attribution contract.\n if (s.phase === \"Hot\") {\n for (const cb of bridge.frameCallbacksFor(e)) cb(ctx.dtMs);\n }\n\n ctx.islandCamera(e)?.setFrustum(size.w / 2, size.h / 2);\n const fbo = pool.acquire(e, size.w, size.h, effectiveDpr);\n gl.setRenderTarget(fbo);\n try {\n // A throwing island must not leave its FBO bound — that would corrupt\n // the composite into the backbuffer (v1 lesson, kept).\n gl.clear();\n gl.render(handle.scene, handle.camera);\n } finally {\n gl.setRenderTarget(null);\n }\n const px = fboPixelSize(size.w, size.h, effectiveDpr, 1);\n bridge.state.markPainted(e, { w: px.width, h: px.height, dpr: effectiveDpr, band });\n stats.repainted += 1;\n }\n\n // 5. eviction to budget (Hot/Waking immune — kernel policy) ----------------\n if (pool.bytesUsed() > ctx.maxFboBytes) {\n const candidates: EvictionCandidate<number>[] = [];\n for (const info of pool.entryInfos()) {\n const s = bridge.state.get(info.key);\n // Phases RECOMPUTED post-paint: an island that woke and painted this\n // very pass is Warm now, not Waking — the stage-2 snapshot would grant\n // it spurious eviction immunity and let a first-paint storm blow the\n // budget (caught by the storm trace).\n const phase = s === undefined ? \"Dormant\" : phaseOf(info.key);\n if (s !== undefined) s.phase = phase;\n candidates.push({\n id: info.key,\n phase,\n bytes: info.bytes,\n lastUsedMs: info.lastUsedMs,\n });\n }\n for (const key of selectEvictions(candidates, pool.bytesUsed(), ctx.maxFboBytes)) {\n if (bridge.state.get(key)?.phase === \"Dormant\") {\n // Tunable-budget breadcrumb (v1 kept it; \"no silent caps\").\n console.debug(`[ice/r3f] evicting Dormant island ${key} — consider raising the FBO budget`);\n }\n pool.release(key);\n bridge.state.markEvicted(key);\n stats.evicted += 1;\n }\n }\n\n // 6. quad reconcile ---------------------------------------------------------\n // Membership = island-state entries (they outlive cull; bridge drops them on\n // death/reset). Pool entries with no state entry are stale (post-reset) —\n // release them; quads with no state entry are removed.\n const liveKeys = new Set<number>();\n for (const [e] of bridge.state.all()) liveKeys.add(e);\n for (const info of pool.entryInfos()) {\n if (!liveKeys.has(info.key)) pool.release(info.key);\n }\n for (const key of quads.keys()) {\n if (!liveKeys.has(key)) quads.remove(key);\n }\n for (const [e, s] of bridge.state.all()) {\n const quad = quads.ensure(e);\n const alive = world.isAlive(e as Entity);\n const fbo = pool.get(e);\n const pos = alive ? world.get(e as Entity, Position) : undefined;\n const size = alive ? world.get(e as Entity, Size) : undefined;\n if (fbo === null || s.fboGeneration < 0 || pos === undefined || size === undefined) {\n // Evicted-while-retained fallback: hidden until first repaint\n // (design-004 §3 — instant reactivation holds only when the FBO survived).\n quad.setVisible(false);\n continue;\n }\n const q = worldRectToComposite({ x: pos.x, y: pos.y, width: size.w, height: size.h });\n // Lift-on-hold scales the QUAD (center-anchored — q.x/q.y is the rect\n // center): texture + rounded alpha corners scale together, and the card\n // overlaps its neighbors — scaling the SCENE instead crops the corners\n // at the card-sized frustum (2026-07-12 field report).\n const lift = s.compositeScale;\n quad.setTransform(q.x, q.y, q.sx * lift, q.sy * lift);\n quad.setTexture(fbo.texture);\n const grabbed = world.get(e as Entity, Grab) !== undefined;\n quad.setRenderOrder(grabbed || lift !== 1 ? GRABBED_RENDER_ORDER : (world.get(e as Entity, StackZ)?.z ?? 0));\n quad.setVisible(true);\n pool.touch(e);\n }\n\n // 7. composite to the backbuffer -------------------------------------------\n gl.setRenderTarget(null);\n gl.clear();\n gl.render(ctx.compositeScene, ctx.compCamera.raw);\n\n stats.fboBytes = pool.bytesUsed();\n return stats;\n}\n","/**\n * GLViews — the P2 root (design-004 §1/§3). Mount ONE inside an R3F\n * `<Canvas frameloop=\"demand\">` that the app positions as the GL-views plane\n * (absolute inset-0, `pointer-events: none` — the router owns GL hit\n * testing; the canvas element never sees pointers).\n *\n * Owns everything whose lifetime IS the GL context's: the FBO pool, the\n * shared unit-quad geometry, the per-widget composite quads, the composite\n * camera, and the priority-1 `useFrame` that runs `runCompositorPass` (which\n * suppresses R3F's default render — the pass owns the whole frame). Island\n * membership mirrors `WidgetRoot`: the same widget mount store, filtered to\n * `surface: \"gl\"`, hidden (culled) entries unmounted — their FBOs stay\n * pooled, that's the retention decoupling.\n *\n * StrictMode/HMR: pool + quads are lazy-init'd and re-created if a previous\n * instance was disposed (v1 lesson — cleanup-then-remount reuses the\n * component instance, so refs may point at disposed objects).\n */\nimport { useFrame, useThree } from \"@react-three/fiber\";\nimport {\n createElement,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type ReactElement,\n} from \"react\";\nimport { Mesh, OrthographicCamera, PlaneGeometry, type Texture, type WebGLRenderTarget } from \"three\";\nimport {\n PrefabId,\n RUNTIME_BUDGETS,\n widgets,\n type Engine,\n type Entity,\n type WidgetMountStore,\n} from \"@ice/core\";\nimport type { GLBridge } from \"./bridge\";\nimport { CompositeMaterial } from \"./composite-material\";\nimport {\n runCompositorPass,\n type GlLike,\n type QuadLike,\n type QuadsLike,\n type TargetLike,\n} from \"./compositor-pass\";\nimport { Island } from \"./island\";\nimport { RenderTargetPool } from \"./pool\";\n\nexport interface GLViewsProps {\n readonly engine: Engine;\n readonly bridge: GLBridge;\n readonly store: WidgetMountStore;\n /** FBO byte budget (default `RUNTIME_BUDGETS.fboBytes`, 256 MB). */\n readonly maxFboBytes?: number;\n /** Repaint stagger per composited frame (v1 default 4). */\n readonly maxRepaintsPerFrame?: number;\n /**\n * Shared IBL: stamped as `scene.environment` on EVERY island's private\n * scene (arrival/change repaints all islands). Load it app-side (e.g.\n * drei's useEnvironment in a Suspense boundary) — undefined until then is\n * fine; islands paint unlit-by-IBL and repaint when it lands.\n */\n readonly environment?: Texture | null;\n}\n\nexport function GLViews({\n engine,\n bridge,\n store,\n maxFboBytes = RUNTIME_BUDGETS.fboBytes,\n maxRepaintsPerFrame = 4,\n environment,\n}: GLViewsProps): ReactElement {\n const world = engine.world;\n const gl = useThree((s) => s.gl);\n const scene = useThree((s) => s.scene);\n const set = useThree((s) => s.set);\n const invalidate = useThree((s) => s.invalidate);\n\n // --- context-lifetime resources (lazy + disposed-aware, v1 pattern) ------\n const poolRef = useRef<RenderTargetPool | null>(null);\n if (poolRef.current === null || poolRef.current.isDisposed()) {\n poolRef.current = new RenderTargetPool();\n }\n const pool = poolRef.current;\n\n const quadGeometry = useMemo(() => new PlaneGeometry(1, 1), []);\n const compCamera = useMemo(() => new OrthographicCamera(0, 1, 0, -1, 0.1, 10000), []);\n\n // Make the composite camera the Canvas default so R3F utilities that read\n // `state.camera` (raycaster defaults etc.) have a sensible reference.\n useEffect(() => {\n set({ camera: compCamera as unknown as never });\n }, [set, compCamera]);\n\n // Composite quads: engine-neutral meshes in the default scene ({opacity}\n // is the whole per-widget composite fact; app looks are app hooks).\n const quadsRef = useRef(new Map<number, Mesh>());\n const quads: QuadsLike = useMemo(\n () => ({\n ensure(key: number): QuadLike {\n let mesh = quadsRef.current.get(key);\n if (mesh === undefined) {\n mesh = new Mesh(quadGeometry, new CompositeMaterial());\n mesh.frustumCulled = false;\n mesh.visible = false; // hidden until the island has painted once\n scene.add(mesh);\n quadsRef.current.set(key, mesh);\n }\n const m = mesh;\n return {\n setTransform: (x, y, sx, sy) => {\n m.position.set(x, y, 0);\n m.scale.set(sx, sy, 1);\n },\n setTexture: (t) => (m.material as CompositeMaterial).setMap(t as WebGLRenderTarget[\"texture\"]),\n setVisible: (v) => {\n m.visible = v;\n },\n setRenderOrder: (n) => {\n m.renderOrder = n;\n },\n };\n },\n remove(key: number) {\n const mesh = quadsRef.current.get(key);\n if (mesh !== undefined) {\n scene.remove(mesh);\n (mesh.material as CompositeMaterial).dispose();\n quadsRef.current.delete(key);\n }\n },\n keys: () => [...quadsRef.current.keys()],\n }),\n [scene, quadGeometry],\n );\n\n // Renderer adapter (explicit clear color: transparent black, v1 contract).\n const glLike: GlLike = useMemo(\n () => ({\n setRenderTarget: (t) => gl.setRenderTarget(t as WebGLRenderTarget | null),\n clear: () => {\n gl.setClearColor(0x000000, 0);\n gl.clear(true, true, false);\n },\n render: (s, c) => gl.render(s as never, c as never),\n setPixelRatio: (n) => gl.setPixelRatio(n),\n getPixelRatio: () => gl.getPixelRatio(),\n }),\n [gl],\n );\n\n // Wire the bridge's demand-loop hook for the life of this Canvas.\n useEffect(() => {\n bridge.setInvalidate(() => invalidate());\n return () => bridge.setInvalidate(null);\n }, [bridge, invalidate]);\n\n // Teardown: quads + pool die with the context (island state survives in\n // the bridge — a remounted Canvas re-wakes islands from Waking).\n useEffect(() => {\n const quadMap = quadsRef.current;\n return () => {\n for (const mesh of quadMap.values()) {\n scene.remove(mesh);\n (mesh.material as CompositeMaterial).dispose();\n }\n quadMap.clear();\n pool.dispose();\n for (const [key] of bridge.state.all()) bridge.state.markEvicted(key);\n };\n }, [scene, pool, bridge]);\n\n // The pass. Priority 1 suppresses R3F's default render — we own the frame.\n useFrame((_, delta) => {\n bridge.renderAssert.begin();\n let stats: ReturnType<typeof runCompositorPass>;\n try {\n stats = runCompositorPass({\n world,\n bridge,\n pool,\n quads,\n gl: glLike,\n compCamera: {\n raw: compCamera, // the REAL camera — gl.render instanceof-checks it\n setFrustum: (f) => {\n compCamera.left = f.left;\n compCamera.right = f.right;\n compCamera.top = f.top;\n compCamera.bottom = f.bottom;\n compCamera.position.set(f.x, f.y, 1000);\n compCamera.updateProjectionMatrix();\n },\n },\n islandCamera: (entity) => {\n const handle = bridge.islandFor(entity);\n if (handle === undefined) return undefined;\n return {\n setFrustum: (halfW, halfH) => {\n handle.camera.left = -halfW;\n handle.camera.right = halfW;\n handle.camera.top = halfH;\n handle.camera.bottom = -halfH;\n handle.camera.updateProjectionMatrix();\n },\n };\n },\n compositeScene: scene,\n maxFboBytes,\n maxRepaintsPerFrame,\n dtMs: delta * 1000,\n });\n } finally {\n bridge.renderAssert.end();\n }\n // Self-sustain: Hot islands and stagger-deferred paints keep the demand\n // loop spinning; otherwise it parks until the next invalidation.\n if (stats.anyHot || stats.pendingPaints > 0) invalidate();\n }, 1);\n\n // --- island membership (mount store → gl-surface islands) -----------------\n const entries = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const islands: ReactElement[] = [];\n for (const entry of entries) {\n if (entry.hidden) continue; // culled: island unmounts, FBO stays pooled\n if (!world.isAlive(entry.entity)) continue;\n const type = world.get(entry.entity, PrefabId)?.id;\n const widget = typeof type === \"string\" ? widgets.get(type) : undefined;\n if (widget === undefined || widget.surface !== \"gl\") continue;\n islands.push(\n createElement(Island, {\n key: String(entry.entity),\n bridge,\n world,\n entity: entry.entity as Entity,\n widget,\n ...(environment !== undefined ? { environment } : {}),\n }),\n );\n }\n return createElement(\"group\", null, islands);\n}\n","import { ShaderMaterial } from \"three\";\nimport type { Texture } from \"three\";\n\n/**\n * Neutral composite material for the island compositor (design-004 §3). One\n * instance per island quad: it samples the island's FBO texture and writes it to\n * the canvas backbuffer at `uOpacity`, with no look of its own.\n *\n * Ported from v1 `CompositionMaterial`\n * (../infinite-canvas .../r3f/compositor/CompositionMaterial.ts) STRIPPED to the\n * engine-neutral core per design-004 §3 rev 2: the v1 app-specific uniforms and\n * shader branches — `uDraggedRect`/`uIsDragged` drag-promote clip, the\n * `uHotPoint`/`uHotStrength`/`uIsOverlapTarget` overlap glow, the rim band, and\n * the module-level `sharedGlowUniforms` — are DELETED. Userland looks belong in\n * userland materials, not the compositor.\n *\n * What is KEPT verbatim is the colour-management contract: the FBO already holds\n * sRGB-encoded, display-ready values (RenderTargetPool sets\n * `texture.colorSpace = SRGBColorSpace`), so this pass must sample-and-write\n * WITHOUT tone mapping. See the fragment-shader note below for the sRGB\n * double-encode trap and why the `<colorspace_fragment>` chunk is still required.\n */\n\nconst VERTEX_SHADER = /* glsl */ `\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n`;\n\n// Fragment shader. There is deliberately NO <tonemapping_fragment> chunk — the\n// FBO holds sRGB values already, so tone mapping would double-process them.\n//\n// The trailing <colorspace_fragment> chunk IS required, and this is the subtle\n// part (the sRGB double-encode trap): Three's texture sampler auto-DECODES the\n// sRGB FBO to linear during texture2D (because RenderTargetPool declares the\n// target's colorSpace = SRGBColorSpace). Without re-encoding to the renderer's\n// outputColorSpace (also sRGB) via <colorspace_fragment>, those linear values\n// would land in the backbuffer and read as washed-out / desaturated. So: no tone\n// map, but DO re-encode — a straight round-trip that leaves the island's pixels\n// exactly as painted.\nconst FRAGMENT_SHADER = /* glsl */ `\nuniform sampler2D map;\nuniform float uOpacity;\nvarying vec2 vUv;\n\nvoid main() {\n vec4 c = texture2D(map, vUv);\n if (c.a < 0.001) discard;\n c.a *= uOpacity;\n gl_FragColor = c;\n #include <colorspace_fragment>\n}\n`;\n\n/**\n * Per-island composite material. Each island quad gets its own instance so the\n * per-quad `map` uniform is independent; Three compiles the shader once and\n * reuses the program across instances since they share source (verify in dev via\n * `renderer.info.programs.length === 1` for the composite shader).\n */\nexport class CompositeMaterial extends ShaderMaterial {\n // Direct handles onto our two uniform cells. ShaderMaterial types `uniforms`\n // as an index signature, so `this.uniforms.map` reads as possibly-undefined\n // under strict indexing; holding the cells we created sidesteps that and keeps\n // the setters allocation-free.\n private readonly mapUniform: { value: Texture | null };\n private readonly opacityUniform: { value: number };\n\n constructor() {\n const uniforms = {\n map: { value: null as Texture | null },\n uOpacity: { value: 1 },\n };\n super({\n vertexShader: VERTEX_SHADER,\n fragmentShader: FRAGMENT_SHADER,\n uniforms,\n transparent: true,\n depthWrite: false,\n // Explicit: this pass must never tone-map (the FBO is already display-\n // ready). v1 left toneMapped at the ShaderMaterial default and relied on\n // the absent tonemapping chunk alone (CompositionMaterial.ts:140-142); we\n // set it false so the no-tone-map contract holds even if the shader ever\n // gains chunks. Behaviour is identical for the current shader.\n toneMapped: false,\n });\n // ShaderMaterial keeps the passed `uniforms` object by reference, so these\n // handles stay in sync with `this.uniforms`.\n this.mapUniform = uniforms.map;\n this.opacityUniform = uniforms.uOpacity;\n }\n\n /** Bind the island's FBO texture (null clears). */\n setMap(map: Texture | null): void {\n this.mapUniform.value = map;\n }\n\n /** Composite opacity. Pass-through — no clamping; callers pass valid 0..1. */\n setOpacity(opacity: number): void {\n this.opacityUniform.value = opacity;\n }\n\n // dispose() is inherited from ShaderMaterial — it fires the dispose event that\n // frees the compiled program; no override needed.\n}\n","/**\n * One island = one GL widget's private Scene + center-origin Y-up ortho\n * camera, mounted via R3F `createPortal` so the content tree (hooks, state,\n * drei) lives OUTSIDE the composite scene and paints into a pooled FBO\n * (design-004 §3; the island-space convention is kernel's — Law 13).\n *\n * Deliberately thin: registration/unregistration is the ONLY effect. The\n * camera frustum is written by the frame pass at paint time from the live\n * `Size` (v1 set it from a React effect AND bumped an ECS component — both\n * moved out; islands never write ECS). Unmount (cull) drops scene + camera;\n * the FBO and island state survive in the pool/bridge — retention is\n * decoupled from culling by design.\n */\nimport { createPortal } from \"@react-three/fiber\";\nimport { createElement, useEffect, useMemo, type ComponentType, type ReactElement } from \"react\";\nimport { OrthographicCamera, Scene, type Texture } from \"three\";\nimport type { Entity, WidgetType, World } from \"@ice/core\";\nimport type { WidgetComponentProps } from \"@ice/react\";\nimport type { GLBridge } from \"./bridge\";\nimport { IslandContext } from \"./use-island-frame\";\n\nexport interface IslandProps {\n readonly bridge: GLBridge;\n readonly world: World;\n readonly entity: Entity;\n readonly widget: WidgetType;\n /** Shared IBL for this island's private scene (see GLViews.environment). */\n readonly environment?: Texture | null;\n}\n\nexport function Island({ bridge, world, entity, widget, environment }: IslandProps): ReactElement | null {\n const scene = useMemo(() => new Scene(), []);\n const camera = useMemo(() => {\n // Generous depth range (ortho — free): at z=100 a large card's rotating\n // geometry (e.g. a 329px torus knot's lobe swinging toward the camera)\n // crossed the near plane and clipped (field report 2026-07-12).\n const cam = new OrthographicCamera(-1, 1, 1, -1, 0.1, 2000);\n cam.position.set(0, 0, 500); // +Z looking at the XY content plane\n cam.lookAt(0, 0, 0);\n return cam;\n }, []);\n\n useEffect(\n () => bridge.registerIsland(entity, { scene, camera }),\n [bridge, entity, scene, camera],\n );\n\n // Shared environment (v1's Compositor propagated its env map to every widget\n // scene; v3 islands are private, so propagation is this explicit stamp). The\n // HDR usually arrives AFTER the first cold paint — bumpPaint repaints even\n // static (animated:false) islands with the new lighting.\n useEffect(() => {\n scene.environment = environment ?? null;\n bridge.bumpPaint(entity);\n }, [environment, scene, bridge, entity]);\n\n const View = widget.component as ComponentType<WidgetComponentProps>;\n if (View == null) return null;\n\n return createPortal(\n createElement(\n IslandContext.Provider,\n { value: { bridge, entity } },\n createElement(View, { entity, world }),\n ),\n scene,\n ) as unknown as ReactElement;\n}\n","/**\n * The island animation contract (design-004 §3, rev 2 corrected).\n *\n * Plain `useFrame` CANNOT drive island repaints: R3F portals share the\n * root's single commingled `internal.subscribers` array, so a subscription\n * cannot be attributed to an island without probing R3F internals (banned).\n * `useIslandFrame` is the engine's wrapper: it registers the callback WITH\n * the island (bridge-side), which (a) holds the island's animation signal\n * while subscribed — the island turns Hot and repaints every visible frame —\n * and (b) fires the callback exactly when its island paints, so content\n * mutation and texture refresh can never desynchronize.\n *\n * The callback runs INSIDE the render pass: it may mutate three objects in\n * the island scene freely, but any ECS write throws under the DEV render\n * write trap (M7 exit). Engine state changes belong in systems or ops.\n */\nimport { createContext, useCallback, useContext, useEffect, useRef } from \"react\";\nimport type { Entity } from \"@ice/core\";\nimport type { GLBridge, IslandFrameCallback } from \"./bridge\";\n\nexport interface IslandContextValue {\n readonly bridge: GLBridge;\n readonly entity: Entity;\n}\n\n/** Provided per-island by `<Island>`; null outside island content. */\nexport const IslandContext = createContext<IslandContextValue | null>(null);\n\nexport function useIslandContext(): IslandContextValue {\n const ctx = useContext(IslandContext);\n if (ctx === null) {\n throw new Error(\"ice: useIslandFrame/useIslandInvalidate must run inside a GL widget's island.\");\n }\n return ctx;\n}\n\n/** Per-frame tick while mounted (island goes Hot). `cb(dtMs)` on paint. */\nexport function useIslandFrame(cb: IslandFrameCallback): void {\n const { bridge, entity } = useIslandContext();\n const ref = useRef(cb);\n ref.current = cb; // latest closure runs without re-subscribing\n useEffect(() => bridge.addFrameCallback(entity, (dt) => ref.current(dt)), [bridge, entity]);\n}\n\n/**\n * One-shot repaint scheduler for content that changes outside React's render\n * cycle (imperative subscriptions, sockets). Bumps the island's paint\n * generation + wakes the demand loop.\n */\nexport function useIslandInvalidate(): () => void {\n const { bridge, entity } = useIslandContext();\n return useCallback(() => bridge.bumpPaint(entity), [bridge, entity]);\n}\n\n/**\n * Composite-quad lift: scales the CARD on the canvas (texture + rounded alpha\n * corners together) and pops it over neighbors while ≠1. Scaling scene content\n * instead crops the corners at the card-sized frustum — the 2026-07-12\n * hard-corner field report. Resets to 1 on unmount.\n */\nexport function useIslandLift(scale: number): void {\n const { bridge, entity } = useIslandContext();\n useEffect(() => {\n bridge.setCompositeScale(entity, scale);\n }, [bridge, entity, scale]);\n useEffect(() => () => bridge.setCompositeScale(entity, 1), [bridge, entity]);\n}\n","import { SRGBColorSpace, WebGLRenderTarget } from \"three\";\n\n/**\n * Per-island FBO pool (design-004 §3). Each compositor island paints into its\n * own persistent `WebGLRenderTarget` instead of the shared canvas backbuffer,\n * so the compositor can sample islands as textures and stack them with correct\n * z / opacity.\n *\n * Ported from v1 `WidgetRenderTargetPool` (../infinite-canvas\n * .../r3f/compositor/WidgetRenderTargetPool.ts) with the design-004 §3 rev 2\n * deltas: the pool is keyed by a plain `number` (the caller's island/entity id)\n * and imports NOTHING from the ECS — it is a pure three resource, so it never\n * depends on the entity representation. Timestamps are injected (see `now`) so\n * the LRU is deterministic under test.\n *\n * Acquire returns an existing FBO when its pixel resolution matches the request;\n * otherwise the old FBO is disposed and a new one is created at the new\n * resolution. Eviction under memory pressure is a higher layer's concern — this\n * pool grows monotonically until islands are `release`d.\n */\n\n/**\n * Colour bytes per pixel for the default RGBA8 render-target format.\n *\n * v1 accounted a flat `BYTES_PER_PIXEL = 8` constant\n * (WidgetRenderTargetPool.ts:8) reasoning \"RGBA8 colour + packed depth/stencil\".\n * We keep the identical byte total but express it in the design-004 §3 form\n * `colour × (samples > 1 ? 2 : 1)`: 4 colour bytes, doubled when MSAA adds the\n * resolve buffer. Because {@link SAMPLES} is 4 (> 1) this yields 8 bytes/pixel —\n * byte-for-byte the v1 figure — while remaining correct if the sample count ever\n * changes.\n */\nconst COLOR_BYTES_PER_PIXEL = 4;\n\n/**\n * MSAA sample count. Matches the canvas's antialias setting so island edges look\n * the same as a direct-to-canvas pass (v1 WidgetRenderTargetPool.ts:73).\n */\nconst SAMPLES = 4;\n\n/** GPU bytes for one target at the given pixel size (see {@link COLOR_BYTES_PER_PIXEL}). */\nfunction targetBytes(pixelWidth: number, pixelHeight: number): number {\n return pixelWidth * pixelHeight * COLOR_BYTES_PER_PIXEL * (SAMPLES > 1 ? 2 : 1);\n}\n\ninterface PoolEntry {\n rt: WebGLRenderTarget;\n /** Pixel width = worldWidth × effectiveDpr, rounded, clamped ≥ 1. */\n pixelWidth: number;\n pixelHeight: number;\n effectiveDpr: number;\n bytes: number;\n /** Injected-clock timestamp of the most recent acquire/touch — drives LRU. */\n lastUsedMs: number;\n}\n\n/** Snapshot row returned by {@link RenderTargetPool.entryInfos}. */\nexport interface PoolEntryInfo {\n key: number;\n bytes: number;\n lastUsedMs: number;\n}\n\nexport class RenderTargetPool {\n private entries = new Map<number, PoolEntry>();\n private totalBytes = 0;\n private disposed = false;\n private readonly now: () => number;\n\n /**\n * @param now Injected monotonic clock for LRU timestamps. Defaults to\n * `performance.now()`; tests pass a deterministic stub so `lastUsedMs`\n * assertions do not depend on wall-clock timing.\n */\n constructor(now: () => number = () => performance.now()) {\n this.now = now;\n }\n\n /**\n * Get or create an FBO for `key` at the requested world size and effective\n * device-pixel-ratio. Returns the existing target unchanged when its pixel\n * dimensions already match; otherwise disposes the stale target and allocates\n * a new one sized to the new resolution.\n */\n acquire(key: number, worldW: number, worldH: number, effectiveDpr: number): WebGLRenderTarget {\n if (this.disposed) {\n throw new Error(\"RenderTargetPool: cannot acquire after dispose\");\n }\n const pixelWidth = Math.max(1, Math.round(worldW * effectiveDpr));\n const pixelHeight = Math.max(1, Math.round(worldH * effectiveDpr));\n const nowMs = this.now();\n\n const existing = this.entries.get(key);\n if (existing && existing.pixelWidth === pixelWidth && existing.pixelHeight === pixelHeight) {\n existing.lastUsedMs = nowMs;\n return existing.rt;\n }\n\n if (existing) {\n existing.rt.dispose();\n this.totalBytes -= existing.bytes;\n }\n\n const rt = new WebGLRenderTarget(pixelWidth, pixelHeight, { samples: SAMPLES });\n // sRGB colour space — without this, Three writes tone-mapped LINEAR values\n // to the FBO. The composite shader samples raw and outputs raw, and the\n // canvas backbuffer would then read the linear values as sRGB → washed-out /\n // dark. SRGBColorSpace tells Three's built-in materials to sRGB-encode when\n // writing here, so the FBO already holds display-ready values (design-004 §3;\n // the composite shader must NOT re-encode — see composite-material.ts).\n rt.texture.colorSpace = SRGBColorSpace;\n const bytes = targetBytes(pixelWidth, pixelHeight);\n this.entries.set(key, { rt, pixelWidth, pixelHeight, effectiveDpr, bytes, lastUsedMs: nowMs });\n this.totalBytes += bytes;\n return rt;\n }\n\n /** Look up an FBO without creating one. */\n get(key: number): WebGLRenderTarget | null {\n return this.entries.get(key)?.rt ?? null;\n }\n\n /**\n * Refresh `lastUsedMs` without re-acquiring. The compositor calls this for\n * every island it samples in the composition pass — without it, warm islands\n * that never repaint would freeze their timestamp at their last paint and the\n * LRU would treat still-visible islands as stale (design-004 §3).\n */\n touch(key: number): void {\n const entry = this.entries.get(key);\n if (!entry) return;\n entry.lastUsedMs = this.now();\n }\n\n /**\n * Release `key`'s FBO. Returns true if something was released. Safe after\n * dispose — returns false rather than corrupting the byte counter or\n * double-disposing the target.\n */\n release(key: number): boolean {\n if (this.disposed) return false;\n const entry = this.entries.get(key);\n if (!entry) return false;\n entry.rt.dispose();\n // Clamp at zero so out-of-order teardown never drives the counter negative.\n this.totalBytes = Math.max(0, this.totalBytes - entry.bytes);\n this.entries.delete(key);\n return true;\n }\n\n /** Total GPU bytes consumed by the pool. */\n bytesUsed(): number {\n return this.totalBytes;\n }\n\n /** Number of FBOs currently held. */\n size(): number {\n return this.entries.size;\n }\n\n /** True after `dispose()` — callers should re-create the pool instead of using it. */\n isDisposed(): boolean {\n return this.disposed;\n }\n\n /** Iterate live entries (key + target). */\n forEach(cb: (key: number, rt: WebGLRenderTarget) => void): void {\n for (const [key, entry] of this.entries) cb(key, entry.rt);\n }\n\n /**\n * Snapshot of every live entry's `bytes` + `lastUsedMs` — the input an\n * eviction pass ranks by LRU.\n */\n entryInfos(): PoolEntryInfo[] {\n const out: PoolEntryInfo[] = [];\n for (const [key, entry] of this.entries) {\n out.push({ key, bytes: entry.bytes, lastUsedMs: entry.lastUsedMs });\n }\n return out;\n }\n\n /** Dispose every FBO. After this, acquire throws and release returns false. */\n dispose(): void {\n if (this.disposed) return;\n for (const entry of this.entries.values()) entry.rt.dispose();\n this.entries.clear();\n this.totalBytes = 0;\n this.disposed = true;\n }\n}\n","import type { BufferGeometry, Material, Texture } from \"three\";\n\n/**\n * Ref-counted cache of shared GPU resources keyed by a caller-supplied\n * `cacheKey` (design-004 §3). Geometries, materials, and textures are pooled so\n * many islands of the same archetype share one instance instead of each\n * allocating its own copy.\n *\n * Ported ~verbatim from v1 `ResourceRegistry`\n * (../infinite-canvas .../r3f/compositor/ResourceRegistry.ts). Three's\n * geometries / materials / textures all expose `.dispose()` and are safe to\n * share across scenes; the registry disposes the underlying resource only after\n * every holder has called the matching `release*`.\n */\n\n/** Anything the registry can own — Three resources all satisfy this. */\ntype Disposable = { dispose: () => void };\n\ninterface Entry<T extends Disposable> {\n resource: T;\n refCount: number;\n}\n\nexport class ResourceRegistry {\n private geometries = new Map<string, Entry<BufferGeometry>>();\n private materials = new Map<string, Entry<Material>>();\n private textures = new Map<string, Entry<Texture>>();\n private disposed = false;\n\n acquireGeometry<T extends BufferGeometry>(key: string, factory: () => T): T {\n const existing = this.geometries.get(key);\n if (existing) {\n existing.refCount++;\n return existing.resource as T;\n }\n const resource = factory();\n this.geometries.set(key, { resource, refCount: 1 });\n return resource;\n }\n releaseGeometry(key: string): void {\n this.releaseFrom(this.geometries, key);\n }\n\n acquireMaterial<T extends Material>(key: string, factory: () => T): T {\n const existing = this.materials.get(key);\n if (existing) {\n existing.refCount++;\n return existing.resource as T;\n }\n const resource = factory();\n this.materials.set(key, { resource, refCount: 1 });\n return resource;\n }\n releaseMaterial(key: string): void {\n this.releaseFrom(this.materials, key);\n }\n\n acquireTexture<T extends Texture>(key: string, factory: () => T): T {\n const existing = this.textures.get(key);\n if (existing) {\n existing.refCount++;\n return existing.resource as T;\n }\n const resource = factory();\n this.textures.set(key, { resource, refCount: 1 });\n return resource;\n }\n releaseTexture(key: string): void {\n this.releaseFrom(this.textures, key);\n }\n\n /** Number of distinct shared geometries currently held. */\n geometryCount(): number {\n return this.geometries.size;\n }\n\n /** Number of distinct shared materials currently held. */\n materialCount(): number {\n return this.materials.size;\n }\n\n /** Number of distinct shared textures currently held. */\n textureCount(): number {\n return this.textures.size;\n }\n\n /**\n * Estimated GPU bytes for shared geometry attribute buffers. Best-effort —\n * actual footprint depends on driver alignment, but a useful relative metric\n * for the profiler.\n */\n geometryBytes(): number {\n let total = 0;\n for (const { resource } of this.geometries.values()) {\n for (const attr of Object.values(resource.attributes)) {\n if (\"array\" in attr && (attr.array as ArrayBufferView).byteLength) {\n total += (attr.array as ArrayBufferView).byteLength;\n }\n }\n if (resource.index) {\n total += (resource.index.array as ArrayBufferView).byteLength;\n }\n }\n return total;\n }\n\n /** Dispose every resource and clear the registry. */\n dispose(): void {\n if (this.disposed) return;\n for (const { resource } of this.geometries.values()) resource.dispose();\n for (const { resource } of this.materials.values()) resource.dispose();\n for (const { resource } of this.textures.values()) resource.dispose();\n this.geometries.clear();\n this.materials.clear();\n this.textures.clear();\n this.disposed = true;\n }\n\n /** True after `dispose()` — callers should re-create the registry instead of using it. */\n isDisposed(): boolean {\n return this.disposed;\n }\n\n private releaseFrom<T extends Disposable>(map: Map<string, Entry<T>>, key: string): void {\n const entry = map.get(key);\n if (!entry) return;\n entry.refCount--;\n if (entry.refCount <= 0) {\n // Defer disposal by one microtask. Under React StrictMode the effect\n // cleanup fires immediately, followed by a remount + new acquire — without\n // the defer, the resource is disposed before the remount can re-acquire\n // it. The microtask gives the re-acquire a chance to bump refCount back\n // above 0; if it does not, we dispose for real.\n queueMicrotask(() => {\n const current = map.get(key);\n if (current && current.refCount <= 0) {\n current.resource.dispose();\n map.delete(key);\n }\n });\n }\n }\n}\n","/**\n * The pointer router's GL path (design-004 §4, rev 2 corrected).\n *\n * At EVENT time (outside the tick — world reads are verified-unrestricted)\n * the router runs its own synchronous point-pick against THE spatial index\n * via core's `pickTopAt` — the identical narrow-phase the in-tick `picking`\n * system runs, so the two can never disagree. It does NOT consult last-frame\n * `Targets`: that relation is absent for a touch's first event (the pointer\n * entity doesn't exist yet at down) and stale for fast mouse crossings —\n * rev 1 of the design ate the first tap on every interactive GL widget.\n * `Targets` remains the in-tick authority; this pick is a routing decision,\n * not a second truth.\n *\n * Hit a GL-view widget → island-local convert (kernel, THE Y-flip) → raycast\n * the island's scene through its ortho camera → dispatch synthetic events to\n * the intersected objects' R3F handlers. A handler calling\n * `stopPropagation()` claims the event: the adapter flags the fact\n * `surfaceHandled` and recognizers skip it (`HandledByWidget`, the M4 spine).\n *\n * Capture semantics (per island): a claimed down captures the pointer — its\n * moves/ups go to that island until up/cancel, mirroring how DOM widget\n * content holds `setPointerCapture` for sustained interactions. Hover\n * enter/leave are synthesized from pick transitions on buttonless moves.\n *\n * R3F-INTERNAL-ADJACENT (the one acknowledged spot, implementation-plan\n * risks): handlers are read from `object.__r3f.handlers` — the instance\n * state R3F v9 attaches to every declaratively-created three object. No\n * other R3F internal is touched; the dispatcher owns its own event shape.\n * Mid-event ordering note (design-004 §4): handlers may run engine ops —\n * legal; such mutations land immediately while the same event's position\n * facts land next tick via the queue.\n */\nimport { Raycaster, Vector2, type Intersection, type Object3D } from \"three\";\nimport { screenToWorld, worldToIsland } from \"@ice/kernel\";\nimport type { SpatialIndex } from \"@ice/kernel\";\nimport {\n Camera,\n PrefabId,\n Position,\n Size,\n pickTopAt,\n widgets,\n type Entity,\n type World,\n} from \"@ice/core\";\nimport type { GLBridge } from \"./bridge\";\n\n/** The synthetic event island handlers receive (R3F-handler-compatible core). */\nexport interface IslandPointerEvent {\n readonly type: string;\n readonly nativeEvent: PointerEvent;\n /** Island-local intersection point (three world = island space). */\n readonly point: Intersection[\"point\"] | undefined;\n readonly distance: number;\n readonly object: Object3D;\n readonly eventObject: Object3D;\n readonly intersections: readonly Intersection[];\n readonly entity: Entity;\n stopPropagation(): void;\n readonly stopped: boolean;\n}\n\ntype HandlerName =\n | \"onPointerDown\"\n | \"onPointerMove\"\n | \"onPointerUp\"\n | \"onPointerCancel\"\n | \"onPointerOver\"\n | \"onPointerOut\"\n | \"onClick\";\n\n/** R3F v9 instance state — the single internal-adjacent touchpoint. */\ninterface R3FInstance {\n eventCount?: number;\n handlers?: Partial<Record<HandlerName, (ev: IslandPointerEvent) => void>>;\n}\n\nfunction handlersOf(obj: Object3D): R3FInstance[\"handlers\"] | undefined {\n const inst = (obj as unknown as { __r3f?: R3FInstance }).__r3f;\n if (inst === undefined || (inst.eventCount ?? 0) === 0) return undefined;\n return inst.handlers;\n}\n\nexport interface GLPointerRouterDeps {\n readonly world: World;\n readonly bridge: GLBridge;\n readonly index: SpatialIndex<Entity>;\n}\n\nexport interface GLPointerRouter {\n /** The adapter's `glRoute` seam. True = island content claimed the event. */\n route(kind: \"down\" | \"move\" | \"up\" | \"cancel\", screenX: number, screenY: number, native: PointerEvent): boolean;\n}\n\nexport function createGLPointerRouter({ world, bridge, index }: GLPointerRouterDeps): GLPointerRouter {\n const raycaster = new Raycaster();\n const ndc = new Vector2();\n\n // pointerId → captured island + the down's claiming object (click pairing).\n const captures = new Map<number, { entity: Entity; downObject: Object3D | undefined }>();\n // entity → objects currently hovered (buttonless-move enter/leave synth).\n const hovered = new Map<Entity, Set<Object3D>>();\n // pointerId → unclaimed down's topmost object (click pairing without a claim).\n const unclaimedDowns = new Map<number, { entity: Entity; object: Object3D }>();\n\n /** Screen → (GL widget entity, island intersections); undefined off-GL. */\n const castAt = (\n screenX: number,\n screenY: number,\n ): { entity: Entity; hits: Intersection[] } | undefined => {\n const cam = world.getResource(Camera);\n if (cam === undefined) return undefined;\n const w = screenToWorld(screenX, screenY, cam);\n const hit = pickTopAt(world, index, w.x, w.y, 0);\n if (hit === undefined) return undefined;\n const type = world.get(hit, PrefabId)?.id;\n const widget = typeof type === \"string\" ? widgets.get(type) : undefined;\n if (widget === undefined || widget.surface !== \"gl\") return undefined;\n const handle = bridge.islandFor(hit);\n const pos = world.get(hit, Position);\n const size = world.get(hit, Size);\n if (handle === undefined || pos === undefined || size === undefined || size.w <= 0 || size.h <= 0) {\n return undefined; // culled island (no scene) — the retained texture is not interactive\n }\n const local = worldToIsland(w.x, w.y, { x: pos.x, y: pos.y, width: size.w, height: size.h });\n ndc.set(local.x / (size.w / 2), local.y / (size.h / 2));\n // The event-time raycast must not depend on paint order (a tap can land\n // before the island's first paint sets the camera frustum): write the\n // frustum from the live Size and refresh matrices here. Event-rate, small\n // trees — cheap.\n const cam3 = handle.camera;\n cam3.left = -size.w / 2;\n cam3.right = size.w / 2;\n cam3.top = size.h / 2;\n cam3.bottom = -size.h / 2;\n cam3.updateProjectionMatrix();\n cam3.updateMatrixWorld(true);\n handle.scene.updateMatrixWorld(true);\n raycaster.setFromCamera(ndc, cam3);\n return { entity: hit, hits: raycaster.intersectObjects(handle.scene.children, true) };\n };\n\n /** R3F bubbling: per intersection, walk up; dedupe eventObjects; stop on stopPropagation. */\n const dispatch = (\n type: HandlerName,\n eventType: string,\n entity: Entity,\n hits: readonly Intersection[],\n native: PointerEvent,\n only?: Object3D,\n ): { stopped: boolean; claimedBy: Object3D | undefined } => {\n const visited = new Set<Object3D>();\n let stopped = false;\n let claimedBy: Object3D | undefined;\n const targets: { obj: Object3D; hit: Intersection | undefined }[] = [];\n if (hits.length === 0 && only !== undefined) {\n targets.push({ obj: only, hit: undefined }); // captured island, ray off content\n }\n for (const hit of hits) {\n for (let obj: Object3D | null = hit.object; obj !== null; obj = obj.parent) {\n if (visited.has(obj)) continue;\n visited.add(obj);\n targets.push({ obj, hit });\n }\n }\n for (const { obj, hit } of targets) {\n const fn = handlersOf(obj)?.[type];\n if (fn === undefined) continue;\n let localStop = false;\n const ev: IslandPointerEvent = {\n type: eventType,\n nativeEvent: native,\n point: hit?.point,\n distance: hit?.distance ?? 0,\n object: hit?.object ?? obj,\n eventObject: obj,\n intersections: hits,\n entity,\n stopPropagation() {\n localStop = true;\n },\n get stopped() {\n return localStop;\n },\n };\n fn(ev);\n if (localStop) {\n stopped = true;\n claimedBy = obj;\n break;\n }\n }\n return { stopped, claimedBy };\n };\n\n /** Buttonless-move hover synth: over/out from pick transitions. */\n const syncHover = (\n now: { entity: Entity; hits: Intersection[] } | undefined,\n native: PointerEvent,\n ): void => {\n const nowEntity = now?.entity;\n const nowObjs = new Set<Object3D>();\n if (now !== undefined) {\n for (const hit of now.hits) {\n for (let obj: Object3D | null = hit.object; obj !== null; obj = obj.parent) nowObjs.add(obj);\n }\n }\n for (const [entity, prev] of hovered) {\n const gone: Object3D[] = [];\n for (const obj of prev) {\n if (entity !== nowEntity || !nowObjs.has(obj)) gone.push(obj);\n }\n for (const obj of gone) {\n prev.delete(obj);\n handlersOf(obj)?.onPointerOut?.({\n type: \"pointerout\",\n nativeEvent: native,\n point: undefined,\n distance: 0,\n object: obj,\n eventObject: obj,\n intersections: [],\n entity,\n stopPropagation() {},\n stopped: false,\n });\n }\n if (prev.size === 0) hovered.delete(entity);\n }\n if (now !== undefined && nowEntity !== undefined) {\n let set = hovered.get(nowEntity);\n if (set === undefined) {\n set = new Set();\n hovered.set(nowEntity, set);\n }\n for (const obj of nowObjs) {\n if (set.has(obj) || handlersOf(obj) === undefined) continue;\n set.add(obj);\n handlersOf(obj)?.onPointerOver?.({\n type: \"pointerover\",\n nativeEvent: native,\n point: undefined,\n distance: 0,\n object: obj,\n eventObject: obj,\n intersections: now.hits,\n entity: nowEntity,\n stopPropagation() {},\n stopped: false,\n });\n }\n }\n };\n\n return {\n route(kind, screenX, screenY, native) {\n if (kind === \"down\") {\n const cast = castAt(screenX, screenY);\n if (cast === undefined) {\n unclaimedDowns.delete(native.pointerId);\n return false;\n }\n const { stopped, claimedBy } = dispatch(\"onPointerDown\", \"pointerdown\", cast.entity, cast.hits, native);\n if (stopped) {\n unclaimedDowns.delete(native.pointerId);\n captures.set(native.pointerId, { entity: cast.entity, downObject: claimedBy });\n return true;\n }\n // UNCLAIMED down over an island: remember the topmost object so a\n // clean up on the same object still yields a click (native-R3F\n // parity; v1 RFC-008 coexistence — the engine's tap runs too, so a\n // cube click can log AND select, 2026-07-12 field report).\n const top = cast.hits[0]?.object;\n if (top !== undefined) unclaimedDowns.set(native.pointerId, { entity: cast.entity, object: top });\n return false;\n }\n\n const capture = captures.get(native.pointerId);\n\n if (kind === \"move\") {\n if (capture !== undefined) {\n const cast = castAt(screenX, screenY);\n const hits = cast !== undefined && cast.entity === capture.entity ? cast.hits : [];\n dispatch(\"onPointerMove\", \"pointermove\", capture.entity, hits, native, capture.downObject);\n return true;\n }\n if (native.buttons === 0) {\n const cast = castAt(screenX, screenY);\n syncHover(cast, native);\n // Native-R3F hover parity (2026-07-12 field report — v1's hover-driven\n // widgets, e.g. the shapes swarm, read point-carrying moves WITHOUT a\n // press): buttonless moves over an island dispatch onPointerMove with\n // the pick's island-local point. Never claims — the engine still sees\n // the move (no gesture is active buttonless, so nothing competes).\n if (cast !== undefined) {\n dispatch(\"onPointerMove\", \"pointermove\", cast.entity, cast.hits, native);\n }\n }\n return false;\n }\n\n // up | cancel\n if (capture === undefined) {\n // Unclaimed click pairing: down and up on the same topmost object.\n const pending = unclaimedDowns.get(native.pointerId);\n unclaimedDowns.delete(native.pointerId);\n if (kind === \"up\" && pending !== undefined) {\n const cast = castAt(screenX, screenY);\n if (cast !== undefined && cast.entity === pending.entity && cast.hits[0]?.object === pending.object) {\n dispatch(\"onClick\", \"click\", cast.entity, cast.hits, native, pending.object);\n }\n }\n return false;\n }\n captures.delete(native.pointerId);\n const cast = castAt(screenX, screenY);\n const hits = cast !== undefined && cast.entity === capture.entity ? cast.hits : [];\n if (kind === \"up\") {\n const { claimedBy } = dispatch(\"onPointerUp\", \"pointerup\", capture.entity, hits, native, capture.downObject);\n // Click pairs down+up on the same claiming object (R3F semantics).\n const clickTarget = claimedBy ?? capture.downObject;\n if (clickTarget !== undefined && clickTarget === capture.downObject) {\n dispatch(\"onClick\", \"click\", capture.entity, hits, native, clickTarget);\n }\n } else {\n dispatch(\"onPointerCancel\", \"pointercancel\", capture.entity, hits, native, capture.downObject);\n }\n return true;\n },\n };\n}\n"],"mappings":"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","names":["createElement","useEffect","useMemo","useRef","OrthographicCamera","useEffect","useEffect","useRef","useMemo","OrthographicCamera","useEffect","createElement","cast","hits"]}
|