@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
236 lines (235 loc) • 8.07 kB
JavaScript
"use strict";
import { Quaternion, Color, Vector2, Vector3, Vector4 } from "three";
import { ParamType } from "../../engine/poly/ParamType";
import { Poly } from "../../engine/Poly";
import { isNumber, isEuler, isVector, isColor, isQuaternion } from "../Type";
import { animBuilderCommonVars } from "./vars/Common";
import { animBuilderStartTimeline } from "./vars/StartTimeline";
import { populateVarsForParamVector4 } from "./vars/type/Vector4";
import { populateVarsForColor, populateVarsForParamColor } from "./vars/type/Color";
import { populateVarsForParamVector3 } from "./vars/type/Vector3";
import { populateVarsForParamVector2 } from "./vars/type/Vector2";
import { populateVarsForNumber, populateVarsForSingleNumber } from "./vars/type/Number";
import { populateVarsForVector } from "./vars/type/Vector";
import { populateVarsAndCreateProxyForQuaternion } from "./vars/type/Quaternion";
import { populateVarsForEuler } from "./vars/type/Euler";
const PROPERTY_SEPARATOR = ".";
export class TimelineBuilderProperty {
constructor() {
this._debug = false;
}
setName(name) {
this._propertyName = name;
}
setTargetValue(value) {
this._targetValue = value;
}
name() {
return this._propertyName;
}
targetValue() {
return this._targetValue;
}
setDebug(debug) {
this._debug = debug;
}
_printDebug(message) {
if (!this._debug) {
return;
}
console.log(message);
}
clone() {
const cloned = new TimelineBuilderProperty();
if (this._propertyName) {
cloned.setName(this._propertyName);
}
if (this._targetValue != null) {
const newTargetValue = isNumber(this._targetValue) ? this._targetValue : this._targetValue.clone();
cloned.setTargetValue(newTargetValue);
}
return cloned;
}
addToTimeline(options) {
const target = options.propertyTarget || options.target;
const objects = target.objects();
const node = target.node();
this._printDebug(["addToTimeline", target, objects, node]);
if (objects) {
this._populateWithObjects(objects, options);
}
if (node) {
this._populateWithNode(node, options);
}
}
_populateWithObjects(objects, options) {
const { timelineBuilder } = options;
this._printDebug(["_populateWithObjects", objects]);
if (!this._propertyName) {
Poly.warn("no property name given");
return;
}
if (this._targetValue == null) {
Poly.warn("no target value given");
return;
}
const operation = timelineBuilder.operation();
const updateCallback = timelineBuilder.updateCallback();
for (const object3d of objects) {
const props = this._sceneGraphProps(object3d, this._propertyName);
if (props) {
const registerableProp = {
object: object3d,
propertyName: this._propertyName
};
let { targetProperty, toTarget, propertyNames } = props;
const vars = animBuilderCommonVars(timelineBuilder);
if (updateCallback && updateCallback.updateMatrix()) {
const oldMatrixAutoUpdate = object3d.matrixAutoUpdate;
vars.onUpdate = () => {
object3d.matrixAutoUpdate = true;
};
vars.onComplete = () => {
object3d.matrixAutoUpdate = oldMatrixAutoUpdate;
if (!object3d.matrixAutoUpdate) {
object3d.updateMatrix();
}
};
}
if (targetProperty instanceof Quaternion && this._targetValue instanceof Quaternion) {
toTarget = populateVarsAndCreateProxyForQuaternion({
targetValue: this._targetValue,
vars,
targetProperty
});
}
this._populateVarsForObjectProperty({
targetValue: this._targetValue,
vars,
targetProperty,
propertyNames,
operation
});
if (toTarget) {
animBuilderStartTimeline({ ...options, vars, target: toTarget, registerableProp });
}
}
}
}
_populateVarsForObjectProperty(options) {
const { vars, targetValue, targetProperty, propertyNames, operation } = options;
function warnMismatch(expectedType) {
Poly.warn(
`mismatch between targetValue and targetProperty (expected ${expectedType})`,
targetValue,
targetProperty
);
}
if (isNumber(targetProperty)) {
if (isNumber(targetValue)) {
return populateVarsForNumber({ targetValue, vars, targetProperty, propertyNames, operation });
}
return warnMismatch("number");
}
if (isEuler(targetProperty)) {
if (targetValue instanceof Vector3) {
return populateVarsForEuler({ targetValue, vars, targetProperty, propertyNames, operation });
}
return warnMismatch("euler");
}
if (isVector(targetProperty)) {
if (isVector(targetValue)) {
return populateVarsForVector({ targetValue, vars, targetProperty, propertyNames, operation });
}
return warnMismatch("vector");
}
if (isColor(targetProperty)) {
if (isColor(targetValue)) {
return populateVarsForColor({ targetValue, vars, targetProperty, propertyNames, operation });
}
return warnMismatch("color");
}
if (isQuaternion(targetProperty)) {
}
Poly.warn(`targetValue and targetProp are not recognized types`, targetValue, targetProperty);
}
_sceneGraphProps(object, propertyName) {
const elements = propertyName.split(PROPERTY_SEPARATOR);
if (elements.length > 1) {
const firstElement = elements.shift();
const subObject = object[firstElement];
if (subObject) {
const subPropertyName = elements.join(PROPERTY_SEPARATOR);
return this._sceneGraphProps(subObject, subPropertyName);
} else {
Poly.warn(`property ${firstElement} not found on object`, object);
}
} else {
const targetProperty = object[propertyName];
let toTarget = null;
const propertyNames = [];
if (isNumber(targetProperty)) {
toTarget = object;
propertyNames.push(propertyName);
} else {
toTarget = targetProperty;
if (this._targetValue instanceof Vector2) {
propertyNames.push("x", "y");
}
if (this._targetValue instanceof Vector3) {
propertyNames.push("x", "y", "z");
}
if (this._targetValue instanceof Vector4) {
propertyNames.push("x", "y", "z", "w");
}
if (this._targetValue instanceof Color) {
propertyNames.push("r", "g", "b");
}
if (this._targetValue instanceof Quaternion) {
}
}
return {
targetProperty,
toTarget,
propertyNames
};
}
}
_populateWithNode(node, options) {
this._printDebug(["_populateWithNode", node]);
const targetParam = node.p[this._propertyName];
this._printDebug(["targetParam", targetParam]);
if (!targetParam) {
Poly.warn(`${this._propertyName} not found on node ${node.path()}`);
return;
}
if (targetParam) {
this._populateVarsForParam(targetParam, options);
}
}
_populateVarsForParam(param, options) {
this._printDebug(["_populateVarsForParam", param]);
if (this._targetValue == null) {
return;
}
switch (param.type()) {
case ParamType.INTEGER:
case ParamType.FLOAT: {
return populateVarsForSingleNumber(param, this._targetValue, options);
}
case ParamType.VECTOR2: {
return populateVarsForParamVector2(param, this._targetValue, options);
}
case ParamType.VECTOR3: {
return populateVarsForParamVector3(param, this._targetValue, options);
}
case ParamType.COLOR: {
return populateVarsForParamColor(param, this._targetValue, options);
}
case ParamType.VECTOR4: {
return populateVarsForParamVector4(param, this._targetValue, options);
}
}
Poly.warn(`param type cannot be animated (yet): '${param.type()}' '${param.path()}'`);
}
}