From cf92a65ea1a591c36a42341d3d18c4cc4515182e Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 01:50:12 +0300 Subject: [PATCH 1/6] heightmap editor - insulate feature --- index.html | 21 +-- modules/heightmap-generator.js | 31 ++-- modules/heightmap-templates.js | 18 ++- modules/ui/heightmap-editor.js | 255 +++++++++++++++++---------------- 4 files changed, 184 insertions(+), 141 deletions(-) diff --git a/index.html b/index.html index 2a5e9214..214bfa9e 100644 --- a/index.html +++ b/index.html @@ -2951,14 +2951,15 @@
- - - - - - - - + + + + + + + + +
@@ -6110,7 +6111,7 @@ - + @@ -6140,7 +6141,7 @@ - + diff --git a/modules/heightmap-generator.js b/modules/heightmap-generator.js index 0723a34a..0f77e770 100644 --- a/modules/heightmap-generator.js +++ b/modules/heightmap-generator.js @@ -26,7 +26,7 @@ window.HeightmapGenerator = (function () { // load heightmap into image and render to canvas const img = new Image(); img.src = `./heightmaps/${input.value}.png`; - img.onload = function () { + img.onload = () => { ctx.drawImage(img, 0, 0, cellsX, cellsY); const imageData = ctx.getImageData(0, 0, cellsX, cellsY); assignColorsToHeight(imageData.data); @@ -61,6 +61,7 @@ window.HeightmapGenerator = (function () { if (a1 === "Range") return addRange(a2, a3, a4, a5); if (a1 === "Trough") return addTrough(a2, a3, a4, a5); if (a1 === "Strait") return addStrait(a2, a3); + if (a1 === "Insulate") return insulate(a2); if (a1 === "Add") return modify(a3, +a2, 1); if (a1 === "Multiply") return modify(a3, 0, +a2); if (a1 === "Smooth") return smooth(a2); @@ -100,7 +101,7 @@ window.HeightmapGenerator = (function () { if (cells === 100000) return 0.93; } - const addHill = function (count, height, rangeX, rangeY) { + const addHill = (count, height, rangeX, rangeY) => { count = getNumberInRange(count); const power = getBlobPower(); while (count > 0) { @@ -137,7 +138,7 @@ window.HeightmapGenerator = (function () { } }; - const addPit = function (count, height, rangeX, rangeY) { + const addPit = (count, height, rangeX, rangeY) => { count = getNumberInRange(count); while (count > 0) { addOnePit(); @@ -173,7 +174,7 @@ window.HeightmapGenerator = (function () { } }; - const addRange = function (count, height, rangeX, rangeY) { + const addRange = (count, height, rangeX, rangeY) => { count = getNumberInRange(count); const power = getLinePower(); while (count > 0) { @@ -259,7 +260,7 @@ window.HeightmapGenerator = (function () { } }; - const addTrough = function (count, height, rangeX, rangeY) { + const addTrough = (count, height, rangeX, rangeY) => { count = getNumberInRange(count); const power = getLinePower(); while (count > 0) { @@ -354,7 +355,7 @@ window.HeightmapGenerator = (function () { } }; - const addStrait = function (width, direction = "vertical") { + const addStrait = (width, direction = "vertical") => { width = Math.min(getNumberInRange(width), grid.cellsX / 3); if (width < 1 && P(width)) return; const used = new Uint8Array(cells.h.length); @@ -407,7 +408,7 @@ window.HeightmapGenerator = (function () { } }; - const modify = function (range, add, mult, power) { + const modify = (range, add, mult, power) => { const min = range === "land" ? 20 : range === "all" ? 0 : +range.split("-")[0]; const max = range === "land" || range === "all" ? 100 : +range.split("-")[1]; const isLand = min === 20; @@ -422,14 +423,26 @@ window.HeightmapGenerator = (function () { }); }; - const smooth = function (fr = 2, add = 0) { + const smooth = (fr = 2, add = 0) => { cells.h = cells.h.map((h, i) => { const a = [h]; cells.c[i].forEach(c => a.push(cells.h[c])); + if (fr === 1) return d3.mean(a) + add; return lim((h * (fr - 1) + d3.mean(a) + add) / fr); }); }; + const insulate = (fr = 2) => { + const power = fr * 2; + cells.h = cells.h.map((h, i) => { + const [x, y] = p[i]; + const nx = (2 * x) / graphWidth - 1; + const ny = (2 * y) / graphHeight - 1; + const distance = (1 - nx ** power) * (1 - ny ** power); // 1 is center, 0 is edge + return h * distance; + }); + }; + function getPointInRange(range, length) { if (typeof range !== "string") { ERROR && console.error("Range should be a string"); @@ -449,5 +462,5 @@ window.HeightmapGenerator = (function () { } } - return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify}; + return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, insulate}; })(); diff --git a/modules/heightmap-templates.js b/modules/heightmap-templates.js index bd371e10..0266ce39 100644 --- a/modules/heightmap-templates.js +++ b/modules/heightmap-templates.js @@ -119,7 +119,6 @@ window.HeightmapTemplates = (function () { Hill 3-4 60-85 20-80 0-5 Hill 3-4 60-85 20-80 95-100`; - const oldWorld = `Hill 4-6 20-40 15-85 30-45 Hill 3-7 20-40 15-85 55-70 Strait 2-7 vertical 0 0 @@ -170,5 +169,20 @@ window.HeightmapTemplates = (function () { Strait 3-7 vertical 0 0 Trough 1-2 40-50 45-65 45-65`; - return {volcano, highIsland, lowIsland, continents, archipelago, atoll, mediterranean, peninsula, peninsula, pangea, isthmus, shattered, taklamakan, oldWorld}; + return { + volcano, + highIsland, + lowIsland, + continents, + archipelago, + atoll, + mediterranean, + peninsula, + peninsula, + pangea, + isthmus, + shattered, + taklamakan, + oldWorld + }; })(); diff --git a/modules/ui/heightmap-editor.js b/modules/ui/heightmap-editor.js index fae944f3..8e11965b 100644 --- a/modules/ui/heightmap-editor.js +++ b/modules/ui/heightmap-editor.js @@ -34,19 +34,19 @@ function editHeightmap() { modules.editHeightmap = true; // add listeners - document.getElementById("paintBrushes").addEventListener("click", openBrushesPanel); - document.getElementById("applyTemplate").addEventListener("click", openTemplateEditor); - document.getElementById("convertImage").addEventListener("click", openImageConverter); - document.getElementById("heightmapPreview").addEventListener("click", toggleHeightmapPreview); - document.getElementById("heightmap3DView").addEventListener("click", changeViewMode); - document.getElementById("finalizeHeightmap").addEventListener("click", finalizeHeightmap); - document.getElementById("renderOcean").addEventListener("click", mockHeightmap); - document.getElementById("templateUndo").addEventListener("click", () => restoreHistory(edits.n - 1)); - document.getElementById("templateRedo").addEventListener("click", () => restoreHistory(edits.n + 1)); + byId("paintBrushes").on("click", openBrushesPanel); + byId("applyTemplate").on("click", openTemplateEditor); + byId("convertImage").on("click", openImageConverter); + byId("heightmapPreview").on("click", toggleHeightmapPreview); + byId("heightmap3DView").on("click", changeViewMode); + byId("finalizeHeightmap").on("click", finalizeHeightmap); + byId("renderOcean").on("click", mockHeightmap); + byId("templateUndo").on("click", () => restoreHistory(edits.n - 1)); + byId("templateRedo").on("click", () => restoreHistory(edits.n + 1)); function enterHeightmapEditMode(type) { editHeightmap.layers = Array.from(mapLayers.querySelectorAll("li:not(.buttonoff)")).map(node => node.id); // store layers preset - editHeightmap.layers.forEach(l => document.getElementById(l).click()); // turn off all layers + editHeightmap.layers.forEach(l => byId(l).click()); // turn off all layers customization = 1; closeDialogs(); @@ -113,7 +113,7 @@ function editHeightmap() { if (tooltip.dataset.main) showMainTip(); // move radius circle if drag mode is active - const pressed = document.getElementById("brushesButtons").querySelector("button.pressed"); + const pressed = byId("brushesButtons").querySelector("button.pressed"); if (!pressed) return; moveCircle(p[0], p[1], brushRadius.valueAsNumber, "#333"); } @@ -137,7 +137,7 @@ function editHeightmap() { function finalizeHeightmap() { if (viewbox.select("#heights").selectAll("*").size() < 200) return tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error"); - if (document.getElementById("imageConverter").offsetParent) return tip("Please exit the Image Conversion mode first", null, "error"); + if (byId("imageConverter").offsetParent) return tip("Please exit the Image Conversion mode first", null, "error"); delete window.edits; // remove global variable redo.disabled = templateRedo.disabled = true; @@ -145,7 +145,7 @@ function editHeightmap() { customization = 0; customizationMenu.style.display = "none"; - if (document.getElementById("options").querySelector(".tab > button.active").id === "toolsTab") toolsContent.style.display = "block"; + if (byId("options").querySelector(".tab > button.active").id === "toolsTab") toolsContent.style.display = "block"; layersPreset.disabled = false; exitCustomization.style.display = "none"; // hide finalize button restoreDefaultEvents(); @@ -153,8 +153,8 @@ function editHeightmap() { closeDialogs(); resetZoom(); - if (document.getElementById("preview")) document.getElementById("preview").remove(); - if (document.getElementById("canvas3d")) enterStandardView(); + if (byId("preview")) byId("preview").remove(); + if (byId("canvas3d")) enterStandardView(); const mode = heightmapEditMode.innerHTML; if (mode === "erase") regenerateErasedData(); @@ -163,7 +163,7 @@ function editHeightmap() { // restore initial layers //viewbox.select("#heights").remove(); - document.getElementById("heights").remove(); + byId("heights").remove(); turnButtonOff("toggleHeight"); document .getElementById("mapLayers") @@ -501,8 +501,8 @@ function editHeightmap() { redo.disabled = templateRedo.disabled = true; if (!noStat) { updateStatistics(); - if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened - if (document.getElementById("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened + if (byId("preview")) drawHeightmapPreview(); // update heightmap preview if opened + if (byId("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened } } @@ -516,8 +516,8 @@ function editHeightmap() { mockHeightmap(); updateStatistics(); - if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened - if (document.getElementById("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened + if (byId("preview")) drawHeightmapPreview(); // update heightmap preview if opened + if (byId("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened } // restart edits from 1st step @@ -543,31 +543,31 @@ function editHeightmap() { modules.openBrushesPanel = true; // add listeners - document.getElementById("brushesButtons").addEventListener("click", e => toggleBrushMode(e)); - document.getElementById("changeOnlyLand").addEventListener("click", e => changeOnlyLandClick(e)); - document.getElementById("undo").addEventListener("click", () => restoreHistory(edits.n - 1)); - document.getElementById("redo").addEventListener("click", () => restoreHistory(edits.n + 1)); - document.getElementById("rescaleShow").addEventListener("click", () => { - document.getElementById("modifyButtons").style.display = "none"; - document.getElementById("rescaleSection").style.display = "block"; + byId("brushesButtons").on("click", e => toggleBrushMode(e)); + byId("changeOnlyLand").on("click", e => changeOnlyLandClick(e)); + byId("undo").on("click", () => restoreHistory(edits.n - 1)); + byId("redo").on("click", () => restoreHistory(edits.n + 1)); + byId("rescaleShow").on("click", () => { + byId("modifyButtons").style.display = "none"; + byId("rescaleSection").style.display = "block"; }); - document.getElementById("rescaleHide").addEventListener("click", () => { - document.getElementById("modifyButtons").style.display = "block"; - document.getElementById("rescaleSection").style.display = "none"; + byId("rescaleHide").on("click", () => { + byId("modifyButtons").style.display = "block"; + byId("rescaleSection").style.display = "none"; }); - document.getElementById("rescaler").addEventListener("change", e => rescale(e.target.valueAsNumber)); - document.getElementById("rescaleCondShow").addEventListener("click", () => { - document.getElementById("modifyButtons").style.display = "none"; - document.getElementById("rescaleCondSection").style.display = "block"; + byId("rescaler").on("change", e => rescale(e.target.valueAsNumber)); + byId("rescaleCondShow").on("click", () => { + byId("modifyButtons").style.display = "none"; + byId("rescaleCondSection").style.display = "block"; }); - document.getElementById("rescaleCondHide").addEventListener("click", () => { - document.getElementById("modifyButtons").style.display = "block"; - document.getElementById("rescaleCondSection").style.display = "none"; + byId("rescaleCondHide").on("click", () => { + byId("modifyButtons").style.display = "block"; + byId("rescaleCondSection").style.display = "none"; }); - document.getElementById("rescaleExecute").addEventListener("click", rescaleWithCondition); - document.getElementById("smoothHeights").addEventListener("click", smoothAllHeights); - document.getElementById("disruptHeights").addEventListener("click", disruptAllHeights); - document.getElementById("brushClear").addEventListener("click", startFromScratch); + byId("rescaleExecute").on("click", rescaleWithCondition); + byId("smoothHeights").on("click", smoothAllHeights); + byId("disruptHeights").on("click", disruptAllHeights); + byId("brushClear").on("click", startFromScratch); function exitBrushMode() { const pressed = document.querySelector("#brushesButtons > button.pressed"); @@ -576,7 +576,7 @@ function editHeightmap() { viewbox.style("cursor", "default").on(".drag", null); removeCircle(); - document.getElementById("brushesSliders").style.display = "none"; + byId("brushesSliders").style.display = "none"; } const dragBrushThrottled = throttle(dragBrush, 100); @@ -586,7 +586,7 @@ function editHeightmap() { return; } exitBrushMode(); - document.getElementById("brushesSliders").style.display = "block"; + byId("brushesSliders").style.display = "block"; e.target.classList.add("pressed"); viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragBrushThrottled)); } @@ -644,21 +644,15 @@ function editHeightmap() { const land = changeOnlyLand.checked; grid.cells.h = grid.cells.h.map(h => (land && (h < 20 || h + v < 20) ? h : lim(h + v))); updateHeightmap(); - document.getElementById("rescaler").value = 0; + byId("rescaler").value = 0; } function rescaleWithCondition() { const range = rescaleLower.value + "-" + rescaleHigher.value; const operator = conditionSign.value; const operand = rescaleModifier.valueAsNumber; - if (Number.isNaN(operand)) { - tip("Operand should be a number", false, "error"); - return; - } - if ((operator === "add" || operator === "subtract") && !Number.isInteger(operand)) { - tip("Operand should be an integer", false, "error"); - return; - } + if (Number.isNaN(operand)) return tip("Operand should be a number", false, "error"); + if ((operator === "add" || operator === "subtract") && !Number.isInteger(operand)) return tip("Operand should be an integer", false, "error"); if (operator === "multiply") HeightmapGenerator.modify(range, 0, operand, 0); else if (operator === "divide") HeightmapGenerator.modify(range, 0, 1 / operand, 0); @@ -697,7 +691,7 @@ function editHeightmap() { function openTemplateEditor() { if ($("#templateEditor").is(":visible")) return; - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); $("#templateEditor").dialog({ title: "Template Editor", @@ -713,7 +707,7 @@ function editHeightmap() { $("#templateBody").sortable({items: "> div", handle: ".icon-resize-vertical", containment: "#templateBody", axis: "y"}); // add listeners - body.addEventListener("click", function (ev) { + body.on("click", function (ev) { const el = ev.target; if (el.classList.contains("icon-check")) { el.classList.remove("icon-check"); @@ -734,27 +728,27 @@ function editHeightmap() { } }); - document.getElementById("templateTools").addEventListener("click", e => addStepOnClick(e)); - document.getElementById("templateSelect").addEventListener("change", e => selectTemplate(e)); - document.getElementById("templateRun").addEventListener("click", executeTemplate); - document.getElementById("templateSave").addEventListener("click", downloadTemplate); - document.getElementById("templateLoad").addEventListener("click", () => templateToLoad.click()); - document.getElementById("templateToLoad").addEventListener("change", function () { + byId("templateTools").on("click", addStepOnClick); + byId("templateSelect").on("change", selectTemplate); + byId("templateRun").on("click", executeTemplate); + byId("templateSave").on("click", downloadTemplate); + byId("templateLoad").on("click", () => templateToLoad.click()); + byId("templateToLoad").on("change", function () { uploadFile(this, uploadTemplate); }); function addStepOnClick(e) { if (e.target.tagName !== "BUTTON") return; - const type = e.target.id.replace("template", ""); - document.getElementById("templateBody").dataset.changed = 1; + const type = e.target.dataset.type; + byId("templateBody").dataset.changed = 1; addStep(type); } function addStep(type, count, dist, arg4, arg5) { - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); body.insertAdjacentHTML("beforeend", getStepHTML(type, count, dist, arg4, arg5)); const elDist = body.querySelector("div:last-child").querySelector(".templateDist"); - if (elDist) elDist.addEventListener("change", setRange); + if (elDist) elDist.on("change", setRange); if (dist && elDist && elDist.tagName === "SELECT") { for (const o of elDist.options) { if (o.value === dist) elDist.value = dist; @@ -769,36 +763,56 @@ function editHeightmap() { } function getStepHTML(type, count, arg3, arg4, arg5) { - const Trash = ``; - const Hide = `
`; - const Reorder = ``; - const common = `
${Hide}
${type}
${Trash}${Reorder}`; + const Trash = /* html */ ``; + const Hide = /* html */ `
`; + const Reorder = /* html */ ``; + const common = /* html */ `
${Hide}
${type}
${Trash}${Reorder}`; - const TempY = `y:`; - const TempX = `x:`; - const Height = `h:`; - const Count = `n:`; - const blob = `${common}${TempY}${TempX}${Height}${Count}
`; + const TempY = /* html */ `y:`; + + const TempX = /* html */ `x:`; + + const Height = /* html */ `h:`; + + const Count = /* html */ `n:`; + + if (type === "Hill" || type === "Pit" || type === "Range" || type === "Trough") return /* html */ `${common}${TempY}${TempX}${Height}${Count}
`; - if (type === "Hill" || type === "Pit" || type === "Range" || type === "Trough") return blob; if (type === "Strait") - return `${common}d:w:
`; + return /* html */ `${common}d: + w:
`; + + if (type === "Insulate") + return /* html */ `${common}f:`; + if (type === "Add") - return `${common}to:v:`; + return /* html */ `${common}to: + v:`; + if (type === "Multiply") - return `${common}to:v:`; + return /* html */ `${common}to: + v:`; + if (type === "Smooth") - return `${common}f:`; + return /* html */ `${common}f:`; } function setRange(event) { @@ -813,7 +827,7 @@ function editHeightmap() { } function selectTemplate(e) { - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); const steps = body.querySelectorAll("div").length; const changed = +body.getAttribute("data-changed"); const template = e.target.value; @@ -839,7 +853,7 @@ function editHeightmap() { } function changeTemplate(template) { - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); body.setAttribute("data-changed", 0); body.innerHTML = ""; @@ -856,11 +870,11 @@ function editHeightmap() { } function executeTemplate() { - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); const steps = body.querySelectorAll("#templateBody > div"); if (!steps.length) return; - const {addHill, addPit, addRange, addTrough, addStrait, modify, smooth} = HeightmapGenerator; + const {addHill, addPit, addRange, addTrough, addStrait, modify, smooth, insulate} = HeightmapGenerator; grid.cells.h = new Uint8Array(grid.cells.i.length); // clean all heights for (const step of steps) { @@ -878,6 +892,7 @@ function editHeightmap() { else if (type === "Range") addRange(count, height, x, y); else if (type === "Trough") addTrough(count, height, x, y); else if (type === "Strait") addStrait(count, dist); + else if (type === "Insulate") insulate(+count); else if (type === "Add") modify(dist, +count, 1); else if (type === "Multiply") modify(dist, 0, +count); else if (type === "Smooth") smooth(+count); @@ -887,12 +902,12 @@ function editHeightmap() { updateStatistics(); mockHeightmap(); - if (document.getElementById("preview")) drawHeightmapPreview(); // update heightmap preview if opened - if (document.getElementById("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened + if (byId("preview")) drawHeightmapPreview(); // update heightmap preview if opened + if (byId("canvas3d")) ThreeD.redraw(); // update 3d heightmap preview if opened } function downloadTemplate() { - const body = document.getElementById("templateBody"); + const body = byId("templateBody"); body.dataset.changed = 0; const steps = body.querySelectorAll("#templateBody > div"); if (!steps.length) return; @@ -977,18 +992,18 @@ function editHeightmap() { })(); // add listeners - document.getElementById("convertImageLoad").addEventListener("click", () => imageToLoad.click()); - document.getElementById("imageToLoad").addEventListener("change", loadImage); - document.getElementById("convertAutoLum").addEventListener("click", () => autoAssing("lum")); - document.getElementById("convertAutoHue").addEventListener("click", () => autoAssing("hue")); - document.getElementById("convertAutoFMG").addEventListener("click", () => autoAssing("scheme")); - document.getElementById("convertColorsButton").addEventListener("click", setConvertColorsNumber); - document.getElementById("convertComplete").addEventListener("click", applyConversion); - document.getElementById("convertCancel").addEventListener("click", cancelConversion); - document.getElementById("convertOverlay").addEventListener("input", function () { + byId("convertImageLoad").on("click", () => imageToLoad.click()); + byId("imageToLoad").on("change", loadImage); + byId("convertAutoLum").on("click", () => autoAssing("lum")); + byId("convertAutoHue").on("click", () => autoAssing("hue")); + byId("convertAutoFMG").on("click", () => autoAssing("scheme")); + byId("convertColorsButton").on("click", setConvertColorsNumber); + byId("convertComplete").on("click", applyConversion); + byId("convertCancel").on("click", cancelConversion); + byId("convertOverlay").on("input", function () { setOverlayOpacity(this.value); }); - document.getElementById("convertOverlayNumber").addEventListener("input", function () { + byId("convertOverlayNumber").on("input", function () { setOverlayOpacity(this.value); }); @@ -1012,7 +1027,7 @@ function editHeightmap() { document.body.appendChild(img); img.onload = function () { - const ctx = document.getElementById("canvas").getContext("2d"); + const ctx = byId("canvas").getContext("2d"); ctx.drawImage(img, 0, 0, graphWidth, graphHeight); heightsFromImage(+convertColors.value); resetZoom(); @@ -1023,7 +1038,7 @@ function editHeightmap() { } function heightsFromImage(count) { - const sourceImage = document.getElementById("canvas"); + const sourceImage = byId("canvas"); const sampleCanvas = document.createElement("canvas"); sampleCanvas.width = grid.cellsX; sampleCanvas.height = grid.cellsY; @@ -1062,7 +1077,7 @@ function editHeightmap() { .attr("class", "color-div") .on("click", colorClicked); - document.getElementById("colorsUnassignedNumber").innerHTML = colors.length; + byId("colorsUnassignedNumber").innerHTML = colors.length; } function mapClicked() { @@ -1119,8 +1134,8 @@ function editHeightmap() { colorsAssigned.appendChild(selectedColor); colorsAssigned.style.display = "block"; - document.getElementById("colorsUnassignedNumber").innerHTML = colorsUnassigned.childElementCount - 2; - document.getElementById("colorsAssignedNumber").innerHTML = colorsAssigned.childElementCount - 2; + byId("colorsUnassignedNumber").innerHTML = colorsUnassigned.childElementCount - 2; + byId("colorsAssignedNumber").innerHTML = colorsAssigned.childElementCount - 2; } } @@ -1187,7 +1202,7 @@ function editHeightmap() { colorsAssigned.style.display = "block"; colorsUnassigned.style.display = "none"; - document.getElementById("colorsAssignedNumber").innerHTML = colorsAssigned.childElementCount - 2; + byId("colorsAssignedNumber").innerHTML = colorsAssigned.childElementCount - 2; } function setConvertColorsNumber() { @@ -1203,7 +1218,7 @@ function editHeightmap() { function setOverlayOpacity(v) { convertOverlay.value = convertOverlayNumber.value = v; - document.getElementById("canvas").style.opacity = v; + byId("canvas").style.opacity = v; } function applyConversion() { @@ -1230,10 +1245,10 @@ function editHeightmap() { } function restoreImageConverterState() { - const canvas = document.getElementById("canvas"); + const canvas = byId("canvas"); if (canvas) canvas.remove(); - const image = document.getElementById("imageToConvert"); + const image = byId("imageToConvert"); if (image) image.remove(); d3.select("#imageConverter").selectAll("div.color-div").remove(); @@ -1275,8 +1290,8 @@ function editHeightmap() { } function toggleHeightmapPreview() { - if (document.getElementById("preview")) { - document.getElementById("preview").remove(); + if (byId("preview")) { + byId("preview").remove(); return; } const preview = document.createElement("canvas"); @@ -1284,13 +1299,13 @@ function editHeightmap() { preview.width = grid.cellsX; preview.height = grid.cellsY; document.body.insertBefore(preview, optionsContainer); - preview.addEventListener("mouseover", () => tip("Heightmap preview. Click to download a screen-sized image")); - preview.addEventListener("click", downloadPreview); + preview.on("mouseover", () => tip("Heightmap preview. Click to download a screen-sized image")); + preview.on("click", downloadPreview); drawHeightmapPreview(); } function drawHeightmapPreview() { - const ctx = document.getElementById("preview").getContext("2d"); + const ctx = byId("preview").getContext("2d"); const imageData = ctx.createImageData(grid.cellsX, grid.cellsY); grid.cells.h.forEach((height, i) => { @@ -1306,7 +1321,7 @@ function editHeightmap() { } function downloadPreview() { - const preview = document.getElementById("preview"); + const preview = byId("preview"); const dataURL = preview.toDataURL("image/png"); const img = new Image(); From a16e609696deb3c172f43bb98814be642a9f8b06 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 19:46:42 +0300 Subject: [PATCH 2/6] Fractious template --- index.css | 2 +- index.html | 33 ++++---- modules/heightmap-generator.js | 19 +++-- modules/heightmap-templates.js | 141 ++++++++++++++------------------- modules/ui/heightmap-editor.js | 58 ++++++++------ 5 files changed, 124 insertions(+), 129 deletions(-) diff --git a/index.css b/index.css index f070c939..1b7a983b 100644 --- a/index.css +++ b/index.css @@ -922,7 +922,7 @@ fieldset { display: inline-block; } -body button.noicon { +#templateTools > button { width: 1.8em; height: 1.6em; margin: 1px; diff --git a/index.html b/index.html index 214bfa9e..32c30825 100644 --- a/index.html +++ b/index.html @@ -1292,7 +1292,7 @@ - + @@ -1302,6 +1302,7 @@ + @@ -2932,13 +2933,13 @@ `; - if (type === "Insulate") - return /* html */ `${common}f:`; + if (type === "Mask") + return /* html */ `${common}f:`; if (type === "Add") return /* html */ `${common}to:`; + return /* html */ `${common}f:`; } function setRange(event) { @@ -870,34 +878,36 @@ function editHeightmap() { } function executeTemplate() { - const body = byId("templateBody"); - const steps = body.querySelectorAll("#templateBody > div"); + const steps = byId("templateBody").querySelectorAll("#templateBody > div"); if (!steps.length) return; - const {addHill, addPit, addRange, addTrough, addStrait, modify, smooth, insulate} = HeightmapGenerator; grid.cells.h = new Uint8Array(grid.cells.i.length); // clean all heights + const seed = byId("templateSeed").value; + if (seed) Math.random = aleaPRNG(seed); + restartHistory(); + for (const step of steps) { if (step.style.opacity === "0.5") continue; - const type = step.dataset.type; const count = step.querySelector(".templateCount")?.value || ""; const height = step.querySelector(".templateHeight")?.value || ""; const dist = step.querySelector(".templateDist")?.value || null; const x = step.querySelector(".templateX")?.value || null; const y = step.querySelector(".templateY")?.value || null; + const type = step.dataset.type; - if (type === "Hill") addHill(count, height, x, y); - else if (type === "Pit") addPit(count, height, x, y); - else if (type === "Range") addRange(count, height, x, y); - else if (type === "Trough") addTrough(count, height, x, y); - else if (type === "Strait") addStrait(count, dist); - else if (type === "Insulate") insulate(+count); - else if (type === "Add") modify(dist, +count, 1); - else if (type === "Multiply") modify(dist, 0, +count); - else if (type === "Smooth") smooth(+count); + if (type === "Hill") HeightmapGenerator.addHill(count, height, x, y); + else if (type === "Pit") HeightmapGenerator.addPit(count, height, x, y); + else if (type === "Range") HeightmapGenerator.addRange(count, height, x, y); + else if (type === "Trough") HeightmapGenerator.addTrough(count, height, x, y); + else if (type === "Strait") HeightmapGenerator.addStrait(count, dist); + else if (type === "Mask") HeightmapGenerator.mask(+count); + else if (type === "Add") HeightmapGenerator.modify(dist, +count, 1); + else if (type === "Multiply") HeightmapGenerator.modify(dist, 0, +count); + else if (type === "Smooth") HeightmapGenerator.smooth(+count); - updateHistory("noStat"); // update history every step + updateHistory("noStat"); // update history on every step } updateStatistics(); From 63db344e0610487a974108b462c8415b1fd4cb98 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 20:55:32 +0300 Subject: [PATCH 3/6] fix style --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 32c30825..20704075 100644 --- a/index.html +++ b/index.html @@ -107,7 +107,7 @@ } } - + @@ -1759,13 +1759,13 @@
- Depressions filling max iterations: +
Depressions filling max iterations:
- Depression depth threshold: +
Depression depth threshold:
@@ -2989,7 +2989,7 @@ > From 2713f6bfda97f140fdedfcde554f9ad481a760dc Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 22:43:06 +0300 Subject: [PATCH 4/6] inversion tool --- index.html | 1 + modules/heightmap-generator.js | 26 +++++- modules/heightmap-templates.js | 8 +- modules/ui/heightmap-editor.js | 145 +++++++++++++++++++++------------ 4 files changed, 122 insertions(+), 58 deletions(-) diff --git a/index.html b/index.html index 20704075..577b4140 100644 --- a/index.html +++ b/index.html @@ -2959,6 +2959,7 @@ + diff --git a/modules/heightmap-generator.js b/modules/heightmap-generator.js index 80eecde1..762350ce 100644 --- a/modules/heightmap-generator.js +++ b/modules/heightmap-generator.js @@ -365,8 +365,8 @@ window.HeightmapGenerator = (function () { const endX = vert ? Math.floor(graphWidth - startX - graphWidth * 0.1 + Math.random() * graphWidth * 0.2) : graphWidth - 5; const endY = vert ? graphHeight - 5 : Math.floor(graphHeight - startY - graphHeight * 0.1 + Math.random() * graphHeight * 0.2); - const start = findGridCell(startX, startY), - end = findGridCell(endX, endY); + const start = findGridCell(startX, startY); + const end = findGridCell(endX, endY); let range = getRange(start, end); const query = []; @@ -446,6 +446,26 @@ window.HeightmapGenerator = (function () { }); }; + const invert = (count, axes) => { + if (!P(count)) return; + + const invertX = axes !== "y"; + const invertY = axes !== "x"; + const {cellsX, cellsY} = grid; + + const inverted = cells.h.map((h, i) => { + const x = i % cellsX; + const y = Math.floor(i / cellsX); + + const nx = invertX ? cellsX - x - 1 : x; + const ny = invertY ? cellsY - y - 1 : y; + const invertedI = nx + ny * cellsX; + return cells.h[invertedI]; + }); + + cells.h = inverted; + }; + function getPointInRange(range, length) { if (typeof range !== "string") { ERROR && console.error("Range should be a string"); @@ -465,5 +485,5 @@ window.HeightmapGenerator = (function () { } } - return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, mask}; + return {generate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, mask, invert}; })(); diff --git a/modules/heightmap-templates.js b/modules/heightmap-templates.js index baff264c..7e0cd20c 100644 --- a/modules/heightmap-templates.js +++ b/modules/heightmap-templates.js @@ -69,7 +69,7 @@ window.HeightmapTemplates = (function () { Hill .5 30-50 25-35 30-70 Smooth 1 0 0 0 Multiply 0.2 25-100 0 0 - Hill .5 10-20 50-55 48-52`; + Hill 0.5 10-20 50-55 48-52`; const mediterranean = `Range 4-6 30-80 0-100 0-10 Range 4-6 30-80 0-100 90-100 @@ -90,7 +90,8 @@ window.HeightmapTemplates = (function () { Hill 3-4 3-5 5-95 80-100 Hill 1-2 3-5 5-95 40-60 Trough 5-6 10-25 5-95 5-95 - Smooth 3 0 0 0`; + Smooth 3 0 0 0 + Invert 0.4 both 0 0`; const pangea = `Hill 1-2 25-40 15-50 0-10 Hill 1-2 5-40 50-85 0-10 @@ -113,7 +114,8 @@ window.HeightmapTemplates = (function () { Trough 4-8 15-30 10-50 20-40 Trough 4-8 15-30 30-70 40-60 Trough 4-8 15-30 50-90 60-80 - Trough 4-8 15-30 70-100 80-100`; + Trough 4-8 15-30 70-100 80-100 + Invert 0.25 x 0 0`; const shattered = `Hill 8 35-40 15-85 30-70 Trough 10-20 40-50 5-95 5-95 diff --git a/modules/ui/heightmap-editor.js b/modules/ui/heightmap-editor.js index 14963745..12d8b283 100644 --- a/modules/ui/heightmap-editor.js +++ b/modules/ui/heightmap-editor.js @@ -613,9 +613,7 @@ function editHeightmap() { const power = brushPower.valueAsNumber; const interpolate = d3.interpolateRound(power, 1); const land = changeOnlyLand.checked; - function lim(v) { - return minmax(v, land ? 20 : 0, 100); - } + const lim = v => minmax(v, land ? 20 : 0, 100); const h = grid.cells.h; const brush = document.querySelector("#brushesButtons > button.pressed").id; @@ -674,15 +672,10 @@ function editHeightmap() { } function startFromScratch() { - if (changeOnlyLand.checked) { - tip("Not allowed when 'Change only land cells' mode is set", false, "error"); - return; - } + if (changeOnlyLand.checked) return tip("Not allowed when 'Change only land cells' mode is set", false, "error"); const someHeights = grid.cells.h.some(h => h); - if (!someHeights) { - tip("Heightmap is already cleared, please do not click twice if not required", false, "error"); - return; - } + if (!someHeights) return tip("Heightmap is already cleared, please do not click twice if not required", false, "error"); + grid.cells.h = new Uint8Array(grid.cells.i.length); viewbox.select("#heights").selectAll("*").remove(); updateHistory(); @@ -752,19 +745,21 @@ function editHeightmap() { } function addStep(type, count, dist, arg4, arg5) { - const body = byId("templateBody"); - body.insertAdjacentHTML("beforeend", getStepHTML(type, count, dist, arg4, arg5)); - const elDist = body.querySelector("div:last-child").querySelector(".templateDist"); - if (elDist) elDist.on("change", setRange); - if (dist && elDist && elDist.tagName === "SELECT") { - for (const o of elDist.options) { - if (o.value === dist) elDist.value = dist; + const $body = byId("templateBody"); + $body.insertAdjacentHTML("beforeend", getStepHTML(type, count, dist, arg4, arg5)); + + const $elDist = $body.querySelector("div:last-child > span > .templateDist"); + if ($elDist) $elDist.on("change", setRange); + + if (dist && $elDist && $elDist.tagName === "SELECT") { + for (const option of $elDist.options) { + if (option.value === dist) $elDist.value = dist; } - if (elDist.value !== dist) { + if ($elDist.value !== dist) { const opt = document.createElement("option"); opt.value = opt.innerHTML = dist; - elDist.add(opt); - elDist.value = dist; + $elDist.add(opt); + $elDist.value = dist; } } } @@ -775,52 +770,97 @@ function editHeightmap() { const Reorder = /* html */ ``; const common = /* html */ `
${Hide}
${type}
${Trash}${Reorder}`; - const TempY = /* html */ `y:`; + const TempY = /* html */ `y: + + `; - const TempX = /* html */ `x:`; + const TempX = /* html */ `x: + + `; - const Height = /* html */ `h:`; + const Height = /* html */ `h: + + `; - const Count = /* html */ `n:`; + const Count = /* html */ `n: + + `; if (type === "Hill" || type === "Pit" || type === "Range" || type === "Trough") return /* html */ `${common}${TempY}${TempX}${Height}${Count}
`; if (type === "Strait") - return /* html */ `${common}d: - w:`; + return /* html */ `${common} + d: + + + w: + + + `; + + if (type === "Invert") + return /* html */ `${common} + by: + + + n: + + + `; if (type === "Mask") - return /* html */ `${common}f:`; + return /* html */ `${common} + f: + + + `; if (type === "Add") - return /* html */ `${common}to: - v:`; + return /* html */ `${common} + to: + + + v: + + + `; if (type === "Multiply") - return /* html */ `${common}to: - v:`; + return /* html */ `${common} + to: + + + v: + + + `; if (type === "Smooth") - return /* html */ `${common}f:`; + return /* html */ `${common} + f: + + + `; } function setRange(event) { @@ -903,6 +943,7 @@ function editHeightmap() { else if (type === "Trough") HeightmapGenerator.addTrough(count, height, x, y); else if (type === "Strait") HeightmapGenerator.addStrait(count, dist); else if (type === "Mask") HeightmapGenerator.mask(+count); + else if (type === "Invert") HeightmapGenerator.invert(+count, dist); else if (type === "Add") HeightmapGenerator.modify(dist, +count, 1); else if (type === "Multiply") HeightmapGenerator.modify(dist, 0, +count); else if (type === "Smooth") HeightmapGenerator.smooth(+count); From ceba329bd622878c7b45874bbaefc8c06f116a45 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 23:54:59 +0300 Subject: [PATCH 5/6] pump version to 1.83.0 --- index.html | 2 +- versioning.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 577b4140..e6883666 100644 --- a/index.html +++ b/index.html @@ -2977,7 +2977,7 @@
- + diff --git a/versioning.js b/versioning.js index ee337422..bc450f65 100644 --- a/versioning.js +++ b/versioning.js @@ -1,7 +1,7 @@ "use strict"; // version and caching control -const version = "1.82.05"; // generator version, update each time +const version = "1.83.0"; // generator version, update each time { document.title += " v" + version; From 91c6a5aaec7fc621793c521578e2cc9c06720b09 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 21 May 2022 23:58:44 +0300 Subject: [PATCH 6/6] add changes to updateWindow --- versioning.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning.js b/versioning.js index bc450f65..54c53146 100644 --- a/versioning.js +++ b/versioning.js @@ -28,6 +28,8 @@ const version = "1.83.0"; // generator version, update each time
    Latest changes: +
  • New heightmap template: Fractious
  • +
  • Template Editor: mask and invert tools
  • Ability to install the App
  • 14 new default fonts
  • Caching for faster startup
  • @@ -35,8 +37,6 @@ const version = "1.83.0"; // generator version, update each time
  • Resample tool by Goteguru
  • Pre-defined heightmaps
  • Advanced notes editor
  • -
  • Zones editor: filter by type
  • -
  • Color picker: new hatchings

Join our Discord server and Reddit community to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.