UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

110 lines (103 loc) 3.73 kB
import {BufferGeometry, Object3D} from 'three'; import {arrayCompact} from '../../ArrayUtils'; import {ObjectType} from '../Constant'; import {ThreejsCoreObject} from '../modules/three/ThreejsCoreObject'; import {isBooleanTrue} from '../../Type'; import {mergeGeometries} from 'three/examples/jsm/utils/BufferGeometryUtils'; import {TransformResetSopOperation} from '../../../engine/operations/sop/TransformReset'; import {TypedSopNode} from '../../../engine/nodes/sop/_Base'; import {applyJustifyModeToGeometries, TextJustifiyParams} from './TextJustify'; import {applyTextLineHeight, TextLineHeightParams} from './TextLineHeight'; import {TextType} from './TextType'; interface TextMergeAllLettersOptions extends TextJustifiyParams, TextLineHeightParams { geometries: Array<BufferGeometry | undefined>; textType: TextType; splitPerLetter: boolean; keepEmptyGeometries: boolean; text: string; } export function textMergeLetters(params: TextMergeAllLettersOptions) { const geometriesByLine = _geometriesByLine(params); for (const geometriesForLine of geometriesByLine) { applyJustifyModeToGeometries(geometriesForLine, params); applyTextLineHeight(geometriesForLine, params); } const allGeometries = geometriesByLine.flat(); const objects = _mergeOrSplit({...params, geometries: allGeometries}); if (objects) { const compactObjects: Object3D[] = []; return arrayCompact(objects, compactObjects); } } function _mergeOrSplit(params: TextMergeAllLettersOptions) { const objectType = params.textType == TextType.LINE ? ObjectType.LINE_SEGMENTS : ObjectType.MESH; if (isBooleanTrue(params.splitPerLetter)) { const chars = Array.from(params.text); let characterIndex = 0; let lineIndex = 0; function _createObject(geo?: BufferGeometry) { let character = chars[characterIndex]; if (character === '\n') { lineIndex++; characterIndex++; return; } if (character == ' ' && params.keepEmptyGeometries == false) { characterIndex++; return; } // if (geo == null) { // characterIndex++; // return; // } const object = TypedSopNode.createObject(geo || new BufferGeometry(), objectType); //this.createObject(geo, objectType); TransformResetSopOperation.centerObject(object, {applyMatrixToObject: true}); const coreObject = new ThreejsCoreObject(object, characterIndex); coreObject.addAttribute('character', character); object.name = character; coreObject.addAttribute('characterId', characterIndex); coreObject.addAttribute('lineId', lineIndex); characterIndex++; return object; } const objects: Object3D[] = []; for (let i = 0; i < params.geometries.length; i++) { const object = _createObject(params.geometries[i]); if (object) { objects.push(object); } } return objects; } else { try { const compactGeometries: BufferGeometry[] = []; arrayCompact(params.geometries, compactGeometries); if (compactGeometries.length > 0) { const mergedGeometry = mergeGeometries(compactGeometries); return [TypedSopNode.createObject(mergedGeometry, objectType)]; } } catch (err) { return; } } } interface GeometriesByLineParams { geometries: Array<BufferGeometry | undefined>; text: string; } function _geometriesByLine(params: GeometriesByLineParams): Array<Array<BufferGeometry | undefined>> { const list: Array<Array<BufferGeometry | undefined>> = []; const chars = Array.from(params.text); let characterIndex = 0; let lineIndex = 0; for (const geometry of params.geometries) { let character = chars[characterIndex]; if (character === '\n') { lineIndex++; } list[lineIndex] = list[lineIndex] || []; list[lineIndex].push(geometry); characterIndex++; } return list; }