UNPKG

@pmndrs/uikit

Version:

Build performant 3D user interfaces with Three.js and yoga.

77 lines (76 loc) 3.24 kB
import { computed, effect, signal, untracked } from '@preact/signals-core'; import { createRootState, setupRoot, DEFAULT_PIXEL_SIZE } from '../components/root.js'; import { Parent, bindHandlers } from './utils.js'; import { readReactive } from '../utils.js'; export class Root extends Parent { styleSignal = signal(undefined); propertiesSignal; defaultPropertiesSignal; unsubscribe; onFrameSet = new Set(); fontFamiliesSignal; pixelSizeSignal; internals; constructor(camera, renderer, properties, defaultProperties, fontFamilies, requestRender, requestFrame) { super(); this.pixelSizeSignal = signal(properties?.pixelSize ?? DEFAULT_PIXEL_SIZE); this.matrixAutoUpdate = false; this.fontFamiliesSignal = signal(fontFamilies); this.propertiesSignal = signal(properties); this.defaultPropertiesSignal = signal(defaultProperties); this.unsubscribe = effect(() => { let getCamera; if (typeof camera === 'function') { getCamera = camera; } else { const cam = readReactive(camera); if (cam == null) { this.contextSignal.value = undefined; return; } getCamera = () => cam; } const abortController = new AbortController(); const objectRef = { current: this }; this.internals = createRootState(objectRef, computed(() => readReactive(this.pixelSizeSignal.value) ?? DEFAULT_PIXEL_SIZE), this.styleSignal, this.propertiesSignal, this.defaultPropertiesSignal, getCamera, renderer, this.onFrameSet, requestRender ?? (() => { }), requestFrame ?? (() => { })); this.contextSignal.value = Object.assign(this.internals, { fontFamiliesSignal: this.fontFamiliesSignal }); super.add(this.internals.interactionPanel); setupRoot(this.internals, this.styleSignal, this.propertiesSignal, this, this.childrenContainer, abortController.signal); bindHandlers(this.internals.handlers, this, abortController.signal); return () => { this.onFrameSet.clear(); this.remove(this.internals.interactionPanel); abortController.abort(); }; }); } update(delta) { for (const onFrame of this.onFrameSet) { onFrame(delta); } } setFontFamilies(fontFamilies) { this.fontFamiliesSignal.value = fontFamilies; } getComputedProperty(key) { return untracked(() => this.internals.mergedProperties?.value.read(key, undefined)); } getStyle() { return this.styleSignal.peek(); } setStyle(style, replace) { this.styleSignal.value = replace ? style : { ...this.styleSignal.peek(), ...style }; } setProperties(properties) { this.pixelSizeSignal.value = properties?.pixelSize ?? DEFAULT_PIXEL_SIZE; this.propertiesSignal.value = properties; } setDefaultProperties(properties) { this.defaultPropertiesSignal.value = properties; } destroy() { this.parent?.remove(this); this.unsubscribe(); } }