UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

167 lines 12.9 kB
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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