@thi.ng/scenegraph
Version:
Extensible 2D/3D scene graph with @thi.ng/hiccup-canvas support
80 lines (79 loc) • 2.34 kB
JavaScript
import { isNumber } from "@thi.ng/checks/is-number";
import { invert23 } from "@thi.ng/matrices/invert";
import { mulM23 } from "@thi.ng/matrices/mulm";
import { mulV23 } from "@thi.ng/matrices/mulv";
import { transform23 } from "@thi.ng/matrices/transform";
import { madd2 } from "@thi.ng/vectors/madd";
import { set2 } from "@thi.ng/vectors/set";
import { setN2 } from "@thi.ng/vectors/setn";
import { sub2 } from "@thi.ng/vectors/sub";
import { ANode } from "./anode.js";
import { toHiccup } from "./hiccup.js";
class Node2D extends ANode {
translate;
rotate;
scale;
constructor(opts) {
super(opts);
this.translate = opts.translate ?? [0, 0];
this.rotate = opts.rotate ?? 0;
const scale = opts.scale ?? 1;
this.scale = isNumber(scale) ? [scale, scale] : scale;
this.update();
}
copy() {
return new Node2D({
id: this.id,
parent: this.parent,
translate: set2([], this.translate),
rotate: this.rotate,
scale: set2([], this.scale),
body: this.body
});
}
update() {
if (this.enabled) {
this.mat = transform23([], this.translate, this.rotate, this.scale);
if (this.parent) {
mulM23(this.mat, this.parent.mat, this.mat);
}
invert23(this.invMat, this.mat);
for (let c of this.children) {
c.update();
}
}
}
mapGlobalPoint(p) {
return mulV23([], this.invMat, p);
}
mapLocalPointToGlobal(p) {
return mulV23([], this.mat, p);
}
mapLocalPointToNode(dest, p) {
return mulV23(null, dest.invMat, mulV23([], this.mat, p));
}
scaleWithReferencePoint(ref, scale) {
if (this.enabled) {
const currScale = isNumber(this.scale) ? setN2([], this.scale) : this.scale;
const newScale = isNumber(scale) ? setN2([], scale) : scale;
const delta = sub2([], currScale, newScale);
this.scale = newScale;
this.translate = madd2([], ref, delta, this.translate);
this.update();
}
return this;
}
/**
* By implementing this method (`IToHiccup` interface), scene graph nodes
* can be directly used by hdom-canvas, hiccup-canvas, rdom-canvas or
* hiccup-svg (for the latter one needs to call `convertTree()` first).
*
* @param ctx - arbitrary user data
*/
toHiccup(ctx) {
return toHiccup(this, ctx);
}
}
export {
Node2D
};