polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
160 lines (148 loc) • 5.21 kB
text/typescript
/**
* Value of the property the animation will be animated to
*
*
*/
import {TypedAnimNode} from './_Base';
import {TimelineBuilder} from '../../../core/animation/TimelineBuilder';
import {CoreType} from '../../../core/Type';
import {TypeAssert} from '../../poly/Assert';
import {Object3D} from 'three/src/core/Object3D';
import {Quaternion} from 'three/src/math/Quaternion';
enum PropertyValueMode {
CUSTOM = 'custom',
FROM_SCENE_GRAPH = 'from scene graph',
FROM_NODE = 'from node',
}
const PROPERTY_VALUE_MODES: PropertyValueMode[] = [
PropertyValueMode.CUSTOM,
PropertyValueMode.FROM_SCENE_GRAPH,
PropertyValueMode.FROM_NODE,
];
const PROPERTY_VALUE_MODE_CUSTOM = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.CUSTOM);
const PROPERTY_VALUE_MODE_FROM_SCENE_GRAPH = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.FROM_SCENE_GRAPH);
const PROPERTY_VALUE_MODE_FROM_NODE = PROPERTY_VALUE_MODES.indexOf(PropertyValueMode.FROM_NODE);
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
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('/geo1', {
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},
});
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},
});
/** @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},
});
/** @param value for a vector4 */
value4 = ParamConfig.VECTOR4([0, 0, 0, 0], {
visibleIf: {mode: PROPERTY_VALUE_MODE_CUSTOM, size: 4},
});
}
const ParamsConfig = new PropertyValueAnimParamsConfig();
export class PropertyValueAnimNode extends TypedAnimNode<PropertyValueAnimParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'propertyValue';
}
initializeNode() {
this.io.inputs.setCount(0, 1);
}
async cook(input_contents: TimelineBuilder[]) {
const timeline_builder = input_contents[0] || new TimelineBuilder();
await this._prepare_timeline_builder(timeline_builder);
this.set_timeline_builder(timeline_builder);
}
private async _prepare_timeline_builder(timeline_builder: TimelineBuilder) {
const mode = PROPERTY_VALUE_MODES[this.pv.mode];
switch (mode) {
case PropertyValueMode.CUSTOM: {
return this._prepare_timebuilder_custom(timeline_builder);
}
case PropertyValueMode.FROM_SCENE_GRAPH: {
return this._prepare_timebuilder_from_scene_graph(timeline_builder);
}
case PropertyValueMode.FROM_NODE: {
return await this._prepare_timebuilder_from_node(timeline_builder);
}
}
TypeAssert.unreachable(mode);
}
private _prepare_timebuilder_custom(timeline_builder: TimelineBuilder) {
const target_value = [this.pv.value1, this.pv.value2.clone(), this.pv.value3.clone(), this.pv.value4.clone()][
this.pv.size - 1
];
timeline_builder.setPropertyValue(target_value);
}
private _prepare_timebuilder_from_scene_graph(timeline_builder: TimelineBuilder) {
const property_name = this.pv.overridePropertyName ? this.pv.propertyName : timeline_builder.propertyName();
if (!property_name) {
return;
}
const found_object = this.scene().findObjectByMask(this.pv.objectMask);
if (found_object) {
const value: any = found_object[property_name as keyof Object3D];
if (value) {
if (CoreType.isNumber(value) || CoreType.isVector(value) || value instanceof Quaternion) {
timeline_builder.setPropertyValue(value);
}
}
}
}
private async _prepare_timebuilder_from_node(timeline_builder: TimelineBuilder) {
const property_name = this.pv.overridePropertyName ? this.pv.propertyName : timeline_builder.propertyName();
if (!property_name) {
return;
}
const node = this.pv.nodePath.node();
if (!node) {
return;
}
const param = node.params.get(property_name);
if (!param) {
return;
}
if (param.isDirty()) {
await param.compute();
}
const value = param.value;
if (value) {
if (CoreType.isNumber(value) || CoreType.isVector(value)) {
timeline_builder.setPropertyValue(value);
}
}
}
}