Merge pull request #1 from mosuzi/master

pull original repo
This commit is contained in:
mosuzi 2023-03-28 11:56:02 +08:00 committed by GitHub
commit 8fd9b82554
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1761 additions and 613 deletions

View file

@ -1176,18 +1176,18 @@ function refreshAllEditors() {
// dynamically loaded editors
async function editStates() {
if (customization) return;
const Editor = await import("../dynamic/editors/states-editor.js?v=12062022");
const Editor = await import("../dynamic/editors/states-editor.js?v=1.89.05");
Editor.open();
}
async function editCultures() {
if (customization) return;
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.88.06");
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.89.09");
Editor.open();
}
async function editReligions() {
if (customization) return;
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.88.06");
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.89.10");
Editor.open();
}

View file

@ -204,6 +204,13 @@ function editHeightmap(options) {
INFO && console.group("Edit Heightmap");
TIME && console.time("regenerateErasedData");
// remove data
pack.cultures = [];
pack.burgs = [];
pack.states = [];
pack.provinces = [];
pack.religions = [];
const erosionAllowed = allowErosion.checked;
markFeatures();
markupGridOcean();
@ -231,8 +238,10 @@ function editHeightmap(options) {
Lakes.defineGroup();
defineBiomes();
rankCells();
Cultures.generate();
Cultures.expand();
BurgsAndStates.generate();
Religions.generate();
BurgsAndStates.defineStateForms();

View file

@ -67,11 +67,11 @@ function editIce() {
function addIcebergOnClick() {
const [x, y] = d3.mouse(this);
const i = findGridCell(x, y, grid);
const c = grid.points[i];
const s = +document.getElementById("iceSize").value;
const [cx, cy] = grid.points[i];
const size = +document.getElementById("iceSize")?.value || 1;
const points = getGridPolygon(i).map(p => [(p[0] + (c[0] - p[0]) / s) | 0, (p[1] + (c[1] - p[1]) / s) | 0]);
const iceberg = ice.append("polygon").attr("points", points).attr("cell", i).attr("size", s);
const points = getGridPolygon(i).map(([x, y]) => [rn(lerp(cx, x, size), 2), rn(lerp(cy, y, size), 2)]);
const iceberg = ice.append("polygon").attr("points", points).attr("cell", i).attr("size", size);
iceberg.call(d3.drag().on("drag", dragElement));
if (d3.event.shiftKey === false) toggleAdd();
}

View file

@ -671,11 +671,10 @@ function toggleIce(event) {
}
function drawIce() {
const cells = grid.cells,
vertices = grid.vertices,
n = cells.i.length,
temp = cells.temp,
h = cells.h;
const {cells, vertices} = grid;
const {temp, h} = cells;
const n = cells.i.length;
const used = new Uint8Array(cells.i.length);
Math.random = aleaPRNG(seed);
@ -700,23 +699,22 @@ function drawIce() {
continue;
}
const tNormalized = normalize(t, -8, 2);
const randomFactor = t > -5 ? 0.4 + rand() * 1.2 : 1;
// mildly cold: iceberd
if (P(normalize(t, -7, 2.5))) continue; // t[-5; 2] cold: skip some cells
if (P(tNormalized ** 0.5 * randomFactor)) continue; // cold: skip some cells
if (grid.features[cells.f[i]].type === "lake") continue; // lake: no icebers
let size = (6.5 + t) / 10; // iceberg size: 0 = full size, 1 = zero size
if (cells.t[i] === -1) size *= 1.3; // coasline: smaller icebers
size = Math.min(size * (0.4 + rand() * 1.2), 0.95); // randomize iceberg size
resizePolygon(i, size);
let size = 1 - tNormalized; // iceberg size: 0 = zero size, 1 = full size
if (cells.t[i] === -1) size /= 1.3; // coasline: smaller icebers
resizePolygon(i, minmax(rn(size * randomFactor, 2), 0.08, 1));
}
function resizePolygon(i, s) {
const c = grid.points[i];
const points = getGridPolygon(i).map(p => [(p[0] + (c[0] - p[0]) * s) | 0, (p[1] + (c[1] - p[1]) * s) | 0]);
ice
.append("polygon")
.attr("points", points)
.attr("cell", i)
.attr("size", rn(1 - s, 2));
function resizePolygon(i, size) {
const [cx, cy] = grid.points[i];
const points = getGridPolygon(i).map(([x, y]) => [rn(lerp(cx, x, size), 2), rn(lerp(cy, y, size), 2)]);
ice.append("polygon").attr("points", points).attr("cell", i).attr("size", size);
}
// connect vertices to chain

View file

@ -42,12 +42,11 @@ function editNotes(id, name) {
$("#notesEditor").dialog({
title: "Notes Editor",
width: "minmax(80vw, 540px)",
width: window.innerWidth * 0.8,
height: window.innerHeight * 0.75,
position: {my: "center", at: "center", of: "svg"},
close: removeEditor
});
$("[aria-describedby='notesEditor']").css("top", "10vh");
if (modules.editNotes) return;
modules.editNotes = true;

View file

@ -77,12 +77,15 @@ document
// show popup with a list of Patreon supportes (updated manually)
async function showSupporters() {
const {supporters} = await import("../dynamic/supporters.js?v=19062022");
const list = supporters.split("\n").sort();
const columns = window.innerWidth < 800 ? 2 : 5;
alertMessage.innerHTML =
"<ul style='column-count: 5; column-gap: 2em'>" + supporters.map(n => `<li>${n}</li>`).join("") + "</ul>";
`<ul style='column-count: ${columns}; column-gap: 2em'>` + list.map(n => `<li>${n}</li>`).join("") + "</ul>";
$("#alert").dialog({
resizable: false,
title: "Patreon Supporters",
width: "54vw",
width: "min-width",
position: {my: "center", at: "center", of: "svg"}
});
}
@ -157,9 +160,20 @@ optionsContent.addEventListener("click", function (event) {
});
function mapSizeInputChange() {
const $mapWidthInput = byId("mapWidthInput");
const $mapHeightInput = byId("mapHeightInput");
changeMapSize();
localStorage.setItem("mapWidth", mapWidthInput.value);
localStorage.setItem("mapHeight", mapHeightInput.value);
localStorage.setItem("mapWidth", $mapWidthInput.value);
localStorage.setItem("mapHeight", $mapHeightInput.value);
const tooWide = +$mapWidthInput.value > window.innerWidth;
const tooHigh = +$mapHeightInput.value > window.innerHeight;
if (tooWide || tooHigh) {
const message = `Canvas size is larger than actual window size (${window.innerWidth} x ${window.innerHeight}). It can affect the performance if you are going to create a new map`;
tip(message, false, "warn", 4000);
}
}
// change svg size on manual size change or window resize, do not change graph size
@ -534,7 +548,7 @@ function applyStoredOptions() {
options.stateLabelsMode = stateLabelsModeInput.value;
}
// randomize options if randomization is allowed (not locked or options='default')
// randomize options if randomization is allowed (not locked or queryParam options='default')
function randomizeOptions() {
const randomize = new URL(window.location.href).searchParams.get("options") === "default"; // ignore stored options
@ -546,7 +560,7 @@ function randomizeOptions() {
manorsInput.value = 1000;
manorsOutput.value = "auto";
}
if (randomize || !locked("religions")) religionsInput.value = religionsOutput.value = gauss(5, 2, 2, 10);
if (randomize || !locked("religions")) religionsInput.value = religionsOutput.value = gauss(6, 3, 2, 10);
if (randomize || !locked("power")) powerInput.value = powerOutput.value = gauss(4, 2, 0, 10, 2);
if (randomize || !locked("neutral")) neutralInput.value = neutralOutput.value = rn(1 + Math.random(), 1);
if (randomize || !locked("cultures")) culturesInput.value = culturesOutput.value = gauss(12, 3, 5, 30);
@ -602,17 +616,17 @@ 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");
// emblems.style("opacity", 1);
// } else {
// // remove style block
// coastline.select("#sea_island").style("filter", null);
// statesHalo.style("display", null);
// emblems.style("opacity", null);
// }
}
// generate current year and era name

View file

@ -74,12 +74,13 @@ function createRiver() {
function addRiver() {
const {rivers, cells} = pack;
const {addMeandering, getApproximateLength, getWidth, getOffset, getName, getRiverPath, getBasin} = Rivers;
const {addMeandering, getApproximateLength, getWidth, getOffset, getName, getRiverPath, getBasin, getNextId} =
Rivers;
const riverCells = createRiver.cells;
if (riverCells.length < 2) return tip("Add at least 2 cells", false, "error");
const riverId = rivers.length ? last(rivers).i + 1 : 1;
const riverId = getNextId(rivers);
const parent = cells.r[last(riverCells)] || riverId;
riverCells.forEach(cell => {
@ -100,12 +101,30 @@ function createRiver() {
const name = getName(mouth);
const basin = getBasin(parent);
rivers.push({i: riverId, source, mouth, discharge, length, width, widthFactor, sourceWidth, parent, cells: riverCells, basin, name, type: "River"});
rivers.push({
i: riverId,
source,
mouth,
discharge,
length,
width,
widthFactor,
sourceWidth,
parent,
cells: riverCells,
basin,
name,
type: "River"
});
const id = "river" + riverId;
// render river
lineGen.curve(d3.curveCatmullRom.alpha(0.1));
viewbox.select("#rivers").append("path").attr("id", id).attr("d", getRiverPath(meanderedPoints, widthFactor, sourceWidth));
viewbox
.select("#rivers")
.append("path")
.attr("id", id)
.attr("d", getRiverPath(meanderedPoints, widthFactor, sourceWidth));
editRiver(id);
}

View file

@ -1,4 +1,7 @@
"use strict";
const CONTROL_POINST_DISTANCE = 10;
function editRoute(onClick) {
if (customization) return;
if (!onClick && elSelected && d3.event.target.id === elSelected.attr("id")) return;
@ -47,13 +50,13 @@ function editRoute(onClick) {
}
function drawControlPoints(node) {
const l = node.getTotalLength();
const increment = l / Math.ceil(l / 4);
for (let i = 0; i <= l; i += increment) {
const totalLength = node.getTotalLength();
const increment = totalLength / Math.ceil(totalLength / CONTROL_POINST_DISTANCE);
for (let i = 0; i <= totalLength; i += increment) {
const point = node.getPointAtLength(i);
addControlPoint([point.x, point.y]);
}
routeLength.innerHTML = rn(l * distanceScaleInput.value) + " " + distanceUnitInput.value;
routeLength.innerHTML = rn(totalLength * distanceScaleInput.value) + " " + distanceUnitInput.value;
}
function addControlPoint(point, before = null) {

View file

@ -1,14 +1,27 @@
// UI module to control the style presets
"use strict";
const systemPresets = ["default", "ancient", "gloom", "light", "watercolor", "clean", "atlas", "cyberpunk", "monochrome"];
const systemPresets = [
"default",
"ancient",
"gloom",
"pale",
"light",
"watercolor",
"clean",
"atlas",
"cyberpunk",
"monochrome"
];
const customPresetPrefix = "fmgStyle_";
// add style presets to list
{
const systemOptions = systemPresets.map(styleName => `<option value="${styleName}">${styleName}</option>`);
const storedStyles = Object.keys(localStorage).filter(key => key.startsWith(customPresetPrefix));
const customOptions = storedStyles.map(styleName => `<option value="${styleName}">${styleName.replace(customPresetPrefix, "")} [custom]</option>`);
const customOptions = storedStyles.map(
styleName => `<option value="${styleName}">${styleName.replace(customPresetPrefix, "")} [custom]</option>`
);
const options = systemOptions.join("") + customOptions.join("");
document.getElementById("stylePreset").innerHTML = options;
}
@ -37,7 +50,8 @@ async function getStylePreset(desiredPreset) {
const isValid = JSON.isValid(storedStyleJSON);
if (isValid) return [desiredPreset, JSON.parse(storedStyleJSON)];
ERROR && console.error(`Custom style ${desiredPreset} stored in localStorage is not valid. Applying default style`);
ERROR &&
console.error(`Custom style ${desiredPreset} stored in localStorage is not valid. Applying default style`);
presetToLoad = "default";
}
}
@ -145,8 +159,31 @@ function addStylePreset() {
"#stateBorders": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
"#provinceBorders": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
"#cells": ["opacity", "stroke", "stroke-width", "filter", "mask"],
"#gridOverlay": ["opacity", "scale", "dx", "dy", "type", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "transform", "filter", "mask"],
"#coordinates": ["opacity", "data-size", "font-size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter", "mask"],
"#gridOverlay": [
"opacity",
"scale",
"dx",
"dy",
"type",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap",
"transform",
"filter",
"mask"
],
"#coordinates": [
"opacity",
"data-size",
"font-size",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap",
"filter",
"mask"
],
"#compass": ["opacity", "transform", "filter", "mask", "shape-rendering"],
"#rose": ["transform"],
"#relig": ["opacity", "stroke", "stroke-width", "filter"],
@ -174,7 +211,17 @@ function addStylePreset() {
"#statesBody": ["opacity", "filter"],
"#statesHalo": ["opacity", "data-width", "stroke-width", "filter"],
"#provs": ["opacity", "fill", "font-size", "font-family", "filter"],
"#temperature": ["opacity", "font-size", "fill", "fill-opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
"#temperature": [
"opacity",
"font-size",
"fill",
"fill-opacity",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap",
"filter"
],
"#ice": ["opacity", "fill", "stroke", "stroke-width", "filter"],
"#emblems": ["opacity", "stroke-width", "filter"],
"#texture": ["opacity", "filter", "mask"],
@ -184,16 +231,65 @@ function addStylePreset() {
"#oceanBase": ["fill"],
"#oceanicPattern": ["href", "opacity"],
"#terrs": ["opacity", "scheme", "terracing", "skip", "relax", "curve", "filter", "mask"],
"#legend": ["data-size", "font-size", "font-family", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "data-x", "data-y", "data-columns"],
"#legend": [
"data-size",
"font-size",
"font-family",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap",
"data-x",
"data-y",
"data-columns"
],
"#legendBox": ["fill", "fill-opacity"],
"#burgLabels > #cities": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"],
"#burgIcons > #cities": ["opacity", "fill", "fill-opacity", "size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap"],
"#burgIcons > #cities": [
"opacity",
"fill",
"fill-opacity",
"size",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap"
],
"#anchors > #cities": ["opacity", "fill", "size", "stroke", "stroke-width"],
"#burgLabels > #towns": ["opacity", "fill", "text-shadow", "data-size", "font-size", "font-family"],
"#burgIcons > #towns": ["opacity", "fill", "fill-opacity", "size", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap"],
"#burgIcons > #towns": [
"opacity",
"fill",
"fill-opacity",
"size",
"stroke",
"stroke-width",
"stroke-dasharray",
"stroke-linecap"
],
"#anchors > #towns": ["opacity", "fill", "size", "stroke", "stroke-width"],
"#labels > #states": ["opacity", "fill", "stroke", "stroke-width", "text-shadow", "data-size", "font-size", "font-family", "filter"],
"#labels > #addedLabels": ["opacity", "fill", "stroke", "stroke-width", "text-shadow", "data-size", "font-size", "font-family", "filter"],
"#labels > #states": [
"opacity",
"fill",
"stroke",
"stroke-width",
"text-shadow",
"data-size",
"font-size",
"font-family",
"filter"
],
"#labels > #addedLabels": [
"opacity",
"fill",
"stroke",
"stroke-width",
"text-shadow",
"data-size",
"font-size",
"font-family",
"filter"
],
"#fogging": ["opacity", "fill", "filter"]
};
@ -238,7 +334,8 @@ function addStylePreset() {
if (!styleJSON) return tip("Please provide a style JSON", false, "error");
if (!JSON.isValid(styleJSON)) return tip("JSON string is not valid, please check the format", false, "error");
if (!desiredName) return tip("Please provide a preset name", false, "error");
if (styleSaverTip.innerHTML === "default") return tip("You cannot overwrite default preset, please change the name", false, "error");
if (styleSaverTip.innerHTML === "default")
return tip("You cannot overwrite default preset, please change the name", false, "error");
const presetName = customPresetPrefix + desiredName;
applyOption(stylePreset, presetName, desiredName + " [custom]");

View file

@ -74,10 +74,8 @@ toolsContent.addEventListener("click", function (event) {
});
function processFeatureRegeneration(event, button) {
if (button === "regenerateStateLabels") {
BurgsAndStates.drawStateLabels();
if (!layerIsOn("toggleLabels")) toggleLabels();
} else if (button === "regenerateReliefIcons") {
if (button === "regenerateStateLabels") BurgsAndStates.drawStateLabels();
else if (button === "regenerateReliefIcons") {
ReliefIcons();
if (!layerIsOn("toggleRelief")) toggleRelief();
} else if (button === "regenerateRoutes") {
@ -628,10 +626,11 @@ function addRiverOnClick() {
getType,
getWidth,
getOffset,
getApproximateLength
getApproximateLength,
getNextId
} = Rivers;
const riverCells = [];
let riverId = rivers.length ? last(rivers).i + 1 : 1;
let riverId = getNextId(rivers);
let parent = riverId;
const initialFlux = grid.cells.prec[cells.g[i]];