mirror of
https://github.com/SwingTheVine/Wplace-BlueMarble.git
synced 2026-05-06 11:39:27 +00:00
390 lines
35 KiB
HTML
390 lines
35 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>settingsManager.js - Documentation</title>
|
|
|
|
<script src="scripts/prettify/prettify.js"></script>
|
|
<script src="scripts/prettify/lang-css.js"></script>
|
|
<!--[if lt IE 9]>
|
|
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
<![endif]-->
|
|
<link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
|
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
|
</head>
|
|
<body>
|
|
|
|
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
<label for="nav-trigger" class="navicon-button x">
|
|
<div class="navicon"></div>
|
|
</label>
|
|
|
|
<label for="nav-trigger" class="overlay"></label>
|
|
|
|
<nav>
|
|
<li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ApiManager.html">ApiManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="ConfettiManager.html">ConfettiManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Observers.html">Observers</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Overlay.html">Overlay</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="SettingsManager.html">SettingsManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Template.html">Template</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="TemplateManager.html">TemplateManager</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowCredits.html">WindowCredits</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowFilter.html">WindowFilter</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowMain.html">WindowMain</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowSettings.html">WindowSettings</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowTelemetry.html">WindowTelemetry</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="WindowWizard.html">WindowWizard</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="module.exports_module.exports.html">exports</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addBr">addBr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addButton">addButton</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addButtonHelp">addButtonHelp</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addCaption">addCaption</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addCheckbox">addCheckbox</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDetails">addDetails</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDiv">addDiv</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addDragbar">addDragbar</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addFieldset">addFieldset</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addForm">addForm</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addHeader">addHeader</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addHr">addHr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addImg">addImg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addInput">addInput</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addInputFile">addInputFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addLegend">addLegend</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addLi">addLi</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addMenu">addMenu</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addOl">addOl</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addOption">addOption</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addP">addP</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSelect">addSelect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSmall">addSmall</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSpan">addSpan</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addSummary">addSummary</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTable">addTable</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTbody">addTbody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTd">addTd</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTextarea">addTextarea</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTfoot">addTfoot</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTh">addTh</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addThead">addThead</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTimer">addTimer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addTr">addTr</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#addUl">addUl</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#base64ToUint8">base64ToUint8</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildElement">buildElement</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildHighlight">buildHighlight</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildOverlay">buildOverlay</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildTemplate">buildTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildWindow">buildWindow</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#buildWindowed">buildWindowed</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateCanvasTransparency">calculateCanvasTransparency</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateCoordsFromChunked">calculateCoordsFromChunked</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#calculateRelativeLuminance">calculateRelativeLuminance</a></span></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#colorpalette">colorpalette</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#colorpaletteForBlueMarble">colorpaletteForBlueMarble</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleError">consoleError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleLog">consoleLog</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#consoleWarn">consoleWarn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#convertTemplateToBlob">convertTemplateToBlob</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createConfetti">createConfetti</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createJSON">createJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createObserverBody">createObserverBody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createTemplate">createTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#createTemplateTiles">createTemplateTiles</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#deleteTemplate">deleteTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#disableTemplate">disableTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadAllTemplates">downloadAllTemplates</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadAllTemplatesFromStorage">downloadAllTemplatesFromStorage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#downloadTemplate">downloadTemplate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#drawTemplateOnTile">drawTemplateOnTile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#encodedToNumber">encodedToNumber</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#escapeHTML">escapeHTML</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getClipboardData">getClipboardData</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getObserverBody">getObserverBody</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#getWplaceVersion">getWplaceVersion</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDisplayError">handleDisplayError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDisplayStatus">handleDisplayStatus</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleDrag">handleDrag</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#handleMinimization">handleMinimization</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#hexToRGB">hexToRGB</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#importJSON">importJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#inject">inject</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeDate">localizeDate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeDuration">localizeDuration</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizeNumber">localizeNumber</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#localizePercent">localizePercent</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#negativeSafeModulo">negativeSafeModulo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#numberToEncoded">numberToEncoded</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#observe">observe</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#observeBlack">observeBlack</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#rgbToHex">rgbToHex</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#selectAllCoordinateInputs">selectAllCoordinateInputs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#serverTPtoDisplayTP">serverTPtoDisplayTP</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setApiManager">setApiManager</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setSettingsManager">setSettingsManager</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setTemplatesShouldBeDrawn">setTemplatesShouldBeDrawn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#setWindowMain">setWindowMain</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#sleep">sleep</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#spontaneousResponseListener">spontaneousResponseListener</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#toggleFlag">toggleFlag</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#uint8ToBase64">uint8ToBase64</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateColorList">updateColorList</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateInnerHTML">updateInnerHTML</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#updateUserStorage">updateUserStorage</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#viewCanvasInNewTab">viewCanvasInNewTab</a></span></li>
|
|
</nav>
|
|
|
|
<div id="main">
|
|
|
|
<h1 class="page-title">settingsManager.js</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section>
|
|
<article>
|
|
<pre class="prettyprint source linenums"><code>import { sleep } from "./utils";
|
|
import WindowSettings from "./WindowSettings";
|
|
|
|
/** SettingsManager class for handling user settings and making them persist between sessions.
|
|
* Logic for {@link WindowSettings} is managed here.
|
|
* "Flags" should follow the same styling as `.classList()` and should not contain spaces.
|
|
* A flag should always be false by default.
|
|
* When a flag is false, it will not exist in the "flags" Array.
|
|
* (Therefore, "flags" should be `[]` by default)
|
|
* If it exists in the "flags" Array, then the flag is `true`.
|
|
* @class SettingsManager
|
|
* @since 0.91.11
|
|
* @example
|
|
* {
|
|
* "uuid": "497dcba3-ecbf-4587-a2dd-5eb0665e6880",
|
|
* "telemetry": 1,
|
|
* "flags": ["hl-noTrans", "ftr-oWin", "te-noSkip"],
|
|
* "highlight": [[1,0,-1],[1,-1,0],[2,1,0],[1,0,1]],
|
|
* "filter": [-2,0,4,5,6,29,63]
|
|
* }
|
|
*/
|
|
export default class SettingsManager extends WindowSettings {
|
|
|
|
/** Constructor for the SettingsManager class
|
|
* @param {string} name - The name of the userscript
|
|
* @param {string} version - The version of the userscript
|
|
* @param {Object} userSettings - The user settings as an object
|
|
* @since 0.91.11
|
|
*/
|
|
constructor(name, version, userSettings) {
|
|
super(name, version); // Executes WindowSettings constructor
|
|
|
|
this.userSettings = userSettings; // User settings as an Object
|
|
this.userSettings.flags ??= []; // Makes sure the key "flags" always exists
|
|
this.userSettingsOld = structuredClone(this.userSettings); // Creates a duplicate of the user settings to store the old version of user settings from 5+ seconds ago
|
|
this.userSettingsSaveLocation = 'bmUserSettings'; // Storage save location
|
|
|
|
this.updateFrequency = 5000; // Cooldown between saving to storage (throttle)
|
|
this.lastUpdateTime = 0; // When this unix timestamp is within the last 5 seconds, we should save this.userSettings to storage
|
|
|
|
setInterval(this.updateUserStorage.bind(this), this.updateFrequency); // Runs every X seconds (see updateFrequency)
|
|
}
|
|
|
|
/** Updates the user settings in userscript storage
|
|
* @since 0.91.39
|
|
*/
|
|
async updateUserStorage() {
|
|
|
|
// Turns the objects into a string
|
|
const userSettingsCurrent = JSON.stringify(this.userSettings);
|
|
const userSettingsOld = JSON.stringify(this.userSettingsOld);
|
|
|
|
// If the user settings have changed, AND the last update to user storage was over 5 seconds ago (5sec throttle)...
|
|
if ((userSettingsCurrent != userSettingsOld) && ((Date.now() - this.lastUpdateTime) > this.updateFrequency)) {
|
|
await GM.setValue(this.userSettingsSaveLocation, userSettingsCurrent); // Updates user storage
|
|
this.userSettingsOld = structuredClone(this.userSettings); // Updates the old user settings with a duplicate of the current user settings
|
|
this.lastUpdateTime = Date.now(); // Updates the variable that contains the last time updated
|
|
console.log(userSettingsCurrent);
|
|
}
|
|
}
|
|
|
|
/** Toggles a boolean flag to the state that was passed in.
|
|
* If no state was passed in, the flag will flip to the opposite state.
|
|
* The existence of the flag determines its state. If it exists, it is `true`.
|
|
* @param {string} flagName - The name of the flag to toggle
|
|
* @param {boolean} [state=undefined] - (Optional) The state to change the flag to
|
|
* @since 0.91.60
|
|
*/
|
|
toggleFlag(flagName, state = undefined) {
|
|
|
|
const flagIndex = this.userSettings?.flags?.indexOf(flagName) ?? -1; // Is the flag `true`?
|
|
|
|
// If the flag is enabled, AND the user does not want to force the flag to be true...
|
|
if ((flagIndex != -1) && (state !== true)) {
|
|
|
|
this.userSettings?.flags?.splice(flagIndex, 1); // Remove the flag (makes it false)
|
|
} else if ((flagIndex == -1) && (state !== false)) {
|
|
// Else if the flag is disabled, AND the user does not want to force the flag to be false...
|
|
this.userSettings?.flags?.push(flagName); // Add the flag (makes it true)
|
|
}
|
|
}
|
|
|
|
// This is one of the most insane OOP setups I have ever laid my eyes on
|
|
|
|
/** Builds the "highlight" category of the settings window
|
|
* @since 0.91.18
|
|
* @see WindowSettings#buildHighlight
|
|
*/
|
|
buildHighlight() {
|
|
|
|
const highlightPresetOff = '<svg viewBox="0 0 3 3"><path d="M0,0H3V3H0ZM0,1H3M0,2H3M1,0V3M2,0V3" fill="#fff"/><path d="M1,1H2V2H1Z" fill="#2f4f4f"/></svg>';
|
|
const highlightPresetCross = '<svg viewBox="0 0 3 3"><path d="M0,0H3V3H0Z" fill="#fff"/><path d="M1,0H2V1H3V2H2V3H1V2H0V1H1Z" fill="brown"/><path d="M1,1H2V2H1Z" fill="#2f4f4f"/></svg>';
|
|
|
|
// Obtains user settings for highlight from storage, or the default array if nothing was found
|
|
const storedHighlight = this.userSettings?.highlight ?? [[1, 0, 1], [2, 0, 0], [1, -1, 0], [1, 1, 0], [1, 0, -1]];
|
|
|
|
// Constructs the category and adds it to the window
|
|
this.window = this.addDiv({'class': 'bm-container'})
|
|
.addHeader(2, {'textContent': 'Pixel Highlight'}).buildElement()
|
|
.addHr().buildElement()
|
|
.addDiv({'class': 'bm-container', 'style': 'margin-left: 1.5ch;'})
|
|
.addCheckbox({'textContent': 'Highlight transparent pixels'}, (instance, label, checkbox) => {
|
|
checkbox.checked = !this.userSettings?.flags?.includes('hl-noTrans'); // Makes the checkbox match the last stored user setting
|
|
checkbox.onchange = (event) => this.toggleFlag('hl-noTrans', !event.target.checked); // Forces the flag to be the opposite state as the checkbox. E.g. "Checked" means 'hl-noTrans' is false (does not exist).
|
|
}).buildElement()
|
|
.addP({'id': 'bm-highlight-preset-label', 'textContent': 'Choose a preset:', 'style': 'font-weight: 700;'}).buildElement()
|
|
.addDiv({'class': 'bm-flex-center', 'role': 'group', 'aria-labelledby': 'bm-highlight-preset-label'})
|
|
.addDiv({'class': 'bm-highlight-preset-container'})
|
|
.addSpan({'textContent': 'None'}).buildElement()
|
|
.addButton({'innerHTML': highlightPresetOff, 'aria-label': 'Preset "None"'}, (instance, button) => {button.onclick = () => this.#updateHighlightToPreset('None')}).buildElement()
|
|
.buildElement()
|
|
.addDiv({'class': 'bm-highlight-preset-container'})
|
|
.addSpan({'textContent': 'Cross'}).buildElement()
|
|
.addButton({'innerHTML': highlightPresetCross, 'aria-label': 'Preset "Cross Shape"'}, (instance, button) => {button.onclick = () => this.#updateHighlightToPreset('Cross')}).buildElement()
|
|
.buildElement()
|
|
.addDiv({'class': 'bm-highlight-preset-container'})
|
|
.addSpan({'textContent': 'X'}).buildElement()
|
|
.addButton({'innerHTML': highlightPresetCross.replace('d="M1,0H2V1H3V2H2V3H1V2H0V1H1Z"', 'd="M0,0V1H3V0H2V3H3V2H0V3H1V0Z"'), 'aria-label': 'Preset "X Shape"'}, (instance, button) => {button.onclick = () => this.#updateHighlightToPreset('X')}).buildElement()
|
|
.buildElement()
|
|
.addDiv({'class': 'bm-highlight-preset-container'})
|
|
.addSpan({'textContent': 'Full'}).buildElement()
|
|
.addButton({'innerHTML': highlightPresetOff.replace('#fff', '#2f4f4f'), 'aria-label': 'Preset "Full Template"'}, (instance, button) => {button.onclick = () => this.#updateHighlightToPreset('Full')}).buildElement()
|
|
.buildElement()
|
|
.buildElement()
|
|
.addP({'id': 'bm-highlight-grid-label', 'textContent': 'Create a custom pattern:', 'style': 'font-weight: 700;'}).buildElement()
|
|
.addDiv({'class': 'bm-highlight-grid', 'role': 'group', 'aria-labelledby': 'bm-highlight-grid-label'});
|
|
// We leave this open so we can add buttons
|
|
|
|
// For each of the 9 buttons...
|
|
for (let buttonY = -1; buttonY <= 1; buttonY++) {
|
|
for (let buttonX = -1; buttonX <= 1; buttonX++) {
|
|
const buttonState = storedHighlight[storedHighlight.findIndex(([, x, y]) => ((x == buttonX) && (y == buttonY)))]?.[0] ?? 0;
|
|
let buttonStateName = 'Disabled';
|
|
if (buttonState == 1) {
|
|
buttonStateName = 'Incorrect';
|
|
} else if (buttonState == 2) {
|
|
buttonStateName = 'Template';
|
|
}
|
|
this.window = this.addButton({
|
|
'data-status': buttonStateName,
|
|
'aria-label': `Sub-pixel ${buttonStateName.toLowerCase()}`
|
|
}, (instance, button) => {
|
|
button.onclick = () => this.#updateHighlightSettings(button, [buttonX, buttonY])
|
|
}).buildElement();
|
|
}
|
|
}
|
|
|
|
// Resumes from where we left off before we added buttons
|
|
this.window = this.buildElement()
|
|
.buildElement()
|
|
.buildElement();
|
|
}
|
|
|
|
/** Updates the display of the highlight buttons in the settings window.
|
|
* Additionally, it will update user settings with the new selection.
|
|
* @param {HTMLButtonElement} button - The button that was pressed
|
|
* @param {Array<number, number>} coords - The relative coordinates of the button
|
|
* @since 0.91.46
|
|
*/
|
|
#updateHighlightSettings(button, coords) {
|
|
|
|
button.disabled = true; // Disabled the button until we are done
|
|
|
|
const status = button.dataset['status']; // Obtains the current status of the button
|
|
|
|
/** Obtains the old highlight storage, or sets it to default. @type {Array<number[]>} */
|
|
const userStorageOld = this.userSettings?.highlight ?? [[1, 0, 1], [2, 0, 0], [1, -1, 0], [1, 1, 0], [1, 0, -1]];
|
|
|
|
let userStorageChange = [2, 0, 0]; // The new change to the user storage
|
|
|
|
const userStorageNew = userStorageOld; // The old storage with the new change
|
|
|
|
// For each different type of status...
|
|
switch (status) {
|
|
|
|
// If the button was in the "Disabled" state
|
|
case 'Disabled':
|
|
|
|
// Change to "Incorrect"
|
|
button.dataset['status'] = 'Incorrect';
|
|
button.ariaLabel = 'Sub-pixel incorrect';
|
|
userStorageChange = [1, ...coords];
|
|
break;
|
|
|
|
// If the button was in the "Incorrect" state
|
|
case 'Incorrect':
|
|
|
|
// Change to "Template"
|
|
button.dataset['status'] = 'Template';
|
|
button.ariaLabel = 'Sub-pixel template';
|
|
userStorageChange = [2, ...coords];
|
|
break;
|
|
|
|
// If the button was in the "Template" state
|
|
case 'Template':
|
|
|
|
// Change to "Disabled"
|
|
button.dataset['status'] = 'Disabled';
|
|
button.ariaLabel = 'Sub-pixel disabled';
|
|
userStorageChange = [0, ...coords];
|
|
break;
|
|
}
|
|
|
|
// Finds the index of the pixel to change
|
|
const indexOfChange = userStorageOld.findIndex(([, x, y]) => ((x == userStorageChange[1]) && (y == userStorageChange[2])));
|
|
|
|
// If the new sub-pixel state is NOT disabled
|
|
if (userStorageChange[0] != 0) {
|
|
|
|
// If a sub-pixel was found...
|
|
if (indexOfChange != -1) {
|
|
userStorageNew[indexOfChange] = userStorageChange;
|
|
} else {
|
|
userStorageNew.push(userStorageChange);
|
|
}
|
|
} else if (indexOfChange != -1) {
|
|
// Else, it is disabled. We want to remove it if it exists.
|
|
userStorageNew.splice(indexOfChange, 1); // Removes 1 index from the array at the index of the pixel change
|
|
}
|
|
|
|
this.userSettings['highlight'] = userStorageNew;
|
|
// TODO: Add timer update here
|
|
|
|
button.disabled = false; // Reenables the button since we are done
|
|
}
|
|
|
|
/** Changes the highlight buttons to the clicked preset.
|
|
* @param {string} preset - The name of the preset
|
|
* @since 0.91.49
|
|
*/
|
|
async #updateHighlightToPreset(preset) {
|
|
|
|
// Obtains all preset buttons as a NodeList
|
|
const presetButtons = document.querySelectorAll('.bm-highlight-preset-container button');
|
|
|
|
// For each preset...
|
|
for (const button of presetButtons) {
|
|
button.disabled = true; // Disables the button
|
|
}
|
|
|
|
let presetArray = [0,0,0,0,2,0,0,0,0]; // The preset "None"
|
|
|
|
// Selects the preset passed in
|
|
switch (preset) {
|
|
case 'Cross':
|
|
presetArray = [0,1,0,1,2,1,0,1,0]; // The preset "Cross"
|
|
break;
|
|
case 'X':
|
|
presetArray = [1,0,1,0,2,0,1,0,1]; // The preset "X"
|
|
break;
|
|
case 'Full':
|
|
presetArray = [2,2,2,2,2,2,2,2,2]; // The preset "Full"
|
|
break;
|
|
}
|
|
|
|
// Obtains the buttons to click as a NodeList
|
|
const buttons = document.querySelector('.bm-highlight-grid')?.childNodes ?? [];
|
|
|
|
// For each button...
|
|
for (let buttonIndex = 0; buttonIndex < buttons.length; buttonIndex++) {
|
|
|
|
const button = buttons[buttonIndex]; // Gets the current button to check
|
|
|
|
// Gets the state of the button as a number
|
|
let buttonState = button.dataset['status'];
|
|
buttonState = (buttonState != 'Disabled') ? ((buttonState != 'Incorrect') ? 2 : 1) : 0;
|
|
|
|
// Finds the difference between the preset and the button
|
|
let buttonStateDelta = presetArray[buttonIndex] - buttonState;
|
|
|
|
// Since there is no difference, the button matches, so we skip it
|
|
if (buttonStateDelta == 0) {continue;}
|
|
|
|
// Makes the difference positive
|
|
buttonStateDelta += (buttonStateDelta < 0) ? 3 : 0;
|
|
|
|
/** At this point, these are the possible options:
|
|
* 1. The preset is zero and the button is two (-2) so we need to click once
|
|
* 2. The preset is one and the button is two (-1) so we need to click twice
|
|
* 3. The preset is one ahead of the button (1) so we need to click once
|
|
* 4. The preset is two ahead of the button (2) so we need to click twice
|
|
* Due to the addition of three in the line above, options 1 & 3 combine, and options 2 & 4 combine.
|
|
* Now the only options we have are:
|
|
* 1. If (1) then click once
|
|
* 2. If (2) then click twice
|
|
* Also due to the addition of three in the line above, our two options are POSITIVE numbers
|
|
*/
|
|
|
|
button.click(); // Clicks once
|
|
|
|
// Clicks a second time if needed
|
|
if (buttonStateDelta == 2) {
|
|
|
|
// For 0.2 seconds, or when the button is NOT disabled, wait for 10 milliseconds before attempting to continue
|
|
for (let timeWaited = 0; timeWaited < 200; timeWaited += 10) {
|
|
if (!button.disabled) {break;} // Breaks early once the button is enabled
|
|
await sleep(10);
|
|
}
|
|
|
|
button.click(); // Clicks again
|
|
}
|
|
}
|
|
|
|
// For each preset...
|
|
for (const button of presetButtons) {
|
|
button.disabled = false; // Re-enables the button
|
|
}
|
|
}
|
|
|
|
/** Build the "template" category of settings window
|
|
* @since 0.91.68
|
|
* @see WindowSettings#buildTemplate
|
|
*/
|
|
buildTemplate() {
|
|
|
|
this.window = this.addDiv({'class': 'bm-container'})
|
|
.addHeader(2, {'textContent': 'Pixel Highlight'}).buildElement()
|
|
.addHr().buildElement()
|
|
.addDiv({'class': 'bm-container', 'style': 'margin-left: 1.5ch;'})
|
|
.addCheckbox({'textContent': 'Template creation should skip transparent tiles'}, (instance, label, checkbox) => {
|
|
checkbox.checked = !this.userSettings?.flags?.includes('hl-noSkip'); // Makes the checkbox match the last stored user setting
|
|
checkbox.onchange = (event) => this.toggleFlag('hl-noSkip', !event.target.checked); // If the user wants to skip, then the checkbox is NOT checked
|
|
}).buildElement()
|
|
.addCheckbox({'innerHTML': 'Experimental: Template creation should <em>aggressively</em> skip transparent tiles'}, (instance, label, checkbox) => {
|
|
checkbox.checked = this.userSettings?.flags?.includes('hl-agSkip'); // Makes the checkbox match the last stored user setting
|
|
checkbox.onchange = (event) => this.toggleFlag('hl-agSkip', event.target.checked); // If the user wants to aggressively skip, then the checkbox is checked
|
|
}).buildElement()
|
|
.buildElement()
|
|
.buildElement()
|
|
}
|
|
}</code></pre>
|
|
</article>
|
|
</section>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<br class="clear">
|
|
|
|
<footer>
|
|
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Mar 17 2026 01:31:43 GMT+0000 (Coordinated Universal Time) using the Minami theme.
|
|
</footer>
|
|
|
|
<script>prettyPrint();</script>
|
|
<script src="scripts/linenumber.js"></script>
|
|
</body>
|
|
</html>
|