mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 18:11:24 +01:00
partial options typing
This commit is contained in:
parent
324d92613d
commit
70e77714b9
3 changed files with 223 additions and 148 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import {ERROR} from "config/logging";
|
import {ERROR} from "config/logging";
|
||||||
|
|
||||||
window.COArenderer = (function () {
|
export const COArenderer = (function () {
|
||||||
const colors = {
|
const colors = {
|
||||||
argent: "#fafafa",
|
argent: "#fafafa",
|
||||||
or: "#ffe066",
|
or: "#ffe066",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import * as d3 from "d3";
|
||||||
|
|
||||||
import {heightmapTemplates} from "config/heightmap-templates";
|
import {heightmapTemplates} from "config/heightmap-templates";
|
||||||
import {precreatedHeightmaps} from "config/precreated-heightmaps";
|
import {precreatedHeightmaps} from "config/precreated-heightmaps";
|
||||||
import {lock, locked} from "scripts/options/lock";
|
import {lock, locked, unlock} from "scripts/options/lock";
|
||||||
import {clearMainTip, tip} from "scripts/tooltips";
|
import {clearMainTip, tip} from "scripts/tooltips";
|
||||||
import {last} from "utils/arrayUtils";
|
import {last} from "utils/arrayUtils";
|
||||||
import {applyDropdownOption} from "utils/nodeUtils";
|
import {applyDropdownOption} from "utils/nodeUtils";
|
||||||
|
|
@ -10,15 +10,84 @@ import {minmax, rn} from "utils/numberUtils";
|
||||||
import {gauss, P, rand, rw} from "utils/probabilityUtils";
|
import {gauss, P, rand, rw} from "utils/probabilityUtils";
|
||||||
import {byId, stored} from "utils/shorthands";
|
import {byId, stored} from "utils/shorthands";
|
||||||
import {regenerateMap} from "scripts/generation/generation";
|
import {regenerateMap} from "scripts/generation/generation";
|
||||||
import {fitScaleBar} from "modules/measurers";
|
// @ts-expect-error js file
|
||||||
|
import {fitScaleBar} from "modules/measurers.js";
|
||||||
import {openDialog} from "dialogs";
|
import {openDialog} from "dialogs";
|
||||||
import {closeDialogs} from "dialogs/utils";
|
import {closeDialogs} from "dialogs/utils";
|
||||||
|
// @ts-expect-error js file
|
||||||
import {quickSave, saveToDropbox, dowloadMap} from "modules/io/save.js";
|
import {quickSave, saveToDropbox, dowloadMap} from "modules/io/save.js";
|
||||||
|
// @ts-expect-error js file
|
||||||
|
import {fitLegendBox} from "modules/legend.js";
|
||||||
|
// @ts-expect-error js file
|
||||||
|
import {COArenderer} from "modules/coa-renderer.js";
|
||||||
|
import { isBurg, isCulture, isProvince, isState } from "utils/typeUtils.js";
|
||||||
|
|
||||||
$("#optionsContainer").draggable({handle: ".drag-trigger", snap: "svg", snapMode: "both"});
|
$("#optionsContainer").draggable({handle: ".drag-trigger", snap: "svg", snapMode: "both"});
|
||||||
$("#exitCustomization").draggable({handle: "div"});
|
$("#exitCustomization").draggable({handle: "div"});
|
||||||
$("#mapLayers").disableSelection();
|
$("#mapLayers").disableSelection();
|
||||||
|
|
||||||
|
// Window Objects
|
||||||
|
const Zoom = window.Zoom;
|
||||||
|
const COA = window.COA;
|
||||||
|
|
||||||
|
// DIV elements
|
||||||
|
const tooltip = byId("tooltip")! as HTMLDivElement;
|
||||||
|
|
||||||
|
// Options pane elements
|
||||||
|
const optionsTrigger = byId("optionsTrigger")! as HTMLButtonElement;
|
||||||
|
const regenerate = byId("regenerate")! as HTMLButtonElement;
|
||||||
|
const optionsDiv = byId("options")! as HTMLDivElement;
|
||||||
|
const collapsible = byId("collapsible")! as HTMLDivElement;
|
||||||
|
const layersContent = byId("layersContent")! as HTMLDivElement;
|
||||||
|
const styleContent = byId("styleContent")! as HTMLDivElement;
|
||||||
|
const customizationMenu = byId("customizationMenu")! as HTMLDivElement;
|
||||||
|
const toolsContent = byId("toolsContent")! as HTMLDivElement;
|
||||||
|
const aboutContent = byId("aboutContent")! as HTMLDivElement;
|
||||||
|
const optionsContent = byId("optionsContent")! as HTMLDivElement;
|
||||||
|
const alertMessage = byId("alertMessage")! as HTMLDivElement;
|
||||||
|
const dialogDiv = byId("dialogs")! as HTMLDivElement;
|
||||||
|
|
||||||
|
// Number inputs
|
||||||
|
const themeColorInput = byId("themeColorInput")! as HTMLInputElement;
|
||||||
|
const themeHueInput = byId("themeHueInput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const transparencyInput = byId("transparencyInput")! as HTMLInputElement;
|
||||||
|
const transparencyOutput = byId("transparencyOutput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const mapWidthInput = byId("mapWidthInput")! as HTMLInputElement;
|
||||||
|
const mapHeightInput = byId("mapHeightInput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const zoomExtentMin = byId("zoomExtentMin")! as HTMLInputElement;
|
||||||
|
const zoomExtentMax = byId("zoomExtentMax")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const optionsSeed = byId("optionsSeed")! as HTMLInputElement;
|
||||||
|
const pointsInput = byId("pointsInput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const culturesInput = byId("culturesInput")! as HTMLInputElement;
|
||||||
|
const regionsOutput = byId("regionsOutput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const uiSizeInput = byId("uiSizeInput")! as HTMLInputElement;
|
||||||
|
const uiSizeOutput = byId("uiSizeOutput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const distanceUnitInput = byId("distanceUnitInput")! as HTMLSelectElement;
|
||||||
|
const heightUnitInput = byId("heightUnitInput")! as HTMLSelectElement;
|
||||||
|
|
||||||
|
// Text inputs
|
||||||
|
const mapName = byId("mapName")! as HTMLInputElement;
|
||||||
|
const templateInput = byId("templateInput")! as HTMLSelectElement
|
||||||
|
const culturesSet = byId("culturesSet")! as HTMLSelectElement;
|
||||||
|
const culturesOutput = byId("culturesOutput")! as HTMLInputElement;
|
||||||
|
|
||||||
|
const stylePreset = byId("stylePreset")! as HTMLSelectElement;
|
||||||
|
|
||||||
|
const shapeRendering = byId("shapeRendering")! as HTMLSelectElement;
|
||||||
|
const stateLabelsModeInput = byId("stateLabelsModeInput")! as HTMLSelectElement;
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
const manorsOutput = byId("manorsOutput")! as HTMLOutputElement;
|
||||||
|
const pointsOutputFormatted = byId("pointsOutputFormatted")! as HTMLOutputElement;
|
||||||
|
|
||||||
|
|
||||||
// remove glow if tip is aknowledged
|
// remove glow if tip is aknowledged
|
||||||
if (stored("disable_click_arrow_tooltip")) {
|
if (stored("disable_click_arrow_tooltip")) {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
|
|
@ -26,37 +95,37 @@ if (stored("disable_click_arrow_tooltip")) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show options pane on trigger click
|
// Show options pane on trigger click
|
||||||
function showOptions(event) {
|
function showOptions(event: MouseEvent) {
|
||||||
if (!stored("disable_click_arrow_tooltip")) {
|
if (!stored("disable_click_arrow_tooltip")) {
|
||||||
clearMainTip();
|
clearMainTip();
|
||||||
localStorage.setItem("disable_click_arrow_tooltip", true);
|
localStorage.setItem("disable_click_arrow_tooltip", "true");
|
||||||
optionsTrigger.classList.remove("glow");
|
optionsTrigger.classList.remove("glow");
|
||||||
}
|
}
|
||||||
|
|
||||||
regenerate.style.display = "none";
|
regenerate.style.display = "none";
|
||||||
byId("options").style.display = "block";
|
optionsDiv.style.display = "block";
|
||||||
optionsTrigger.style.display = "none";
|
optionsTrigger.style.display = "none";
|
||||||
|
|
||||||
if (event) event.stopPropagation();
|
if (event) event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide options pane on trigger click
|
// Hide options pane on trigger click
|
||||||
export function hideOptions(event) {
|
export function hideOptions(event: Event) {
|
||||||
byId("options").style.display = "none";
|
optionsDiv.style.display = "none";
|
||||||
optionsTrigger.style.display = "block";
|
optionsTrigger.style.display = "block";
|
||||||
if (event) event.stopPropagation();
|
if (event) event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// To toggle options on hotkey press
|
// To toggle options on hotkey press
|
||||||
export function toggleOptions(event) {
|
export function toggleOptions(event: MouseEvent) {
|
||||||
if (byId("options").style.display === "none") showOptions(event);
|
if (optionsDiv.style.display === "none") showOptions(event);
|
||||||
else hideOptions(event);
|
else hideOptions(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle "New Map!" pane on hover
|
// Toggle "New Map!" pane on hover
|
||||||
optionsTrigger.on("mouseenter", function () {
|
optionsTrigger.on("mouseenter", function () {
|
||||||
if (optionsTrigger.classList.contains("glow")) return;
|
if (optionsTrigger.classList.contains("glow")) return;
|
||||||
if (byId("options").style.display === "none") regenerate.style.display = "block";
|
if (optionsDiv.style.display === "none") regenerate.style.display = "block";
|
||||||
});
|
});
|
||||||
|
|
||||||
collapsible.on("mouseleave", function () {
|
collapsible.on("mouseleave", function () {
|
||||||
|
|
@ -64,21 +133,19 @@ collapsible.on("mouseleave", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Activate options tab on click
|
// Activate options tab on click
|
||||||
document
|
optionsDiv
|
||||||
.getElementById("options")
|
.querySelector("div.tab")!
|
||||||
.querySelector("div.tab")
|
.on("click", function (event: any ) { // MARKER: any
|
||||||
.on("click", function (event) {
|
|
||||||
if (event.target.tagName !== "BUTTON") return;
|
if (event.target.tagName !== "BUTTON") return;
|
||||||
const id = event.target.id;
|
const id = event.target.id;
|
||||||
const active = byId("options").querySelector(".tab > button.active");
|
const active = optionsDiv.querySelector(".tab > button.active");
|
||||||
if (active && id === active.id) return; // already active tab is clicked
|
if (active && id === active.id) return; // already active tab is clicked
|
||||||
|
|
||||||
if (active) active.classList.remove("active");
|
if (active) active.classList.remove("active");
|
||||||
byId(id).classList.add("active");
|
byId(id)!.classList.add("active");
|
||||||
document
|
optionsDiv
|
||||||
.getElementById("options")
|
.querySelectorAll<HTMLElement>(".tabcontent")
|
||||||
.querySelectorAll(".tabcontent")
|
.forEach((e: HTMLElement) => {e.style.display = "none"});
|
||||||
.forEach(e => (e.style.display = "none"));
|
|
||||||
|
|
||||||
if (id === "layersTab") layersContent.style.display = "block";
|
if (id === "layersTab") layersContent.style.display = "block";
|
||||||
else if (id === "styleTab") styleContent.style.display = "block";
|
else if (id === "styleTab") styleContent.style.display = "block";
|
||||||
|
|
@ -90,9 +157,10 @@ document
|
||||||
|
|
||||||
// show popup with a list of Patreon supportes (updated manually)
|
// show popup with a list of Patreon supportes (updated manually)
|
||||||
async function showSupporters() {
|
async function showSupporters() {
|
||||||
|
// @ts-expect-error js file
|
||||||
const {supporters} = await import("../dynamic/supporters.js");
|
const {supporters} = await import("../dynamic/supporters.js");
|
||||||
alertMessage.innerHTML =
|
alertMessage.innerHTML =
|
||||||
"<ul style='column-count: 5; column-gap: 2em'>" + supporters.map(n => `<li>${n}</li>`).join("") + "</ul>";
|
"<ul style='column-count: 5; column-gap: 2em'>" + (supporters as String[]).map(n => `<li>${n}</li>`).join("") + "</ul>"; // MARKER: as conversion
|
||||||
$("#alert").dialog({
|
$("#alert").dialog({
|
||||||
resizable: false,
|
resizable: false,
|
||||||
title: "Patreon Supporters",
|
title: "Patreon Supporters",
|
||||||
|
|
@ -102,16 +170,16 @@ async function showSupporters() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// on any option or dialog change
|
// on any option or dialog change
|
||||||
byId("options").on("change", storeValueIfRequired);
|
optionsDiv.on("change", storeValueIfRequired);
|
||||||
byId("dialogs").on("change", storeValueIfRequired);
|
dialogDiv.on("change", storeValueIfRequired);
|
||||||
byId("options").on("input", updateOutputToFollowInput);
|
optionsDiv.on("input", updateOutputToFollowInput);
|
||||||
byId("dialogs").on("input", updateOutputToFollowInput);
|
dialogDiv.on("input", updateOutputToFollowInput);
|
||||||
|
|
||||||
function storeValueIfRequired(ev) {
|
function storeValueIfRequired(ev: any) { // MARKER: any
|
||||||
if (ev.target.dataset.stored) lock(ev.target.dataset.stored);
|
if (ev.target.dataset.stored) lock(ev.target.dataset.stored);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOutputToFollowInput(ev) {
|
function updateOutputToFollowInput(ev: any) { // MARKER: any
|
||||||
const id = ev.target.id;
|
const id = ev.target.id;
|
||||||
const value = ev.target.value;
|
const value = ev.target.value;
|
||||||
|
|
||||||
|
|
@ -120,17 +188,17 @@ function updateOutputToFollowInput(ev) {
|
||||||
|
|
||||||
// generic case
|
// generic case
|
||||||
if (id.slice(-5) === "Input") {
|
if (id.slice(-5) === "Input") {
|
||||||
const output = byId(id.slice(0, -5) + "Output");
|
const output = byId(id.slice(0, -5) + "Output") as HTMLOutputElement; // MARKER: as conversion
|
||||||
if (output) output.value = value;
|
if (output) output.value = value;
|
||||||
} else if (id.slice(-6) === "Output") {
|
} else if (id.slice(-6) === "Output") {
|
||||||
const input = byId(id.slice(0, -6) + "Input");
|
const input = byId(id.slice(0, -6) + "Input") as HTMLInputElement; // MARKER: as conversion
|
||||||
if (input) input.value = value;
|
if (input) input.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Option listeners
|
// Option listeners
|
||||||
const optionsContent = byId("optionsContent");
|
|
||||||
optionsContent.on("input", function (event) {
|
optionsContent.on("input", function (event: any) { // MARKER: any
|
||||||
const id = event.target.id;
|
const id = event.target.id;
|
||||||
const value = event.target.value;
|
const value = event.target.value;
|
||||||
if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange();
|
if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange();
|
||||||
|
|
@ -144,12 +212,12 @@ optionsContent.on("input", function (event) {
|
||||||
else if (id === "transparencyInput") changeDialogsTheme(themeColorInput.value, value);
|
else if (id === "transparencyInput") changeDialogsTheme(themeColorInput.value, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
optionsContent.on("change", function (event) {
|
optionsContent.on("change", function (event: any) { // MARKER: any
|
||||||
const id = event.target.id;
|
const id = event.target.id;
|
||||||
const value = event.target.value;
|
const value = event.target.value;
|
||||||
|
|
||||||
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
|
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
|
||||||
else if (id === "optionsSeed") generateMapWithSeed("seed change");
|
else if (id === "optionsSeed") generateMapWithSeed();
|
||||||
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value);
|
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value);
|
||||||
else if (id === "shapeRendering") setRendering(value);
|
else if (id === "shapeRendering") setRendering(value);
|
||||||
else if (id === "yearInput") changeYear();
|
else if (id === "yearInput") changeYear();
|
||||||
|
|
@ -157,7 +225,7 @@ optionsContent.on("change", function (event) {
|
||||||
else if (id === "stateLabelsModeInput") options.stateLabelsMode = value;
|
else if (id === "stateLabelsModeInput") options.stateLabelsMode = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
optionsContent.on("click", function (event) {
|
optionsContent.on("click", function (event:any) { // MARKER: any
|
||||||
const id = event.target.id;
|
const id = event.target.id;
|
||||||
if (id === "toggleFullscreen") toggleFullscreen();
|
if (id === "toggleFullscreen") toggleFullscreen();
|
||||||
else if (id === "optionsMapHistory") showSeedHistoryDialog();
|
else if (id === "optionsMapHistory") showSeedHistoryDialog();
|
||||||
|
|
@ -184,8 +252,8 @@ export function addResizeListener() {
|
||||||
if (stored("mapWidth") && stored("mapHeight")) return;
|
if (stored("mapWidth") && stored("mapHeight")) return;
|
||||||
|
|
||||||
const {innerWidth, innerHeight} = window;
|
const {innerWidth, innerHeight} = window;
|
||||||
byId("mapWidthInput").value = innerWidth;
|
mapWidthInput.value = innerWidth.toString(); // MARKER: toString
|
||||||
byId("mapHeightInput").value = innerHeight;
|
mapHeightInput.value = innerHeight.toString(); // MARKER: toString
|
||||||
|
|
||||||
changeMapSize();
|
changeMapSize();
|
||||||
});
|
});
|
||||||
|
|
@ -193,14 +261,14 @@ export function addResizeListener() {
|
||||||
|
|
||||||
// change svg size on manual size change or window resize, do not change graph size
|
// change svg size on manual size change or window resize, do not change graph size
|
||||||
function changeMapSize() {
|
function changeMapSize() {
|
||||||
svgWidth = Math.min(+mapWidthInput.value, window.innerWidth);
|
svgWidth = Math.min(Number(mapWidthInput.value), window.innerWidth);
|
||||||
svgHeight = Math.min(+mapHeightInput.value, window.innerHeight);
|
svgHeight = Math.min(Number(mapHeightInput.value), window.innerHeight);
|
||||||
svg.attr("width", svgWidth).attr("height", svgHeight);
|
svg.attr("width", svgWidth).attr("height", svgHeight);
|
||||||
|
|
||||||
const maxWidth = Math.max(+mapWidthInput.value, graphWidth);
|
const maxWidth = Math.max(Number(mapWidthInput.value), graphWidth);
|
||||||
const maxHeight = Math.max(+mapHeightInput.value, graphHeight);
|
const maxHeight = Math.max(Number(mapHeightInput.value), graphHeight);
|
||||||
|
|
||||||
Zoom.translateExtent([0, 0, maxWidth, maxHeight]);
|
Zoom.translateExtent([[0, 0], [maxWidth, maxHeight]]);
|
||||||
|
|
||||||
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
|
landmass.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
|
||||||
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
|
oceanPattern.select("rect").attr("x", 0).attr("y", 0).attr("width", maxWidth).attr("height", maxHeight);
|
||||||
|
|
@ -210,15 +278,15 @@ function changeMapSize() {
|
||||||
texture.select("image").attr("width", maxWidth).attr("height", maxHeight);
|
texture.select("image").attr("width", maxWidth).attr("height", maxHeight);
|
||||||
|
|
||||||
fitScaleBar();
|
fitScaleBar();
|
||||||
if (window.fitLegendBox) fitLegendBox();
|
fitLegendBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
// just apply canvas size that was already set
|
// just apply canvas size that was already set
|
||||||
export function applyMapSize() {
|
export function applyMapSize() {
|
||||||
const zoomMin = +zoomExtentMin.value;
|
const zoomMin = Number(zoomExtentMin.value);
|
||||||
const zoomMax = +zoomExtentMax.value;
|
const zoomMax = Number(zoomExtentMax.value);
|
||||||
graphWidth = +mapWidthInput.value;
|
graphWidth = Number(mapWidthInput.value);
|
||||||
graphHeight = +mapHeightInput.value;
|
graphHeight = Number(mapHeightInput.value);
|
||||||
svgWidth = Math.min(graphWidth, window.innerWidth);
|
svgWidth = Math.min(graphWidth, window.innerWidth);
|
||||||
svgHeight = Math.min(graphHeight, window.innerHeight);
|
svgHeight = Math.min(graphHeight, window.innerHeight);
|
||||||
svg.attr("width", svgWidth).attr("height", svgHeight);
|
svg.attr("width", svgWidth).attr("height", svgHeight);
|
||||||
|
|
@ -231,19 +299,19 @@ export function applyMapSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFullscreen() {
|
function toggleFullscreen() {
|
||||||
if (mapWidthInput.value != window.innerWidth || mapHeightInput.value != window.innerHeight) {
|
if (Number(mapWidthInput.value) != Number(window.innerWidth) || Number(mapHeightInput.value) != Number(window.innerHeight)) {
|
||||||
mapWidthInput.value = window.innerWidth;
|
mapWidthInput.value = window.innerWidth.toString();
|
||||||
mapHeightInput.value = window.innerHeight;
|
mapHeightInput.value = window.innerHeight.toString();
|
||||||
localStorage.removeItem("mapHeight");
|
localStorage.removeItem("mapHeight");
|
||||||
localStorage.removeItem("mapWidth");
|
localStorage.removeItem("mapWidth");
|
||||||
} else {
|
} else {
|
||||||
mapWidthInput.value = graphWidth;
|
mapWidthInput.value = graphWidth.toString();
|
||||||
mapHeightInput.value = graphHeight;
|
mapHeightInput.value = graphHeight.toString();
|
||||||
}
|
}
|
||||||
changeMapSize();
|
changeMapSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleTranslateExtent(el) {
|
function toggleTranslateExtent(el: any) { // MARKER: any
|
||||||
const on = !Number(el.dataset.on);
|
const on = !Number(el.dataset.on);
|
||||||
const extent = on
|
const extent = on
|
||||||
? [-graphWidth / 2, -graphHeight / 2, graphWidth * 1.5, graphHeight * 1.5]
|
? [-graphWidth / 2, -graphHeight / 2, graphWidth * 1.5, graphHeight * 1.5]
|
||||||
|
|
@ -259,13 +327,13 @@ const voiceInterval = setInterval(function () {
|
||||||
if (voices.length) clearInterval(voiceInterval);
|
if (voices.length) clearInterval(voiceInterval);
|
||||||
else return;
|
else return;
|
||||||
|
|
||||||
const select = byId("speakerVoice");
|
const select = byId("speakerVoice")! as HTMLSelectElement;
|
||||||
voices.forEach((voice, i) => {
|
voices.forEach((voice, i) => {
|
||||||
select.options.add(new Option(voice.name, i, false));
|
select.options.add(new Option(voice.name, i.toString(), false));
|
||||||
});
|
});
|
||||||
if (stored("speakerVoice")) select.value = stored("speakerVoice");
|
if (stored("speakerVoice")) select.value = stored("speakerVoice")!; // MARKER: !
|
||||||
// se voice to store
|
// se voice to store
|
||||||
else select.value = voices.findIndex(voice => voice.lang === "en-US"); // or to first found English-US
|
else select.value = voices.findIndex(voice => voice.lang === "en-US").toString(); // or to first found English-US
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
function testSpeaker() {
|
function testSpeaker() {
|
||||||
|
|
@ -273,7 +341,7 @@ function testSpeaker() {
|
||||||
const speaker = new SpeechSynthesisUtterance(text);
|
const speaker = new SpeechSynthesisUtterance(text);
|
||||||
const voices = speechSynthesis.getVoices();
|
const voices = speechSynthesis.getVoices();
|
||||||
if (voices.length) {
|
if (voices.length) {
|
||||||
const voiceId = +byId("speakerVoice").value;
|
const voiceId = Number((byId("speakerVoice") as HTMLInputElement).value); // MARKER: as conversion
|
||||||
speaker.voice = voices[voiceId];
|
speaker.voice = voices[voiceId];
|
||||||
}
|
}
|
||||||
speechSynthesis.speak(speaker);
|
speechSynthesis.speak(speaker);
|
||||||
|
|
@ -302,12 +370,12 @@ function showSeedHistoryDialog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate map with historical seed
|
// generate map with historical seed
|
||||||
function restoreSeed(id) {
|
function restoreSeed(id: number) {
|
||||||
const {seed, width, height, template} = mapHistory[id];
|
const {seed, width, height, template} = mapHistory[id];
|
||||||
byId("optionsSeed").value = seed;
|
optionsSeed.value = seed;
|
||||||
byId("mapWidthInput").value = width;
|
mapWidthInput.value = width.toString();
|
||||||
byId("mapHeightInput").value = height;
|
mapHeightInput.value = height.toString();
|
||||||
byId("templateInput").value = template;
|
templateInput.value = template;
|
||||||
|
|
||||||
if (locked("template")) unlock("template");
|
if (locked("template")) unlock("template");
|
||||||
|
|
||||||
|
|
@ -315,8 +383,8 @@ function restoreSeed(id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreDefaultZoomExtent() {
|
function restoreDefaultZoomExtent() {
|
||||||
zoomExtentMin.value = 1;
|
zoomExtentMin.value = "1";
|
||||||
zoomExtentMax.value = 20;
|
zoomExtentMax.value = "20";
|
||||||
Zoom.scaleExtent([1, 20]);
|
Zoom.scaleExtent([1, 20]);
|
||||||
Zoom.scaleTo(svg, 1);
|
Zoom.scaleTo(svg, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -335,52 +403,52 @@ function copyMapURL() {
|
||||||
.catch(err => tip("Could not copy URL: " + err, false, "error", 5000));
|
.catch(err => tip("Could not copy URL: " + err, false, "error", 5000));
|
||||||
}
|
}
|
||||||
|
|
||||||
const cellsDensityMap = {
|
const cellsDensityMap = [
|
||||||
1: 1000,
|
1000,
|
||||||
2: 2000,
|
2000,
|
||||||
3: 5000,
|
5000,
|
||||||
4: 10000,
|
10000,
|
||||||
5: 20000,
|
20000,
|
||||||
6: 30000,
|
30000,
|
||||||
7: 40000,
|
40000,
|
||||||
8: 50000,
|
50000,
|
||||||
9: 60000,
|
60000,
|
||||||
10: 70000,
|
70000,
|
||||||
11: 80000,
|
80000,
|
||||||
12: 90000,
|
90000,
|
||||||
13: 100000
|
100000
|
||||||
};
|
];
|
||||||
|
|
||||||
function changeCellsDensity(value) {
|
function changeCellsDensity(value: number) {
|
||||||
const cells = cellsDensityMap[value] || 1000;
|
const cells = cellsDensityMap[value] || 1000;
|
||||||
pointsInput.dataset.cells = cells;
|
pointsInput.dataset.cells = cells.toString();
|
||||||
pointsOutputFormatted.value = getCellsDensityValue(cells);
|
pointsOutputFormatted.value = getCellsDensityValue(cells);
|
||||||
pointsOutputFormatted.style.color = getCellsDensityColor(cells);
|
pointsOutputFormatted.style.color = getCellsDensityColor(cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCellsDensityValue(cells) {
|
function getCellsDensityValue(cells: number) {
|
||||||
return cells / 1000 + "K";
|
return cells / 1000 + "K";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCellsDensityColor(cells) {
|
function getCellsDensityColor(cells: number) {
|
||||||
return cells > 50000 ? "#b12117" : cells !== 10000 ? "#dfdf12" : "#053305";
|
return cells > 50000 ? "#b12117" : cells !== 10000 ? "#dfdf12" : "#053305";
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeCultureSet() {
|
function changeCultureSet() {
|
||||||
const max = culturesSet.selectedOptions[0].dataset.max;
|
const max = culturesSet.selectedOptions[0].dataset.max!;
|
||||||
culturesInput.max = culturesOutput.max = max;
|
culturesInput.max = culturesOutput.max = max;
|
||||||
if (+culturesOutput.value > +max) culturesInput.value = culturesOutput.value = max;
|
if (Number(culturesOutput.value) > Number(max)) culturesInput.value = culturesOutput.value = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeEmblemShape(emblemShape) {
|
function changeEmblemShape(emblemShape: string) {
|
||||||
const image = byId("emblemShapeImage");
|
const image = <unknown>byId("emblemShapeImage")! as SVGPathElement;
|
||||||
const shapePath = window.COArenderer && COArenderer.shieldPaths[emblemShape];
|
const shapePath = COArenderer && COArenderer.shieldPaths[emblemShape];
|
||||||
shapePath ? image.setAttribute("d", shapePath) : image.removeAttribute("d");
|
shapePath ? image.setAttribute("d", shapePath) : image.removeAttribute("d");
|
||||||
|
|
||||||
const specificShape = ["culture", "state", "random"].includes(emblemShape) ? null : emblemShape;
|
const specificShape = ["culture", "state", "random"].includes(emblemShape) ? null : emblemShape;
|
||||||
if (emblemShape === "random") pack.cultures.filter(c => !c.removed).forEach(c => (c.shield = COA.getRandomShield()));
|
if (emblemShape === "random") pack.cultures.filter(c => isCulture(c) && !c.removed).forEach(c => (c.shield = COA.getRandomShield()));
|
||||||
|
|
||||||
const rerenderCOA = (id, coa) => {
|
const rerenderCOA = (id: string, coa: ICoa | string) => {
|
||||||
const coaEl = byId(id);
|
const coaEl = byId(id);
|
||||||
if (!coaEl) return; // not rendered
|
if (!coaEl) return; // not rendered
|
||||||
coaEl.remove();
|
coaEl.remove();
|
||||||
|
|
@ -388,7 +456,7 @@ function changeEmblemShape(emblemShape) {
|
||||||
};
|
};
|
||||||
|
|
||||||
pack.states.forEach(state => {
|
pack.states.forEach(state => {
|
||||||
if (!state.i || state.removed || !state.coa || state.coa === "custom") return;
|
if (!isState(state) || state.removed || !state.coa || state.coa === "custom") return;
|
||||||
|
|
||||||
const newShield = specificShape || COA.getPackShield(state.culture, null);
|
const newShield = specificShape || COA.getPackShield(state.culture, null);
|
||||||
if (newShield === state.coa.shield) return;
|
if (newShield === state.coa.shield) return;
|
||||||
|
|
@ -397,7 +465,7 @@ function changeEmblemShape(emblemShape) {
|
||||||
});
|
});
|
||||||
|
|
||||||
pack.provinces.forEach(province => {
|
pack.provinces.forEach(province => {
|
||||||
if (!province.i || province.removed || !province.coa || province.coa === "custom") return;
|
if (!isProvince(province) || province.removed || !province.coa || province.coa === "custom") return;
|
||||||
const culture = pack.cells.culture[province.center];
|
const culture = pack.cells.culture[province.center];
|
||||||
const newShield = specificShape || COA.getPackShield(culture, province.state);
|
const newShield = specificShape || COA.getPackShield(culture, province.state);
|
||||||
if (newShield === province.coa.shield) return;
|
if (newShield === province.coa.shield) return;
|
||||||
|
|
@ -406,7 +474,7 @@ function changeEmblemShape(emblemShape) {
|
||||||
});
|
});
|
||||||
|
|
||||||
pack.burgs.forEach(burg => {
|
pack.burgs.forEach(burg => {
|
||||||
if (!burg.i || burg.removed || !burg.coa || burg.coa === "custom") return;
|
if (!isBurg(burg) || burg.removed || !burg.coa || burg.coa === "custom") return;
|
||||||
const newShield = specificShape || COA.getPackShield(burg.culture, burg.state);
|
const newShield = specificShape || COA.getPackShield(burg.culture, burg.state);
|
||||||
if (newShield === burg.coa.shield) return;
|
if (newShield === burg.coa.shield) return;
|
||||||
burg.coa.shield = newShield;
|
burg.coa.shield = newShield;
|
||||||
|
|
@ -414,28 +482,32 @@ function changeEmblemShape(emblemShape) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeStatesNumber(value) {
|
function changeStatesNumber(value: string) {
|
||||||
regionsOutput.style.color = +value ? null : "#b12117";
|
if (Number(value)) {
|
||||||
burgLabels.select("#capitals").attr("data-size", Math.max(rn(6 - value / 20), 3));
|
regionsOutput.style.removeProperty("color");
|
||||||
labels.select("#countries").attr("data-size", Math.max(rn(18 - value / 6), 4));
|
} else {
|
||||||
|
regionsOutput.style.color = "#b12117";
|
||||||
|
}
|
||||||
|
burgLabels.select("#capitals").attr("data-size", Math.max(rn(6 - Number(value) / 20), 3));
|
||||||
|
labels.select("#countries").attr("data-size", Math.max(rn(18 - Number(value) / 6), 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeUIsize(value) {
|
function changeUIsize(value: string) {
|
||||||
if (isNaN(+value) || +value < 0.5) return;
|
if (isNaN(Number(value)) || Number(value) < 0.5) return;
|
||||||
|
|
||||||
const max = getUImaxSize();
|
const max = getUImaxSize();
|
||||||
if (+value > max) value = max;
|
if (Number(value) > max) value = max.toString();
|
||||||
|
|
||||||
uiSizeInput.value = uiSizeOutput.value = value;
|
uiSizeInput.value = uiSizeOutput.value = value;
|
||||||
document.getElementsByTagName("body")[0].style.fontSize = rn(value * 10, 2) + "px";
|
document.getElementsByTagName("body")[0].style.fontSize = rn(Number(value) * 10, 2) + "px";
|
||||||
byId("options").style.width = value * 300 + "px";
|
optionsDiv.style.width = Number(value) * 300 + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUImaxSize() {
|
function getUImaxSize() {
|
||||||
return rn(Math.min(window.innerHeight / 465, window.innerWidth / 302), 1);
|
return rn(Math.min(window.innerHeight / 465, window.innerWidth / 302), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTooltipSize(value) {
|
function changeTooltipSize(value: string) {
|
||||||
tooltip.style.fontSize = `calc(${value}px + 0.5vw)`;
|
tooltip.style.fontSize = `calc(${value}px + 0.5vw)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -445,23 +517,23 @@ function restoreDefaultThemeColor() {
|
||||||
changeDialogsTheme(THEME_COLOR, transparencyInput.value);
|
changeDialogsTheme(THEME_COLOR, transparencyInput.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeThemeHue(hue) {
|
function changeThemeHue(hue: string) {
|
||||||
const {s, l} = d3.hsl(themeColorInput.value);
|
const {s, l} = d3.hsl(themeColorInput.value);
|
||||||
const newColor = d3.hsl(+hue, s, l).hex();
|
const newColor = d3.hsl(+hue, s, l).formatHex();
|
||||||
changeDialogsTheme(newColor, transparencyInput.value);
|
changeDialogsTheme(newColor, transparencyInput.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// change color and transparency for modal windows
|
// change color and transparency for modal windows
|
||||||
function changeDialogsTheme(themeColor, transparency) {
|
function changeDialogsTheme(themeColor: string, transparency: string) {
|
||||||
transparencyInput.value = transparencyOutput.value = transparency;
|
transparencyInput.value = transparencyOutput.value = transparency;
|
||||||
const alpha = (100 - +transparency) / 100;
|
const alpha = (100 - Number(transparency)) / 100;
|
||||||
const alphaReduced = Math.min(alpha + 0.3, 1);
|
const alphaReduced = Math.min(alpha + 0.3, 1);
|
||||||
|
|
||||||
const {h, s, l} = d3.hsl(themeColor || THEME_COLOR);
|
const {h, s, l} = d3.hsl(themeColor || THEME_COLOR);
|
||||||
themeColorInput.value = themeColor || THEME_COLOR;
|
themeColorInput.value = themeColor || THEME_COLOR;
|
||||||
themeHueInput.value = h;
|
themeHueInput.value = h.toString();
|
||||||
|
|
||||||
const getRGBA = (hue, saturation, lightness, alpha) => {
|
const getRGBA = (hue: number, saturation: number, lightness: number, alpha: number) => {
|
||||||
const color = d3.hsl(hue, saturation, lightness, alpha);
|
const color = d3.hsl(hue, saturation, lightness, alpha);
|
||||||
return color.toString();
|
return color.toString();
|
||||||
};
|
};
|
||||||
|
|
@ -480,81 +552,84 @@ function changeDialogsTheme(themeColor, transparency) {
|
||||||
|
|
||||||
const sx = document.documentElement.style;
|
const sx = document.documentElement.style;
|
||||||
theme.forEach(({name, h, s, l, alpha}) => {
|
theme.forEach(({name, h, s, l, alpha}) => {
|
||||||
sx.setProperty(name, getRGBA(h, s, l, alpha));
|
sx.setProperty(name, getRGBA(h, s, l, alpha!)); // MARKER: !
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeZoomExtent(value) {
|
function changeZoomExtent(value: string) {
|
||||||
const zoomExtentMin = byId("zoomExtentMin");
|
const zoomExtentMin = byId("zoomExtentMin")! as HTMLInputElement;
|
||||||
const zoomExtentMax = byId("zoomExtentMax");
|
const zoomExtentMax = byId("zoomExtentMax")! as HTMLInputElement;
|
||||||
|
|
||||||
if (+zoomExtentMin.value > +zoomExtentMax.value) {
|
if (Number(zoomExtentMin.value) > Number(zoomExtentMax.value)) {
|
||||||
[zoomExtentMin.value, zoomExtentMax.value] = [zoomExtentMax.value, zoomExtentMin.value];
|
[zoomExtentMin.value, zoomExtentMax.value] = [zoomExtentMax.value, zoomExtentMin.value];
|
||||||
}
|
}
|
||||||
const min = Math.max(+zoomExtentMin.value, 0.01);
|
const min = Math.max(Number(zoomExtentMin.value, 0.01);
|
||||||
const max = Math.min(+zoomExtentMax.value, 200);
|
const max = Math.min(Number(zoomExtentMax.value, 200);
|
||||||
zoomExtentMin.value = min;
|
zoomExtentMin.value = min.toString();
|
||||||
zoomExtentMax.value = max;
|
zoomExtentMax.value = max.toString();
|
||||||
zoom.scaleExtent([min, max]);
|
const scale = minmax(Number(value), 0.01, 200);
|
||||||
const scale = minmax(+value, 0.01, 200);
|
Zoom.scaleExtent([min, max]);
|
||||||
Zoom.scaleTo(svg, scale);
|
Zoom.scaleTo(svg, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore options stored in localStorage
|
// restore options stored in localStorage
|
||||||
export function applyStoredOptions() {
|
export function applyStoredOptions() {
|
||||||
if (!stored("mapWidth") || !stored("mapHeight")) {
|
if (!stored("mapWidth") || !stored("mapHeight")) {
|
||||||
mapWidthInput.value = window.innerWidth;
|
mapWidthInput.value = window.innerWidth.toString();
|
||||||
mapHeightInput.value = window.innerHeight;
|
mapHeightInput.value = window.innerHeight.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const heightmapId = stored("template");
|
const heightmapId = stored("template");
|
||||||
if (heightmapId) {
|
if (heightmapId) {
|
||||||
const name = heightmapTemplates[heightmapId]?.name || precreatedHeightmaps[heightmapId]?.name || heightmapId;
|
const name = heightmapTemplates[heightmapId]?.name || precreatedHeightmaps[heightmapId]?.name || heightmapId;
|
||||||
applyDropdownOption(byId("templateInput"), heightmapId, name);
|
applyDropdownOption(templateInput, heightmapId, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stored("distanceUnit")) applyDropdownOption(byId("distanceUnitInput"), stored("distanceUnit"));
|
if (stored("distanceUnit")) applyDropdownOption(distanceUnitInput, stored("distanceUnit")!); // MARKER: !
|
||||||
if (stored("heightUnit")) applyDropdownOption(byId("heightUnit"), stored("heightUnit"));
|
if (stored("heightUnit")) applyDropdownOption(heightUnitInput, stored("heightUnit")!); // MARKER: !
|
||||||
|
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
const key = localStorage.key(i);
|
const key = localStorage.key(i)!; // MARKER: !
|
||||||
|
|
||||||
if (key === "speakerVoice") continue;
|
if (key === "speakerVoice") continue;
|
||||||
const input = byId(key + "Input") || byId(key);
|
const input = (byId(key + "Input")! || byId(key)!) as HTMLInputElement; // MARKER: !
|
||||||
const output = byId(key + "Output");
|
const output = (byId(key + "Output")!) as HTMLInputElement; // MARKER: !
|
||||||
|
|
||||||
const value = stored(key);
|
const value = stored(key);
|
||||||
if (input) input.value = value;
|
if (input) input.value = value!; // MARKER: !
|
||||||
if (output) output.value = value;
|
if (output) output.value = value!; // MARKER: !
|
||||||
lock(key);
|
lock(key);
|
||||||
|
|
||||||
// add saved style presets to options
|
// add saved style presets to options
|
||||||
if (key.slice(0, 5) === "style") applyDropdownOption(byId("stylePreset"), key, key.slice(5));
|
if (key.slice(0, 5) === "style") applyDropdownOption(stylePreset, key, key.slice(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stored("winds"))
|
if (stored("winds"))
|
||||||
options.winds = localStorage
|
options.winds = localStorage
|
||||||
.getItem("winds")
|
.getItem("winds")!
|
||||||
.split(",")
|
.split(",")
|
||||||
.map(w => +w);
|
.map(w => Number(w));
|
||||||
if (stored("military")) options.military = JSON.parse(stored("military"));
|
if (stored("military") options.military = JSON.parse(stored("military")!); // MARKER: !
|
||||||
|
|
||||||
if (stored("tooltipSize")) changeTooltipSize(stored("tooltipSize"));
|
if (stored("tooltipSize")) changeTooltipSize(stored("tooltipSize")!);
|
||||||
if (stored("regions")) changeStatesNumber(stored("regions"));
|
if (stored("regions")) changeStatesNumber(stored("regions")!);
|
||||||
|
|
||||||
uiSizeInput.max = uiSizeOutput.max = getUImaxSize();
|
uiSizeInput.max = uiSizeOutput.max = getUImaxSize().toString();
|
||||||
if (stored("uiSize")) changeUIsize(stored("uiSize"));
|
if (stored("uiSize")) {
|
||||||
else changeUIsize(minmax(rn(mapWidthInput.value / 1280, 1), 1, 2.5));
|
changeUIsize(stored("uiSize")!)
|
||||||
|
} else {
|
||||||
|
changeUIsize(minmax(rn(Number(mapWidthInput.value) / 1280, 1), 1, 2.5).toString());
|
||||||
|
}
|
||||||
|
|
||||||
// search params overwrite stored and default options
|
// search params overwrite stored and default options
|
||||||
const params = new URL(window.location.href).searchParams;
|
const params = new URL(window.location.href).searchParams;
|
||||||
const width = +params.get("width");
|
const width = Number(params.get("width"));
|
||||||
const height = +params.get("height");
|
const height = Number(params.get("height"));
|
||||||
if (width) mapWidthInput.value = width;
|
if (width) mapWidthInput.value = width.toString();
|
||||||
if (height) mapHeightInput.value = height;
|
if (height) mapHeightInput.value = height.toString();
|
||||||
|
|
||||||
const transparency = stored("transparency") || 5;
|
const transparency = stored("transparency") || "5";
|
||||||
const themeColor = stored("themeColor");
|
const themeColor = stored("themeColor") || THEME_COLOR;
|
||||||
changeDialogsTheme(themeColor, transparency);
|
changeDialogsTheme(themeColor, transparency);
|
||||||
|
|
||||||
setRendering(shapeRendering.value);
|
setRendering(shapeRendering.value);
|
||||||
|
|
@ -41,7 +41,7 @@ export function lock(id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlock option
|
// unlock option
|
||||||
function unlock(id: string) {
|
export function unlock(id: string) {
|
||||||
localStorage.removeItem(id);
|
localStorage.removeItem(id);
|
||||||
const $lock = document.getElementById("lock_" + id);
|
const $lock = document.getElementById("lock_" + id);
|
||||||
if ($lock) {
|
if ($lock) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue