diff --git a/betterSettings.js b/betterSettings.js deleted file mode 100644 index 8baba711..00000000 --- a/betterSettings.js +++ /dev/null @@ -1,291 +0,0 @@ -const settingType = { - COLOR: [0, "#ff0000"], - TEXT: [1, ""], - NUMBER: [2, 0], - BOOLEAN: [3, false], - SELECT: [4, null] -} -class Setting { - constructor (name, storageName, type, disabled = false, defaultValue = null) { - this.tabName = null; - this.name = name; - this.storageName = storageName; - this.type = type[0]; - this.disabled = disabled; - this.defaultValue = defaultValue ?? type[1]; - } - - set(value) { - this.value = value; - const settings = JSON.parse(localStorage.getItem(`${this.tabName}/settings`)) ?? {}; - settings[this.name] = value; - localStorage.setItem(`${this.tabName}/settings`, JSON.stringify(settings)); - } - - update() { - this.value = (JSON.parse(localStorage.getItem(`${this.tabName}/settings`)) ?? {})[this.name] ?? this.defaultValue; - } - - get() { - this.update(); - return this.value; - } - - enable() { - this.disabled = false; - } - - disable() { - this.disabled = true; - } - - #parseColor(colorString) { - if (colorString instanceof Array) return parseColor(colorString[0]); - if (typeof colorString != "string") return "#ffffff"; - if (colorString.startsWith("rgb(")) { - const color = colorString.replace("rgb(", "").replace(")", ""); - return `#${color.split(",").map(a => parseInt(a).toString(16)).join("")}`; - } else { - if (colorString.startsWith("#")) { - const color = colorString.slice(1); - if (color.length == 3) return `#${color.repeat(2)}`; - else if (color.length == 2) return `#${color.repeat(3)}`; - else if (color.length >= 6) return `#${color.slice(0, 6)}`; - else return `#${color}`; - } - } - } - - build() { - const value = this.get(); - const id = "betterSettings/" + this.modName + "/" + this.storageName; - const span = document.createElement("span"); - span.className = "setting-span"; - span.title = 'Default: "' + this.defaultValue + '"' + (this.disabled ? ". This setting is disabled." : ""); - span.innerText = this.name + " "; - const element = document.createElement("input"); - switch (this.type) { - case 0: { - element.type = "color"; - element.disabled = this.disabled; - element.id = id; - element.value = value; - element.onchange = (ev) => { - this.set(this.#parseColor(ev.target.value)); - } - break; - } - case 1: { - element.type = "text"; - element.disabled = this.disabled; - element.id = id; - element.value = value; - element.onchange = (ev) => { - this.set(ev.target.value); - } - break; - } - case 2: { - element.type = "number"; - element.disabled = this.disabled; - element.id = id; - element.value = value; - element.onchange = (ev) => { - this.set(parseFloat(ev.target.value)); - } - break; - } - case 3: { - element.type = "input"; - element.className = "toggleInput"; - element.disabled = this.disabled; - element.id = id; - element.value = value ? "ON" : "OFF"; - element.setAttribute("state", value ? "1" : "0"); - element.onclick = (ev) => { - ev.target.value = ev.target.value == "ON" ? "OFF" : "ON"; - ev.target.setAttribute("state", ev.target.getAttribute("state") == "1" ? "0" : "1"); - this.set(ev.target.value == "ON"); - } - break; - } - } - span.appendChild(element); - return span; - } -} - -class SelectSetting extends Setting { - constructor (name, storageName, values, disabled = false, defaultValue = null) { - super(name, storageName, settingType.SELECT, disabled, defaultValue ?? values[0][1]); - this.values = values; - } - - build() { - const value = this.get(); - const id = "betterSettings/" + this.modName + "/" + this.storageName; - let selected = false; - const span = document.createElement("span"); - span.className = "setting-span"; - span.title = "Default: " + this.defaultValue; - span.innerText = this.name; - const element = document.createElement("select"); - element.id = id; - for (const val of this.values) { - const option = document.createElement("option"); - option.value = val[0]; - option.innerText = val[1]; - if (val[0] == value && !selected) { - option.selected = true; - selected = true; - } - element.appendChild(option); - } - element.onchange = (ev) => { - this.set(ev.target.value); - } - span.appendChild(element); - return span; - } -} - -class SettingsTab { - constructor (tabName) { - this.categories = new Map(); - this.registry = new Map(); - this.tabName = tabName; - } - - registerSetting(setting, category = "General") { - setting.tabName = this.tabName.toLowerCase().replace(/ /, "_"); - setting.update(); - if (this.categories.has(category)) this.categories.get(category).push(setting); - else this.categories.set(category, [setting]); - this.registry.set(setting.storageName, setting); - } - - registerSettings(category = "General", ...settings) { - for (const setting of settings) { - this.registerSetting(setting, category); - } - } - - set(name, value) { - this.registry.get(name)?.set(value); - } - - get(name) { - return this.registry.get(name)?.get(); - } - - build() { - const result = document.createElement("div"); - for (const key of this.categories.keys()) { - const category = document.createElement("div"); - const title = document.createElement("span"); - title.innerText = key; - title.className = "betterSettings-categoryTitle"; - category.appendChild(title); - for (const setting of this.categories.get(key)) { - if (setting instanceof Setting) category.appendChild(setting.build()); - } - result.append(category, document.createElement("br")); - } - return result; - } -} - -class SettingsManager { - constructor () { - this.settings = new Map(); - } - - registerTab(settingsTab) { - this.settings.set(settingsTab.tabName, settingsTab); - } - - getSettings() { - return this.settings; - } -} - -const settingsManager = new SettingsManager(); -{ -const injectCss = () => { - const css = `.modSelectSettingsButton { - padding: 10px; - cursor: pointer; - } - .modSelectSettingsButton[current=true] { - background-color: rgb(71, 71, 71); - } - .modSelectSettingsButton:hover { - background-color: rgb(51, 51, 51); - } - #modSelectControls { - margin-bottom: 10px; - position: relative; - display: flex; - overflow-x: scroll; - } - .betterSettings-categoryTitle { - font-size: 1.25em; - }`; - const style = document.createElement("style"); - style.innerHTML = css; - document.head.appendChild(style); -} - -const inject = () => { - const settingsMenu = document.getElementById("settingsMenu"); - const menuText = settingsMenu.querySelector(".menuText"); - const menuTextChildren = menuText.children; - const generalDiv = document.createElement("div"); - generalDiv.id = "betterSettings/div/general"; - while (menuTextChildren.length > 0) { - generalDiv.appendChild(menuTextChildren[0]); - } - menuText.appendChild(generalDiv); - const controls = document.createElement("div"); - controls.id = "modSelectControls"; - const generalButton = document.createElement("button"); - generalButton.setAttribute("current", true); - generalButton.id = "betterSettings/button/general"; - generalButton.className = "modSelectSettingsButton"; - generalButton.innerText = "General"; - generalButton.onclick = (ev) => { - for (const element of controls.children) { - element.setAttribute("current", false); - document.getElementById(element.id.replace("button", "div")).style.display = "none"; - } - ev.target.setAttribute("current", true); - document.getElementById("betterSettings/div/general").style.display = ""; - } - controls.appendChild(generalButton); - const wrapper = document.createElement("div"); - wrapper.appendChild(generalDiv); - for (const mod of settingsManager.getSettings().keys()) { - const modButton = document.createElement("button"); - modButton.setAttribute("current", false); - modButton.id = "betterSettings/button/" + mod; - modButton.className = "modSelectSettingsButton"; - modButton.innerText = mod; - modButton.onclick = (ev) => { - for (const element of controls.children) { - element.setAttribute("current", false); - document.getElementById(element.id.replace("button", "div")).style.display = "none"; - } - ev.target.setAttribute("current", true); - document.getElementById("betterSettings/div/" + mod).style.display = ""; - } - controls.appendChild(modButton); - const modDiv = document.createElement("div"); - modDiv.style.display = "none"; - modDiv.id = "betterSettings/div/" + mod; - modDiv.appendChild(settingsManager.getSettings().get(mod).build()); - wrapper.appendChild(modDiv); - } - menuText.append(controls, wrapper); -} -runAfterLoadList.push(inject, injectCss); -} \ No newline at end of file diff --git a/editTools.js b/editTools.js deleted file mode 100644 index 94ec191f..00000000 --- a/editTools.js +++ /dev/null @@ -1,612 +0,0 @@ -if (!enabledMods.includes("mods/betterSettings.js")) { enabledMods.unshift("mods/betterSettings.js"); localStorage.setItem("enabledMods", JSON.stringify(enabledMods)); window.location.reload() }; - -const settingsTab = new SettingsTab("Edit tools"); - -const element = new Setting("Element", "element", settingType.TEXT, false, "wall"); -const replace = new Setting("Replace pixels", "replace", settingType.BOOLEAN, false, true); - -const filter = new Setting("Filter", "filter", settingType.BOOLEAN, false, false); -const filteredElement = new Setting("Filtered Element", "filterElement", settingType.TEXT, false, ""); - -const transparentSelection = new Setting("Transparent selection", "transparentSelection", settingType.BOOLEAN, false, true); - -settingsTab.registerSettings("Box tools", element, replace); -settingsTab.registerSettings("Filter settings", filter, filteredElement); -settingsTab.registerSettings("Selection settings", transparentSelection); - -settingsManager.registerTab(settingsTab); - -runAfterLoadList.push(() => { - // the game doesn't load without the setTimeout - setTimeout(() => { - document.getElementById("elementButton-select").style.backgroundColor = "transparent"; - document.getElementById("elementButton-select").style.border = "2px dashed rgba(255, 255, 255, 0.75)"; - document.getElementById("elementButton-select").classList = ["elementButton"]; - }, 1) -}) - -// current selection -let selection_ = { - start: {}, - end: {} -} -// selection position, used for moveSelection -let selectionPosition = {}; -// copy of the selection that is being moved (pixels), used for moveSelection -let selectionMoved = []; -// offsets of the mouse relative to selection position, used for moveSelection -let selectionOffsets = {}; - -// current box, used in box and rectangle -let box = { - start: {}, - end: {} -} - -// whether the next mouseUp even should trigger -let skip = false; -// whether user is currently holding -let holding = false; -// mobile device shift equivalent -let lockSelection = false; - -// current clipboard, used for cutting, copying and pasting -let clipboard = []; - -// createPixel but with color argument -const createPixelColor = (element, x, y, color) => { - const pixel = new Pixel(x, y, element); - pixel.color = color; - currentPixels.push(pixel); - checkUnlock(element); -} - -// replaces a pixel at x, y position with replacement element specified in the settings -const replacePixel = (x, y) => { - if (outOfBounds(x, y)) return; - if (pixelMap[x][y]) { - if (!replace.get()) return; - deletePixel(x, y); - } - createPixel(element.get(), x, y); -} - -// checks whether position pos is in bounds -const inBounds = (bounds, pos) => { - bounds = { - start: { - x: Math.min(bounds.start.x, bounds.end.x), - y: Math.min(bounds.start.y, bounds.end.y) - }, - end: { - x: Math.max(bounds.start.x, bounds.end.x), - y: Math.max(bounds.start.y, bounds.end.y) - } - } - return pos.x >= bounds.start.x && pos.x <= bounds.end.x && pos.y >= bounds.start.y && pos.y <= bounds.end.y; -} - -// generates a selection based on start and end positions -const select = (start, end) => { - const res = []; - for (let i = 0; i <= end.x - start.x; i++) { - res[i] = []; - for (let j = 0; j <= end.y - start.y; j++) { - res[i][j] = pixelMap[i + start.x][j + start.y]; - } - } - return res; -} - -elements.select = { - name: "Select", - category: "editTools", - maxSize: 1, - onMouseDown: () => { - if (outOfBounds(mousePos.x, mousePos.y)) { - skip = true; - return; - } - skip = false; - holding = true; - selection_.start = mousePos; - }, - onMouseUp: () => { - if (skip) return; - selection_.end = mousePos; - if (selection_.start == selection_.end) selection_ = {}; - holding = false; - }, - tool: (_) => {}, - perTick: () => { - if (!selection_) return; - if (holding) { - selection_.end = mousePos; - } - const canvas = document.getElementById("game"); - const ctx = canvas.getContext("2d"); - const start = { - x: Math.round(selection_.start.x * pixelSize), - y: Math.round(selection_.start.y * pixelSize) - } - const end = { - x: Math.round(selection_.end.x * pixelSize), - y: Math.round((selection_.end.y + 1) * pixelSize) - } - const {strokeStyle, lineWidth} = ctx; - ctx.setLineDash([8, 8]); - ctx.lineWidth = 2; - ctx.strokeStyle = "white"; - ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.setLineDash([]); - } -} - -elements.box = { - name: "Box", - category: "editTools", - onMouseDown: () => { - if (outOfBounds(mousePos.x, mousePos.y) || showingMenu) { - skip = true; - return; - } - skip = false; - holding = true; - box.start = mousePos; - }, - onMouseUp: () => { - if (skip) return; - box.end = mousePos; - holding = false; - for (let i = -Math.floor(mouseSize / 2); i < Math.abs(box.start.x - box.end.x) + Math.floor(mouseSize / 2); i++) { - const x = Math.min(box.start.x, box.end.x) + i; - for (let j = -Math.floor(mouseSize / 2); j <= Math.floor(mouseSize / 2); j++) { - replacePixel(x, box.start.y + (box.start.y > box.end.y ? -j : j)); - replacePixel(x, box.end.y + (box.end.y > box.start.y ? -j : j)); - } - } - for (let i = -Math.floor(mouseSize / 2); i <= Math.abs(box.start.y - box.end.y) + Math.floor(mouseSize / 2); i++) { - const y = Math.min(box.start.y, box.end.y) + i; - for (let j = -Math.floor(mouseSize / 2); j <= Math.floor(mouseSize / 2); j++) { - replacePixel(box.start.x + (box.start.x > box.end.x ? -j : j), y); - replacePixel(box.end.x + (box.end.x > box.start.x ? -j : j), y); - } - } - }, - tool: (_) => {}, - perTick: () => { - if (holding) { - if (shiftDown || lockSelection) { - box.end = { - y: mousePos.y, - x: box.start.x + Math.abs(mousePos.y - box.start.y) * (box.start.x > mousePos.x ? -1 : 1) - }; - mousePos = box.end; - } else { - box.end = mousePos; - } - const canvas = document.getElementById("game"); - const ctx = canvas.getContext("2d"); - const start = { - x: Math.round(box.start.x * pixelSize), - y: Math.round(box.start.y * pixelSize) - } - const end = { - x: Math.round(box.end.x * pixelSize), - y: Math.round((box.end.y + 1) * pixelSize) - } - const {strokeStyle, lineWidth} = ctx; - ctx.setLineDash([8, 8]); - ctx.lineWidth = 2; - ctx.strokeStyle = "yellow"; - ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.setLineDash([]); - } - } -} - -elements.cut = { - name: "Cut", - category: "editTools", - maxSize: 0, - tool: (_) => {}, - onSelect: () => { - if (!selection_.start || !selection_.end) return alert("No selection made"); - const selected = select({ - x: Math.min(selection_.start.x, selection_.end.x), - y: Math.min(selection_.start.y, selection_.end.y) - }, { - x: Math.max(selection_.start.x, selection_.end.x), - y: Math.max(selection_.start.y, selection_.end.y) - }) - clipboard = selected; - for (const i of selected) { - for (const pixel of i) { - if (!pixel) continue; - deletePixel(pixel.x, pixel.y); - } - } - selectElement("unknown"); - } -} -elements.copy = { - name: "Copy", - category: "editTools", - maxSize: 0, - tool: (_) => {}, - onSelect: () => { - if (!selection_.start || !selection_.end) return alert("No selection made"); - const selected = select({ - x: Math.min(selection_.start.x, selection_.end.x), - y: Math.min(selection_.start.y, selection_.end.y) - }, { - x: Math.max(selection_.start.x, selection_.end.x), - y: Math.max(selection_.start.y, selection_.end.y) - }) - clipboard = selected; - selectElement("unknown"); - } -} - -elements.selectionMove = { - name: "Move selection", - category: "editTools", - maxSize: 0, - tool: (_) => {}, - onMouseDown: () => { - if (outOfBounds(mousePos.x, mousePos.y)) return; - if (!selection_.start || !selection_.end) return; - if (!inBounds(selection_, mousePos)) return; - selectionOffsets = { - x: mousePos.x - Math.min(selection_.start.x, selection_.end.x), - y: mousePos.y - Math.min(selection_.start.y, selection_.end.y) - } - const selected = select({ - x: Math.min(selection_.start.x, selection_.end.x), - y: Math.min(selection_.start.y, selection_.end.y) - }, { - x: Math.max(selection_.start.x, selection_.end.x), - y: Math.max(selection_.start.y, selection_.end.y) - }) - selectionPosition = { - x: selection_.start.x, - y: selection_.start.y - } - for (const i of selected) { - for (const pixel of i) { - if (!pixel) continue; - deletePixel(pixel.x, pixel.y); - } - } - selectionMoved = selected; - }, - perTick: () => { - const canvas = document.getElementById("game"); - const ctx = canvas.getContext("2d"); - ctx.globalAlpha = 1; - const start = { - x: Math.round(selection_.start.x * pixelSize), - y: Math.round(selection_.start.y * pixelSize) - } - const end = { - x: Math.round(selection_.end.x * pixelSize), - y: Math.round((selection_.end.y + 1) * pixelSize) - } - const {strokeStyle, lineWidth} = ctx; - ctx.setLineDash([8, 8]); - ctx.lineWidth = 2; - ctx.strokeStyle = "white"; - ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.setLineDash([]); - if (!selectionMoved || selectionMoved.length == 0) return; - selectionPosition = { - x: mousePos.x - selectionOffsets.x, - y: mousePos.y - selectionOffsets.y - } - selection_ = { - start: { - x: selectionPosition.x, - y: selectionPosition.y - }, - end: { - x: selectionPosition.x + selectionMoved.length - 1, - y: selectionPosition.y + selectionMoved[0].length - 1 - } - } - ctx.globalAlpha = 0.5; - for (let i = 0; i < selectionMoved.length; i++) { - for (let j = 0; j < selectionMoved[i].length; j++) { - const x = selectionPosition.x + i; - const y = selectionPosition.y + j; - if (!selectionMoved[i][j]) continue; - ctx.globalCompositeOperation = 'destination-over'; - ctx.fillStyle = selectionMoved[i][j].color; - ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize); - } - } - }, - onMouseUp: () => { - if (outOfBounds(mousePos.x, mousePos.y)) return; - for (let i = 0; i < selectionMoved.length; i++) { - for (let j = 0; j < selectionMoved[i].length; j++) { - const x = selectionPosition.x + i; - const y = selectionPosition.y + j; - if (!selectionMoved[i][j] && transparentSelection.get()) continue; - if (pixelMap[x][y]) deletePixel(x, y); - createPixelColor(selectionMoved[i][j].element, x, y, selectionMoved[i][j].color); - } - } - selectionMoved = []; - } -} - -elements.paste = { - name: "Paste", - category: "editTools", - tool: (_) => {}, - maxSize: 1, - onMouseDown: () => { - if (!clipboard) return alert("Nothing left to paste"); - for (let i = 0; i < clipboard.length; i++) { - for (let j = 0; j < clipboard[i].length; j++) { - const x = mousePos.x + i; - const y = mousePos.y + j; - if (outOfBounds(x, y) || (!clipboard[i][j] && transparentSelection.get())) continue; - if (!pixelMap[x][y]) createPixelColor(clipboard[i][j].element, x, y, clipboard[i][j].color); - else { - deletePixel(x, y); - createPixelColor(clipboard[i][j].element, x, y, clipboard[i][j].color); - } - } - } - } -} - -elements.rectangle = { - name: "Rectangle", - category: "editTools", - onMouseDown: () => { - if (outOfBounds(mousePos.x, mousePos.y)) { - skip = true; - return; - } - skip = false; - holding = true; - box.start = mousePos; - }, - onMouseUp: () => { - if (skip) return; - box.end = mousePos; - holding = false; - for (let i = -Math.floor(mouseSize / 2); i <= Math.abs(box.start.x - box.end.x) + Math.floor(mouseSize / 2); i++) { - for (let j = -Math.floor(mouseSize / 2); j <= Math.abs(box.start.y - box.end.y) + Math.floor(mouseSize / 2); j++) { - replacePixel(Math.min(box.start.x, box.end.x) + i, Math.min(box.start.y, box.end.y) + j); - } - } - }, - tool: (_) => {}, - perTick: () => { - if (holding) { - if (shiftDown || lockSelection) { - box.end = { - y: mousePos.y, - x: box.start.x + Math.abs(mousePos.y - box.start.y) * (box.start.x > mousePos.x ? -1 : 1) - }; - mousePos = box.end; - } else { - box.end = mousePos; - } - const canvas = document.getElementById("game"); - const ctx = canvas.getContext("2d"); - const start = { - x: Math.round(box.start.x * pixelSize), - y: Math.round(box.start.y * pixelSize) - } - const end = { - x: Math.round(box.end.x * pixelSize), - y: Math.round((box.end.y + 1) * pixelSize) - } - const {strokeStyle, lineWidth} = ctx; - ctx.setLineDash([8, 8]); - ctx.lineWidth = 2; - ctx.strokeStyle = "yellow"; - ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.setLineDash([]); - } - } -} - -// Ellipse Midpoint Algorithm -// https://stackoverflow.com/questions/15474122/is-there-a-midpoint-ellipse-algorithm -// https://web.archive.org/web/20160305234351/http://geofhagopian.net/sablog/Slog-october/slog-10-25-05.htm -function ellipsePlotPoints(xc, yc, x, y) { - replacePixel(xc + x, yc + y); - replacePixel(xc - x, yc + y); - replacePixel(xc + x, yc - y); - replacePixel(xc - x, yc - y); -} - -function ellipse(xc, yc, w, h) { - const a2 = Math.pow(w, 2); - const b2 = Math.pow(h, 2); - const twoa2 = 2 * a2; - const twob2 = 2 * b2; - let p; - let x = 0; - let y = h; - let px = 0; - let py = twoa2 * y; - - /* Plot the initial point in each quadrant. */ - ellipsePlotPoints(xc, yc, x, y); - - p = Math.round(b2 - (a2 * b) + (0.25 * a2)); - while (px < py) { - x++; - px += twob2; - if (p < 0) p += b2 + px; - else { - y--; - py -= twoa2; - p += b2 + px - py; - } - ellipsePlotPoints(xc, yc, x, y); - } - - p = Math.round(b2 * (x + 0.5) * (x + 0.5) + a2 * (y - 1) * (y - 1) - a2 * b2); - while (y > 0) { - y--; - py -= twoa2; - if (p > 0) p += a2 - py; - else { - x++; - px += twob2; - p += a2 - py + px; - } - ellipsePlotPoints(xc, yc, x, y); - } -} - -elements.ellipse = { - name: "Ellipse", - category: "editTools", - tool: (_) => {}, - maxSize: 1, - onMouseDown: () => { - if (outOfBounds(mousePos.x, mousePos.y)) { - skip = true; - return; - } - skip = false; - holding = true; - box.start = mousePos; - }, - onMouseUp: () => { - if (skip) return; - box.end = mousePos; - holding = false; - const w = Math.abs(box.end.x - box.start.x); - const h = Math.abs(box.end.y - box.start.y); - const x = Math.min(box.start.x, box.end.x) + Math.floor(w / 2); - const y = Math.min(box.start.y, box.end.y) + Math.floor(h / 2); - ellipse(x, y, Math.floor(w / 2), Math.floor(h / 2)); - }, - tool: (_) => {}, - perTick: () => { - if (holding) { - if (shiftDown || lockSelection) { - box.end = { - y: mousePos.y, - x: box.start.x + Math.abs(mousePos.y - box.start.y) * (box.start.x > mousePos.x ? -1 : 1) - }; - mousePos = box.end; - } else { - box.end = mousePos; - } - const canvas = document.getElementById("game"); - const ctx = canvas.getContext("2d"); - const start = { - x: Math.round(box.start.x * pixelSize), - y: Math.round(box.start.y * pixelSize) - } - const end = { - x: Math.round(box.end.x * pixelSize), - y: Math.round((box.end.y + 1) * pixelSize) - } - const {strokeStyle, lineWidth} = ctx; - ctx.setLineDash([8, 8]); - ctx.lineWidth = 2; - ctx.strokeStyle = "yellow"; - ctx.strokeRect(start.x, start.y, end.x - start.x, end.y - start.y); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.setLineDash([]); - } - } -} - -document.addEventListener("mousedown", (ev) => { - if (elements[currentElement].onMouseDown) { - elements[currentElement].onMouseDown(); - } -}) - -// mouse2 overwrite for delete filter -// no mouse1 overwrite for replace functionality, I don't think I should be overwriting such big functions -// maybe in a future update -mouse2Action = (e,mouseX=undefined,mouseY=undefined,startPos) => { - // Erase pixel at mouse position - if (mouseX == undefined && mouseY == undefined) { - var canvas = document.getElementById("game"); - var ctx = canvas.getContext("2d"); - lastPos = mousePos; - mousePos = getMousePos(canvas, e); - var mouseX = mousePos.x; - var mouseY = mousePos.y; - } - // If the current element is "pick" or "lookup", coords = [mouseX,mouseY] - if (currentElement == "pick" || currentElement == "lookup") { - var coords = [[mouseX,mouseY]]; - } - else if (!isMobile) { - startPos = startPos || lastPos - var coords = lineCoords(startPos.x,startPos.y,mouseX,mouseY); - } - else { - var coords = mouseRange(mouseX,mouseY); - } - // For each x,y in coords - for (var i = 0; i < coords.length; i++) { - var x = coords[i][0]; - var y = coords[i][1]; - - if (!isEmpty(x, y)) { - if (outOfBounds(x,y)) { - continue - } - var pixel = pixelMap[x][y]; - // filter - if (filter.get() && pixel.element != filteredElement.get()) continue; - delete pixelMap[x][y]; - // Remove pixel from currentPixels - for (var j = 0; j < currentPixels.length; j++) { - if (currentPixels[j].x == x && currentPixels[j].y == y) { - currentPixels.splice(j, 1); - break; - } - } - } - } -} - -// Mobile check -// https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser -// http://detectmobilebrowsers.com/ -window.mobileAndTabletCheck = () => { - let check = false; - (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); - return check; -}; - -// if user is on mobile, add lock selection tool -if (window.mobileAndTabletCheck()) { - elements.lockSelection = { - name: "Lock selection", - category: "editTools", - tool: (_) => {}, - onSelect: () => { - // unselect so you can click it multiple times - selectElement("unknown"); - document.getElementById("elementButton-lockSelection").innerText = lockSelection ? "Lock selection" : "Unlock selection"; - lockSelection = !lockSelection; - } - } -} \ No newline at end of file