polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
136 lines (126 loc) • 4.24 kB
text/typescript
/**
* Target of the animation
*
*
*/
import {TypedAnimNode} from './_Base';
import {TimelineBuilder} from '../../../core/animation/TimelineBuilder';
enum TargetType {
SCENE_GRAPH = 'scene graph',
NODE = 'node',
}
const TARGET_TYPES: TargetType[] = [TargetType.SCENE_GRAPH, TargetType.NODE];
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {TypeAssert} from '../../poly/Assert';
import {PropertyTarget} from '../../../core/animation/PropertyTarget';
import {AnimationUpdateCallback} from '../../../core/animation/UpdateCallback';
import {BaseParamType} from '../../params/_Base';
import {BaseNodeType} from '../_Base';
class TargetAnimParamsConfig extends NodeParamsConfig {
/** @param sets if the target is a Polygonjs node, or a THREE object */
type = ParamConfig.INTEGER(0, {
menu: {
entries: TARGET_TYPES.map((name, value) => {
return {name, value};
}),
},
});
/** @param if set to a Polygonjs node, this is the node path */
nodePath = ParamConfig.OPERATOR_PATH('/geo1', {
visibleIf: {type: TARGET_TYPES.indexOf(TargetType.NODE)},
});
/** @param if set to a THREE object, this is a mask to find the objects */
objectMask = ParamConfig.STRING('/geo*', {
visibleIf: {type: TARGET_TYPES.indexOf(TargetType.SCENE_GRAPH)},
});
/** @param sets if the matrix should be updated as the animation progresses */
updateMatrix = ParamConfig.BOOLEAN(0, {
visibleIf: {type: TARGET_TYPES.indexOf(TargetType.SCENE_GRAPH)},
});
/** @param prints which objects are targeted by this node, for debugging */
printResolve = ParamConfig.BUTTON(null, {
callback: (node: BaseNodeType, param: BaseParamType) => {
TargetAnimNode.PARAM_CALLBACK_print_resolve(node as TargetAnimNode);
},
});
}
const ParamsConfig = new TargetAnimParamsConfig();
export class TargetAnimNode extends TypedAnimNode<TargetAnimParamsConfig> {
params_config = ParamsConfig;
static type() {
return 'target';
}
initializeNode() {
this.io.inputs.setCount(0, 1);
this.scene().dispatchController.onAddListener(() => {
this.params.onParamsCreated('params_label', () => {
this.params.label.init([this.p.type, this.p.nodePath, this.p.objectMask], () => {
const type = TARGET_TYPES[this.pv.type];
switch (type) {
case TargetType.NODE:
return this.pv.nodePath;
case TargetType.SCENE_GRAPH:
return this.pv.objectMask;
}
TypeAssert.unreachable(type);
});
});
});
}
cook(input_contents: TimelineBuilder[]) {
const timeline_builder = input_contents[0] || new TimelineBuilder();
const target = this._create_target(timeline_builder);
timeline_builder.set_target(target);
this._set_update_callback(timeline_builder);
this.set_timeline_builder(timeline_builder);
}
private _create_target(timeline_builder: TimelineBuilder) {
const type = TARGET_TYPES[this.pv.type];
const property_target = new PropertyTarget();
switch (type) {
case TargetType.NODE: {
property_target.set_node_path(this.pv.nodePath);
return property_target;
}
case TargetType.SCENE_GRAPH: {
property_target.set_object_mask(this.pv.objectMask);
return property_target;
}
}
TypeAssert.unreachable(type);
}
private _set_update_callback(timeline_builder: TimelineBuilder) {
const type = TARGET_TYPES[this.pv.type];
let update_callback = timeline_builder.update_callback();
switch (type) {
case TargetType.NODE: {
return;
}
case TargetType.SCENE_GRAPH: {
if (this.pv.updateMatrix) {
update_callback = update_callback || new AnimationUpdateCallback();
update_callback.set_update_matrix(this.pv.updateMatrix);
timeline_builder.set_update_callback(update_callback);
}
return;
}
}
TypeAssert.unreachable(type);
}
static PARAM_CALLBACK_print_resolve(node: TargetAnimNode) {
node.print_resolve();
}
private print_resolve() {
const type = TARGET_TYPES[this.pv.type];
const timeline_builder = new TimelineBuilder();
const target = this._create_target(timeline_builder);
switch (type) {
case TargetType.NODE: {
return console.log(target.node(this.scene()));
}
case TargetType.SCENE_GRAPH: {
return console.log(target.objects(this.scene()));
}
}
}
}