mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 17:51:24 +01:00
collect statistics for a short period
This commit is contained in:
parent
2a9edd2458
commit
5d714c8c17
9 changed files with 160 additions and 53 deletions
|
|
@ -4,6 +4,7 @@
|
|||
// download map as SVG
|
||||
async function saveSVG() {
|
||||
TIME && console.time("saveSVG");
|
||||
track("export", "svg");
|
||||
const url = await getMapURL("svg");
|
||||
const link = document.createElement("a");
|
||||
link.download = getFileName() + ".svg";
|
||||
|
|
@ -17,6 +18,7 @@ async function saveSVG() {
|
|||
// download map as PNG
|
||||
async function savePNG() {
|
||||
TIME && console.time("savePNG");
|
||||
track("export", "png");
|
||||
const url = await getMapURL("png");
|
||||
|
||||
const link = document.createElement("a");
|
||||
|
|
@ -47,6 +49,7 @@ async function savePNG() {
|
|||
// download map as JPEG
|
||||
async function saveJPEG() {
|
||||
TIME && console.time("saveJPEG");
|
||||
track("export", "jpg");
|
||||
const url = await getMapURL("png");
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
|
|
@ -264,7 +267,11 @@ async function getMapURL(type, options = {}) {
|
|||
if (!cloneEl.getElementById("labels")) cloneEl.getElementById("textPaths")?.remove(); // removed unused textPaths
|
||||
|
||||
// add armies style
|
||||
if (cloneEl.getElementById("armies")) cloneEl.insertAdjacentHTML("afterbegin", "<style>#armies text {stroke: none; fill: #fff; text-shadow: 0 0 4px #000; dominant-baseline: central; text-anchor: middle; font-family: Helvetica; fill-opacity: 1;}#armies text.regimentIcon {font-size: .8em;}</style>");
|
||||
if (cloneEl.getElementById("armies"))
|
||||
cloneEl.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<style>#armies text {stroke: none; fill: #fff; text-shadow: 0 0 4px #000; dominant-baseline: central; text-anchor: middle; font-family: Helvetica; fill-opacity: 1;}#armies text.regimentIcon {font-size: .8em;}</style>"
|
||||
);
|
||||
|
||||
// add xlink: for href to support svg1.1
|
||||
if (type === "svg") {
|
||||
|
|
@ -372,6 +379,7 @@ function inlineStyle(clone) {
|
|||
}
|
||||
|
||||
function saveGeoJSON_Cells() {
|
||||
track("export", "getJSON cells");
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
const cells = pack.cells;
|
||||
const getPopulation = i => {
|
||||
|
|
@ -402,6 +410,7 @@ function saveGeoJSON_Cells() {
|
|||
}
|
||||
|
||||
function saveGeoJSON_Routes() {
|
||||
track("export", "getJSON routes");
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
|
||||
routes.selectAll("g > path").each(function () {
|
||||
|
|
@ -418,6 +427,7 @@ function saveGeoJSON_Routes() {
|
|||
}
|
||||
|
||||
function saveGeoJSON_Rivers() {
|
||||
track("export", "getJSON rivers");
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
|
||||
rivers.selectAll("path").each(function () {
|
||||
|
|
@ -440,6 +450,8 @@ function saveGeoJSON_Rivers() {
|
|||
}
|
||||
|
||||
function saveGeoJSON_Markers() {
|
||||
// TODO: rework for new markers
|
||||
track("export", "getJSON markers");
|
||||
const json = {type: "FeatureCollection", features: []};
|
||||
|
||||
markers.selectAll("use").each(function () {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ function quickLoad() {
|
|||
}
|
||||
|
||||
async function loadFromDropbox() {
|
||||
track("load", `from dropbox`);
|
||||
const mapPath = document.getElementById("loadFromDropboxSelect")?.value;
|
||||
|
||||
DEBUG && console.log("Loading map from Dropbox:", mapPath);
|
||||
|
|
@ -68,6 +69,7 @@ function loadMapPrompt(blob) {
|
|||
|
||||
function loadLastSavedMap() {
|
||||
WARN && console.warn("Load last saved map");
|
||||
track("load", `from browser storage`);
|
||||
try {
|
||||
uploadMap(blob);
|
||||
} catch (error) {
|
||||
|
|
@ -78,6 +80,7 @@ function loadMapPrompt(blob) {
|
|||
}
|
||||
|
||||
function loadMapFromURL(maplink, random) {
|
||||
track("load", `from url`);
|
||||
const URL = decodeURIComponent(maplink);
|
||||
|
||||
fetch(URL, {method: "GET", mode: "cors"})
|
||||
|
|
@ -93,6 +96,7 @@ function loadMapFromURL(maplink, random) {
|
|||
}
|
||||
|
||||
function showUploadErrorMessage(error, URL, random) {
|
||||
track("error", `map load from url`);
|
||||
ERROR && console.error(error);
|
||||
alertMessage.innerHTML = `Cannot load map from the ${link(URL, "link provided")}.
|
||||
${random ? `A new random map is generated. ` : ""}
|
||||
|
|
@ -431,12 +435,27 @@ function parseLoadedData(data) {
|
|||
|
||||
// 1.0 adds a legend box
|
||||
legend = svg.append("g").attr("id", "legend");
|
||||
legend.attr("font-family", "Almendra SC").attr("font-size", 13).attr("data-size", 13).attr("data-x", 99).attr("data-y", 93).attr("stroke-width", 2.5).attr("stroke", "#812929").attr("stroke-dasharray", "0 4 10 4").attr("stroke-linecap", "round");
|
||||
legend
|
||||
.attr("font-family", "Almendra SC")
|
||||
.attr("font-size", 13)
|
||||
.attr("data-size", 13)
|
||||
.attr("data-x", 99)
|
||||
.attr("data-y", 93)
|
||||
.attr("stroke-width", 2.5)
|
||||
.attr("stroke", "#812929")
|
||||
.attr("stroke-dasharray", "0 4 10 4")
|
||||
.attr("stroke-linecap", "round");
|
||||
|
||||
// 1.0 separated drawBorders fron drawStates()
|
||||
stateBorders = borders.append("g").attr("id", "stateBorders");
|
||||
provinceBorders = borders.append("g").attr("id", "provinceBorders");
|
||||
borders.attr("opacity", null).attr("stroke", null).attr("stroke-width", null).attr("stroke-dasharray", null).attr("stroke-linecap", null).attr("filter", null);
|
||||
borders
|
||||
.attr("opacity", null)
|
||||
.attr("stroke", null)
|
||||
.attr("stroke-width", null)
|
||||
.attr("stroke-dasharray", null)
|
||||
.attr("stroke-linecap", null)
|
||||
.attr("filter", null);
|
||||
stateBorders.attr("opacity", 0.8).attr("stroke", "#56566d").attr("stroke-width", 1).attr("stroke-dasharray", "2").attr("stroke-linecap", "butt");
|
||||
provinceBorders.attr("opacity", 0.8).attr("stroke", "#56566d").attr("stroke-width", 0.5).attr("stroke-dasharray", "1").attr("stroke-linecap", "butt");
|
||||
|
||||
|
|
@ -976,7 +995,7 @@ function parseLoadedData(data) {
|
|||
},
|
||||
"New map": function () {
|
||||
$(this).dialog("close");
|
||||
regenerateMap();
|
||||
regenerateMap("loading error");
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
|
|
|
|||
|
|
@ -16,12 +16,15 @@ function editHeightmap() {
|
|||
width: "28em",
|
||||
buttons: {
|
||||
Erase: function () {
|
||||
track("edit", "heightmap erase");
|
||||
enterHeightmapEditMode("erase");
|
||||
},
|
||||
Keep: function () {
|
||||
track("edit", "heightmap keep");
|
||||
enterHeightmapEditMode("keep");
|
||||
},
|
||||
Risk: function () {
|
||||
track("edit", "heightmap risk");
|
||||
enterHeightmapEditMode("risk");
|
||||
},
|
||||
Cancel: function () {
|
||||
|
|
@ -87,7 +90,16 @@ function editHeightmap() {
|
|||
exitCustomization.style.bottom = svgHeight / 2 + "px";
|
||||
exitCustomization.style.transform = "scale(2)";
|
||||
exitCustomization.style.display = "block";
|
||||
d3.select("#exitCustomization").transition().duration(1000).style("opacity", 1).transition().duration(2000).ease(d3.easeSinInOut).style("right", "10px").style("bottom", "10px").style("transform", "scale(1)");
|
||||
d3.select("#exitCustomization")
|
||||
.transition()
|
||||
.duration(1000)
|
||||
.style("opacity", 1)
|
||||
.transition()
|
||||
.duration(2000)
|
||||
.ease(d3.easeSinInOut)
|
||||
.style("right", "10px")
|
||||
.style("bottom", "10px")
|
||||
.style("transform", "scale(1)");
|
||||
} else exitCustomization.style.display = "block";
|
||||
|
||||
openBrushesPanel();
|
||||
|
|
@ -130,7 +142,8 @@ function editHeightmap() {
|
|||
|
||||
// Exit customization mode
|
||||
function finalizeHeightmap() {
|
||||
if (viewbox.select("#heights").selectAll("*").size() < 200) return tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error");
|
||||
if (viewbox.select("#heights").selectAll("*").size() < 200)
|
||||
return tip("Insufficient land area! There should be at least 200 land cells to finalize the heightmap", null, "error");
|
||||
if (document.getElementById("imageConverter").offsetParent) return tip("Please exit the Image Conversion mode first", null, "error");
|
||||
|
||||
delete window.edits; // remove global variable
|
||||
|
|
@ -618,7 +631,10 @@ function editHeightmap() {
|
|||
else if (brush === "brushLower") s.forEach(i => (h[i] = lim(h[i] - power)));
|
||||
else if (brush === "brushDepress") s.forEach((i, d) => (h[i] = lim(h[i] - interpolate(d / Math.max(s.length - 1, 1)))));
|
||||
else if (brush === "brushAlign") s.forEach(i => (h[i] = lim(h[start])));
|
||||
else if (brush === "brushSmooth") s.forEach(i => (h[i] = rn((d3.mean(grid.cells.c[i].filter(i => (land ? h[i] >= 20 : 1)).map(c => h[c])) + h[i] * (10 - power) + 0.6) / (11 - power), 1)));
|
||||
else if (brush === "brushSmooth")
|
||||
s.forEach(
|
||||
i => (h[i] = rn((d3.mean(grid.cells.c[i].filter(i => (land ? h[i] >= 20 : 1)).map(c => h[c])) + h[i] * (10 - power) + 0.6) / (11 - power), 1))
|
||||
);
|
||||
else if (brush === "brushDisrupt") s.forEach(i => (h[i] = h[i] < 15 ? h[i] : lim(h[i] + power / 1.6 - Math.random() * power)));
|
||||
|
||||
mockHeightmapSelection(s);
|
||||
|
|
@ -688,6 +704,7 @@ function editHeightmap() {
|
|||
|
||||
function openTemplateEditor() {
|
||||
if ($("#templateEditor").is(":visible")) return;
|
||||
track("edit", "template editor");
|
||||
const body = document.getElementById("templateBody");
|
||||
|
||||
$("#templateEditor").dialog({
|
||||
|
|
@ -767,15 +784,29 @@ function editHeightmap() {
|
|||
|
||||
const TempY = `<span>y:<input class="templateY" data-tip="Placement range percentage along Y axis (minY-maxY)" value=${arg5 || "20-80"}></span>`;
|
||||
const TempX = `<span>x:<input class="templateX" data-tip="Placement range percentage along X axis (minX-maxX)" value=${arg4 || "15-85"}></span>`;
|
||||
const Height = `<span>h:<input class="templateHeight" data-tip="Blob maximum height, use hyphen to get a random number in range" value=${arg3 || "40-50"}></span>`;
|
||||
const Height = `<span>h:<input class="templateHeight" data-tip="Blob maximum height, use hyphen to get a random number in range" value=${
|
||||
arg3 || "40-50"
|
||||
}></span>`;
|
||||
const Count = `<span>n:<input class="templateCount" data-tip="Blobs to add, use hyphen to get a random number in range" value=${count || "1-2"}></span>`;
|
||||
const blob = `${common}${TempY}${TempX}${Height}${Count}</div>`;
|
||||
|
||||
if (type === "Hill" || type === "Pit" || type === "Range" || type === "Trough") return blob;
|
||||
if (type === "Strait") return `${common}<span>d:<select class="templateDist" data-tip="Strait direction"><option value="vertical" selected>vertical</option><option value="horizontal">horizontal</option></select></span><span>w:<input class="templateCount" data-tip="Strait width, use hyphen to get a random number in range" value=${count || "2-7"}></span></div>`;
|
||||
if (type === "Add") return `${common}<span>to:<select class="templateDist" data-tip="Change only land or all cells"><option value="all" selected>all cells</option><option value="land">land only</option><option value="interval">interval</option></select></span><span>v:<input class="templateCount" data-tip="Add value to height of all cells (negative values are allowed)" type="number" value=${count || -10} min=-100 max=100 step=1></span></div>`;
|
||||
if (type === "Multiply") return `${common}<span>to:<select class="templateDist" data-tip="Change only land or all cells"><option value="all" selected>all cells</option><option value="land">land only</option><option value="interval">interval</option></select></span><span>v:<input class="templateCount" data-tip="Multiply all cells Height by the value" type="number" value=${count || 1.1} min=0 max=10 step=.1></span></div>`;
|
||||
if (type === "Smooth") return `${common}<span>f:<input class="templateCount" data-tip="Set smooth fraction. 1 - full smooth, 2 - half-smooth, etc." type="number" min=1 max=10 value=${count || 2}></span></div>`;
|
||||
if (type === "Strait")
|
||||
return `${common}<span>d:<select class="templateDist" data-tip="Strait direction"><option value="vertical" selected>vertical</option><option value="horizontal">horizontal</option></select></span><span>w:<input class="templateCount" data-tip="Strait width, use hyphen to get a random number in range" value=${
|
||||
count || "2-7"
|
||||
}></span></div>`;
|
||||
if (type === "Add")
|
||||
return `${common}<span>to:<select class="templateDist" data-tip="Change only land or all cells"><option value="all" selected>all cells</option><option value="land">land only</option><option value="interval">interval</option></select></span><span>v:<input class="templateCount" data-tip="Add value to height of all cells (negative values are allowed)" type="number" value=${
|
||||
count || -10
|
||||
} min=-100 max=100 step=1></span></div>`;
|
||||
if (type === "Multiply")
|
||||
return `${common}<span>to:<select class="templateDist" data-tip="Change only land or all cells"><option value="all" selected>all cells</option><option value="land">land only</option><option value="interval">interval</option></select></span><span>v:<input class="templateCount" data-tip="Multiply all cells Height by the value" type="number" value=${
|
||||
count || 1.1
|
||||
} min=0 max=10 step=.1></span></div>`;
|
||||
if (type === "Smooth")
|
||||
return `${common}<span>f:<input class="templateCount" data-tip="Set smooth fraction. 1 - full smooth, 2 - half-smooth, etc." type="number" min=1 max=10 value=${
|
||||
count || 2
|
||||
}></span></div>`;
|
||||
}
|
||||
|
||||
function setRange(event) {
|
||||
|
|
@ -910,6 +941,7 @@ function editHeightmap() {
|
|||
|
||||
function openImageConverter() {
|
||||
if ($("#imageConverter").is(":visible")) return;
|
||||
track("edit", "convert image");
|
||||
imageToLoad.click();
|
||||
closeDialogs("#imageConverter");
|
||||
|
||||
|
|
@ -1170,10 +1202,14 @@ function editHeightmap() {
|
|||
}
|
||||
|
||||
function setConvertColorsNumber() {
|
||||
prompt(`Please set maximum number of colors. <br>An actual number is usually lower and depends on color scheme`, {default: +convertColors.value, step: 1, min: 3, max: 255}, number => {
|
||||
convertColors.value = number;
|
||||
heightsFromImage(number);
|
||||
});
|
||||
prompt(
|
||||
`Please set maximum number of colors. <br>An actual number is usually lower and depends on color scheme`,
|
||||
{default: +convertColors.value, step: 1, min: 3, max: 255},
|
||||
number => {
|
||||
convertColors.value = number;
|
||||
heightsFromImage(number);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function setOverlayOpacity(v) {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ function handleKeyup(event) {
|
|||
const alt = altKey || key === "Alt";
|
||||
|
||||
if (key === "F1") showInfo();
|
||||
else if (key === "F2") regeneratePrompt();
|
||||
else if (key === "F2") regeneratePrompt("hotkey");
|
||||
else if (key === "F6") quickSave();
|
||||
else if (key === "F9") quickLoad();
|
||||
else if (key === "TAB") toggleOptions(event);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ if (localStorage.getItem("disable_click_arrow_tooltip")) {
|
|||
|
||||
// Show options pane on trigger click
|
||||
function showOptions(event) {
|
||||
track("click", "show options");
|
||||
if (!localStorage.getItem("disable_click_arrow_tooltip")) {
|
||||
clearMainTip();
|
||||
localStorage.setItem("disable_click_arrow_tooltip", true);
|
||||
|
|
@ -75,6 +76,7 @@ document
|
|||
|
||||
// show popup with a list of Patreon supportes (updated manually, to be replaced with API call)
|
||||
function showSupporters() {
|
||||
track("click", "show supporters");
|
||||
const supporters = `Aaron Meyer,Ahmad Amerih,AstralJacks,aymeric,Billy Dean Goehring,Branndon Edwards,Chase Mayers,Curt Flood,cyninge,Dino Princip,
|
||||
E.M. White,es,Fondue,Fritjof Olsson,Gatsu,Johan Fröberg,Jonathan Moore,Joseph Miranda,Kate,KC138,Luke Nelson,Markus Finster,Massimo Vella,Mikey,
|
||||
Nathan Mitchell,Paavi1,Pat,Ryan Westcott,Sasquatch,Shawn Spencer,Sizz_TV,Timothée CALLET,UTG community,Vlad Tomash,Wil Sisney,William Merriott,
|
||||
|
|
@ -160,7 +162,7 @@ optionsContent.addEventListener("change", function (event) {
|
|||
const value = event.target.value;
|
||||
|
||||
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
|
||||
else if (id === "optionsSeed") generateMapWithSeed();
|
||||
else if (id === "optionsSeed") generateMapWithSeed("seed change");
|
||||
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value);
|
||||
if (id === "shapeRendering") viewbox.attr("shape-rendering", value);
|
||||
else if (id === "yearInput") changeYear();
|
||||
|
|
@ -170,7 +172,6 @@ optionsContent.addEventListener("change", function (event) {
|
|||
optionsContent.addEventListener("click", function (event) {
|
||||
const id = event.target.id;
|
||||
if (id === "toggleFullscreen") toggleFullscreen();
|
||||
else if (id === "optionsSeedGenerate") generateMapWithSeed();
|
||||
else if (id === "optionsMapHistory") showSeedHistoryDialog();
|
||||
else if (id === "optionsCopySeed") copyMapURL();
|
||||
else if (id === "optionsEraRegenerate") regenerateEra();
|
||||
|
|
@ -211,8 +212,8 @@ function changeMapSize() {
|
|||
|
||||
// just apply canvas size that was already set
|
||||
function applyMapSize() {
|
||||
const zoomMin = +zoomExtentMin.value,
|
||||
zoomMax = +zoomExtentMax.value;
|
||||
const zoomMin = +zoomExtentMin.value;
|
||||
const zoomMax = +zoomExtentMax.value;
|
||||
graphWidth = +mapWidthInput.value;
|
||||
graphHeight = +mapHeightInput.value;
|
||||
svgWidth = Math.min(graphWidth, window.innerWidth);
|
||||
|
|
@ -280,12 +281,9 @@ function testSpeaker() {
|
|||
speechSynthesis.speak(speaker);
|
||||
}
|
||||
|
||||
function generateMapWithSeed() {
|
||||
if (optionsSeed.value == seed) {
|
||||
tip("The current map already has this seed", false, "error");
|
||||
return;
|
||||
}
|
||||
regeneratePrompt();
|
||||
function generateMapWithSeed(source) {
|
||||
if (optionsSeed.value == seed) return tip("The current map already has this seed", false, "error");
|
||||
regeneratePrompt(source);
|
||||
}
|
||||
|
||||
function showSeedHistoryDialog() {
|
||||
|
|
@ -316,7 +314,7 @@ function restoreSeed(id) {
|
|||
mapHeightInput.value = mapHistory[id].height;
|
||||
templateInput.value = mapHistory[id].template;
|
||||
if (locked("template")) unlock("template");
|
||||
regeneratePrompt();
|
||||
regeneratePrompt("seed history");
|
||||
}
|
||||
|
||||
function restoreDefaultZoomExtent() {
|
||||
|
|
@ -656,23 +654,17 @@ function restoreDefaultOptions() {
|
|||
// Sticked menu Options listeners
|
||||
document.getElementById("sticked").addEventListener("click", function (event) {
|
||||
const id = event.target.id;
|
||||
if (id === "newMapButton") regeneratePrompt();
|
||||
if (id === "newMapButton") regeneratePrompt("sticky button");
|
||||
else if (id === "saveButton") showSavePane();
|
||||
else if (id === "exportButton") showExportPane();
|
||||
else if (id === "loadButton") showLoadPane();
|
||||
else if (id === "zoomReset") resetZoom(1000);
|
||||
});
|
||||
|
||||
function regeneratePrompt() {
|
||||
if (customization) {
|
||||
tip("New map cannot be generated when edit mode is active, please exit the mode and retry", false, "error");
|
||||
return;
|
||||
}
|
||||
function regeneratePrompt(source) {
|
||||
if (customization) return tip("New map cannot be generated when edit mode is active, please exit the mode and retry", false, "error");
|
||||
const workingTime = (Date.now() - last(mapHistory).created) / 60000; // minutes
|
||||
if (workingTime < 5) {
|
||||
regenerateMap();
|
||||
return;
|
||||
}
|
||||
if (workingTime < 5) return regenerateMap(source);
|
||||
|
||||
alertMessage.innerHTML = `Are you sure you want to generate a new map?<br>
|
||||
All unsaved changes made to the current map will be lost`;
|
||||
|
|
@ -685,7 +677,7 @@ function regeneratePrompt() {
|
|||
},
|
||||
Generate: function () {
|
||||
closeDialogs();
|
||||
regenerateMap();
|
||||
regenerateMap(source);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -792,6 +784,7 @@ function loadURL() {
|
|||
|
||||
// load map
|
||||
document.getElementById("mapToLoad").addEventListener("change", function () {
|
||||
track("load", `from local file`);
|
||||
const fileToLoad = this.files[0];
|
||||
this.value = "";
|
||||
closeDialogs();
|
||||
|
|
@ -811,6 +804,7 @@ function openSaveTiles() {
|
|||
width: "23em",
|
||||
buttons: {
|
||||
Download: function () {
|
||||
track("export", `tiles`);
|
||||
status.innerHTML = "Preparing for download...";
|
||||
setTimeout(() => (status.innerHTML = "Downloading. It may take some time."), 1000);
|
||||
loading = setInterval(() => (status.innerHTML += "."), 1000);
|
||||
|
|
@ -900,6 +894,7 @@ function enterStandardView() {
|
|||
}
|
||||
|
||||
async function enter3dView(type) {
|
||||
track("click", `3d mode: ${type}`);
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.id = "canvas3d";
|
||||
canvas.dataset.type = type;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue