@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
127 lines (98 loc) • 3.32 kB
JavaScript
import { assert } from "../../../core/assert.js";
import Name from "../../ecs/name/Name.js";
import { BoundQuaternionWriter } from "../curve/binding/BoundQuaternionWriter.js";
import { BoundValueWriter } from "../curve/binding/BoundValueWriter.js";
import { BoundVector3Writer } from "../curve/binding/BoundVector3Writer.js";
/**
*
* @param {EntityNode} node
* @returns {string|undefined}
*/
function get_node_name(node) {
/**
* @type {Name}
*/
const name = node.entity.getComponent(Name);
if (name === null) {
return undefined;
}
return name.getValue();
}
/**
* Following THREE.js PropertyBinding.findNode implementation
* @param {EntityNode} root
* @param {string} node_name
* @returns {EntityNode|undefined}
*/
function find_node(root, node_name) {
assert.isString(node_name, 'node_name');
const root_name = get_node_name(root);
if (root_name === node_name) {
return root;
}
// search into node subtree.
const children = root.children;
const child_count = children.length;
for (let j = 0; j < child_count; j++) {
/**
* @type {EntityNode}
*/
const child = children[j];
const subtree_result = find_node(child, node_name);
if (subtree_result !== undefined) {
return subtree_result;
}
}
}
/**
*
* @param {EntityNode} root
* @param {string[]} path_parts
* @param {number} part_first
* @param {number} part_last
*/
function entity_node_resolve_path(root, path_parts, part_first, part_last) {
assert.isNonNegativeInteger(part_first, 'part_first');
assert.isNonNegativeInteger(part_last, 'part_last');
assert.lessThan(part_last, path_parts.length, 'overflow');
let node = root;
for (let i = part_first; i <= part_last; i++) {
const part = path_parts[i];
const sub_node = find_node(node, part);
if (sub_node === undefined) {
throw new Error(`Child '${part}' not found, at index ${i} of [${path_parts.join(', ')}]. Valid names at this level: [${node.children.map(get_node_name)}]`);
}
node = sub_node;
}
return node;
}
/**
*
* @param {EntityNode} node
* @param {string[]} path_parts
* @returns {BoundValueWriter}
*/
export function bind_property_writer(node, path_parts) {
assert.defined(path_parts, 'path_parts');
assert.isArray(path_parts, 'path_parts');
const part_count = path_parts.length;
const property_name = path_parts[part_count - 1];
const parent = entity_node_resolve_path(node, path_parts, 0, part_count - 2);
let writer;
switch (property_name) {
case "position":
writer = new BoundVector3Writer(parent.transform.position);
break;
case "quaternion":
writer = new BoundQuaternionWriter(parent.transform.rotation);
break;
case "scale":
writer = new BoundVector3Writer(parent.transform.scale);
break;
default:
console.log(`Unsupported property name: ${property_name}`);
// NO-OP
writer = new BoundValueWriter();
}
return writer;
}