v. 0.58.14b

This commit is contained in:
Azgaar 2018-08-11 01:34:42 +03:00
parent 42dcae94bb
commit bb37137f21
3 changed files with 189 additions and 103 deletions

View file

@ -524,12 +524,13 @@ p {
display: none; display: none;
text-align: center; text-align: center;
top: calc(98vh - (10px + 0.5vw)); top: calc(98vh - (10px + 0.5vw));
width: 100%; width: 90%;
cursor: default; left: 5%;
text-shadow: 1px 1px 2px #1d0e0f; cursor: default;
color: #ffffff; text-shadow: 1px 1px 3px #0e0e0e;
font-size: calc(10px + 0.5vw); color: #ffffff;
pointer-events: none; font-size: calc(10px + 0.5vw);
pointer-events: none;
} }
#optionsContent table td:nth-of-type(1) { #optionsContent table td:nth-of-type(1) {

View file

@ -164,8 +164,8 @@
<canvas id="canvas" style="opacity: 0"></canvas> <canvas id="canvas" style="opacity: 0"></canvas>
<div id="optionsContainer" class="hidden"> <div id="optionsContainer" class="hidden">
<div id="collapsible"> <div id="collapsible">
<button id="optionsTrigger" onmouseover="tip('Click to toggle options')" class="options icon-right-open glow"></button> <button id="optionsTrigger" onmouseover="tip('Click to toggle options. Hotkey: O')" class="options icon-right-open glow"></button>
<button id="regenerate" onmouseover="tip('Click to generate a new map')" class="options">New Map!</button> <button id="regenerate" onmouseover="tip('Click to generate a new map. Hotkey: F6')" class="options">New Map!</button>
</div> </div>
<div id="options"> <div id="options">
<div class="drag-trigger" onmouseover="tip('Drag to move options pane')"></div> <div class="drag-trigger" onmouseover="tip('Drag to move options pane')"></div>
@ -560,15 +560,15 @@
</ul> </ul>
</div> </div>
<div id="sticked"> <div id="sticked">
<button id="randomMap" onmouseover="tip('Generate a new random map based on options set (F2). May take about 1 minute')" class="options">New Map</button> <button id="randomMap" onmouseover="tip('Generate a new map based on options. May take about 1 minute. Hotkey: F6')" class="options">New Map</button>
<button id="saveButton" onmouseover="tip('Select file format to save map')" class="options">Save as</button> <button id="saveButton" onmouseover="tip('Select file format to save map')" class="options">Save as</button>
<div id="saveDropdown"> <div id="saveDropdown">
<div id="saveMap" onmouseover="tip('Save as fully functional map in .map format')">.map</div> <div id="saveMap" onmouseover="tip('Save as fully functional map in .map format. Hotkey: M')">.map</div>
<div id="saveSVG" onmouseover="tip('Download the map as .svg image (open derectly in browser or in vector editor like Inkscape)')">.svg</div> <div id="saveSVG" onmouseover="tip('Download the map as .svg image (open in browser or in Inkscape. Hotkey: S)')">.svg</div>
<div id="savePNG" onmouseover="tip('Download the visible part of the map as 4K .png image. Please ensure popups are not blocked!')">.png</div> <div id="savePNG" onmouseover="tip('Download the visible part of the map as 4K .png image. Please ensure popups are not blocked! Hotkey: P')">.png</div>
</div> </div>
<button id="loadMap" onmouseover="tip('Load fully functional map in a .map format')" class="options">Load</button> <button id="loadMap" onmouseover="tip('Load fully functional map in a .map format. Hotkey: L')" class="options">Load</button>
<button id="zoomReset" onmouseover="tip('Reset map zoom to 1')" class="options">Reset Zoom</button> <button id="zoomReset" onmouseover="tip('Reset map zoom. Hotkey: 0')" class="options">Reset Zoom</button>
</div> </div>
</div> </div>
</div> </div>
@ -752,6 +752,7 @@
<output id="burgPopulationFriendly" onmouseover="tip('Burg population (in people)')">1000</output> <output id="burgPopulationFriendly" onmouseover="tip('Burg population (in people)')">1000</output>
</div> </div>
<button id="burgRelocate" onmouseover="tip('Move burg to a different cell')" class="icon-target"></button>
<button id="burgAddfromEditor" onmouseover="tip('Add new Burg')" class="icon-plus"></button> <button id="burgAddfromEditor" onmouseover="tip('Add new Burg')" class="icon-plus"></button>
<button id="burgRemove" onmouseover="tip('Remove the Burg')" class="icon-trash"></button> <button id="burgRemove" onmouseover="tip('Remove the Burg')" class="icon-trash"></button>
</div> </div>

262
script.js
View file

@ -37,7 +37,7 @@ function fantasyMap() {
labels = viewbox.append("g").attr("id", "labels"), labels = viewbox.append("g").attr("id", "labels"),
burgLabels = labels.append("g").attr("id", "burgLabels"), burgLabels = labels.append("g").attr("id", "burgLabels"),
icons = viewbox.append("g").attr("id", "icons"), icons = viewbox.append("g").attr("id", "icons"),
burgIcons = icons.append("g").attr("id", "burgIcons") burgIcons = icons.append("g").attr("id", "burgIcons"),
ruler = viewbox.append("g").attr("id", "ruler"), ruler = viewbox.append("g").attr("id", "ruler"),
debug = viewbox.append("g").attr("id", "debug"); debug = viewbox.append("g").attr("id", "debug");
@ -1581,6 +1581,10 @@ function fantasyMap() {
const x = d3.event.x, y = d3.event.y; const x = d3.event.x, y = d3.event.y;
const transform = `translate(${(dx+x)},${(dy+y)})`; const transform = `translate(${(dx+x)},${(dy+y)})`;
el.attr("transform", transform); el.attr("transform", transform);
const pp = this.parentNode.parentNode.id;
if (pp === "burgIcons" || pp === "burgLabels") {
tip('Use dragging for fine-tuning only, to move burg to a different cell use "Relocate" button');
}
}); });
d3.event.on("end", function() { d3.event.on("end", function() {
@ -2433,7 +2437,7 @@ function fantasyMap() {
function unselect() { function unselect() {
if (elSelected) { if (elSelected) {
elSelected.call(d3.drag().on("drag", null)).classed("draggable", false); elSelected.call(d3.drag().on("drag", null)).attr("class", null);
debug.select(".controlPoints").remove(); debug.select(".controlPoints").remove();
viewbox.style("cursor", "default"); viewbox.style("cursor", "default");
elSelected = null; elSelected = null;
@ -2917,12 +2921,8 @@ function fantasyMap() {
} }
function editBurg() { function editBurg() {
if (customization) {return;} if (customization) return;
if (elSelected) { unselect();
const self = d3.select(this).attr("data-id") === elSelected.attr("data-id");
if (self) {return;}
}
closeDialogs("#burgEditor, .stable"); closeDialogs("#burgEditor, .stable");
elSelected = d3.select(this); elSelected = d3.select(this);
const id = +elSelected.attr("data-id"); const id = +elSelected.attr("data-id");
@ -2987,7 +2987,7 @@ function fantasyMap() {
}); });
} }
$("#burgEditor > button").not("#burgAddfromEditor").not("#burgRemove").click(function() { $("#burgEditor > button").not("#burgAddfromEditor").not("#burgRelocate").not("#burgRemove").click(function() {
if ($(this).next().is(":visible")) { if ($(this).next().is(":visible")) {
$("#burgEditor > button").show(); $("#burgEditor > button").show();
$(this).next("div").hide(); $(this).next("div").hide();
@ -3260,6 +3260,75 @@ function fantasyMap() {
manors[id].population = +this.value; manors[id].population = +this.value;
}); });
$("#burgRelocate").click(function() {
if ($(this).hasClass('pressed')) {
$(".pressed").removeClass('pressed');
restoreDefaultEvents();
tip("", true);
} else {
$(".pressed").removeClass('pressed');
const id = elSelected.attr("data-id");
$(this).addClass('pressed').attr("data-id", id);
viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick);
tip("Click on map to relocate burg. Hold Shift for continuous move", true);
}
});
// move burg to a different cell
function relocateBurgOnClick() {
const point = d3.mouse(this);
const index = getIndex(point);
const i = +$("#burgRelocate").attr("data-id");
if (isNaN(i) || !manors[i]) return;
if (cells[index].height < 0.2) {
tip("Cannot place burg in the water! Select a land cell", null, "error");
return;
}
if (cells[index].manor !== undefined && cells[index].manor !== i) {
tip("There is already a burg in this cell. Please select a free cell", null, "error");
$('#grid').fadeIn();
d3.select("#toggleGrid").classed("buttonoff", false);
return;
}
let region = cells[index].region;
const oldRegion = manors[i].region;
// relocating capital to other country you "conqure" thid cell
if (states[oldRegion] && states[oldRegion].capital === i) {
if (region !== oldRegion) {
tip("Capital cannot be moved to another country!", null, "error");
return;
}
}
if (d3.event.shiftKey === false) {
$("#burgRelocate").removeClass("pressed");
restoreDefaultEvents();
tip("", true);
if (region !== oldRegion) {
recalculateStateData(oldRegion);
recalculateStateData(region);
updateCountryEditors();
}
}
const x = rn(point[0], 2), y = rn(point[1], 2);
burgIcons.select("circle[data-id='"+i+"']").attr("cx", x).attr("cy", y);
burgLabels.select("text[data-id='"+i+"']").attr("x", x).attr("y", y);
const anchor = icons.select("use[data-id='"+i+"']");
if (anchor.size()) {
const size = anchor.attr("width");
const xa = rn(x - size * 0.47, 2);
const ya = rn(y - size * 0.47, 2);
icons.select("use[data-id='"+i+"']").attr("x", xa).attr("y", ya);
}
cells[index].manor = i;
cells[manors[i].cell].manor = undefined;
manors[i].x = x, manors[i].y = y, manors[i].region = region, manors[i].cell = index;
}
$("#burgAddfromEditor").click(function() { $("#burgAddfromEditor").click(function() {
clickToAdd(); // to load on click event function clickToAdd(); // to load on click event function
$("#addBurg").click(); $("#addBurg").click();
@ -3393,7 +3462,8 @@ function fantasyMap() {
if (m.i === m.region && !cell.port) {score *= 2;} // land-capitals if (m.i === m.region && !cell.port) {score *= 2;} // land-capitals
if (m.i === m.region && cell.port) {score *= 3;} // port-capitals if (m.i === m.region && cell.port) {score *= 3;} // port-capitals
if (m.region === "neutral") score *= urbanFactor; if (m.region === "neutral") score *= urbanFactor;
m.population = rn(score, 1); const rnd = 0.6 + Math.random() * 0.8; // random factor
m.population = rn(score * rnd, 1);
}); });
// calculate rural population for each cell based on area + elevation (elevation to be changed to biome) // calculate rural population for each cell based on area + elevation (elevation to be changed to biome)
@ -4296,7 +4366,10 @@ function fantasyMap() {
if (Math.random() < 0.85 || culture === null) { if (Math.random() < 0.85 || culture === null) {
// culture is random if capital is not yet defined // culture is random if capital is not yet defined
if (culture === null) culture = rand(cultures.length - 1); if (culture === null) culture = rand(cultures.length - 1);
while (name.length > 8) {name = generateName(culture);} // try to avoid too long words as a basename
for (let i=0; i < 20 && name.length > 7; i++) {
name = generateName(culture);
}
} else { } else {
name = manors[state].name; name = manors[state].name;
} }
@ -4309,10 +4382,30 @@ function fantasyMap() {
// remove -sk and -ev/-ov for Ruthenian // remove -sk and -ev/-ov for Ruthenian
name = name.slice(0,-2); name = name.slice(0,-2);
addSuffix = true; addSuffix = true;
} else if (name.length > 5 && base === 1 && name.slice(-3) === "ton") {
// remove -ton ending for English
name = name.slice(0,-3);
addSuffix = true;
} else if (name.length > 6 && name.slice(-4) === "berg") { } else if (name.length > 6 && name.slice(-4) === "berg") {
// remove -berg ending for any // remove -berg ending for any
name = name.slice(0,-4); name = name.slice(0,-4);
addSuffix = true; addSuffix = true;
} else if (base === 12) {
// Japanese ends on vowels
if (vowels.includes(name.slice(-1))) return name;
return name + "u";
} else if (base === 10) {
// Korean has "guk" suffix
if (name.slice(-3) === "guk") return name;
if (name.slice(-1) === "g") name = name.slice(0,-1);
if (Math.random() < 0.2 && name.length < 7) name = name + "guk"; // 20% for "guk"
return name;
} else if (base === 11) {
// Chinese has "guo" suffix
if (name.slice(-3) === "guo") return name;
if (name.slice(-1) === "g") name = name.slice(0,-1);
if (Math.random() < 0.3 && name.length < 7) name = name + " Guo"; // 30% for "guo"
return name;
} }
// define if suffix should be used // define if suffix should be used
@ -4332,7 +4425,6 @@ function fantasyMap() {
} }
if (addSuffix === false) return name; if (addSuffix === false) return name;
let suffix = "ia"; // common latin suffix let suffix = "ia"; // common latin suffix
const rnd = Math.random(); const rnd = Math.random();
if (rnd < 0.05 && base === 3) suffix = "terra"; // 5% "terra" for Italian if (rnd < 0.05 && base === 3) suffix = "terra"; // 5% "terra" for Italian
@ -4341,6 +4433,8 @@ function fantasyMap() {
else if (rnd < 0.5 && base == 0) suffix = "land"; // 50% "land" for German else if (rnd < 0.5 && base == 0) suffix = "land"; // 50% "land" for German
else if (rnd < 0.4 && base == 1) suffix = "land"; // 40% "land" for English else if (rnd < 0.4 && base == 1) suffix = "land"; // 40% "land" for English
else if (rnd < 0.3 && base == 6) suffix = "land"; // 30% "land" for Nordic else if (rnd < 0.3 && base == 6) suffix = "land"; // 30% "land" for Nordic
else if (rnd < 0.1 && base == 7) suffix = "eia"; // 10% "eia" for Greek ("ia" is also Greek)
else if (rnd < 0.4 && base == 9) suffix = "maa"; // 40% "maa" for Finnic
if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it
return name + suffix; return name + suffix;
} }
@ -4756,7 +4850,7 @@ function fantasyMap() {
// Add support "click to add" button events // Add support "click to add" button events
$("#customizeTab").click(function() {clickToAdd()}); $("#customizeTab").click(function() {clickToAdd()});
function clickToAdd() { function clickToAdd() {
if (modules.clickToAdd) {return;} if (modules.clickToAdd) return;
modules.clickToAdd = true; modules.clickToAdd = true;
// add label on click // add label on click
@ -4802,11 +4896,11 @@ function fantasyMap() {
if ($(this).hasClass('pressed')) { if ($(this).hasClass('pressed')) {
$(".pressed").removeClass('pressed'); $(".pressed").removeClass('pressed');
restoreDefaultEvents(); restoreDefaultEvents();
tip("", true);
} else { } else {
$(".pressed").removeClass('pressed'); $(".pressed").removeClass('pressed');
$(this).attr("data-state", -1).addClass('pressed'); $(this).attr("data-state", -1).addClass('pressed');
$("#burgAdd").addClass('pressed'); $("#burgAdd, #burgAddfromEditor").addClass('pressed');
closeDialogs(".stable");
viewbox.style("cursor", "crosshair").on("click", addBurgOnClick); viewbox.style("cursor", "crosshair").on("click", addBurgOnClick);
tip("Click on map to place burg icon with a label. Hold Shift to place several", true); tip("Click on map to place burg icon with a label. Hold Shift to place several", true);
} }
@ -4823,11 +4917,11 @@ function fantasyMap() {
const name = generateName(culture); const name = generateName(culture);
if (cells[index].height < 0.2) { if (cells[index].height < 0.2) {
tip("Cannot place burg in the water! Select a land cell"); tip("Cannot place burg in the water! Select a land cell", null, "error");
return; return;
} }
if (cells[index].manor !== undefined) { if (cells[index].manor !== undefined) {
tip("There is already a burg in this cell. You have to select a free cell"); tip("There is already a burg in this cell. Please select a free cell", null, "error");
$('#grid').fadeIn(); $('#grid').fadeIn();
d3.select("#toggleGrid").classed("buttonoff", false); d3.select("#toggleGrid").classed("buttonoff", false);
return; return;
@ -4839,7 +4933,7 @@ function fantasyMap() {
invokeActiveZooming(); invokeActiveZooming();
if (d3.event.shiftKey === false) { if (d3.event.shiftKey === false) {
$("#addBurg, #burgAdd").removeClass("pressed"); $("#addBurg, #burgAdd, #burgAddfromEditor").removeClass("pressed");
restoreDefaultEvents(); restoreDefaultEvents();
} }
@ -5011,7 +5105,7 @@ function fantasyMap() {
// re-calculate data for a particular state // re-calculate data for a particular state
function recalculateStateData(state) { function recalculateStateData(state) {
const s = states[state]; const s = states[state] || states[states.length - 1];
if (s.capital === "neutral") state = "neutral"; if (s.capital === "neutral") state = "neutral";
const burgs = $.grep(manors, function(e) {return e.region === state;}); const burgs = $.grep(manors, function(e) {return e.region === state;});
s.burgs = burgs.length; s.burgs = burgs.length;
@ -5717,7 +5811,7 @@ function fantasyMap() {
const extent = (100 / scaleTo) + "%"; const extent = (100 / scaleTo) + "%";
const xShift = (nWidth * scaleTo - svgWidth) / 2 / scaleTo; const xShift = (nWidth * scaleTo - svgWidth) / 2 / scaleTo;
const yShift = (nHeight * scaleTo - svgHeight) / 2 / scaleTo; const yShift = (nHeight * scaleTo - svgHeight) / 2 / scaleTo;
ocean.selectAll("rect").attr("x", xShift).attr("y", yShift).attr("width", extent).attr("height", extent); svg.select("#ocean").selectAll("rect").attr("x", xShift).attr("y", yShift).attr("width", extent).attr("height", extent);
zoom.translateExtent([[0, 0], [nWidth, nHeight]]).scaleExtent([scaleTo, 20]).scaleTo(svg, scaleTo); zoom.translateExtent([[0, 0], [nWidth, nHeight]]).scaleExtent([scaleTo, 20]).scaleTo(svg, scaleTo);
$(this).dialog("close"); $(this).dialog("close");
}, },
@ -5767,8 +5861,8 @@ function fantasyMap() {
labels.append("g").attr("id", "burgLabels"); labels.append("g").attr("id", "burgLabels");
$("#labels #capitals, #labels #towns").detach().appendTo($("#burgLabels")); $("#labels #capitals, #labels #towns").detach().appendTo($("#burgLabels"));
labels.select("#burgLabels").selectAll("text").each(function() { labels.select("#burgLabels").selectAll("text").each(function() {
let id = this.getAttribute("id"); const id = this.getAttribute("id");
if (!id) return; if (id === null || id === undefined) return;
this.removeAttribute("id"); this.removeAttribute("id");
this.setAttribute("data-id", +id.replace("manorLabel", "")); this.setAttribute("data-id", +id.replace("manorLabel", ""));
}); });
@ -5781,9 +5875,9 @@ function fantasyMap() {
icons.select("#burgIcons").select("#towns").attr("size", .5).attr("fill-opacity", .7).attr("stroke-opacity", 1); icons.select("#burgIcons").select("#towns").attr("size", .5).attr("fill-opacity", .7).attr("stroke-opacity", 1);
} }
icons.selectAll("g").each(function(d) { icons.selectAll("g").each(function() {
const size = this.getAttribute("font-size"); const size = this.getAttribute("font-size");
if (size === undefined) return; if (size === null || size === undefined) return;
this.removeAttribute("font-size"); this.removeAttribute("font-size");
this.setAttribute("size", size); this.setAttribute("size", size);
}); });
@ -5791,13 +5885,14 @@ function fantasyMap() {
icons.select("#burgIcons").selectAll("circle").each(function() { icons.select("#burgIcons").selectAll("circle").each(function() {
this.setAttribute("r", this.parentNode.getAttribute("size")); this.setAttribute("r", this.parentNode.getAttribute("size"));
const id = this.getAttribute("id"); const id = this.getAttribute("id");
if (!id) return; if (id === null || id === undefined) return;
this.removeAttribute("id"); this.removeAttribute("id");
this.setAttribute("data-id", +id.replace("manorIcon", "")); this.setAttribute("data-id", +id.replace("manorIcon", ""));
}); });
icons.selectAll("use").each(function() { icons.selectAll("use").each(function() {
const size = this.parentNode.getAttribute("size"); const size = this.parentNode.getAttribute("size");
if (size === null || size === undefined) return;
this.setAttribute("width", size); this.setAttribute("width", size);
this.setAttribute("height", size); this.setAttribute("height", size);
}); });
@ -5962,71 +6057,56 @@ function fantasyMap() {
} }
} }
// Hotkeys // Hotkeys, see github.com/Azgaar/Fantasy-Map-Generator/wiki/Hotkeys
d3.select("body").on("keydown", function() { d3.select("body").on("keydown", function() {
const active = document.activeElement.tagName; const active = document.activeElement.tagName;
if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return; if (active === "INPUT" || active === "SELECT" || active === "TEXTAREA") return;
switch(d3.event.keyCode) { const key = d3.event.keyCode;
case 27: // Escape to close all dialogs const ctrl = d3.event.ctrlKey;
closeDialogs(); const p = d3.mouse(this);
break; if (key === 117) $("#randomMap").click(); // "F6" for new map
case 79: // "O" to toggle options else if (key === 27) closeDialogs(); // Escape to close all dialogs
optionsTrigger.click(); else if (key === 79) optionsTrigger.click(); // "O" to toggle options
break; else if (key === 80) saveAsImage("png"); // "P" to save as PNG
case 113: // "F2" for new map else if (key === 83) saveAsImage("svg"); // "S" to save as SVG
$("#randomMap").click(); else if (key === 77) saveMap(); // "M" to save MAP file
break; else if (key === 76) mapToLoad.click(); // "L" to load MAP
case 32: // Space to log focused cell data else if (key === 32) console.table(cells[diagram.find(p[0], p[1]).index]); // Space to log focused cell data
var point = d3.mouse(this); else if (key === 192) console.log(cells); // "`" to log cells data
const index = diagram.find(point[0], point[1]).index; else if (key === 66) console.table(manors); // "B" to log burgs data
console.table(cells[index]); else if (key === 67) console.table(states); // "C" to log countries data
break; else if (key === 70) console.table(features); // "F" to log features data
case 67: // "C" to log cells data else if (key === 37) zoom.translateBy(svg, 10, 0); // Left to scroll map left
console.log(cells); else if (key === 39) zoom.translateBy(svg, -10, 0); // Right to scroll map right
break; else if (key === 38) zoom.translateBy(svg, 0, 10); // Up to scroll map up
case 66: // "B" to log burgs data else if (key === 40) zoom.translateBy(svg, 0, -10); // Up to scroll map up
console.table(manors); else if (key === 107) zoom.scaleBy(svg, 1.2); // Plus to zoom map up
break; else if (key === 109) zoom.scaleBy(svg, 0.8); // Minus to zoom map out
case 83: // "S" to log states data else if (key === 48 || key === 96) resetZoom(); // 0 to reset zoom
console.table(states); else if (key === 49 || key === 97) zoom.scaleTo(svg, 1); // 1 to zoom to 1
break; else if (key === 50 || key === 98) zoom.scaleTo(svg, 2); // 2 to zoom to 2
case 70: // "F" to log features data else if (key === 51 || key === 99) zoom.scaleTo(svg, 3); // 3 to zoom to 3
console.table(features); else if (key === 52 || key === 100) zoom.scaleTo(svg, 4); // 4 to zoom to 4
break; else if (key === 53 || key === 101) zoom.scaleTo(svg, 5); // 5 to zoom to 5
case 37: // Left to scroll map left else if (key === 54 || key === 102) zoom.scaleTo(svg, 6); // 6 to zoom to 6
zoom.translateBy(svg, 10, 0); else if (key === 55 || key === 103) zoom.scaleTo(svg, 7); // 7 to zoom to 7
break; else if (key === 56 || key === 104) zoom.scaleTo(svg, 8); // 8 to zoom to 8
case 39: // Right to scroll map right else if (key === 57 || key === 105) zoom.scaleTo(svg, 9); // 9 to zoom to 9
zoom.translateBy(svg, -10, 0); else if (key === 9) $("#updateFullscreen").click(); // Tab to fit map to fullscreen
break; else if (ctrl && key === 90) undo.click(); // Ctrl + "Z" to toggle undo
case 38: // Up to scroll map up else if (ctrl && key === 89) redo.click(); // Ctrl + "Y" to toggle undo
zoom.translateBy(svg, 0, 10);
break;
case 40: // Down to scroll map down
zoom.translateBy(svg, 0, -10);
break;
case 107: // Plus to zoom map up
zoom.scaleBy(svg, 1.2);
break;
case 109: // Minus to zoom map out
zoom.scaleBy(svg, 0.8);
break;
case 9: // Tab to toggle full-screen mode
$("#updateFullscreen").click();
break;
case 90: // Ctrl + "Z" to toggle undo
if (customization !== 1) return;
if (d3.event.ctrlKey === false) return;
undo.click();
break;
case 89: // Ctrl + "Y" to toggle undo
if (customization !== 1) return;
if (d3.event.ctrlKey === false) return;
redo.click();
break;
}
}); });
// Show help
function showHelp() {
$("#help").dialog({
title: "About Fantasy Map Generator",
minHeight: 30, width: "auto", maxWidth: 275, resizable: false,
position: {my: "center top+10", at: "bottom", of: this},
close: unselect
});
}
// Toggle Options pane // Toggle Options pane
$("#optionsTrigger").on("click", function() { $("#optionsTrigger").on("click", function() {
if (tooltip.getAttribute("data-main") === "Сlick the arrow button to open options") { if (tooltip.getAttribute("data-main") === "Сlick the arrow button to open options") {
@ -8557,7 +8637,8 @@ function fantasyMap() {
const width = Math.max(svgWidth, graphWidth); const width = Math.max(svgWidth, graphWidth);
const height = Math.max(svgHeight, graphHeight); const height = Math.max(svgHeight, graphHeight);
zoom.translateExtent([[0, 0], [width, height]]); zoom.translateExtent([[0, 0], [width, height]]);
ocean.selectAll("rect").attr("width", width).attr("height", height); svg.select("#ocean").selectAll("rect").attr("x", 0)
.attr("y", 0).attr("width", width).attr("height", height);
} }
// fit full-screen map if window is resized // fit full-screen map if window is resized
@ -8996,9 +9077,12 @@ function fantasyMap() {
} }
} }
function tip(tip, main) { function tip(tip, main, error) {
tooltip.innerHTML = tip; const tooltip = d3.select("#tooltip");
if (main) {tooltip.setAttribute("data-main", tip);} const reg = "linear-gradient(0.1turn, #ffffff00, #5e5c5c33, #ffffff00)";
const red = "linear-gradient(0.1turn, #ffffff00, #c71d1d4d, #ffffff00)";
tooltip.text(tip).style("background", error ? red : reg);
if (main) tooltip.attr("data-main", tip);
} }
$("#optionsContainer *").on("mouseout", function() { $("#optionsContainer *").on("mouseout", function() {