@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
125 lines (120 loc) • 4.85 kB
text/typescript
/**
* Creates CSS2DObjects.
*
* @remarks
* This is very useful to create 2D html labels that would be positioned at specific points in the 3D world.
* Note that the camera must be configured to use a CSS2DRenderer to display them
*
*
*/
import {TypedSopNode} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {StringParamLanguage} from '../../params/utils/OptionsController';
import {SopType} from '../../poly/registers/nodes/types/Sop';
import {Poly} from '../../Poly';
import {CoreCSSObjectAttribute, DEFAULT_CSS2DOBJECT} from '../../../core/render/CSSRenderers/CSSObjectAttribute';
import {createCSS2DObject} from '../../../core/render/CSSRenderers/CSS2DObject';
import {stringToAttribNames} from '../../../core/String';
import {Object3D} from 'three';
import {InputCloneMode} from '../../poly/InputCloneMode';
import {replaceChild} from '../../poly/PolyOnObjectsAddRemoveHooksController';
import {CoreObjectType, ObjectContent} from '../../../core/geometry/ObjectContent';
class CSS2DObjectSopParamsConfig extends NodeParamsConfig {
/** @param toggles on if attributes are copied from the geometry to the html element */
copyAttributes = ParamConfig.BOOLEAN(true);
/** @param names of the attributes that are copied from the geometry to the html element */
attributesToCopy = ParamConfig.STRING('', {
visibleIf: {copyAttributes: true},
});
/** @param defines if the htmlId attribute is used to create the html id attribute */
overrideId = ParamConfig.BOOLEAN(true);
/** @param value of the html element id attribute */
id = ParamConfig.STRING(DEFAULT_CSS2DOBJECT.id, {
visibleIf: {overrideId: 1},
});
/** @param defines if the htmlClass attribute is used to create the html class */
overrideClassName = ParamConfig.BOOLEAN(true);
/** @param value of the html class */
className = ParamConfig.STRING(DEFAULT_CSS2DOBJECT.className, {
visibleIf: {overrideClassName: 1},
});
/** @param defines if the html attribute is used to create the html content */
overrideHTML = ParamConfig.BOOLEAN(true);
/** @param value of the html content */
html = ParamConfig.STRING(DEFAULT_CSS2DOBJECT.html, {
visibleIf: {overrideHTML: 1},
language: StringParamLanguage.HTML,
});
}
const ParamsConfig = new CSS2DObjectSopParamsConfig();
export class CSS2DObjectSopNode extends TypedSopNode<CSS2DObjectSopParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return SopType.CSS2D_OBJECT;
}
override initializeNode() {
this.io.inputs.setCount(0, 1);
this.io.inputs.initInputsClonedState(InputCloneMode.FROM_NODE);
}
override cook(inputCoreGroups: CoreGroup[]) {
const coreGroup = inputCoreGroups[0];
if (coreGroup) {
// if there are input threejs objects,
// add attributes to them
const objects = coreGroup.allObjects();
for (const object of objects) {
this._addAttributes(object);
}
this.setCoreGroup(coreGroup);
} else {
// if no input, create CSS object
// and also add attributes.
// Even if the attributes can be redundant,
// they give clues that they can be changed
// to update the output
const attribNames: string[] = [];
const group = createCSS2DObject({
id: this.pv.id,
className: this.pv.className,
html: this.pv.html,
copyAttributes: this.pv.copyAttributes,
attributesToCopy: stringToAttribNames(this.pv.attributesToCopy, attribNames),
});
group.name = this.name();
this._addAttributes(group);
this.setObjects([group]);
}
}
private _addAttributes(object: ObjectContent<CoreObjectType>) {
Poly.onObjectsAddRemoveHooks.assignOnAddHookHandler(object, this);
if (this.pv.overrideId) {
CoreCSSObjectAttribute.setElementId(object, this.pv.id);
}
if (this.pv.overrideClassName) {
CoreCSSObjectAttribute.setElementClass(object, this.pv.className);
}
if (this.pv.overrideHTML) {
CoreCSSObjectAttribute.setElementHTML(object, this.pv.html);
}
CoreCSSObjectAttribute.setCopyAttributes(object, this.pv.copyAttributes);
CoreCSSObjectAttribute.setAttributesToCopy(object, this.pv.attributesToCopy);
}
public override updateObjectOnAdd(object: Object3D, parent: Object3D) {
const id = CoreCSSObjectAttribute.getElementId(object);
const className = CoreCSSObjectAttribute.getElementClass(object);
const html = CoreCSSObjectAttribute.getElementHTML(object);
const copyAttributes = CoreCSSObjectAttribute.getCopyAttributes(object);
const attributesToCopy = CoreCSSObjectAttribute.getAttributesToCopy(object);
const attribNames: string[] = [];
const CSSObject = createCSS2DObject({
object,
id,
className,
html,
copyAttributes,
attributesToCopy: stringToAttribNames(attributesToCopy, attribNames),
});
replaceChild(parent, object, CSSObject);
}
}