UNPKG

@tolokoban/tgd

Version:

ToloGameDev library for WebGL2

246 lines 20.7 kB
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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