mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 01:41:22 +01:00
Refactor layers rendering (#1120)
* feat: render states - use global fn * feat: render states - separate pole detection from layer render * feat: render provinces * chore: unify drawFillWithGap * refactor: drawIce * refactor: drawBorders * refactor: drawHeightmap * refactor: drawTemperature * refactor: drawBiomes * refactor: drawPrec * refactor: drawPrecipitation * refactor: drawPopulation * refactor: drawCells * refactor: geColor * refactor: drawMarkers * refactor: drawScaleBar * refactor: drawScaleBar * refactor: drawMilitary * refactor: pump version to 1.104.00 * refactor: pump version to 1.104.00 * refactor: drawCoastline and createDefaultRuler * refactor: drawCoastline * refactor: Features module start * refactor: features - define distance fields * feat: drawFeatures * feat: drawIce don't hide * feat: detect coastline - fix issue with border feature * feat: separate labels rendering from generation process * feat: auto-update and restore layers * refactor - change layers * refactor - sort layers * fix: regenerate burgs to re-render layers * fix: getColor is not defined * fix: burgs overview - don't auto-show labels on hover * fix: redraw population on change * refactor: improve tooltip logic for burg labels and icons * chore: pump version to 1.104.0 * fefactor: edit coastline and lake * fix: minot fixes * fix: submap --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
parent
ec993d1a9b
commit
05de284e02
52 changed files with 2473 additions and 2713 deletions
|
|
@ -373,7 +373,7 @@ window.ThreeD = (function () {
|
|||
}
|
||||
|
||||
// icons
|
||||
if (layerIsOn("toggleIcons")) {
|
||||
if (layerIsOn("toggleBurgIcons")) {
|
||||
const geometry = isCity ? city_icon_geometry : town_icon_geometry;
|
||||
const material = isCity ? city_icon_material : town_icon_material;
|
||||
const iconMesh = new THREE.Mesh(geometry, material);
|
||||
|
|
@ -444,6 +444,7 @@ window.ThreeD = (function () {
|
|||
const url = await getMapURL("mesh", {
|
||||
noLabels: options.labels3d,
|
||||
noWater: options.extendedWater,
|
||||
noViewbox: true,
|
||||
fullMap: true
|
||||
});
|
||||
const canvas = document.createElement("canvas");
|
||||
|
|
@ -623,7 +624,7 @@ window.ThreeD = (function () {
|
|||
material.map = texture;
|
||||
if (addMesh) addGlobe3dMesh();
|
||||
};
|
||||
img2.src = await getMapURL("mesh", {noScaleBar: true, fullMap: true});
|
||||
img2.src = await getMapURL("mesh", {noScaleBar: true, fullMap: true, noVignette: true});
|
||||
}
|
||||
|
||||
function addGlobe3dMesh() {
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ class Battle {
|
|||
const shift = side === "attackers" ? attackers.length * -8 : (defenders.length - 1) * 8;
|
||||
regiment.px = regiment.x;
|
||||
regiment.py = regiment.y;
|
||||
Military.moveRegiment(regiment, defenders[0].x, defenders[0].y + shift);
|
||||
moveRegiment(regiment, defenders[0].x, defenders[0].y + shift);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -909,7 +909,7 @@ class Battle {
|
|||
|
||||
cancelResults() {
|
||||
// move regiments back to initial positions
|
||||
this.attackers.regiments.concat(this.defenders.regiments).forEach(r => Military.moveRegiment(r, r.px, r.py));
|
||||
this.attackers.regiments.concat(this.defenders.regiments).forEach(r => moveRegiment(r, r.px, r.py));
|
||||
$("#battleScreen").dialog("close");
|
||||
this.cleanData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
function editBurg(id) {
|
||||
if (customization) return;
|
||||
closeDialogs(".stable");
|
||||
if (!layerIsOn("toggleIcons")) toggleIcons();
|
||||
if (!layerIsOn("toggleBurgIcons")) toggleBurgIcons();
|
||||
if (!layerIsOn("toggleLabels")) toggleLabels();
|
||||
|
||||
const burg = id || d3.event.target.dataset.id;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
function overviewBurgs(settings = {stateId: null, cultureId: null}) {
|
||||
if (customization) return;
|
||||
closeDialogs("#burgsOverview, .stable");
|
||||
if (!layerIsOn("toggleIcons")) toggleIcons();
|
||||
if (!layerIsOn("toggleBurgIcons")) toggleBurgIcons();
|
||||
if (!layerIsOn("toggleLabels")) toggleLabels();
|
||||
|
||||
const body = byId("burgsBody");
|
||||
|
|
@ -154,9 +154,9 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
|
|||
}
|
||||
|
||||
function burgHighlightOn(event) {
|
||||
if (!layerIsOn("toggleLabels")) toggleLabels();
|
||||
const burg = +event.target.dataset.id;
|
||||
burgLabels.select("[data-id='" + burg + "']").classed("drag", true);
|
||||
const label = burgLabels.select("[data-id='" + burg + "']");
|
||||
if (label.size()) label.classed("drag", true);
|
||||
}
|
||||
|
||||
function burgHighlightOff() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use strict";
|
||||
function editCoastline(node = d3.event.target) {
|
||||
|
||||
function editCoastline() {
|
||||
if (customization) return;
|
||||
closeDialogs(".stable");
|
||||
if (layerIsOn("toggleCells")) toggleCells();
|
||||
|
|
@ -12,6 +13,7 @@ function editCoastline(node = d3.event.target) {
|
|||
});
|
||||
|
||||
debug.append("g").attr("id", "vertices");
|
||||
const node = d3.event.target;
|
||||
elSelected = d3.select(node);
|
||||
selectCoastlineGroup(node);
|
||||
drawCoastlineVertices();
|
||||
|
|
@ -21,93 +23,98 @@ function editCoastline(node = d3.event.target) {
|
|||
modules.editCoastline = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("coastlineGroupsShow").addEventListener("click", showGroupSection);
|
||||
document.getElementById("coastlineGroup").addEventListener("change", changeCoastlineGroup);
|
||||
document.getElementById("coastlineGroupAdd").addEventListener("click", toggleNewGroupInput);
|
||||
document.getElementById("coastlineGroupName").addEventListener("change", createNewGroup);
|
||||
document.getElementById("coastlineGroupRemove").addEventListener("click", removeCoastlineGroup);
|
||||
document.getElementById("coastlineGroupsHide").addEventListener("click", hideGroupSection);
|
||||
document.getElementById("coastlineEditStyle").addEventListener("click", editGroupStyle);
|
||||
byId("coastlineGroupsShow").on("click", showGroupSection);
|
||||
byId("coastlineGroup").on("change", changeCoastlineGroup);
|
||||
byId("coastlineGroupAdd").on("click", toggleNewGroupInput);
|
||||
byId("coastlineGroupName").on("change", createNewGroup);
|
||||
byId("coastlineGroupRemove").on("click", removeCoastlineGroup);
|
||||
byId("coastlineGroupsHide").on("click", hideGroupSection);
|
||||
byId("coastlineEditStyle").on("click", editGroupStyle);
|
||||
|
||||
function drawCoastlineVertices() {
|
||||
const f = +elSelected.attr("data-f"); // feature id
|
||||
const v = pack.features[f].vertices; // coastline outer vertices
|
||||
const featureId = +elSelected.attr("data-f");
|
||||
const {vertices, area} = pack.features[featureId];
|
||||
|
||||
const l = pack.cells.i.length;
|
||||
const c = [...new Set(v.map(v => pack.vertices.c[v]).flat())].filter(c => c < l);
|
||||
const cellsNumber = pack.cells.i.length;
|
||||
const neibCells = unique(vertices.map(v => pack.vertices.c[v]).flat()).filter(cellId => cellId < cellsNumber);
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("polygon")
|
||||
.data(c)
|
||||
.data(neibCells)
|
||||
.enter()
|
||||
.append("polygon")
|
||||
.attr("points", d => getPackPolygon(d))
|
||||
.attr("points", getPackPolygon)
|
||||
.attr("data-c", d => d);
|
||||
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("circle")
|
||||
.data(v)
|
||||
.data(vertices)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", d => pack.vertices.p[d][0])
|
||||
.attr("cy", d => pack.vertices.p[d][1])
|
||||
.attr("r", 0.4)
|
||||
.attr("data-v", d => d)
|
||||
.call(d3.drag().on("drag", dragVertex))
|
||||
.on("mousemove", () => tip("Drag to move the vertex, please use for fine-tuning only. Edit heightmap to change actual cell heights"));
|
||||
.call(d3.drag().on("drag", handleVertexDrag).on("end", handleVertexDragEnd))
|
||||
.on("mousemove", () =>
|
||||
tip("Drag to move the vertex. Please use for fine-tuning only. Edit heightmap to change actual cell heights!")
|
||||
);
|
||||
|
||||
const area = pack.features[f].area;
|
||||
coastlineArea.innerHTML = si(getArea(area)) + " " + getAreaUnit();
|
||||
}
|
||||
|
||||
function dragVertex() {
|
||||
const x = rn(d3.event.x, 2),
|
||||
y = rn(d3.event.y, 2);
|
||||
function handleVertexDrag() {
|
||||
const {vertices, features} = pack;
|
||||
|
||||
const x = rn(d3.event.x, 2);
|
||||
const y = rn(d3.event.y, 2);
|
||||
this.setAttribute("cx", x);
|
||||
this.setAttribute("cy", y);
|
||||
const v = +this.dataset.v;
|
||||
pack.vertices.p[v] = [x, y];
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("polygon")
|
||||
.attr("points", d => getPackPolygon(d));
|
||||
redrawCoastline();
|
||||
|
||||
const vertexId = d3.select(this).datum();
|
||||
vertices.p[vertexId] = [x, y];
|
||||
|
||||
const featureId = +elSelected.attr("data-f");
|
||||
const feature = features[featureId];
|
||||
|
||||
// change coastline path
|
||||
defs.select("#featurePaths > path#feature_" + featureId).attr("d", getFeaturePath(feature));
|
||||
|
||||
// update area
|
||||
const points = feature.vertices.map(vertex => vertices.p[vertex]);
|
||||
feature.area = Math.abs(d3.polygonArea(points));
|
||||
coastlineArea.innerHTML = si(getArea(feature.area)) + " " + getAreaUnit();
|
||||
|
||||
// update cell
|
||||
debug.select("#vertices").selectAll("polygon").attr("points", getPackPolygon);
|
||||
}
|
||||
|
||||
function redrawCoastline() {
|
||||
lineGen.curve(d3.curveBasisClosed);
|
||||
const f = +elSelected.attr("data-f");
|
||||
const vertices = pack.features[f].vertices;
|
||||
const points = clipPoly(
|
||||
vertices.map(v => pack.vertices.p[v]),
|
||||
1
|
||||
);
|
||||
const d = round(lineGen(points));
|
||||
elSelected.attr("d", d);
|
||||
defs.select("mask#land > path#land_" + f).attr("d", d); // update land mask
|
||||
defs.select("mask#water > path#water_" + f).attr("d", d); // update water mask
|
||||
|
||||
const area = Math.abs(d3.polygonArea(points));
|
||||
coastlineArea.innerHTML = si(getArea(area)) + " " + getAreaUnit();
|
||||
function handleVertexDragEnd() {
|
||||
if (layerIsOn("toggleStates")) drawStates();
|
||||
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
if (layerIsOn("toggleBiomes")) drawBiomes();
|
||||
if (layerIsOn("toggleReligions")) drawReligions();
|
||||
if (layerIsOn("toggleCultures")) drawCultures();
|
||||
}
|
||||
|
||||
function showGroupSection() {
|
||||
document.querySelectorAll("#coastlineEditor > button").forEach(el => (el.style.display = "none"));
|
||||
document.getElementById("coastlineGroupsSelection").style.display = "inline-block";
|
||||
byId("coastlineGroupsSelection").style.display = "inline-block";
|
||||
}
|
||||
|
||||
function hideGroupSection() {
|
||||
document.querySelectorAll("#coastlineEditor > button").forEach(el => (el.style.display = "inline-block"));
|
||||
document.getElementById("coastlineGroupsSelection").style.display = "none";
|
||||
document.getElementById("coastlineGroupName").style.display = "none";
|
||||
document.getElementById("coastlineGroupName").value = "";
|
||||
document.getElementById("coastlineGroup").style.display = "inline-block";
|
||||
byId("coastlineGroupsSelection").style.display = "none";
|
||||
byId("coastlineGroupName").style.display = "none";
|
||||
byId("coastlineGroupName").value = "";
|
||||
byId("coastlineGroup").style.display = "inline-block";
|
||||
}
|
||||
|
||||
function selectCoastlineGroup(node) {
|
||||
const group = node.parentNode.id;
|
||||
const select = document.getElementById("coastlineGroup");
|
||||
const select = byId("coastlineGroup");
|
||||
select.options.length = 0; // remove all options
|
||||
|
||||
coastline.selectAll("g").each(function () {
|
||||
|
|
@ -116,7 +123,7 @@ function editCoastline(node = d3.event.target) {
|
|||
}
|
||||
|
||||
function changeCoastlineGroup() {
|
||||
document.getElementById(this.value).appendChild(elSelected.node());
|
||||
byId(this.value).appendChild(elSelected.node());
|
||||
}
|
||||
|
||||
function toggleNewGroupInput() {
|
||||
|
|
@ -131,54 +138,44 @@ function editCoastline(node = d3.event.target) {
|
|||
}
|
||||
|
||||
function createNewGroup() {
|
||||
if (!this.value) {
|
||||
tip("Please provide a valid group name");
|
||||
return;
|
||||
}
|
||||
if (!this.value) return tip("Please provide a valid group name");
|
||||
|
||||
const group = this.value
|
||||
.toLowerCase()
|
||||
.replace(/ /g, "_")
|
||||
.replace(/[^\w\s]/gi, "");
|
||||
|
||||
if (document.getElementById(group)) {
|
||||
tip("Element with this id already exists. Please provide a unique name", false, "error");
|
||||
return;
|
||||
}
|
||||
if (byId(group)) return tip("Element with this id already exists. Please provide a unique name", false, "error");
|
||||
|
||||
if (Number.isFinite(+group.charAt(0))) {
|
||||
tip("Group name should start with a letter", false, "error");
|
||||
return;
|
||||
}
|
||||
if (Number.isFinite(+group.charAt(0))) return tip("Group name should start with a letter", false, "error");
|
||||
|
||||
// just rename if only 1 element left
|
||||
const oldGroup = elSelected.node().parentNode;
|
||||
const basic = ["sea_island", "lake_island"].includes(oldGroup.id);
|
||||
if (!basic && oldGroup.childElementCount === 1) {
|
||||
document.getElementById("coastlineGroup").selectedOptions[0].remove();
|
||||
document.getElementById("coastlineGroup").options.add(new Option(group, group, false, true));
|
||||
byId("coastlineGroup").selectedOptions[0].remove();
|
||||
byId("coastlineGroup").options.add(new Option(group, group, false, true));
|
||||
oldGroup.id = group;
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("coastlineGroupName").value = "";
|
||||
byId("coastlineGroupName").value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// create a new group
|
||||
const newGroup = elSelected.node().parentNode.cloneNode(false);
|
||||
document.getElementById("coastline").appendChild(newGroup);
|
||||
byId("coastline").appendChild(newGroup);
|
||||
newGroup.id = group;
|
||||
document.getElementById("coastlineGroup").options.add(new Option(group, group, false, true));
|
||||
document.getElementById(group).appendChild(elSelected.node());
|
||||
byId("coastlineGroup").options.add(new Option(group, group, false, true));
|
||||
byId(group).appendChild(elSelected.node());
|
||||
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("coastlineGroupName").value = "";
|
||||
byId("coastlineGroupName").value = "";
|
||||
}
|
||||
|
||||
function removeCoastlineGroup() {
|
||||
const group = elSelected.node().parentNode.id;
|
||||
if (["sea_island", "lake_island"].includes(group)) {
|
||||
tip("This is one of the default groups, it cannot be removed", false, "error");
|
||||
return;
|
||||
}
|
||||
if (["sea_island", "lake_island"].includes(group))
|
||||
return tip("This is one of the default groups, it cannot be removed", false, "error");
|
||||
|
||||
const count = elSelected.node().parentNode.childElementCount;
|
||||
alertMessage.innerHTML = /* html */ `Are you sure you want to remove the group? All coastline elements of the group (${count}) will be moved under
|
||||
|
|
@ -190,14 +187,14 @@ function editCoastline(node = d3.event.target) {
|
|||
buttons: {
|
||||
Remove: function () {
|
||||
$(this).dialog("close");
|
||||
const sea = document.getElementById("sea_island");
|
||||
const groupEl = document.getElementById(group);
|
||||
const sea = byId("sea_island");
|
||||
const groupEl = byId(group);
|
||||
while (groupEl.childNodes.length) {
|
||||
sea.appendChild(groupEl.childNodes[0]);
|
||||
}
|
||||
groupEl.remove();
|
||||
document.getElementById("coastlineGroup").selectedOptions[0].remove();
|
||||
document.getElementById("coastlineGroup").value = "sea_island";
|
||||
byId("coastlineGroup").selectedOptions[0].remove();
|
||||
byId("coastlineGroup").value = "sea_island";
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
|
|
|
|||
|
|
@ -10,31 +10,27 @@ function restoreDefaultEvents() {
|
|||
legend.call(d3.drag().on("start", dragLegendBox));
|
||||
}
|
||||
|
||||
// on viewbox click event - run function based on target
|
||||
// handle viewbox click
|
||||
function clicked() {
|
||||
const el = d3.event.target;
|
||||
if (!el || !el.parentElement || !el.parentElement.parentElement) return;
|
||||
const parent = el.parentElement;
|
||||
const grand = parent.parentElement;
|
||||
const great = grand.parentElement;
|
||||
const p = d3.mouse(this);
|
||||
const i = findCell(p[0], p[1]);
|
||||
const parent = el?.parentElement;
|
||||
const grand = parent?.parentElement;
|
||||
const great = grand?.parentElement;
|
||||
const ancestor = great?.parentElement;
|
||||
if (!ancestor) return;
|
||||
|
||||
if (grand.id === "emblems") editEmblem();
|
||||
else if (parent.id === "rivers") editRiver(el.id);
|
||||
else if (grand.id === "routes") editRoute(el.id);
|
||||
else if (el.tagName === "tspan" && grand.parentNode.parentNode.id === "labels") editLabel();
|
||||
else if (ancestor.id === "labels" && el.tagName === "tspan") editLabel();
|
||||
else if (grand.id === "burgLabels") editBurg();
|
||||
else if (grand.id === "burgIcons") editBurg();
|
||||
else if (parent.id === "ice") editIce();
|
||||
else if (parent.id === "terrain") editReliefIcon();
|
||||
else if (grand.id === "markers" || great.id === "markers") editMarker();
|
||||
else if (grand.id === "coastline") editCoastline();
|
||||
else if (grand.id === "lakes") editLake();
|
||||
else if (great.id === "armies") editRegiment();
|
||||
else if (pack.cells.t[i] === 1) {
|
||||
const node = byId("island_" + pack.cells.f[i]);
|
||||
editCoastline(node);
|
||||
} else if (grand.id === "lakes") editLake();
|
||||
}
|
||||
|
||||
// clear elSelected variable
|
||||
|
|
@ -1252,18 +1248,18 @@ function refreshAllEditors() {
|
|||
// dynamically loaded editors
|
||||
async function editStates() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/states-editor.js?v=1.99.05");
|
||||
const Editor = await import("../dynamic/editors/states-editor.js?v=1.104.0");
|
||||
Editor.open();
|
||||
}
|
||||
|
||||
async function editCultures() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.99.05");
|
||||
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.104.0");
|
||||
Editor.open();
|
||||
}
|
||||
|
||||
async function editReligions() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.99.05");
|
||||
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.104.0");
|
||||
Editor.open();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,12 +161,14 @@ function showMapTooltip(point, e, i, g) {
|
|||
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];
|
||||
const population = si(b.population * populationRate * urbanization);
|
||||
tip(`${b.name}. Population: ${population}. Click to edit`);
|
||||
if (burgsOverview?.offsetParent) highlightEditorLine(burgsOverview, burg, 5000);
|
||||
return;
|
||||
const burgId = +path[path.length - 10].dataset.id;
|
||||
if (burgId) {
|
||||
const burg = pack.burgs[burgId];
|
||||
const population = si(burg.population * populationRate * urbanization);
|
||||
tip(`${burg.name}. Population: ${population}. Click to edit`);
|
||||
if (burgsOverview?.offsetParent) highlightEditorLine(burgsOverview, burgId, 5000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (group === "labels") return tip("Click to edit the Label");
|
||||
|
|
@ -211,9 +213,9 @@ function showMapTooltip(point, e, i, g) {
|
|||
if (group === "ice") return tip("Click to edit the Ice");
|
||||
|
||||
// covering elements
|
||||
if (layerIsOn("togglePrec") && land) tip("Annual Precipitation: " + getFriendlyPrecipitation(i));
|
||||
if (layerIsOn("togglePrecipitation") && land) tip("Annual Precipitation: " + getFriendlyPrecipitation(i));
|
||||
else if (layerIsOn("togglePopulation")) tip(getPopulationTip(i));
|
||||
else if (layerIsOn("toggleTemp")) tip("Temperature: " + convertTemperature(grid.cells.temp[g]));
|
||||
else if (layerIsOn("toggleTemperature")) tip("Temperature: " + convertTemperature(grid.cells.temp[g]));
|
||||
else if (layerIsOn("toggleBiomes") && pack.cells.biome[i]) {
|
||||
const biome = pack.cells.biome[i];
|
||||
tip("Biome: " + biomesData.name[biome]);
|
||||
|
|
|
|||
|
|
@ -215,8 +215,7 @@ function editHeightmap(options) {
|
|||
pack.religions = [];
|
||||
|
||||
const erosionAllowed = allowErosion.checked;
|
||||
markFeatures();
|
||||
markupGridOcean();
|
||||
Features.markupGrid();
|
||||
if (erosionAllowed) {
|
||||
addLakesInDeepDepressions();
|
||||
openNearSeaLakes();
|
||||
|
|
@ -225,7 +224,7 @@ function editHeightmap(options) {
|
|||
calculateTemperatures();
|
||||
generatePrecipitation();
|
||||
reGraph();
|
||||
drawCoastline();
|
||||
Features.markupPack();
|
||||
|
||||
Rivers.generate(erosionAllowed);
|
||||
|
||||
|
|
@ -237,8 +236,6 @@ function editHeightmap(options) {
|
|||
}
|
||||
}
|
||||
|
||||
drawRivers();
|
||||
Lakes.defineGroup();
|
||||
Biomes.define();
|
||||
rankCells();
|
||||
|
||||
|
|
@ -249,15 +246,14 @@ function editHeightmap(options) {
|
|||
Routes.generate();
|
||||
Religions.generate();
|
||||
BurgsAndStates.defineStateForms();
|
||||
BurgsAndStates.generateProvinces();
|
||||
Provinces.generate();
|
||||
Provinces.getPoles();
|
||||
BurgsAndStates.defineBurgFeatures();
|
||||
|
||||
drawStates();
|
||||
drawBorders();
|
||||
drawStateLabels();
|
||||
|
||||
Rivers.specify();
|
||||
Lakes.generateName();
|
||||
Features.specify();
|
||||
|
||||
Military.generate();
|
||||
Markers.generate();
|
||||
|
|
@ -338,14 +334,13 @@ function editHeightmap(options) {
|
|||
zone.selectAll("*").remove();
|
||||
});
|
||||
|
||||
markFeatures();
|
||||
markupGridOcean();
|
||||
Features.markupGrid();
|
||||
if (erosionAllowed) addLakesInDeepDepressions();
|
||||
OceanLayers();
|
||||
calculateTemperatures();
|
||||
generatePrecipitation();
|
||||
reGraph();
|
||||
drawCoastline();
|
||||
Features.markupPack();
|
||||
|
||||
if (erosionAllowed) Rivers.generate(true);
|
||||
|
||||
|
|
@ -440,8 +435,6 @@ function editHeightmap(options) {
|
|||
}
|
||||
|
||||
drawStateLabels();
|
||||
drawStates();
|
||||
drawBorders();
|
||||
|
||||
if (erosionAllowed) {
|
||||
Rivers.specify();
|
||||
|
|
@ -489,10 +482,14 @@ function editHeightmap(options) {
|
|||
updateHistory();
|
||||
}
|
||||
|
||||
function getColor(value, scheme = getColorScheme()) {
|
||||
return scheme(1 - (value < 20 ? value - 5 : value) / 100);
|
||||
}
|
||||
|
||||
// draw or update heightmap
|
||||
function mockHeightmap() {
|
||||
const data = renderOcean.checked ? grid.cells.i : grid.cells.i.filter(i => grid.cells.h[i] >= 20);
|
||||
const scheme = getColorScheme();
|
||||
|
||||
viewbox
|
||||
.select("#heights")
|
||||
.selectAll("polygon")
|
||||
|
|
@ -500,13 +497,12 @@ function editHeightmap(options) {
|
|||
.join("polygon")
|
||||
.attr("points", d => getGridPolygon(d))
|
||||
.attr("id", d => "cell" + d)
|
||||
.attr("fill", d => getColor(grid.cells.h[d], scheme));
|
||||
.attr("fill", d => getColor(grid.cells.h[d]));
|
||||
}
|
||||
|
||||
// draw or update heightmap for a selection of cells
|
||||
function mockHeightmapSelection(selection) {
|
||||
const ocean = renderOcean.checked;
|
||||
const scheme = getColorScheme();
|
||||
|
||||
selection.forEach(function (i) {
|
||||
let cell = viewbox.select("#heights").select("#cell" + i);
|
||||
|
|
@ -518,7 +514,7 @@ function editHeightmap(options) {
|
|||
.append("polygon")
|
||||
.attr("points", getGridPolygon(i))
|
||||
.attr("id", "cell" + i);
|
||||
cell.attr("fill", getColor(grid.cells.h[i], scheme));
|
||||
cell.attr("fill", getColor(grid.cells.h[i]));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1349,7 +1345,7 @@ function editHeightmap(options) {
|
|||
return lum | 0; // land
|
||||
};
|
||||
|
||||
const scheme = d3.range(101).map(i => getColor(i, color()));
|
||||
const scheme = d3.range(101).map(i => getColor(i));
|
||||
const hues = scheme.map(rgb => d3.hsl(rgb).h | 0);
|
||||
const getHeightByScheme = function (color) {
|
||||
let height = scheme.indexOf(color);
|
||||
|
|
|
|||
|
|
@ -75,13 +75,13 @@ function handleKeyup(event) {
|
|||
else if (code === "KeyD") toggleBorders();
|
||||
else if (code === "KeyR") toggleReligions();
|
||||
else if (code === "KeyU") toggleRoutes();
|
||||
else if (code === "KeyT") toggleTemp();
|
||||
else if (code === "KeyT") toggleTemperature();
|
||||
else if (code === "KeyN") togglePopulation();
|
||||
else if (code === "KeyJ") toggleIce();
|
||||
else if (code === "KeyA") togglePrec();
|
||||
else if (code === "KeyA") togglePrecipitation();
|
||||
else if (code === "KeyY") toggleEmblems();
|
||||
else if (code === "KeyL") toggleLabels();
|
||||
else if (code === "KeyI") toggleIcons();
|
||||
else if (code === "KeyI") toggleBurgIcons();
|
||||
else if (code === "KeyM") toggleMilitary();
|
||||
else if (code === "KeyK") toggleMarkers();
|
||||
else if (code === "Equal" && !customization) toggleRulers();
|
||||
|
|
|
|||
|
|
@ -23,17 +23,15 @@ function editLake() {
|
|||
modules.editLake = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("lakeName").addEventListener("input", changeName);
|
||||
document.getElementById("lakeNameCulture").addEventListener("click", generateNameCulture);
|
||||
document.getElementById("lakeNameRandom").addEventListener("click", generateNameRandom);
|
||||
|
||||
document.getElementById("lakeGroup").addEventListener("change", changeLakeGroup);
|
||||
document.getElementById("lakeGroupAdd").addEventListener("click", toggleNewGroupInput);
|
||||
document.getElementById("lakeGroupName").addEventListener("change", createNewGroup);
|
||||
document.getElementById("lakeGroupRemove").addEventListener("click", removeLakeGroup);
|
||||
|
||||
document.getElementById("lakeEditStyle").addEventListener("click", editGroupStyle);
|
||||
document.getElementById("lakeLegend").addEventListener("click", editLakeLegend);
|
||||
byId("lakeName").on("input", changeName);
|
||||
byId("lakeNameCulture").on("click", generateNameCulture);
|
||||
byId("lakeNameRandom").on("click", generateNameRandom);
|
||||
byId("lakeGroup").on("change", changeLakeGroup);
|
||||
byId("lakeGroupAdd").on("click", toggleNewGroupInput);
|
||||
byId("lakeGroupName").on("change", createNewGroup);
|
||||
byId("lakeGroupRemove").on("click", removeLakeGroup);
|
||||
byId("lakeEditStyle").on("click", editGroupStyle);
|
||||
byId("lakeLegend").on("click", editLakeLegend);
|
||||
|
||||
function getLake() {
|
||||
const lakeId = +elSelected.attr("data-f");
|
||||
|
|
@ -41,85 +39,91 @@ function editLake() {
|
|||
}
|
||||
|
||||
function updateLakeValues() {
|
||||
const cells = pack.cells;
|
||||
const {cells, vertices, rivers} = pack;
|
||||
|
||||
const l = getLake();
|
||||
document.getElementById("lakeName").value = l.name;
|
||||
document.getElementById("lakeArea").value = si(getArea(l.area)) + " " + getAreaUnit();
|
||||
byId("lakeName").value = l.name;
|
||||
byId("lakeArea").value = si(getArea(l.area)) + " " + getAreaUnit();
|
||||
|
||||
const length = d3.polygonLength(l.vertices.map(v => pack.vertices.p[v]));
|
||||
document.getElementById("lakeShoreLength").value = si(length * distanceScale) + " " + distanceUnitInput.value;
|
||||
const length = d3.polygonLength(l.vertices.map(v => vertices.p[v]));
|
||||
byId("lakeShoreLength").value = si(length * distanceScale) + " " + distanceUnitInput.value;
|
||||
|
||||
const lakeCells = Array.from(cells.i.filter(i => cells.f[i] === l.i));
|
||||
const heights = lakeCells.map(i => cells.h[i]);
|
||||
|
||||
document.getElementById("lakeElevation").value = getHeight(l.height);
|
||||
document.getElementById("lakeAverageDepth").value = getHeight(d3.mean(heights), "abs");
|
||||
document.getElementById("lakeMaxDepth").value = getHeight(d3.min(heights), "abs");
|
||||
byId("lakeElevation").value = getHeight(l.height);
|
||||
byId("lakeAverageDepth").value = getHeight(d3.mean(heights), "abs");
|
||||
byId("lakeMaxDepth").value = getHeight(d3.min(heights), "abs");
|
||||
|
||||
document.getElementById("lakeFlux").value = l.flux;
|
||||
document.getElementById("lakeEvaporation").value = l.evaporation;
|
||||
byId("lakeFlux").value = l.flux;
|
||||
byId("lakeEvaporation").value = l.evaporation;
|
||||
|
||||
const inlets = l.inlets && l.inlets.map(inlet => pack.rivers.find(river => river.i === inlet)?.name);
|
||||
const outlet = l.outlet ? pack.rivers.find(river => river.i === l.outlet)?.name : "no";
|
||||
document.getElementById("lakeInlets").value = inlets ? inlets.length : "no";
|
||||
document.getElementById("lakeInlets").title = inlets ? inlets.join(", ") : "";
|
||||
document.getElementById("lakeOutlet").value = outlet;
|
||||
const inlets = l.inlets && l.inlets.map(inlet => rivers.find(river => river.i === inlet)?.name);
|
||||
const outlet = l.outlet ? rivers.find(river => river.i === l.outlet)?.name : "no";
|
||||
byId("lakeInlets").value = inlets ? inlets.length : "no";
|
||||
byId("lakeInlets").title = inlets ? inlets.join(", ") : "";
|
||||
byId("lakeOutlet").value = outlet;
|
||||
}
|
||||
|
||||
function drawLakeVertices() {
|
||||
const v = getLake().vertices; // lake outer vertices
|
||||
const vertices = getLake().vertices;
|
||||
|
||||
const c = [...new Set(v.map(v => pack.vertices.c[v]).flat())];
|
||||
const neibCells = unique(vertices.map(v => pack.vertices.c[v]).flat());
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("polygon")
|
||||
.data(c)
|
||||
.data(neibCells)
|
||||
.enter()
|
||||
.append("polygon")
|
||||
.attr("points", d => getPackPolygon(d))
|
||||
.attr("points", getPackPolygon)
|
||||
.attr("data-c", d => d);
|
||||
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("circle")
|
||||
.data(v)
|
||||
.data(vertices)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", d => pack.vertices.p[d][0])
|
||||
.attr("cy", d => pack.vertices.p[d][1])
|
||||
.attr("r", 0.4)
|
||||
.attr("data-v", d => d)
|
||||
.call(d3.drag().on("drag", dragVertex))
|
||||
.call(d3.drag().on("drag", handleVertexDrag).on("end", handleVertexDragEnd))
|
||||
.on("mousemove", () =>
|
||||
tip("Drag to move the vertex, please use for fine-tuning only. Edit heightmap to change actual cell heights")
|
||||
tip("Drag to move the vertex. Please use for fine-tuning only! Edit heightmap to change actual cell heights")
|
||||
);
|
||||
}
|
||||
|
||||
function dragVertex() {
|
||||
const x = rn(d3.event.x, 2),
|
||||
y = rn(d3.event.y, 2);
|
||||
function handleVertexDrag() {
|
||||
const x = rn(d3.event.x, 2);
|
||||
const y = rn(d3.event.y, 2);
|
||||
this.setAttribute("cx", x);
|
||||
this.setAttribute("cy", y);
|
||||
const v = +this.dataset.v;
|
||||
pack.vertices.p[v] = [x, y];
|
||||
debug
|
||||
.select("#vertices")
|
||||
.selectAll("polygon")
|
||||
.attr("points", d => getPackPolygon(d));
|
||||
redrawLake();
|
||||
|
||||
const vertexId = d3.select(this).datum();
|
||||
pack.vertices.p[vertexId] = [x, y];
|
||||
|
||||
const feature = getLake();
|
||||
|
||||
// update lake path
|
||||
defs.select("#featurePaths > path#feature_" + feature.i).attr("d", getFeaturePath(feature));
|
||||
|
||||
// update area
|
||||
const points = feature.vertices.map(vertex => pack.vertices.p[vertex]);
|
||||
feature.area = Math.abs(d3.polygonArea(points));
|
||||
byId("lakeArea").value = si(getArea(feature.area)) + " " + getAreaUnit();
|
||||
|
||||
// update cell
|
||||
debug.select("#vertices").selectAll("polygon").attr("points", getPackPolygon);
|
||||
}
|
||||
|
||||
function redrawLake() {
|
||||
lineGen.curve(d3.curveBasisClosed);
|
||||
const feature = getLake();
|
||||
const points = feature.vertices.map(v => pack.vertices.p[v]);
|
||||
const d = round(lineGen(points));
|
||||
elSelected.attr("d", d);
|
||||
defs.select("mask#land > path#land_" + feature.i).attr("d", d); // update land mask
|
||||
|
||||
feature.area = Math.abs(d3.polygonArea(points));
|
||||
document.getElementById("lakeArea").value = si(getArea(feature.area)) + " " + getAreaUnit();
|
||||
function handleVertexDragEnd() {
|
||||
if (layerIsOn("toggleStates")) drawStates();
|
||||
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
if (layerIsOn("toggleBiomes")) drawBiomes();
|
||||
if (layerIsOn("toggleReligions")) drawReligions();
|
||||
if (layerIsOn("toggleCultures")) drawCultures();
|
||||
}
|
||||
|
||||
function changeName() {
|
||||
|
|
@ -138,7 +142,7 @@ function editLake() {
|
|||
|
||||
function selectLakeGroup(node) {
|
||||
const group = node.parentNode.id;
|
||||
const select = document.getElementById("lakeGroup");
|
||||
const select = byId("lakeGroup");
|
||||
select.options.length = 0; // remove all options
|
||||
|
||||
lakes.selectAll("g").each(function () {
|
||||
|
|
@ -147,7 +151,7 @@ function editLake() {
|
|||
}
|
||||
|
||||
function changeLakeGroup() {
|
||||
document.getElementById(this.value).appendChild(elSelected.node());
|
||||
byId(this.value).appendChild(elSelected.node());
|
||||
getLake().group = this.value;
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +176,7 @@ function editLake() {
|
|||
.replace(/ /g, "_")
|
||||
.replace(/[^\w\s]/gi, "");
|
||||
|
||||
if (document.getElementById(group)) {
|
||||
if (byId(group)) {
|
||||
tip("Element with this id already exists. Please provide a unique name", false, "error");
|
||||
return;
|
||||
}
|
||||
|
|
@ -186,23 +190,23 @@ function editLake() {
|
|||
const oldGroup = elSelected.node().parentNode;
|
||||
const basic = ["freshwater", "salt", "sinkhole", "frozen", "lava", "dry"].includes(oldGroup.id);
|
||||
if (!basic && oldGroup.childElementCount === 1) {
|
||||
document.getElementById("lakeGroup").selectedOptions[0].remove();
|
||||
document.getElementById("lakeGroup").options.add(new Option(group, group, false, true));
|
||||
byId("lakeGroup").selectedOptions[0].remove();
|
||||
byId("lakeGroup").options.add(new Option(group, group, false, true));
|
||||
oldGroup.id = group;
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("lakeGroupName").value = "";
|
||||
byId("lakeGroupName").value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// create a new group
|
||||
const newGroup = elSelected.node().parentNode.cloneNode(false);
|
||||
document.getElementById("lakes").appendChild(newGroup);
|
||||
byId("lakes").appendChild(newGroup);
|
||||
newGroup.id = group;
|
||||
document.getElementById("lakeGroup").options.add(new Option(group, group, false, true));
|
||||
document.getElementById(group).appendChild(elSelected.node());
|
||||
byId("lakeGroup").options.add(new Option(group, group, false, true));
|
||||
byId(group).appendChild(elSelected.node());
|
||||
|
||||
toggleNewGroupInput();
|
||||
document.getElementById("lakeGroupName").value = "";
|
||||
byId("lakeGroupName").value = "";
|
||||
}
|
||||
|
||||
function removeLakeGroup() {
|
||||
|
|
@ -221,14 +225,14 @@ function editLake() {
|
|||
buttons: {
|
||||
Remove: function () {
|
||||
$(this).dialog("close");
|
||||
const freshwater = document.getElementById("freshwater");
|
||||
const groupEl = document.getElementById(group);
|
||||
const freshwater = byId("freshwater");
|
||||
const groupEl = byId(group);
|
||||
while (groupEl.childNodes.length) {
|
||||
freshwater.appendChild(groupEl.childNodes[0]);
|
||||
}
|
||||
groupEl.remove();
|
||||
document.getElementById("lakeGroup").selectedOptions[0].remove();
|
||||
document.getElementById("lakeGroup").value = "freshwater";
|
||||
byId("lakeGroup").selectedOptions[0].remove();
|
||||
byId("lakeGroup").value = "freshwater";
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
|
|
|
|||
1578
modules/ui/layers.js
1578
modules/ui/layers.js
File diff suppressed because it is too large
Load diff
|
|
@ -530,3 +530,32 @@ class Planimeter extends Measurer {
|
|||
this.el.select("text").attr("x", c[0]).attr("y", c[1]).text(area);
|
||||
}
|
||||
}
|
||||
|
||||
function createDefaultRuler() {
|
||||
TIME && console.time("createDefaultRuler");
|
||||
const {features, vertices} = pack;
|
||||
|
||||
const areas = features.map(f => (f.land ? f.area || 0 : -Infinity));
|
||||
const largestLand = areas.indexOf(Math.max(...areas));
|
||||
const featureVertices = features[largestLand].vertices;
|
||||
|
||||
const MIN_X = 100;
|
||||
const MAX_X = graphWidth - 100;
|
||||
const MIN_Y = 100;
|
||||
const MAX_Y = graphHeight - 100;
|
||||
|
||||
let leftmostVertex = [graphWidth - MIN_X, graphHeight / 2];
|
||||
let rightmostVertex = [MIN_X, graphHeight / 2];
|
||||
|
||||
for (const vertex of featureVertices) {
|
||||
const [x, y] = vertices.p[vertex];
|
||||
if (y < MIN_Y || y > MAX_Y) continue;
|
||||
if (x < leftmostVertex[0] && x >= MIN_X) leftmostVertex = [x, y];
|
||||
if (x > rightmostVertex[0] && x <= MAX_X) rightmostVertex = [x, y];
|
||||
}
|
||||
|
||||
rulers = new Rulers();
|
||||
rulers.create(Ruler, [leftmostVertex, rightmostVertex]);
|
||||
|
||||
TIME && console.timeEnd("createDefaultRuler");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ function editProvinces() {
|
|||
if (layerIsOn("toggleCultures")) toggleCultures();
|
||||
|
||||
provs.selectAll("text").call(d3.drag().on("drag", dragLabel)).classed("draggable", true);
|
||||
const body = document.getElementById("provincesBodySection");
|
||||
const body = byId("provincesBodySection");
|
||||
refreshProvincesEditor();
|
||||
|
||||
if (modules.editProvinces) return;
|
||||
|
|
@ -23,22 +23,22 @@ function editProvinces() {
|
|||
});
|
||||
|
||||
// add listeners
|
||||
document.getElementById("provincesEditorRefresh").addEventListener("click", refreshProvincesEditor);
|
||||
document.getElementById("provincesEditStyle").addEventListener("click", () => editStyle("provs"));
|
||||
document.getElementById("provincesFilterState").addEventListener("change", provincesEditorAddLines);
|
||||
document.getElementById("provincesPercentage").addEventListener("click", togglePercentageMode);
|
||||
document.getElementById("provincesChart").addEventListener("click", showChart);
|
||||
document.getElementById("provincesToggleLabels").addEventListener("click", toggleLabels);
|
||||
document.getElementById("provincesExport").addEventListener("click", downloadProvincesData);
|
||||
document.getElementById("provincesRemoveAll").addEventListener("click", removeAllProvinces);
|
||||
document.getElementById("provincesManually").addEventListener("click", enterProvincesManualAssignent);
|
||||
document.getElementById("provincesManuallyApply").addEventListener("click", applyProvincesManualAssignent);
|
||||
document.getElementById("provincesManuallyCancel").addEventListener("click", () => exitProvincesManualAssignment());
|
||||
document.getElementById("provincesRelease").addEventListener("click", triggerProvincesRelease);
|
||||
document.getElementById("provincesAdd").addEventListener("click", enterAddProvinceMode);
|
||||
document.getElementById("provincesRecolor").addEventListener("click", recolorProvinces);
|
||||
byId("provincesEditorRefresh").on("click", refreshProvincesEditor);
|
||||
byId("provincesEditStyle").on("click", () => editStyle("provs"));
|
||||
byId("provincesFilterState").on("change", provincesEditorAddLines);
|
||||
byId("provincesPercentage").on("click", togglePercentageMode);
|
||||
byId("provincesChart").on("click", showChart);
|
||||
byId("provincesToggleLabels").on("click", toggleLabels);
|
||||
byId("provincesExport").on("click", downloadProvincesData);
|
||||
byId("provincesRemoveAll").on("click", removeAllProvinces);
|
||||
byId("provincesManually").on("click", enterProvincesManualAssignent);
|
||||
byId("provincesManuallyApply").on("click", applyProvincesManualAssignent);
|
||||
byId("provincesManuallyCancel").on("click", () => exitProvincesManualAssignment());
|
||||
byId("provincesRelease").on("click", triggerProvincesRelease);
|
||||
byId("provincesAdd").on("click", enterAddProvinceMode);
|
||||
byId("provincesRecolor").on("click", recolorProvinces);
|
||||
|
||||
body.addEventListener("click", function (ev) {
|
||||
body.on("click", function (ev) {
|
||||
if (customization) return;
|
||||
const el = ev.target,
|
||||
cl = el.classList,
|
||||
|
|
@ -58,7 +58,7 @@ function editProvinces() {
|
|||
else if (cl.contains("icon-lock") || cl.contains("icon-lock-open")) updateLockStatus(p, cl);
|
||||
});
|
||||
|
||||
body.addEventListener("change", function (ev) {
|
||||
body.on("change", function (ev) {
|
||||
const el = ev.target,
|
||||
cl = el.classList,
|
||||
line = el.parentNode,
|
||||
|
|
@ -100,7 +100,7 @@ function editProvinces() {
|
|||
}
|
||||
|
||||
function updateFilter() {
|
||||
const stateFilter = document.getElementById("provincesFilterState");
|
||||
const stateFilter = byId("provincesFilterState");
|
||||
const selectedState = stateFilter.value || 1;
|
||||
stateFilter.options.length = 0; // remove all options
|
||||
stateFilter.options.add(new Option(`all`, -1, false, selectedState == -1));
|
||||
|
|
@ -111,7 +111,7 @@ function editProvinces() {
|
|||
// add line for each province
|
||||
function provincesEditorAddLines() {
|
||||
const unit = " " + getAreaUnit();
|
||||
const selectedState = +document.getElementById("provincesFilterState").value;
|
||||
const selectedState = +byId("provincesFilterState").value;
|
||||
let filtered = pack.provinces.filter(p => p.i && !p.removed); // all valid burgs
|
||||
if (selectedState != -1) filtered = filtered.filter(p => p.state === selectedState); // filtered by state
|
||||
body.innerHTML = "";
|
||||
|
|
@ -194,9 +194,9 @@ function editProvinces() {
|
|||
byId("provincesFooterPopulation").dataset.population = totalPopulation;
|
||||
|
||||
body.querySelectorAll("div.states").forEach(el => {
|
||||
el.addEventListener("click", selectProvinceOnLineClick);
|
||||
el.addEventListener("mouseenter", ev => provinceHighlightOn(ev));
|
||||
el.addEventListener("mouseleave", ev => provinceHighlightOff(ev));
|
||||
el.on("click", selectProvinceOnLineClick);
|
||||
el.on("mouseenter", ev => provinceHighlightOn(ev));
|
||||
el.on("mouseleave", ev => provinceHighlightOff(ev));
|
||||
});
|
||||
|
||||
if (body.dataset.type === "percentage") {
|
||||
|
|
@ -306,7 +306,7 @@ function editProvinces() {
|
|||
const {cell: center, culture} = burgs[burgId];
|
||||
const color = getRandomColor();
|
||||
const coa = province.coa;
|
||||
const coaEl = document.getElementById("provinceCOA" + provinceId);
|
||||
const coaEl = byId("provinceCOA" + provinceId);
|
||||
if (coaEl) coaEl.id = "stateCOA" + newStateId;
|
||||
emblems.select(`#provinceEmblems > use[data-i='${provinceId}']`).remove();
|
||||
|
||||
|
|
@ -454,6 +454,7 @@ function editProvinces() {
|
|||
p.burgs.forEach(b => (pack.burgs[b].population = population));
|
||||
}
|
||||
|
||||
if (layerIsOn("togglePopulation")) drawPopulation();
|
||||
refreshProvincesEditor();
|
||||
}
|
||||
}
|
||||
|
|
@ -482,7 +483,7 @@ function editProvinces() {
|
|||
unfog("focusProvince" + p);
|
||||
|
||||
const coaId = "provinceCOA" + p;
|
||||
if (document.getElementById(coaId)) document.getElementById(coaId).remove();
|
||||
if (byId(coaId)) byId(coaId).remove();
|
||||
emblems.select(`#provinceEmblems > use[data-i='${p}']`).remove();
|
||||
|
||||
pack.provinces[p] = {i: p, removed: true};
|
||||
|
|
@ -490,8 +491,7 @@ function editProvinces() {
|
|||
const g = provs.select("#provincesBody");
|
||||
g.select("#province" + p).remove();
|
||||
g.select("#province-gap" + p).remove();
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
else drawBorders();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
refreshProvincesEditor();
|
||||
$(this).dialog("close");
|
||||
},
|
||||
|
|
@ -504,13 +504,13 @@ function editProvinces() {
|
|||
|
||||
function editProvinceName(province) {
|
||||
const p = pack.provinces[province];
|
||||
document.getElementById("provinceNameEditor").dataset.province = province;
|
||||
document.getElementById("provinceNameEditorShort").value = p.name;
|
||||
byId("provinceNameEditor").dataset.province = province;
|
||||
byId("provinceNameEditorShort").value = p.name;
|
||||
applyOption(provinceNameEditorSelectForm, p.formName);
|
||||
document.getElementById("provinceNameEditorFull").value = p.fullName;
|
||||
byId("provinceNameEditorFull").value = p.fullName;
|
||||
|
||||
const cultureId = pack.cells.culture[p.center];
|
||||
document.getElementById("provinceCultureDisplay").innerText = pack.cultures[cultureId].name;
|
||||
byId("provinceCultureDisplay").innerText = pack.cultures[cultureId].name;
|
||||
|
||||
$("#provinceNameEditor").dialog({
|
||||
resizable: false,
|
||||
|
|
@ -531,22 +531,22 @@ function editProvinces() {
|
|||
modules.editProvinceName = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("provinceNameEditorShortCulture").addEventListener("click", regenerateShortNameCulture);
|
||||
document.getElementById("provinceNameEditorShortRandom").addEventListener("click", regenerateShortNameRandom);
|
||||
document.getElementById("provinceNameEditorAddForm").addEventListener("click", addCustomForm);
|
||||
document.getElementById("provinceNameEditorFullRegenerate").addEventListener("click", regenerateFullName);
|
||||
byId("provinceNameEditorShortCulture").on("click", regenerateShortNameCulture);
|
||||
byId("provinceNameEditorShortRandom").on("click", regenerateShortNameRandom);
|
||||
byId("provinceNameEditorAddForm").on("click", addCustomForm);
|
||||
byId("provinceNameEditorFullRegenerate").on("click", regenerateFullName);
|
||||
|
||||
function regenerateShortNameCulture() {
|
||||
const province = +provinceNameEditor.dataset.province;
|
||||
const culture = pack.cells.culture[pack.provinces[province].center];
|
||||
const name = Names.getState(Names.getCultureShort(culture), culture);
|
||||
document.getElementById("provinceNameEditorShort").value = name;
|
||||
byId("provinceNameEditorShort").value = name;
|
||||
}
|
||||
|
||||
function regenerateShortNameRandom() {
|
||||
const base = rand(nameBases.length - 1);
|
||||
const name = Names.getState(Names.getBase(base), undefined, base);
|
||||
document.getElementById("provinceNameEditorShort").value = name;
|
||||
byId("provinceNameEditorShort").value = name;
|
||||
}
|
||||
|
||||
function addCustomForm() {
|
||||
|
|
@ -558,9 +558,9 @@ function editProvinces() {
|
|||
}
|
||||
|
||||
function regenerateFullName() {
|
||||
const short = document.getElementById("provinceNameEditorShort").value;
|
||||
const form = document.getElementById("provinceNameEditorSelectForm").value;
|
||||
document.getElementById("provinceNameEditorFull").value = getFullName();
|
||||
const short = byId("provinceNameEditorShort").value;
|
||||
const form = byId("provinceNameEditorSelectForm").value;
|
||||
byId("provinceNameEditorFull").value = getFullName();
|
||||
|
||||
function getFullName() {
|
||||
if (!form) return short;
|
||||
|
|
@ -570,9 +570,9 @@ function editProvinces() {
|
|||
}
|
||||
|
||||
function applyNameChange(p) {
|
||||
p.name = document.getElementById("provinceNameEditorShort").value;
|
||||
p.formName = document.getElementById("provinceNameEditorSelectForm").value;
|
||||
p.fullName = document.getElementById("provinceNameEditorFull").value;
|
||||
p.name = byId("provinceNameEditorShort").value;
|
||||
p.formName = byId("provinceNameEditorSelectForm").value;
|
||||
p.fullName = byId("provinceNameEditorFull").value;
|
||||
provs.select("#provinceLabel" + p.i).text(p.name);
|
||||
refreshProvincesEditor();
|
||||
}
|
||||
|
|
@ -651,7 +651,7 @@ function editProvinces() {
|
|||
.attr("height", height)
|
||||
.attr("font-size", "10px");
|
||||
const graph = svg.append("g").attr("transform", `translate(10, 0)`);
|
||||
document.getElementById("provincesTreeType").addEventListener("change", updateChart);
|
||||
byId("provincesTreeType").on("change", updateChart);
|
||||
|
||||
treeLayout(root);
|
||||
|
||||
|
|
@ -688,7 +688,7 @@ function editProvinces() {
|
|||
|
||||
function hideInfo(ev) {
|
||||
provinceHighlightOff(ev);
|
||||
if (!document.getElementById("provinceInfo")) return;
|
||||
if (!byId("provinceInfo")) return;
|
||||
provinceInfo.innerHTML = "‍";
|
||||
d3.select(ev.target).select("rect").classed("selected", 0);
|
||||
}
|
||||
|
|
@ -816,7 +816,7 @@ function editProvinces() {
|
|||
stateBorders.select("path").attr("stroke", "#000").attr("stroke-width", 1.2);
|
||||
|
||||
customization = 11;
|
||||
provs.select("g#provincesBody").append("g").attr("id", "temp");
|
||||
provs.select("g#provincesBody").append("g").attr("id", "temp").attr("stroke-width", 0.3);
|
||||
provs
|
||||
.select("g#provincesBody")
|
||||
.append("g")
|
||||
|
|
@ -826,7 +826,7 @@ function editProvinces() {
|
|||
.attr("stroke-width", 1);
|
||||
|
||||
document.querySelectorAll("#provincesBottom > *").forEach(el => (el.style.display = "none"));
|
||||
document.getElementById("provincesManuallyButtons").style.display = "inline-block";
|
||||
byId("provincesManuallyButtons").style.display = "inline-block";
|
||||
|
||||
provincesEditor.querySelectorAll(".hide").forEach(el => el.classList.add("hidden"));
|
||||
provincesHeader.querySelector("div[data-sortby='state']").style.left = "7.7em";
|
||||
|
|
@ -950,10 +950,10 @@ function editProvinces() {
|
|||
pack.cells.province[i] = +this.dataset.province;
|
||||
});
|
||||
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
else drawBorders();
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces();
|
||||
else drawProvinces();
|
||||
Provinces.getPoles();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||
|
||||
exitProvincesManualAssignment();
|
||||
refreshProvincesEditor();
|
||||
}
|
||||
|
|
@ -970,7 +970,7 @@ function editProvinces() {
|
|||
debug.selectAll("path.selected").remove();
|
||||
|
||||
document.querySelectorAll("#provincesBottom > *").forEach(el => (el.style.display = "inline-block"));
|
||||
document.getElementById("provincesManuallyButtons").style.display = "none";
|
||||
byId("provincesManuallyButtons").style.display = "none";
|
||||
|
||||
provincesEditor.querySelectorAll(".hide:not(.show)").forEach(el => el.classList.remove("hidden"));
|
||||
provincesHeader.querySelector("div[data-sortby='state']").style.left = "22em";
|
||||
|
|
@ -1044,12 +1044,11 @@ function editProvinces() {
|
|||
cells.province[c] = province;
|
||||
});
|
||||
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
else drawBorders();
|
||||
if (!layerIsOn("toggleProvinces")) toggleProvinces();
|
||||
else drawProvinces();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||
|
||||
collectStatistics();
|
||||
document.getElementById("provincesFilterState").value = state;
|
||||
byId("provincesFilterState").value = state;
|
||||
provincesEditorAddLines();
|
||||
}
|
||||
|
||||
|
|
@ -1062,7 +1061,7 @@ function editProvinces() {
|
|||
}
|
||||
|
||||
function recolorProvinces() {
|
||||
const state = +document.getElementById("provincesFilterState").value;
|
||||
const state = +byId("provincesFilterState").value;
|
||||
|
||||
pack.provinces.forEach(p => {
|
||||
if (!p || p.removed) return;
|
||||
|
|
@ -1120,8 +1119,7 @@ function editProvinces() {
|
|||
pack.states.forEach(s => (s.provinces = []));
|
||||
|
||||
unfog();
|
||||
if (!layerIsOn("toggleBorders")) toggleBorders();
|
||||
else drawBorders();
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
provs.select("#provincesBody").remove();
|
||||
turnButtonOff("toggleProvinces");
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ function editRegiment(selector) {
|
|||
reg.name = Military.getName(reg, military);
|
||||
military.push(reg);
|
||||
Military.generateNote(reg, pack.states[state]); // add legend
|
||||
Military.drawRegiment(reg, state);
|
||||
drawRegiment(reg, state);
|
||||
if (regimentsOverviewRefresh.offsetParent) regimentsOverviewRefresh.click();
|
||||
toggleAdd();
|
||||
}
|
||||
|
|
@ -296,7 +296,7 @@ function editRegiment(selector) {
|
|||
(defender.px = defender.x), (defender.py = defender.y);
|
||||
|
||||
// move attacker to defender
|
||||
Military.moveRegiment(attacker, defender.x, defender.y - 8);
|
||||
moveRegiment(attacker, defender.x, defender.y - 8);
|
||||
|
||||
// draw battle icon
|
||||
const attack = d3
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ function overviewRegiments(state) {
|
|||
reg.name = Military.getName(reg, military);
|
||||
military.push(reg);
|
||||
Military.generateNote(reg, pack.states[state]); // add legend
|
||||
Military.drawRegiment(reg, state);
|
||||
drawRegiment(reg, state);
|
||||
toggleAdd();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ function getColorScheme(scheme = "bright") {
|
|||
return heightmapColorSchemes[scheme];
|
||||
}
|
||||
|
||||
function getColor(value, scheme = getColorScheme("bright")) {
|
||||
return scheme(1 - (value < 20 ? value - 5 : value) / 100);
|
||||
}
|
||||
|
||||
// Toggle style sections on element select
|
||||
styleElementSelect.on("change", selectStyleElement);
|
||||
|
||||
|
|
@ -114,6 +118,7 @@ function selectStyleElement() {
|
|||
"armies",
|
||||
"routes",
|
||||
"lakes",
|
||||
"biomes",
|
||||
"borders",
|
||||
"cults",
|
||||
"relig",
|
||||
|
|
@ -952,7 +957,7 @@ styleArmiesSize.on("input", e => {
|
|||
armies.selectAll("g").remove(); // clear armies layer
|
||||
pack.states.forEach(s => {
|
||||
if (!s.i || s.removed || !s.military.length) return;
|
||||
Military.drawRegiments(s.military, s.i);
|
||||
drawRegiments(s.military, s.i);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ window.UISubmap = (function () {
|
|||
fullMap: true,
|
||||
noLabels: true,
|
||||
noScaleBar: true,
|
||||
noVignette: true,
|
||||
noIce: true
|
||||
});
|
||||
|
||||
|
|
@ -282,7 +283,7 @@ window.UISubmap = (function () {
|
|||
|
||||
oldstate = null; // destroy old state to free memory
|
||||
|
||||
restoreLayers();
|
||||
drawLayers();
|
||||
if (ThreeD.options.isOn) ThreeD.redraw();
|
||||
if ($("#worldConfigurator").is(":visible")) editWorld();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,8 +75,10 @@ toolsContent.addEventListener("click", function (event) {
|
|||
});
|
||||
|
||||
function processFeatureRegeneration(event, button) {
|
||||
if (button === "regenerateStateLabels") drawStateLabels();
|
||||
else if (button === "regenerateReliefIcons") {
|
||||
if (button === "regenerateStateLabels") {
|
||||
$("#labels").fadeIn();
|
||||
drawStateLabels();
|
||||
} else if (button === "regenerateReliefIcons") {
|
||||
ReliefIcons.draw();
|
||||
if (!layerIsOn("toggleRelief")) toggleRelief();
|
||||
} else if (button === "regenerateRoutes") {
|
||||
|
|
@ -126,14 +128,14 @@ function regenerateRoutes() {
|
|||
|
||||
function regenerateRivers() {
|
||||
Rivers.generate();
|
||||
Lakes.defineGroup();
|
||||
Rivers.specify();
|
||||
if (!layerIsOn("toggleRivers")) toggleRivers();
|
||||
else drawRivers();
|
||||
Features.specify();
|
||||
if (layerIsOn("toggleRivers")) drawRivers();
|
||||
}
|
||||
|
||||
function recalculatePopulation() {
|
||||
rankCells();
|
||||
|
||||
pack.burgs.forEach(b => {
|
||||
if (!b.i || b.removed || b.lock) return;
|
||||
const i = b.cell;
|
||||
|
|
@ -143,6 +145,8 @@ function recalculatePopulation() {
|
|||
if (b.port) b.population = b.population * 1.3; // increase port population
|
||||
b.population = rn(b.population * gauss(2, 3, 0.6, 20, 3), 3);
|
||||
});
|
||||
|
||||
layerIsOn("togglePopulation") ? drawPopulation() : togglePopulation();
|
||||
}
|
||||
|
||||
function regenerateStates() {
|
||||
|
|
@ -152,12 +156,14 @@ function regenerateStates() {
|
|||
pack.states = newStates;
|
||||
BurgsAndStates.expandStates();
|
||||
BurgsAndStates.normalizeStates();
|
||||
BurgsAndStates.getPoles();
|
||||
BurgsAndStates.collectStatistics();
|
||||
BurgsAndStates.assignColors();
|
||||
BurgsAndStates.generateCampaigns();
|
||||
BurgsAndStates.generateDiplomacy();
|
||||
BurgsAndStates.defineStateForms();
|
||||
BurgsAndStates.generateProvinces(true);
|
||||
Provinces.generate(true);
|
||||
Provinces.getPoles();
|
||||
|
||||
layerIsOn("toggleStates") ? drawStates() : toggleStates();
|
||||
layerIsOn("toggleBorders") ? drawBorders() : toggleBorders();
|
||||
|
|
@ -332,9 +338,11 @@ function recreateStates() {
|
|||
function regenerateProvinces() {
|
||||
unfog();
|
||||
|
||||
BurgsAndStates.generateProvinces(true, true);
|
||||
drawBorders();
|
||||
if (layerIsOn("toggleProvinces")) drawProvinces();
|
||||
Provinces.generate(true, true);
|
||||
Provinces.getPoles();
|
||||
|
||||
if (layerIsOn("toggleBorders")) drawBorders();
|
||||
layerIsOn("toggleProvinces") ? drawProvinces() : toggleProvinces();
|
||||
|
||||
// remove emblems
|
||||
document.querySelectorAll("[id^=provinceCOA]").forEach(el => el.remove());
|
||||
|
|
@ -437,9 +445,11 @@ function regenerateBurgs() {
|
|||
|
||||
BurgsAndStates.specifyBurgs();
|
||||
BurgsAndStates.defineBurgFeatures();
|
||||
BurgsAndStates.drawBurgs();
|
||||
regenerateRoutes();
|
||||
|
||||
drawBurgIcons();
|
||||
drawBurgLabels();
|
||||
|
||||
// remove emblems
|
||||
document.querySelectorAll("[id^=burgCOA]").forEach(el => el.remove());
|
||||
emblems.selectAll("use").remove();
|
||||
|
|
@ -498,13 +508,13 @@ function regenerateEmblems() {
|
|||
province.coa.shield = COA.getShield(culture, province.state);
|
||||
});
|
||||
|
||||
if (layerIsOn("toggleEmblems")) drawEmblems(); // redrawEmblems
|
||||
layerIsOn("toggleEmblems") ? drawEmblems() : toggleEmblems();
|
||||
}
|
||||
|
||||
function regenerateReligions() {
|
||||
Religions.generate();
|
||||
if (!layerIsOn("toggleReligions")) toggleReligions();
|
||||
else drawReligions();
|
||||
if (layerIsOn("toggleReligions")) drawReligions();
|
||||
else toggleReligions();
|
||||
refreshAllEditors();
|
||||
}
|
||||
|
||||
|
|
@ -520,7 +530,9 @@ function regenerateCultures() {
|
|||
|
||||
function regenerateMilitary() {
|
||||
Military.generate();
|
||||
if (!layerIsOn("toggleMilitary")) toggleMilitary();
|
||||
if (layerIsOn("toggleMilitary")) drawMilitary();
|
||||
else toggleMilitary();
|
||||
|
||||
if (byId("militaryOverviewRefresh").offsetParent) militaryOverviewRefresh.click();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ function editUnits() {
|
|||
|
||||
function changeHeightExponent() {
|
||||
calculateTemperatures();
|
||||
if (layerIsOn("toggleTemp")) drawTemp();
|
||||
if (layerIsOn("toggleTemperature")) drawTemperature();
|
||||
}
|
||||
|
||||
function changeTemperatureScale() {
|
||||
if (layerIsOn("toggleTemp")) drawTemp();
|
||||
if (layerIsOn("toggleTemperature")) drawTemperature();
|
||||
}
|
||||
|
||||
function changePopulationRate() {
|
||||
|
|
|
|||
|
|
@ -86,13 +86,13 @@ function editWorld() {
|
|||
generatePrecipitation();
|
||||
const heights = new Uint8Array(pack.cells.h);
|
||||
Rivers.generate();
|
||||
Lakes.defineGroup();
|
||||
Rivers.specify();
|
||||
pack.cells.h = new Float32Array(heights);
|
||||
Biomes.define();
|
||||
Features.specify();
|
||||
|
||||
if (layerIsOn("toggleTemp")) drawTemp();
|
||||
if (layerIsOn("togglePrec")) drawPrec();
|
||||
if (layerIsOn("toggleTemperature")) drawTemperature();
|
||||
if (layerIsOn("togglePrecipitation")) drawPrecipitation();
|
||||
if (layerIsOn("toggleBiomes")) drawBiomes();
|
||||
if (layerIsOn("toggleCoordinates")) drawCoordinates();
|
||||
if (layerIsOn("toggleRivers")) drawRivers();
|
||||
|
|
|
|||
|
|
@ -472,6 +472,7 @@ function editZones() {
|
|||
burgs.forEach(b => (b.population = population));
|
||||
}
|
||||
|
||||
if (layerIsOn("togglePopulation")) drawPopulation();
|
||||
zonesEditorAddLines();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue