Halo width
@@ -2063,23 +2069,16 @@
-
Click to configure:
-
-
- Heightmap
-
+
Edit
+
Biomes
-
- States
+
+ Burgs
-
- Provinces
+
+ Cultures
Diplomacy
-
- Cultures
-
-
- Namesbase
-
- Zones
-
- Religions
-
Emblems
- Units
- Notes
-
-
-
Click to overview:
-
- Charts
+ Heightmap
-
- Burgs
-
-
- Routes
-
-
- Rivers
+
+ Markers
Military
-
- Markers
+
+ Namesbase
-
- Cells
+ Notes
+
+ Provinces
+
+ Religions
+
+
+ Rivers
+
+
+ Routes
+
+
+ States
+
+ Units
+ Zones
-
Click to regenerate:
-
+
Regenerate
+
+
+ Burgs
+
+ Cultures
+ Emblems
+ Ice
Labels
-
- Relief
+
+ Markers
- Routes
-
- Rivers
+
+ Military
Population
-
- States
-
- Burgs
+ Relief
- Emblems
Religions
- Cultures
-
- Military
+
+ Rivers
- Ice
-
- Markers
+ Routes
+
+ States
-
Click to add:
-
+
Add
+
Label
-
- River
-
- Route
Marker
+
+ River
+
+ <<<<<<< HEAD
+ Route
+ =======
+ Route
-
Click to create a new map:
-
+
+
+ Presets:
+ Whole world
+ Northern
+ Tropical
+ Southern
+
@@ -7894,18 +7941,19 @@
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -8136,7 +8184,7 @@
-
+
@@ -8158,15 +8206,15 @@
-
-
-
+
+
+
-
+
@@ -8204,10 +8252,10 @@
-
-
+
+
-
+
diff --git a/main.js b/main.js
index eb8b39d9..ef86ade5 100644
--- a/main.js
+++ b/main.js
@@ -53,7 +53,7 @@ let biomes = viewbox.append("g").attr("id", "biomes");
let cells = viewbox.append("g").attr("id", "cells");
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
let coordinates = viewbox.append("g").attr("id", "coordinates");
-let compass = viewbox.append("g").attr("id", "compass");
+let compass = viewbox.append("g").attr("id", "compass").style("display", "none");
let rivers = viewbox.append("g").attr("id", "rivers");
let terrain = viewbox.append("g").attr("id", "terrain");
let relig = viewbox.append("g").attr("id", "relig");
@@ -126,6 +126,9 @@ emblems.append("g").attr("id", "burgEmblems");
emblems.append("g").attr("id", "provinceEmblems");
emblems.append("g").attr("id", "stateEmblems");
+// compass
+compass.append("use").attr("xlink:href", "#defs-compass-rose");
+
// fogging
fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%");
fogging
@@ -195,10 +198,10 @@ let options = {
};
let mapCoordinates = {}; // map coordinates on globe
-let populationRate = +document.getElementById("populationRateInput").value;
-let distanceScale = +document.getElementById("distanceScaleInput").value;
-let urbanization = +document.getElementById("urbanizationInput").value;
-let urbanDensity = +document.getElementById("urbanDensityInput").value;
+let populationRate = +byId("populationRateInput").value;
+let distanceScale = +byId("distanceScaleInput").value;
+let urbanization = +byId("urbanizationInput").value;
+let urbanDensity = +byId("urbanDensityInput").value;
applyStoredOptions();
@@ -439,10 +442,10 @@ function handleZoom(isScaleChanged, isPositionChanged) {
// zoom image converter overlay
if (customization === 1) {
- const canvas = document.getElementById("canvas");
+ const canvas = byId("canvas");
if (!canvas || canvas.style.opacity === "0") return;
- const img = document.getElementById("imageToConvert");
+ const img = byId("imageToConvert");
if (!img) return;
const ctx = canvas.getContext("2d");
@@ -524,7 +527,7 @@ function invokeActiveZooming() {
+markers.attr("rescale") &&
pack.markers?.forEach(marker => {
const {i, x, y, size = 30, hidden} = marker;
- const el = !hidden && document.getElementById(`marker${i}`);
+ const el = !hidden && byId(`marker${i}`);
if (!el) return;
const zoomedSize = Math.max(rn(size / 5 + 24 / scale, 2), 1);
@@ -561,18 +564,18 @@ void (function addDragToUpload() {
document.addEventListener("dragover", function (e) {
e.stopPropagation();
e.preventDefault();
- document.getElementById("mapOverlay").style.display = null;
+ byId("mapOverlay").style.display = null;
});
document.addEventListener("dragleave", function (e) {
- document.getElementById("mapOverlay").style.display = "none";
+ byId("mapOverlay").style.display = "none";
});
document.addEventListener("drop", function (e) {
e.stopPropagation();
e.preventDefault();
- const overlay = document.getElementById("mapOverlay");
+ const overlay = byId("mapOverlay");
overlay.style.display = "none";
if (e.dataTransfer.items == null || e.dataTransfer.items.length !== 1) return; // no files or more than one
const file = e.dataTransfer.items[0].getAsFile();
@@ -780,7 +783,7 @@ function addLakesInDeepDepressions() {
TIME && console.time("addLakesInDeepDepressions");
const {cells, features} = grid;
const {c, h, b} = cells;
- const ELEVATION_LIMIT = +document.getElementById("lakeElevationLimitOutput").value;
+ const ELEVATION_LIMIT = +byId("lakeElevationLimitOutput").value;
if (ELEVATION_LIMIT === 80) return;
for (const i of cells.i) {
@@ -880,73 +883,77 @@ function openNearSeaLakes() {
// define map size and position based on template and random factor
function defineMapSize() {
- const [size, latitude] = getSizeAndLatitude();
+ const [size, latitude, longitude] = getSizeAndLatitude();
const randomize = new URL(window.location.href).searchParams.get("options") === "default"; // ignore stored options
- if (randomize || !locked("mapSize")) mapSizeOutput.value = mapSizeInput.value = rn(size);
- if (randomize || !locked("latitude")) latitudeOutput.value = latitudeInput.value = rn(latitude);
+ if (randomize || !locked("mapSize")) mapSizeOutput.value = mapSizeInput.value = size;
+ if (randomize || !locked("latitude")) latitudeOutput.value = latitudeInput.value = latitude;
+ if (randomize || !locked("longitude")) longitudeOutput.value = longitudeInput.value = longitude;
function getSizeAndLatitude() {
const template = byId("templateInput").value; // heightmap template
- if (template === "africa-centric") return [45, 53];
- if (template === "arabia") return [20, 35];
- if (template === "atlantics") return [42, 23];
- if (template === "britain") return [7, 20];
- if (template === "caribbean") return [15, 40];
- if (template === "east-asia") return [11, 28];
- if (template === "eurasia") return [38, 19];
- if (template === "europe") return [20, 16];
- if (template === "europe-accented") return [14, 22];
- if (template === "europe-and-central-asia") return [25, 10];
- if (template === "europe-central") return [11, 22];
- if (template === "europe-north") return [7, 18];
- if (template === "greenland") return [22, 7];
- if (template === "hellenica") return [8, 27];
- if (template === "iceland") return [2, 15];
- if (template === "indian-ocean") return [45, 55];
- if (template === "mediterranean-sea") return [10, 29];
- if (template === "middle-east") return [8, 31];
- if (template === "north-america") return [37, 17];
- if (template === "us-centric") return [66, 27];
- if (template === "us-mainland") return [16, 30];
- if (template === "world") return [78, 27];
- if (template === "world-from-pacific") return [75, 32];
+ if (template === "africa-centric") return [45, 53, 38];
+ if (template === "arabia") return [20, 35, 35];
+ if (template === "atlantics") return [42, 23, 65];
+ if (template === "britain") return [7, 20, 51.3];
+ if (template === "caribbean") return [15, 40, 74.8];
+ if (template === "east-asia") return [11, 28, 9.4];
+ if (template === "eurasia") return [38, 19, 27];
+ if (template === "europe") return [20, 16, 44.8];
+ if (template === "europe-accented") return [14, 22, 44.8];
+ if (template === "europe-and-central-asia") return [25, 10, 39.5];
+ if (template === "europe-central") return [11, 22, 46.4];
+ if (template === "europe-north") return [7, 18, 48.9];
+ if (template === "greenland") return [22, 7, 55.8];
+ if (template === "hellenica") return [8, 27, 43.5];
+ if (template === "iceland") return [2, 15, 55.3];
+ if (template === "indian-ocean") return [45, 55, 14];
+ if (template === "mediterranean-sea") return [10, 29, 45.8];
+ if (template === "middle-east") return [8, 31, 34.4];
+ if (template === "north-america") return [37, 17, 87];
+ if (template === "us-centric") return [66, 27, 100];
+ if (template === "us-mainland") return [16, 30, 77.5];
+ if (template === "world") return [78, 27, 40];
+ if (template === "world-from-pacific") return [75, 32, 30]; // longitude doesn't fit
const part = grid.features.some(f => f.land && f.border); // if land goes over map borders
const max = part ? 80 : 100; // max size
const lat = () => gauss(P(0.5) ? 40 : 60, 20, 25, 75); // latitude shift
if (!part) {
- if (template === "Pangea") return [100, 50];
- if (template === "Shattered" && P(0.7)) return [100, 50];
- if (template === "Continents" && P(0.5)) return [100, 50];
- if (template === "Archipelago" && P(0.35)) return [100, 50];
- if (template === "High Island" && P(0.25)) return [100, 50];
- if (template === "Low Island" && P(0.1)) return [100, 50];
+ if (template === "pangea") return [100, 50, 50];
+ if (template === "shattered" && P(0.7)) return [100, 50, 50];
+ if (template === "continents" && P(0.5)) return [100, 50, 50];
+ if (template === "archipelago" && P(0.35)) return [100, 50, 50];
+ if (template === "highIsland" && P(0.25)) return [100, 50, 50];
+ if (template === "lowIsland" && P(0.1)) return [100, 50, 50];
}
- if (template === "Pangea") return [gauss(70, 20, 30, max), lat()];
- if (template === "Volcano") return [gauss(20, 20, 10, max), lat()];
- if (template === "Mediterranean") return [gauss(25, 30, 15, 80), lat()];
- if (template === "Peninsula") return [gauss(15, 15, 5, 80), lat()];
- if (template === "Isthmus") return [gauss(15, 20, 3, 80), lat()];
- if (template === "Atoll") return [gauss(5, 10, 2, max), lat()];
+ if (template === "pangea") return [gauss(70, 20, 30, max), lat(), 50];
+ if (template === "volcano") return [gauss(20, 20, 10, max), lat(), 50];
+ if (template === "mediterranean") return [gauss(25, 30, 15, 80), lat(), 50];
+ if (template === "peninsula") return [gauss(15, 15, 5, 80), lat(), 50];
+ if (template === "isthmus") return [gauss(15, 20, 3, 80), lat(), 50];
+ if (template === "atoll") return [gauss(3, 2, 1, 5, 1), lat(), 50];
- return [gauss(30, 20, 15, max), lat()]; // Continents, Archipelago, High Island, Low Island
+ return [gauss(30, 20, 15, max), lat(), 50]; // Continents, Archipelago, High Island, Low Island
}
}
// calculate map position on globe
function calculateMapCoordinates() {
- const size = +document.getElementById("mapSizeOutput").value;
- const latShift = +document.getElementById("latitudeOutput").value;
+ const sizeFraction = +byId("mapSizeOutput").value / 100;
+ const latShift = +byId("latitudeOutput").value / 100;
+ const lonShift = +byId("longitudeOutput").value / 100;
- const latT = rn((size / 100) * 180, 1);
- const latN = rn(90 - ((180 - latT) * latShift) / 100, 1);
+ const latT = rn(sizeFraction * 180, 1);
+ const latN = rn(90 - (180 - latT) * latShift, 1);
const latS = rn(latN - latT, 1);
- const lon = rn(Math.min(((graphWidth / graphHeight) * latT) / 2, 180));
- mapCoordinates = {latT, latN, latS, lonT: lon * 2, lonW: -lon, lonE: lon};
+ const lonT = rn(Math.min((graphWidth / graphHeight) * latT, 360), 1);
+ const lonE = rn(180 - (360 - lonT) * lonShift, 1);
+ const lonW = rn(lonE - lonT, 1);
+ mapCoordinates = {latT, latN, latS, lonT, lonW, lonE};
}
// temperature model, trying to follow real-world data
@@ -1759,7 +1766,7 @@ function addZones(number = 1) {
}
function addEruption() {
- const volcano = document.getElementById("markers").querySelector("use[data-id='#marker_volcano']");
+ const volcano = byId("markers").querySelector("use[data-id='#marker_volcano']");
if (!volcano) return;
const x = +volcano.dataset.x,
@@ -1978,7 +1985,7 @@ function undraw() {
.getElementById("deftemp")
.querySelectorAll("path, clipPath, svg")
.forEach(el => el.remove());
- document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
+ byId("coas").innerHTML = ""; // remove auto-generated emblems
notes = [];
rulers = new Rulers();
unfog();
diff --git a/modules/dynamic/auto-update.js b/modules/dynamic/auto-update.js
index 28ac3d2b..7db74d2e 100644
--- a/modules/dynamic/auto-update.js
+++ b/modules/dynamic/auto-update.js
@@ -848,10 +848,23 @@ export function resolveVersionConflicts(version) {
}
if (version < 1.98) {
- // v1.98.00 changed routes generation algorithm and data format
+ // v1.98.00 changed compass layer and rose element id
+ const rose = compass.select("use");
+ rose.attr("xlink:href", "#defs-compass-rose");
+
+ if (!compass.selectAll("*").size()) {
+ compass.style("display", "none");
+ compass.append("use").attr("xlink:href", "#defs-compass-rose");
+ shiftCompass();
+ }
+ }
+
+ if (version < 1.99) {
+ // v1.99.00 changed routes generation algorithm and data format
// 1. cells.road => cells.routes and now it an object of objects {i1: {i2: routeId, i3: routeId}}
// 2. cells.crossroad is removed
// 3. pack.routes is added as an array of objects
// 4. rendering is changed
+ // v1.98.00 changed compass layer and rose element id
}
}
diff --git a/modules/dynamic/export-json.js b/modules/dynamic/export-json.js
index 7e3c2c6c..4f66dc95 100644
--- a/modules/dynamic/export-json.js
+++ b/modules/dynamic/export-json.js
@@ -94,7 +94,8 @@ function getSettings() {
populationRate: populationRate,
urbanization: urbanization,
mapSize: mapSizeOutput.value,
- latitudeO: latitudeOutput.value,
+ latitude: latitudeOutput.value,
+ longitude: longitudeOutput.value,
prec: precOutput.value,
options: options,
mapName: mapName.value,
diff --git a/modules/io/export.js b/modules/io/export.js
index 9920c4ad..0d1286b9 100644
--- a/modules/io/export.js
+++ b/modules/io/export.js
@@ -87,7 +87,7 @@ async function exportToPngTiles() {
imgSchema.src = urlSchema;
await loadImage(imgSchema);
- status.innerHTML = "Drawing schema...";
+ status.innerHTML = "Rendering schema...";
ctx.drawImage(imgSchema, 0, 0, canvas.width, canvas.height);
const blob = await canvasToBlob(canvas, "image/png");
ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -95,9 +95,9 @@ async function exportToPngTiles() {
// download tiles
const url = await getMapURL("tiles", {fullMap: true});
- const tilesX = +byId("tileColsInput").value;
- const tilesY = +byId("tileRowsInput").value;
- const scale = +byId("tileScaleInput").value;
+ const tilesX = +byId("tileColsOutput").value || 2;
+ const tilesY = +byId("tileRowsOutput").value || 2;
+ const scale = +byId("tileScaleOutput").value || 1;
const tolesTotal = tilesX * tilesY;
const tileW = (graphWidth / tilesX) | 0;
@@ -113,11 +113,17 @@ async function exportToPngTiles() {
await loadImage(img);
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ function getRowLabel(row) {
+ const first = row >= alphabet.length ? alphabet[Math.floor(row / alphabet.length) - 1] : "";
+ const last = alphabet[row % alphabet.length];
+ return first + last;
+ }
+
for (let y = 0, row = 0, id = 1; y + tileH <= graphHeight; y += tileH, row++) {
- const rowName = alphabet[row % alphabet.length];
+ const rowName = getRowLabel(row);
for (let x = 0, cell = 1; x + tileW <= graphWidth; x += tileW, cell++, id++) {
- status.innerHTML = `Drawing tile ${rowName}${cell} (${id} of ${tolesTotal})...`;
+ status.innerHTML = `Rendering tile ${rowName}${cell} (${id} of ${tolesTotal})...`;
ctx.drawImage(img, x, y, tileW, tileH, 0, 0, width, height);
const blob = await canvasToBlob(canvas, "image/png");
ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -295,7 +301,7 @@ async function getMapURL(type, options) {
// add wind rose
if (cloneEl.getElementById("compass")) {
- const rose = svgDefs.getElementById("rose");
+ const rose = svgDefs.getElementById("defs-compass-rose");
if (rose) cloneDefs.appendChild(rose.cloneNode(true));
}
diff --git a/modules/io/load.js b/modules/io/load.js
index ea5b8a5c..a11ef1dd 100644
--- a/modules/io/load.js
+++ b/modules/io/load.js
@@ -242,6 +242,7 @@ async function parseLoadedData(data, mapVersion) {
if (settings[22]) stylePreset.value = settings[22];
if (settings[23]) rescaleLabels.checked = +settings[23];
if (settings[24]) urbanDensity = urbanDensityInput.value = urbanDensityOutput.value = +settings[24];
+ if (settings[25]) longitudeInput.value = longitudeOutput.value = minmax(settings[25] || 50, 0, 100);
})();
void (function applyOptionsToUI() {
@@ -458,7 +459,7 @@ async function parseLoadedData(data, mapVersion) {
{
// dynamically import and run auto-update script
const versionNumber = parseFloat(params[0]);
- const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.97.04");
+ const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.98.00");
resolveVersionConflicts(versionNumber);
}
diff --git a/modules/io/save.js b/modules/io/save.js
index a3a5cbea..fd8c586b 100644
--- a/modules/io/save.js
+++ b/modules/io/save.js
@@ -67,7 +67,8 @@ function prepareMapData() {
+hideLabels.checked,
stylePreset.value,
+rescaleLabels.checked,
- urbanDensity
+ urbanDensity,
+ longitudeOutput.value
].join("|");
const coords = JSON.stringify(mapCoordinates);
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
diff --git a/modules/ui/general.js b/modules/ui/general.js
index 9c8c195f..8ac87374 100644
--- a/modules/ui/general.js
+++ b/modules/ui/general.js
@@ -290,7 +290,7 @@ function toDMS(coord, c) {
const minutes = Math.floor(minutesNotTruncated);
const seconds = Math.floor((minutesNotTruncated - minutes) * 60);
const cardinal = c === "lat" ? (coord >= 0 ? "N" : "S") : coord >= 0 ? "E" : "W";
- return degrees + "° " + minutes + "′ " + seconds + "″ " + cardinal;
+ return degrees + "°" + minutes + "′" + seconds + "″" + cardinal;
}
// get surface elevation
diff --git a/modules/ui/layers.js b/modules/ui/layers.js
index f1af7d52..fd1e48fd 100644
--- a/modules/ui/layers.js
+++ b/modules/ui/layers.js
@@ -1070,27 +1070,29 @@ function drawStates() {
const bodyData = body.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
const gapData = gap.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
- const haloData = halo.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
const bodyString = bodyData.map(d => ` `).join("");
const gapString = gapData.map(d => ` `).join("");
- const clipString = bodyData
- .map(d => ` `)
- .join("");
- const haloString = haloData
- .map(
- d =>
- ` `
- )
- .join("");
-
statesBody.html(bodyString + gapString);
- defs.select("#statePaths").html(clipString);
- statesHalo.html(haloString);
- // connect vertices to chain
+ const isOptimized = shapeRendering.value === "optimizeSpeed";
+ if (!isOptimized) {
+ const haloData = halo.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
+
+ const haloString = haloData
+ .map(d => {
+ const stroke = d3.color(d[2]) ? d3.color(d[2]).darker().hex() : "#666666";
+ return ` `;
+ })
+ .join("");
+ statesHalo.html(haloString);
+
+ const clipString = bodyData
+ .map(d => ` `)
+ .join("");
+ defs.select("#statePaths").html(clipString);
+ }
+
function connectVertices(start, state) {
const chain = []; // vertices chain to form a path
const getType = c => {
@@ -1525,10 +1527,6 @@ function toggleCompass(event) {
if (!layerIsOn("toggleCompass")) {
turnButtonOn("toggleCompass");
$("#compass").fadeIn();
- if (!compass.selectAll("*").size()) {
- compass.append("use").attr("xlink:href", "#rose");
- shiftCompass();
- }
if (event && isCtrlClick(event)) editStyle("compass");
} else {
if (event && isCtrlClick(event)) {
diff --git a/modules/ui/options.js b/modules/ui/options.js
index 8b9e12a7..f4d95951 100644
--- a/modules/ui/options.js
+++ b/modules/ui/options.js
@@ -644,17 +644,16 @@ function randomizeCultureSet() {
function setRendering(value) {
viewbox.attr("shape-rendering", value);
- // if (value === "optimizeSpeed") {
- // // block some styles
- // coastline.select("#sea_island").style("filter", "none");
- // statesHalo.style("display", "none");
- // emblems.style("opacity", 1);
- // } else {
- // // remove style block
- // coastline.select("#sea_island").style("filter", null);
- // statesHalo.style("display", null);
- // emblems.style("opacity", null);
- // }
+ if (value === "optimizeSpeed") {
+ // block some styles
+ coastline.select("#sea_island").style("filter", "none");
+ statesHalo.style("display", "none");
+ } else {
+ // remove style block
+ coastline.select("#sea_island").style("filter", null);
+ statesHalo.style("display", null);
+ if (pack.cells && statesHalo.selectAll("*").size() === 0) drawStates();
+ }
}
// generate current year and era name
@@ -902,9 +901,9 @@ function updateTilesOptions() {
}
const tileSize = byId("tileSize");
- const tilesX = +byId("tileColsOutput").value;
- const tilesY = +byId("tileRowsOutput").value;
- const scale = +byId("tileScaleOutput").value;
+ const tilesX = +byId("tileColsOutput").value || 2;
+ const tilesY = +byId("tileRowsOutput").value || 2;
+ const scale = +byId("tileScaleOutput").value || 1;
// calculate size
const sizeX = graphWidth * scale * tilesX;
@@ -921,11 +920,16 @@ function updateTilesOptions() {
const tileH = (graphHeight / tilesY) | 0;
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ function getRowLabel(row) {
+ const first = row >= alphabet.length ? alphabet[Math.floor(row / alphabet.length) - 1] : "";
+ const last = alphabet[row % alphabet.length];
+ return first + last;
+ }
+
for (let y = 0, row = 0; y + tileH <= graphHeight; y += tileH, row++) {
for (let x = 0, column = 1; x + tileW <= graphWidth; x += tileW, column++) {
rects.push(` `);
- const label = alphabet[row % alphabet.length] + column;
- labels.push(`${label} `);
+ labels.push(`${getRowLabel(row)}${column} `);
}
}
diff --git a/modules/ui/stylePresets.js b/modules/ui/stylePresets.js
index aa13d800..adbf5c14 100644
--- a/modules/ui/stylePresets.js
+++ b/modules/ui/stylePresets.js
@@ -63,7 +63,7 @@ async function getStylePreset(desiredPreset) {
async function fetchSystemPreset(preset) {
try {
- const res = await fetch(`./styles/${preset}.json`);
+ const res = await fetch(`./styles/${preset}.json?v=${version}`);
return await res.json();
} catch (err) {
throw new Error("Cannot fetch style preset", preset);
@@ -198,7 +198,7 @@ function addStylePreset() {
"mask"
],
"#compass": ["opacity", "transform", "filter", "mask", "shape-rendering"],
- "#rose": ["transform"],
+ "#compass > use": ["transform"],
"#relig": ["opacity", "stroke", "stroke-width", "filter"],
"#cults": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
"#landmass": ["opacity", "fill", "filter"],
diff --git a/modules/ui/world-configurator.js b/modules/ui/world-configurator.js
index 0f25057e..9ac0062c 100644
--- a/modules/ui/world-configurator.js
+++ b/modules/ui/world-configurator.js
@@ -5,18 +5,17 @@ function editWorld() {
title: "Configure World",
resizable: false,
width: "minmax(40em, 85vw)",
- buttons: {
- "Whole World": () => applyWorldPreset(100, 50),
- Northern: () => applyWorldPreset(33, 25),
- Tropical: () => applyWorldPreset(33, 50),
- Southern: () => applyWorldPreset(33, 75)
- },
+ buttons: {"Update world": updateWorld},
open: function () {
- const buttons = $(this).dialog("widget").find(".ui-dialog-buttonset > button");
- buttons[0].addEventListener("mousemove", () => tip("Click to set map size to cover the whole World"));
- buttons[1].addEventListener("mousemove", () => tip("Click to set map size to cover the Northern latitudes"));
- buttons[2].addEventListener("mousemove", () => tip("Click to set map size to cover the Tropical latitudes"));
- buttons[3].addEventListener("mousemove", () => tip("Click to set map size to cover the Southern latitudes"));
+ const checkbox = /* html */ `
+
+ auto-apply changes
+
`;
+ const pane = this.parentElement.querySelector(".ui-dialog-buttonpane");
+ pane.insertAdjacentHTML("afterbegin", checkbox);
+
+ const button = this.parentElement.querySelector(".ui-dialog-buttonset > button");
+ button.on("mousemove", () => tip("Apply curreny settings to the map"));
},
close: function () {
$(this).dialog("destroy");
@@ -34,12 +33,17 @@ function editWorld() {
if (modules.editWorld) return;
modules.editWorld = true;
- byId("worldControls").addEventListener("input", e => updateWorld(e.target));
- globe.select("#globeWindArrows").on("click", changeWind);
- globe.select("#globeGraticule").attr("d", round(path(d3.geoGraticule()()))); // globe graticule
+ const graticule = d3.geoGraticule();
+ globe.select("#globeWindArrows").on("click", handleWindChange);
+ globe.select("#globeGraticule").attr("d", round(path(graticule()))); // globe graticule
updateWindDirections();
- byId("restoreWinds").addEventListener("click", restoreDefaultWinds);
+ byId("worldControls").on("input", handleControlsChange);
+ byId("restoreWinds").on("click", restoreDefaultWinds);
+ byId("wcWholeWorld").on("click", () => applyWorldPreset(100, 50));
+ byId("wcNorthern").on("click", () => applyWorldPreset(33, 25));
+ byId("wcTropical").on("click", () => applyWorldPreset(33, 50));
+ byId("wcSouthern").on("click", () => applyWorldPreset(33, 75));
function updateInputValues() {
byId("temperatureEquatorInput").value = options.temperatureEquator;
@@ -55,27 +59,27 @@ function editWorld() {
byId("temperatureSouthPoleF").innerText = convertTemperature(options.temperatureSouthPole, "°F");
}
- function updateWorld(el) {
- if (el?.dataset.stored) {
- const stored = el.dataset.stored;
- byId(stored + "Input").value = el.value;
- byId(stored + "Output").value = el.value;
- lock(el.dataset.stored);
+ function handleControlsChange({target}) {
+ const stored = target.dataset.stored;
+ byId(stored + "Input").value = target.value;
+ byId(stored + "Output").value = target.value;
+ lock(stored);
- if (stored === "temperatureEquator") {
- options.temperatureEquator = Number(el.value);
- byId("temperatureEquatorF").innerText = convertTemperature(options.temperatureEquator, "°F");
- }
- if (stored === "temperatureNorthPole") {
- options.temperatureNorthPole = Number(el.value);
- byId("temperatureNorthPoleF").innerText = convertTemperature(options.temperatureNorthPole, "°F");
- }
- if (stored === "temperatureSouthPole") {
- options.temperatureSouthPole = Number(el.value);
- byId("temperatureSouthPoleF").innerText = convertTemperature(options.temperatureSouthPole, "°F");
- }
+ if (stored === "temperatureEquator") {
+ options.temperatureEquator = Number(target.value);
+ byId("temperatureEquatorF").innerText = convertTemperature(options.temperatureEquator, "°F");
+ } else if (stored === "temperatureNorthPole") {
+ options.temperatureNorthPole = Number(target.value);
+ byId("temperatureNorthPoleF").innerText = convertTemperature(options.temperatureNorthPole, "°F");
+ } else if (stored === "temperatureSouthPole") {
+ options.temperatureSouthPole = Number(target.value);
+ byId("temperatureSouthPoleF").innerText = convertTemperature(options.temperatureSouthPole, "°F");
}
+ if (byId("wcAutoChange").checked) updateWorld();
+ }
+
+ function updateWorld() {
updateGlobeTemperature();
updateGlobePosition();
calculateTemperatures();
@@ -130,6 +134,7 @@ function editWorld() {
[mc.lonW, mc.latN],
[mc.lonE, mc.latS]
]);
+
globe.select("#globeArea").attr("d", round(path(area.outline()))); // map area
}
@@ -163,21 +168,22 @@ function editWorld() {
});
}
- function changeWind() {
+ function handleWindChange() {
const arrow = d3.event.target.nextElementSibling;
const tier = +arrow.dataset.tier;
options.winds[tier] = (options.winds[tier] + 45) % 360;
const tr = parseTransform(arrow.getAttribute("transform"));
arrow.setAttribute("transform", `rotate(${options.winds[tier]} ${tr[1]} ${tr[2]})`);
localStorage.setItem("winds", options.winds);
+
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map(c => ((90 - c) / 30) | 0);
- if (mapTiers.includes(tier)) updateWorld();
+ if (byId("wcAutoChange").checked && mapTiers.includes(tier)) updateWorld();
}
function restoreDefaultWinds() {
const defaultWinds = [225, 45, 225, 315, 135, 315];
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map(c => ((90 - c) / 30) | 0);
- const update = mapTiers.some(t => options.winds[t] != defaultWinds[t]);
+ const update = byId("wcAutoChange").checked && mapTiers.some(t => options.winds[t] != defaultWinds[t]);
options.winds = defaultWinds;
updateWindDirections();
if (update) updateWorld();
@@ -188,6 +194,6 @@ function editWorld() {
byId("latitudeInput").value = byId("latitudeOutput").value = lat;
lock("mapSize");
lock("latitude");
- updateWorld();
+ if (byId("wcAutoChange").checked) updateWorld();
}
}
diff --git a/run_php_server.bat b/run_php_server.bat
new file mode 100644
index 00000000..e168921d
--- /dev/null
+++ b/run_php_server.bat
@@ -0,0 +1,3 @@
+start chrome.exe http://localhost:3000/
+@echo off
+php -S localhost:3000
diff --git a/styles/ancient.json b/styles/ancient.json
index 78cac9e1..17d210a5 100644
--- a/styles/ancient.json
+++ b/styles/ancient.json
@@ -72,8 +72,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": "translate(80 80) scale(.25)"
+ "#compass > use": {
+ "transform": "translate(80 80) scale(0.25)"
},
"#relig": {
"opacity": 0.7,
diff --git a/styles/atlas.json b/styles/atlas.json
index 040e551c..d8936b65 100644
--- a/styles/atlas.json
+++ b/styles/atlas.json
@@ -72,7 +72,7 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
+ "#compass > use": {
"transform": "translate(80 80) scale(.25)"
},
"#relig": {
diff --git a/styles/clean.json b/styles/clean.json
index 6f2e7ac6..ba6fc3a5 100644
--- a/styles/clean.json
+++ b/styles/clean.json
@@ -73,8 +73,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(.25)"
},
"#relig": {
"opacity": 0.7,
diff --git a/styles/cyberpunk.json b/styles/cyberpunk.json
index 7b8d64b6..152cd0cd 100644
--- a/styles/cyberpunk.json
+++ b/styles/cyberpunk.json
@@ -72,8 +72,8 @@
"mask": "",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(.25)"
},
"#relig": {
"opacity": 0.5,
diff --git a/styles/default.json b/styles/default.json
index 7e6521ea..5cf061ba 100644
--- a/styles/default.json
+++ b/styles/default.json
@@ -72,8 +72,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(0.25)"
},
"#relig": {
"opacity": 0.7,
diff --git a/styles/gloom.json b/styles/gloom.json
index 72c123e1..766db87b 100644
--- a/styles/gloom.json
+++ b/styles/gloom.json
@@ -73,7 +73,7 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
+ "#compass > use": {
"transform": "translate(100 100) scale(0.3)"
},
"#relig": {
diff --git a/styles/light.json b/styles/light.json
index 955c7091..30748daf 100644
--- a/styles/light.json
+++ b/styles/light.json
@@ -72,8 +72,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(.25)"
},
"#relig": {
"opacity": 0.5,
diff --git a/styles/monochrome.json b/styles/monochrome.json
index c0810154..6af0d6a1 100644
--- a/styles/monochrome.json
+++ b/styles/monochrome.json
@@ -73,8 +73,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(.25)"
},
"#relig": {
"opacity": 0.7,
diff --git a/styles/night.json b/styles/night.json
index dbbcf0bf..790cad8d 100644
--- a/styles/night.json
+++ b/styles/night.json
@@ -72,7 +72,7 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
+ "#compass > use": {
"transform": "translate(80 80) scale(0.25)"
},
"#relig": {
diff --git a/styles/pale.json b/styles/pale.json
index 883c614b..3a32ed6d 100644
--- a/styles/pale.json
+++ b/styles/pale.json
@@ -72,8 +72,8 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
- "transform": null
+ "#compass > use": {
+ "transform": "translate(80 80) scale(.25)"
},
"#relig": {
"opacity": 0.5,
diff --git a/styles/watercolor.json b/styles/watercolor.json
index 2605433c..4386940f 100644
--- a/styles/watercolor.json
+++ b/styles/watercolor.json
@@ -72,7 +72,7 @@
"mask": "url(#water)",
"shape-rendering": "optimizespeed"
},
- "#rose": {
+ "#compass > use": {
"transform": "translate(80 80) scale(.25)"
},
"#relig": {
diff --git a/versioning.js b/versioning.js
index bf275623..20aa7a28 100644
--- a/versioning.js
+++ b/versioning.js
@@ -1,7 +1,7 @@
"use strict";
// version and caching control
-const version = "1.98.00"; // generator version, update each time
+const version = "1.99.00"; // generator version, update each time
{
document.title += " v" + version;
@@ -28,7 +28,11 @@ const version = "1.98.00"; // generator version, update each time
Latest changes:
+<<<<<<< HEAD
New routes generatation algorithm
+=======
+ Configurable longitude
+>>>>>>> 00abd5213b446922a60e2053eaca711a6d4067e2
Preview villages map
Ability to render ocean heightmap
Scale bar styling features
@@ -41,6 +45,10 @@ const version = "1.98.00"; // generator version, update each time
North and South Poles temperature can be set independently
More than 70 new heraldic charges
Multi-color heraldic charges support
+<<<<<<< HEAD
+=======
+ New 3D scene options and improvements
+>>>>>>> 00abd5213b446922a60e2053eaca711a6d4067e2
Join our Discord server and Reddit community to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.