From 92a50d9810c401d5eab1077a32c2caf0d6042390 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Tue, 3 Sep 2019 22:34:52 +0300 Subject: [PATCH 1/3] v1.0.07 --- index.css | 14 +++- index.html | 10 ++- main.js | 152 ++++++++++++++++++++++-------------- modules/burgs-and-states.js | 3 +- modules/save-and-load.js | 9 ++- modules/ui/burg-editor.js | 2 +- modules/ui/burgs-editor.js | 2 +- modules/ui/general.js | 17 ++-- modules/ui/options.js | 27 ++++++- 9 files changed, 161 insertions(+), 75 deletions(-) diff --git a/index.css b/index.css index cb25d8c4..07f2ab8e 100644 --- a/index.css +++ b/index.css @@ -996,14 +996,26 @@ div.slider .ui-slider-handle { top: 100%; border: 1px solid #5e4fa2; background-color: #a4879b; - width: 44px; + width: 3.6em; } +#loadDropdown { + display: none; + position: absolute; + left: 53%; + top: 100%; + border: 1px solid #5e4fa2; + background-color: #a4879b; + width: 6em; +} + +#loadDropdown>div, #saveDropdown>div { padding: 2px 4px; cursor: pointer; } +#loadDropdown>div:hover, #saveDropdown>div:hover { color: white; } diff --git a/index.html b/index.html index a6f2333c..e5313fb5 100644 --- a/index.html +++ b/index.html @@ -1814,13 +1814,17 @@
- +
.map
.svg
.png
- + +
+
from URL
+
from file
+
@@ -2945,6 +2949,7 @@ + @@ -2969,7 +2974,6 @@ - diff --git a/main.js b/main.js index 97d5ffd8..3ca86481 100644 --- a/main.js +++ b/main.js @@ -81,9 +81,8 @@ population.append("g").attr("id", "urban"); fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%"); // assign events separately as not a viewbox child -scaleBar.on("mousemove", function() {tip("Click to open Units Editor")}); -legend.on("mousemove", function() {tip("Drag to change the position. Click to hide the legend")}) - .on("click", () => clearLegend()); +scaleBar.on("mousemove", () => tip("Click to open Units Editor")); +legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend()); // main data variables let grid = {}; // initial grapg based on jittered square grid and data @@ -111,61 +110,52 @@ landmass.append("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr oceanPattern.append("rect").attr("fill", "url(#oceanic)").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight); oceanLayers.append("rect").attr("id", "oceanBase").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight); -applyDefaultNamesData(); // apply default namesbase on load -applyDefaultStyle(); // apply style on load -generate(); // generate map on load -focusOn(); // based on searchParams focus on point, cell or burg from MFCG -applyPreset(); // apply saved layers preset on load +applyDefaultNamesData(); // always apply default namesbase load as namesdata is not stored in .map file -// show message on load if required -setTimeout(showWelcomeMessage, 7000); -function showWelcomeMessage() { - // Changelog dialog window - if (localStorage.getItem("version") != version) { - const link = 'https://www.reddit.com/r/FantasyMapGenerator/comments/cxu1c5/update_new_version_is_published_v_10'; // announcement on Reddit - alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version ${version}. +// load linked map from url or generate a random map +void function checkLoadParameters() { + const url = new URL(window.location.href); + const maplink = url.searchParams.get("maplink"); - This version is compatible with versions 0.8b and 0.9b, but not with older .map files. - Please use an archived version to open old files. - - - -

Join our Reddit community and - Discord server - to ask questions, share maps, discuss the Generator, report bugs and propose new features.

- -

Thanks for all supporters on Patreon!

`; - - $("#alert").dialog( - {resizable: false, title: "Fantasy Map Generator update", width: 310, - buttons: { - OK: function() { - localStorage.clear(); - localStorage.setItem("version", version); - $(this).dialog("close"); - } - }, - position: {my: "center", at: "center", of: "svg"} - }); + // check if URL is valid + if (maplink) { + const pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; + const valid = pattern.test(maplink); + if (valid) {loadMapFromURL(maplink, 1); return;} else + showUploadErrorMessage("Map link is a valid URL", maplink); } + generateRandomMapOnLoad(); +}() + +function loadMapFromURL(maplink, random) { + const URL = decodeURIComponent(maplink); + + fetch(URL, {method: 'GET', mode: 'cors'}) + .then(response => { + if(response.ok) return response.blob(); + throw new Error("Cannot load map from URL"); + }).then(blob => uploadFile(blob)) + .catch(error => { + showUploadErrorMessage(error.message, URL, random); + if (random) generateRandomMapOnLoad(); + }); +} + +function showUploadErrorMessage(error, URL, random) { + console.log(error); + alertMessage.innerHTML = ` + Cannot load map from the link provided. + ${random?`A new random map is generated. `:''} + Please ensure the linked file is reachable`; + $("#alert").dialog({title: "Loading error", width: 320, buttons: {OK: function() {$(this).dialog("close");}}}); +} + +function generateRandomMapOnLoad() { + applyDefaultStyle(); // apply style + generate(); // generate map + focusOn(); // based on searchParams focus on point, cell or burg from MFCG + applyPreset(); // apply saved layers preset + setTimeout(showWelcomeMessage, 7000); // show welcome message if required } function applyDefaultNamesData() { @@ -431,11 +421,10 @@ function findBurgForMFCG(params) { const label = burgLabels.select("[data-id='" + b + "']"); if (label.size()) { - tip("Here stands the glorious city of " + burgs[b].name, true, "error"); + tip("Here stands the glorious city of " + burgs[b].name, true, "success", 10000); label.classed("drag", true).on("mouseover", function() { d3.select(this).classed("drag", false); label.on("mouseover", null); - tip("", true); }); } @@ -443,6 +432,55 @@ function findBurgForMFCG(params) { invokeActiveZooming(); } +function showWelcomeMessage() { + // Changelog dialog window + if (localStorage.getItem("version") != version) { + const link = 'https://www.reddit.com/r/FantasyMapGenerator/comments/cxu1c5/update_new_version_is_published_v_10'; // announcement on Reddit + alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version ${version}. + + This version is compatible with versions 0.8b and 0.9b, but not with older .map files. + Please use an archived version to open old files. + + + +

Join our Reddit community and + Discord server + to ask questions, share maps, discuss the Generator, report bugs and propose new features.

+ +

Thanks for all supporters on Patreon!

`; + + $("#alert").dialog( + {resizable: false, title: "Fantasy Map Generator update", width: 310, + buttons: { + OK: function() { + localStorage.clear(); + localStorage.setItem("version", version); + $(this).dialog("close"); + } + }, + position: {my: "center", at: "center", of: "svg"} + }); + } +} + function zoomed() { const transform = d3.event.transform; const scaleDiff = scale - transform.k; diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js index f0478656..828b6354 100644 --- a/modules/burgs-and-states.js +++ b/modules/burgs-and-states.js @@ -265,6 +265,8 @@ const type = states[s].type; cells.c[n].forEach(function(e) { + if (cells.state[e] && e === states[cells.state[e]].center) return; // do not overwrite capital cells + const cultureCost = states[s].culture === cells.culture[e] ? -9 : 700; const biomeCost = getBiomeCost(cells.road[e], b, cells.biome[e], type); const heightCost = getHeightCost(pack.features[cells.f[e]], cells.h[e], type); @@ -278,7 +280,6 @@ if (cells.h[e] >= 20) cells.state[e] = s; // assign state to cell cost[e] = totalCost; queue.queue({e, p:totalCost, s, b}); - //const points = [cells.p[n][0], cells.p[n][1], (cells.p[n][0]+cells.p[e][0])/2, (cells.p[n][1]+cells.p[e][1])/2, cells.p[e][0], cells.p[e][1]]; //debug.append("text").attr("x", (cells.p[n][0]+cells.p[e][0])/2 - 1).attr("y", (cells.p[n][1]+cells.p[e][1])/2 - 1).text(rn(totalCost-p)).attr("font-size", .8); //debug.append("polyline").attr("points", points).attr("marker-mid", "url(#arrow)").attr("opacity", .6); diff --git a/modules/save-and-load.js b/modules/save-and-load.js index ff9d883d..6eca5740 100644 --- a/modules/save-and-load.js +++ b/modules/save-and-load.js @@ -210,6 +210,7 @@ function saveMap() { function uploadFile(file, callback) { console.time("loadMap"); + closeDialogs(); const fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent) { const dataLoaded = fileLoadedEvent.target.result; @@ -423,7 +424,7 @@ function parseLoadedData(data) { getCurrentPreset(); }() - void function restoreRulersEvents() { + void function restoreEvents() { ruler.selectAll("g").call(d3.drag().on("start", dragRuler)); ruler.selectAll("text").on("click", removeParent); ruler.selectAll("g.ruler circle").call(d3.drag().on("drag", dragRulerEdge)); @@ -431,6 +432,9 @@ function parseLoadedData(data) { ruler.selectAll("g.ruler rect").call(d3.drag().on("start", rulerCenterDrag)); ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd)); ruler.selectAll("g.opisometer circle").call(d3.drag().on("start", dragOpisometerEnd)); + + scaleBar.on("mousemove", () => tip("Click to open Units Editor")); + legend.on("mousemove", () => tip("Drag to change the position. Click to hide the legend")).on("click", () => clearLegend()); }() void function resolveVersionConflicts() { @@ -518,6 +522,7 @@ function parseLoadedData(data) { changeMapSize(); restoreDefaultEvents(); invokeActiveZooming(); - tip("Map is loaded"); + tip("Map is successfully loaded", true, "success", 7000); console.timeEnd("loadMap"); + showStatistics(); } diff --git a/modules/ui/burg-editor.js b/modules/ui/burg-editor.js index 7eadf7bc..0511dd14 100644 --- a/modules/ui/burg-editor.js +++ b/modules/ui/burg-editor.js @@ -94,7 +94,7 @@ function editBurg() { } function createNewGroup() { - if (!this.value) {tip("Please provide a valid group name"); return;} + if (!this.value) {tip("Please provide a valid group name", false, "error"); return;} let group = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, ""); if (Number.isFinite(+group.charAt(0))) group = "g" + group; diff --git a/modules/ui/burgs-editor.js b/modules/ui/burgs-editor.js index ffb45cb7..74e36189 100644 --- a/modules/ui/burgs-editor.js +++ b/modules/ui/burgs-editor.js @@ -186,7 +186,7 @@ function editBurgs() { if (!pack.burgs[burg].port) { const haven = pack.cells.haven[pack.burgs[burg].cell]; const port = haven ? pack.cells.f[haven] : -1; - if (!haven) tip("Port haven is not found, system won't be able to make a searoute", false, "warning"); + if (!haven) tip("Port haven is not found, system won't be able to make a searoute", false, "warn"); pack.burgs[burg].port = port; const g = pack.burgs[burg].capital ? "cities" : "towns"; diff --git a/modules/ui/general.js b/modules/ui/general.js index 77ce6fe4..9d6c21d6 100644 --- a/modules/ui/general.js +++ b/modules/ui/general.js @@ -18,16 +18,18 @@ const tooltip = document.getElementById("tooltip"); document.getElementById("dialogs").addEventListener("mousemove", showDataTip); document.getElementById("optionsContainer").addEventListener("mousemove", showDataTip); -function tip(tip = "Tip is undefined", main = false, error = false) { - const reg = "linear-gradient(0.1turn, #ffffff00, #5e5c5c66, #ffffff00)"; - const red = "linear-gradient(0.1turn, #ffffff00, #e3141499, #ffffff00)"; +function tip(tip = "Tip is undefined", main, error, time) { tooltip.innerHTML = tip; - tooltip.style.background = error ? red : reg; - if (main) tooltip.dataset.main = tip; + tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #5e5c5c80, #ffffff00)"; + if (error === "error") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #e11d1dcc, #ffffff00)"; else + if (error === "warn") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #be5d08cc, #ffffff00)"; else + if (error === "success") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #127912cc, #ffffff00)"; + + if (main) tooltip.dataset.main = tip; // set main tip + if (time) setTimeout(tooltip.dataset.main = "", time); // clear main in some time } function showMainTip() { - tooltip.style.background = "linear-gradient(0.1turn, #aaffff00, #3a26264d, #ffffff00)"; tooltip.innerHTML = tooltip.dataset.main; } @@ -236,7 +238,8 @@ document.addEventListener("keydown", function(event) { 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 === 76) mapToLoad.click(); // Ctrl + "L" to load MAP + 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 (key === 46) removeElementOnKey(); // "Delete" to remove the selected element else if (shift && key === 192) console.log(pack.cells); // Shift + "`" to log cells data diff --git a/modules/ui/options.js b/modules/ui/options.js index 2d6706b2..768f20c9 100644 --- a/modules/ui/options.js +++ b/modules/ui/options.js @@ -677,6 +677,7 @@ optionsContent.addEventListener("input", function(event) { else if (id === "provincesInput") provincesOutput.value = value; else if (id === "provincesOutput") provincesOutput.value = value; else if (id === "provincesOutput") powerOutput.value = value; + else if (id === "powerInput") powerOutput.value = value; else if (id === "powerOutput") powerInput.value = value; else if (id === "neutralInput") neutralOutput.value = value; else if (id === "neutralOutput") neutralInput.value = value; @@ -991,12 +992,14 @@ document.getElementById("sticked").addEventListener("click", function(event) { const id = event.target.id; if (id === "newMapButton") regeneratePrompt(); else if (id === "saveButton") toggleSavePane(); - else if (id === "loadMap") mapToLoad.click(); + else if (id === "loadButton") toggleLoadPane(); else if (id === "zoomReset") resetZoom(1000); else if (id === "saveMap") saveMap(); else if (id === "saveSVG") saveAsImage("svg"); else if (id === "savePNG") saveAsImage("png"); if (id === "saveMap" || id === "saveSVG" || id === "savePNG") toggleSavePane(); + if (id === "loadURL") {loadURL(); toggleLoadPane()} + if (id === "loadMap") {mapToLoad.click(); toggleLoadPane()} }); function regeneratePrompt() { @@ -1033,12 +1036,32 @@ function toggleSavePane() { } }); } +} +function toggleLoadPane() { + if (loadDropdown.style.display === "block") {loadDropdown.style.display = "none"; return;} + loadDropdown.style.display = "block"; +} + +function loadURL() { + const pattern = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; + const inner = `Provide URL to a .map file: `; + alertMessage.innerHTML = inner; + $("#alert").dialog({resizable: false, title: "Load map from URL", width: 280, + buttons: { + Load: function() { + const value = mapURL.value; + if (!pattern.test(value)) {tip("Please provide a valid URL", false, "error"); return;} + loadMapFromURL(value); + $(this).dialog("close"); + }, + Cancel: function() {$(this).dialog("close");} + } + }); } // load map document.getElementById("mapToLoad").addEventListener("change", function() { - closeDialogs(); const fileToLoad = this.files[0]; this.value = ""; uploadFile(fileToLoad); From baf23bee37b9e1ca7f6c31cff19910db5eaa3ffb Mon Sep 17 00:00:00 2001 From: Azgaar Date: Wed, 4 Sep 2019 22:28:51 +0300 Subject: [PATCH 2/3] 1.0.08 --- index.html | 21 +++++-- main.js | 8 ++- modules/save-and-load.js | 104 ++++++++++++++++++---------------- modules/ui/burgs-editor.js | 2 +- modules/ui/cultures-editor.js | 2 +- modules/ui/options.js | 48 ++++++++++++++-- 6 files changed, 122 insertions(+), 63 deletions(-) diff --git a/index.html b/index.html index e5313fb5..20e908b8 100644 --- a/index.html +++ b/index.html @@ -1801,7 +1801,13 @@

Join our Discord server and Reddit community to ask questions, get help and share created maps. You may support the project on Patreon.

The project is under active development. For older versions see the changelog. To track the development progress see the devboard. Please report bugs here. You can also contact me directly via email.

A special thanks to all supporters!

-

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, Xariun, Gun Metal Games, Scott Marner, Spencer Sherman, Valerii Matskevych, Alloyed Clavicle, Stewart Walsh, Ruthlyn Mollett (Javan), Benjamin Mair-Pratt, Diagonath, Alexander Thomas, Ashley Wilson-Savoury, William Henry, Preston Brooks, JOSHUA QUALTIERI and many others!

+

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, Xariun, + Gun Metal Games, Scott Marner, Spencer Sherman, Valerii Matskevych, Alloyed Clavicle, Stewart Walsh, Ruthlyn Mollett (Javan), + Benjamin Mair-Pratt, Diagonath, Alexander Thomas, Ashley Wilson-Savoury, William Henry, Preston Brooks, JOSHUA QUALTIERI, + Hilton Williams, Katharina Haase, Hisham Bedri, Ian arless, Karnat, Bird, Kevin and many others!