@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
246 lines • 20.7 kB
JavaScript
import { TgdCameraPerspective } from "./../../camera/index.js";
import { TgdContext } from "./../../context/index.js";
import { TgdMat3, TgdQuat, TgdVec3 } from "./../../math/index.js";
import { TgdTexture2D } from "./../../texture/index.js";
import { tgdActionCreateCameraInterpolation, tgdCanvasCreate } from "./../../utils/index.js";
import { TgdPainterClear } from "../clear.js";
import { TgdPainterGroupCamera } from "../group-camera.js";
import { TgdPainterOverlay } from "../overlay/index.js";
import { TgdPainter } from "../painter.js";
import { TgdPainterState } from "../state/index.js";
import { PainterTipsMask } from "./painters/mask.js";
import { PainterTipsNormal } from "./painters/normal.js";
import { TgdUniformBufferObject } from "./../../uniform/index.js";
import { PainterAxes } from "./painters/axes.js";
import { TgdEvent } from "./../../event/index.js";
import { TgdPainterFramebuffer } from "../framebuffer.js";
export class TgdPainterGizmo extends TgdPainter {
constructor(context, { alignX = +1, alignY = +1, size = 128, margin = 0 } = {}) {
super();
this.context = context;
this.eventTap = new TgdEvent();
this.camera = new TgdCameraPerspective({
name: "Gizmo/Camera",
near: 0.1,
far: 10,
});
this.group = null;
this.overlay = null;
this.contextOffscreen = null;
this.tipsNormal = null;
this.init = (tipsNormal) => {
const { context, size, alignX, alignY, camera, uniformCamera } = this;
this.tipsNormal = tipsNormal;
const group = new TgdPainterState(context, {
depth: "off",
blend: "alpha",
});
this.group = group;
group.removeAll();
const clear = new TgdPainterClear(context, {
color: [0, 0, 0, 0],
depth: 1,
});
const axes = new PainterAxes(context, { uniformCamera, size });
const state = new TgdPainterState(context, {
depth: "less",
blend: "off",
cull: "off",
children: [
new TgdPainterGroupCamera(context, {
camera,
children: [clear, axes, tipsNormal],
}),
],
});
const framebuffer = new TgdPainterFramebuffer(context, {
name: "Framebuffer",
antiAliasing: true,
depthBuffer: true,
textureColor0: this.textureFramebuffer,
children: [state],
fixedSize: true,
});
const overlay = new TgdPainterOverlay(context, {
alignX,
alignY,
scaleY: -1,
width: size,
height: size,
margin: 0,
texture: framebuffer.textureColor0,
});
this.overlay = overlay;
group.add(framebuffer, overlay);
context.paint();
// Offscreen
const offscreenCanvas = new OffscreenCanvas(size, size);
const contextOffscreen = new TgdContext(offscreenCanvas, {
preserveDrawingBuffer: true,
antialias: false,
alpha: false,
camera,
});
contextOffscreen.add(new TgdPainterState(contextOffscreen, {
depth: "less",
blend: "off",
cull: "off",
children: [
new TgdPainterClear(contextOffscreen, {
color: [0, 0, 0, 1],
depth: 1,
}),
new PainterTipsMask(contextOffscreen, { size }),
],
}));
contextOffscreen.camera = camera;
this.contextOffscreen = contextOffscreen;
overlay.eventHover.addListener((evt) => {
const [red] = contextOffscreen.readPixel(evt.current.x, evt.current.y);
const index = Math.floor((4 + red * 8) / 0xff) - 1;
if (tipsNormal.index !== index) {
tipsNormal.index = index;
context.paint();
}
});
overlay.eventMoveStart.addListener(() => true);
overlay.eventMove.addListener(() => true);
overlay.eventMoveEnd.addListener(() => true);
let animations = [];
overlay.eventTap.addListener((evt) => {
const [red] = contextOffscreen.readPixel(evt.x, evt.y);
const index = Math.floor((4 + red * 8) / 0xff) - 1;
if (index < 0 || index > 5)
return;
const { matrix } = context.camera.transfo;
const facing = new TgdVec3(matrix.m02, matrix.m12, matrix.m22);
const axisZ = AXES[index];
this.eventTap.dispatch(axisZ);
if (axisZ.isClose(facing)) {
// Clicking the facing vector is like cliking the opposite vector.
axisZ.scale(-1);
}
if (Math.abs(axisZ.y) > 0.999)
axisZ.scale(-1);
const axisY = Math.abs(axisZ.y) > 0.999 ? new TgdVec3(0, 0, 1) : new TgdVec3(0, 1, 0);
const axisX = TgdVec3.newFrom(axisY).cross(axisZ);
const orientation = TgdQuat.fromMatrix(new TgdMat3(axisX, axisY, axisZ));
context.animCancelArray(animations);
animations = context.animSchedule({
duration: 0.2,
action: tgdActionCreateCameraInterpolation(context.camera, {
orientation,
}),
});
});
};
const uniformCamera = new TgdUniformBufferObject(context, {
uniforms: {
uniModelViewMatrix: "mat4",
uniProjectionMatrix: "mat4",
},
});
this.uniformCamera = uniformCamera;
this._alignX = alignX;
this._alignY = alignY;
this._size = size;
this._margin = margin;
this.name = "Gizmo";
this.textureFramebuffer = new TgdTexture2D(context, {
name: `Gizmo FB (${size}×${size})`,
load: tgdCanvasCreate(size, size),
params: {
minFilter: "NEAREST",
magFilter: "NEAREST",
},
});
PainterTipsNormal.create(context, { size, uniformCamera }).then(this.init);
}
get alignX() {
return this._alignX;
}
set alignX(alignX) {
if (this._alignX === alignX)
return;
this._alignX = alignX;
const { overlay } = this;
if (overlay)
overlay.alignX = alignX;
}
get alignY() {
return this._alignY;
}
set alignY(alignY) {
if (this._alignY === alignY)
return;
this._alignY = alignY;
const { overlay } = this;
if (overlay)
overlay.alignY = alignY;
}
get size() {
return this._size;
}
set size(size) {
if (this._size === size)
return;
this._size = size;
const { overlay } = this;
if (overlay) {
overlay.width = size;
overlay.height = size;
}
this.textureFramebuffer.resize(size, size);
if (this.tipsNormal)
this.tipsNormal.size = size;
this.context?.paint();
}
get margin() {
return this._margin;
}
set margin(margin) {
if (this._margin === margin)
return;
this._margin = margin;
const { overlay } = this;
if (overlay) {
overlay.marginBottom = margin;
overlay.marginTop = margin;
overlay.marginLeft = margin;
overlay.marginRight = margin;
}
}
delete() {
this.group?.delete();
this.uniformCamera.delete();
}
paint(time, delta) {
const { context, contextOffscreen, camera, group, size, uniformCamera } = this;
camera.screenWidth = size;
camera.screenHeight = size;
camera.fitSpaceAtTarget(3, 3);
camera.transfo.orientation = context.camera.transfo.orientation;
uniformCamera.values.uniModelViewMatrix = camera.matrixModelView;
uniformCamera.values.uniProjectionMatrix = camera.matrixProjection;
group?.paint(time, delta);
// Offscreen
contextOffscreen?.paint();
}
get hierarchy() {
const { group } = this;
if (!group)
return {};
return {
[this.name]: [group.hierarchy],
};
}
}
const AXES = [
new TgdVec3(+1, 0, 0),
new TgdVec3(0, +1, 0),
new TgdVec3(0, 0, +1),
new TgdVec3(-1, 0, 0),
new TgdVec3(0, -1, 0),
new TgdVec3(0, 0, -1),
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l6bW8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvcGFpbnRlci9naXptby9naXptby50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDbEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDckQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUUzQyxPQUFPLEVBQUUsa0NBQWtDLEVBQUUsZUFBZSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQ2hGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFFMUMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQzlDLE9BQU8sRUFBNEIsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQ2pFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDMUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQ2pELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUNyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDN0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNyQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQVN0RCxNQUFNLE9BQU8sZUFBZ0IsU0FBUSxVQUFVO0lBbUIzQyxZQUNvQixPQUFtQixFQUNuQyxFQUFFLE1BQU0sR0FB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