mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
rivers creator dialog
This commit is contained in:
parent
c5698c5a11
commit
8bbfe6dd2c
7 changed files with 165 additions and 64 deletions
|
|
@ -1674,6 +1674,12 @@ rect.fillRect {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
div.editorLine {
|
||||
margin: 0.2em 0;
|
||||
padding: 0 0.2em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
#emblemDownloadControl > input {
|
||||
width: 4.1em;
|
||||
}
|
||||
|
|
|
|||
12
index.html
12
index.html
|
|
@ -1663,6 +1663,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="riverCreator" class="dialog" style="display: none">
|
||||
<div id="riverCreatorBody"></div>
|
||||
<div id="riverCreatorBottom">
|
||||
<button id="riverCreatorComplete" data-tip="Complete river creation" class="icon-check"></button>
|
||||
<button id="riverCreatorCancel" data-tip="Cancel the creation" class="icon-cancel"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="lakeEditor" class="dialog" style="display: none">
|
||||
<div id="lakeBody" style="padding-bottom: .3em">
|
||||
<div>
|
||||
|
|
@ -3223,7 +3231,8 @@
|
|||
|
||||
<div id="riversBottom">
|
||||
<button id="riversOverviewRefresh" data-tip="Refresh the Editor" class="icon-cw"></button>
|
||||
<button id="addNewRiver" data-tip="Add a new river. Hold Shift to add multiple" class="icon-plus"></button>
|
||||
<button id="addNewRiver" data-tip="Automatically add river starting from clicked cell. Hold Shift to add multiple" class="icon-plus"></button>
|
||||
<button id="riverCreateNew" data-tip="Create new river selecting river cells" class="icon-map-pin"></button>
|
||||
<button id="riversBasinHighlight" data-tip="Toggle basin highlight mode" class="icon-sitemap"></button>
|
||||
<button id="riversExport" data-tip="Save rivers-related data as a text file (.csv)" class="icon-download"></button>
|
||||
<button id="riversRemoveAll" data-tip="Remove all rivers" class="icon-trash"></button>
|
||||
|
|
@ -4218,6 +4227,7 @@
|
|||
<script defer src="modules/ui/coastline-editor.js"></script>
|
||||
<script defer src="modules/ui/labels-editor.js"></script>
|
||||
<script defer src="modules/ui/rivers-editor.js"></script>
|
||||
<script defer src="modules/ui/rivers-creator.js"></script>
|
||||
<script defer src="modules/ui/relief-editor.js"></script>
|
||||
<script defer src="modules/ui/religions-editor.js"></script>
|
||||
<script defer src="modules/ui/markers-editor.js"></script>
|
||||
|
|
|
|||
|
|
@ -96,10 +96,7 @@ function showMapTooltip(point, e, i, g) {
|
|||
const land = pack.cells.h[i] >= 20;
|
||||
|
||||
// specific elements
|
||||
if (group === "armies") {
|
||||
tip(e.target.parentNode.dataset.name + ". Click to edit");
|
||||
return;
|
||||
}
|
||||
if (group === "armies") return tip(e.target.parentNode.dataset.name + ". Click to edit");
|
||||
|
||||
if (group === "emblems" && e.target.tagName === "use") {
|
||||
const parent = e.target.parentNode;
|
||||
|
|
@ -123,14 +120,11 @@ function showMapTooltip(point, e, i, g) {
|
|||
if (riversOverview.offsetParent) highlightEditorLine(riversOverview, river, 5000);
|
||||
return;
|
||||
}
|
||||
if (group === "routes") {
|
||||
tip("Click to edit the Route");
|
||||
return;
|
||||
}
|
||||
if (group === "terrain") {
|
||||
tip("Click to edit the Relief Icon");
|
||||
return;
|
||||
}
|
||||
|
||||
if (group === "routes") return tip("Click to edit the Route");
|
||||
|
||||
if (group === "terrain") return tip("Click to edit the Relief Icon");
|
||||
|
||||
if (subgroup === "burgLabels" || subgroup === "burgIcons") {
|
||||
const burg = +path[path.length - 10].dataset.id;
|
||||
const b = pack.burgs[burg];
|
||||
|
|
@ -139,50 +133,25 @@ function showMapTooltip(point, e, i, g) {
|
|||
if (burgsOverview.offsetParent) highlightEditorLine(burgsOverview, burg, 5000);
|
||||
return;
|
||||
}
|
||||
if (group === "labels") {
|
||||
tip("Click to edit the Label");
|
||||
return;
|
||||
}
|
||||
if (group === "markers") {
|
||||
tip("Click to edit the Marker");
|
||||
return;
|
||||
}
|
||||
if (group === "labels") return tip("Click to edit the Label");
|
||||
|
||||
if (group === "markers") return tip("Click to edit the Marker");
|
||||
|
||||
if (group === "ruler") {
|
||||
const tag = e.target.tagName;
|
||||
const className = e.target.getAttribute("class");
|
||||
if (tag === "circle" && className === "edge") {
|
||||
tip("Drag to adjust. Hold Ctrl and drag to add a point. Click to remove the point");
|
||||
return;
|
||||
}
|
||||
if (tag === "circle" && className === "control") {
|
||||
tip("Drag to adjust. Hold Shifta and drag to keep axial direction. Click to remove the point");
|
||||
return;
|
||||
}
|
||||
if (tag === "circle") {
|
||||
tip("Drag to adjust the measurer");
|
||||
return;
|
||||
}
|
||||
if (tag === "polyline") {
|
||||
tip("Click on drag to add a control point");
|
||||
return;
|
||||
}
|
||||
if (tag === "path") {
|
||||
tip("Drag to move the measurer");
|
||||
return;
|
||||
}
|
||||
if (tag === "text") {
|
||||
tip("Drag to move, click to remove the measurer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (subgroup === "burgIcons") {
|
||||
tip("Click to edit the Burg");
|
||||
return;
|
||||
}
|
||||
if (subgroup === "burgLabels") {
|
||||
tip("Click to edit the Burg");
|
||||
return;
|
||||
if (tag === "circle" && className === "edge") return tip("Drag to adjust. Hold Ctrl and drag to add a point. Click to remove the point");
|
||||
if (tag === "circle" && className === "control") return tip("Drag to adjust. Hold Shift and drag to keep axial direction. Click to remove the point");
|
||||
if (tag === "circle") return tip("Drag to adjust the measurer");
|
||||
if (tag === "polyline") return tip("Click on drag to add a control point");
|
||||
if (tag === "path") return tip("Drag to move the measurer");
|
||||
if (tag === "text") return tip("Drag to move, click to remove the measurer");
|
||||
}
|
||||
|
||||
if (subgroup === "burgIcons") return tip("Click to edit the Burg");
|
||||
|
||||
if (subgroup === "burgLabels") return tip("Click to edit the Burg");
|
||||
|
||||
if (group === "lakes" && !land) {
|
||||
const lakeId = +e.target.dataset.f;
|
||||
const name = pack.features[lakeId]?.name;
|
||||
|
|
@ -190,20 +159,16 @@ function showMapTooltip(point, e, i, g) {
|
|||
tip(`${fullName} lake. Click to edit`);
|
||||
return;
|
||||
}
|
||||
if (group === "coastline") {
|
||||
tip("Click to edit the coastline");
|
||||
return;
|
||||
}
|
||||
if (group === "coastline") return tip("Click to edit the coastline");
|
||||
|
||||
if (group === "zones") {
|
||||
const zone = path[path.length - 8];
|
||||
tip(zone.dataset.description);
|
||||
if (zonesEditor.offsetParent) highlightEditorLine(zonesEditor, zone.id, 5000);
|
||||
return;
|
||||
}
|
||||
if (group === "ice") {
|
||||
tip("Click to edit the Ice");
|
||||
return;
|
||||
}
|
||||
|
||||
if (group === "ice") return tip("Click to edit the Ice");
|
||||
|
||||
// covering elements
|
||||
if (layerIsOn("togglePrec") && land) tip("Annual Precipitation: " + getFriendlyPrecipitation(i));
|
||||
|
|
|
|||
120
modules/ui/rivers-creator.js
Normal file
120
modules/ui/rivers-creator.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
"use strict";
|
||||
function createRiver() {
|
||||
if (customization) return;
|
||||
closeDialogs();
|
||||
if (!layerIsOn("toggleRivers")) toggleRivers();
|
||||
|
||||
document.getElementById("toggleCells").dataset.forced = +!layerIsOn("toggleCells");
|
||||
if (!layerIsOn("toggleCells")) toggleCells();
|
||||
|
||||
tip("Click to add river point, click again to remove", true);
|
||||
debug.append("g").attr("id", "controlCells");
|
||||
viewbox.style("cursor", "crosshair").on("click", onCellClick);
|
||||
|
||||
createRiver.cells = [];
|
||||
const body = document.getElementById("riverCreatorBody");
|
||||
|
||||
$("#riverCreator").dialog({
|
||||
title: "Create River",
|
||||
resizable: false,
|
||||
position: {my: "left top", at: "left+10 top+10", of: "#map"},
|
||||
close: closeRiverCreator
|
||||
});
|
||||
|
||||
if (modules.createRiver) return;
|
||||
modules.createRiver = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("riverCreatorComplete").addEventListener("click", addRiver);
|
||||
document.getElementById("riverCreatorCancel").addEventListener("click", () => $("#riverCreator").dialog("close"));
|
||||
body.addEventListener("click", function (ev) {
|
||||
const el = ev.target;
|
||||
const cl = el.classList;
|
||||
const cell = +el.parentNode.dataset.cell;
|
||||
if (cl.contains("editFlux")) pack.cells.fl[cell] = +el.value;
|
||||
else if (cl.contains("icon-trash-empty")) removeCell(cell);
|
||||
});
|
||||
|
||||
function onCellClick() {
|
||||
const cell = findCell(...d3.mouse(this));
|
||||
|
||||
if (createRiver.cells.includes(cell)) removeCell(cell);
|
||||
else addCell(cell);
|
||||
}
|
||||
|
||||
function addCell(cell) {
|
||||
createRiver.cells.push(cell);
|
||||
drawCells(createRiver.cells);
|
||||
|
||||
const flux = pack.cells.fl[cell];
|
||||
const line = `<div class="editorLine" data-cell="${cell}">
|
||||
<span>Cell ${cell}</span>
|
||||
<span data-tip="Set flux affects river width" style="margin-left: 0.4em">Flux</span>
|
||||
<input type="number" min=0 value="${flux}" class="editFlux" style="width: 5em"/>
|
||||
<span data-tip="Remove the cell" class="icon-trash-empty pointer"></span>
|
||||
</div>`;
|
||||
body.innerHTML += line;
|
||||
}
|
||||
|
||||
function removeCell(cell) {
|
||||
createRiver.cells = createRiver.cells.filter(c => c !== cell);
|
||||
drawCells(createRiver.cells);
|
||||
body.querySelector(`div[data-cell='${cell}']`)?.remove();
|
||||
}
|
||||
|
||||
function drawCells(cells) {
|
||||
debug
|
||||
.select("#controlCells")
|
||||
.selectAll(`polygon`)
|
||||
.data(cells)
|
||||
.join("polygon")
|
||||
.attr("points", d => getPackPolygon(d))
|
||||
.attr("class", "current");
|
||||
}
|
||||
|
||||
function addRiver() {
|
||||
const {rivers, cells} = pack;
|
||||
const {addMeandering, getApproximateLength, getWidth, getOffset, getName, getRiverPath} = Rivers;
|
||||
|
||||
const riverId = last(rivers).i + 1;
|
||||
const riverCells = createRiver.cells;
|
||||
|
||||
riverCells.forEach(cell => {
|
||||
if (!cells.r[cell]) cells.r[cell] = riverId;
|
||||
});
|
||||
|
||||
const source = riverCells[0];
|
||||
const mouth = riverCells[riverCells.length - 1];
|
||||
const sourceWidth = 0.05;
|
||||
const widthFactor = 1;
|
||||
|
||||
const meanderedPoints = addMeandering(riverCells);
|
||||
|
||||
const discharge = cells.fl[mouth]; // m3 in second
|
||||
const length = getApproximateLength(meanderedPoints);
|
||||
const width = getWidth(getOffset(discharge, meanderedPoints.length, widthFactor, sourceWidth));
|
||||
const name = getName(mouth);
|
||||
|
||||
rivers.push({i: riverId, source, mouth, discharge, length, width, widthFactor, sourceWidth, parent: riverId, cells: riverCells, basin: riverId, name, type: "River"});
|
||||
|
||||
// render river
|
||||
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
|
||||
viewbox
|
||||
.select("#rivers")
|
||||
.append("path")
|
||||
.attr("id", "river" + riverId)
|
||||
.attr("d", getRiverPath(meanderedPoints, widthFactor, sourceWidth));
|
||||
|
||||
editRiver(riverId);
|
||||
}
|
||||
|
||||
function closeRiverCreator() {
|
||||
debug.select("#controlCells").remove();
|
||||
restoreDefaultEvents();
|
||||
clearMainTip();
|
||||
|
||||
const forced = +document.getElementById("toggleCells").dataset.forced;
|
||||
document.getElementById("toggleCells").dataset.forced = 0;
|
||||
if (forced && layerIsOn("toggleCells")) toggleCells();
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ function editRiver(id) {
|
|||
$("#riverEditor").dialog({
|
||||
title: "Edit River",
|
||||
resizable: false,
|
||||
position: {my: "left+40 center", at: "center", of: "svg", collision: "fit"},
|
||||
position: {my: "left top", at: "left+10 top+10", of: "#map"},
|
||||
close: closeRiverEditor
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ function overviewRivers() {
|
|||
// add listeners
|
||||
document.getElementById("riversOverviewRefresh").addEventListener("click", riversOverviewAddLines);
|
||||
document.getElementById("addNewRiver").addEventListener("click", toggleAddRiver);
|
||||
document.getElementById("riverCreateNew").addEventListener("click", createRiver);
|
||||
document.getElementById("riversBasinHighlight").addEventListener("click", toggleBasinsHightlight);
|
||||
document.getElementById("riversExport").addEventListener("click", downloadRiversData);
|
||||
document.getElementById("riversRemoveAll").addEventListener("click", triggerAllRiversRemove);
|
||||
|
|
|
|||
|
|
@ -531,8 +531,7 @@ function toggleAddRiver() {
|
|||
|
||||
function addRiverOnClick() {
|
||||
const {cells, rivers} = pack;
|
||||
const point = d3.mouse(this);
|
||||
let i = findCell(point[0], point[1]);
|
||||
let i = findCell(...d3.mouse(this));
|
||||
|
||||
if (cells.r[i]) return tip("There is already a river here", false, "error");
|
||||
if (cells.h[i] < 20) return tip("Cannot create river in water cell", false, "error");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue