This commit is contained in:
Azgaar 2019-10-24 22:27:41 +03:00
parent 2ba1332eec
commit a3fa5443d6
16 changed files with 137 additions and 113 deletions

View file

@ -4,13 +4,12 @@
(global.ReliefIcons = factory());
}(this, (function () {'use strict';
var ReliefIcons = function ReliefIcons() {
const ReliefIcons = function() {
console.time('drawRelief');
terrain.selectAll("*").remove();
const density = +styleReliefDensityInput.value;
if (!density) return;
const size = 1.6, mod = .2 * size; // size modifier;s
const density = terrain.attr("density") || .4;
const size = 1.6 * (terrain.attr("size") || 1);
const mod = .2 * size; // size modifier;s
const relief = []; // t: type, c: cell, x: centerX, y: centerY, s: size;
const cells = pack.cells;
@ -106,9 +105,10 @@
}
function getIcon(type) {
if (styleReliefSet.value === "simple") return "#relief-" + getOldIcon(type) + "-1";
if (styleReliefSet.value === "colored") return "#relief-" + type + "-" + getVariant(type);
if (styleReliefSet.value === "gray") return "#relief-" + type + "-" + getVariant(type) + "-bw";
const set = terrain.attr("set") || "simple";
if (set === "simple") return "#relief-" + getOldIcon(type) + "-1";
if (set === "colored") return "#relief-" + type + "-" + getVariant(type);
if (set === "gray") return "#relief-" + type + "-" + getVariant(type) + "-bw";
return "#relief-" + getOldIcon(type) + "-1"; // simple
}

View file

@ -74,7 +74,7 @@ async function saveJPEG() {
}
// parse map svg to object url
async function getMapURL(type) {
async function getMapURL(type, subtype) {
const cloneEl = document.getElementById("map").cloneNode(true); // clone svg
cloneEl.id = "fantasyMap";
document.body.appendChild(cloneEl);
@ -83,6 +83,7 @@ async function getMapURL(type) {
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox && type === "mesh") clone.select("#oceanPattern").remove();
if (subtype === "globe") clone.select("#scaleBar").remove();
if (type === "mesh") clone.attr("width", graphWidth).attr("height", graphHeight);
if (type !== "png") clone.select("#viewbox").attr("transform", null); // reset transform to show whole map
if (type === "svg") removeUnusedElements(clone);
@ -551,7 +552,7 @@ function uploadMap(file, callback) {
function parseLoadedData(data) {
try {
// exit customization
closeDialogs();
if (window.closeDialogs) closeDialogs();
customization = 0;
if (customizationMenu.offsetParent) styleTab.click();
@ -908,12 +909,18 @@ function parseLoadedData(data) {
// v 1.11 had an issue with fogging being displayed on load
unfog();
// v 1.2 added new terrain attributes
if (!terrain.attr("set")) terrain.attr("set", "simple");
if (!terrain.attr("size")) terrain.attr("size", 1);
if (!terrain.attr("density")) terrain.attr("density", .4);
}
}()
changeMapSize();
if (window.restoreDefaultEvents) restoreDefaultEvents();
focusOn(); // based on searchParams focus on point, cell or burg
invokeActiveZooming();
console.warn(`TOTAL: ${rn((performance.now()-uploadMap.timeStart)/1000,2)}s`);

View file

@ -190,7 +190,7 @@ async function startGlobe(canvas) {
// create globe mesh just from svg
async function addGlobe3dMesh() {
threeD.material = new THREE.MeshLambertMaterial();
const url = await getMapURL("mesh");
const url = await getMapURL("mesh", "globe");
threeD.material.map = new THREE.TextureLoader().load(url, render);
threeD.mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(1, 64, 64), threeD.material);
threeD.scene.add(threeD.mesh);

View file

@ -304,6 +304,9 @@ function editCultures() {
pack.cells.culture.forEach((c, i) => {if(c === culture) pack.cells.culture[i] = 0;});
pack.cultures[culture].removed = true;
const origin = pack.cultures[culture].origin;
pack.cultures.forEach(c => {if(c.origin === culture) c.origin = origin;});
refreshCulturesEditor();
}
@ -363,6 +366,7 @@ function editCultures() {
// build hierarchy tree
pack.cultures[0].origin = null;
const cultures = pack.cultures.filter(c => !c.removed);
if (cultures.length < 3) {tip("Not enough cultures to show hierarchy", false, "error"); return;}
const root = d3.stratify().id(d => d.i).parentId(d => d.origin)(cultures);
const treeWidth = root.leaves().length;
const treeHeight = root.height;
@ -452,7 +456,6 @@ function editCultures() {
}
}
// re-calculate cultures
function recalculateCultures(must) {
if (!must && !culturesAutoChange.checked) return;
@ -508,7 +511,7 @@ function editCultures() {
body.querySelector("div.selected").classList.remove("selected");
body.querySelector("div[data-id='"+culture+"']").classList.add("selected");
}
function dragCultureBrush() {
const r = +culturesManuallyBrush.value;
@ -523,7 +526,6 @@ function editCultures() {
});
}
// change culture within selection
function changeCultureForSelection(selection) {
const temp = cults.select("#temp");
const selected = body.querySelector("div.selected");
@ -564,7 +566,7 @@ function editCultures() {
}
exitCulturesManualAssignment();
}
function exitCulturesManualAssignment(close) {
customization = 0;
cults.select("#temp").remove();
@ -637,7 +639,7 @@ function editCultures() {
const name = getFileName("Cultures") + ".csv";
downloadFile(data, name);
}
function closeCulturesEditor() {
debug.select("#cultureCenters").remove();
exitCulturesManualAssignment("close");

View file

@ -262,7 +262,7 @@ function drawLegend(name, data) {
fitLegendBox();
}
// fit Legend box to map size
// fit Legend box to canvas size
function fitLegendBox() {
if (!legend.selectAll("*").size()) return;
const px = isNaN(+legend.attr("data-x")) ? 99 : legend.attr("data-x") / 100;

View file

@ -50,7 +50,7 @@ function moved() {
showNotes(d3.event, i);
const g = findGridCell(point[0], point[1]); // grid cell id
if (tooltip.dataset.main) showMainTip(); else showMapTooltip(point, d3.event, i, g);
if (toolsContent.style.display === "block" && cellInfo.style.display === "block") updateCellInfo(point, i, g);
if (cellInfo.offsetParent) updateCellInfo(point, i, g);
}
// show note box on hover (if any)

View file

@ -2,10 +2,6 @@
"use strict";
function editHeightmap() {
const heights = viewbox.select("#heights").size()
? viewbox.select("#heights")
: viewbox.insert("g", "#terrs").attr("id", "heights");
void function selectEditMode() {
alertMessage.innerHTML = `<p>Heightmap is a core element on which all other data (rivers, burgs, states etc) is based.
So the best edit approach is to <i>erase</i> the secondary data and let the system automatically regenerate it on edit completion.</p>
@ -31,6 +27,7 @@ function editHeightmap() {
let edits = [];
restartHistory();
viewbox.insert("g", "#terrs").attr("id", "heights");
if (modules.editHeightmap) return;
modules.editHeightmap = true;
@ -111,7 +108,7 @@ function editHeightmap() {
// Exit customization mode
function finalizeHeightmap() {
if (heights.selectAll("*").size() < 200) {
if (viewbox.select("#heights").selectAll("*").size() < 200) {
tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error");
return;
}
@ -136,7 +133,7 @@ function editHeightmap() {
else if (mode === "risk") restoreRiskedData();
// restore initial layers
heights.selectAll("*").remove();
viewbox.select("#heights").remove();
turnButtonOff("toggleHeight");
document.getElementById("mapLayers").querySelectorAll("li").forEach(function(e) {
if (editHeightmap.layers.includes(e.id) && !layerIsOn(e.id)) e.click(); // turn on
@ -381,7 +378,7 @@ function editHeightmap() {
function mockHeightmap() {
const data = renderOcean.checked ? grid.cells.i : grid.cells.i.filter(i => grid.cells.h[i] >= 20);
const scheme = getColorScheme();
heights.selectAll("polygon").data(data).join("polygon").attr("points", d => getGridPolygon(d))
viewbox.select("#heights").selectAll("polygon").data(data).join("polygon").attr("points", d => getGridPolygon(d))
.attr("id", d => "cell"+d).attr("fill", d => getColor(grid.cells.h[d], scheme));
}
@ -391,9 +388,9 @@ function editHeightmap() {
const scheme = getColorScheme();
selection.forEach(function(i) {
let cell = heights.select("#cell"+i);
let cell = viewbox.select("#heights").select("#cell"+i);
if (!ocean && grid.cells.h[i] < 20) {cell.remove(); return;}
if (!cell.size()) cell = heights.append("polygon").attr("points", getGridPolygon(i)).attr("id", "cell"+i);
if (!cell.size()) cell = viewbox.select("#heights").append("polygon").attr("points", getGridPolygon(i)).attr("id", "cell"+i);
cell.attr("fill", getColor(grid.cells.h[i], scheme));
});
}
@ -579,7 +576,7 @@ function editHeightmap() {
const someHeights = grid.cells.h.some(h => h);
if (!someHeights) {tip("Heightmap is already cleared, please do not click twice if not required", false, "error"); return;}
grid.cells.h = new Uint8Array(grid.cells.i.length);
heights.selectAll("*").remove();
viewbox.select("#heights").selectAll("*").remove();
updateHistory();
}
@ -941,7 +938,7 @@ function editHeightmap() {
// remove all heights
grid.cells.h = new Uint8Array(grid.cells.i.length);
heights.selectAll("*").remove();
viewbox.select("#heights").selectAll("*").remove();
updateHistory();
if (modules.openImageConverter) return;
@ -995,7 +992,7 @@ function editHeightmap() {
const imageData = ctx.getImageData(0, 0, graphWidth, graphHeight);
const data = imageData.data;
heights.selectAll("*").remove();
viewbox.select("#heights").selectAll("*").remove();
d3.select("#imageConverter").selectAll("div.color-div").remove();
colorsSelect.style.display = "block";
colorsUnassigned.style.display = "block";
@ -1011,7 +1008,7 @@ function editHeightmap() {
const cmap = MMCQ.quantize(gridColors, count);
const usedColors = new Set();
heights.selectAll("polygon").data(grid.cells.i).join("polygon")
viewbox.select("#heights").selectAll("polygon").data(grid.cells.i).join("polygon")
.attr("points", d => getGridPolygon(d))
.attr("id", d => "cell"+d).attr("fill", d => {
const clr = `rgb(${cmap.nearest(gridColors[d])})`;
@ -1035,7 +1032,7 @@ function editHeightmap() {
}
function colorClicked() {
heights.selectAll(".selectedCell").attr("class", null);
viewbox.select("#heights").selectAll(".selectedCell").attr("class", null);
const unselect = this.classList.contains("selectedColor");
const selectedColor = imageConverter.querySelector("div.selectedColor");
@ -1054,8 +1051,8 @@ function editHeightmap() {
}
const color = this.getAttribute("data-color");
heights.selectAll("polygon.selectedCell").classed("selectedCell", 0);
heights.selectAll("polygon[fill='" + color + "']").classed("selectedCell", 1);
viewbox.select("#heights").selectAll("polygon.selectedCell").classed("selectedCell", 0);
viewbox.select("#heights").selectAll("polygon[fill='" + color + "']").classed("selectedCell", 1);
}
function assignHeight() {
@ -1066,7 +1063,7 @@ function editHeightmap() {
selectedColor.setAttribute("data-color", rgb);
selectedColor.setAttribute("data-height", height);
heights.selectAll(".selectedCell").each(function() {
viewbox.select("#heights").selectAll(".selectedCell").each(function() {
this.setAttribute("fill", rgb);
this.setAttribute("data-height", height);
});
@ -1090,7 +1087,7 @@ function editHeightmap() {
const colorTo = color(1 - (normalized < .2 ? normalized-.05 : normalized));
const heightTo = normalized * 100;
heights.selectAll("polygon[fill='" + colorFrom + "']").attr("fill", colorTo).attr("data-height", heightTo);
viewbox.select("#heights").selectAll("polygon[fill='" + colorFrom + "']").attr("fill", colorTo).attr("data-height", heightTo);
el.style.backgroundColor = colorTo;
el.setAttribute("data-color", colorTo);
el.setAttribute("data-height", heightTo);
@ -1127,13 +1124,13 @@ function editHeightmap() {
viewbox.style("cursor", "default").on(".drag", null);
tip('Heightmap edit mode is active. Click on "Exit Customization" to finalize the heightmap', true);
heights.selectAll("polygon").each(function() {
viewbox.select("#heights").selectAll("polygon").each(function() {
const height = +this.getAttribute("data-height") || 0;
const i = +this.id.slice(4);
grid.cells.h[i] = height;
});
heights.selectAll("polygon").remove();
viewbox.select("#heights").selectAll("polygon").remove();
updateHeightmap();
}
}

View file

@ -461,7 +461,9 @@ function drawCells() {
}
function toggleCultures(event) {
if (!cults.selectAll("path").size()) {
const cultures = pack.cultures.filter(c => c.i && !c.removed);
const empty = !cults.selectAll("path").size();
if (empty && cultures.length) {
turnButtonOn("toggleCultures");
drawCultures();
if (event && event.ctrlKey) editStyle("cults");
@ -472,7 +474,7 @@ function toggleCultures(event) {
}
}
function drawCultures(event) {
function drawCultures() {
console.time("drawCultures");
cults.selectAll("path").remove();
@ -520,7 +522,8 @@ function drawCultures(event) {
}
function toggleReligions(event) {
if (!relig.selectAll("path").size()) {
const religions = pack.religions.filter(r => r.i && !r.removed);
if (!relig.selectAll("path").size() && religions.length) {
turnButtonOn("toggleReligions");
drawReligions();
if (event && event.ctrlKey) editStyle("relig");

View file

@ -266,7 +266,7 @@ function drawScaleBar() {
fitScaleBar();
}
// fit ScaleBar to map size
// fit ScaleBar to canvas size
function fitScaleBar() {
if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return;
const px = isNaN(+barPosX.value) ? .99 : barPosX.value / 100;

View file

@ -133,26 +133,33 @@ function mapSizeInputChange() {
// change svg size on manual size change or window resize, do not change graph size
function changeMapSize() {
svgWidth = +mapWidthInput.value;
svgHeight = +mapHeightInput.value;
const svgWidth = Math.min(+mapWidthInput.value, window.innerWidth);
const svgHeight = Math.min(+mapHeightInput.value, window.innerHeight);
svg.attr("width", svgWidth).attr("height", svgHeight);
const width = Math.max(svgWidth, graphWidth);
const height = Math.max(svgHeight, graphHeight);
zoom.translateExtent([[0, 0], [width, height]]);
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
oceanLayers.select("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
const maxWidth = Math.max(+mapWidthInput.value, graphWidth);
const maxHeight = Math.max(+mapHeightInput.value, graphHeight);
zoom.translateExtent([[0, 0], [maxWidth, maxHeight]]);
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
oceanLayers.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
defs.select("#mapClip > rect").attr("width", maxWidth).attr("height", maxHeight);
fitScaleBar();
if (window.fitLegendBox) fitLegendBox();
}
// just apply map size that was already set, apply graph size!
// just apply canvas size that was already set
function applyMapSize() {
svgWidth = graphWidth = +mapWidthInput.value;
svgHeight = graphHeight = +mapHeightInput.value;
graphWidth = +mapWidthInput.value;
graphHeight = +mapHeightInput.value;
svgWidth = Math.min(graphWidth, window.innerWidth)
svgHeight = Math.min(graphHeight, window.innerHeight)
svg.attr("width", svgWidth).attr("height", svgHeight);
zoom.translateExtent([[0, 0],[graphWidth, graphHeight]]).scaleExtent([1, 20]).scaleTo(svg, 1);
viewbox.attr("transform", null);
viewbox.attr("transform", null).attr("clip-path", "url(#mapClip)");
defs.append("clipPath").attr("id", "mapClip").append("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight);
//zoom.translateExtent([[-svgWidth*.2, -graphHeight*.2], [svgWidth*1.2, graphHeight*1.2]]);
}
function toggleFullscreen() {

View file

@ -57,11 +57,12 @@ function editProvinces() {
}
function collectStatistics() {
const cells = pack.cells, provinces = pack.provinces;
const cells = pack.cells, provinces = pack.provinces, burgs = pack.burgs;
provinces.forEach(p => {
if (!p.i || p.removed) return;
p.area = p.rural = p.urban = 0;
p.burgs = [];
if (p.burg && !burgs[p.burg] || burgs[p.burg].removed) p.burg = 0;
});
for (const i of cells.i) {
@ -71,7 +72,7 @@ function editProvinces() {
provinces[p].area += cells.area[i];
provinces[p].rural += cells.pop[i];
if (!cells.burg[i]) continue;
provinces[p].urban += pack.burgs[cells.burg[i]].population;
provinces[p].urban += burgs[cells.burg[i]].population;
provinces[p].burgs.push(cells.burg[i]);
}

View file

@ -360,6 +360,7 @@ function editReligions() {
// build hierarchy tree
pack.religions[0].origin = null;
const religions = pack.religions.filter(r => !r.removed);
if (religions.length < 3) {tip("Not enough religions to show hierarchy", false, "error"); return;}
const root = d3.stratify().id(d => d.i).parentId(d => d.origin)(religions);
const treeWidth = root.leaves().length;
const treeHeight = root.height;

File diff suppressed because one or more lines are too long

View file

@ -15,10 +15,11 @@ toolsContent.addEventListener("click", function(event) {
if (button === "editCulturesButton") editCultures(); else
if (button === "editReligions") editReligions(); else
if (button === "editNamesBaseButton") editNamesbase(); else
if (button === "overviewBurgsButton") editBurgs(); else
if (button === "editUnitsButton") editUnits(); else
if (button === "editNotesButton") editNotes(); else
if (button === "editZonesButton") editZones();
if (button === "editZonesButton") editZones(); else
if (button === "overviewBurgsButton") editBurgs(); else
if (button === "overviewCellsButton") viewCellDetails();
// Click to Regenerate buttons
if (event.target.parentNode.id === "regenerateFeature") {
@ -90,7 +91,8 @@ function regenerateBurgs() {
rankCells();
cells.burg = new Uint16Array(cells.i.length);
const burgs = pack.burgs = [0]; // clear burgs array
states.filter(s => s.i).forEach(s => s.capital = 0); // clear capitals
states.filter(s => s.i).forEach(s => s.capital = 0); // clear state capitals
pack.provinces.filter(p => p.i).forEach(p => p.burg = 0); // clear province capitals
const burgsTree = d3.quadtree();
const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for capitals placement
@ -477,4 +479,8 @@ function addMarkerOnClick() {
.attr("data-size", desired).attr("width", size).attr("height", size);
if (d3.event.shiftKey === false) unpressClickToAddButton();
}
function viewCellDetails() {
$("#cellInfo").dialog({resizable: false, width: "22em", title: "Cell Details"});
}