@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
204 lines (190 loc) • 7.15 kB
text/typescript
/**
* Update properties from the THREE OBJECT3D from the input
*
* @remarks
* This can update properties such as name, visible, renderOrder.
*
*/
import {TypedSopNode} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {ObjectPropertiesSopOperation} from '../../operations/sop/ObjectProperties';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {isBooleanTrue} from '../../../core/Type';
import {StringParam} from '../../params/String';
import {BooleanParam} from '../../params/Boolean';
import {IntegerParam} from '../../params/Integer';
import {FloatParam} from '../../params/Float';
import {CoreObjectType} from '../../../core/geometry/ObjectContent';
import {filterCoreObjectsFromCoreGroup} from '../../../core/geometry/Mask';
import {BaseCoreObject} from '../../../core/geometry/entities/object/BaseCoreObject';
import {SopType} from '../../poly/registers/nodes/types/Sop';
const DEFAULT = ObjectPropertiesSopOperation.DEFAULT_PARAMS;
class ObjectPropertiesSopParamsConfig extends NodeParamsConfig {
/** @param group to assign the material to */
group = ParamConfig.STRING(DEFAULT.group, {
objectMask: true,
});
/** @param toggle on to set a new name */
tname = ParamConfig.BOOLEAN(DEFAULT.tname);
/** @param new name */
name = ParamConfig.STRING(DEFAULT.name, {
visibleIf: {tname: true},
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to set a new render order */
trenderOrder = ParamConfig.BOOLEAN(DEFAULT.trenderOrder);
/** @param render order */
renderOrder = ParamConfig.INTEGER(DEFAULT.renderOrder, {
visibleIf: {trenderOrder: true},
range: [0, 10],
rangeLocked: [false, false],
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to allow to set frustrumCulled */
tfrustumCulled = ParamConfig.BOOLEAN(DEFAULT.tfrustumCulled);
/** @param sets frustrumCulled */
frustumCulled = ParamConfig.BOOLEAN(DEFAULT.frustumCulled, {
visibleIf: {tfrustumCulled: true},
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to allow to set matrixAutoUpdate */
tmatrixAutoUpdate = ParamConfig.BOOLEAN(DEFAULT.tmatrixAutoUpdate);
/** @param sets matrixAutoUpdate */
matrixAutoUpdate = ParamConfig.BOOLEAN(DEFAULT.matrixAutoUpdate, {
visibleIf: {tmatrixAutoUpdate: true},
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to allow to set visible */
tvisible = ParamConfig.BOOLEAN(DEFAULT.tvisible);
/** @param sets visible */
visible = ParamConfig.BOOLEAN(DEFAULT.visible, {
visibleIf: {tvisible: true},
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to allow to set castShadow */
tcastShadow = ParamConfig.BOOLEAN(DEFAULT.tcastShadow);
/** @param sets castShadow */
castShadow = ParamConfig.BOOLEAN(DEFAULT.castShadow, {
visibleIf: {tcastShadow: true},
separatorAfter: true,
expression: {forEntities: true},
});
/** @param toggle on to allow to set receiveShadow */
treceiveShadow = ParamConfig.BOOLEAN(DEFAULT.treceiveShadow);
/** @param sets receiveShadow */
receiveShadow = ParamConfig.BOOLEAN(DEFAULT.receiveShadow, {
visibleIf: {treceiveShadow: true},
expression: {forEntities: true},
});
}
const ParamsConfig = new ObjectPropertiesSopParamsConfig();
export class ObjectPropertiesSopNode extends TypedSopNode<ObjectPropertiesSopParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return SopType.OBJECT_PROPERTIES;
}
override initializeNode() {
this.io.inputs.setCount(1);
this.io.inputs.initInputsClonedState(ObjectPropertiesSopOperation.INPUT_CLONED_STATE);
}
private _operation: ObjectPropertiesSopOperation | undefined;
override async cook(inputCoreGroups: CoreGroup[]) {
this._operation = this._operation || new ObjectPropertiesSopOperation(this.scene(), this.states, this);
// first check that any param has an expression
const paramWithExpression = this.params.all.find((param) => param.hasExpression());
if (paramWithExpression) {
const coreGroup = inputCoreGroups[0];
await this._cookWithExpressions(coreGroup);
this.setCoreGroup(coreGroup);
} else {
const coreGroup = this._operation.cook(inputCoreGroups, this.pv);
this.setCoreGroup(coreGroup);
}
}
private async _cookWithExpressions(coreGroup: CoreGroup) {
const selectedCoreObjects = filterCoreObjectsFromCoreGroup(coreGroup, this.pv);
await this._cookWithExpressionsForCoreObjects(selectedCoreObjects);
}
private async _cookWithExpressionsForCoreObjects<T extends CoreObjectType>(entities: BaseCoreObject<T>[]) {
const p = this.p;
async function applyStringParam(booleanParam: BooleanParam, valueParam: StringParam, property: 'name') {
if (isBooleanTrue(booleanParam.value)) {
if (valueParam.expressionController && valueParam.expressionController.entitiesDependent()) {
await valueParam.expressionController.computeExpressionForObjects(
entities,
(entity, value: string) => {
entity.object()[property] = value;
}
);
} else {
for (const entity of entities) {
const object = entity.object();
if (object) {
object[property] = valueParam.value;
}
}
}
}
}
async function applyNumberParam(
booleanParam: BooleanParam,
valueParam: IntegerParam | FloatParam,
property: 'renderOrder'
) {
if (isBooleanTrue(booleanParam.value)) {
if (valueParam.expressionController && valueParam.expressionController.entitiesDependent()) {
await valueParam.expressionController.computeExpressionForObjects(
entities,
(entity, value: number) => {
entity.object()[property] = value;
}
);
} else {
for (const entity of entities) {
const object = entity.object();
if (object) {
object[property] = valueParam.value;
}
}
}
}
}
async function applyBooleanParam(
booleanParam: BooleanParam,
valueParam: BooleanParam,
property: 'frustumCulled' | 'matrixAutoUpdate' | 'visible' | 'castShadow' | 'receiveShadow'
) {
if (isBooleanTrue(booleanParam.value)) {
if (valueParam.expressionController && valueParam.expressionController.entitiesDependent()) {
await valueParam.expressionController.computeExpressionForObjects(
entities,
(entity, value: boolean) => {
entity.object()[property] = value;
}
);
} else {
for (const entity of entities) {
const object = entity.object();
if (object) {
object[property] = valueParam.value;
}
}
}
}
}
await Promise.all([
applyStringParam(p.tname, p.name, 'name'),
applyNumberParam(p.trenderOrder, p.renderOrder, 'renderOrder'),
applyBooleanParam(p.tfrustumCulled, p.frustumCulled, 'frustumCulled'),
applyBooleanParam(p.tmatrixAutoUpdate, p.matrixAutoUpdate, 'matrixAutoUpdate'),
applyBooleanParam(p.tvisible, p.visible, 'visible'),
applyBooleanParam(p.tcastShadow, p.castShadow, 'castShadow'),
applyBooleanParam(p.treceiveShadow, p.receiveShadow, 'receiveShadow'),
]);
}
}