mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-21 19:41:23 +01:00
Merge remote-tracking branch 'upstream/master' into geodata
This commit is contained in:
commit
1aa668bd20
17 changed files with 278 additions and 64 deletions
BIN
.DS_Store
vendored
BIN
.DS_Store
vendored
Binary file not shown.
5
LICENSE
5
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018-2019 Max Ganiev (Azgaar)
|
||||
Copyright 2018-2019 Max Ganiev (Azgaar), azgaar.fmg@yandex.by
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -12,6 +12,9 @@ furnished to do so, subject to the following conditions:
|
|||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
You can produce, without restrictions, any derivative works from the original
|
||||
software and even reap commercial benefits from the sale of the secondary product.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Refer to the [project wiki](https://github.com/Azgaar/Fantasy-Map-Generator/wiki
|
|||
|
||||
[](https://cdn.discordapp.com/attachments/515359096925454350/593891237984206848/The_Wichin_Island_-_diplomacy.png)
|
||||
|
||||
Join our [Reddit community](https://www.reddit.com/r/FantasyMapGenerator) and [Discord server](https://discordapp.com/invite/X7E84HU) to share the created maps, discuss the Generator, suggest ideas and get a most recent updates. You may also contact me directly via [email](mailto:maxganiev@yandex.com). For bug reports please use the project [issues page](https://github.com/Azgaar/Fantasy-Map-Generator/issues) or Discord "Bugs" channel. If you are facing performance issues, please read [the tips](https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Tips#performance-tips).
|
||||
Join our [Reddit community](https://www.reddit.com/r/FantasyMapGenerator) and [Discord server](https://discordapp.com/invite/X7E84HU) to share the created maps, discuss the Generator, suggest ideas and get a most recent updates. You may also contact me directly via [email](mailto:azgaar.fmg@yandex.by). For bug reports please use the project [issues page](https://github.com/Azgaar/Fantasy-Map-Generator/issues) or Discord "Bugs" channel. If you are facing performance issues, please read [the tips](https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Tips#performance-tips).
|
||||
|
||||
You can support the project [on Patreon](https://www.patreon.com/azgaar).
|
||||
|
||||
|
|
|
|||
|
|
@ -1931,7 +1931,7 @@ svg.button {
|
|||
|
||||
#errorBox {
|
||||
font-size: .9em;
|
||||
font-family: monospace;
|
||||
font-family: Consolas, monospace;
|
||||
color: #920303;
|
||||
background-color: #dabdbd91;
|
||||
padding: 2px;
|
||||
|
|
|
|||
40
index.html
40
index.html
|
|
@ -1709,18 +1709,18 @@
|
|||
<div id="toolsContent" class="tabcontent">
|
||||
<div id="openEditor">
|
||||
<p>Click to configure:</p>
|
||||
<button id="editHeightmapButton" data-tip="Click to open Heightmap customization menu">Heightmap</button>
|
||||
<button id="editBiomesButton" data-tip="Click to open Biomes Editor">Biomes</button>
|
||||
<button id="editStatesButton" data-tip="Click to open States Editor">States</button>
|
||||
<button id="editProvincesButton" data-tip="Click to open Provinces Editor">Provinces</button>
|
||||
<button id="editDiplomacyButton" data-tip="Click to open Diplomatical relationships Editor">Diplomacy</button>
|
||||
<button id="editCulturesButton" data-tip="Click to open Cultures Editor">Cultures</button>
|
||||
<button id="editNamesBaseButton" data-tip="Click to open Namesbase Editor">Namesbase</button>
|
||||
<button id="editZonesButton" data-tip="Click to open Zones Editor">Zones</button>
|
||||
<button id="editReligions" data-tip="Click to open Religions Editor">Religions</button>
|
||||
<button id="editBurgsButton" data-tip="Click to open Burgs Editor">Burgs</button>
|
||||
<button id="editUnitsButton" data-tip="Click to open Units Editor">Units</button>
|
||||
<button id="editNotesButton" data-tip="Click to open Notes Editor">Notes</button>
|
||||
<button id="editHeightmapButton" data-tip="Click to open Heightmap customization menu. Shortcut: Shift + H">Heightmap</button>
|
||||
<button id="editBiomesButton" data-tip="Click to open Biomes Editor. Shortcut: Shift + B">Biomes</button>
|
||||
<button id="editStatesButton" data-tip="Click to open States Editor. Shortcut: Shift + S">States</button>
|
||||
<button id="editProvincesButton" data-tip="Click to open Provinces Editor. Shortcut: Shift + P">Provinces</button>
|
||||
<button id="editDiplomacyButton" data-tip="Click to open Diplomatical relationships Editor. Shortcut: Shift + D">Diplomacy</button>
|
||||
<button id="editCulturesButton" data-tip="Click to open Cultures Editor. Shortcut: Shift + C">Cultures</button>
|
||||
<button id="editNamesBaseButton" data-tip="Click to open Namesbase Editor. Shortcut: Shift + N">Namesbase</button>
|
||||
<button id="editZonesButton" data-tip="Click to open Zones Editor. Shortcut: Shift + Z">Zones</button>
|
||||
<button id="editReligions" data-tip="Click to open Religions Editor. Shortcut: Shift + R">Religions</button>
|
||||
<button id="editBurgsButton" data-tip="Click to open Burgs Editor. Shortcut: Shift + T">Burgs</button>
|
||||
<button id="editUnitsButton" data-tip="Click to open Units Editor. Shortcut: Shift + U">Units</button>
|
||||
<button id="editNotesButton" data-tip="Click to open Notes Editor. Shortcut: Shift + O">Notes</button>
|
||||
</div>
|
||||
|
||||
<div id="regenerateFeature">
|
||||
|
|
@ -1738,11 +1738,11 @@
|
|||
|
||||
<div id="addFeature">
|
||||
<p>Click to add:</p>
|
||||
<button id="addBurgTool" data-tip="Click on map to place a burg. Hold Shift to add multiple">Burg</button>
|
||||
<button id="addLabel" data-tip="Click on map to place label. Hold Shift to add multiple">Label</button>
|
||||
<button id="addRiver" data-tip="Click on map to place a river. Hold Shift to add multiple">River</button>
|
||||
<button id="addRoute" data-tip="Click on map to place a route">Route</button>
|
||||
<button id="addMarker" data-tip="Click on map to place a marker. Hold Shift to add multiple">Marker</button>
|
||||
<button id="addBurgTool" data-tip="Click on map to place a burg. Hold Shift to add multiple. Shortcut: Shift + G">Burg</button>
|
||||
<button id="addLabel" data-tip="Click on map to place label. Hold Shift to add multiple. Shortcut: Shift + A">Label</button>
|
||||
<button id="addRiver" data-tip="Click on map to place a river. Hold Shift to add multiple. Shortcut: Shift + I">River</button>
|
||||
<button id="addRoute" data-tip="Click on map to place a route. Shortcut: Shift + E">Route</button>
|
||||
<button id="addMarker" data-tip="Click on map to place a marker. Hold Shift to add multiple. Shortcut: Shift + K">Marker</button>
|
||||
</div>
|
||||
|
||||
<p>Cell info: <i data-tip="Click to toggle the section" class="collapsible icon-down-open pointer"></i></p>
|
||||
|
|
@ -1812,7 +1812,7 @@
|
|||
<div id="aboutContent" class="tabcontent">
|
||||
<p><a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is a free <a href="https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE" target="_blank">open source</a> tool which procedurally generates fantasy maps. You may use auto-generated maps as they are, edit them or even create a new map from scratch. Check out the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Quick-Start-Tutorial" target="_blank">quick start tutorial</a> and <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki" target="_blank">project wiki</a> for guidance.</p>
|
||||
<p>Join our <a href='https://discordapp.com/invite/X7E84HU' target='_blank'>Discord server</a> and <a href="https://www.reddit.com/r/FantasyMapGenerator/" target="_blank">Reddit community</a> to ask questions, get help and share created maps. You may support the project on <a href='https://www.patreon.com/azgaar' target='_blank'>Patreon</a>.</p>
|
||||
<p>The project is under active development. For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. To track the development progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>. Please report bugs <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You can also contact me directly via <a href="mailto:maxganiev@yandex.ru" target="_blank">email</a>.</p>
|
||||
<p>The project is under active development. For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. To track the development progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>. Please report bugs <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You can also contact me directly via <a href="mailto:azgaar.fmg@yandex.by" target="_blank">email</a>.</p>
|
||||
<p>A special thanks to all supporters! <i data-tip="Click to see supporters names" class="collapsible icon-down-open pointer"></i></p>
|
||||
<p style="display:none">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,
|
||||
|
|
@ -1838,7 +1838,7 @@
|
|||
<div id="saveMap" data-tip="Download the map as fully functional .map file to your machine. Shortcut: Ctrl + M">.map</div>
|
||||
<div id="saveSVG" data-tip="Download the map as vector image (open in browser or Inkscape). Shortcut: Ctrl + S">.svg</div>
|
||||
<div id="savePNG" data-tip="Download visible part of the map as .png image. Shortcut: Ctrl + P">.png</div>
|
||||
<div id="saveGeo" data-tip="Download cell data as GeoJSON (for use in GIS tools such as QGIS).">.json</div>
|
||||
<div id="saveGeo" data-tip="Download map data in GeoJSON format. Shortcut: Ctrl + G">.json</div>
|
||||
<div id="quickSave" data-tip="Save map to browser storage. Shortcut: F6">storage</div>
|
||||
<!-- <div id="saveDropbox" data-tip="Save fully functional .map file to Dropbox. Shortcut: Ctrl + B">Dropbox</div> -->
|
||||
</div>
|
||||
|
|
@ -2385,7 +2385,7 @@
|
|||
<button id="templateRedo" data-tip="Redo the action" class="icon-cw" disabled></button>
|
||||
<button id="templateSave" data-tip="Download the template as a text file" class="icon-download"></button>
|
||||
<button id="templateLoad" data-tip="Open previously downloaded template" class="icon-upload"></button>
|
||||
<button id="templateMail" onclick="window.open('mailto:maxganiev@yandex.com?Subject=Template%20suggestion', '_blank')" data-tip="Send a template suggestion to Azgaar" class="icon-mail-alt"></button>
|
||||
<button id="templateMail" onclick="window.open('mailto:azgaar.fmg@yandex.by?Subject=Template%20suggestion', '_blank')" data-tip="Send a template suggestion to Azgaar" class="icon-mail-alt"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
1
libs/jquery-ui.css
vendored
1
libs/jquery-ui.css
vendored
|
|
@ -362,7 +362,6 @@ body .ui-dialog {
|
|||
border: 0;
|
||||
padding: .5em 1em;
|
||||
background: none;
|
||||
overflow: auto;
|
||||
}
|
||||
.ui-dialog .ui-dialog-buttonpane {
|
||||
text-align: left;
|
||||
|
|
|
|||
15
main.js
15
main.js
|
|
@ -1,5 +1,5 @@
|
|||
// Fantasy Map Generator main script
|
||||
// Azgaar (maxganiev@yandex.com). Minsk, 2017-2019
|
||||
// Azgaar (azgaar.fmg@yandex.by). Minsk, 2017-2019
|
||||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||
// MIT License
|
||||
|
||||
|
|
@ -688,17 +688,14 @@ function generate() {
|
|||
console.error(error);
|
||||
clearMainTip();
|
||||
|
||||
const regex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||
const errorNoURL = error.stack.replace(regex, url => '<i>' + last(url.split("/")) + '</i>');
|
||||
const errorParsed = errorNoURL.replace(/at /ig, "<br> at ");
|
||||
|
||||
alertMessage.innerHTML = `An error is occured on map generation. Please retry.
|
||||
<br>If error persists, clear the stored data and try again.
|
||||
<p id="errorBox">${errorParsed}</p>`;
|
||||
<br>If error is critical, clear the stored data and try again.
|
||||
<p id="errorBox">${parseError(error)}</p>`;
|
||||
$("#alert").dialog({
|
||||
resizable: false, title: "Generation error", maxWidth:500, buttons: {
|
||||
resizable: false, title: "Generation error", width:320, buttons: {
|
||||
"Clear data": function() {localStorage.clear(); localStorage.setItem("version", version);},
|
||||
Regenerate: function() {regenerateMap(); $(this).dialog("close");}
|
||||
Regenerate: function() {regenerateMap(); $(this).dialog("close");},
|
||||
Ignore: function() {$(this).dialog("close");}
|
||||
}, position: {my: "center", at: "center", of: "svg"}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
13
maps/template_crescent.txt
Normal file
13
maps/template_crescent.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Hill 2-3 20-40 20-40 20-40
|
||||
Hill 2-3 20-40 20-40 40-60
|
||||
Hill 2-3 20-40 40-60 20-40
|
||||
Hill 2-3 20-40 60-80 20-40
|
||||
Hill 2-3 20-40 20-40 60-80
|
||||
Smooth 1 0 0 0
|
||||
Range 1-2 40-50 20-40 20-80
|
||||
Range 1-2 40-50 20-80 20-40
|
||||
Trough 1-2 40-50 15-85 15-85
|
||||
Pit 1-2 40-50 15-85 15-85
|
||||
Hill 1-2 30-50 60-85 60-85
|
||||
Smooth 2 0 0 0
|
||||
Hill 6-8 10-20 20-80 20-80
|
||||
|
|
@ -436,6 +436,8 @@
|
|||
|
||||
void function drawLabels() {
|
||||
const g = labels.select("#states"), t = defs.select("#textPaths");
|
||||
const displayed = layerIsOn("toggleLabels");
|
||||
if (!displayed) toggleLabels();
|
||||
|
||||
if (!list) {
|
||||
g.selectAll("text").remove();
|
||||
|
|
@ -520,6 +522,7 @@
|
|||
});
|
||||
|
||||
example.remove();
|
||||
if (!displayed) toggleLabels();
|
||||
}()
|
||||
|
||||
console.timeEnd("drawStateLabels");
|
||||
|
|
@ -583,6 +586,7 @@
|
|||
const generateDiplomacy = function() {
|
||||
console.time("generateDiplomacy");
|
||||
const cells = pack.cells, states = pack.states;
|
||||
const chronicle = states[0].diplomacy = [];
|
||||
const valid = states.filter(s => s.i && !states.removed);
|
||||
if (valid.length < 2) return;
|
||||
|
||||
|
|
@ -592,7 +596,6 @@
|
|||
const navals = {"Neutral":1, "Suspicion":2, "Rival":1, "Unknown":1}; // relations of naval powers
|
||||
|
||||
valid.forEach(s => s.diplomacy = new Array(states.length).fill("x")); // clear all relationships
|
||||
const chronicle = states[0].diplomacy = [];
|
||||
const areaMean = d3.mean(valid.map(s => s.area)); // avarage state area
|
||||
|
||||
// generic relations
|
||||
|
|
|
|||
|
|
@ -387,6 +387,146 @@ async function saveMap() {
|
|||
window.setTimeout(() => window.URL.revokeObjectURL(URL), 5000);
|
||||
}
|
||||
|
||||
// download map data as GeoJSON
|
||||
function saveGeoJSON() {
|
||||
alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS.
|
||||
Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance`;
|
||||
|
||||
$("#alert").dialog({title: "GIS data export", resizable: false, width: 320, position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Cells: saveGeoJSON_Cells,
|
||||
Routes: saveGeoJSON_Roads,
|
||||
Rivers: saveGeoJSON_Rivers,
|
||||
Close: function() {$(this).dialog("close");}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveGeoJSON_Roads() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
routes._groups[0][0].childNodes.forEach(n => {
|
||||
n.childNodes.forEach(r => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRoadPoints(r));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+r.id+"\",\n";
|
||||
data += " \"type\": \""+n.id+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_routes_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function saveGeoJSON_Rivers() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
rivers._groups[0][0].childNodes.forEach(n => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRiverPoints(n));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+n.id+"\",\n";
|
||||
data += " \"width\": \""+n.dataset.width+"\",\n";
|
||||
data += " \"increment\": \""+n.dataset.increment+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_rivers_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function getRoadPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength();
|
||||
const increment = l / Math.ceil(l / 2);
|
||||
for (let i=0; i <= l; i += increment) {
|
||||
const p = node.getPointAtLength(i);
|
||||
|
||||
let x = mapCoordinates.lonW + (p.x / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (p.y / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function getRiverPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength() / 2; // half-length
|
||||
const increment = 0.25; // defines density of points
|
||||
for (let i=l, c=i; i >= 0; i -= increment, c += increment) {
|
||||
const p1 = node.getPointAtLength(i);
|
||||
const p2 = node.getPointAtLength(c);
|
||||
|
||||
let x = mapCoordinates.lonW + (((p1.x+p2.x)/2) / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (((p1.y+p2.y)/2) / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
function saveGeoJSON_Cells() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
const cells = pack.cells, v = pack.vertices;
|
||||
|
||||
cells.i.forEach(i => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [[";
|
||||
cells.v[i].forEach(n => {
|
||||
let x = mapCoordinates.lonW + (v.p[n][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[n][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"],";
|
||||
});
|
||||
// close the ring
|
||||
let x = mapCoordinates.lonW + (v.p[cells.v[i][0]][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[cells.v[i][0]][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"]";
|
||||
data += "]] },\n \"properties\": {\n";
|
||||
|
||||
let height = parseInt(getFriendlyHeight(cells.h[i]));
|
||||
|
||||
data += " \"id\": \""+i+"\",\n";
|
||||
data += " \"height\": \""+height+"\",\n";
|
||||
data += " \"biome\": \""+cells.biome[i]+"\",\n";
|
||||
data += " \"population\": \""+cells.pop[i]+"\",\n";
|
||||
data += " \"state\": \""+cells.state[i]+"\",\n";
|
||||
data += " \"province\": \""+cells.province[i]+"\",\n";
|
||||
data += " \"culture\": \""+cells.culture[i]+"\",\n";
|
||||
data += " \"religion\": \""+cells.religion[i]+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_cells_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function uploadFile(file, callback) {
|
||||
uploadFile.timeStart = performance.now();
|
||||
|
||||
|
|
@ -695,6 +835,7 @@ function parseLoadedData(data) {
|
|||
|
||||
// v 1.0 initially has Sympathy status then relaced with Friendly
|
||||
for (const s of pack.states) {
|
||||
if (!s.diplomacy) continue;
|
||||
s.diplomacy = s.diplomacy.map(r => r === "Sympathy" ? "Friendly" : r);
|
||||
}
|
||||
}
|
||||
|
|
@ -713,13 +854,9 @@ function parseLoadedData(data) {
|
|||
console.error(error);
|
||||
clearMainTip();
|
||||
|
||||
const regex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||
const errorNoURL = error.stack.replace(regex, url => '<i>' + last(url.split("/")) + '</i>');
|
||||
const errorParsed = errorNoURL.replace(/ at /ig, "<br> at ");
|
||||
|
||||
alertMessage.innerHTML = `An error is occured on map loading. Select a different file to load,
|
||||
<br>generate a new random map or cancel the loading
|
||||
<p id="errorBox">${errorParsed}</p>`;
|
||||
<p id="errorBox">${parseError(error)}</p>`;
|
||||
$("#alert").dialog({
|
||||
resizable: false, title: "Loading error", maxWidth:500, buttons: {
|
||||
"Select file": function() {$(this).dialog("close"); mapToLoad.click();},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
function editDiplomacy() {
|
||||
if (customization) return;
|
||||
if (pack.states.filter(s => s.i && !s.removed).length < 2) {
|
||||
tip("There should be at least 2 states to edit the diplomacy", false, "Error");
|
||||
tip("There should be at least 2 states to edit the diplomacy", false, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -231,28 +231,50 @@ document.addEventListener("keydown", function(event) {
|
|||
const active = document.activeElement.tagName;
|
||||
if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; // don't trigger if user inputs a text
|
||||
if (active === "DIV" && document.activeElement.contentEditable === "true") return; // don't trigger if user inputs a text
|
||||
const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey;
|
||||
const key = event.keyCode, ctrl = event.ctrlKey, shift = event.shiftKey, meta = event.metaKey;
|
||||
if (key === 27) {closeDialogs(); hideOptions();} // Escape to close all dialogs
|
||||
else if (key === 9) {toggleOptions(event); event.preventDefault();} // Tab to toggle options
|
||||
|
||||
else if (key === 113) regeneratePrompt(); // "F2" for new map
|
||||
else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element
|
||||
else if (key === 117) quickSave(); // "F6" for quick save
|
||||
else if (key === 120) quickLoad(); // "F9" for quick load
|
||||
|
||||
else if (ctrl && key === 80) saveAsImage("png"); // Ctrl + "P" to save as PNG
|
||||
else if (ctrl && key === 83) saveAsImage("svg"); // Ctrl + "S" to save as SVG
|
||||
else if (ctrl && key === 77) saveMap(); // Ctrl + "M" to save MAP file
|
||||
else if (ctrl && key === 71) saveGeoJSON(); // Ctrl + "G" to save as GeoJSON
|
||||
else if (ctrl && key === 85) mapToLoad.click(); // Ctrl + "U" to load MAP from URL
|
||||
else if (ctrl && key === 76) mapToLoad.click(); // Ctrl + "L" to load MAP from local file
|
||||
else if (ctrl && key === 81) toggleSaveReminder(); // Ctrl + "Q" to toggle save reminder
|
||||
else if (key === 46) removeElementOnKey(); // "Delete" to remove the selected element
|
||||
else if (undo.offsetParent && ctrl && key === 90) undo.click(); // Ctrl + "Z" to undo
|
||||
else if (redo.offsetParent && ctrl && key === 89) redo.click(); // Ctrl + "Y" to redo
|
||||
|
||||
else if (shift && key === 192) console.log(pack.cells); // Shift + "`" to log cells data
|
||||
else if (shift && key === 66) console.table(pack.burgs); // Shift + "B" to log burgs data
|
||||
else if (shift && key === 83) console.table(pack.states); // Shift + "S" to log states data
|
||||
else if (shift && key === 67) console.table(pack.cultures); // Shift + "C" to log cultures data
|
||||
else if (shift && key === 82) console.table(pack.religions); // Shift + "R" to log religions data
|
||||
else if (shift && key === 70) console.table(pack.features); // Shift + "F" to log features data
|
||||
else if (shift && key === 72) editHeightmap(); // Shift + "H" to edit Heightmap
|
||||
else if (shift && key === 66) editBiomes(); // Shift + "B" to edit Biomes
|
||||
else if (shift && key === 83) editStates(); // Shift + "S" to edit States
|
||||
else if (shift && key === 80) editProvinces(); // Shift + "P" to edit Provinces
|
||||
else if (shift && key === 68) editDiplomacy(); // Shift + "D" to edit Diplomacy
|
||||
else if (shift && key === 67) editCultures(); // Shift + "C" to edit Cultures
|
||||
else if (shift && key === 78) editNamesbase(); // Shift + "N" to edit Namesbase
|
||||
else if (shift && key === 90) editZones(); // Shift + "Z" to edit Zones
|
||||
else if (shift && key === 82) editReligions(); // Shift + "R" to edit Religions
|
||||
else if (shift && key === 84) editBurgs(); // Shift + "T" to edit Burgs
|
||||
else if (shift && key === 85) editUnits(); // Shift + "U" to edit Units
|
||||
else if (shift && key === 79) editNotes(); // Shift + "O" to edit Notes
|
||||
|
||||
else if (shift && key === 71) toggleAddBurg(); // Shift + "G" to click to add Burg
|
||||
else if (shift && key === 65) toggleAddLabel(); // Shift + "A" to click to add Label
|
||||
else if (shift && key === 73) toggleAddRiver(); // Shift + "I" to click to add River
|
||||
else if (shift && key === 69) toggleAddRoute(); // Shift + "E" to click to add Route
|
||||
else if (shift && key === 75) toggleAddMarker(); // Shift + "K" to click to add Marker
|
||||
|
||||
else if (meta && key === 192) console.log(pack.cells); // Metakey + "`" to log cells data
|
||||
else if (meta && key === 66) console.table(pack.burgs); // Metakey + "B" to log burgs data
|
||||
else if (meta && key === 83) console.table(pack.states); // Metakey + "S" to log states data
|
||||
else if (meta && key === 67) console.table(pack.cultures); // Metakey + "C" to log cultures data
|
||||
else if (meta && key === 82) console.table(pack.religions); // Metakey + "R" to log religions data
|
||||
else if (meta && key === 70) console.table(pack.features); // Metakey + "F" to log features data
|
||||
|
||||
else if (key === 88) toggleTexture(); // "X" to toggle Texture layer
|
||||
else if (key === 72) toggleHeight(); // "H" to toggle Heightmap layer
|
||||
|
|
@ -294,10 +316,6 @@ document.addEventListener("keydown", function(event) {
|
|||
else if (key === 55 || key === 103) zoom.scaleTo(svg, 7); // 7 to zoom to 7
|
||||
else if (key === 56 || key === 104) zoom.scaleTo(svg, 8); // 8 to zoom to 8
|
||||
else if (key === 57 || key === 105) zoom.scaleTo(svg, 9); // 9 to zoom to 9
|
||||
|
||||
else if (ctrl && key === 90) undo.click(); // Ctrl + "Z" to undo
|
||||
else if (ctrl && key === 89) redo.click(); // Ctrl + "Y" to redo
|
||||
|
||||
else if (ctrl) pressControl(); // Control to toggle mode
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1117,7 +1117,8 @@ function getHeight(h) {
|
|||
preview.width = grid.cellsX;
|
||||
preview.height = grid.cellsY;
|
||||
document.body.insertBefore(preview, optionsContainer);
|
||||
preview.addEventListener("mouseover", () => tip("Heightmap preview. Right click and 'Save image as..' to download the image"));
|
||||
preview.addEventListener("mouseover", () => tip("Heightmap preview. Click to download the image"));
|
||||
preview.addEventListener("click", downloadPreview);
|
||||
drawHeightmapPreview();
|
||||
}
|
||||
|
||||
|
|
@ -1137,6 +1138,41 @@ function getHeight(h) {
|
|||
ctx.putImageData(imageData, 0, 0);
|
||||
}
|
||||
|
||||
function downloadPreview() {
|
||||
const preview = document.getElementById("preview");
|
||||
const dataURL = preview.toDataURL("image/png");
|
||||
|
||||
const img = new Image();
|
||||
img.src = dataURL;
|
||||
|
||||
img.onload = function() {
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
canvas.width = svgWidth;
|
||||
canvas.height = svgHeight;
|
||||
document.body.insertBefore(canvas, optionsContainer);
|
||||
ctx.drawImage(img, 0, 0, svgWidth, svgHeight);
|
||||
|
||||
// const imageData = ctx.getImageData(0, 0, svgWidth, svgHeight);
|
||||
// for (let i=0; i < imageData.data.length; i+=4) {
|
||||
// const v = Math.min(rn(imageData.data[i] * gauss(1, .05, .9, 1.1, 3)), 255);
|
||||
// imageData.data[i] = v;
|
||||
// imageData.data[i+1] = v;
|
||||
// imageData.data[i+2] = v;
|
||||
// }
|
||||
// ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
const imgBig = canvas.toDataURL("image/png");
|
||||
const link = document.createElement("a");
|
||||
link.target = "_blank";
|
||||
link.download = "heightmap_" + Date.now() + ".png";
|
||||
link.href = imgBig;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
canvas.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function openPerspectivePanel() {
|
||||
if ($("#perspectivePanel").is(":visible")) return;
|
||||
$("#perspectivePanel").dialog({
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ function editLabel() {
|
|||
viewbox.on("touchmove mousemove", showEditorTips);
|
||||
|
||||
$("#labelEditor").dialog({
|
||||
title: "Edit Label", resizable: false,
|
||||
title: "Edit Label", resizable: false, width: fitContent(),
|
||||
position: {my: "center top+10", at: "bottom", of: text, collision: "fit"},
|
||||
close: closeLabelEditor
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1011,11 +1011,11 @@ function toggleMarkers() {
|
|||
function toggleLabels() {
|
||||
if (!layerIsOn("toggleLabels")) {
|
||||
turnButtonOn("toggleLabels");
|
||||
$('#labels').fadeIn();
|
||||
labels.attr("display", null)
|
||||
invokeActiveZooming();
|
||||
} else {
|
||||
turnButtonOff("toggleLabels");
|
||||
$('#labels').fadeOut();
|
||||
labels.attr("display", "none");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1027,12 +1027,10 @@ function toggleSavePane() {
|
|||
<br>Please check browser settings and turn off adBlocker if it is enabled`;
|
||||
|
||||
$("#alert").dialog({title: "File saver", resizable: false, position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
OK: function() {
|
||||
localStorage.setItem("dns_allow_popup_message", true);
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
buttons: {OK: function() {
|
||||
localStorage.setItem("dns_allow_popup_message", true);
|
||||
$(this).dialog("close");
|
||||
}}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue