@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
167 lines • 12.9 kB
JavaScript
import { TgdConsole } from "./../../debug/index.js";
import { TgdMat4 } from "./../../math/index.js";
import { isTgdInterfaceTransformablePainter, } from "../../interface/index.js";
import { TgdTransfo } from "../../math/transfo.js";
import { TgdPainterGroup } from "../group.js";
/**
* A Node can hold others Nodes or any object providing the
* TgdPainterNodeChild interface.
*
* Each Node is a local space for its children.
*
* All objects implementing `TgdInterfaceTransformable` have a `transfo` attribute
* that controls its position/orientation/scale in the world coordinate system. If
* you need an object's transformation to be defined in another object coordinate
* system, you just have to wrap it in a `TgdPainterNode`.
*
* As long as a `Transformable` is hold by the `painter` attribute of a `TgdPainterNode`,
* it will be controlled by the node.
* That means, you should not use its `transfo` attribute because it will be
* overwritten by the node.
*
* @example
* ```
* const body = new TgdPainterNode({
* target: new TgdPainterMesh(context)
* })
* const leftArm = new TgdPainterNode({
* transfo: { poition: [1, 0, 0] },
* target: new TgdPainterMesh(context)
* })
* const rightArm = new TgdPainterNode({
* transfo: { poition: [-1, 0, 0] },
* target: new TgdPainterMesh(context)
* })
* body.add( leftArm, rightArm )
* ```
*/
export class TgdPainterNode extends TgdPainterGroup {
constructor(options = {}) {
super();
this.parentMatrix = new TgdMat4();
/**
* globalMatrix = parentMatrix * transfo
*/
this.globalMatrix = new TgdMat4();
this.nodes = [];
this.targets = [];
const { children = [], transfo, logic, paintTheTargets = true, name = `TgdPainterNode/${this.name}` } = options;
this.paintTheTargets = paintTheTargets;
for (const child of children)
this.add(child);
this.transfo = new TgdTransfo(transfo);
if (logic)
this.logic.add(logic?.bind(this));
this.name = name;
}
delete() {
for (const child of this.nodes) {
child.delete();
}
for (const target of this.targets)
target.delete?.();
}
add(...painters) {
for (const painter of painters) {
if (painter instanceof TgdPainterNode) {
this.nodes.push(painter);
}
else if (isTgdInterfaceTransformablePainter(painter)) {
this.targets.push(painter);
}
else if (typeof painter === "function") {
this.logic.add(painter);
}
else {
console.error(`[${this.name}] Only nodes, transformable painters or logic functions can be added to a node!`);
console.error(`[${this.name}] You tried to add this:`, painter);
throw new Error(`[${this.name}] Only nodes, transformable painters or logic functions can be added to a node!`);
}
}
return this;
}
remove(...painters) {
for (const painter of painters) {
if (painter instanceof TgdPainterNode) {
const nodePosition = this.nodes.indexOf(painter);
if (nodePosition !== -1)
this.nodes.splice(nodePosition, 1);
}
else if (isTgdInterfaceTransformablePainter(painter)) {
const index = this.targets.indexOf(painter);
if (index !== -1)
this.targets.splice(index, 1);
}
}
return this;
}
getNodes() {
return [...this.nodes];
}
getTargets() {
return [...this.targets];
}
paint(time, delta) {
this.logic.exec(time, delta);
this.parentMatrix.reset();
const fringe = [this];
while (fringe.length > 0) {
const node = fringe.shift();
node.globalMatrix.from(node.parentMatrix).multiply(node.transfo.matrix);
node.logic.exec(time, delta);
for (const target of node.targets) {
target.transfo.matrix.from(node.globalMatrix);
if (this.paintTheTargets)
target.paint?.(time, delta);
}
for (const child of node.nodes) {
child.parentMatrix.from(node.globalMatrix);
fringe.push(child);
}
}
}
debug(caption = "TgdPainterNode") {
const out = new TgdConsole({ text: `${caption.trim()}\n`, bold: true });
actualDebug(out, this);
out.debug();
}
get hierarchy() {
return {
[this.active ? this.name : `${this.name} (Inactive)`]: [
...this.targets.map((target, index) => ({
[target.name ?? `target#${index}`]: null,
})),
...this.nodes.map((painter) => painter.hierarchy),
],
};
}
}
function actualDebug(out, node, indent = "| ") {
out.add(`${indent}${node.name} [${format(node.transfo.orientation)}] (${format(node.transfo.position)})\n`, {
bold: true,
});
const targets = node.getTargets();
if (targets.length > 0) {
if (targets.length === 1) {
out.add(`${indent} Target: ${targets[0].name ?? "..."}\n`);
}
else {
out.add(`${indent} Targets (${targets.length})\n`);
for (const target of targets) {
out.add(`${indent} ${target.name ?? "..."}\n`);
}
}
}
const nodes = node.getNodes();
if (nodes.length > 0) {
out.add(`${indent} Nodes (${nodes.length})`);
for (const child of nodes) {
actualDebug(out, child, `${indent} | `);
}
}
}
function format(vec) {
const list = [...vec].map((v) => v.toFixed(3));
return list.join(", ");
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wYWludGVyL25vZGUvbm9kZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQ3ZDLE9BQU8sRUFBRSxPQUFPLEVBQThCLE1BQU0sV0FBVyxDQUFBO0FBQy9ELE9BQU8sRUFDSCxrQ0FBa0MsR0FHckMsTUFBTSxpQkFBaUIsQ0FBQTtBQUN4QixPQUFPLEVBQUUsVUFBVSxFQUEwQixNQUFNLG9CQUFvQixDQUFBO0FBRXZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFlMUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0ErQkc7QUFDSCxNQUFNLE9BQU8sY0FBZSxTQUFRLGVBQWU7SUFZL0MsWUFBWSxVQUEwQyxFQUFFO1FBQ3BELEtBQUssRUFBRSxDQUFBO1FBVk0saUJBQVksR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO1FBQzdDOztXQUVHO1FBQ2MsaUJBQVksR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO1FBQzVCLFVBQUssR0FBcUIsRUFBRSxDQUFBO1FBQzVCLFlBQU8sR0FBdUMsRUFBRSxDQUFBO1FBSzdELE1BQU0sRUFBRSxRQUFRLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsZUFBZSxHQUFHLElBQUksRUFBRSxJQUFJLEdBQUcsa0JBQWtCLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQTtRQUMvRyxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQTtRQUN0QyxLQUFLLE1BQU0sS0FBSyxJQUFJLFFBQVE7WUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzdDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDdEMsSUFBSSxLQUFLO1lBQUUs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