securityos/public/System/Hexells/demo.js

118 lines
2.9 KiB
JavaScript

class Demo {
constructor(canvas, isScreenMode) {
this.canvas = canvas;
this.gl = canvas.getContext("webgl", {
alpha: false,
desynchronized: true,
powerPreference: "high-performance"
});
this.brushRadius = 16;
this.stepPerFrame = 1;
this.isScreenMode = isScreenMode;
fetch("/System/Hexells/models.json")
.then((r) => r.json())
.then((models) => {
this.ca = new CA(this.gl, models, [160, 160], () =>
this.setup(models)
);
});
}
setup(models) {
this.shuffledModelIds = models.model_names
.map((_, i) => [Math.random(), i])
.sort()
.map((p) => p[1]);
this.curModelIndex = this.shuffledModelIds[0];
this.modelId = this.shuffledModelIds[this.curModelIndex];
this.ca.paint(0, 0, -1, this.modelId);
this.guesture = null;
setInterval(() => this.switchModel(1), 20 * 1000);
requestAnimationFrame(() => this.render());
}
startGestue(pos) {
this.gesture = {
d: 0,
l: 0,
prevPos: pos,
r: 0,
time: Date.now(),
u: 0,
};
}
touch(xy) {
const [x, y] = xy;
const g = this.gesture;
if (g) {
const [x0, y0] = g.prevPos;
g.l += Math.max(x0 - x, 0);
g.r += Math.max(x - x0, 0);
g.u += Math.max(y0 - y, 0);
g.d += Math.max(y - y0, 0);
g.prevPos = xy;
}
const viewSize = getViewSize();
this.ca.clearCircle(x, y, this.brushRadius, viewSize);
}
endGestue() {
if (!this.gesture) {
return;
}
if (Date.now() - this.gesture.time < 1000) {
const { l, r, u, d } = this.gesture;
if (l > 200 && Math.max(r, u, d) < l * 0.25) {
this.switchModel(-1);
} else if (r > 200 && Math.max(l, u, d) < r * 0.25) {
this.switchModel(1);
}
}
this.gesture = null;
}
switchModel(swipe) {
const n = this.shuffledModelIds.length;
this.curModelIndex = (this.curModelIndex + n + swipe) % n;
const id = this.shuffledModelIds[this.curModelIndex];
this.setModel(id);
}
setModel(id) {
this.modelId = id;
this.ca.paint(0, 0, -1, id);
this.ca.disturb();
}
getViewSize() {
return [
globalThis.demoCanvasRect?.width || this.canvas.clientWidth || this.canvas.width,
globalThis.demoCanvasRect?.height || this.canvas.clientHeight || this.canvas.height
];
}
render() {
for (let i = 0; i < this.stepPerFrame; ++i) {
this.ca.step();
}
const { canvas } = this;
const dpr = globalThis.devicePixelRatio || 1;
const [w, h] = this.getViewSize();
canvas.width = Math.round(w * dpr);
canvas.height = Math.round(h * dpr);
twgl.bindFramebufferInfo(this.gl);
this.ca.draw(this.getViewSize(), "color");
requestAnimationFrame(() => this.render());
}
}
globalThis.Demo = Demo;