UNPKG

@pmndrs/uikit

Version:

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

103 lines (102 loc) 5.3 kB
import { createFlexNodeState } from '../flex/node.js'; import { createHoverPropertyTransformers, setupCursorCleanup } from '../hover.js'; import { computedIsClipped, createGlobalClippingPlanes } from '../clipping.js'; import { setupObjectTransform, computedTransformMatrix } from '../transform.js'; import { createResponsivePropertyTransformers } from '../responsive.js'; import { ElementType, computedOrderInfo, setupRenderOrder } from '../order.js'; import { createActivePropertyTransfomers } from '../active.js'; import { signal } from '@preact/signals-core'; import { computedGlobalMatrix, computedHandlers, computedIsVisible, computedMergedProperties, setupNode, setupMatrixWorldUpdate, setupPointerEvents, computedAncestorsHaveListeners, } from './utils.js'; import { setupLayoutListeners, setupClippedListeners } from '../listeners.js'; import { FrontSide, Material } from 'three'; import { darkPropertyTransformers } from '../dark.js'; import { makeClippedCast } from '../panel/index.js'; import { abortableEffect } from '../utils.js'; export function createCustomContainerState(parentCtx, style, properties, defaultProperties) { const flexState = createFlexNodeState(); const hoveredSignal = signal([]); const activeSignal = signal([]); //properties const mergedProperties = computedMergedProperties(style, properties, defaultProperties, { ...darkPropertyTransformers, ...createResponsivePropertyTransformers(parentCtx.root.size), ...createHoverPropertyTransformers(hoveredSignal), ...createActivePropertyTransfomers(activeSignal), }); const transformMatrix = computedTransformMatrix(mergedProperties, flexState, parentCtx.root.pixelSize); const globalMatrix = computedGlobalMatrix(parentCtx.childrenMatrix, transformMatrix); const isClipped = computedIsClipped(parentCtx.clippingRect, globalMatrix, flexState.size, parentCtx.root.pixelSize); const isVisible = computedIsVisible(flexState, isClipped, mergedProperties); const orderInfo = computedOrderInfo(mergedProperties, 'zIndexOffset', ElementType.Custom, undefined, parentCtx.orderInfo); const handlers = computedHandlers(style, properties, defaultProperties, hoveredSignal, activeSignal); const ancestorsHaveListeners = computedAncestorsHaveListeners(parentCtx, handlers); return Object.assign(flexState, { hoveredSignal, activeSignal, mergedProperties, transformMatrix, globalMatrix, isClipped, isVisible, orderInfo, handlers, ancestorsHaveListeners, root: parentCtx.root, }); } export function setupCustomContainer(state, parentCtx, style, properties, object, mesh, abortSignal) { setupCursorCleanup(state.hoveredSignal, abortSignal); //create node setupNode(state, parentCtx, object, true, abortSignal); //transform setupObjectTransform(parentCtx.root, object, state.transformMatrix, abortSignal); //setup mesh const clippingPlanes = createGlobalClippingPlanes(parentCtx.root, parentCtx.clippingRect); mesh.matrixAutoUpdate = false; if (mesh.material instanceof Material) { const material = mesh.material; material.clippingPlanes = clippingPlanes; material.needsUpdate = true; material.shadowSide = FrontSide; abortableEffect(() => { material.depthTest = state.mergedProperties.value.read('depthTest', true); parentCtx.root.requestRender(); }, abortSignal); abortableEffect(() => { material.depthWrite = state.mergedProperties.value.read('depthWrite', false); parentCtx.root.requestRender(); }, abortSignal); } mesh.raycast = makeClippedCast(mesh, mesh.raycast, parentCtx.root.objectRef, parentCtx.clippingRect, state.orderInfo, state); setupRenderOrder(mesh, parentCtx.root, state.orderInfo); abortableEffect(() => { mesh.renderOrder = state.mergedProperties.value.read('renderOrder', 0); parentCtx.root.requestRender(); }, abortSignal); abortableEffect(() => { mesh.receiveShadow = state.mergedProperties.value.read('receiveShadow', false); parentCtx.root.requestRender(); }, abortSignal); abortableEffect(() => { mesh.castShadow = state.mergedProperties.value.read('castShadow', false); parentCtx.root.requestRender(); }, abortSignal); abortableEffect(() => { if (state.size.value == null) { return; } const [width, height] = state.size.value; const pixelSize = parentCtx.root.pixelSize.value; mesh.scale.set(width * pixelSize, height * pixelSize, 1); mesh.updateMatrix(); parentCtx.root.requestRender(); }, abortSignal); abortableEffect(() => { void (mesh.visible = state.isVisible.value); parentCtx.root.requestRender(); }, abortSignal); setupMatrixWorldUpdate(true, true, object, parentCtx.root, state.globalMatrix, false, abortSignal); setupPointerEvents(state.mergedProperties, state.ancestorsHaveListeners, parentCtx.root, object, true, abortSignal); setupLayoutListeners(style, properties, state.size, abortSignal); setupClippedListeners(style, properties, state.isClipped, abortSignal); }