mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
v1.0.05
This commit is contained in:
parent
ee70be134f
commit
59785125b0
6 changed files with 150 additions and 30 deletions
32
index.css
32
index.css
|
|
@ -1289,8 +1289,13 @@ div.states > div.biomeArea {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
#picker text {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#pickerHeader {
|
||||
fill: #916e7f;
|
||||
stroke: #5d4651;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
|
|
@ -1302,8 +1307,17 @@ div.states > div.biomeArea {
|
|||
cursor: move !important;
|
||||
}
|
||||
|
||||
#picker text {
|
||||
cursor: default;
|
||||
#pickerCloseRect {
|
||||
cursor: pointer;
|
||||
fill: #916e7f;
|
||||
stroke: #f8ffff;
|
||||
}
|
||||
|
||||
#pickerCloseText {
|
||||
fill: #f8ffff;
|
||||
font-size: 10px;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#pickerControls line {
|
||||
|
|
@ -1322,6 +1336,20 @@ div.states > div.biomeArea {
|
|||
stroke: #000000;
|
||||
}
|
||||
|
||||
#pickerSpaces input {
|
||||
height: 8px;
|
||||
width: 16px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#pickerSpaces input::-webkit-inner-spin-button,
|
||||
#pickerSpaces input::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#pickerColors rect, #pickerHatches rect {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1788,9 +1788,9 @@
|
|||
|
||||
<div>
|
||||
<p>Cell info:</p>
|
||||
<span>Coord: </span><span id="heightmapInfoX"></span>/<span id="heightmapInfoY"></span>
|
||||
<span style="margin-left:8px">Cell: </span><span id="heightmapInfoCell"></span>
|
||||
<span style="margin-left:8px">Height: </span><span id="heightmapInfoHeight"></span>
|
||||
<span>Coord: </span><span id="heightmapInfoX"></span>/<span id="heightmapInfoY"></span><br>
|
||||
<span>Cell: </span><span id="heightmapInfoCell"></span><br>
|
||||
<span>Height: </span><span id="heightmapInfoHeight"></span>
|
||||
</div>
|
||||
|
||||
<button data-tip="Finalize the heightmap and exit the edit mode" id="finalizeHeightmap" class="glow">Exit Customization</button>
|
||||
|
|
@ -2369,7 +2369,7 @@
|
|||
<button id="convertAutoHue" data-tip="Auto-assign colors based on hue (good to colored images)" class="icon-brush"></button>
|
||||
<button id="convertColorsMinus" data-tip="Reduce the number of colors. Minimal number is 3" class="icon-minus-squared"></button>
|
||||
<button id="convertColorsPlus" data-tip="Increase the number of colors. Maximum number is 256" class="icon-plus-squared"></button>
|
||||
<input id="convertColors" value="12" style="display: none"/>
|
||||
<input id="convertColors" value="18" style="display: none"/>
|
||||
<button id="convertComplete" data-tip="Complete the assignment. All unassigned colors will be considered as ocean" class="icon-check"></button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
2
main.js
2
main.js
|
|
@ -391,7 +391,7 @@ function focusOn() {
|
|||
}
|
||||
|
||||
const b = +params.get("burg");
|
||||
if (b) {
|
||||
if (b && pack.burgs[b]) {
|
||||
x = pack.burgs[b].x;
|
||||
y = pack.burgs[b].y;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,9 +252,13 @@ function clearLegend() {
|
|||
|
||||
// draw color (fill) picker
|
||||
function createPicker() {
|
||||
const pos = () => tip("Drag to change the picker position");
|
||||
const cl = () => tip("Click to close the picker");
|
||||
const closePicker = () => contaiter.style("display", "none");
|
||||
|
||||
const contaiter = d3.select("body").append("svg").attr("id", "pickerContainer").attr("width", "100%").attr("height", "100%");
|
||||
const curtain = contaiter.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("opacity", .2);
|
||||
curtain.on("click", () => contaiter.style("display", "none")).on("mousemove", () => tip("Click to close the picker"));
|
||||
contaiter.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("opacity", .2)
|
||||
.on("mousemove", cl).on("click", closePicker);
|
||||
const picker = contaiter.append("g").attr("id", "picker").call(d3.drag().on("start", dragPicker));
|
||||
|
||||
const controls = picker.append("g").attr("id", "pickerControls");
|
||||
|
|
@ -279,6 +283,24 @@ function createPicker() {
|
|||
controls.selectAll("line").on("click", clickPickerControl);
|
||||
controls.selectAll("circle").call(d3.drag().on("start", dragPickerControl));
|
||||
|
||||
const spaces = picker.append("foreignObject").attr("id", "pickerSpaces")
|
||||
.attr("x", 4).attr("y", 20).attr("width", 303).attr("height", 20)
|
||||
.on("mousemove", () => tip("Color value in different color spaces. Edit to change"));
|
||||
const html = `
|
||||
<label style="margin-right: 6px">HSL:
|
||||
<input type="number" id="pickerHSL_H" data-space="hsl" min=0 max=360 value="231">,
|
||||
<input type="number" id="pickerHSL_S" data-space="hsl" min=0 max=100 value="70">,
|
||||
<input type="number" id="pickerHSL_L" data-space="hsl" min=0 max=100 value="70">
|
||||
</label>
|
||||
<label style="margin-right: 6px">RGB:
|
||||
<input type="number" id="pickerRGB_R" data-space="rgb" min=0 max=255 value="125">,
|
||||
<input type="number" id="pickerRGB_G" data-space="rgb" min=0 max=255 value="142">,
|
||||
<input type="number" id="pickerRGB_B" data-space="rgb" min=0 max=255 value="232">
|
||||
</label>
|
||||
<label>HEX: <input type="text" id="pickerHEX" data-space="hex" style="width:42px" autocorrect="off" spellcheck="false" value="#7d8ee8"></label>`;
|
||||
spaces.node().insertAdjacentHTML('beforeend', html);
|
||||
spaces.selectAll("input").on("change", changePickerSpace);
|
||||
|
||||
const colors = picker.append("g").attr("id", "pickerColors").attr("stroke", "#333333");
|
||||
const hatches = picker.append("g").attr("id", "pickerHatches").attr("stroke", "#333333");
|
||||
const hatching = d3.selectAll("g#hatching > pattern");
|
||||
|
|
@ -287,12 +309,12 @@ function createPicker() {
|
|||
const clr = d3.range(number).map(i => d3.hsl(i/number*360, .7, .7).hex());
|
||||
clr.forEach(function(d, i) {
|
||||
colors.append("rect").attr("id", "picker_" + d).attr("fill", d).attr("class", i?"":"selected")
|
||||
.attr("x", i*22+4).attr("y", 20).attr("width", 16).attr("height", 16);
|
||||
.attr("x", i*22+4).attr("y", 40).attr("width", 16).attr("height", 16);
|
||||
});
|
||||
|
||||
hatching.each(function(d, i) {
|
||||
hatches.append("rect").attr("id", "picker_" + this.id).attr("fill", "url(#" + this.id + ")")
|
||||
.attr("x", i*22+4).attr("y", 41).attr("width", 16).attr("height", 16);
|
||||
.attr("x", i*22+4).attr("y", 61).attr("width", 16).attr("height", 16);
|
||||
});
|
||||
|
||||
colors.selectAll("rect").on("click", pickerFillClicked).on("mousemove", () => tip("Click to fill with the color"));
|
||||
|
|
@ -302,8 +324,10 @@ function createPicker() {
|
|||
const bbox = picker.node().getBBox();
|
||||
const width = bbox.width + 8;
|
||||
const height = bbox.height + 9;
|
||||
const pos = () => tip("Drag to change the picker position");
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "#ffffff").on("mousemove", pos);
|
||||
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "#ffffff").attr("stroke", "#5d4651").on("mousemove", pos);
|
||||
picker.insert("text", ":first-child").attr("x", 291).attr("y", -11).attr("id", "pickerCloseText").text("✖");
|
||||
picker.insert("rect", ":first-child").attr("x", 288).attr("y", -21).attr("id", "pickerCloseRect").attr("width", 14).attr("height", 14).on("mousemove", cl).on("click", closePicker);
|
||||
picker.insert("text", ":first-child").attr("x", 12).attr("y", -10).attr("id", "pickerLabel").text("Color Picker").on("mousemove", pos);
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", -30).attr("width", width).attr("height", 30).attr("id", "pickerHeader").on("mousemove", pos);
|
||||
picker.attr("transform", `translate(${(svgWidth-width)/2},${(svgHeight-height)/2})`);
|
||||
|
|
@ -314,6 +338,25 @@ function updateSelectedRect(fill) {
|
|||
document.getElementById("picker").querySelector("rect[fill='"+fill+"']").classList.add("selected");
|
||||
}
|
||||
|
||||
function updateSpaces() {
|
||||
// hsl
|
||||
const h = getPickerControl(pickerH, 360);
|
||||
const s = getPickerControl(pickerS, 1);
|
||||
const l = getPickerControl(pickerL, 1);
|
||||
pickerHSL_H.value = rn(h);
|
||||
pickerHSL_S.value = rn(s * 100); // multiplied by 100
|
||||
pickerHSL_L.value = rn(l * 100); // multiplied by 100
|
||||
|
||||
// rgb
|
||||
const rgb = d3.color(d3.hsl(h, s, l));
|
||||
pickerRGB_R.value = rgb.r;
|
||||
pickerRGB_G.value = rgb.g;
|
||||
pickerRGB_B.value = rgb.b;
|
||||
|
||||
// hex
|
||||
pickerHEX.value = rgb.hex();
|
||||
}
|
||||
|
||||
function updatePickerColors() {
|
||||
const colors = d3.select("#picker > #pickerColors").selectAll("rect");
|
||||
const number = colors.size();
|
||||
|
|
@ -339,6 +382,7 @@ function openPicker(fill, callback) {
|
|||
if (!isNaN(hsl.h)) setPickerControl(pickerH, hsl.h, 360);
|
||||
if (!isNaN(hsl.s)) setPickerControl(pickerS, hsl.s, 1);
|
||||
if (!isNaN(hsl.l)) setPickerControl(pickerL, hsl.l, 1);
|
||||
updateSpaces();
|
||||
updatePickerColors();
|
||||
}
|
||||
|
||||
|
|
@ -380,13 +424,20 @@ function dragPicker() {
|
|||
}
|
||||
|
||||
function pickerFillClicked() {
|
||||
updateSelectedRect(this.getAttribute("fill"));
|
||||
const fill = this.getAttribute("fill");
|
||||
updateSelectedRect(fill);
|
||||
openPicker.updateFill();
|
||||
|
||||
const hsl = d3.hsl(fill);
|
||||
if (isNaN(hsl.h)) return; // not a color
|
||||
setPickerControl(pickerH, hsl.h, 360);
|
||||
updateSpaces();
|
||||
}
|
||||
|
||||
function clickPickerControl() {
|
||||
const min = this.getScreenCTM().e;
|
||||
this.nextSibling.setAttribute("cx", d3.event.x - min);
|
||||
updateSpaces();
|
||||
updatePickerColors();
|
||||
openPicker.updateFill();
|
||||
}
|
||||
|
|
@ -398,11 +449,33 @@ function dragPickerControl() {
|
|||
d3.event.on("drag", function() {
|
||||
const x = Math.max(Math.min(d3.event.x, max), min);
|
||||
this.setAttribute("cx", x);
|
||||
updateSpaces();
|
||||
updatePickerColors();
|
||||
openPicker.updateFill();
|
||||
});
|
||||
}
|
||||
|
||||
function changePickerSpace() {
|
||||
const valid = this.checkValidity();
|
||||
if (!valid) {tip("You must provide a correct value", false, "error"); return;}
|
||||
|
||||
const space = this.dataset.space;
|
||||
const i = Array.from(this.parentNode.querySelectorAll("input")).map(input => input.value); // inputs
|
||||
const fill = space === "hex" ? d3.rgb(this.value)
|
||||
: space === "rgb" ? d3.rgb(i[0], i[1], i[2])
|
||||
: d3.hsl(i[0], i[1]/100, i[2]/100);
|
||||
|
||||
const hsl = d3.hsl(fill);
|
||||
if (isNaN(hsl.l)) {tip("You must provide a correct value", false, "error"); return;}
|
||||
if (!isNaN(hsl.h)) setPickerControl(pickerH, hsl.h, 360);
|
||||
if (!isNaN(hsl.s)) setPickerControl(pickerS, hsl.s, 1);
|
||||
if (!isNaN(hsl.l)) setPickerControl(pickerL, hsl.l, 1);
|
||||
|
||||
updateSpaces();
|
||||
updatePickerColors();
|
||||
openPicker.updateFill();
|
||||
}
|
||||
|
||||
// remove all fogging
|
||||
function unfog() {
|
||||
defs.select("#fog").selectAll("path").remove();
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ function editHeightmap() {
|
|||
heightmapInfoX.innerHTML = rn(p[0]);
|
||||
heightmapInfoY.innerHTML = rn(p[1]);
|
||||
heightmapInfoCell.innerHTML = cell;
|
||||
heightmapInfoHeight.innerHTML = grid.cells.h[cell];
|
||||
|
||||
tip("Height: " + getFriendlyHeight(grid.cells.h[cell]));
|
||||
const h = grid.cells.h[cell];
|
||||
heightmapInfoHeight.innerHTML = `${h} (${getFriendlyHeight(h)})`;
|
||||
if (tooltip.dataset.main) showMainTip();
|
||||
|
||||
// move radius circle if drag mode is active
|
||||
const pressed = document.querySelector("#brushesButtons > button.pressed");
|
||||
|
|
@ -218,6 +218,14 @@ function editHeightmap() {
|
|||
if (grid.cells.h[i] < 20) grid.cells.h[i] = 20;
|
||||
}
|
||||
|
||||
// save culture centers x and y to restore center cell id after re-graph
|
||||
for (const c of pack.cultures) {
|
||||
if (!c.i || c.removed) continue;
|
||||
const p = pack.cells.p[c.center];
|
||||
c.x = p[0];
|
||||
c.y = p[1];
|
||||
}
|
||||
|
||||
markFeatures();
|
||||
OceanLayers();
|
||||
calculateTemperatures();
|
||||
|
|
@ -299,6 +307,11 @@ function editHeightmap() {
|
|||
else {p.center = provCells[0]; p.burg = pack.cells.burg[p.center];}
|
||||
}
|
||||
|
||||
for (const c of pack.cultures) {
|
||||
if (!c.i || c.removed) continue;
|
||||
c.center = findCell(c.x, c.y);
|
||||
}
|
||||
|
||||
BurgsAndStates.drawStateLabels();
|
||||
drawStates();
|
||||
drawBorders();
|
||||
|
|
@ -883,7 +896,12 @@ function editHeightmap() {
|
|||
setOverlayOpacity(0);
|
||||
|
||||
document.getElementById("convertImageLoad").classList.add("glow"); // add glow effect
|
||||
tip('Image Converter is opened. Upload the image and assign the colors to desired heights', true); // main tip
|
||||
tip('Image Converter is opened. Upload the image and assign the colors to desired heights', true, "warn"); // main tip
|
||||
|
||||
// remove all heights
|
||||
grid.cells.h = new Uint8Array(grid.cells.i.length);
|
||||
terrs.selectAll("*").remove();
|
||||
updateHistory();
|
||||
|
||||
if (modules.openImageConverter) return;
|
||||
modules.openImageConverter = true;
|
||||
|
|
@ -944,8 +962,8 @@ function editHeightmap() {
|
|||
colorsUnassigned.style.display = "block";
|
||||
colorsAssigned.style.display = "none";
|
||||
|
||||
const gridColors = grid.points.map(function(p) {
|
||||
const x = Math.floor(p[0]), y = Math.floor(p[1]);
|
||||
const gridColors = grid.points.map(p => {
|
||||
const x = Math.floor(p[0]-.01), y = Math.floor(p[1]-.01);
|
||||
const i = (x + y * graphWidth) * 4;
|
||||
const r = data[i], g = data[i+1], b = data[i+2];
|
||||
return [r, g, b];
|
||||
|
|
@ -961,7 +979,7 @@ function editHeightmap() {
|
|||
return clr;
|
||||
}).on("click", mapClicked);
|
||||
|
||||
const unassigned = [...usedColors].sort((a, b) => d3.lab(a).b - d3.lab(b).b);
|
||||
const unassigned = [...usedColors].sort((a, b) => d3.lab(a).l - d3.lab(b).l);
|
||||
const unassignedContainer = d3.select("#colorsUnassigned");
|
||||
unassignedContainer.selectAll("div").data(unassigned).enter().append("div")
|
||||
.attr("data-color", i => i).style("background-color", i => i)
|
||||
|
|
@ -1027,7 +1045,7 @@ function editHeightmap() {
|
|||
unassigned.forEach(function(el) {
|
||||
const colorFrom = el.getAttribute("data-color");
|
||||
const lab = d3.lab(colorFrom);
|
||||
const normalized = type === "hue" ? rn(normalize(lab.b + lab.a / 2, -50, 200), 2) : rn(normalize(lab.l, 0, 100), 2);
|
||||
const normalized = type === "hue" ? rn(normalize(lab.b + lab.a / 2, -50, 200), 2) : rn(normalize(lab.l, -15, 100), 2);
|
||||
const colorTo = color(1 - normalized);
|
||||
const heightTo = normalized * 100;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ function getBoundaryPoints(width, height, spacing) {
|
|||
// get points on a regular square grid and jitter them a bit
|
||||
function getJitteredGrid(width, height, spacing) {
|
||||
const radius = spacing / 2; // square radius
|
||||
const jittering = radius * 0.9; // max deviation
|
||||
const jitter = function() {return Math.random() * 2 * jittering - jittering;};
|
||||
const jittering = radius * .9; // max deviation
|
||||
const jitter = () => Math.random() * 2 * jittering - jittering;
|
||||
|
||||
let points = [];
|
||||
for (let y = radius; y < height; y += spacing) {
|
||||
for (let x = radius; x < width; x += spacing) {
|
||||
let xj = rn(x + jitter(), 2);
|
||||
let yj = rn(y + jitter(), 2);
|
||||
const xj = Math.min(rn(x + jitter(), 2), width);
|
||||
const yj = Math.min(rn(y + jitter(), 2), height);
|
||||
points.push([xj, yj]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue