From db80f18d3826af26b7ffbc01c3b62faced282f62 Mon Sep 17 00:00:00 2001 From: Mnem42 Date: Tue, 3 Feb 2026 17:39:30 +0000 Subject: [PATCH] there be stuf? yes be stuf --- mods/zoom.js | 209 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 123 insertions(+), 86 deletions(-) diff --git a/mods/zoom.js b/mods/zoom.js index 2a781625..ddbf7b36 100644 --- a/mods/zoom.js +++ b/mods/zoom.js @@ -8,17 +8,17 @@ input_container = null; push_btn = null; pop_btn = null; - constructor(name, storage_name, default_values = [], desc = "", step = 1, custom_validator = () => true, disabled = false) { + constructor(name, storage_name, desc, options) { super( name, storage_name, [5, 0], - disabled, - default_values ?? [], + options.disabled, + options.default_values, desc, - custom_validator + options.custom_validator ); - this.step = step; + this.step = options.step ?? 1; } #new_input(value, i) { const elem = document.createElement("input"); @@ -182,10 +182,13 @@ canvas_bkg; zoom; unl_zoom; - show_floater; fpan_speed; cpan_speed; upan_speed; + use_ijkl; + show_floater; + pan_zeroing_en; + zoom_zeroing_en; constructor(on_edit) { const { Numlist: Numlist2, MultiSetting, SettingGroup } = def_classes(); const settings_tab = new SettingsTab("zoom.js"); @@ -238,13 +241,42 @@ "Whether to show the floater or not", validator ); + this.use_ijkl = new Setting( + "Use IJKL", + "use_ijkl", + settingType.BOOLEAN, + false, + false, + "Makes the mod use IJKL instead of WASD for panning (requires refresh)", + validator + ); + this.pan_zeroing_en = new Setting( + "Enable pan zeroing", + "en_pzero", + settingType.BOOLEAN, + false, + true, + "Allows the Q key to reset pan (requires refresh)", + validator + ); + this.zoom_zeroing_en = new Setting( + "Enable zoom zeroing", + "en_zzero", + settingType.BOOLEAN, + false, + true, + "Allows the P key to reset zoom. Doesn't work with set zoom levels (requires refresh)", + validator + ); const zoom_levels = new Numlist2( "Zoom levels", "zoom_levels", - [0.5, 1, 2, 3, 6, 12], "Zoom levels", - 1, - validator + { + default_values: [0.5, 1, 2, 3, 6, 12], + step: 0.1, + custom_validator: validator + } ); this.unl_zoom = new SettingGroup({ speed: new Setting( @@ -284,8 +316,17 @@ ); settings_tab.registerSettings( void 0, - this.canvas_bkg, + this.canvas_bkg + ); + settings_tab.registerSettings( + "Controls", + this.use_ijkl, this.show_floater, + this.pan_zeroing_en, + this.zoom_zeroing_en + ); + settings_tab.registerSettings( + "Zoom", this.zoom ); settings_tab.registerSettings( @@ -328,7 +369,7 @@ runAfterReset(() => { this.zoom_level = 1; this.zoom_panning = [0, 0]; - this.rescale(); + this.update(); }); } handle_zoom(direction) { @@ -364,7 +405,7 @@ } this.zoom_level = Number(this.zoom_level.toPrecision(3)); } - this.rescale(); + this.update(); } handle_pan(direction, speed) { switch (direction) { @@ -381,12 +422,12 @@ this.zoom_panning[1] -= speed; break; } - this.rescale(); + this.update(); } scale() { return this.settings.zoom.value == 0 ? this.settings.zoom.settings[0].value[this.zoom_level] : this.zoom_level; } - rescale() { + update() { this.log_info(); const x = this.zoom_panning[0] * (pixelSize * this.scale()); const y = this.zoom_panning[1] * (pixelSize * this.scale()); @@ -400,19 +441,36 @@ `; this.patcher.zoom_data_div.innerText += `Pan : ${x_pan}, ${y_pan}`; } + kbd_speed_noshift(ev) { + return ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value; + } patch_keybinds() { + const pan_keys = this.settings.use_ijkl.value ? ["i", "j", "k", "l"] : ["w", "a", "s", "d"]; + const pan_keys_upper = this.settings.use_ijkl.value ? ["I", "J", "K", "L"] : ["W", "A", "S", "D"]; keybinds["9"] = () => this.handle_zoom("in"); keybinds["0"] = () => this.handle_zoom("out"); - keybinds["w"] = (ev) => this.handle_pan("up", ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value); - keybinds["a"] = (ev) => this.handle_pan("left", ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value); - keybinds["s"] = (ev) => this.handle_pan("down", ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value); - keybinds["d"] = (ev) => this.handle_pan("right", ev.altKey ? this.settings.upan_speed.value : this.settings.cpan_speed.value); - keybinds["W"] = () => this.handle_pan("up", this.settings.fpan_speed.value); - keybinds["A"] = () => this.handle_pan("left", this.settings.fpan_speed.value); - keybinds["S"] = () => this.handle_pan("down", this.settings.fpan_speed.value); - keybinds["D"] = () => this.handle_pan("right", this.settings.fpan_speed.value); + keybinds[pan_keys[0]] = (ev) => this.handle_pan("up", this.kbd_speed_noshift(ev)); + keybinds[pan_keys[1]] = (ev) => this.handle_pan("left", this.kbd_speed_noshift(ev)); + keybinds[pan_keys[2]] = (ev) => this.handle_pan("down", this.kbd_speed_noshift(ev)); + keybinds[pan_keys[3]] = (ev) => this.handle_pan("right", this.kbd_speed_noshift(ev)); + keybinds[pan_keys_upper[0]] = () => this.handle_pan("up", this.settings.fpan_speed.value); + keybinds[pan_keys_upper[1]] = () => this.handle_pan("left", this.settings.fpan_speed.value); + keybinds[pan_keys_upper[2]] = () => this.handle_pan("down", this.settings.fpan_speed.value); + keybinds[pan_keys_upper[3]] = () => this.handle_pan("right", this.settings.fpan_speed.value); + if (this.settings.pan_zeroing_en.value) { + keybinds["q"] = () => { + this.zoom_panning = [0, 0]; + this.update(); + }; + } + if (this.settings.zoom_zeroing_en.value) { + keybinds["p"] = () => { + if (this.settings.zoom.value == 1) this.zoom_level = 1; + this.update(); + }; + } } - speed() { + floater_speed() { switch (this.patcher.panmode_sel.innerText) { case "C": return this.settings.cpan_speed.value; @@ -425,84 +483,59 @@ } } patch_floater() { - document.getElementById("zm_floater_u").onclick = () => this.handle_pan("up", this.speed()); - document.getElementById("zm_floater_d").onclick = () => this.handle_pan("down", this.speed()); - document.getElementById("zm_floater_l").onclick = () => this.handle_pan("left", this.speed()); - document.getElementById("zm_floater_r").onclick = () => this.handle_pan("right", this.speed()); + function patch(id, fn) { + document.getElementById(id).onclick = fn; + } + patch("zm_floater_zi", () => this.handle_zoom("in")); + patch("zm_floater_zo", () => this.handle_zoom("out")); + patch("zm_floater_u", () => this.handle_pan("up", this.floater_speed())); + patch("zm_floater_d", () => this.handle_pan("down", this.floater_speed())); + patch("zm_floater_l", () => this.handle_pan("left", this.floater_speed())); + patch("zm_floater_r", () => this.handle_pan("right", this.floater_speed())); } }; + // assets/numlist.css + var numlist_default = "#settingsMenu .zm_nml_btn_container button { font-size: 2em; padding: 0px; margin: 0px;}\r\n#settingsMenu .zm_nml_icontainer { align-self: center }\r\n#settingsMenu .zm_nml_setting { display: grid; grid-template-columns: 7em 1fr;}\r\n\r\n#settingsMenu .zm_nml_setting span {\r\n input { width: 2em; margin-right: 4px; margin-bottom: 4px;}\r\n \r\n input:focus {\r\n outline: none;\r\n box-shadow: none;\r\n border-color: white;\r\n }\r\n}"; + + // assets/main.css + var main_default = '#zm_data_div { margin-bottom: 10px }\r\n#canvasDiv { overflow: hidden; background-color: var(--opac-85) }\r\n\r\n@media(pointer=coarse){\r\n #zm_floater_container#zm_floater_container { \r\n width: 40%;\r\n height: auto;\r\n }\r\n #zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n }\r\n}\r\n\r\n@media(pointer:coarse) and (orientation:landscape){\r\n #zm_floater_container#zm_floater_container {\r\n width: auto;\r\n top: 5px;\r\n }\r\n #zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n }\r\n}\r\n\r\n#colorSelector { z-index: 1; right: 5px }\r\n#zm_floater_container {\r\n position: absolute;\r\n display: grid;\r\n\r\n right: 5px;\r\n bottom: 5px;\r\n height: 100px;\r\n aspect-ratio: 1;\r\n\r\n max-width: 200px;\r\n max-height: 200px;\r\n\r\n border: 2px solid white;\r\n background-color: black;\r\n font-size: 120%;\r\n\r\n button { text-align: center; border: 0px solid white }\r\n\r\n button:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px };\r\n button:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px };\r\n button:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px };\r\n button:where([data-pos="br"]) { border-width: 2px 0px 0px 2px };\r\n}\r\n#zm_floater_container:has(#zm_collapse[data-collapsed="true"]) {\r\n height: 50px;\r\n \r\n button:not(#zm_collapse) { display: none; }\r\n}\r\n#canvasDiv:has(#colorSelector[style *= "block"]) #zm_floater_container {\r\n bottom: 50px;\r\n}\r\n\r\n.zm_corner { border: 2px solid white; }\r\n\r\n#zm_collapse {\r\n grid-row: 3;\r\n grid-column: 3;\r\n}\r\n#zm_collapse[data-collapsed="true"] {\r\n grid-row: 1;\r\n grid-column: 1;\r\n border-width: 0px;\r\n}'; + + // assets/multisetting.css + var multisetting_default = '.zm_ms_row {\r\n display: grid;\r\n grid-template-columns: 2.2em 1fr; \r\n}\r\n\r\n.zm_ms_row[data-current="false"] {\r\n .zm_ms_selbtn { color: transparent }\r\n}\r\n\r\n.zm_ms_selbtn.zm_ms_selbtn:not(#_) {\r\n height: 100%;\r\n width: calc(100% - 10px);\r\n\r\n margin-right: 2px;\r\n padding: 0px;\r\n\r\n border: 2px solid var(--theme);\r\n font-size: 1.5em;\r\n}'; + // assets/ctrl_info.html var ctrl_info_default = "\r\n Zoom in/out\r\n \r\n 9/\r\n 0\r\n \r\n\r\n\r\n Pan\r\n \r\n W\r\n A\r\n S\r\n D\r\n \r\n\r\n\r\n Pan (fast)\r\n \r\n Shift + \r\n W\r\n A\r\n S\r\n D\r\n \r\n"; // assets/floater.html var floater_default = '
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n
'; - // assets/main.css - var main_default = '#zm_data_div { margin-bottom: 10px }\r\n#canvasDiv { overflow: hidden; background-color: var(--opac-85) }\r\n\r\n@media(pointer=coarse){\r\n#zm_floater_container#zm_floater_container { \r\n width: 40%;\r\n height: auto;\r\n}\r\n#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n}\r\n}\r\n\r\n@media(pointer:coarse) and (orientation:landscape){\r\n#zm_floater_container#zm_floater_container {\r\n width: auto;\r\n top: 5px;\r\n}\r\n#zm_floater_container:has(#zm_collapse[data-collapsed="true"]){\r\n width: calc(40% / 3);\r\n}\r\n}\r\n\r\n#colorSelector { z-index: 1; right: 5px }\r\n#zm_floater_container {\r\nposition: absolute;\r\ndisplay: grid;\r\n\r\nright: 5px;\r\nbottom: 5px;\r\nheight: 100px;\r\naspect-ratio: 1;\r\n\r\nmax-width: 200px;\r\nmax-height: 200px;\r\n\r\nborder: 2px solid white;\r\nbackground-color: black;\r\nfont-size: 120%;\r\n\r\nbutton { text-align: center; border: 0px solid white }\r\n\r\nbutton:where([data-pos="tl"]) { border-width: 0px 2px 2px 0px };\r\nbutton:where([data-pos="tr"]) { border-width: 2px 2px 0px 0px };\r\nbutton:where([data-pos="bl"]) { border-width: 0px 0px 2px 2px };\r\nbutton:where([data-pos="br"]) { border-width: 2px 0px 0px 2px };\r\n}\r\n#zm_floater_container:has(#zm_collapse[data-collapsed="true"]) {\r\nheight: 50px;\r\n\r\nbutton:not(#zm_collapse) {\r\n display: none;\r\n}\r\n}\r\n#canvasDiv:has(#colorSelector[style *= "block"]) #zm_floater_container {\r\nbottom: 50px;\r\n}\r\n\r\n.zm_corner { border: 2px solid white; }\r\n\r\n#zm_collapse {\r\ngrid-row: 3;\r\ngrid-column: 3;\r\n}\r\n#zm_collapse[data-collapsed="true"] {\r\ngrid-row: 1;\r\ngrid-column: 1;\r\nborder-width: 0px;\r\n}'; - // assets/nlist_spinner.png var nlist_spinner_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAYCAYAAADH2bwQAAAAcklEQVQokcWSXQrAIAyDv8oOoPe/49wJzB7coIg/jA2WPhQ1TdOiATsThNmjJ8QV4XjdokIkRHqiEAF2NAgoSw8GlCuD3K3zYEzgFdSQBbA15LaYQN1i9lU+3y16CgDqjSl/MKBoMIk5DyNk46sf9SfhBITwI86iGhy9AAAAAElFTkSuQmCC"; - // assets/numlist.css.ts + // assets/spinner.css.ts var CSS = ` -#settingsMenu .zm_nml_btn_container button { - font-size: 2em; - padding: 0px; - margin: 0px; +#betterSettings\\/div\\/zoom\\.js input::-webkit-inner-spin-button, +#betterSettings\\/div\\/zoom\\.js input::-webkit-outer-spin-button { + -webkit-appearance: none; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 0.75em; + background: #000 url(${nlist_spinner_default}) no-repeat center center; + background-size: 100%; + border-left: 2px solid var(--theme); + image-rendering: pixelated; + opacity: 0.8; } - -#settingsMenu .zm_nml_icontainer { - align-self: center -} - -#settingsMenu .zm_nml_setting { - display: grid; - grid-template-columns: 7em 1fr; -} - -#settingsMenu .zm_nml_setting span { - input { - width: 2em; - margin-right: 4px; - margin-bottom: 4px; - } - - input:focus { - outline: none; - box-shadow: none; - border-color: white; - } - - /* Sorry, firefox users */ - input::-webkit-inner-spin-button, - input::-webkit-outer-spin-button { - -webkit-appearance: none; - position: absolute; - top: 0; - right: 0; - bottom: 0; - width: 0.75em; - - background: #000 url(${nlist_spinner_default}) no-repeat center center; - background-size: 100%; - border-left: 2px solid var(--theme); - - image-rendering: pixelated; - opacity: 0.8; - } - - input::-webkit-inner-spin-button:hover, - input::-webkit-outer-spin-button:active { - border-left: 2px solid white; - opacity: 1; - } +#betterSettings\\/div\\/zoom\\.js input::-webkit-inner-spin-button:hover, +#betterSettings\\/div\\/zoom\\.js input::-webkit-outer-spin-button:active { + border-left: 2px solid white; + opacity: 1; } `; - var numlist_css_default = CSS; - - // assets/multisetting.css - var multisetting_default = '.zm_ms_row {\r\n display: grid;\r\n grid-template-columns: 2.2em 1fr; \r\n}\r\n\r\n.zm_ms_row[data-current="false"] {\r\n .zm_ms_selbtn { color: transparent }\r\n}\r\n\r\n.zm_ms_selbtn.zm_ms_selbtn:not(#_) {\r\n height: 100%;\r\n width: calc(100% - 10px);\r\n\r\n margin-right: 2px;\r\n padding: 0px;\r\n\r\n border: 2px solid var(--theme);\r\n font-size: 1.5em;\r\n}'; + var spinner_css_default = CSS; // src/patcher.ts var Patcher = class { @@ -518,7 +551,7 @@ document.head.appendChild(style_div); dependOn("betterSettings.js", () => { const style_div2 = document.createElement("style"); - style_div2.innerHTML = numlist_css_default + multisetting_default; + style_div2.innerHTML = numlist_default + multisetting_default + spinner_css_default; document.head.appendChild(style_div2); }); this.canvas_div = document.getElementById("canvasDiv"); @@ -538,6 +571,10 @@ break; } }; + const collapse_btn = document.getElementById("zm_collapse"); + collapse_btn.onclick = () => { + collapse_btn.dataset.collapsed = collapse_btn.dataset.collapsed == "true" ? "false" : "true"; + }; this.zoom_data_div = document.createElement("div"); this.zoom_data_div.id = "zm_data_div"; document.getElementById("logDiv")?.prepend(this.zoom_data_div);