diff --git a/modules/dynamic/heightmap-selection.js b/modules/dynamic/heightmap-selection.js index 4e05c2c9..7b7a0412 100644 --- a/modules/dynamic/heightmap-selection.js +++ b/modules/dynamic/heightmap-selection.js @@ -83,7 +83,7 @@ export function open() { function appendStyleSheet() { const styles = /* css */ ` - .heightmap-selection { + div.dialog > div.heightmap-selection { width: 70vw; height: 70vh; } @@ -110,9 +110,13 @@ function appendStyleSheet() { .heightmap-selection_options { display: grid; - grid-template-columns: repeat(2, minmax(50%, 200px)); - grid-row-gap: 6px; + grid-template-columns: 2fr 1fr; justify-items: start; + } + + .heightmap-selection_options > div:first-child { + display: grid; + grid-template-columns: 1fr 1fr; align-items: center; } @@ -177,20 +181,25 @@ function insertEditorHtml() {

Options

- - +
+ + +
+
+ Color scheme + +
- Color scheme - + + +
- -
@@ -243,6 +252,9 @@ function addListeners() { byId("heightmapSelectionRenderOcean").on("change", redrawAll); byId("heightmapSelectionColorScheme").on("change", redrawAll); + byId("heightmapSelectionRedrawPreview").on("click", redrawAll); + byId("heightmapSelectionEditTemplates").on("click", confirmHeightmapEdit); + byId("heightmapSelectionImportHeightmap").on("click", confirmHeightmapEdit); } function getSelected() { @@ -318,3 +330,14 @@ function redrawAll() { else drawPrecreatedHeightmap(id); } } + +function confirmHeightmapEdit() { + const tool = this.dataset.tool; + + confirmationDialog({ + title: this.dataset.tip, + message: "Opening the tool will erase the current map. Are you sure you want to proceed?", + confirm: "Continue", + onConfirm: () => editHeightmap({mode: "erase", tool}) + }); +} diff --git a/modules/ui/heightmap-editor.js b/modules/ui/heightmap-editor.js index f30004c1..69d98184 100644 --- a/modules/ui/heightmap-editor.js +++ b/modules/ui/heightmap-editor.js @@ -1,35 +1,13 @@ "use strict"; -function editHeightmap() { - void (function selectEditMode() { - alertMessage.innerHTML = /* html */ `Heightmap is a core element on which all other data (rivers, burgs, states etc) is based. So the best edit approach is to - erase the secondary data and let the system automatically regenerate it on edit completion. -

Erase mode also allows you Convert an Image into a heightmap or use Template Editor.

-

You can keep the data, but you won't be able to change the coastline.

-

- Try risk mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors. -

-

Please save the map before editing the heightmap!

-

Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.

`; - - $("#alert").dialog({ - resizable: false, - title: "Edit Heightmap", - width: "28em", - buttons: { - Erase: () => enterHeightmapEditMode("erase"), - Keep: () => enterHeightmapEditMode("keep"), - Risk: () => enterHeightmapEditMode("risk"), - Cancel: function () { - $(this).dialog("close"); - } - } - }); - })(); - +function editHeightmap(options) { + const {mode, tool} = options || {}; restartHistory(); viewbox.insert("g", "#terrs").attr("id", "heights"); + if (!mode) showModeDialog(); + else enterHeightmapEditMode(mode); + if (modules.editHeightmap) return; modules.editHeightmap = true; @@ -44,35 +22,66 @@ function editHeightmap() { byId("templateUndo").on("click", () => restoreHistory(edits.n - 1)); byId("templateRedo").on("click", () => restoreHistory(edits.n + 1)); - function enterHeightmapEditMode(type) { + function showModeDialog() { + alertMessage.innerHTML = /* html */ `Heightmap is a core element on which all other data (rivers, burgs, states etc) is based. So the best edit approach is to + erase the secondary data and let the system automatically regenerate it on edit completion. +

Erase mode also allows you Convert an Image into a heightmap or use Template Editor.

+

You can keep the data, but you won't be able to change the coastline.

+

Try risk mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors.

+

Please save the map before editing the heightmap!

+

Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.

`; + + $("#alert").dialog({ + resizable: false, + title: "Edit Heightmap", + width: "28em", + buttons: { + Erase: () => enterHeightmapEditMode("erase"), + Keep: () => enterHeightmapEditMode("keep"), + Risk: () => enterHeightmapEditMode("risk"), + Cancel: function () { + $(this).dialog("close"); + } + } + }); + } + + function enterHeightmapEditMode(mode) { editHeightmap.layers = Array.from(mapLayers.querySelectorAll("li:not(.buttonoff)")).map(node => node.id); // store layers preset editHeightmap.layers.forEach(l => byId(l).click()); // turn off all layers customization = 1; closeDialogs(); tip('Heightmap edit mode is active. Click on "Exit Customization" to finalize the heightmap', true); - customizationMenu.style.display = "block"; - toolsContent.style.display = "none"; - heightmapEditMode.innerHTML = type; - if (type === "erase") { + byId("options") + .querySelectorAll(".tabcontent") + .forEach(tabcontent => { + tabcontent.style.display = "none"; + }); + byId("options").querySelector(".tab > .active").classList.remove("active"); + byId("customizationMenu").style.display = "block"; + byId("toolsTab").classList.add("active"); + heightmapEditMode.innerHTML = mode; + + if (mode === "erase") { undraw(); changeOnlyLand.checked = false; - } else if (type === "keep") { + } else if (mode === "keep") { viewbox.selectAll("#landmass, #lakes").style("display", "none"); changeOnlyLand.checked = true; - } else if (type === "risk") { + } else if (mode === "risk") { defs.selectAll("#land, #water").selectAll("path").remove(); viewbox.selectAll("#coastline path, #lakes path, #oceanLayers path").remove(); changeOnlyLand.checked = false; } // show convert and template buttons for Erase mode only - applyTemplate.style.display = type === "erase" ? "inline-block" : "none"; - convertImage.style.display = type === "erase" ? "inline-block" : "none"; + applyTemplate.style.display = mode === "erase" ? "inline-block" : "none"; + convertImage.style.display = mode === "erase" ? "inline-block" : "none"; // hide erosion checkbox if mode is Keep - allowErosionBox.style.display = type === "keep" ? "none" : "inline-block"; + allowErosionBox.style.display = mode === "keep" ? "none" : "inline-block"; // show finalize button if (!sessionStorage.getItem("noExitButtonAnimation")) { @@ -95,27 +104,30 @@ function editHeightmap() { .style("transform", "scale(1)"); } else exitCustomization.style.display = "block"; - openBrushesPanel(); turnButtonOn("toggleHeight"); layersPreset.value = "heightmap"; layersPreset.disabled = true; mockHeightmap(); viewbox.on("touchmove mousemove", moveCursor); + + if (tool === "templateEditor") openTemplateEditor(); + else if (tool === "imageConverter") openImageConverter(); + else openBrushesPanel(); } function moveCursor() { - const p = d3.mouse(this), - cell = findGridCell(p[0], p[1]); - heightmapInfoX.innerHTML = rn(p[0]); - heightmapInfoY.innerHTML = rn(p[1]); + const [x, y] = d3.mouse(this); + const cell = findGridCell(x, y); + heightmapInfoX.innerHTML = rn(x); + heightmapInfoY.innerHTML = rn(y); heightmapInfoCell.innerHTML = cell; - heightmapInfoHeight.innerHTML = /* html */ `${grid.cells.h[cell]} (${getHeight(grid.cells.h[cell])})`; + heightmapInfoHeight.innerHTML = `${grid.cells.h[cell]} (${getHeight(grid.cells.h[cell])})`; if (tooltip.dataset.main) showMainTip(); // move radius circle if drag mode is active const pressed = byId("brushesButtons").querySelector("button.pressed"); if (!pressed) return; - moveCircle(p[0], p[1], brushRadius.valueAsNumber, "#333"); + moveCircle(x, y, brushRadius.valueAsNumber, "#333"); } // get user-friendly (real-world) height value from map data