mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
heightmap select - style fixes
This commit is contained in:
parent
6766de46ef
commit
f56bd0f586
7 changed files with 123 additions and 91 deletions
|
|
@ -2309,11 +2309,8 @@ svg.button {
|
||||||
|
|
||||||
#mapOverlay {
|
#mapOverlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
|
||||||
56
index.html
56
index.html
|
|
@ -24,29 +24,21 @@
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#map {
|
#loading > * {
|
||||||
position: absolute;
|
pointer-events: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
#initial {
|
#loading > #loading-rose > use {
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: black;
|
stroke: black;
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
#init-rose {
|
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
opacity: 0.7;
|
animation: 20s linear 0s infinite spin;
|
||||||
animation: 20s infinite spin;
|
|
||||||
}
|
}
|
||||||
@keyframes spin {
|
#loading > #loading-typography {
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#loading {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #fff5da;
|
color: #fff5da;
|
||||||
|
|
@ -54,11 +46,6 @@
|
||||||
text-shadow: 0px 1px 4px #4c3a35;
|
text-shadow: 0px 1px 4px #4c3a35;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
}
|
||||||
#loading-text {
|
#loading-text {
|
||||||
font-size: 1.8em;
|
font-size: 1.8em;
|
||||||
|
|
@ -106,6 +93,14 @@
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="index.css?v=21052022" />
|
<link rel="stylesheet" href="index.css?v=21052022" />
|
||||||
<link rel="stylesheet" href="icons.css" />
|
<link rel="stylesheet" href="icons.css" />
|
||||||
|
|
@ -116,6 +111,7 @@
|
||||||
id="map"
|
id="map"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
|
style="position: absolute"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
|
@ -267,19 +263,25 @@
|
||||||
</defs>
|
</defs>
|
||||||
<g id="viewbox"></g>
|
<g id="viewbox"></g>
|
||||||
<g id="scaleBar"></g>
|
<g id="scaleBar"></g>
|
||||||
<g id="initial" opacity="1">
|
|
||||||
<rect x="-1%" y="-1%" width="102%" height="102%" fill="#466eab" />
|
|
||||||
<rect x="-1%" y="-1%" width="102%" height="102%" fill="url(#oceanic)" />
|
|
||||||
<use href="#rose" id="init-rose" x="50%" y="50%" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div id="loading">
|
<div id="loading">
|
||||||
|
<svg width="100%" height="100%">
|
||||||
|
<rect x="-1%" y="-1%" width="102%" height="102%" fill="#466eab" />
|
||||||
|
<rect x="-1%" y="-1%" width="102%" height="102%" fill="url(#oceanic)" />
|
||||||
|
</svg>
|
||||||
|
<svg id="loading-rose" width="100%" height="100%" viewBox="0 0 700 700">
|
||||||
|
<use href="#rose" x="50%" y="50%" />
|
||||||
|
</svg>
|
||||||
|
<div id="loading-typography">
|
||||||
|
<div>
|
||||||
<div id="titleName"><t data-t="titleName">Azgaar's</t></div>
|
<div id="titleName"><t data-t="titleName">Azgaar's</t></div>
|
||||||
<div id="title"><t data-t="title">Fantasy Map Generator</t></div>
|
<div id="title"><t data-t="title">Fantasy Map Generator</t></div>
|
||||||
<div id="versionText"><t data-t="version">v. </t><span id="version"></span></div>
|
<div id="versionText"><t data-t="version">v. </t><span id="version"></span></div>
|
||||||
<p id="loading-text"><t data-t="loading">LOADING</t><span>.</span><span>.</span><span>.</span></p>
|
<p id="loading-text"><t data-t="loading">LOADING</t><span>.</span><span>.</span><span>.</span></p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="optionsContainer" style="opacity: 0">
|
<div id="optionsContainer" style="opacity: 0">
|
||||||
<div id="collapsible">
|
<div id="collapsible">
|
||||||
|
|
|
||||||
5
main.js
5
main.js
|
|
@ -201,9 +201,6 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
d3.select("#loading-text").transition().duration(1000).style("opacity", 0);
|
|
||||||
d3.select("#init-rose").transition().duration(4000).style("opacity", 0);
|
|
||||||
} else {
|
} else {
|
||||||
hideLoading();
|
hideLoading();
|
||||||
await checkLoadParameters();
|
await checkLoadParameters();
|
||||||
|
|
@ -213,14 +210,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
|
||||||
function hideLoading() {
|
function hideLoading() {
|
||||||
d3.select("#loading").transition().duration(4000).style("opacity", 0);
|
d3.select("#loading").transition().duration(4000).style("opacity", 0);
|
||||||
d3.select("#initial").transition().duration(4000).attr("opacity", 0);
|
|
||||||
d3.select("#optionsContainer").transition().duration(3000).style("opacity", 1);
|
d3.select("#optionsContainer").transition().duration(3000).style("opacity", 1);
|
||||||
d3.select("#tooltip").transition().duration(4000).style("opacity", 1);
|
d3.select("#tooltip").transition().duration(4000).style("opacity", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showLoading() {
|
function showLoading() {
|
||||||
d3.select("#loading").transition().duration(200).style("opacity", 1);
|
d3.select("#loading").transition().duration(200).style("opacity", 1);
|
||||||
d3.select("#initial").transition().duration(200).attr("opacity", 1);
|
|
||||||
d3.select("#optionsContainer").transition().duration(100).style("opacity", 0);
|
d3.select("#optionsContainer").transition().duration(100).style("opacity", 0);
|
||||||
d3.select("#tooltip").transition().duration(200).style("opacity", 0);
|
d3.select("#tooltip").transition().duration(200).style("opacity", 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,23 @@ function appendStyleSheet() {
|
||||||
|
|
||||||
.heightmap-selection_container {
|
.heightmap-selection_container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||||
grid-gap: 8px;
|
grid-gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.heightmap-selection_container {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
||||||
|
grid-gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 2000px) {
|
||||||
|
.heightmap-selection_container {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.heightmap-selection article {
|
.heightmap-selection article {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
@ -128,13 +141,9 @@ function appendStyleSheet() {
|
||||||
|
|
||||||
.heightmap-selection article > img {
|
.heightmap-selection article > img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
aspect-ratio: 16/9;
|
aspect-ratio: ${graphWidth}/${graphHeight};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
object-fit: cover;
|
object-fit: fill;
|
||||||
}
|
|
||||||
|
|
||||||
img.heightmap-selection_precreated {
|
|
||||||
filter: contrast(1.3);
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
@ -164,8 +173,10 @@ function insertEditorHtml() {
|
||||||
|
|
||||||
const heightmapsHtml = heightmaps
|
const heightmapsHtml = heightmaps
|
||||||
.map(({id, name}) => {
|
.map(({id, name}) => {
|
||||||
|
drawPrecreatedHeightmap(id);
|
||||||
|
|
||||||
return /* html */ `<article data-id="${id}" data-seed="${seed}">
|
return /* html */ `<article data-id="${id}" data-seed="${seed}">
|
||||||
<img src="../../heightmaps/${id}.png" alt="${name}" class="heightmap-selection_precreated" />
|
<img alt="${name}" />
|
||||||
<div>${name}</div>
|
<div>${name}</div>
|
||||||
</article>`;
|
</article>`;
|
||||||
})
|
})
|
||||||
|
|
@ -222,15 +233,19 @@ function drawHeights(heights) {
|
||||||
canvas.height = grid.cellsY;
|
canvas.height = grid.cellsY;
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
const imageData = ctx.createImageData(grid.cellsX, grid.cellsY);
|
const imageData = ctx.createImageData(grid.cellsX, grid.cellsY);
|
||||||
|
const scheme = getColorScheme();
|
||||||
|
const waterColor = scheme(1);
|
||||||
|
|
||||||
heights.forEach((height, i) => {
|
for (let i = 0; i < heights.length; i++) {
|
||||||
const h = height < 20 ? Math.max(height / 1.5, 0) : height;
|
const color = heights[i] < 20 ? waterColor : scheme(1 - heights[i] / 100);
|
||||||
const v = (h / 100) * 255;
|
const {r, g, b} = d3.color(color);
|
||||||
imageData.data[i * 4] = v;
|
|
||||||
imageData.data[i * 4 + 1] = v;
|
const n = i * 4;
|
||||||
imageData.data[i * 4 + 2] = v;
|
imageData.data[n] = r;
|
||||||
imageData.data[i * 4 + 3] = 255;
|
imageData.data[n + 1] = g;
|
||||||
});
|
imageData.data[n + 2] = b;
|
||||||
|
imageData.data[n + 3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.putImageData(imageData, 0, 0);
|
ctx.putImageData(imageData, 0, 0);
|
||||||
return canvas.toDataURL("image/png");
|
return canvas.toDataURL("image/png");
|
||||||
|
|
@ -243,6 +258,13 @@ function generateHeightmap(id) {
|
||||||
return heights;
|
return heights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function drawPrecreatedHeightmap(id) {
|
||||||
|
const heights = await HeightmapGenerator.fromPrecreated(id);
|
||||||
|
const dataUrl = drawHeights(heights);
|
||||||
|
const article = byId("heightmapSelection").querySelector(`[data-id="${id}"]`);
|
||||||
|
article.querySelector("img").src = dataUrl;
|
||||||
|
}
|
||||||
|
|
||||||
function regeneratePreview(article, id) {
|
function regeneratePreview(article, id) {
|
||||||
const seed = generateSeed();
|
const seed = generateSeed();
|
||||||
article.dataset.seed = seed;
|
article.dataset.seed = seed;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ window.HeightmapGenerator = (function () {
|
||||||
|
|
||||||
const fromPrecreated = id => {
|
const fromPrecreated = id => {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
TIME && console.time("defineHeightmap");
|
|
||||||
// create canvas where 1px corresponts to a cell
|
// create canvas where 1px corresponts to a cell
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
const ctx = canvas.getContext("2d");
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
@ -38,31 +37,26 @@ window.HeightmapGenerator = (function () {
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
ctx.drawImage(img, 0, 0, cellsX, cellsY);
|
ctx.drawImage(img, 0, 0, cellsX, cellsY);
|
||||||
const imageData = ctx.getImageData(0, 0, cellsX, cellsY);
|
const imageData = ctx.getImageData(0, 0, cellsX, cellsY);
|
||||||
assignColorsToHeight(imageData.data);
|
const heights = getHeightsFromImageData(imageData.data);
|
||||||
canvas.remove();
|
canvas.remove();
|
||||||
img.remove();
|
img.remove();
|
||||||
|
resolve(heights);
|
||||||
grid.cells.h = heights;
|
|
||||||
cleanup();
|
|
||||||
TIME && console.timeEnd("defineHeightmap");
|
|
||||||
resolve();
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const generate = async function () {
|
const generate = async function () {
|
||||||
Math.random = aleaPRNG(seed);
|
Math.random = aleaPRNG(seed);
|
||||||
resetHeights();
|
|
||||||
const id = byId("templateInput").value;
|
|
||||||
|
|
||||||
if (HeightmapTemplates[id]) {
|
TIME && console.time("defineHeightmap");
|
||||||
TIME && console.time("generateHeightmap");
|
const id = byId("templateInput").value;
|
||||||
grid.cells.h = fromTemplate(id);
|
resetHeights();
|
||||||
|
|
||||||
|
const isTemplate = id in HeightmapTemplates;
|
||||||
|
grid.cells.h = isTemplate ? fromTemplate(id) : await fromPrecreated(id);
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
TIME && console.timeEnd("generateHeightmap");
|
TIME && console.timeEnd("defineHeightmap");
|
||||||
} else {
|
|
||||||
return fromPrecreated(id);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function addStep(tool, a2, a3, a4, a5) {
|
function addStep(tool, a2, a3, a4, a5) {
|
||||||
|
|
@ -491,13 +485,32 @@ window.HeightmapGenerator = (function () {
|
||||||
return rand(min * length, max * length);
|
return rand(min * length, max * length);
|
||||||
}
|
}
|
||||||
|
|
||||||
function assignColorsToHeight(imageData) {
|
function getHeightsFromImageData(imageData) {
|
||||||
for (let i = 0; i < grid.cells.i.length; i++) {
|
const heights = new Uint8Array(grid.points.length);
|
||||||
|
for (let i = 0; i < heights.length; i++) {
|
||||||
const lightness = imageData[i * 4] / 255;
|
const lightness = imageData[i * 4] / 255;
|
||||||
const powered = lightness < 0.2 ? lightness : 0.2 + (lightness - 0.2) ** 0.8;
|
const powered = lightness < 0.2 ? lightness : 0.2 + (lightness - 0.2) ** 0.8;
|
||||||
heights[i] = minmax(Math.floor(powered * 100), 0, 100);
|
heights[i] = minmax(Math.floor(powered * 100), 0, 100);
|
||||||
}
|
}
|
||||||
|
return heights;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {setHeights, resetHeights, getHeights, cleanup, generate, fromTemplate, addHill, addRange, addTrough, addStrait, addPit, smooth, modify, mask, invert};
|
return {
|
||||||
|
setHeights,
|
||||||
|
resetHeights,
|
||||||
|
getHeights,
|
||||||
|
cleanup,
|
||||||
|
generate,
|
||||||
|
fromTemplate,
|
||||||
|
fromPrecreated,
|
||||||
|
addHill,
|
||||||
|
addRange,
|
||||||
|
addTrough,
|
||||||
|
addStrait,
|
||||||
|
addPit,
|
||||||
|
smooth,
|
||||||
|
modify,
|
||||||
|
mask,
|
||||||
|
invert
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1369,10 +1369,12 @@ function editHeightmap() {
|
||||||
grid.cells.h.forEach((height, i) => {
|
grid.cells.h.forEach((height, i) => {
|
||||||
const h = height < 20 ? Math.max(height / 1.5, 0) : height;
|
const h = height < 20 ? Math.max(height / 1.5, 0) : height;
|
||||||
const v = (h / 100) * 255;
|
const v = (h / 100) * 255;
|
||||||
imageData.data[i * 4] = v;
|
|
||||||
imageData.data[i * 4 + 1] = v;
|
const n = i * 4;
|
||||||
imageData.data[i * 4 + 2] = v;
|
imageData.data[n] = v;
|
||||||
imageData.data[i * 4 + 3] = 255;
|
imageData.data[n + 1] = v;
|
||||||
|
imageData.data[n + 2] = v;
|
||||||
|
imageData.data[n + 3] = 255;
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.putImageData(imageData, 0, 0);
|
ctx.putImageData(imageData, 0, 0);
|
||||||
|
|
|
||||||
|
|
@ -151,9 +151,9 @@ function toggleHeight(event) {
|
||||||
function drawHeightmap() {
|
function drawHeightmap() {
|
||||||
TIME && console.time("drawHeightmap");
|
TIME && console.time("drawHeightmap");
|
||||||
terrs.selectAll("*").remove();
|
terrs.selectAll("*").remove();
|
||||||
const cells = pack.cells,
|
|
||||||
vertices = pack.vertices,
|
const {cells, vertices} = pack;
|
||||||
n = cells.i.length;
|
const n = cells.i.length;
|
||||||
const used = new Uint8Array(cells.i.length);
|
const used = new Uint8Array(cells.i.length);
|
||||||
const paths = new Array(101).fill("");
|
const paths = new Array(101).fill("");
|
||||||
|
|
||||||
|
|
@ -161,6 +161,7 @@ function drawHeightmap() {
|
||||||
const terracing = terrs.attr("terracing") / 10; // add additional shifted darker layer for pseudo-3d effect
|
const terracing = terrs.attr("terracing") / 10; // add additional shifted darker layer for pseudo-3d effect
|
||||||
const skip = +terrs.attr("skip") + 1;
|
const skip = +terrs.attr("skip") + 1;
|
||||||
const simplification = +terrs.attr("relax");
|
const simplification = +terrs.attr("relax");
|
||||||
|
|
||||||
switch (+terrs.attr("curve")) {
|
switch (+terrs.attr("curve")) {
|
||||||
case 0:
|
case 0:
|
||||||
lineGen.curve(d3.curveBasisClosed);
|
lineGen.curve(d3.curveBasisClosed);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue