@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
211 lines (198 loc) • 6.78 kB
text/typescript
/**
* Value of the property the animation will be animated to
*
*
*/
import {TypedAnimNode} from './_Base';
import {TimelineBuilder} from '../../../core/animation/TimelineBuilder';
import {isNumber, isVector} from '../../../core/Type';
import {TypeAssert} from '../../poly/Assert';
import {Object3D} from 'three';
import {Quaternion} from 'three';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {isBooleanTrue} from '../../../core/BooleanValue';
import {BaseNodeType} from '../_Base';
export enum AnimPropertyValueNodeMode {
CUSTOM = 'custom',
FROM_SCENE_GRAPH = 'from scene graph',
FROM_NODE = 'from node',
}
const PROPERTY_VALUE_MODES: AnimPropertyValueNodeMode[] = [
AnimPropertyValueNodeMode.CUSTOM,
AnimPropertyValueNodeMode.FROM_SCENE_GRAPH,
AnimPropertyValueNodeMode.FROM_NODE,
];
const PROPERTY_VALUE_MODE_CUSTOM = PROPERTY_VALUE_MODES.indexOf(AnimPropertyValueNodeMode.CUSTOM);
const PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH = PROPERTY_VALUE_MODES.indexOf(AnimPropertyValueNodeMode.FROM_SCENE_GRAPH);
const PROPERTY_VALUE_MODE_FROM_NODE = PROPERTY_VALUE_MODES.indexOf(AnimPropertyValueNodeMode.FROM_NODE);
class PropertyValueAnimParamsConfig extends NodeParamsConfig {
/** @param mode */
mode = ParamConfig.INTEGER(PROPERTY_VALUE_MODE_CUSTOM, {
menu: {
entries: PROPERTY_VALUE_MODES.map((name, value) => {
return {name, value};
}),
},
});
/** @param if set to a Polygonjs node, this is the node path */
nodePath = ParamConfig.NODE_PATH('', {
visibleIf: {mode: PROPERTY_VALUE_MODE_FROM_NODE},
});
/** @param if set to a THREE object, this is a mask to find the objects */
objectMask = ParamConfig.STRING('*geo1', {
visibleIf: {mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH},
});
/** @param print the object matching the objectMask, to help debugging */
printResolve = ParamConfig.BUTTON(null, {
visibleIf: {mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH},
callback: (node: BaseNodeType) => {
PropertyValueAnimNode.PARAM_CALLBACK_printResolve(node as PropertyValueAnimNode);
},
});
overridePropertyName = ParamConfig.BOOLEAN(0, {
visibleIf: [{mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH}, {mode: PROPERTY_VALUE_MODE_FROM_NODE}],
});
propertyName = ParamConfig.STRING('', {
visibleIf: [
{overridePropertyName: true, mode: PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH},
{overridePropertyName: true, mode: PROPERTY_VALUE_MODE_FROM_NODE},
],
});
/** @param size of the parameter to animate */
size = ParamConfig.INTEGER(3, {
range: [1, 4],
rangeLocked: [true, true],
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM},
separatorAfter: true,
});
/** @param value for a float */
value1 = ParamConfig.FLOAT(0, {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 1},
});
/** @param value for a vector2 */
value2 = ParamConfig.VECTOR2([0, 0], {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 2},
});
/** @param value for a vector3 */
value3 = ParamConfig.VECTOR3([0, 0, 0], {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 3, asColor: false},
});
/** @param value for a vector3 as color */
color = ParamConfig.COLOR([0, 0, 0], {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 3, asColor: true},
});
/** @param value for a vector4 */
value4 = ParamConfig.VECTOR4([0, 0, 0, 0], {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 4},
});
/** @param when using vector3, use toggle on it should be a color */
asColor = ParamConfig.BOOLEAN(0, {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 3},
});
}
const ParamsConfig = new PropertyValueAnimParamsConfig();
export class PropertyValueAnimNode extends TypedAnimNode<PropertyValueAnimParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return 'propertyValue';
}
override initializeNode() {
this.io.inputs.setCount(0, 1);
}
override async cook(inputContents: TimelineBuilder[]) {
const timelineBuilder = inputContents[0] || new TimelineBuilder();
await this._prepareTimelineBuilder(timelineBuilder);
this.setTimelineBuilder(timelineBuilder);
}
setMode(targetType: AnimPropertyValueNodeMode) {
this.p.mode.set(PROPERTY_VALUE_MODES.indexOf(targetType));
}
private async _prepareTimelineBuilder(timelineBuilder: TimelineBuilder) {
const mode = PROPERTY_VALUE_MODES[this.pv.mode];
switch (mode) {
case AnimPropertyValueNodeMode.CUSTOM: {
return this._prepareTimebuilderCustom(timelineBuilder);
}
case AnimPropertyValueNodeMode.FROM_SCENE_GRAPH: {
return this._prepareTimebuilderFromSceneGraph(timelineBuilder);
}
case AnimPropertyValueNodeMode.FROM_NODE: {
return await this._prepareTimebuilderFromNode(timelineBuilder);
}
}
TypeAssert.unreachable(mode);
}
private _prepareTimebuilderCustom(timelineBuilder: TimelineBuilder) {
const size = this.pv.size;
switch (size) {
case 1: {
return timelineBuilder.setPropertyValue(this.pv.value1);
}
case 2: {
return timelineBuilder.setPropertyValue(this.pv.value2);
}
case 3: {
if (isBooleanTrue(this.pv.asColor)) {
return timelineBuilder.setPropertyValue(this.pv.color);
} else {
return timelineBuilder.setPropertyValue(this.pv.value3);
}
}
case 4: {
return timelineBuilder.setPropertyValue(this.pv.value4);
}
}
}
private _prepareTimebuilderFromSceneGraph(timelineBuilder: TimelineBuilder) {
const propertyName = isBooleanTrue(this.pv.overridePropertyName)
? this.pv.propertyName
: timelineBuilder.propertyName();
if (!propertyName) {
return;
}
const foundObject = this._foundObjectFromSceneGraph() as Object3D | undefined;
if (foundObject) {
const value: any = foundObject[propertyName as keyof Object3D];
if (value) {
if (isNumber(value) || isVector(value) || value instanceof Quaternion) {
timelineBuilder.setPropertyValue(value);
}
}
}
}
private async _prepareTimebuilderFromNode(timelineBuilder: TimelineBuilder) {
const propertyName = isBooleanTrue(this.pv.overridePropertyName)
? this.pv.propertyName
: timelineBuilder.propertyName();
if (!propertyName) {
return;
}
const node = this.pv.nodePath.node();
if (!node) {
return;
}
const param = node.params.get(propertyName);
if (!param) {
return;
}
if (param.isDirty()) {
await param.compute();
}
const value = param.value;
if (value) {
if (isNumber(value) || isVector(value)) {
timelineBuilder.setPropertyValue(value);
}
}
}
static PARAM_CALLBACK_printResolve(node: PropertyValueAnimNode) {
node.printResolve();
}
private _foundObjectFromSceneGraph() {
return this.scene().findObjectByMask(this.pv.objectMask);
}
private printResolve() {
const foundObject = this._foundObjectFromSceneGraph();
console.log(foundObject);
}
}