mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 03:51:23 +01:00
add customer exporter
This commit is contained in:
parent
d6ee8f55ec
commit
f29f319254
2 changed files with 217 additions and 2 deletions
|
|
@ -3346,12 +3346,13 @@
|
||||||
<div id="saveMapData" style="display: none" class="dialog">
|
<div id="saveMapData" style="display: none" class="dialog">
|
||||||
<div style="margin-bottom: .3em">Please select a saving variant:</div>
|
<div style="margin-bottom: .3em">Please select a saving variant:</div>
|
||||||
<div>
|
<div>
|
||||||
<button onclick="saveMap()" data-tip="Download the map as fully-functional .map file to your machine">.map</button>
|
<!--<button onclick="saveMap()" data-tip="Download the map as fully-functional .map file to your machine">.map</button>
|
||||||
<button onclick="saveSVG()" data-tip="Download the map as vector image (open in browser or Inkscape)">.svg</button>
|
<button onclick="saveSVG()" data-tip="Download the map as vector image (open in browser or Inkscape)">.svg</button>
|
||||||
<button onclick="savePNG()" data-tip="Download visible part of the map as .png (lossless compressed)">.png</button>
|
<button onclick="savePNG()" data-tip="Download visible part of the map as .png (lossless compressed)">.png</button>
|
||||||
<button onclick="saveJPEG()" data-tip="Download visible part of the map as .jpeg (lossy compressed) image">.jpeg</button>
|
<button onclick="saveJPEG()" data-tip="Download visible part of the map as .jpeg (lossy compressed) image">.jpeg</button>
|
||||||
<button onclick="saveGeoJSON()" data-tip="Download map data in GeoJSON format">.json</button>
|
<button onclick="saveGeoJSON()" data-tip="Download map data in GeoJSON format">.json</button>
|
||||||
<button onclick="quickSave()" data-tip="Save fully-functional map to browser storage. Shortcut: F6">storage</button>
|
<button onclick="quickSave()" data-tip="Save fully-functional map to browser storage. Shortcut: F6">storage</button>-->
|
||||||
|
<button onclick="customExport()" data-tip="Export to map to our game engine">export</button>
|
||||||
</div>
|
</div>
|
||||||
<p style="font-style: italic">Generator uses pop-up window to download files. Please ensure your browser does not block popups</p>
|
<p style="font-style: italic">Generator uses pop-up window to download files. Please ensure your browser does not block popups</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -962,3 +962,217 @@ function parseLoadedData(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export the map for our game engine
|
||||||
|
async function customExport () {
|
||||||
|
if (customization) {tip("Map cannot be saved when edit mode is active, please exit the mode and retry", false, "error"); return;}
|
||||||
|
closeDialogs("#alert");
|
||||||
|
|
||||||
|
drawProvinces();
|
||||||
|
|
||||||
|
const landmassImage = await getMapImageBase64(["landmass"]);
|
||||||
|
const provincesImage = await getMapImageBase64(["provs"]);
|
||||||
|
|
||||||
|
const blob = await getMapExportData(landmassImage, provincesImage);
|
||||||
|
const URL = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.download = getFileName() + ".json";
|
||||||
|
link.href = URL;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
tip(`${link.download} is saved. Open "Downloads" screen (CTRL + J) to check`, true, "success", 7000);
|
||||||
|
window.setTimeout(() => window.URL.revokeObjectURL(URL), 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMapImageBase64 (visibles) {
|
||||||
|
return new Promise(async resolve => {
|
||||||
|
const url = await getMapLayerURL("png", null, visibles);
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = mapWidthInput.value * pngResolutionInput.value;
|
||||||
|
canvas.height = mapHeightInput.value * pngResolutionInput.value;
|
||||||
|
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
|
const img = new Image();
|
||||||
|
img.src = url;
|
||||||
|
|
||||||
|
img.onload = function() {
|
||||||
|
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||||
|
resolve(canvas.toDataURL());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse map svg to object url
|
||||||
|
async function getMapLayerURL(type, subtype, visibles) {
|
||||||
|
const cloneEl = document.getElementById("map").cloneNode(true); // clone svg
|
||||||
|
cloneEl.id = "fantasyMap";
|
||||||
|
document.body.appendChild(cloneEl);
|
||||||
|
const clone = d3.select(cloneEl);
|
||||||
|
clone.attr("width", mapWidthInput.value).attr("height", mapHeightInput.value).attr("background-color", "transparent");
|
||||||
|
clone.select("#debug").remove();
|
||||||
|
clone.select('#ruler').remove();
|
||||||
|
clone.select('#scaleBar').remove();
|
||||||
|
|
||||||
|
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||||
|
if (isFirefox && type === "mesh") clone.select("#oceanPattern").remove();
|
||||||
|
|
||||||
|
if (subtype === "noWater") {clone.select("#oceanBase").attr("opacity", 0); clone.select("#oceanPattern").attr("opacity", 0);}
|
||||||
|
if (type !== "png") {
|
||||||
|
// reset transform to show the whole map
|
||||||
|
clone.attr("width", graphWidth).attr("height", graphHeight);
|
||||||
|
clone.select("#viewbox").attr("transform", null);
|
||||||
|
}
|
||||||
|
if (type === "svg") removeUnusedElements(clone);
|
||||||
|
if (customization && type === "mesh") updateMeshCells(clone);
|
||||||
|
|
||||||
|
const LAYERS = ["ocean", "lake", "landmass", "texture", "terrs", "biomes", "cells", "gridOverlay", "coordinates", "compass",
|
||||||
|
"rivers", "terrain", "relig", "cults", "regions", "statesBody", "statesHalo", "provs", "zones", "borders", "stateBorders",
|
||||||
|
"provinceBorders", "routes", "roads", "trails", "searoutes", "temperature", "coastline", "prec", "population", "labels",
|
||||||
|
"icons", "burgIcons", "anchors", "markers", "fogging-cont", "fogging"];
|
||||||
|
|
||||||
|
LAYERS.forEach((layer) => {
|
||||||
|
if (visibles.indexOf(layer) < 0) {
|
||||||
|
clone.select('#' + layer).remove();
|
||||||
|
} else {
|
||||||
|
clone.select('#' + layer).attr("opacity", 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
inlineStyle(clone);
|
||||||
|
|
||||||
|
const fontStyle = await GFontToDataURI(getFontsToLoad()); // load non-standard fonts
|
||||||
|
if (fontStyle) clone.select("defs").append("style").text(fontStyle.join('\n')); // add font to style
|
||||||
|
|
||||||
|
clone.append("metadata").text("<dc:format>image/svg+xml</dc:format>");
|
||||||
|
const serialized = (new XMLSerializer()).serializeToString(clone.node());
|
||||||
|
const svg_xml = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>` + serialized;
|
||||||
|
clone.remove();
|
||||||
|
const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
window.setTimeout(() => window.URL.revokeObjectURL(url), 5000);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMapExportData (landmassImage, provincesImage) {
|
||||||
|
console.time("getMapExportData");
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const date = new Date();
|
||||||
|
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||||
|
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
|
||||||
|
|
||||||
|
const params = { version, license, dateString, seed, graphWidth, graphHeight };
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
distanceUnitInput: distanceUnitInput.value,
|
||||||
|
distanceScaleInput: distanceScaleInput.value,
|
||||||
|
areaUnit: areaUnit.value,
|
||||||
|
heightUnit: heightUnit.value,
|
||||||
|
heightExponentInput: heightExponentInput.value,
|
||||||
|
temperatureScale: temperatureScale.value,
|
||||||
|
barSize: barSize.value,
|
||||||
|
barLabel: barLabel.value,
|
||||||
|
barBackOpacity: barBackOpacity.value,
|
||||||
|
barBackColor: barBackColor.value,
|
||||||
|
barPosX: barPosX.value,
|
||||||
|
barPosY: barPosY.value,
|
||||||
|
populationRate: populationRate.value,
|
||||||
|
urbanization: urbanization.value,
|
||||||
|
mapSizeOutput: mapSizeOutput.value,
|
||||||
|
latitudeOutput: latitudeOutput.value,
|
||||||
|
temperatureEquatorOutput: temperatureEquatorOutput.value,
|
||||||
|
temperaturePoleOutput: temperaturePoleOutput.value,
|
||||||
|
precOutput: precOutput.value,
|
||||||
|
winds,
|
||||||
|
mapName: mapName.value
|
||||||
|
};
|
||||||
|
|
||||||
|
const coords = mapCoordinates;
|
||||||
|
|
||||||
|
const biomes = {
|
||||||
|
color: biomesData.color,
|
||||||
|
habitability: biomesData.habitability,
|
||||||
|
name: biomesData.name
|
||||||
|
};
|
||||||
|
|
||||||
|
const notesData = notes;
|
||||||
|
|
||||||
|
const cloneEl = document.getElementById("map").cloneNode(true); // clone svg
|
||||||
|
|
||||||
|
// set transform values to default
|
||||||
|
cloneEl.setAttribute("width", graphWidth);
|
||||||
|
cloneEl.setAttribute("height", graphHeight);
|
||||||
|
cloneEl.querySelector("#viewbox").setAttribute("transform", null);
|
||||||
|
const svg_xml = (new XMLSerializer()).serializeToString(cloneEl);
|
||||||
|
|
||||||
|
const gridGeneral = {spacing:grid.spacing, cellsX:grid.cellsX, cellsY:grid.cellsY, boundary:grid.boundary, points:grid.points, features:grid.features};
|
||||||
|
const features = pack.features;
|
||||||
|
const cultures = pack.cultures;
|
||||||
|
const states = pack.states;
|
||||||
|
const burgs = pack.burgs;
|
||||||
|
const religions = pack.religions;
|
||||||
|
const provinces = pack.provinces;
|
||||||
|
const rivers = pack.rivers;
|
||||||
|
|
||||||
|
// store name array only if it is not the same as default
|
||||||
|
const defaultNB = Names.getNameBases();
|
||||||
|
const namesData = nameBases.map((b,i) => {
|
||||||
|
const names = defaultNB[i] && defaultNB[i].b === b.b ? "" : b.b;
|
||||||
|
return `${b.name}|${b.min}|${b.max}|${b.d}|${b.m}|${names}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
// round population to save resources
|
||||||
|
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||||
|
|
||||||
|
// data format as below
|
||||||
|
const data = JSON.stringify(
|
||||||
|
{
|
||||||
|
params,
|
||||||
|
options,
|
||||||
|
coords,
|
||||||
|
biomes,
|
||||||
|
notesData,
|
||||||
|
gridGeneral,
|
||||||
|
grid: {
|
||||||
|
cells: {
|
||||||
|
h: grid.cells.h,
|
||||||
|
prec: grid.cells.prec,
|
||||||
|
f: grid.cells.f,
|
||||||
|
t: grid.cells.t,
|
||||||
|
temp: grid.cells.temp
|
||||||
|
}
|
||||||
|
},
|
||||||
|
features,
|
||||||
|
cultures,
|
||||||
|
states,
|
||||||
|
burgs,
|
||||||
|
pack: {
|
||||||
|
cells: {
|
||||||
|
r: pack.cells.r,
|
||||||
|
road: pack.cells.road,
|
||||||
|
s: pack.cells.s,
|
||||||
|
state: pack.cells.state,
|
||||||
|
religion: pack.cells.religion,
|
||||||
|
province: pack.cells.province,
|
||||||
|
crossroad: pack.cells.crossroad
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pop,
|
||||||
|
religions,
|
||||||
|
provinces,
|
||||||
|
namesData,
|
||||||
|
rivers,
|
||||||
|
landmassImage,
|
||||||
|
provincesImage
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
const blob = new Blob([data], {type: "text/plain"});
|
||||||
|
|
||||||
|
console.timeEnd("getMapExportData");
|
||||||
|
resolve(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue