@pmndrs/uikit
Version:
Build performant 3D user interfaces with Three.js and yoga.
58 lines (57 loc) • 3.66 kB
JavaScript
import { computed, signal } from '@preact/signals-core';
import { Component } from './component.js';
import { ElementType, setupOrderInfo } from '../order.js';
import { additionalTextDefaults, computedFont, computedFontFamilies, computedGylphGroupDependencies, createInstancedText, } from '../text/index.js';
import { computedPanelGroupDependencies } from '../panel/instanced-panel-group.js';
import { setupInstancedPanel } from '../panel/instanced-panel.js';
import { getDefaultPanelMaterialConfig } from '../panel/panel-material.js';
import { abortableEffect } from '../utils.js';
import { componentDefaults } from '../properties/defaults.js';
import { Matrix4, Quaternion, Vector3 } from 'three';
export const textDefaults = { ...componentDefaults, ...additionalTextDefaults };
const IdentityMatrix = new Matrix4();
const IdentityQuaternion = new Quaternion();
const IdentityScale = new Vector3(1, 1, 1);
const positionHelper = new Vector3();
export class Text extends Component {
backgroundOrderInfo = signal(undefined);
backgroundGroupDeps;
fontSignal;
globalTextMatrix;
constructor(inputProperties, initialClasses, config) {
super(inputProperties, initialClasses, {
defaults: textDefaults,
hasNonUikitChildren: false,
...config,
});
this.material.visible = false;
const parentClippingRect = computed(() => this.parentContainer.value?.clippingRect.value);
this.backgroundGroupDeps = computedPanelGroupDependencies(this.properties);
this.globalTextMatrix = computed(() => {
if (this.paddingInset.value == null || this.borderInset.value == null) {
return IdentityMatrix;
}
const [pTop, pRight, pBottom, pLeft] = this.paddingInset.value;
const [bTop, bRight, bBottom, bLeft] = this.borderInset.value;
const topInset = pTop + bTop;
const rightInset = pRight + bRight;
const bottomInset = pBottom + bBottom;
const leftInset = pLeft + bLeft;
const pixelSize = this.properties.value.pixelSize;
positionHelper.set((leftInset - rightInset) * 0.5 * pixelSize, (bottomInset - topInset) * 0.5 * pixelSize, 0);
return new Matrix4()
.compose(positionHelper, IdentityQuaternion, IdentityScale)
.premultiply(this.globalMatrix.value ?? IdentityMatrix);
});
setupOrderInfo(this.backgroundOrderInfo, this.properties, 'zIndex', ElementType.Panel, this.backgroundGroupDeps, computed(() => (this.parentContainer.value == null ? null : this.parentContainer.value.orderInfo.value)), this.abortSignal);
const fontFamilies = computedFontFamilies(this.properties, this.parentContainer);
this.fontSignal = computedFont(this.properties, fontFamilies);
setupOrderInfo(this.orderInfo, this.properties, 'zIndex', ElementType.Text, computedGylphGroupDependencies(this.fontSignal), this.backgroundOrderInfo, this.abortSignal);
setupInstancedPanel(this.properties, this.root, this.backgroundOrderInfo, this.backgroundGroupDeps, this.globalPanelMatrix, this.size, this.borderInset, parentClippingRect, this.isVisible, getDefaultPanelMaterialConfig(), this.abortSignal);
const customLayouting = createInstancedText(this, parentClippingRect, config?.selectionRange, config?.selectionTransformations, config?.caretTransformation, config?.instancedTextRef);
abortableEffect(() => this.node.setCustomLayouting(customLayouting.value), this.abortSignal);
}
add() {
throw new Error(`the text component can not have any children`);
}
}