mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
feat: heightmap brushes - linear edit option (1.88.00)
This commit is contained in:
parent
d3ea2df1a2
commit
4a96c24cf3
7 changed files with 194 additions and 85 deletions
|
|
@ -1303,11 +1303,6 @@ div.slider .ui-slider-handle {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#brushPower,
|
|
||||||
#brushRadius {
|
|
||||||
width: 12em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#rescaleHigher,
|
#rescaleHigher,
|
||||||
#rescaleLower,
|
#rescaleLower,
|
||||||
#rescaleModifier {
|
#rescaleModifier {
|
||||||
|
|
|
||||||
42
index.html
42
index.html
|
|
@ -108,7 +108,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<link rel="preload" href="index.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
<link rel="preload" href="index.css?v=1.88.00" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
||||||
<link rel="preload" href="icons.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
<link rel="preload" href="icons.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
||||||
<link rel="preload" href="libs/jquery-ui.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
<link rel="preload" href="libs/jquery-ui.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
||||||
</head>
|
</head>
|
||||||
|
|
@ -3836,6 +3836,12 @@
|
||||||
<path d="m15,63 l15,-13 15,20 15,-20 15,19 15,-14" fill="none" stroke="#000" stroke-width="5" />
|
<path d="m15,63 l15,-13 15,20 15,-20 15,19 15,-14" fill="none" stroke="#000" stroke-width="5" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button id="brushLine" data-tip="Line: select two points to change heights along the line">
|
||||||
|
<svg viewBox="0 -5 100 100" height="1em" width="1.6em">
|
||||||
|
<path d="M0 90 L100 10" fill="none" stroke="#000" stroke-width="7"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="brushesSliders" style="display: none">
|
<div id="brushesSliders" style="display: none">
|
||||||
|
|
@ -3848,6 +3854,7 @@
|
||||||
min="1"
|
min="1"
|
||||||
max="99"
|
max="99"
|
||||||
value="25"
|
value="25"
|
||||||
|
style="width: 13em"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
id="brushRadiusNumber"
|
id="brushRadiusNumber"
|
||||||
|
|
@ -3869,6 +3876,7 @@
|
||||||
min="1"
|
min="1"
|
||||||
max="10"
|
max="10"
|
||||||
value="5"
|
value="5"
|
||||||
|
style="width: 13em"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
id="brushPowerNumber"
|
id="brushPowerNumber"
|
||||||
|
|
@ -3882,6 +3890,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="lineSlider" style="display: none">
|
||||||
|
<div data-tip="Set change power">
|
||||||
|
<div style="width: 3.2em; display: inline-block"><i>Power:</i></div>
|
||||||
|
<input
|
||||||
|
id="linePower"
|
||||||
|
oninput="tip('Line power: '+this.value); linePowerNumber.value = this.value"
|
||||||
|
type="range"
|
||||||
|
min="-100"
|
||||||
|
max="100"
|
||||||
|
value="30"
|
||||||
|
style="width: 13em"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
id="linePowerNumber"
|
||||||
|
oninput="tip('Line power: '+this.value); linePower.value = this.value"
|
||||||
|
type="number"
|
||||||
|
min="-100"
|
||||||
|
max="100"
|
||||||
|
value="30"
|
||||||
|
style="border: 1px solid #d4d4d4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-tip="Allow brush to change only land cells and hence restrict the coastline modification"
|
data-tip="Allow brush to change only land cells and hence restrict the coastline modification"
|
||||||
style="margin-bottom: 0.6em"
|
style="margin-bottom: 0.6em"
|
||||||
|
|
@ -7796,7 +7828,7 @@
|
||||||
<script src="utils/nodeUtils.js"></script>
|
<script src="utils/nodeUtils.js"></script>
|
||||||
<script src="utils/numberUtils.js"></script>
|
<script src="utils/numberUtils.js"></script>
|
||||||
<script src="utils/polyfills.js"></script>
|
<script src="utils/polyfills.js"></script>
|
||||||
<script src="utils/probabilityUtils.js"></script>
|
<script src="utils/probabilityUtils.js?v=1.88.00"></script>
|
||||||
<script src="utils/stringUtils.js"></script>
|
<script src="utils/stringUtils.js"></script>
|
||||||
<script src="utils/languageUtils.js"></script>
|
<script src="utils/languageUtils.js"></script>
|
||||||
<script src="utils/unitUtils.js?v=1.87.00"></script>
|
<script src="utils/unitUtils.js?v=1.87.00"></script>
|
||||||
|
|
@ -7804,7 +7836,7 @@
|
||||||
<script src="modules/voronoi.js"></script>
|
<script src="modules/voronoi.js"></script>
|
||||||
<script src="config/heightmap-templates.js"></script>
|
<script src="config/heightmap-templates.js"></script>
|
||||||
<script src="config/precreated-heightmaps.js"></script>
|
<script src="config/precreated-heightmaps.js"></script>
|
||||||
<script src="modules/heightmap-generator.js"></script>
|
<script src="modules/heightmap-generator.js?v=1.88.00"></script>
|
||||||
<script src="modules/ocean-layers.js?v=1.87.15"></script>
|
<script src="modules/ocean-layers.js?v=1.87.15"></script>
|
||||||
<script src="modules/river-generator.js"></script>
|
<script src="modules/river-generator.js"></script>
|
||||||
<script src="modules/lakes.js"></script>
|
<script src="modules/lakes.js"></script>
|
||||||
|
|
@ -7834,7 +7866,7 @@
|
||||||
<script defer src="modules/ui/editors.js?v=1.87.07"></script>
|
<script defer src="modules/ui/editors.js?v=1.87.07"></script>
|
||||||
<script defer src="modules/ui/tools.js?v=1.87.03"></script>
|
<script defer src="modules/ui/tools.js?v=1.87.03"></script>
|
||||||
<script defer src="modules/ui/world-configurator.js"></script>
|
<script defer src="modules/ui/world-configurator.js"></script>
|
||||||
<script defer src="modules/ui/heightmap-editor.js?v=1.87.10"></script>
|
<script defer src="modules/ui/heightmap-editor.js?v=1.88.00"></script>
|
||||||
<script defer src="modules/ui/provinces-editor.js"></script>
|
<script defer src="modules/ui/provinces-editor.js"></script>
|
||||||
<script defer src="modules/ui/biomes-editor.js"></script>
|
<script defer src="modules/ui/biomes-editor.js"></script>
|
||||||
<script defer src="modules/ui/namesbase-editor.js?v=1.87.10"></script>
|
<script defer src="modules/ui/namesbase-editor.js?v=1.87.10"></script>
|
||||||
|
|
@ -7864,7 +7896,7 @@
|
||||||
<script defer src="modules/ui/markers-editor.js"></script>
|
<script defer src="modules/ui/markers-editor.js"></script>
|
||||||
<script defer src="modules/ui/3d.js"></script>
|
<script defer src="modules/ui/3d.js"></script>
|
||||||
<script defer src="modules/ui/submap.js"></script>
|
<script defer src="modules/ui/submap.js"></script>
|
||||||
<script defer src="modules/ui/hotkeys.js?v=1.87.00"></script>
|
<script defer src="modules/ui/hotkeys.js?v=1.88.00"></script>
|
||||||
<script defer src="modules/coa-renderer.js?v=1.87.08"></script>
|
<script defer src="modules/coa-renderer.js?v=1.87.08"></script>
|
||||||
<script defer src="libs/rgbquant.min.js"></script>
|
<script defer src="libs/rgbquant.min.js"></script>
|
||||||
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
|
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ window.HeightmapGenerator = (function () {
|
||||||
|
|
||||||
const setGraph = graph => {
|
const setGraph = graph => {
|
||||||
const {cellsDesired, cells, points} = graph;
|
const {cellsDesired, cells, points} = graph;
|
||||||
heights = cells.h || createTypedArray({maxValue: 100, length: points.length});
|
heights = cells.h ? Uint8Array.from(cells.h) : createTypedArray({maxValue: 100, length: points.length});
|
||||||
blobPower = getBlobPower(cellsDesired);
|
blobPower = getBlobPower(cellsDesired);
|
||||||
linePower = getLinePower(cellsDesired);
|
linePower = getLinePower(cellsDesired);
|
||||||
grid = graph;
|
grid = graph;
|
||||||
|
|
@ -198,7 +198,8 @@ window.HeightmapGenerator = (function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addRange = (count, height, rangeX, rangeY) => {
|
// fromCell, toCell are options cell ids
|
||||||
|
const addRange = (count, height, rangeX, rangeY, startCell, endCell) => {
|
||||||
count = getNumberInRange(count);
|
count = getNumberInRange(count);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
addOneRange();
|
addOneRange();
|
||||||
|
|
@ -209,6 +210,7 @@ window.HeightmapGenerator = (function () {
|
||||||
const used = new Uint8Array(heights.length);
|
const used = new Uint8Array(heights.length);
|
||||||
let h = lim(getNumberInRange(height));
|
let h = lim(getNumberInRange(height));
|
||||||
|
|
||||||
|
if (rangeX && rangeY) {
|
||||||
// find start and end points
|
// find start and end points
|
||||||
const startX = getPointInRange(rangeX, graphWidth);
|
const startX = getPointInRange(rangeX, graphWidth);
|
||||||
const startY = getPointInRange(rangeY, graphHeight);
|
const startY = getPointInRange(rangeY, graphHeight);
|
||||||
|
|
@ -217,6 +219,7 @@ window.HeightmapGenerator = (function () {
|
||||||
limit = 0,
|
limit = 0,
|
||||||
endX,
|
endX,
|
||||||
endY;
|
endY;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
endX = Math.random() * graphWidth * 0.8 + graphWidth * 0.1;
|
endX = Math.random() * graphWidth * 0.8 + graphWidth * 0.1;
|
||||||
endY = Math.random() * graphHeight * 0.7 + graphHeight * 0.15;
|
endY = Math.random() * graphHeight * 0.7 + graphHeight * 0.15;
|
||||||
|
|
@ -224,8 +227,10 @@ window.HeightmapGenerator = (function () {
|
||||||
limit++;
|
limit++;
|
||||||
} while ((dist < graphWidth / 8 || dist > graphWidth / 3) && limit < 50);
|
} while ((dist < graphWidth / 8 || dist > graphWidth / 3) && limit < 50);
|
||||||
|
|
||||||
const startCell = findGridCell(startX, startY, grid);
|
startCell = findGridCell(startX, startY, grid);
|
||||||
const endCell = findGridCell(endX, endY, grid);
|
endCell = findGridCell(endX, endY, grid);
|
||||||
|
}
|
||||||
|
|
||||||
let range = getRange(startCell, endCell);
|
let range = getRange(startCell, endCell);
|
||||||
|
|
||||||
// get main ridge
|
// get main ridge
|
||||||
|
|
@ -286,7 +291,7 @@ window.HeightmapGenerator = (function () {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addTrough = (count, height, rangeX, rangeY) => {
|
const addTrough = (count, height, rangeX, rangeY, startCell, endCell) => {
|
||||||
count = getNumberInRange(count);
|
count = getNumberInRange(count);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
addOneTrough();
|
addOneTrough();
|
||||||
|
|
@ -297,20 +302,20 @@ window.HeightmapGenerator = (function () {
|
||||||
const used = new Uint8Array(heights.length);
|
const used = new Uint8Array(heights.length);
|
||||||
let h = lim(getNumberInRange(height));
|
let h = lim(getNumberInRange(height));
|
||||||
|
|
||||||
|
if (rangeX && rangeY) {
|
||||||
// find start and end points
|
// find start and end points
|
||||||
let limit = 0,
|
let limit = 0,
|
||||||
startX,
|
startX,
|
||||||
startY,
|
startY,
|
||||||
start,
|
|
||||||
dist = 0,
|
dist = 0,
|
||||||
endX,
|
endX,
|
||||||
endY;
|
endY;
|
||||||
do {
|
do {
|
||||||
startX = getPointInRange(rangeX, graphWidth);
|
startX = getPointInRange(rangeX, graphWidth);
|
||||||
startY = getPointInRange(rangeY, graphHeight);
|
startY = getPointInRange(rangeY, graphHeight);
|
||||||
start = findGridCell(startX, startY, grid);
|
startCell = findGridCell(startX, startY, grid);
|
||||||
limit++;
|
limit++;
|
||||||
} while (heights[start] < 20 && limit < 50);
|
} while (heights[startCell] < 20 && limit < 50);
|
||||||
|
|
||||||
limit = 0;
|
limit = 0;
|
||||||
do {
|
do {
|
||||||
|
|
@ -320,7 +325,10 @@ window.HeightmapGenerator = (function () {
|
||||||
limit++;
|
limit++;
|
||||||
} while ((dist < graphWidth / 8 || dist > graphWidth / 2) && limit < 50);
|
} while ((dist < graphWidth / 8 || dist > graphWidth / 2) && limit < 50);
|
||||||
|
|
||||||
let range = getRange(start, findGridCell(endX, endY, grid));
|
endCell = findGridCell(endX, endY, grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
let range = getRange(startCell, endCell);
|
||||||
|
|
||||||
// get main ridge
|
// get main ridge
|
||||||
function getRange(cur, end) {
|
function getRange(cur, end) {
|
||||||
|
|
@ -388,8 +396,12 @@ window.HeightmapGenerator = (function () {
|
||||||
const vert = direction === "vertical";
|
const vert = direction === "vertical";
|
||||||
const startX = vert ? Math.floor(Math.random() * graphWidth * 0.4 + graphWidth * 0.3) : 5;
|
const startX = vert ? Math.floor(Math.random() * graphWidth * 0.4 + graphWidth * 0.3) : 5;
|
||||||
const startY = vert ? 5 : Math.floor(Math.random() * graphHeight * 0.4 + graphHeight * 0.3);
|
const startY = vert ? 5 : Math.floor(Math.random() * graphHeight * 0.4 + graphHeight * 0.3);
|
||||||
const endX = vert ? Math.floor(graphWidth - startX - graphWidth * 0.1 + Math.random() * graphWidth * 0.2) : graphWidth - 5;
|
const endX = vert
|
||||||
const endY = vert ? graphHeight - 5 : Math.floor(graphHeight - startY - graphHeight * 0.1 + Math.random() * graphHeight * 0.2);
|
? 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, grid);
|
const start = findGridCell(startX, startY, grid);
|
||||||
const end = findGridCell(endX, endY, grid);
|
const end = findGridCell(endX, endY, grid);
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,12 @@ function editHeightmap(options) {
|
||||||
// move radius circle if drag mode is active
|
// move radius circle if drag mode is active
|
||||||
const pressed = byId("brushesButtons").querySelector("button.pressed");
|
const pressed = byId("brushesButtons").querySelector("button.pressed");
|
||||||
if (!pressed) return;
|
if (!pressed) return;
|
||||||
|
|
||||||
|
if (pressed.id === "brushLine") {
|
||||||
|
debug.select("line").attr("x2", x).attr("y2", y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
moveCircle(x, y, brushRadius.valueAsNumber, "#333");
|
moveCircle(x, y, brushRadius.valueAsNumber, "#333");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,7 +187,6 @@ function editHeightmap(options) {
|
||||||
else if (mode === "risk") restoreRiskedData();
|
else if (mode === "risk") restoreRiskedData();
|
||||||
|
|
||||||
// restore initial layers
|
// restore initial layers
|
||||||
//viewbox.select("#heights").remove();
|
|
||||||
byId("heights").remove();
|
byId("heights").remove();
|
||||||
turnButtonOff("toggleHeight");
|
turnButtonOff("toggleHeight");
|
||||||
document
|
document
|
||||||
|
|
@ -494,10 +499,8 @@ function editHeightmap(options) {
|
||||||
|
|
||||||
selection.forEach(function (i) {
|
selection.forEach(function (i) {
|
||||||
let cell = viewbox.select("#heights").select("#cell" + i);
|
let cell = viewbox.select("#heights").select("#cell" + i);
|
||||||
if (!ocean && grid.cells.h[i] < 20) {
|
if (!ocean && grid.cells.h[i] < 20) return cell.remove();
|
||||||
cell.remove();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!cell.size())
|
if (!cell.size())
|
||||||
cell = viewbox
|
cell = viewbox
|
||||||
.select("#heights")
|
.select("#heights")
|
||||||
|
|
@ -594,25 +597,82 @@ function editHeightmap(options) {
|
||||||
|
|
||||||
function exitBrushMode() {
|
function exitBrushMode() {
|
||||||
const pressed = document.querySelector("#brushesButtons > button.pressed");
|
const pressed = document.querySelector("#brushesButtons > button.pressed");
|
||||||
if (!pressed) return;
|
if (pressed) pressed.classList.remove("pressed");
|
||||||
pressed.classList.remove("pressed");
|
|
||||||
|
|
||||||
viewbox.style("cursor", "default").on(".drag", null);
|
viewbox.style("cursor", "default").on(".drag", null).on("click", clicked);
|
||||||
|
debug.selectAll(".lineCircle").remove();
|
||||||
removeCircle();
|
removeCircle();
|
||||||
|
|
||||||
byId("brushesSliders").style.display = "none";
|
byId("brushesSliders").style.display = "none";
|
||||||
|
byId("lineSlider").style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
const dragBrushThrottled = throttle(dragBrush, 100);
|
const dragBrushThrottled = throttle(dragBrush, 100);
|
||||||
function toggleBrushMode(e) {
|
|
||||||
if (e.target.classList.contains("pressed")) {
|
function toggleBrushMode(event) {
|
||||||
|
if (event.target.classList.contains("pressed")) {
|
||||||
exitBrushMode();
|
exitBrushMode();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
exitBrushMode();
|
exitBrushMode();
|
||||||
|
event.target.classList.add("pressed");
|
||||||
|
|
||||||
|
if (event.target.id === "brushLine") {
|
||||||
|
byId("lineSlider").style.display = "block";
|
||||||
|
viewbox.style("cursor", "crosshair").on("click", placeLinearFeature);
|
||||||
|
} else {
|
||||||
byId("brushesSliders").style.display = "block";
|
byId("brushesSliders").style.display = "block";
|
||||||
e.target.classList.add("pressed");
|
|
||||||
viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragBrushThrottled));
|
viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragBrushThrottled));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function placeLinearFeature() {
|
||||||
|
const [x, y] = d3.mouse(this);
|
||||||
|
const toCell = findGridCell(x, y, grid);
|
||||||
|
|
||||||
|
const lineCircle = debug.selectAll(".lineCircle");
|
||||||
|
if (!lineCircle.size()) {
|
||||||
|
// first click: add 1st control point
|
||||||
|
debug.append("line").attr("id", "brushCircle").attr("x1", x).attr("y1", y).attr("x2", x).attr("y2", y);
|
||||||
|
|
||||||
|
debug
|
||||||
|
.append("circle")
|
||||||
|
.attr("data-cell", toCell)
|
||||||
|
.attr("class", "lineCircle")
|
||||||
|
.attr("r", 6)
|
||||||
|
.attr("cx", x)
|
||||||
|
.attr("cy", y)
|
||||||
|
.attr("fill", "yellow")
|
||||||
|
.attr("stroke", "#333")
|
||||||
|
.attr("stroke-width", 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// second click: execute operation and remove control points
|
||||||
|
const fromCell = +lineCircle.attr("data-cell");
|
||||||
|
debug.selectAll("*").remove();
|
||||||
|
|
||||||
|
const power = byId("linePower").valueAsNumber;
|
||||||
|
if (power === 0) return tip("Power should not be zero", false, "error");
|
||||||
|
|
||||||
|
const heights = grid.cells.h;
|
||||||
|
const operation = power > 0 ? HeightmapGenerator.addRange : HeightmapGenerator.addTrough;
|
||||||
|
HeightmapGenerator.setGraph(grid);
|
||||||
|
operation("1", String(Math.abs(power)), null, null, fromCell, toCell);
|
||||||
|
const changedHeights = HeightmapGenerator.getHeights();
|
||||||
|
|
||||||
|
let selection = [];
|
||||||
|
for (let i = 0; i < heights.length; i++) {
|
||||||
|
if (changedHeights[i] === heights[i]) continue;
|
||||||
|
if (changeOnlyLand.checked && heights[i] < 20) continue;
|
||||||
|
heights[i] = changedHeights[i];
|
||||||
|
selection.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
mockHeightmapSelection(selection);
|
||||||
|
updateHistory();
|
||||||
|
}
|
||||||
|
|
||||||
function dragBrush() {
|
function dragBrush() {
|
||||||
const r = brushRadius.valueAsNumber;
|
const r = brushRadius.valueAsNumber;
|
||||||
|
|
@ -632,37 +692,44 @@ function editHeightmap(options) {
|
||||||
d3.event.on("end", updateHeightmap);
|
d3.event.on("end", updateHeightmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeHeightForSelection(s, start) {
|
function changeHeightForSelection(selection, start) {
|
||||||
const power = brushPower.valueAsNumber;
|
const power = brushPower.valueAsNumber;
|
||||||
|
|
||||||
const interpolate = d3.interpolateRound(power, 1);
|
const interpolate = d3.interpolateRound(power, 1);
|
||||||
const land = changeOnlyLand.checked;
|
const land = changeOnlyLand.checked;
|
||||||
const lim = v => minmax(v, land ? 20 : 0, 100);
|
const lim = v => minmax(v, land ? 20 : 0, 100);
|
||||||
const h = grid.cells.h;
|
const heights = grid.cells.h;
|
||||||
|
|
||||||
const brush = document.querySelector("#brushesButtons > button.pressed").id;
|
const brush = document.querySelector("#brushesButtons > button.pressed").id;
|
||||||
if (brush === "brushRaise") s.forEach(i => (h[i] = h[i] < 20 ? 20 : lim(h[i] + power)));
|
if (brush === "brushRaise") selection.forEach(i => (heights[i] = heights[i] < 20 ? 20 : lim(heights[i] + power)));
|
||||||
else if (brush === "brushElevate")
|
else if (brush === "brushElevate")
|
||||||
s.forEach((i, d) => (h[i] = lim(h[i] + interpolate(d / Math.max(s.length - 1, 1)))));
|
selection.forEach(
|
||||||
else if (brush === "brushLower") s.forEach(i => (h[i] = lim(h[i] - power)));
|
(i, d) => (heights[i] = lim(heights[i] + interpolate(d / Math.max(selection.length - 1, 1))))
|
||||||
|
);
|
||||||
|
else if (brush === "brushLower") selection.forEach(i => (heights[i] = lim(heights[i] - power)));
|
||||||
else if (brush === "brushDepress")
|
else if (brush === "brushDepress")
|
||||||
s.forEach((i, d) => (h[i] = lim(h[i] - interpolate(d / Math.max(s.length - 1, 1)))));
|
selection.forEach(
|
||||||
else if (brush === "brushAlign") s.forEach(i => (h[i] = lim(h[start])));
|
(i, d) => (heights[i] = lim(heights[i] - interpolate(d / Math.max(selection.length - 1, 1))))
|
||||||
|
);
|
||||||
|
else if (brush === "brushAlign") selection.forEach(i => (heights[i] = lim(heights[start])));
|
||||||
else if (brush === "brushSmooth")
|
else if (brush === "brushSmooth")
|
||||||
s.forEach(
|
selection.forEach(
|
||||||
i =>
|
i =>
|
||||||
(h[i] = rn(
|
(heights[i] = rn(
|
||||||
(d3.mean(grid.cells.c[i].filter(i => (land ? h[i] >= 20 : 1)).map(c => h[c])) +
|
(d3.mean(grid.cells.c[i].filter(i => (land ? heights[i] >= 20 : 1)).map(c => heights[c])) +
|
||||||
h[i] * (10 - power) +
|
heights[i] * (10 - power) +
|
||||||
0.6) /
|
0.6) /
|
||||||
(11 - power),
|
(11 - power),
|
||||||
1
|
1
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
else if (brush === "brushDisrupt")
|
else if (brush === "brushDisrupt")
|
||||||
s.forEach(i => (h[i] = h[i] < 15 ? h[i] : lim(h[i] + power / 1.6 - Math.random() * power)));
|
selection.forEach(
|
||||||
|
i => (heights[i] = heights[i] < 15 ? heights[i] : lim(heights[i] + power / 1.6 - Math.random() * power))
|
||||||
|
);
|
||||||
|
|
||||||
mockHeightmapSelection(s);
|
mockHeightmapSelection(selection);
|
||||||
// updateHistory(); uncomment to update history every step
|
// updateHistory(); uncomment to update history on every step
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeOnlyLandClick(e) {
|
function changeOnlyLandClick(e) {
|
||||||
|
|
|
||||||
|
|
@ -89,13 +89,13 @@ function handleKeyup(event) {
|
||||||
else if (code === "KeyI") toggleIcons();
|
else if (code === "KeyI") toggleIcons();
|
||||||
else if (code === "KeyM") toggleMilitary();
|
else if (code === "KeyM") toggleMilitary();
|
||||||
else if (code === "KeyK") toggleMarkers();
|
else if (code === "KeyK") toggleMarkers();
|
||||||
else if (code === "Equal") toggleRulers();
|
else if (code === "Equal" && !customization) toggleRulers();
|
||||||
else if (code === "Slash") toggleScaleBar();
|
else if (code === "Slash") toggleScaleBar();
|
||||||
else if (code === "ArrowLeft") zoom.translateBy(svg, 10, 0);
|
else if (code === "ArrowLeft") zoom.translateBy(svg, 10, 0);
|
||||||
else if (code === "ArrowRight") zoom.translateBy(svg, -10, 0);
|
else if (code === "ArrowRight") zoom.translateBy(svg, -10, 0);
|
||||||
else if (code === "ArrowUp") zoom.translateBy(svg, 0, 10);
|
else if (code === "ArrowUp") zoom.translateBy(svg, 0, 10);
|
||||||
else if (code === "ArrowDown") zoom.translateBy(svg, 0, -10);
|
else if (code === "ArrowDown") zoom.translateBy(svg, 0, -10);
|
||||||
else if (key === "+" || key === "-") pressNumpadSign(key);
|
else if (key === "+" || key === "-" || key === "=") handleSizeChange(key);
|
||||||
else if (key === "0") resetZoom(1000);
|
else if (key === "0") resetZoom(1000);
|
||||||
else if (key === "1") zoom.scaleTo(svg, 1);
|
else if (key === "1") zoom.scaleTo(svg, 1);
|
||||||
else if (key === "2") zoom.scaleTo(svg, 2);
|
else if (key === "2") zoom.scaleTo(svg, 2);
|
||||||
|
|
@ -117,11 +117,12 @@ function allowHotkeys() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pressNumpadSign(key) {
|
// "+", "-" and "=" keys on numpad. "=" is for "+" on Mac
|
||||||
const change = key === "+" ? 1 : -1;
|
function handleSizeChange(key) {
|
||||||
let brush = null;
|
let brush = null;
|
||||||
|
|
||||||
if (document.getElementById("brushRadius")?.offsetParent) brush = document.getElementById("brushRadius");
|
if (document.getElementById("brushRadius")?.offsetParent) brush = document.getElementById("brushRadius");
|
||||||
|
else if (document.getElementById("linePower")?.offsetParent) brush = document.getElementById("linePower");
|
||||||
else if (document.getElementById("biomesManuallyBrush")?.offsetParent)
|
else if (document.getElementById("biomesManuallyBrush")?.offsetParent)
|
||||||
brush = document.getElementById("biomesManuallyBrush");
|
brush = document.getElementById("biomesManuallyBrush");
|
||||||
else if (document.getElementById("statesManuallyBrush")?.offsetParent)
|
else if (document.getElementById("statesManuallyBrush")?.offsetParent)
|
||||||
|
|
@ -135,6 +136,7 @@ function pressNumpadSign(key) {
|
||||||
brush = document.getElementById("religionsManuallyBrush");
|
brush = document.getElementById("religionsManuallyBrush");
|
||||||
|
|
||||||
if (brush) {
|
if (brush) {
|
||||||
|
const change = key === "-" ? -5 : 5;
|
||||||
const value = minmax(+brush.value + change, +brush.min, +brush.max);
|
const value = minmax(+brush.value + change, +brush.min, +brush.max);
|
||||||
brush.value = document.getElementById(brush.id + "Number").value = value;
|
brush.value = document.getElementById(brush.id + "Number").value = value;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ function biased(min, max, ex) {
|
||||||
// get number from string in format "1-3" or "2" or "0.5"
|
// get number from string in format "1-3" or "2" or "0.5"
|
||||||
function getNumberInRange(r) {
|
function getNumberInRange(r) {
|
||||||
if (typeof r !== "string") {
|
if (typeof r !== "string") {
|
||||||
ERROR && console.error("The value should be a string", r);
|
ERROR && console.error("Range value should be a string", r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!isNaN(+r)) return ~~r + +P(r - ~~r);
|
if (!isNaN(+r)) return ~~r + +P(r - ~~r);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// version and caching control
|
// version and caching control
|
||||||
const version = "1.87.15"; // generator version, update each time
|
const version = "1.88.00"; // generator version, update each time
|
||||||
|
|
||||||
{
|
{
|
||||||
document.title += " v" + version;
|
document.title += " v" + version;
|
||||||
|
|
@ -28,6 +28,7 @@ const version = "1.87.15"; // generator version, update each time
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<strong>Latest changes:</strong>
|
<strong>Latest changes:</strong>
|
||||||
|
<li>Heightmap brushes: linear edit option</li>
|
||||||
<li>Data Charts screen</li>
|
<li>Data Charts screen</li>
|
||||||
<li>Сultures and religions can have multiple parents in hierarchy tree</li>
|
<li>Сultures and religions can have multiple parents in hierarchy tree</li>
|
||||||
<li>Heightmap selection screen</li>
|
<li>Heightmap selection screen</li>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue