UNPKG

@polygonjs/polygonjs

Version:

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

154 lines (145 loc) 4.57 kB
/** * Populates informations from an IntersectData into its parameters * * @remarks * * This node typically works with the event/raycast * */ import {TypedEventNode} from './_Base'; import {AttribType, ATTRIBUTE_TYPES, AttribTypeMenuEntries} from '../../../core/geometry/Constant'; import {EventConnectionPoint, EventConnectionPointType} from '../utils/io/connections/Event'; import {Intersection} from 'three'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {isString, isNumber, isArray, isVector} from '../../../core/Type'; import {TypeAssert} from '../../poly/Assert'; import {resolveIntersectGeometryAttribute} from '../../../core/geometry/intersect/CoreIntersect'; import {coreObjectClassFactory} from '../../../core/geometry/CoreObjectFactory'; import {EventContext} from '../../../core/event/EventContextType'; export enum TargetType { SCENE_GRAPH = 'scene graph', NODE = 'node', } export const TARGET_TYPES: TargetType[] = [TargetType.SCENE_GRAPH, TargetType.NODE]; class IntersectDataParamsConfig extends NodeParamsConfig { /** @param geometry vertex attribute to read */ attributeName = ParamConfig.STRING('id', { cook: false, }); /** @param type of attribute */ attributeType = ParamConfig.INTEGER(ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC), { menu: { entries: AttribTypeMenuEntries, }, }); /** @param attribute value for float */ attributeValue1 = ParamConfig.FLOAT(0, { cook: false, visibleIf: { attributeType: ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC), }, }); /** @param attribute value that attributeValue1 is set to when no object is intersected */ resetValue1 = ParamConfig.FLOAT(-1, { cook: false, visibleIf: { attributeType: ATTRIBUTE_TYPES.indexOf(AttribType.NUMERIC), }, }); /** @param attribute value for string */ attributeValues = ParamConfig.STRING('', { visibleIf: { attributeType: ATTRIBUTE_TYPES.indexOf(AttribType.STRING), }, }); /** @param attribute value that attributeValues is set to when no object is intersected */ resetValues = ParamConfig.STRING('', { visibleIf: { attributeType: ATTRIBUTE_TYPES.indexOf(AttribType.STRING), }, }); } const ParamsConfig = new IntersectDataParamsConfig(); export class IntersectDataEventNode extends TypedEventNode<IntersectDataParamsConfig> { override paramsConfig = ParamsConfig; static override type() { return 'intersectData'; } static readonly INPUT_HIT = 'hit'; static readonly INPUT_MISS = 'miss'; override initializeNode() { this.io.inputs.setNamedInputConnectionPoints([ new EventConnectionPoint( IntersectDataEventNode.INPUT_HIT, EventConnectionPointType.BASE, this._processHit.bind(this) ), new EventConnectionPoint( IntersectDataEventNode.INPUT_MISS, EventConnectionPointType.BASE, this._processMiss.bind(this) ), ]); } private _processHit(context: EventContext<Event>) { const intersect = context.value?.intersect; if (!intersect) { return; } this._resolveIntersectAttribute(intersect); } private _processMiss(context: EventContext<Event>) { const attribType = ATTRIBUTE_TYPES[this.pv.attributeType]; switch (attribType) { case AttribType.NUMERIC: { this.p.attributeValue1.set(this.pv.resetValue1); return; } case AttribType.STRING: { this.p.attributeValues.set(this.pv.resetValues); return; } } TypeAssert.unreachable(attribType); } private _resolveIntersectAttribute(intersection: Intersection) { const attribType = ATTRIBUTE_TYPES[this.pv.attributeType]; let attribValue: string | number | null | undefined = IntersectDataEventNode.resolveObjectAttribute( intersection, this.pv.attributeName ); if (attribValue == null) { attribValue = resolveIntersectGeometryAttribute(intersection, this.pv.attributeName, attribType); } if (attribValue != null) { switch (attribType) { case AttribType.NUMERIC: { this.p.attributeValue1.set(attribValue); return; } case AttribType.STRING: { if (isString(attribValue)) { this.p.attributeValues.set(attribValue); } return; } } TypeAssert.unreachable(attribType); } } static resolveObjectAttribute(intersection: Intersection, attribName: string) { const value = coreObjectClassFactory(intersection.object).attribValue(intersection.object, attribName); if (value == null) { return; } if (isNumber(value) || isString(value)) { return value; } if (isArray(value)) { return value[0]; } if (isVector(value)) { return value.x; } } }