@imgui-js-xyz/target-web
Version:
imgui.js for games
905 lines (904 loc) • 37.2 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { imgui } from "@imgui-js-xyz/core";
import { imgui as imgui2 } from "@imgui-js-xyz/core";
class ImGuiCanvas2DRenderer {
constructor(context) {
__publicField(this, "_context");
this._context = context;
}
get width() {
return this._context.canvas.scrollWidth;
}
get height() {
return this._context.canvas.scrollHeight;
}
destroy() {
}
newFrame() {
}
renderDrawData(drawData, fb_width, fb_height) {
const pos = drawData.DisplayPos;
drawData.IterateDrawLists((draw_list) => {
draw_list.IterateDrawCmds((draw_cmd) => {
if (draw_cmd.UserCallback !== null) {
draw_cmd.UserCallback(draw_list, draw_cmd);
} else {
const clip_rect = new imgui.Vec4(draw_cmd.ClipRect.x - pos.x, draw_cmd.ClipRect.y - pos.y, draw_cmd.ClipRect.z - pos.x, draw_cmd.ClipRect.w - pos.y);
if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0 && clip_rect.w >= 0) {
this._executeDrawCmd(draw_list, draw_cmd, clip_rect);
}
}
});
});
}
createFontsTexture(pixels, width, height) {
const imageCanvas = document.createElement("canvas");
imageCanvas.width = width;
imageCanvas.height = height;
const imageCtx = imageCanvas.getContext("2d");
if (imageCtx === null) {
return null;
}
const imageData = imageCtx.getImageData(0, 0, width, height);
imageData.data.set(pixels);
imageCtx.putImageData(imageData, 0, 0);
return imageCanvas;
}
_executeDrawCmd(drawList, drawCmd, clipRect) {
const { _context: ctx } = this;
ctx.save();
ctx.beginPath();
ctx.rect(clipRect.x, clipRect.y, clipRect.z - clipRect.x, clipRect.w - clipRect.y);
ctx.clip();
const idx = imgui.DrawIdxSize === 4 ? new Uint32Array(drawList.IdxBuffer.buffer, drawList.IdxBuffer.byteOffset + drawCmd.IdxOffset * imgui.DrawIdxSize) : new Uint16Array(drawList.IdxBuffer.buffer, drawList.IdxBuffer.byteOffset + drawCmd.IdxOffset * imgui.DrawIdxSize);
for (let i = 0; i < drawCmd.ElemCount; i += 3) {
const i0 = idx[i + 0];
const i1 = idx[i + 1];
const i2 = idx[i + 2];
const v0 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i0 * imgui.DrawVertSize);
const v1 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i1 * imgui.DrawVertSize);
const v2 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i2 * imgui.DrawVertSize);
const i3 = idx[i + 3];
const i4 = idx[i + 4];
const i5 = idx[i + 5];
const v3 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i3 * imgui.DrawVertSize);
const v4 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i4 * imgui.DrawVertSize);
const v5 = new imgui.DrawVert(drawList.VtxBuffer.buffer, drawList.VtxBuffer.byteOffset + i5 * imgui.DrawVertSize);
let quad = true;
let minMin = v0;
let minMax = v0;
let maxMin = v0;
let maxMax = v0;
for (const v of [v1, v2, v3, v4, v5]) {
let found = false;
if (v.pos[0] <= minMin.pos[0] && v.pos[1] <= minMin.pos[1]) {
minMin = v;
found = true;
}
if (v.pos[0] <= minMax.pos[0] && v.pos[1] >= minMax.pos[1]) {
minMax = v;
found = true;
}
if (v.pos[0] >= maxMin.pos[0] && v.pos[1] <= maxMin.pos[1]) {
maxMin = v;
found = true;
}
if (v.pos[0] >= maxMax.pos[0] && v.pos[1] >= maxMax.pos[1]) {
maxMax = v;
found = true;
}
if (!found) {
quad = false;
}
}
quad = quad && minMin.pos[0] === minMax.pos[0];
quad = quad && maxMin.pos[0] === maxMax.pos[0];
quad = quad && minMin.pos[1] === maxMin.pos[1];
quad = quad && minMax.pos[1] === maxMax.pos[1];
if (quad) {
if (minMin.uv[0] === maxMax.uv[0] || minMin.uv[1] === maxMax.uv[1]) {
ctx.beginPath();
ctx.rect(minMin.pos[0], minMin.pos[1], maxMax.pos[0] - minMin.pos[0], maxMax.pos[1] - minMin.pos[1]);
ctx.fillStyle = `rgba(${v0.col[0] >> 0 & 255}, ${v0.col[0] >> 8 & 255}, ${v0.col[0] >> 16 & 255}, ${(v0.col[0] >> 24 & 255) / 255})`;
ctx.fill();
} else {
const image = drawCmd.TextureId;
let width = 0;
let height = 0;
if (image instanceof HTMLVideoElement) {
width = image.videoWidth;
height = image.videoHeight;
} else if (image instanceof VideoFrame) {
width = image.displayWidth;
height = image.displayHeight;
} else if (image instanceof SVGAnimatedLength) {
width = typeof image.width === "number" ? image.width : image.width.animVal.value;
height = typeof image.height === "number" ? image.height : image.height.animVal.value;
} else {
width = image.width;
height = image.height;
}
image && ctx.drawImage(
image,
minMin.uv[0] * width,
minMin.uv[1] * height,
(maxMax.uv[0] - minMin.uv[0]) * width,
(maxMax.uv[1] - minMin.uv[1]) * height,
minMin.pos[0],
minMin.pos[1],
maxMax.pos[0] - minMin.pos[0],
maxMax.pos[1] - minMin.pos[1]
);
}
i += 3;
} else {
ctx.beginPath();
ctx.moveTo(v0.pos[0], v0.pos[1]);
ctx.lineTo(v1.pos[0], v1.pos[1]);
ctx.lineTo(v2.pos[0], v2.pos[1]);
ctx.closePath();
ctx.fillStyle = `rgba(${v0.col[0] >> 0 & 255}, ${v0.col[0] >> 8 & 255}, ${v0.col[0] >> 16 & 255}, ${(v0.col[0] >> 24 & 255) / 255})`;
ctx.fill();
}
}
ctx.restore();
}
}
class ImGuiWebGLRenderer {
constructor(context) {
__publicField(this, "_context");
__publicField(this, "_gl2");
__publicField(this, "_gl_vao");
__publicField(this, "g_ShaderHandle");
__publicField(this, "g_VertHandle");
__publicField(this, "g_FragHandle");
__publicField(this, "g_AttribLocationTex");
__publicField(this, "g_AttribLocationProjMtx");
__publicField(this, "g_AttribLocationPosition", -1);
__publicField(this, "g_AttribLocationUV", -1);
__publicField(this, "g_AttribLocationColor", -1);
__publicField(this, "g_VboHandle");
__publicField(this, "g_ElementsHandle");
__publicField(this, "g_FontTexture", null);
this._context = context;
if (typeof WebGL2RenderingContext !== "undefined" && context instanceof WebGL2RenderingContext) {
this._gl2 = context;
} else {
this._gl_vao = context.getExtension("OES_vertex_array_object") ?? void 0;
}
{
const gl = context;
const vertex_shader = [
"uniform mat4 ProjMtx;",
"attribute vec2 Position;",
"attribute vec2 UV;",
"attribute vec4 Color;",
"varying vec2 Frag_UV;",
"varying vec4 Frag_Color;",
"void main() {",
" Frag_UV = UV;",
" Frag_Color = Color;",
" gl_Position = ProjMtx * vec4(Position.xy,0,1);",
"}"
];
const fragment_shader = [
"precision mediump float;",
// WebGL requires precision specifiers
"uniform sampler2D Texture;",
"varying vec2 Frag_UV;",
"varying vec4 Frag_Color;",
"void main() {",
" gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV);",
"}"
];
const g_ShaderHandle = this.g_ShaderHandle = assertNonNull(gl.createProgram());
const g_VertHandle = this.g_VertHandle = assertNonNull(gl.createShader(gl.VERTEX_SHADER));
const g_FragHandle = this.g_FragHandle = assertNonNull(gl.createShader(gl.FRAGMENT_SHADER));
gl.shaderSource(g_VertHandle, vertex_shader.join("\n"));
gl.shaderSource(g_FragHandle, fragment_shader.join("\n"));
gl.compileShader(g_VertHandle);
gl.compileShader(g_FragHandle);
gl.attachShader(g_ShaderHandle, g_VertHandle);
gl.attachShader(g_ShaderHandle, g_FragHandle);
gl.linkProgram(g_ShaderHandle);
this.g_AttribLocationTex = assertNonNull(gl.getUniformLocation(g_ShaderHandle, "Texture"));
this.g_AttribLocationProjMtx = assertNonNull(gl.getUniformLocation(g_ShaderHandle, "ProjMtx"));
this.g_AttribLocationPosition = gl.getAttribLocation(g_ShaderHandle, "Position") || 0;
this.g_AttribLocationUV = gl.getAttribLocation(g_ShaderHandle, "UV") || 0;
this.g_AttribLocationColor = gl.getAttribLocation(g_ShaderHandle, "Color") || 0;
this.g_VboHandle = assertNonNull(gl.createBuffer());
this.g_ElementsHandle = assertNonNull(gl.createBuffer());
}
}
get width() {
return this._context.drawingBufferWidth;
}
get height() {
return this._context.drawingBufferHeight;
}
destroy() {
const { _context: gl } = this;
if (this.g_FontTexture) {
gl.deleteTexture(this.g_FontTexture);
this.g_FontTexture = null;
}
gl.deleteBuffer(this.g_VboHandle);
gl.deleteBuffer(this.g_ElementsHandle);
this.g_AttribLocationPosition = -1;
this.g_AttribLocationUV = -1;
this.g_AttribLocationColor = -1;
gl.deleteProgram(this.g_ShaderHandle);
gl.deleteShader(this.g_VertHandle);
gl.deleteShader(this.g_FragHandle);
}
newFrame() {
}
renderDrawData(drawData, frameBufferWidth, frameBufferHeight) {
const { _context: gl, _gl2: gl2, _gl_vao: gl_vao } = this;
const last_active_texture = gl.getParameter(gl.ACTIVE_TEXTURE) || null;
const last_program = gl.getParameter(gl.CURRENT_PROGRAM) || null;
const last_texture = gl.getParameter(gl.TEXTURE_BINDING_2D) || null;
const last_array_buffer = gl.getParameter(gl.ARRAY_BUFFER_BINDING) || null;
const last_element_array_buffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING) || null;
const last_vertex_array_object = gl2 && gl2.getParameter(gl2.VERTEX_ARRAY_BINDING) || gl && gl_vao && gl.getParameter(gl_vao.VERTEX_ARRAY_BINDING_OES) || null;
const last_viewport = gl.getParameter(gl.VIEWPORT) || null;
const last_scissor_box = gl.getParameter(gl.SCISSOR_BOX) || null;
const last_blend_src_rgb = gl.getParameter(gl.BLEND_SRC_RGB) || null;
const last_blend_dst_rgb = gl.getParameter(gl.BLEND_DST_RGB) || null;
const last_blend_src_alpha = gl.getParameter(gl.BLEND_SRC_ALPHA) || null;
const last_blend_dst_alpha = gl.getParameter(gl.BLEND_DST_ALPHA) || null;
const last_blend_equation_rgb = gl.getParameter(gl.BLEND_EQUATION_RGB) || null;
const last_blend_equation_alpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA) || null;
const last_enable_blend = gl.getParameter(gl.BLEND) || null;
const last_enable_cull_face = gl.getParameter(gl.CULL_FACE) || null;
const last_enable_depth_test = gl.getParameter(gl.DEPTH_TEST) || null;
const last_enable_scissor_test = gl.getParameter(gl.SCISSOR_TEST) || null;
this._doRenderDrawData(drawData, frameBufferWidth, frameBufferHeight);
gl && last_program !== null && gl.useProgram(last_program);
gl && last_texture !== null && gl.bindTexture(gl.TEXTURE_2D, last_texture);
gl && last_active_texture !== null && gl.activeTexture(last_active_texture);
gl2 && gl2.bindVertexArray(last_vertex_array_object) || gl_vao && gl_vao.bindVertexArrayOES(last_vertex_array_object);
gl && last_array_buffer !== null && gl.bindBuffer(gl.ARRAY_BUFFER, last_array_buffer);
gl && last_element_array_buffer !== null && gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
gl && (last_blend_equation_rgb !== null && last_blend_equation_alpha !== null) && gl.blendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
gl && (last_blend_src_rgb !== null && last_blend_src_alpha !== null && last_blend_dst_rgb !== null && last_blend_dst_alpha !== null) && gl.blendFuncSeparate(last_blend_src_rgb, last_blend_src_alpha, last_blend_dst_rgb, last_blend_dst_alpha);
gl && (last_enable_blend ? gl.enable(gl.BLEND) : gl.disable(gl.BLEND));
gl && (last_enable_cull_face ? gl.enable(gl.CULL_FACE) : gl.disable(gl.CULL_FACE));
gl && (last_enable_depth_test ? gl.enable(gl.DEPTH_TEST) : gl.disable(gl.DEPTH_TEST));
gl && (last_enable_scissor_test ? gl.enable(gl.SCISSOR_TEST) : gl.disable(gl.SCISSOR_TEST));
gl && last_viewport !== null && gl.viewport(last_viewport[0], last_viewport[1], last_viewport[2], last_viewport[3]);
gl && last_scissor_box !== null && gl.scissor(last_scissor_box[0], last_scissor_box[1], last_scissor_box[2], last_scissor_box[3]);
}
createFontsTexture(pixels, width, height) {
const { _context: gl } = this;
const last_texture = gl.getParameter(gl.TEXTURE_BINDING_2D);
try {
const fontTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, fontTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
this.g_FontTexture = fontTexture;
return fontTexture;
} finally {
last_texture && gl.bindTexture(gl.TEXTURE_2D, last_texture);
}
}
_doRenderDrawData(drawData, frameBufferWidth, frameBufferHeight) {
const { _context: gl, _gl2: gl2, _gl_vao: gl_vao } = this;
const vertex_array_object = gl2 ? gl2.createVertexArray() : gl_vao ? gl_vao.createVertexArrayOES() : null;
gl.enable(gl.BLEND);
gl.blendEquation(gl.FUNC_ADD);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.disable(gl.CULL_FACE);
gl.disable(gl.DEPTH_TEST);
gl.enable(gl.SCISSOR_TEST);
gl.viewport(0, 0, frameBufferWidth, frameBufferHeight);
const L = drawData.DisplayPos.x;
const R = drawData.DisplayPos.x + drawData.DisplaySize.x;
const T = drawData.DisplayPos.y;
const B = drawData.DisplayPos.y + drawData.DisplaySize.y;
const ortho_projection = new Float32Array([
2 / (R - L),
0,
0,
0,
0,
2 / (T - B),
0,
0,
0,
0,
-1,
0,
(R + L) / (L - R),
(T + B) / (B - T),
0,
1
]);
gl.useProgram(this.g_ShaderHandle);
gl.uniform1i(this.g_AttribLocationTex, 0);
this.g_AttribLocationProjMtx && gl.uniformMatrix4fv(this.g_AttribLocationProjMtx, false, ortho_projection);
gl2 && gl2.bindVertexArray(vertex_array_object) || gl_vao && gl_vao.bindVertexArrayOES(vertex_array_object);
gl.bindBuffer(gl.ARRAY_BUFFER, this.g_VboHandle);
gl.enableVertexAttribArray(this.g_AttribLocationPosition);
gl.enableVertexAttribArray(this.g_AttribLocationUV);
gl.enableVertexAttribArray(this.g_AttribLocationColor);
gl.vertexAttribPointer(this.g_AttribLocationPosition, 2, gl.FLOAT, false, imgui.DrawVertSize, imgui.DrawVertPosOffset);
gl.vertexAttribPointer(this.g_AttribLocationUV, 2, gl.FLOAT, false, imgui.DrawVertSize, imgui.DrawVertUVOffset);
gl.vertexAttribPointer(this.g_AttribLocationColor, 4, gl.UNSIGNED_BYTE, true, imgui.DrawVertSize, imgui.DrawVertColOffset);
const pos = drawData.DisplayPos;
const idx_buffer_type = gl && (imgui.DrawIdxSize === 4 ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT) || 0;
drawData.IterateDrawLists((draw_list) => {
gl.bindBuffer(gl.ARRAY_BUFFER, this.g_VboHandle);
gl.bufferData(gl.ARRAY_BUFFER, draw_list.VtxBuffer, gl.STREAM_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.g_ElementsHandle);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, draw_list.IdxBuffer, gl.STREAM_DRAW);
draw_list.IterateDrawCmds((draw_cmd) => {
if (draw_cmd.UserCallback !== null) {
draw_cmd.UserCallback(draw_list, draw_cmd);
} else {
const clip_rect = new imgui.Vec4(draw_cmd.ClipRect.x - pos.x, draw_cmd.ClipRect.y - pos.y, draw_cmd.ClipRect.z - pos.x, draw_cmd.ClipRect.w - pos.y);
if (clip_rect.x < frameBufferWidth && clip_rect.y < frameBufferHeight && clip_rect.z >= 0 && clip_rect.w >= 0) {
gl.scissor(clip_rect.x, frameBufferHeight - clip_rect.w, clip_rect.z - clip_rect.x, clip_rect.w - clip_rect.y);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, draw_cmd.TextureId);
gl.drawElements(gl.TRIANGLES, draw_cmd.ElemCount, idx_buffer_type, draw_cmd.IdxOffset * imgui.DrawIdxSize);
}
}
});
});
gl2 && gl2.deleteVertexArray(vertex_array_object) || gl_vao && gl_vao.deleteVertexArrayOES(vertex_array_object);
}
}
function assertNonNull(v) {
if (v === null) {
throw new Error("null assertion failed");
}
return v;
}
var __defProp2 = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = __getOwnPropDesc(target, key);
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = decorator(target, key, result) || result;
if (result) __defProp2(target, key, result);
return result;
};
const mouseButtonMap = [0, 2, 1, 3, 4];
const keyCodeToIndex = {
NumpadEnter: 176
};
const boundMethods = /* @__PURE__ */ new Set();
const bound = (_, propertyKey) => {
boundMethods.add(propertyKey);
};
class ImGuiWebContext {
constructor(value, {
wantEvents = true
} = {}) {
__publicField(this, "_canvas");
__publicField(this, "_renderer");
__publicField(this, "_prevTime", 0);
__publicField(this, "_clipboardText", "");
__publicField(this, "_destroyingController", new AbortController());
this.value = value;
for (const method of boundMethods) {
this[method] = this[method].bind(this);
}
const io = imgui.GetIO();
{
if (typeof window !== "undefined") {
io.BackendPlatformName = "imgui_impl_browser";
imgui.LoadIniSettingsFromMemory(window.localStorage.getItem("imgui.ini") || "");
} else {
io.BackendPlatformName = "imgui_impl_console";
}
if (typeof navigator !== "undefined") {
io.ConfigMacOSXBehaviors = navigator.platform.match(/Mac/) !== null;
}
if (typeof document !== "undefined") {
document.body.addEventListener("copy", this._documentOnCopy);
document.body.addEventListener("cut", this._documentOnCut);
document.body.addEventListener("paste", this._documentOnPaste);
}
io.SetClipboardTextFn = (_userData, text) => {
this._clipboardText = text;
if (typeof navigator !== "undefined" && typeof navigator.clipboard !== "undefined") {
navigator.clipboard.writeText(this._clipboardText).then(() => {
}, (err) => {
console.error(err);
});
}
};
io.GetClipboardTextFn = (_user_data) => {
return this._clipboardText;
};
io.ClipboardUserData = null;
if (typeof window !== "undefined") {
window.addEventListener("gamepadconnected", this._windowOnGamePadConnected);
window.addEventListener("gamepaddisconnected", this._windowOnGamePadDisconnected);
}
}
{
let canvas;
if (value instanceof HTMLCanvasElement || value instanceof OffscreenCanvas) {
canvas = value;
const context = canvas.getContext("webgl2", { alpha: false }) || canvas.getContext("webgl", { alpha: false }) || canvas.getContext("2d");
if (!context) {
throw new Error("This browser can not provide any drawing context.");
}
value = context;
}
if (typeof WebGL2RenderingContext !== "undefined" && value instanceof WebGL2RenderingContext) {
io.BackendRendererName = "imgui_impl_webgl2";
canvas = value.canvas;
this._renderer = new ImGuiWebGLRenderer(value);
} else if (typeof WebGLRenderingContext !== "undefined" && value instanceof WebGLRenderingContext) {
io.BackendRendererName = "imgui_impl_webgl";
canvas = value.canvas;
this._renderer = new ImGuiWebGLRenderer(value);
} else if (typeof CanvasRenderingContext2D !== "undefined" && value instanceof CanvasRenderingContext2D) {
io.BackendRendererName = "imgui_impl_2d";
canvas = value.canvas;
this._renderer = new ImGuiCanvas2DRenderer(value);
} else {
throw new Error("You must provide a valid canvas or rendering context.");
}
this._canvas = canvas;
}
if (wantEvents) {
const { _canvas: canvas } = this;
if (canvas instanceof HTMLCanvasElement) {
canvas.style.touchAction = "none";
const signal = this._destroyingController.signal;
canvas.addEventListener("blur", this._canvasOnBlur, { signal });
canvas.addEventListener("keydown", this._canvasOnKeyDown, { signal });
canvas.addEventListener("keyup", this._canvasOnKeyUp, { signal });
canvas.addEventListener("keypress", this._canvasOnKeyPress, { signal });
canvas.addEventListener("pointermove", this._canvasOnPointerMove, { signal });
canvas.addEventListener("pointerdown", this._canvasOnPointerDown, { signal });
canvas.addEventListener("contextmenu", this._canvasOnContextMenu, { signal });
canvas.addEventListener("pointerup", this._canvasOnPointerUp, { signal });
canvas.addEventListener("wheel", this._canvasOnWheel, { signal });
}
}
io.BackendFlags |= imgui.BackendFlags.HasMouseCursors;
io.KeyMap[imgui.Key.Tab] = 9;
io.KeyMap[imgui.Key.LeftArrow] = 37;
io.KeyMap[imgui.Key.RightArrow] = 39;
io.KeyMap[imgui.Key.UpArrow] = 38;
io.KeyMap[imgui.Key.DownArrow] = 40;
io.KeyMap[imgui.Key.PageUp] = 33;
io.KeyMap[imgui.Key.PageDown] = 34;
io.KeyMap[imgui.Key.Home] = 36;
io.KeyMap[imgui.Key.End] = 35;
io.KeyMap[imgui.Key.Insert] = 45;
io.KeyMap[imgui.Key.Delete] = 46;
io.KeyMap[imgui.Key.Backspace] = 8;
io.KeyMap[imgui.Key.Space] = 32;
io.KeyMap[imgui.Key.Enter] = 13;
io.KeyMap[imgui.Key.Escape] = 27;
io.KeyMap[imgui.Key.KeyPadEnter] = keyCodeToIndex["NumpadEnter"];
io.KeyMap[imgui.Key.A] = 65;
io.KeyMap[imgui.Key.C] = 67;
io.KeyMap[imgui.Key.V] = 86;
io.KeyMap[imgui.Key.X] = 88;
io.KeyMap[imgui.Key.Y] = 89;
io.KeyMap[imgui.Key.Z] = 90;
this._createFontTexture();
}
destroy() {
const io = imgui.GetIO();
io.Fonts.TexID = null;
this._destroyingController.abort();
this._renderer.destroy();
if (typeof window !== "undefined") {
window.removeEventListener("gamepadconnected", this._windowOnGamePadConnected);
window.removeEventListener("gamepaddisconnected", this._windowOnGamePadDisconnected);
}
if (typeof document !== "undefined") {
document.body.removeEventListener("copy", this._documentOnCopy);
document.body.removeEventListener("cut", this._documentOnCut);
document.body.removeEventListener("paste", this._documentOnPaste);
}
}
newFrame(time) {
const io = imgui.GetIO();
if (io.WantSaveIniSettings) {
io.WantSaveIniSettings = false;
if (typeof window !== "undefined") {
window.localStorage.setItem("imgui.ini", imgui.SaveIniSettingsToMemory());
}
}
let canvasWidth = 0;
let canvasHeight = 0;
if (this._canvas instanceof HTMLCanvasElement) {
canvasWidth = this._canvas.width;
canvasHeight = this._canvas.height;
} else {
canvasWidth = this._canvas.width;
canvasHeight = this._canvas.height;
}
const w = canvasWidth || 640;
const h = canvasHeight || 480;
const display_w = this._renderer.width || w;
const display_h = this._renderer.height || h;
io.DisplaySize.x = w;
io.DisplaySize.y = h;
io.DisplayFramebufferScale.x = w > 0 ? display_w / w : 0;
io.DisplayFramebufferScale.y = h > 0 ? display_h / h : 0;
const dt = time - this._prevTime;
this._prevTime = time;
io.DeltaTime = dt / 1e3;
if (io.WantSetMousePos) {
console.log("TODO: MousePos", io.MousePos.x, io.MousePos.y);
}
if (typeof document !== "undefined") {
if (io.MouseDrawCursor) {
document.body.style.cursor = "none";
} else {
switch (imgui.GetMouseCursor()) {
case imgui.MouseCursor.None:
document.body.style.cursor = "none";
break;
default:
case imgui.MouseCursor.Arrow:
document.body.style.cursor = "default";
break;
case imgui.MouseCursor.TextInput:
document.body.style.cursor = "text";
break;
// When hovering over InputText, etc.
case imgui.MouseCursor.ResizeAll:
document.body.style.cursor = "all-scroll";
break;
// Unused
case imgui.MouseCursor.ResizeNS:
document.body.style.cursor = "ns-resize";
break;
// When hovering over an horizontal border
case imgui.MouseCursor.ResizeEW:
document.body.style.cursor = "ew-resize";
break;
// When hovering over a vertical border or a column
case imgui.MouseCursor.ResizeNESW:
document.body.style.cursor = "nesw-resize";
break;
// When hovering over the bottom-left corner of a window
case imgui.MouseCursor.ResizeNWSE:
document.body.style.cursor = "nwse-resize";
break;
// When hovering over the bottom-right corner of a window
case imgui.MouseCursor.Hand:
document.body.style.cursor = "move";
break;
case imgui.MouseCursor.NotAllowed:
document.body.style.cursor = "not-allowed";
break;
}
}
}
for (let i = 0; i < io.NavInputs.length; ++i) {
}
if (io.ConfigFlags & imgui.ConfigFlags.NavEnableGamepad) {
const gamepads = typeof navigator !== "undefined" && typeof navigator.getGamepads === "function" ? navigator.getGamepads() : [];
for (let i = 0; i < gamepads.length; ++i) {
const gamepad = gamepads[i];
if (!gamepad) {
continue;
}
io.BackendFlags |= imgui.BackendFlags.HasGamepad;
const buttons_count = gamepad.buttons.length;
const axes_count = gamepad.axes.length;
const MAP_BUTTON = (NAV_NO, BUTTON_NO) => {
if (!gamepad) {
return;
}
if (buttons_count > BUTTON_NO && gamepad.buttons[BUTTON_NO].pressed)
io.NavInputs[NAV_NO] = 1;
};
const MAP_ANALOG = (NAV_NO, AXIS_NO, V0, V1) => {
if (!gamepad) {
return;
}
let v = axes_count > AXIS_NO ? gamepad.axes[AXIS_NO] : V0;
v = (v - V0) / (V1 - V0);
if (v > 1) v = 1;
if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v;
};
const match = gamepad.id.match(/^([0-9a-f]{4})-([0-9a-f]{4})-.*$/);
const match_chrome = gamepad.id.match(/^.*\(.*Vendor: ([0-9a-f]{4}) Product: ([0-9a-f]{4})\).*$/);
const vendor = match && match[1] || match_chrome && match_chrome[1] || "0000";
const product = match && match[2] || match_chrome && match_chrome[2] || "0000";
switch (vendor + product) {
case "046dc216":
MAP_BUTTON(imgui.NavInput.Activate, 1);
MAP_BUTTON(imgui.NavInput.Cancel, 2);
MAP_BUTTON(imgui.NavInput.Menu, 0);
MAP_BUTTON(imgui.NavInput.Input, 3);
MAP_ANALOG(imgui.NavInput.DpadLeft, 4, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.DpadRight, 4, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.DpadUp, 5, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.DpadDown, 5, 0.3, 0.9);
MAP_BUTTON(imgui.NavInput.FocusPrev, 4);
MAP_BUTTON(imgui.NavInput.FocusNext, 5);
MAP_BUTTON(imgui.NavInput.TweakSlow, 6);
MAP_BUTTON(imgui.NavInput.TweakFast, 7);
MAP_ANALOG(imgui.NavInput.LStickLeft, 0, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickRight, 0, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.LStickUp, 1, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickDown, 1, 0.3, 0.9);
break;
case "046dc21d":
MAP_BUTTON(imgui.NavInput.Activate, 0);
MAP_BUTTON(imgui.NavInput.Cancel, 1);
MAP_BUTTON(imgui.NavInput.Menu, 2);
MAP_BUTTON(imgui.NavInput.Input, 3);
MAP_BUTTON(imgui.NavInput.DpadLeft, 14);
MAP_BUTTON(imgui.NavInput.DpadRight, 15);
MAP_BUTTON(imgui.NavInput.DpadUp, 12);
MAP_BUTTON(imgui.NavInput.DpadDown, 13);
MAP_BUTTON(imgui.NavInput.FocusPrev, 4);
MAP_BUTTON(imgui.NavInput.FocusNext, 5);
MAP_ANALOG(imgui.NavInput.TweakSlow, 6, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.TweakFast, 7, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.LStickLeft, 0, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickRight, 0, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.LStickUp, 1, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickDown, 1, 0.3, 0.9);
break;
case "2dc86001":
// 8Bitdo SN30 Pro 8Bitdo SN30 Pro (Vendor: 2dc8 Product: 6001)
case "2dc86101":
MAP_BUTTON(imgui.NavInput.Activate, 1);
MAP_BUTTON(imgui.NavInput.Cancel, 0);
MAP_BUTTON(imgui.NavInput.Menu, 4);
MAP_BUTTON(imgui.NavInput.Input, 3);
MAP_ANALOG(imgui.NavInput.DpadLeft, 6, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.DpadRight, 6, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.DpadUp, 7, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.DpadDown, 7, 0.3, 0.9);
MAP_BUTTON(imgui.NavInput.FocusPrev, 6);
MAP_BUTTON(imgui.NavInput.FocusNext, 7);
MAP_BUTTON(imgui.NavInput.TweakSlow, 8);
MAP_BUTTON(imgui.NavInput.TweakFast, 9);
MAP_ANALOG(imgui.NavInput.LStickLeft, 0, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickRight, 0, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.LStickUp, 1, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickDown, 1, 0.3, 0.9);
break;
default:
MAP_BUTTON(imgui.NavInput.Activate, 0);
MAP_BUTTON(imgui.NavInput.Cancel, 1);
MAP_BUTTON(imgui.NavInput.Menu, 2);
MAP_BUTTON(imgui.NavInput.Input, 3);
MAP_BUTTON(imgui.NavInput.DpadLeft, 14);
MAP_BUTTON(imgui.NavInput.DpadRight, 15);
MAP_BUTTON(imgui.NavInput.DpadUp, 12);
MAP_BUTTON(imgui.NavInput.DpadDown, 13);
MAP_BUTTON(imgui.NavInput.FocusPrev, 4);
MAP_BUTTON(imgui.NavInput.FocusNext, 5);
MAP_BUTTON(imgui.NavInput.TweakSlow, 6);
MAP_BUTTON(imgui.NavInput.TweakFast, 7);
MAP_ANALOG(imgui.NavInput.LStickLeft, 0, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickRight, 0, 0.3, 0.9);
MAP_ANALOG(imgui.NavInput.LStickUp, 1, -0.3, -0.9);
MAP_ANALOG(imgui.NavInput.LStickDown, 1, 0.3, 0.9);
break;
}
}
}
imgui.NewFrame();
}
endFrame() {
imgui.EndFrame();
}
render() {
imgui.Render();
const drawData = imgui.GetDrawData();
if (drawData === null) {
throw new Error(`Empty draw data.`);
}
this._doRenderDrawData(drawData);
}
_doRenderDrawData(drawData) {
const io = imgui.GetIO();
const fb_width = io.DisplaySize.x * io.DisplayFramebufferScale.x;
const fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
if (fb_width === 0 || fb_height === 0) {
return;
}
drawData.ScaleClipRects(io.DisplayFramebufferScale);
this._renderer.renderDrawData(drawData, fb_width, fb_height);
}
_createFontTexture() {
const io = imgui.GetIO();
const { width, height, pixels } = io.Fonts.GetTexDataAsRGBA32();
const texture = this._renderer.createFontsTexture(pixels, width, height);
io.Fonts.SetTexID(texture);
}
_documentOnCopy(event) {
if (event.clipboardData) {
event.clipboardData.setData("text/plain", this._clipboardText);
}
event.preventDefault();
}
_documentOnCut(event) {
if (event.clipboardData) {
event.clipboardData.setData("text/plain", this._clipboardText);
}
event.preventDefault();
}
_documentOnPaste(event) {
if (event.clipboardData) {
this._clipboardText = event.clipboardData.getData("text/plain");
}
event.preventDefault();
}
_windowOnGamePadConnected(event) {
console.log(
"Gamepad connected at index %d: %s. %d buttons, %d axes.",
event.gamepad.index,
event.gamepad.id,
event.gamepad.buttons.length,
event.gamepad.axes.length
);
}
_windowOnGamePadDisconnected(event) {
console.log(
"Gamepad disconnected at index %d: %s.",
event.gamepad.index,
event.gamepad.id
);
}
_canvasOnBlur(_event) {
const io = imgui.GetIO();
io.KeyCtrl = false;
io.KeyShift = false;
io.KeyAlt = false;
io.KeySuper = false;
for (let i = 0; i < io.KeysDown.length; ++i) {
io.KeysDown[i] = false;
}
for (let i = 0; i < io.MouseDown.length; ++i) {
io.MouseDown[i] = false;
}
}
_canvasOnKeyDown(event) {
const io = imgui.GetIO();
io.KeyCtrl = event.ctrlKey;
io.KeyShift = event.shiftKey;
io.KeyAlt = event.altKey;
io.KeySuper = event.metaKey;
const key_index = keyCodeToIndex[event.code] || event.keyCode;
imgui.ASSERT(key_index >= 0 && key_index < imgui.ARRAYSIZE(io.KeysDown));
io.KeysDown[key_index] = true;
if (
/* io.WantCaptureKeyboard || */
event.key === "Tab"
) {
event.preventDefault();
}
}
_canvasOnKeyUp(event) {
const io = imgui.GetIO();
io.KeyCtrl = event.ctrlKey;
io.KeyShift = event.shiftKey;
io.KeyAlt = event.altKey;
io.KeySuper = event.metaKey;
const key_index = keyCodeToIndex[event.code] || event.keyCode;
imgui.ASSERT(key_index >= 0 && key_index < imgui.ARRAYSIZE(io.KeysDown));
io.KeysDown[key_index] = false;
if (io.WantCaptureKeyboard) {
event.preventDefault();
}
}
_canvasOnKeyPress(event) {
const io = imgui.GetIO();
io.AddInputCharacter(event.charCode);
if (io.WantCaptureKeyboard) {
event.preventDefault();
}
}
_canvasOnPointerMove(event) {
const io = imgui.GetIO();
io.MousePos.x = event.offsetX;
io.MousePos.y = event.offsetY;
if (io.WantCaptureMouse) {
event.preventDefault();
}
}
_canvasOnPointerDown(event) {
const io = imgui.GetIO();
io.MousePos.x = event.offsetX;
io.MousePos.y = event.offsetY;
io.MouseDown[mouseButtonMap[event.button]] = true;
if (io.WantCaptureMouse) {
event.preventDefault();
}
}
_canvasOnContextMenu(event) {
const io = imgui.GetIO();
if (io.WantCaptureMouse) {
event.preventDefault();
}
}
_canvasOnPointerUp(event) {
const io = imgui.GetIO();
io.MouseDown[mouseButtonMap[event.button]] = false;
if (io.WantCaptureMouse) {
event.preventDefault();
}
}
_canvasOnWheel(event) {
const io = imgui.GetIO();
let scale = 1;
switch (event.deltaMode) {
case event.DOM_DELTA_PIXEL:
scale = 0.01;
break;
case event.DOM_DELTA_LINE:
scale = 0.2;
break;
case event.DOM_DELTA_PAGE:
scale = 1;
break;
}
io.MouseWheelH = event.deltaX * scale;
io.MouseWheel = -event.deltaY * scale;
if (io.WantCaptureMouse) {
event.preventDefault();
}
}
}
__decorateClass([
bound
], ImGuiWebContext.prototype, "_documentOnCopy");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_documentOnCut");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_documentOnPaste");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_windowOnGamePadConnected");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_windowOnGamePadDisconnected");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnBlur");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnKeyDown");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnKeyUp");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnKeyPress");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnPointerMove");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnPointerDown");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnContextMenu");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnPointerUp");
__decorateClass([
bound
], ImGuiWebContext.prototype, "_canvasOnWheel");
export {
ImGuiWebContext,
imgui2 as imgui
};