From 6d1108878f342af3941e9204c28106e777101d24 Mon Sep 17 00:00:00 2001 From: Cube14yt Date: Thu, 27 Nov 2025 20:34:10 +0800 Subject: [PATCH 1/4] Update static.js --- mods/static.js | 160 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 150 insertions(+), 10 deletions(-) diff --git a/mods/static.js b/mods/static.js index 82e8a1b3..dbeca0b1 100644 --- a/mods/static.js +++ b/mods/static.js @@ -8,14 +8,10 @@ } function randomColor() { - const letters = "0123456789ABCDEF"; - let color = "#"; - for (let i = 0; i < 6; i++) { - color += letters[Math.floor(Math.random() * 16)]; - } - return color; + return '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, '0'); } + function loopScreen(callback) { for (let x = 0; x <= width; x++) { for (let y = 0; y <= height; y++) { @@ -24,19 +20,163 @@ } } - keybinds["KeyS"] = () => { - staticMode === 0 ? staticMode = 1 : staticMode === 1 ? staticMode = 2 : staticMode = 0 + /** + * Converts RGB to RGBA + * @param {string|object} rgb - Either "rgb(r, g, b)" string or {r, g, b} object + * @param {number} alpha - Alpha value between 0 and 1 + * @returns {string} RGBA string + */ + function rgbToRgba(rgb, alpha = 1) { + let r, g, b; + + if (typeof rgb === 'string') { + const match = rgb.match(/\d+/g); + if (!match || match.length < 3) throw new Error('Invalid RGB string'); + [r, g, b] = match.map(Number); + } else if (typeof rgb === 'object') { + ({ r, g, b } = rgb); + } else { + throw new Error('Invalid input: must be RGB string or object'); + } + alpha = Math.min(Math.max(alpha, 0), 1); + + return `rgba(${r}, ${g}, ${b}, ${alpha})`; } + /** + * Updates the alpha value of an rgba string + * @param {string} rgbaString - Example: "rgba(255, 0, 0, 0.5)" + * @param {number} newAlpha - New alpha value (0 to 1) + * @returns {string} - Updated rgba string + */ + function setAlpha(rgbaString, newAlpha) { + // Use a regex to capture the r, g, b values + const match = rgbaString.match(/rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\s*\)/); + if (!match) { + throw new Error("Invalid rgba string: " + rgbaString); + } + const [_, r, g, b] = match; + return `rgba(${r}, ${g}, ${b}, ${newAlpha})`; + } + + function drawCircle(ctx, x, y, radius, options = {}) { + const { fill = 'blue', stroke = null, lineWidth = 1 } = options; + + // Only compute offset if needed + const offset = lineWidth % 2 === 0 ? 0 : 0.5; + const cx = x + offset; + const cy = y + offset; + + ctx.beginPath(); + ctx.arc(cx, cy, radius, 0, Math.PI * 2); + + // Set styles only if needed + if (fill) { + if (ctx.fillStyle !== fill) ctx.fillStyle = fill; + ctx.fill(); + } + + if (stroke) { + if (ctx.strokeStyle !== stroke) ctx.strokeStyle = stroke; + if (ctx.lineWidth !== lineWidth) ctx.lineWidth = lineWidth; + ctx.stroke(); + } + } + + function toggleStaticMode() { + staticMode = (staticMode + 1) % 5 + } + + if (isMobile) { + const staticButton = document.createElement("button") + staticButton.id = "staticButton" + staticButton.title = "Change static mode" + staticButton.classList.add("controlButton") + staticButton.onclick = () => { + toggleStaticMode() + } + staticButton.textContent = "Static" + document.getElementById("pauseButton").before(staticButton) + } + + keybinds["KeyS"] = () => { + toggleStaticMode() + } + keybinds["KeyK"] = () => { + toggleStaticMode() + } + + + // Static rendering loop + let cachedColorMap = [] renderPostPixel(function (ctx) { if (!staticMode) return + if (!paused) { + cachedColorMap = [] + } else { + cachedColorMap.forEach(renderObj => { + let x = renderObj.x + let y = renderObj.y + let color = renderObj.color + if (color.match(/^#[0-9A-Fa-f]{6}$/)) { + color = rgbToRgba(hexToRGB(color), 1) + } + let colorFullAlpha = setAlpha(color, 1) + let isCircle = renderObj.circle + if (isCircle) { + drawCircle(ctx, canvasCoord(x) + 2.1, canvasCoord(y) + 2.1, 3, { fill: color }) + } else { + drawSquare(ctx, colorFullAlpha, x, y, 1, 0.2) + } + }) + return + } loopScreen((x, y) => { if (staticMode === 1) { - drawSquare(ctx, randomGrayscale(), x, y, 1, 0.2) + let color = randomGrayscale() + drawSquare(ctx, color, x, y, 1, 0.2) + cachedColorMap.push({ x, y, color }) } if (staticMode === 2) { - drawSquare(ctx, randomColor(), x, y, 1, 0.3) + let color = randomColor() + drawSquare(ctx, color, x, y, 1, 0.2) + cachedColorMap.push({ x, y, color }) } + if (staticMode === 3) { + let color = rgbToRgba(randomGrayscale(), 0.2) + drawCircle(ctx, canvasCoord(x) + 2.1, canvasCoord(y) + 2.1, 3, { fill: color }) + cachedColorMap.push({ x, y, color, circle: true }) + } + if (staticMode === 4) { + let color = rgbToRgba(hexToRGB(randomColor()), 0.2) + drawCircle(ctx, canvasCoord(x) + 2.1, canvasCoord(y) + 2.1, 3, { fill: color }) + cachedColorMap.push({ x, y, color, circle: true }) + } + // Currently broken with pausing + /* + if (staticMode === 5) { + let color = rgbToRgba(randomGrayscale(), 0.2) + const random = Math.random() + if (random <= 0.5) { + drawSquare(ctx, color, x, y) + cachedColorMap.push({ x, y, color }) + } else { + drawCircle(ctx, canvasCoord(x) + 2.1, canvasCoord(y) + 2.1, 3, { fill: color }) + cachedColorMap.push({ x, y, color, circle: true }) + } + } + if (staticMode === 6) { + let color = rgbToRgba(hexToRGB(randomColor()), 0.2) + const random = Math.random() + if (random <= 0.5) { + drawSquare(ctx, color, x, y) + cachedColorMap.push({ x, y, color }) + } else { + drawCircle(ctx, canvasCoord(x) + 2.1, canvasCoord(y) + 2.1, 3, { fill: color }) + cachedColorMap.push({ x, y, color, circle: true }) + } + } + */ }) }) })() From b14547443267dbcc43c694836242e7fd789b3ad5 Mon Sep 17 00:00:00 2001 From: Cube14yt Date: Thu, 27 Nov 2025 20:56:39 +0800 Subject: [PATCH 2/4] Add files via upload --- mods/mobile_keybinds.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 mods/mobile_keybinds.js diff --git a/mods/mobile_keybinds.js b/mods/mobile_keybinds.js new file mode 100644 index 00000000..9afbeb6d --- /dev/null +++ b/mods/mobile_keybinds.js @@ -0,0 +1,21 @@ +(() => { + function runKeybind() { + promptInput("Input the keybind you want to run. (e.g. KeyA, Digit1, Backspace)", (keybind) => { + if (keybinds[keybind]) { + keybinds[keybind](); + } + }) + } + + if (isMobile) { + const keybindButton = document.createElement("button") + keybindButton.id = "keybindButton" + keybindButton.title = "Change static mode" + keybindButton.classList.add("controlButton") + keybindButton.onclick = () => { + runKeybind() + } + keybindButton.textContent = "Keybind" + document.getElementById("pauseButton").before(keybindButton) + } +})() \ No newline at end of file From 6bc1c2b88c7b81e51ea7f5c0958fc70dfe507ac6 Mon Sep 17 00:00:00 2001 From: Mnem42 <177770058+Mnem42@users.noreply.github.com> Date: Sat, 29 Nov 2025 20:00:26 +0000 Subject: [PATCH 3/4] Add floating tool thing to zoom.js --- mods/zoom.js | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) diff --git a/mods/zoom.js b/mods/zoom.js index a5a21a20..6ff0d8e5 100644 --- a/mods/zoom.js +++ b/mods/zoom.js @@ -45,6 +45,140 @@ rescale() } + function gen_button(row, col, html, click, nopos, id){ + const elem = document.createElement("button") + + + if (!nopos){ + elem.style.gridColumn = row + elem.style.gridRow = col + } + if (id) { elem.id = id } + + // Table for the data-pos to assign (row major). If null, don't add. + const data_pos_map = [ + ["tl", null, "tr"], + [null, null, null], + ["bl", null, "br"] + ] + + elem.innerHTML = html + elem.onclick = click + + if (data_pos_map[row-1][col-1] !== null) { + elem.dataset.pos = data_pos_map[row-1][col-1] + } + + return elem + } + + function add_css(){ + const FLOATER_CSS = ` + #zm_data_div { + margin-bottom: 10px; + } + + #canvasDiv { + overflow: hidden + } + + #zm_floater_container { + position: absolute; + display: grid; + + right: 5px; + bottom: 5px; + height: 24%; + aspect-ratio: 1; + + border: 2px solid white; + background-color: black; + font-size: 120%; + + button { text-align: center; border: 0px solid white } + + button:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px }; + button:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px }; + button:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px }; + button:where([data-pos="br"]) { border-width: 2px 0px 0px 2px }; + } + #zm_floater_container:has(#zm_collapse[data-collapsed="true"]) { + height: calc(8% - 1px); + + button:not(#zm_collapse) { + display: none + } + } + + .zm_corner { + border: 2px solid white; + } + + #zm_collapse { + grid-row: 3; + grid-column: 3; + } + #zm_collapse[data-collapsed="true"] { + grid-row: 1; + grid-column: 1; + border-width: 0px; + } + ` + + const style_div = document.createElement("style") + style_div.innerHTML = FLOATER_CSS + + document.head.appendChild(style_div) + } + + function add_zoom_floaters(){ + const container = document.createElement("div") + container.id = "zm_floater_container" + + // Pan mode selector (C: Coarse F: Fine) + const pan_mode_sel = gen_button( + 1,3, "C", + (evt) => { + evt.target.dataset.mode = evt.target.dataset.mode == "F" ? "C" : "F" + evt.target.innerText = evt.target.dataset.mode + }, + false, + "zm_panmode_sel" + ) + + const speed = () => + (window.zoom_level > 3 ? 5 : 10) * // More granular at higher zoom levels + (pan_mode_sel.dataset.mode == "F" ? 0.25 : 1) // Increase granularity in fine mode + + container.append( + // Direction buttons + gen_button(2,1, "↑", () => handle_pan("up" ,speed())), + gen_button(1,2, "←", () => handle_pan("left" ,speed())), + gen_button(3,2, "→", () => handle_pan("right" ,speed())), + gen_button(2,3, "↓", () => handle_pan("down" ,speed())), + + // Zoom buttons + gen_button(1,1, "+", () => handle_zoom("in")), + gen_button(3,1, "-", () => handle_zoom("out")), + + // Collapse button + gen_button( + 3,3, "#", + (evt) => { + evt.target.dataset.collapsed = evt.target.dataset.collapsed == "true" + ? "false" + : "true" + }, + true, + "zm_collapse" + ), + pan_mode_sel + ) + + const canvas_div = document.getElementById("canvasDiv") + canvas_div.appendChild(container) + } + function rescale(){ log_info() @@ -87,8 +221,12 @@ } function patch_ui(){ + add_css() + add_zoom_floaters() + zoom_data_div = document.createElement("div") - document.getElementById("logDiv").appendChild(zoom_data_div) + zoom_data_div.id = "zm_data_div" + document.getElementById("logDiv").prepend(zoom_data_div) const controls_table = document.getElementById("controlsTable").lastElementChild controls_table.insertAdjacentHTML("beforeBegin",` From 86477148160aba15b9ceca61fd037930f9e6772d Mon Sep 17 00:00:00 2001 From: Mnem42 <177770058+Mnem42@users.noreply.github.com> Date: Sat, 29 Nov 2025 21:39:28 +0000 Subject: [PATCH 4/4] idk why it uses % instead of em --- mods/zoom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/zoom.js b/mods/zoom.js index 6ff0d8e5..6c5ba232 100644 --- a/mods/zoom.js +++ b/mods/zoom.js @@ -93,7 +93,7 @@ border: 2px solid white; background-color: black; - font-size: 120%; + font-size: 1.2em; button { text-align: center; border: 0px solid white }