Update worldEdit.js

This commit is contained in:
redbirdly 2025-08-11 14:28:26 +08:00 committed by GitHub
parent 2afcb6d97c
commit 5c38ac7c38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 360 additions and 340 deletions

View File

@ -4,390 +4,410 @@
// Constants // Constants
const w_accentColor = "#7cff62"; const w_accentColor = "#7cff62";
const w_style = { const w_style = {
strokeWidth: 1, strokeWidth: 1,
selectFill: "#57b64530", selectFill: "#57b64530",
selectStroke: w_accentColor, selectStroke: w_accentColor,
selectDash: true, selectDash: true,
pasteFill: "#00FFFF40", pasteFill: "#00FFFF40",
pasteStroke: "#00FFFF" pasteStroke: "#00FFFF"
}; };
// Global variables // Global variables
let worldEditElements = {}; let worldEditElements = {};
let pastePreviewCanvas; let pastePreviewCanvas;
let w_state = { let w_state = {
firstSelectionPos: { x: 0, y: 0 }, firstSelectionPos: {x: 0, y: 0},
selection: null, selection: null,
clipboard: null, clipboard: null,
prevNonWorldEditElement: "unknown" prevNonWorldEditElement: "unknown"
}; };
// Define settings // Define settings
let w_settingsTab; let w_settingsTab;
let w_deselectOnResetSetting; let w_deselectOnResetSetting;
dependOn("betterSettings.js", () => { dependOn("betterSettings.js", () => {
w_settingsTab = new SettingsTab("WorldEdit"); w_settingsTab = new SettingsTab("WorldEdit");
w_deselectOnResetSetting = new Setting("Deselect on reset", "deselectOnReset", settingType.BOOLEAN, false, true); w_deselectOnResetSetting = new Setting("Deselect on reset", "deselectOnReset", settingType.BOOLEAN, false, true);
w_settingsTab.registerSettings("Selection", w_deselectOnResetSetting); w_settingsTab.registerSettings("Selection", w_deselectOnResetSetting);
settingsManager.registerTab(w_settingsTab); settingsManager.registerTab(w_settingsTab);
}, true); }, true);
// Classes // Classes
class Rect { class Rect {
constructor(x, y, w, h) { constructor(x, y, w, h) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.w = w; this.w = w;
this.h = h; this.h = h;
} }
static fromCorners(start, end) {
return new Rect(start.x, start.y, end.x - start.x, end.y - start.y); static fromCorners(start, end) {
} return new Rect(start.x, start.y, end.x - start.x, end.y - start.y);
static fromCornersXYXY(x, y, x2, y2) { }
return new Rect(x, y, x2 - x, y2 - y);
} static fromCornersXYXY(x, y, x2, y2) {
static fromGrid(grid, origin = { x: 0, y: 0 }) { return new Rect(x, y, x2 - x, y2 - y);
return new Rect(origin.x, origin.y, grid[0].length, grid.length); }
}
get area() { static fromGrid(grid, origin = {x: 0, y: 0}) {
return this.w * this.h; return new Rect(origin.x, origin.y, grid[0].length, grid.length);
} }
get x2() {
return this.x + this.w; get area() {
} return this.w * this.h;
get y2() { }
return this.y + this.h;
} get x2() {
set x2(val) { return this.x + this.w;
this.w = val - this.x; }
}
set y2(val) { get y2() {
this.h = val - this.y; return this.y + this.h;
} }
copy() {
return new Rect(this.x, this.y, this.w, this.h); set x2(val) {
} this.w = val - this.x;
normalized() { }
return Rect.fromCornersXYXY(Math.min(this.x, this.x2), Math.min(this.y, this.y2), Math.max(this.x, this.x2), Math.max(this.y, this.y2));
} set y2(val) {
this.h = val - this.y;
}
copy() {
return new Rect(this.x, this.y, this.w, this.h);
}
normalized() {
return Rect.fromCornersXYXY(Math.min(this.x, this.x2), Math.min(this.y, this.y2), Math.max(this.x, this.x2), Math.max(this.y, this.y2));
}
} }
// Functions // Functions
function isPointInWorld(point) { function isPointInWorld(point) {
return point.x >= 0 && point.x <= width && point.y >= 0 && point.y <= height; return point.x >= 0 && point.x <= width && point.y >= 0 && point.y <= height;
} }
function limitPointToWorld(point) { function limitPointToWorld(point) {
return { return {
x: Math.max(0, Math.min(point.x, width)), x: Math.max(0, Math.min(point.x, width)),
y: Math.max(0, Math.min(point.y, height)) y: Math.max(0, Math.min(point.y, height))
}; };
} }
function mousePosToWorldPos(pos) { function mousePosToWorldPos(pos) {
const rect = canvas.getBoundingClientRect(); const rect = canvas.getBoundingClientRect();
let x = pos.x - rect.left; let x = pos.x - rect.left;
let y = pos.y - rect.top; let y = pos.y - rect.top;
x = Math.floor((x / canvas.clientWidth) * (width + 1)); x = Math.floor((x / canvas.clientWidth) * (width + 1));
y = Math.floor((y / canvas.clientHeight) * (height + 1)); y = Math.floor((y / canvas.clientHeight) * (height + 1));
return { x: x, y: y }; return {x: x, y: y};
} }
function updatePastePreviewCanvas() { function updatePastePreviewCanvas() {
const clipboard = w_state.clipboard; const clipboard = w_state.clipboard;
if (!clipboard) if (!clipboard)
return; return;
const clipboardRect = Rect.fromGrid(clipboard); const clipboardRect = Rect.fromGrid(clipboard);
// Create canvas // Create canvas
pastePreviewCanvas = new OffscreenCanvas(clipboardRect.w, clipboardRect.h); pastePreviewCanvas = new OffscreenCanvas(clipboardRect.w, clipboardRect.h);
const pastePreviewCtx = pastePreviewCanvas.getContext("2d"); const pastePreviewCtx = pastePreviewCanvas.getContext("2d");
const imageData = pastePreviewCtx.createImageData(clipboardRect.w, clipboardRect.h); const imageData = pastePreviewCtx.createImageData(clipboardRect.w, clipboardRect.h);
const buffer = new Uint32Array(imageData.data.buffer); const buffer = new Uint32Array(imageData.data.buffer);
buffer.fill(0x00000000); buffer.fill(0x00000000);
for (let y = 0; y < clipboardRect.h; y++) { for (let y = 0; y < clipboardRect.h; y++) {
for (let x = 0; x < clipboardRect.w; x++) { for (let x = 0; x < clipboardRect.w; x++) {
if (clipboard[y][x]) if (clipboard[y][x])
buffer[y * clipboardRect.w + x] = 0x44FFFF00; buffer[y * clipboardRect.w + x] = 0x44FFFF00;
} }
} }
pastePreviewCtx.putImageData(imageData, 0, 0); pastePreviewCtx.putImageData(imageData, 0, 0);
} }
function renderSelection(ctx) { function renderSelection(ctx) {
const selection = w_state.selection; const selection = w_state.selection;
if (!selection) if (!selection)
return; return;
const isSelecting = (mouseIsDown && const isSelecting = (mouseIsDown &&
(mouseType !== "middle" && mouseType !== "right") && (mouseType !== "middle" && mouseType !== "right") &&
currentElement === "w_select"); currentElement === "w_select");
ctx.globalAlpha = 1.0; ctx.globalAlpha = 1.0;
// Fill // Fill
if (!isSelecting) { if (!isSelecting) {
ctx.fillStyle = w_style.selectFill; ctx.fillStyle = w_style.selectFill;
ctx.fillRect(selection.x * pixelSize, selection.y * pixelSize, selection.w * pixelSize, selection.h * pixelSize); ctx.fillRect(selection.x * pixelSize, selection.y * pixelSize, selection.w * pixelSize, selection.h * pixelSize);
} }
// Dash if selection is big enough // Dash if selection is big enough
if (w_style.selectDash && selection.w >= 2 && selection.h >= 2) if (w_style.selectDash && selection.w >= 2 && selection.h >= 2)
ctx.setLineDash([pixelSize, pixelSize]); ctx.setLineDash([pixelSize, pixelSize]);
// Stroke // Stroke
ctx.strokeStyle = w_style.selectStroke; ctx.strokeStyle = w_style.selectStroke;
ctx.lineWidth = w_style.strokeWidth; ctx.lineWidth = w_style.strokeWidth;
ctx.strokeRect(selection.x * pixelSize, selection.y * pixelSize, selection.w * pixelSize, selection.h * pixelSize); ctx.strokeRect(selection.x * pixelSize, selection.y * pixelSize, selection.w * pixelSize, selection.h * pixelSize);
ctx.setLineDash([]); ctx.setLineDash([]);
} }
function renderPastePreview(ctx) { function renderPastePreview(ctx) {
if (currentElement !== 'w_paste') if (currentElement !== 'w_paste')
return; return;
const clipboard = w_state.clipboard; const clipboard = w_state.clipboard;
if (!clipboard) if (!clipboard)
return; return;
const clipboardRect = Rect.fromGrid(clipboard, mousePos); const clipboardRect = Rect.fromGrid(clipboard, mousePos);
ctx.globalAlpha = 1.0; ctx.globalAlpha = 1.0;
// Fill // Fill
ctx.fillStyle = w_style.pasteFill; ctx.fillStyle = w_style.pasteFill;
ctx.fillRect(clipboardRect.x * pixelSize, clipboardRect.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize); ctx.fillRect(clipboardRect.x * pixelSize, clipboardRect.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize);
// Stroke // Stroke
ctx.strokeStyle = w_style.pasteStroke; ctx.strokeStyle = w_style.pasteStroke;
ctx.lineWidth = w_style.strokeWidth; ctx.lineWidth = w_style.strokeWidth;
ctx.strokeRect(clipboardRect.x * pixelSize, clipboardRect.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize); ctx.strokeRect(clipboardRect.x * pixelSize, clipboardRect.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize);
if (pastePreviewCanvas) if (pastePreviewCanvas)
ctx.drawImage(pastePreviewCanvas, mousePos.x * pixelSize, mousePos.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize); ctx.drawImage(pastePreviewCanvas, mousePos.x * pixelSize, mousePos.y * pixelSize, clipboardRect.w * pixelSize, clipboardRect.h * pixelSize);
} }
function addWorldEditKeybinds() { function addWorldEditKeybinds() {
keybinds.w = () => { keybinds.w = () => {
selectCategory("worldEdit"); selectCategory("worldEdit");
}; };
keybinds.d = () => { keybinds.d = () => {
elements.w_deselect.rawOnSelect(); elements.w_deselect.rawOnSelect();
}; };
keybinds.a = () => { keybinds.a = () => {
elements.w_select_all.rawOnSelect(); elements.w_select_all.rawOnSelect();
}; };
keybinds.s = () => { keybinds.s = () => {
selectElement("w_select"); selectElement("w_select");
selectCategory("worldEdit"); selectCategory("worldEdit");
}; };
keybinds.c = () => { keybinds.c = () => {
elements.w_copy.rawOnSelect(); elements.w_copy.rawOnSelect();
}; };
keybinds.v = () => { keybinds.v = () => {
selectElement("w_paste"); selectElement("w_paste");
selectCategory("worldEdit"); selectCategory("worldEdit");
}; };
keybinds.x = () => { keybinds.x = () => {
elements.w_cut.rawOnSelect(); elements.w_cut.rawOnSelect();
}; };
keybinds.Delete = () => { keybinds.Delete = () => {
elements.w_delete.rawOnSelect(); elements.w_delete.rawOnSelect();
}; };
keybinds.g = () => { keybinds.g = () => {
elements.w_fill.rawOnSelect(); elements.w_fill.rawOnSelect();
}; };
} }
function modifySelectElement() { function modifySelectElement() {
const originalSelectElement = selectElement; const originalSelectElement = selectElement;
// @ts-ignore // @ts-ignore
selectElement = (element) => { selectElement = (element) => {
// Keep track of last non-worldEdit element // Keep track of last non-worldEdit element
if (!worldEditElements.hasOwnProperty(currentElement)) if (!worldEditElements.hasOwnProperty(currentElement))
w_state.prevNonWorldEditElement = currentElement; w_state.prevNonWorldEditElement = currentElement;
originalSelectElement(element); originalSelectElement(element);
}; };
} }
function addWorldEditElements(elementsToAdd) { function addWorldEditElements(elementsToAdd) {
for (const elementName in elementsToAdd) { for (const elementName in elementsToAdd) {
const element = elementsToAdd[elementName]; const element = elementsToAdd[elementName];
elements[elementName] = element; elements[elementName] = element;
// Apply base settings for every worldEdit element // Apply base settings for every worldEdit element
element.category ?? (element.category = "worldEdit"); element.category ?? (element.category = "worldEdit");
element.color ?? (element.color = w_accentColor); element.color ?? (element.color = w_accentColor);
element.tool ?? (element.tool = () => null); element.tool ?? (element.tool = () => null);
element.maxSize ?? (element.maxSize = 1); element.maxSize ?? (element.maxSize = 1);
// Some elements will auto-deselect themselves // Some elements will auto-deselect themselves
if (!element.shouldStaySelected) { if (!element.shouldStaySelected) {
const originalOnSelect = element.onSelect; const originalOnSelect = element.onSelect;
element.rawOnSelect = originalOnSelect; element.rawOnSelect = originalOnSelect;
element.onSelect = function (...args) { element.onSelect = function (...args) {
originalOnSelect(...args); originalOnSelect(...args);
selectElement(w_state.prevNonWorldEditElement); selectElement(w_state.prevNonWorldEditElement);
}; };
} }
} }
} }
// Elements // Elements
worldEditElements.w_deselect = { worldEditElements.w_deselect = {
onSelect: function () { onSelect: function () {
w_state.selection = null; w_state.selection = null;
if (pixelTicks != 0) if (pixelTicks != 0)
logMessage("Deselected area."); logMessage("Deselected area.");
} }
}; };
worldEditElements.w_select_all = { worldEditElements.w_select_all = {
onSelect: function () { onSelect: function () {
w_state.selection = new Rect(0, 0, width + 1, height + 1); w_state.selection = new Rect(0, 0, width + 1, height + 1);
logMessage("Selected everything."); logMessage("Selected everything.");
} }
}; };
worldEditElements.w_select = { worldEditElements.w_select = {
onPointerDown: function (e) { onPointerDown: function (e) {
const pos = mousePosToWorldPos({ x: e.clientX, y: e.clientY }); const pos = mousePosToWorldPos({x: e.clientX, y: e.clientY});
if (showingMenu) if (showingMenu)
return; return;
if (!isPointInWorld(pos)) if (!isPointInWorld(pos))
return; return;
if (mouseType === "middle" || mouseType === "right") if (mouseType === "middle" || mouseType === "right")
return; return;
w_state.firstSelectionPos = pos; w_state.firstSelectionPos = pos;
}, },
onPointerMove: function (e) { onPointerMove: function (e) {
const pos = mousePosToWorldPos({ x: e.clientX, y: e.clientY }); const pos = mousePosToWorldPos({x: e.clientX, y: e.clientY});
if (!mouseIsDown) if (!mouseIsDown)
return; return;
if (showingMenu) if (showingMenu)
return; return;
if (mouseType === "middle" || mouseType === "right") if (mouseType === "middle" || mouseType === "right")
return; return;
if (currentElement !== "w_select") if (currentElement !== "w_select")
return; return;
const rect = Rect.fromCorners(w_state.firstSelectionPos, limitPointToWorld(pos)).normalized(); const rect = Rect.fromCorners(w_state.firstSelectionPos, limitPointToWorld(pos)).normalized();
rect.x2 += 1; rect.x2 += 1;
rect.y2 += 1; rect.y2 += 1;
w_state.selection = rect; w_state.selection = rect;
}, },
shouldStaySelected: true shouldStaySelected: true
}; };
worldEditElements.w_copy = { worldEditElements.w_copy = {
onSelect: function () { onSelect: function () {
const selection = w_state.selection; const selection = w_state.selection;
if (!selection) { if (!selection) {
logMessage("Error: Nothing is selected."); logMessage("Error: Nothing is selected.");
return; return;
} }
// Copy pixels // Copy pixels
w_state.clipboard = []; w_state.clipboard = [];
let clipboard = w_state.clipboard; let clipboard = w_state.clipboard;
for (let y = selection.y; y < selection.y2; y++) { for (let y = selection.y; y < selection.y2; y++) {
const row = []; const row = [];
for (let x = selection.x; x < selection.x2; x++) { for (let x = selection.x; x < selection.x2; x++) {
row.push(structuredClone(pixelMap[x][y])); row.push(structuredClone(pixelMap[x][y]));
} }
clipboard.push(row); clipboard.push(row);
} }
updatePastePreviewCanvas(); updatePastePreviewCanvas();
logMessage(`Copied ${selection.w}x${selection.h}=${selection.area} pixel area.`); logMessage(`Copied ${selection.w}x${selection.h}=${selection.area} pixel area.`);
} }
}; };
worldEditElements.w_paste = { worldEditElements.w_paste = {
onPointerDown: function () { onPointerDown: function () {
if (showingMenu) if (showingMenu)
return; return;
if (!isPointInWorld(mousePos)) if (!isPointInWorld(mousePos))
return; return;
if (mouseType === "middle" || mouseType === "right") if (mouseType === "middle" || mouseType === "right")
return; return;
const clipboard = w_state.clipboard; const clipboard = w_state.clipboard;
if (!clipboard) { if (!clipboard) {
logMessage("Error: Nothing in clipboard."); logMessage("Error: Nothing in clipboard.");
return; return;
} }
const pasteOrigin = mousePos; const pasteOrigin = mousePos;
// Paste pixels // Paste pixels
for (let y = 0; y < clipboard.length; y++) { for (let y = 0; y < clipboard.length; y++) {
for (let x = 0; x < clipboard[0].length; x++) { for (let x = 0; x < clipboard[0].length; x++) {
const clipboardPixel = clipboard[y][x]; const clipboardPixel = clipboard[y][x];
const dest = { x: pasteOrigin.x + x, y: pasteOrigin.y + y }; const dest = {x: pasteOrigin.x + x, y: pasteOrigin.y + y};
if (!isPointInWorld(dest)) if (!isPointInWorld(dest))
continue; // Skip if out of bounds continue; // Skip if out of bounds
if (pixelMap[dest.x][dest.y]) if (pixelMap[dest.x][dest.y])
continue; // Skip if pixel already there continue; // Skip if pixel already there
if (!clipboardPixel) if (!clipboardPixel)
continue; // Skip if new pixel is air continue; // Skip if new pixel is air
// Create pixel // Create pixel
const newPixel = structuredClone(clipboardPixel); const newPixel = structuredClone(clipboardPixel);
Object.assign(newPixel, dest); Object.assign(newPixel, dest);
pixelMap[dest.x][dest.y] = newPixel; pixelMap[dest.x][dest.y] = newPixel;
currentPixels.push(newPixel); currentPixels.push(newPixel);
} }
} }
const area = Rect.fromGrid(clipboard).area; const area = Rect.fromGrid(clipboard).area;
logMessage(`Pasted ${clipboard[0].length}x${clipboard.length}=${area} pixel area.`); logMessage(`Pasted ${clipboard[0].length}x${clipboard.length}=${area} pixel area.`);
}, },
shouldStaySelected: true shouldStaySelected: true
}; };
worldEditElements.w_cut = { worldEditElements.w_cut = {
onSelect: function () { onSelect: function () {
const selection = w_state.selection; const selection = w_state.selection;
if (!selection) { if (!selection) {
logMessage("Error: Nothing is selected."); logMessage("Error: Nothing is selected.");
return; return;
} }
// Cut pixels // Cut pixels
w_state.clipboard = []; w_state.clipboard = [];
let clipboard = w_state.clipboard; let clipboard = w_state.clipboard;
for (let y = selection.y; y < selection.y2; y++) { for (let y = selection.y; y < selection.y2; y++) {
const row = []; const row = [];
for (let x = selection.x; x < selection.x2; x++) { for (let x = selection.x; x < selection.x2; x++) {
row.push(structuredClone(pixelMap[x][y])); row.push(structuredClone(pixelMap[x][y]));
const pixel = pixelMap[x][y]; const pixel = pixelMap[x][y];
const index = currentPixels.indexOf(pixel); const index = currentPixels.indexOf(pixel);
if (index !== -1) if (index !== -1)
currentPixels.splice(index, 1); currentPixels.splice(index, 1);
if (pixel) { if (pixel) {
delete pixelMap[x][y]; delete pixelMap[x][y];
} }
} }
clipboard.push(row); clipboard.push(row);
} }
updatePastePreviewCanvas(); updatePastePreviewCanvas();
logMessage(`Cut ${selection.w}x${selection.h}=${selection.area} pixel area.`); logMessage(`Cut ${selection.w}x${selection.h}=${selection.area} pixel area.`);
} }
}; };
worldEditElements.w_delete = { worldEditElements.w_delete = {
onSelect: function () { onSelect: function () {
const selection = w_state.selection; const selection = w_state.selection;
if (!selection) { if (!selection) {
logMessage("Error: Nothing is selected."); logMessage("Error: Nothing is selected.");
return; return;
} }
// Delete pixels // Delete pixels
for (let y = selection.y; y < selection.y2; y++) { for (let y = selection.y; y < selection.y2; y++) {
for (let x = selection.x; x < selection.x2; x++) { for (let x = selection.x; x < selection.x2; x++) {
const pixel = pixelMap[x][y]; const pixel = pixelMap[x][y];
const index = currentPixels.indexOf(pixel); const index = currentPixels.indexOf(pixel);
if (index !== -1) if (index !== -1)
currentPixels.splice(index, 1); currentPixels.splice(index, 1);
if (pixel) { if (pixel) {
delete pixelMap[x][y]; delete pixelMap[x][y];
} }
} }
} }
logMessage(`Deleted ${selection.w}x${selection.h}=${selection.area} pixel area.`); logMessage(`Deleted ${selection.w}x${selection.h}=${selection.area} pixel area.`);
} }
}; };
worldEditElements.w_fill = { worldEditElements.w_fill = {
onSelect: function () { onSelect: function () {
const selection = w_state.selection; const selection = w_state.selection;
const fillElement = w_state.prevNonWorldEditElement; const fillElement = w_state.prevNonWorldEditElement;
if (!selection) { if (!selection) {
logMessage("Error: Nothing is selected."); logMessage("Error: Nothing is selected.");
return; return;
} }
// Fill area // Fill area
for (let y = selection.y; y < selection.y2; y++) { for (let y = selection.y; y < selection.y2; y++) {
for (let x = selection.x; x < selection.x2; x++) { for (let x = selection.x; x < selection.x2; x++) {
const placed = currentPixels.push(new Pixel(x, y, fillElement)); const placed = currentPixels.push(new Pixel(x, y, fillElement));
if (!placed) if (!placed)
return; return;
if (currentPixels.length > maxPixelCount || !fillElement) { if (currentPixels.length > maxPixelCount || !fillElement) {
currentPixels[currentPixels.length - 1].del = true; currentPixels[currentPixels.length - 1].del = true;
} } else if (elements[fillElement] && elements[fillElement].onPlace !== undefined) {
else if (elements[fillElement] && elements[fillElement].onPlace !== undefined) { elements[fillElement].onPlace(currentPixels[currentPixels.length - 1]);
elements[fillElement].onPlace(currentPixels[currentPixels.length - 1]); }
} }
} }
} logMessage(`Filled in ${selection.w}x${selection.h}=${selection.area} pixel area.`);
logMessage(`Filled in ${selection.w}x${selection.h}=${selection.area} pixel area.`); }
}
}; };
// Setup and hooks // Setup and hooks
modifySelectElement(); modifySelectElement();
addWorldEditElements(worldEditElements); addWorldEditElements(worldEditElements);
addWorldEditKeybinds(); addWorldEditKeybinds();
runAfterReset(() => { runAfterReset(() => {
if (w_deselectOnResetSetting.value) if (w_deselectOnResetSetting.value)
w_state.selection = null; w_state.selection = null;
}); });
runAfterReset(updatePastePreviewCanvas); runAfterReset(updatePastePreviewCanvas);
renderPostPixel(renderSelection); renderPostPixel(renderSelection);
@ -395,15 +415,15 @@ renderPostPixel(renderPastePreview);
// Mobile support // Mobile support
let addedCustomEventListeners = false; let addedCustomEventListeners = false;
runAfterReset(() => { runAfterReset(() => {
if (addedCustomEventListeners) if (addedCustomEventListeners)
return; return;
gameCanvas.addEventListener("pointerdown", (e) => { gameCanvas.addEventListener("pointerdown", (e) => {
if (elements[currentElement] && elements[currentElement].onPointerDown) if (elements[currentElement] && elements[currentElement].onPointerDown)
elements[currentElement].onPointerDown(e); elements[currentElement].onPointerDown(e);
}, { passive: false }); }, {passive: false});
gameCanvas.addEventListener("pointermove", (e) => { gameCanvas.addEventListener("pointermove", (e) => {
if (elements[currentElement] && elements[currentElement].onPointerMove) if (elements[currentElement] && elements[currentElement].onPointerMove)
elements[currentElement].onPointerMove(e); elements[currentElement].onPointerMove(e);
}, { passive: false }); }, {passive: false});
addedCustomEventListeners = true; addedCustomEventListeners = true;
}); });