Slider-input web component (#1109)

* feat: slider-input web component

* feat: slider-input web component - Brush size

* feat: slider-input - statesGrowthRate

* feat: slider-input - units editor

* feat: slider-input - dissalow invalid numbers

* chore: pump version to v1.99.05

* chore: pump version to v1.99.05

---------

Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
Azgaar 2024-08-22 13:35:36 +02:00 committed by GitHub
parent da8c4f1e4a
commit d4aef4920c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 546 additions and 798 deletions

View file

@ -24,7 +24,7 @@ window.BurgsAndStates = (() => {
function placeCapitals() {
TIME && console.time("placeCapitals");
let count = +regionsOutput.value;
let count = +byId("statesNumber").value;
let burgs = [0];
const rand = () => 0.5 + Math.random() * 0.5;
@ -85,7 +85,7 @@ window.BurgsAndStates = (() => {
b.capital = 1;
// states data
const expansionism = rn(Math.random() * powerInput.value + 1, 1);
const expansionism = rn(Math.random() * byId("sizeVariety").value + 1, 1);
const basename = b.name.length < 9 && each5th(b.cell) ? b.name : Names.getCultureShort(b.culture);
const name = Names.getState(basename, b.culture);
const type = cultures[b.culture].type;
@ -378,9 +378,9 @@ window.BurgsAndStates = (() => {
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = [];
const globalNeutralRate = byId("neutralInput")?.valueAsNumber || 1;
const statesNeutralRate = byId("statesNeutral")?.valueAsNumber || 1;
const neutral = (cells.i.length / 2) * globalNeutralRate * statesNeutralRate; // limit cost for state growth
const globalGrowthRate = byId("growthRate").valueAsNumber || 1;
const statesGrowthRate = byId("statesGrowthRate")?.valueAsNumber || 1;
const growthRate = (cells.i.length / 2) * globalGrowthRate * statesGrowthRate; // limit cost for state growth
// remove state from all cells except of locked
for (const cellId of cells.i) {
@ -419,7 +419,7 @@ window.BurgsAndStates = (() => {
const cellCost = Math.max(cultureCost + populationCost + biomeCost + heightCost + riverCost + typeCost, 0);
const totalCost = p + 10 + cellCost / states[s].expansionism;
if (totalCost > neutral) return;
if (totalCost > growthRate) return;
if (!cost[e] || totalCost < cost[e]) {
if (cells.h[e] >= 20) cells.state[e] = s; // assign state to cell
@ -975,9 +975,8 @@ window.BurgsAndStates = (() => {
});
}
const percentage = +provincesInput.value;
const max = percentage == 100 ? 1000 : gauss(20, 5, 5, 100) * percentage ** 0.5; // max growth
const provincesRatio = +byId("provincesRatio").value;
const max = provincesRatio == 100 ? 1000 : gauss(20, 5, 5, 100) * provincesRatio ** 0.5; // max growth
const forms = {
Monarchy: {County: 22, Earldom: 6, Shire: 2, Landgrave: 2, Margrave: 2, Barony: 2, Captaincy: 1, Seneschalty: 1},
@ -1000,7 +999,7 @@ window.BurgsAndStates = (() => {
.sort((a, b) => b.population * gauss(1, 0.2, 0.5, 1.5, 3) - a.population)
.sort((a, b) => b.capital - a.capital);
if (stateBurgs.length < 2) return; // at least 2 provinces are required
const provincesNumber = Math.max(Math.ceil((stateBurgs.length * percentage) / 100), 2);
const provincesNumber = Math.max(Math.ceil((stateBurgs.length * provincesRatio) / 100), 2);
const form = Object.assign({}, forms[s.form]);

View file

@ -169,7 +169,7 @@ window.Cultures = (function () {
else if (type === "Nomadic") base = 1.5;
else if (type === "Hunting") base = 0.7;
else if (type === "Highland") base = 1.2;
return rn(((Math.random() * powerInput.value) / 2 + 1) * base, 1);
return rn(((Math.random() * byId("sizeVariety").value) / 2 + 1) * base, 1);
}
TIME && console.timeEnd("generateCultures");

View file

@ -51,24 +51,9 @@ function insertEditorHtml() {
<button id="culturesHeirarchy" data-tip="Show cultures hierarchy tree" class="icon-sitemap"></button>
<button id="culturesManually" data-tip="Manually re-assign cultures" class="icon-brush"></button>
<div id="culturesManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic">Brush size:
<input
id="culturesManuallyBrush"
oninput="tip('Brush size: '+this.value); culturesManuallyBrushNumber.value = this.value"
type="range"
min="5"
max="99"
value="15"
style="width: 7em"
/>
<input
id="culturesManuallyBrushNumber"
oninput="tip('Brush size: '+this.value); culturesManuallyBrush.value = this.value"
type="number"
min="5"
max="99"
value="15"
/> </label><br />
<div data-tip="Change brush size. Shortcut: + to increase; to decrease" style="margin-block: 0.3em;">
<slider-input id="culturesBrush" min="5" max="100" value="15">Brush size:</slider-input>
</div>
<button id="culturesManuallyApply" data-tip="Apply assignment" class="icon-check"></button>
<button id="culturesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
</div>
@ -718,7 +703,7 @@ function selectCultureOnMapClick() {
}
function dragCultureBrush() {
const radius = +culturesManuallyBrush.value;
const radius = +culturesBrush.value;
d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return;
@ -759,7 +744,7 @@ function changeCultureForSelection(selection) {
function moveCultureBrush() {
showMainTip();
const point = d3.mouse(this);
const radius = +culturesManuallyBrush.value;
const radius = +culturesBrush.value;
moveCircle(point[0], point[1], radius);
}

View file

@ -26,7 +26,7 @@ function insertEditorHtml() {
<div id="religionsHeader" class="header" style="grid-template-columns: 13em 6em 7em 18em 6em 7em 6em 7em">
<div data-tip="Click to sort by religion name" class="sortable alphabetically" data-sortby="name">Religion&nbsp;</div>
<div data-tip="Click to sort by religion type" class="sortable alphabetically icon-sort-name-down" data-sortby="type">Type&nbsp;</div>
<div data-tip="Click to sort by religion form" class="sortable alphabetically hide" data-sortby="form">Form&nbsp;</div>
<div data-tip="Click to sort by religion form" class="sortable alphabetically" data-sortby="form">Form&nbsp;</div>
<div data-tip="Click to sort by supreme deity" class="sortable alphabetically hide" data-sortby="deity">Supreme Deity&nbsp;</div>
<div data-tip="Click to sort by religion area" class="sortable hide" data-sortby="area">Area&nbsp;</div>
<div data-tip="Click to sort by number of believers (religion area population)" class="sortable hide" data-sortby="population">Believers&nbsp;</div>
@ -66,25 +66,9 @@ function insertEditorHtml() {
<button id="religionsManually" data-tip="Manually re-assign religions" class="icon-brush"></button>
<div id="religionsManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic">Brush size:
<input
id="religionsManuallyBrush"
oninput="tip('Brush size: '+this.value); religionsManuallyBrushNumber.value = this.value"
type="range"
min="5"
max="99"
value="15"
style="width: 7em"
/>
<input
id="religionsManuallyBrushNumber"
oninput="tip('Brush size: '+this.value); religionsManuallyBrush.value = this.value"
type="number"
min="5"
max="99"
value="15"
/> </label
><br />
<div data-tip="Change brush size. Shortcut: + to increase; to decrease" style="margin-block: 0.3em;">
<slider-input id="religionsBrush" min="5" max="100" value="15">Brush size:</slider-input>
</div>
<button id="religionsManuallyApply" data-tip="Apply assignment" class="icon-check"></button>
<button id="religionsManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
</div>
@ -183,7 +167,7 @@ function religionsEditorAddLines() {
<select data-tip="Religion type" class="religionType placeholder" style="width: 5em">
${getTypeOptions(r.type)}
</select>
<input data-tip="Religion form" class="religionForm placeholder hide" style="width: 6em" value="" autocorrect="off" spellcheck="false" />
<input data-tip="Religion form" class="religionForm placeholder" style="width: 6em" value="" autocorrect="off" spellcheck="false" />
<span data-tip="Click to re-generate supreme deity" class="icon-arrows-cw placeholder hide"></span>
<input data-tip="Religion supreme deity" class="religionDeity placeholder hide" style="width: 17em" value="" autocorrect="off" spellcheck="false" />
<span data-tip="Religion area" style="padding-right: 4px" class="icon-map-o hide"></span>
@ -215,7 +199,7 @@ function religionsEditorAddLines() {
<select data-tip="Religion type" class="religionType" style="width: 5em">
${getTypeOptions(r.type)}
</select>
<input data-tip="Religion form" class="religionForm hide" style="width: 6em"
<input data-tip="Religion form" class="religionForm" style="width: 6em"
value="${r.form}" autocorrect="off" spellcheck="false" />
<span data-tip="Click to re-generate supreme deity" class="icon-arrows-cw hide"></span>
<input data-tip="Religion supreme deity" class="religionDeity hide" style="width: 17em"
@ -696,7 +680,7 @@ function selectReligionOnMapClick() {
}
function dragReligionBrush() {
const radius = +byId("religionsManuallyBrushNumber").value;
const radius = +byId("religionsBrush").value;
d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return;
@ -736,7 +720,7 @@ function changeReligionForSelection(selection) {
function moveReligionBrush() {
showMainTip();
const [x, y] = d3.mouse(this);
const radius = +byId("religionsManuallyBrushNumber").value;
const radius = +byId("religionsBrush").value;
moveCircle(x, y, radius);
}

View file

@ -24,7 +24,7 @@ function insertEditorHtml() {
<div id="statesHeader" class="header" style="grid-template-columns: 11em 8em 7em 7em 6em 6em 8em 6em 7em 6em">
<div data-tip="Click to sort by state name" class="sortable alphabetically" data-sortby="name">State&nbsp;</div>
<div data-tip="Click to sort by state form name" class="sortable alphabetically" data-sortby="form">Form&nbsp;</div>
<div data-tip="Click to sort by capital name" class="sortable alphabetically hide" data-sortby="capital">Capital&nbsp;</div>
<div data-tip="Click to sort by capital name" class="sortable alphabetically" data-sortby="capital">Capital&nbsp;</div>
<div data-tip="Click to sort by state dominant culture" class="sortable alphabetically hide" data-sortby="culture">Culture&nbsp;</div>
<div data-tip="Click to sort by state burgs count" class="sortable hide" data-sortby="burgs">Burgs&nbsp;</div>
<div data-tip="Click to sort by state area" class="sortable hide icon-sort-number-down" data-sortby="area">Area&nbsp;</div>
@ -55,60 +55,25 @@ function insertEditorHtml() {
<div id="statesRegenerateButtons" style="display: none">
<button id="statesRegenerateBack" data-tip="Hide the regeneration menu" class="icon-cog-alt"></button>
<button id="statesRandomize" data-tip="Randomize states Expansion value and re-calculate states and provinces" class="icon-shuffle"></button>
<span data-tip="Additional growth rate. Defines how many lands will stay neutral">
<label class="italic">Growth rate:</label>
<input
id="statesNeutral"
type="range"
min=".1"
max="3"
step=".05"
value="1"
style="width: 12em"
/>
<input
id="statesNeutralNumber"
type="number"
min=".1"
max="3"
step=".05"
value="1"
style="width: 4em"
/>
</span>
<div data-tip="Additional growth rate. Defines how many land cells remain neutral" style="display: inline-block">
<slider-input id="statesGrowthRate" min=".1" max="3" step=".05" value="1">Growth rate:</slider-input>
</div>
<button id="statesRecalculate" data-tip="Recalculate states based on current values of growth-related attributes" class="icon-retweet"></button>
<span data-tip="Allow states neutral distance, expansion and type changes to take an immediate effect">
<div data-tip="Allow states neutral distance, expansion and type changes to take an immediate effect" style="display: inline-block">
<input id="statesAutoChange" class="checkbox" type="checkbox" />
<label for="statesAutoChange" class="checkbox-label"><i>auto-apply changes</i></label>
</span>
<span data-tip="Allow system to change state labels when states data is change">
</div>
<div data-tip="Allow system to change state labels when states data is change" style="display: inline-block">
<input id="adjustLabels" class="checkbox" type="checkbox" />
<label for="adjustLabels" class="checkbox-label"><i>auto-change labels</i></label>
</span>
</div>
</div>
<button id="statesManually" data-tip="Manually re-assign states" class="icon-brush"></button>
<div id="statesManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic"
>Brush size:
<input
id="statesManuallyBrush"
oninput="tip('Brush size: '+this.value); statesManuallyBrushNumber.value = this.value"
type="range"
min="5"
max="99"
value="15"
style="width: 5em"
/>
<input
id="statesManuallyBrushNumber"
oninput="tip('Brush size: '+this.value); statesManuallyBrush.value = this.value"
type="number"
min="5"
max="99"
value="15"
/> </label
><br />
<div data-tip="Change brush size. Shortcut: + to increase; to decrease" style="margin-block: 0.3em;">
<slider-input id="statesBrush" min="5" max="100" value="15">Brush size:</slider-input>
</div>
<button id="statesManuallyApply" data-tip="Apply assignment" class="icon-check"></button>
<button id="statesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
</div>
@ -135,8 +100,7 @@ function addListeners() {
byId("statesRegenerateBack").on("click", exitRegenerationMenu);
byId("statesRecalculate").on("click", () => recalculateStates(true));
byId("statesRandomize").on("click", randomizeStatesExpansion);
byId("statesNeutral").on("input", changeStatesGrowthRate);
byId("statesNeutralNumber").on("change", changeStatesGrowthRate);
byId("statesGrowthRate").on("input", () => recalculateStates(false));
byId("statesManually").on("click", enterStatesManualAssignent);
byId("statesManuallyApply").on("click", applyStatesManualAssignent);
byId("statesManuallyCancel").on("click", () => exitStatesManualAssignment(false));
@ -228,10 +192,10 @@ function statesEditorAddLines() {
<input data-tip="Neutral lands name. Click to change" class="stateName name pointer italic" value="${
s.name
}" readonly />
<svg class="coaIcon placeholder hide"></svg>
<svg class="coaIcon placeholder"></svg>
<input class="stateForm placeholder" value="none" />
<span class="icon-star-empty placeholder hide"></span>
<input class="stateCapital placeholder hide" />
<span class="icon-star-empty placeholder"></span>
<input class="stateCapital placeholder" />
<select class="stateCulture placeholder hide">${getCultureOptions(0)}</select>
<span data-tip="Click to overview neutral burgs" class="icon-dot-circled pointer hide" style="padding-right: 1px"></span>
<div data-tip="Burgs count" class="stateBurgs hide">${s.burgs}</div>
@ -267,14 +231,14 @@ function statesEditorAddLines() {
>
<fill-box fill="${s.color}"></fill-box>
<input data-tip="State name. Click to change" class="stateName name pointer" value="${s.name}" readonly />
<svg data-tip="Click to show and edit state emblem" class="coaIcon pointer hide" viewBox="0 0 200 200"><use href="#stateCOA${
<svg data-tip="Click to show and edit state emblem" class="coaIcon pointer" viewBox="0 0 200 200"><use href="#stateCOA${
s.i
}"></use></svg>
<input data-tip="State form name. Click to change" class="stateForm name pointer" value="${
s.formName
}" readonly />
<span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer hide"></span>
<input data-tip="Capital name. Click and type to rename" class="stateCapital hide" value="${capital}" autocorrect="off" spellcheck="false" />
<span data-tip="State capital. Click to zoom into view" class="icon-star-empty pointer"></span>
<input data-tip="Capital name. Click and type to rename" class="stateCapital" value="${capital}" autocorrect="off" spellcheck="false" />
<select data-tip="Dominant culture. Click to change" class="stateCulture hide">${getCultureOptions(
s.culture
)}</select>
@ -728,7 +692,7 @@ function showStatesChart() {
.sum(d => d.area)
.sort((a, b) => b.value - a.value);
const size = 150 + 200 * uiSizeOutput.value;
const size = 150 + 200 * uiSize.value;
const margin = {top: 0, right: -50, bottom: 0, left: -50};
const w = size - margin.left - margin.right;
const h = size - margin.top - margin.bottom;
@ -885,14 +849,6 @@ function recalculateStates(must) {
refreshStatesEditor();
}
function changeStatesGrowthRate() {
const growthRate = +this.value;
byId("statesNeutral").value = growthRate;
byId("statesNeutralNumber").value = growthRate;
tip("Growth rate: " + growthRate);
recalculateStates(false);
}
function randomizeStatesExpansion() {
pack.states.forEach(s => {
if (!s.i || s.removed) return;
@ -959,7 +915,7 @@ function selectStateOnMapClick() {
}
function dragStateBrush() {
const r = +statesManuallyBrush.value;
const r = +statesBrush.value;
d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return;
@ -1002,7 +958,7 @@ function changeStateForSelection(selection) {
function moveStateBrush() {
showMainTip();
const point = d3.mouse(this);
const radius = +statesManuallyBrush.value;
const radius = +statesBrush.value;
moveCircle(point[0], point[1], radius);
}

View file

@ -222,14 +222,14 @@ async function parseLoadedData(data, mapVersion) {
void (function parseSettings() {
const settings = data[1].split("|");
if (settings[0]) applyOption(distanceUnitInput, settings[0]);
if (settings[1]) distanceScale = distanceScaleInput.value = distanceScaleOutput.value = settings[1];
if (settings[1]) distanceScale = distanceScaleInput.value = settings[1];
if (settings[2]) areaUnit.value = settings[2];
if (settings[3]) applyOption(heightUnit, settings[3]);
if (settings[4]) heightExponentInput.value = heightExponentOutput.value = settings[4];
if (settings[4]) heightExponentInput.value = settings[4];
if (settings[5]) temperatureScale.value = settings[5];
// setting 6-11 (scaleBar) are part of style now, kept as "" in newer versions for compatibility
if (settings[12]) populationRate = populationRateInput.value = populationRateOutput.value = settings[12];
if (settings[13]) urbanization = urbanizationInput.value = urbanizationOutput.value = settings[13];
if (settings[12]) populationRate = populationRateInput.value = settings[12];
if (settings[13]) urbanization = urbanizationInput.value = settings[13];
if (settings[14]) mapSizeInput.value = mapSizeOutput.value = minmax(settings[14], 1, 100);
if (settings[15]) latitudeInput.value = latitudeOutput.value = minmax(settings[15], 0, 100);
if (settings[18]) precInput.value = precOutput.value = settings[18];
@ -241,7 +241,7 @@ async function parseLoadedData(data, mapVersion) {
if (settings[21]) hideLabels.checked = +settings[21];
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[24]) urbanDensity = urbanDensityInput.value = +settings[24];
if (settings[25]) longitudeInput.value = longitudeOutput.value = minmax(settings[25] || 50, 0, 100);
})();

View file

@ -1,7 +1,7 @@
"use strict";
window.ReliefIcons = (function () {
const ReliefIcons = function () {
const draw = function () {
TIME && console.time("drawRelief");
terrain.selectAll("*").remove();
@ -124,5 +124,5 @@ window.ReliefIcons = (function () {
return "#relief-" + getOldIcon(type) + "-1"; // simple
}
return ReliefIcons;
return {draw};
})();

View file

@ -457,7 +457,7 @@ window.Religions = (function () {
const lockedReligions = pack.religions?.filter(r => r.i && r.lock && !r.removed) || [];
const folkReligions = generateFolkReligions();
const organizedReligions = generateOrganizedReligions(+religionsInput.value, lockedReligions);
const organizedReligions = generateOrganizedReligions(+religionsNumber.value, lockedReligions);
const namedReligions = specifyReligions([...folkReligions, ...organizedReligions]);
const indexedReligions = combineReligions(namedReligions, lockedReligions);
@ -698,7 +698,8 @@ window.Religions = (function () {
const queue = new PriorityQueue({comparator: (a, b) => a.p - b.p});
const cost = [];
const maxExpansionCost = (cells.i.length / 20) * neutralInput.value; // limit cost for organized religions growth
// limit cost for organized religions growth
const maxExpansionCost = (cells.i.length / 20) * byId("growthRate").valueAsNumber;
religions
.filter(r => r.i && !r.lock && r.type !== "Folk" && !r.removed)

View file

@ -35,7 +35,6 @@ window.Rivers = (function () {
TIME && console.timeEnd("generateRivers");
function drainWater() {
//const MIN_FLUX_TO_FORM_RIVER = 10 * distanceScale;
const MIN_FLUX_TO_FORM_RIVER = 30;
const cellsNumberModifier = (pointsInput.dataset.cells / 10000) ** 0.25;

View file

@ -317,7 +317,7 @@ function editBiomes() {
}
function regenerateIcons() {
ReliefIcons();
ReliefIcons.draw();
if (!layerIsOn("toggleRelief")) toggleRelief();
}
@ -383,7 +383,7 @@ function editBiomes() {
}
function dragBiomeBrush() {
const r = +biomesManuallyBrush.value;
const r = +biomesBrush.value;
d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return;
@ -425,7 +425,7 @@ function editBiomes() {
function moveBiomeBrush() {
showMainTip();
const point = d3.mouse(this);
const radius = +biomesManuallyBrush.value;
const radius = +biomesBrush.value;
moveCircle(point[0], point[1], radius);
}

View file

@ -340,8 +340,8 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
.sum(d => d.population)
.sort((a, b) => b.value - a.value);
const width = 150 + 200 * uiSizeOutput.value;
const height = 150 + 200 * uiSizeOutput.value;
const width = 150 + 200 * uiSize.value;
const height = 150 + 200 * uiSize.value;
const margin = {top: 0, right: -50, bottom: -10, left: -50};
const w = width - margin.left - margin.right;
const h = height - margin.top - margin.bottom;

View file

@ -516,13 +516,14 @@ function fitLegendBox() {
// draw legend with the same data, but using different settings
function redrawLegend() {
if (!legend.select("rect").size()) return;
const name = legend.select("#legendLabel").text();
const data = legend
.attr("data")
.split("|")
.map(l => l.split(","));
drawLegend(name, data);
if (legend.select("rect").size()) {
const name = legend.select("#legendLabel").text();
const data = legend
.attr("data")
.split("|")
.map(l => l.split(","));
drawLegend(name, data);
}
}
function dragLegendBox() {
@ -1251,18 +1252,18 @@ function refreshAllEditors() {
// dynamically loaded editors
async function editStates() {
if (customization) return;
const Editor = await import("../dynamic/editors/states-editor.js?v=1.99.00");
const Editor = await import("../dynamic/editors/states-editor.js?v=1.99.05");
Editor.open();
}
async function editCultures() {
if (customization) return;
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.96.01");
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.99.05");
Editor.open();
}
async function editReligions() {
if (customization) return;
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.96.00");
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.99.05");
Editor.open();
}

View file

@ -90,7 +90,7 @@ function editHeightmap(options) {
if (!sessionStorage.getItem("noExitButtonAnimation")) {
sessionStorage.setItem("noExitButtonAnimation", true);
exitCustomization.style.opacity = 0;
const width = 12 * uiSizeOutput.value * 11;
const width = 12 * uiSize.value * 11;
exitCustomization.style.right = (svgWidth - width) / 2 + "px";
exitCustomization.style.bottom = svgHeight / 2 + "px";
exitCustomization.style.transform = "scale(2)";
@ -136,7 +136,7 @@ function editHeightmap(options) {
return;
}
moveCircle(x, y, brushRadius.valueAsNumber, "#333");
moveCircle(x, y, heightmapBrushRadius.valueAsNumber, "#333");
}
// get user-friendly (real-world) height value from map data
@ -664,7 +664,7 @@ function editHeightmap(options) {
const fromCell = +lineCircle.attr("data-cell");
debug.selectAll("*").remove();
const power = byId("linePower").valueAsNumber;
const power = byId("heightmapLinePower").valueAsNumber;
if (power === 0) return tip("Power should not be zero", false, "error");
const heights = grid.cells.h;
@ -686,7 +686,7 @@ function editHeightmap(options) {
}
function dragBrush() {
const r = brushRadius.valueAsNumber;
const r = heightmapBrushRadius.valueAsNumber;
const [x, y] = d3.mouse(this);
const start = findGridCell(x, y, grid);
@ -704,7 +704,7 @@ function editHeightmap(options) {
}
function changeHeightForSelection(selection, start) {
const power = brushPower.valueAsNumber;
const power = heightmapBrushPower.valueAsNumber;
const interpolate = d3.interpolateRound(power, 1);
const land = changeOnlyLand.checked;

View file

@ -30,7 +30,7 @@ function handleKeyup(event) {
else if (code === "Tab") toggleOptions(event);
else if (code === "Escape") closeAllDialogs();
else if (code === "Delete") removeElementOnKey();
else if (code === "KeyO" && document.getElementById("canvas3d")) toggle3dOptions();
else if (code === "KeyO" && byId("canvas3d")) toggle3dOptions();
else if (ctrl && code === "KeyQ") toggleSaveReminder();
else if (ctrl && code === "KeyS") saveMap("machine");
else if (ctrl && code === "KeyC") saveMap("dropbox");
@ -123,24 +123,21 @@ function allowHotkeys() {
function handleSizeChange(key) {
let brush = null;
if (document.getElementById("brushRadius")?.offsetParent) brush = document.getElementById("brushRadius");
else if (document.getElementById("linePower")?.offsetParent) brush = document.getElementById("linePower");
else if (document.getElementById("biomesManuallyBrush")?.offsetParent)
brush = document.getElementById("biomesManuallyBrush");
else if (document.getElementById("statesManuallyBrush")?.offsetParent)
brush = document.getElementById("statesManuallyBrush");
else if (document.getElementById("provincesManuallyBrush")?.offsetParent)
brush = document.getElementById("provincesManuallyBrush");
else if (document.getElementById("culturesManuallyBrush")?.offsetParent)
brush = document.getElementById("culturesManuallyBrush");
else if (document.getElementById("zonesBrush")?.offsetParent) brush = document.getElementById("zonesBrush");
else if (document.getElementById("religionsManuallyBrush")?.offsetParent)
brush = document.getElementById("religionsManuallyBrush");
if (byId("heightmapBrushRadius")?.offsetParent) brush = byId("heightmapBrushRadius");
else if (byId("heightmapLinePower")?.offsetParent) brush = byId("heightmapLinePower");
else if (byId("biomesBrush")?.offsetParent) brush = byId("biomesBrush");
else if (byId("culturesBrush")?.offsetParent) brush = byId("culturesBrush");
else if (byId("statesBrush")?.offsetParent) brush = byId("statesBrush");
else if (byId("provincesBrush")?.offsetParent) brush = byId("provincesBrush");
else if (byId("religionsBrush")?.offsetParent) brush = byId("religionsBrush");
else if (byId("zonesBrush")?.offsetParent) brush = byId("zonesBrush");
if (brush) {
const change = key === "-" ? -5 : 5;
const value = minmax(+brush.value + change, +brush.min, +brush.max);
brush.value = document.getElementById(brush.id + "Number").value = value;
const min = +brush.getAttribute("min") || 5;
const max = +brush.getAttribute("max") || 100;
const value = +brush.value + change;
brush.value = minmax(value, min, max);
return;
}

View file

@ -93,7 +93,7 @@ function restoreCustomPresets() {
// run on map generation
function applyPreset() {
const preset = localStorage.getItem("preset") || document.getElementById("layersPreset").value;
const preset = localStorage.getItem("preset") || byId("layersPreset").value;
changePreset(preset);
}
@ -113,12 +113,12 @@ function changePreset(preset) {
const isDefault = getDefaultPresets()[preset];
removePresetButton.style.display = isDefault ? "none" : "inline-block";
savePresetButton.style.display = "none";
if (document.getElementById("canvas3d")) setTimeout(ThreeD.update(), 400);
if (byId("canvas3d")) setTimeout(ThreeD.update(), 400);
}
function savePreset() {
prompt("Please provide a preset name", {default: ""}, preset => {
presets[preset] = Array.from(document.getElementById("mapLayers").querySelectorAll("li:not(.buttonoff)"))
presets[preset] = Array.from(byId("mapLayers").querySelectorAll("li:not(.buttonoff)"))
.map(node => node.id)
.sort();
layersPreset.add(new Option(preset, preset, false, true));
@ -143,7 +143,7 @@ function removePreset() {
}
function getCurrentPreset() {
const layers = Array.from(document.getElementById("mapLayers").querySelectorAll("li:not(.buttonoff)"))
const layers = Array.from(byId("mapLayers").querySelectorAll("li:not(.buttonoff)"))
.map(node => node.id)
.sort();
const defaultPresets = getDefaultPresets();
@ -174,7 +174,7 @@ function restoreLayers() {
if (layerIsOn("togglePrec")) drawPrec();
if (layerIsOn("togglePopulation")) drawPopulation();
if (layerIsOn("toggleBiomes")) drawBiomes();
if (layerIsOn("toggleRelief")) ReliefIcons();
if (layerIsOn("toggleRelief")) ReliefIcons.draw();
if (layerIsOn("toggleCultures")) drawCultures();
if (layerIsOn("toggleProvinces")) drawProvinces();
if (layerIsOn("toggleReligions")) drawReligions();
@ -1516,8 +1516,8 @@ function drawCoordinates() {
// conver svg point into viewBox point
function getViewPoint(x, y) {
const view = document.getElementById("viewbox");
const svg = document.getElementById("map");
const view = byId("viewbox");
const svg = byId("map");
const pt = svg.createSVGPoint();
(pt.x = x), (pt.y = y);
return pt.matrixTransform(view.getScreenCTM().inverse());
@ -1541,7 +1541,7 @@ function toggleCompass(event) {
function toggleRelief(event) {
if (!layerIsOn("toggleRelief")) {
turnButtonOn("toggleRelief");
if (!terrain.selectAll("*").size()) ReliefIcons();
if (!terrain.selectAll("*").size()) ReliefIcons.draw();
$("#terrain").fadeIn();
if (event && isCtrlClick(event)) editStyle("terrain");
} else {
@ -1907,21 +1907,21 @@ function drawEmblems() {
const getStateEmblemsSize = () => {
const startSize = minmax((graphHeight + graphWidth) / 40, 10, 100);
const statesMod = 1 + validStates.length / 100 - (15 - validStates.length) / 200; // states number modifier
const sizeMod = +document.getElementById("emblemsStateSizeInput").value || 1;
const sizeMod = +byId("emblemsStateSizeInput").value || 1;
return rn((startSize / statesMod) * sizeMod); // target size ~50px on 1536x754 map with 15 states
};
const getProvinceEmblemsSize = () => {
const startSize = minmax((graphHeight + graphWidth) / 100, 5, 70);
const provincesMod = 1 + validProvinces.length / 1000 - (115 - validProvinces.length) / 1000; // states number modifier
const sizeMod = +document.getElementById("emblemsProvinceSizeInput").value || 1;
const sizeMod = +byId("emblemsProvinceSizeInput").value || 1;
return rn((startSize / provincesMod) * sizeMod); // target size ~20px on 1536x754 map with 115 provinces
};
const getBurgEmblemSize = () => {
const startSize = minmax((graphHeight + graphWidth) / 185, 2, 50);
const burgsMod = 1 + validBurgs.length / 1000 - (450 - validBurgs.length) / 1000; // states number modifier
const sizeMod = +document.getElementById("emblemsBurgSizeInput").value || 1;
const sizeMod = +byId("emblemsBurgSizeInput").value || 1;
return rn((startSize / burgsMod) * sizeMod); // target size ~8.5px on 1536x754 map with 450 burgs
};
@ -2020,17 +2020,17 @@ function toggleVignette(event) {
}
function layerIsOn(el) {
const buttonoff = document.getElementById(el).classList.contains("buttonoff");
const buttonoff = byId(el).classList.contains("buttonoff");
return !buttonoff;
}
function turnButtonOff(el) {
document.getElementById(el).classList.add("buttonoff");
byId(el).classList.add("buttonoff");
getCurrentPreset();
}
function turnButtonOn(el) {
document.getElementById(el).classList.remove("buttonoff");
byId(el).classList.remove("buttonoff");
getCurrentPreset();
}

View file

@ -66,12 +66,18 @@ document
.querySelectorAll(".tabcontent")
.forEach(e => (e.style.display = "none"));
if (id === "layersTab") layersContent.style.display = "block";
else if (id === "styleTab") styleContent.style.display = "block";
else if (id === "optionsTab") optionsContent.style.display = "block";
else if (id === "toolsTab")
if (id === "layersTab") {
layersContent.style.display = "block";
} else if (id === "styleTab") {
styleContent.style.display = "block";
selectStyleElement();
} else if (id === "optionsTab") {
optionsContent.style.display = "block";
} else if (id === "toolsTab") {
customization === 1 ? (customizationMenu.style.display = "block") : (toolsContent.style.display = "block");
else if (id === "aboutTab") aboutContent.style.display = "block";
} else if (id === "aboutTab") {
aboutContent.style.display = "block";
}
});
// show popup with a list of Patreon supportes (updated manually)
@ -125,9 +131,9 @@ optionsContent.addEventListener("input", event => {
if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange();
else if (id === "pointsInput") changeCellsDensity(+value);
else if (id === "culturesSet") changeCultureSet();
else if (id === "regionsInput" || id === "regionsOutput") changeStatesNumber(value);
else if (id === "statesNumber") changeStatesNumber(value);
else if (id === "emblemShape") changeEmblemShape(value);
else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value);
else if (id === "tooltipSize") changeTooltipSize(value);
else if (id === "themeHueInput") changeThemeHue(value);
else if (id === "themeColorInput") changeDialogsTheme(themeColorInput.value, transparencyInput.value);
else if (id === "transparencyInput") changeDialogsTheme(themeColorInput.value, value);
@ -137,7 +143,7 @@ optionsContent.addEventListener("change", event => {
const {id, value} = event.target;
if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value);
else if (id === "optionsSeed") generateMapWithSeed("seed change");
else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUiSize(value);
else if (id === "uiSize") changeUiSize(+value);
else if (id === "shapeRendering") setRendering(value);
else if (id === "yearInput") changeYear();
else if (id === "eraInput") changeEra();
@ -389,18 +395,18 @@ function changeEmblemShape(emblemShape) {
}
function changeStatesNumber(value) {
regionsOutput.style.color = +value ? null : "#b12117";
byId("statesNumber").style.color = +value ? null : "#b12117";
burgLabels.select("#capitals").attr("data-size", Math.max(rn(6 - value / 20), 3));
labels.select("#countries").attr("data-size", Math.max(rn(18 - value / 6), 4));
}
function changeUiSize(value) {
if (isNaN(+value) || +value < 0.5) return;
if (isNaN(value) || value < 0.5) return;
const max = getUImaxSize();
if (+value > max) value = max;
if (value > max) value = max;
uiSizeInput.value = uiSizeOutput.value = value;
uiSize.value = value;
document.getElementsByTagName("body")[0].style.fontSize = rn(value * 10, 2) + "px";
byId("options").style.width = value * 300 + "px";
}
@ -427,7 +433,7 @@ function changeThemeHue(hue) {
// change color and transparency for modal windows
function changeDialogsTheme(themeColor, transparency) {
transparencyInput.value = transparencyOutput.value = transparency;
transparencyInput.value = transparency;
const alpha = (100 - +transparency) / 100;
const alphaReduced = Math.min(alpha + 0.3, 1);
@ -489,11 +495,11 @@ function resetLanguage() {
if (!languageSelect.value) return;
languageSelect.value = "en";
languageSelect.dispatchEvent(new Event("change"));
languageSelect.handleChange(new Event("change"));
// do once again to actually reset the language
languageSelect.value = "en";
languageSelect.dispatchEvent(new Event("change"));
languageSelect.handleChange(new Event("change"));
}
function changeZoomExtent(value) {
@ -533,7 +539,6 @@ function applyStoredOptions() {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key === "speakerVoice") continue;
const input = byId(key + "Input") || byId(key);
@ -560,8 +565,8 @@ function applyStoredOptions() {
if (stored("tooltipSize")) changeTooltipSize(stored("tooltipSize"));
if (stored("regions")) changeStatesNumber(stored("regions"));
uiSizeInput.max = uiSizeOutput.max = getUImaxSize();
if (stored("uiSize")) changeUiSize(stored("uiSize"));
uiSize.max = uiSize.max = getUImaxSize();
if (stored("uiSize")) changeUiSize(+stored("uiSize"));
else changeUiSize(minmax(rn(mapWidthInput.value / 1280, 1), 1, 2.5));
// search params overwrite stored and default options
@ -586,15 +591,15 @@ function randomizeOptions() {
// 'Options' settings
if (randomize || !locked("points")) changeCellsDensity(4); // reset to default, no need to randomize
if (randomize || !locked("template")) randomizeHeightmapTemplate();
if (randomize || !locked("regions")) regionsInput.value = regionsOutput.value = gauss(18, 5, 2, 30);
if (randomize || !locked("provinces")) provincesInput.value = provincesOutput.value = gauss(20, 10, 20, 100);
if (randomize || !locked("statesNumber")) statesNumber.value = gauss(18, 5, 2, 30);
if (randomize || !locked("provincesRatio")) provincesRatio.value = gauss(20, 10, 20, 100);
if (randomize || !locked("manors")) {
manorsInput.value = 1000;
manorsOutput.value = "auto";
}
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("religionsNumber")) religionsNumber.value = gauss(6, 3, 2, 10);
if (randomize || !locked("sizeVariety")) sizeVariety.value = gauss(4, 2, 0, 10, 1);
if (randomize || !locked("growthRate")) growthRate.value = rn(1 + Math.random(), 1);
if (randomize || !locked("cultures")) culturesInput.value = culturesOutput.value = gauss(12, 3, 5, 30);
if (randomize || !locked("culturesSet")) randomizeCultureSet();
@ -606,8 +611,7 @@ function randomizeOptions() {
// 'Units Editor' settings
const US = navigator.language === "en-US";
if (randomize || !locked("distanceScale"))
distanceScale = distanceScaleOutput.value = distanceScaleInput.value = gauss(3, 1, 1, 5);
if (randomize || !locked("distanceScale")) distanceScale = distanceScaleInput.value = gauss(3, 1, 1, 5);
if (!stored("distanceUnit")) distanceUnitInput.value = US ? "mi" : "km";
if (!stored("heightUnit")) heightUnit.value = US ? "ft" : "m";
if (!stored("temperatureScale")) temperatureScale.value = US ? "°F" : "°C";

View file

@ -628,8 +628,8 @@ function editProvinces() {
.parentId(d => d.state)(data)
.sum(d => d.area);
const width = 300 + 300 * uiSizeOutput.value,
height = 90 + 90 * uiSizeOutput.value;
const width = 300 + 300 * uiSize.value,
height = 90 + 90 * uiSize.value;
const margin = {top: 10, right: 10, bottom: 0, left: 10};
const w = width - margin.left - margin.right;
const h = height - margin.top - margin.bottom;
@ -879,7 +879,7 @@ function editProvinces() {
}
function dragBrush() {
const r = +provincesManuallyBrush.value;
const r = +provincesBrush.value;
d3.event.on("drag", () => {
if (!d3.event.dx && !d3.event.dy) return;
@ -937,7 +937,7 @@ function editProvinces() {
function moveBrush() {
showMainTip();
const point = d3.mouse(this);
const radius = +provincesManuallyBrush.value;
const radius = +provincesBrush.value;
moveCircle(point[0], point[1], radius);
}

View file

@ -72,6 +72,7 @@ function getColorScheme(scheme = "bright") {
// Toggle style sections on element select
styleElementSelect.addEventListener("change", selectStyleElement);
function selectStyleElement() {
const styleElement = styleElementSelect.value;
let el = d3.select("#" + styleElement);
@ -92,7 +93,7 @@ function selectStyleElement() {
// opacity
if (!["landmass", "ocean", "regions", "legend"].includes(styleElement)) {
styleOpacity.style.display = "block";
styleOpacityInput.value = styleOpacityOutput.value = el.attr("opacity") || 1;
styleOpacityInput.value = el.attr("opacity") || 1;
}
// filter
@ -129,7 +130,7 @@ function selectStyleElement() {
styleStroke.style.display = "block";
styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke");
styleStrokeWidth.style.display = "block";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || "";
styleStrokeWidthInput.value = el.attr("stroke-width") || 0;
}
// stroke dash
@ -176,9 +177,9 @@ function selectStyleElement() {
styleHeightmapRenderOcean.checked = +el.attr("data-render");
styleHeightmapScheme.value = el.attr("scheme");
styleHeightmapTerracingInput.value = styleHeightmapTerracingOutput.value = el.attr("terracing");
styleHeightmapSkipInput.value = styleHeightmapSkipOutput.value = el.attr("skip");
styleHeightmapSimplificationInput.value = styleHeightmapSimplificationOutput.value = el.attr("relax");
styleHeightmapTerracing.value = el.attr("terracing");
styleHeightmapSkip.value = el.attr("skip");
styleHeightmapSimplification.value = el.attr("relax");
styleHeightmapCurve.value = el.attr("curve");
}
@ -201,13 +202,13 @@ function selectStyleElement() {
const tr = parseTransform(compass.select("use").attr("transform"));
styleCompassShiftX.value = tr[0];
styleCompassShiftY.value = tr[1];
styleCompassSizeInput.value = styleCompassSizeOutput.value = tr[2];
styleCompassSizeInput.value = tr[2];
}
if (styleElement === "terrain") {
styleRelief.style.display = "block";
styleReliefSizeOutput.innerHTML = styleReliefSizeInput.value = terrain.attr("size");
styleReliefDensityOutput.innerHTML = styleReliefDensityInput.value = terrain.attr("density");
styleReliefSize.value = terrain.attr("size") || 1;
styleReliefDensity.value = terrain.attr("density") || 0.4;
styleReliefSet.value = terrain.attr("set");
}
@ -220,17 +221,16 @@ function selectStyleElement() {
.select("#urban")
.attr("stroke");
styleStrokeWidth.style.display = "block";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || "";
styleStrokeWidthInput.value = el.attr("stroke-width") || 0;
}
if (styleElement === "regions") {
styleStates.style.display = "block";
styleStatesBodyOpacity.value = styleStatesBodyOpacityOutput.value = statesBody.attr("opacity") || 1;
styleStatesBodyOpacity.value = statesBody.attr("opacity") || 1;
styleStatesBodyFilter.value = statesBody.attr("filter") || "";
styleStatesHaloWidth.value = styleStatesHaloWidthOutput.value = statesHalo.attr("data-width") || 10;
styleStatesHaloOpacity.value = styleStatesHaloOpacityOutput.value = statesHalo.attr("opacity") || 1;
const blur = parseFloat(statesHalo.attr("filter")?.match(/blur\(([^)]+)\)/)?.[1]) || 0;
styleStatesHaloBlur.value = styleStatesHaloBlurOutput.value = blur;
styleStatesHaloWidth.value = statesHalo.attr("data-width") || 10;
styleStatesHaloOpacity.value = statesHalo.attr("opacity") || 1;
styleStatesHaloBlur.value = parseFloat(statesHalo.attr("filter")?.match(/blur\(([^)]+)\)/)?.[1]) || 0;
}
if (styleElement === "labels") {
@ -243,7 +243,7 @@ function selectStyleElement() {
styleVisibility.style.display = "block";
styleFillInput.value = styleFillOutput.value = el.attr("fill") || "#3e3e4b";
styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke") || "#3a3a3a";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || 0;
styleStrokeWidthInput.value = el.attr("stroke-width") || 0;
styleShadowInput.value = el.style("text-shadow") || "white 0 0 4px";
styleFont.style.display = "block";
@ -258,7 +258,7 @@ function selectStyleElement() {
styleFont.style.display = "block";
styleSelectFont.value = el.attr("font-family");
styleFontSize.value = el.attr("data-size");
styleFontSize.value = el.attr("font-size");
}
if (styleElement == "burgIcons") {
@ -269,7 +269,7 @@ function selectStyleElement() {
styleRadius.style.display = "block";
styleFillInput.value = styleFillOutput.value = el.attr("fill") || "#ffffff";
styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke") || "#3e3e4b";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || 0.24;
styleStrokeWidthInput.value = el.attr("stroke-width") || 0.24;
styleStrokeDasharrayInput.value = el.attr("stroke-dasharray") || "";
styleStrokeLinecapInput.value = el.attr("stroke-linecap") || "inherit";
styleRadiusInput.value = el.attr("size") || 1;
@ -282,7 +282,7 @@ function selectStyleElement() {
styleIconSize.style.display = "block";
styleFillInput.value = styleFillOutput.value = el.attr("fill") || "#ffffff";
styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke") || "#3e3e4b";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || 0.24;
styleStrokeWidthInput.value = el.attr("stroke-width") || 0.24;
styleIconSizeInput.value = el.attr("size") || 2;
}
@ -292,12 +292,13 @@ function selectStyleElement() {
styleSize.style.display = "block";
styleLegend.style.display = "block";
styleLegendColItemsOutput.value = styleLegendColItems.value = el.attr("data-columns");
styleLegendBackOutput.value = styleLegendBack.value = el.select("#legendBox").attr("fill");
styleLegendOpacityOutput.value = styleLegendOpacity.value = el.select("#legendBox").attr("fill-opacity");
styleLegendColItems.value = el.attr("data-columns");
const legendBox = el.select("#legendBox");
styleLegendBack.value = styleLegendBackOutput.value = legendBox.size() ? legendBox.attr("fill") : "#ffffff";
styleLegendOpacity.value = legendBox.size() ? legendBox.attr("fill-opacity") : 1;
styleStrokeInput.value = styleStrokeOutput.value = el.attr("stroke") || "#111111";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || 0.5;
styleStrokeWidthInput.value = el.attr("stroke-width") || 0.5;
styleFont.style.display = "block";
styleSelectFont.value = el.attr("font-family");
@ -308,18 +309,17 @@ function selectStyleElement() {
styleOcean.style.display = "block";
styleOceanFill.value = styleOceanFillOutput.value = oceanLayers.select("#oceanBase").attr("fill");
styleOceanPattern.value = byId("oceanicPattern")?.getAttribute("href");
styleOceanPatternOpacity.value = styleOceanPatternOpacityOutput.value =
byId("oceanicPattern").getAttribute("opacity") || 1;
styleOceanPatternOpacity.value = byId("oceanicPattern").getAttribute("opacity") || 1;
outlineLayers.value = oceanLayers.attr("layers");
}
if (styleElement === "temperature") {
styleStrokeWidth.style.display = "block";
styleTemperature.style.display = "block";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || "";
styleTemperatureFillOpacityInput.value = styleTemperatureFillOpacityOutput.value = el.attr("fill-opacity") || 0.1;
styleStrokeWidthInput.value = el.attr("stroke-width") || "";
styleTemperatureFillOpacityInput.value = el.attr("fill-opacity") || 0.1;
styleTemperatureFillInput.value = styleTemperatureFillOutput.value = el.attr("fill") || "#000";
styleTemperatureFontSizeInput.value = styleTemperatureFontSizeOutput.value = el.attr("font-size") || "8px";
styleTemperatureFontSizeInput.value = el.attr("font-size") || "8px";
}
if (styleElement === "coordinates") {
@ -329,14 +329,14 @@ function selectStyleElement() {
if (styleElement === "armies") {
styleArmies.style.display = "block";
styleArmiesFillOpacity.value = styleArmiesFillOpacityOutput.value = el.attr("fill-opacity");
styleArmiesSize.value = styleArmiesSizeOutput.value = el.attr("box-size");
styleArmiesFillOpacity.value = el.attr("fill-opacity");
styleArmiesSize.value = el.attr("box-size");
}
if (styleElement === "emblems") {
styleEmblems.style.display = "block";
styleStrokeWidth.style.display = "block";
styleStrokeWidthInput.value = styleStrokeWidthOutput.value = el.attr("stroke-width") || 1;
styleStrokeWidthInput.value = el.attr("stroke-width") || 1;
}
// update group options
@ -372,11 +372,9 @@ function selectStyleElement() {
const scaleBarBack = el.select("#scaleBarBack");
if (scaleBarBack.size()) {
styleScaleBarBackgroundOpacityInput.value = styleScaleBarBackgroundOpacityOutput.value =
scaleBarBack.attr("opacity");
styleScaleBarBackgroundFillInput.value = styleScaleBarBackgroundFillOutput.value = scaleBarBack.attr("fill");
styleScaleBarBackgroundStrokeInput.value = styleScaleBarBackgroundStrokeOutput.value =
scaleBarBack.attr("stroke");
styleScaleBarBackgroundOpacity.value = scaleBarBack.attr("opacity");
styleScaleBarBackgroundFill.value = styleScaleBarBackgroundFillOutput.value = scaleBarBack.attr("fill");
styleScaleBarBackgroundStroke.value = styleScaleBarBackgroundStrokeOutput.value = scaleBarBack.attr("stroke");
styleScaleBarBackgroundStrokeWidth.value = scaleBarBack.attr("stroke-width");
styleScaleBarBackgroundFilter.value = scaleBarBack.attr("filter");
styleScaleBarBackgroundPaddingTop.value = scaleBarBack.attr("data-top");
@ -398,7 +396,7 @@ function selectStyleElement() {
styleVignetteHeight.value = digit(maskRect.getAttribute("height"));
styleVignetteRx.value = digit(maskRect.getAttribute("rx"));
styleVignetteRy.value = digit(maskRect.getAttribute("ry"));
styleVignetteBlur.value = styleVignetteBlurOutput.value = digit(maskRect.getAttribute("filter"));
styleVignetteBlur.value = digit(maskRect.getAttribute("filter"));
}
}
}
@ -424,9 +422,8 @@ styleStrokeInput.addEventListener("input", function () {
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});
styleStrokeWidthInput.addEventListener("input", function () {
styleStrokeWidthOutput.value = this.value;
getEl().attr("stroke-width", +this.value);
styleStrokeWidthInput.addEventListener("input", e => {
getEl().attr("stroke-width", e.target.value);
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});
@ -440,9 +437,8 @@ styleStrokeLinecapInput.addEventListener("change", function () {
if (styleElementSelect.value === "gridOverlay" && layerIsOn("toggleGrid")) drawGrid();
});
styleOpacityInput.addEventListener("input", function () {
styleOpacityOutput.value = this.value;
getEl().attr("opacity", this.value);
styleOpacityInput.addEventListener("input", e => {
getEl().attr("opacity", e.target.value);
});
styleFilterInput.addEventListener("change", function () {
@ -537,9 +533,8 @@ styleOceanPattern.addEventListener("change", function () {
byId("oceanicPattern")?.setAttribute("href", this.value);
});
styleOceanPatternOpacity.addEventListener("input", function () {
byId("oceanicPattern").setAttribute("opacity", this.value);
styleOceanPatternOpacityOutput.value = this.value;
styleOceanPatternOpacity.addEventListener("input", e => {
byId("oceanicPattern").setAttribute("opacity", e.target.value);
});
outlineLayers.addEventListener("change", function () {
@ -672,81 +667,74 @@ openCreateHeightmapSchemeButton.addEventListener("click", function () {
});
});
styleHeightmapRenderOcean.addEventListener("change", function () {
getEl().attr("data-render", +this.checked);
styleHeightmapRenderOcean.addEventListener("change", e => {
const checked = +e.target.checked;
getEl().attr("data-render", checked);
drawHeightmap();
});
styleHeightmapTerracingInput.addEventListener("input", function () {
getEl().attr("terracing", this.value);
styleHeightmapTerracing.addEventListener("input", e => {
getEl().attr("terracing", e.target.value);
drawHeightmap();
});
styleHeightmapSkipInput.addEventListener("input", function () {
getEl().attr("skip", this.value);
styleHeightmapSkip.addEventListener("input", e => {
getEl().attr("skip", e.target.value);
drawHeightmap();
});
styleHeightmapSimplificationInput.addEventListener("input", function () {
getEl().attr("relax", this.value);
styleHeightmapSimplification.addEventListener("input", e => {
getEl().attr("relax", e.target.value);
drawHeightmap();
});
styleHeightmapCurve.addEventListener("change", function () {
getEl().attr("curve", this.value);
styleHeightmapCurve.addEventListener("change", e => {
getEl().attr("curve", e.target.value);
drawHeightmap();
});
styleReliefSet.addEventListener("change", function () {
terrain.attr("set", this.value);
ReliefIcons();
styleReliefSet.addEventListener("change", e => {
terrain.attr("set", e.target.value);
ReliefIcons.draw();
if (!layerIsOn("toggleRelief")) toggleRelief();
});
styleReliefSizeInput.addEventListener("change", function () {
terrain.attr("size", this.value);
styleReliefSizeOutput.value = this.value;
ReliefIcons();
styleReliefSize.addEventListener("change", e => {
terrain.attr("size", e.target.value);
ReliefIcons.draw();
if (!layerIsOn("toggleRelief")) toggleRelief();
});
styleReliefDensityInput.addEventListener("change", function () {
terrain.attr("density", this.value);
styleReliefDensityOutput.value = this.value;
ReliefIcons();
styleReliefDensity.addEventListener("change", e => {
terrain.attr("density", e.target.value);
ReliefIcons.draw();
if (!layerIsOn("toggleRelief")) toggleRelief();
});
styleTemperatureFillOpacityInput.addEventListener("input", function () {
temperature.attr("fill-opacity", this.value);
styleTemperatureFillOpacityOutput.value = this.value;
styleTemperatureFillOpacityInput.addEventListener("input", e => {
temperature.attr("fill-opacity", e.target.value);
});
styleTemperatureFontSizeInput.addEventListener("input", function () {
temperature.attr("font-size", this.value + "px");
styleTemperatureFontSizeOutput.value = this.value + "px";
styleTemperatureFontSizeInput.addEventListener("input", e => {
temperature.attr("font-size", e.target.value + "px");
});
styleTemperatureFillInput.addEventListener("input", function () {
temperature.attr("fill", this.value);
styleTemperatureFillOutput.value = this.value;
styleTemperatureFillInput.addEventListener("input", e => {
temperature.attr("fill", e.target.value);
styleTemperatureFillOutput.value = e.target.value;
});
stylePopulationRuralStrokeInput.addEventListener("input", function () {
stylePopulationRuralStrokeInput.addEventListener("input", e => {
population.select("#rural").attr("stroke", this.value);
stylePopulationRuralStrokeOutput.value = this.value;
});
stylePopulationUrbanStrokeInput.addEventListener("input", function () {
stylePopulationUrbanStrokeInput.addEventListener("input", e => {
population.select("#urban").attr("stroke", this.value);
stylePopulationUrbanStrokeOutput.value = this.value;
});
styleCompassSizeInput.addEventListener("input", function () {
styleCompassSizeOutput.value = this.value;
shiftCompass();
});
styleCompassSizeInput.addEventListener("input", shiftCompass);
styleCompassShiftX.addEventListener("input", shiftCompass);
styleCompassShiftY.addEventListener("input", shiftCompass);
@ -755,20 +743,18 @@ function shiftCompass() {
compass.select("use").attr("transform", tr);
}
styleLegendColItems.addEventListener("input", function () {
styleLegendColItemsOutput.value = this.value;
legend.select("#legendBox").attr("data-columns", this.value);
styleLegendColItems.addEventListener("input", e => {
legend.select("#legendBox").attr("data-columns", e.target.value);
redrawLegend();
});
styleLegendBack.addEventListener("input", function () {
styleLegendBackOutput.value = this.value;
legend.select("#legendBox").attr("fill", this.value);
styleLegendBack.addEventListener("input", e => {
styleLegendBackOutput.value = e.target.value;
legend.select("#legendBox").attr("fill", e.target.value);
});
styleLegendOpacity.addEventListener("input", function () {
styleLegendOpacityOutput.value = this.value;
legend.select("#legendBox").attr("fill-opacity", this.value);
styleLegendOpacity.addEventListener("input", e => {
legend.select("#legendBox").attr("fill-opacity", e.target.value);
});
styleSelectFont.addEventListener("change", changeFont);
@ -829,13 +815,13 @@ styleFontSize.addEventListener("change", function () {
});
styleFontPlus.addEventListener("click", function () {
const size = +getEl().attr("data-size") + 1;
changeFontSize(getEl(), Math.min(size, 999));
const current = +styleFontSize.value || 12;
changeFontSize(getEl(), Math.min(current + 1, 999));
});
styleFontMinus.addEventListener("click", function () {
const size = +getEl().attr("data-size") - 1;
changeFontSize(getEl(), Math.max(size, 1));
const current = +styleFontSize.value || 12;
changeFontSize(getEl(), Math.max(current - 1, 1));
});
function changeFontSize(el, size) {
@ -921,39 +907,37 @@ function changeIconSize(size, group) {
styleIconSizeInput.value = size;
}
styleStatesBodyOpacity.addEventListener("input", function () {
styleStatesBodyOpacityOutput.value = this.value;
statesBody.attr("opacity", this.value);
styleStatesBodyOpacity.addEventListener("input", e => {
statesBody.attr("opacity", e.target.value);
});
styleStatesBodyFilter.addEventListener("change", function () {
statesBody.attr("filter", this.value);
});
styleStatesHaloWidth.addEventListener("input", function () {
styleStatesHaloWidthOutput.value = this.value;
statesHalo.attr("data-width", this.value).attr("stroke-width", this.value);
styleStatesHaloWidth.addEventListener("input", e => {
const value = e.target.value;
statesHalo.attr("data-width", value).attr("stroke-width", value);
});
styleStatesHaloOpacity.addEventListener("input", function () {
styleStatesHaloOpacityOutput.value = this.value;
statesHalo.attr("opacity", this.value);
styleStatesHaloOpacity.addEventListener("input", e => {
statesHalo.attr("opacity", e.target.value);
});
styleStatesHaloBlur.addEventListener("input", function () {
styleStatesHaloBlurOutput.value = this.value;
const blur = +this.value > 0 ? `blur(${this.value}px)` : null;
styleStatesHaloBlur.addEventListener("input", e => {
const value = Number(e.target.value);
const blur = value > 0 ? `blur(${value}px)` : null;
statesHalo.attr("filter", blur);
});
styleArmiesFillOpacity.addEventListener("input", function () {
armies.attr("fill-opacity", this.value);
styleArmiesFillOpacityOutput.value = this.value;
styleArmiesFillOpacity.addEventListener("input", e => {
armies.attr("fill-opacity", e.target.value);
});
styleArmiesSize.addEventListener("input", function () {
armies.attr("box-size", this.value).attr("font-size", this.value * 2);
styleArmiesSizeOutput.value = this.value;
styleArmiesSize.addEventListener("input", e => {
const value = Number(e.target.value);
armies.attr("box-size", value).attr("font-size", value * 2);
armies.selectAll("g").remove(); // clear armies layer
pack.states.forEach(s => {
if (!s.i || s.removed || !s.military.length) return;
@ -1029,7 +1013,7 @@ styleVignettePreset.addEventListener("change", function () {
const vignette = byId("vignette");
if (vignette) {
styleOpacityInput.value = styleOpacityOutput.value = vignette.getAttribute("opacity");
styleOpacityInput.value = vignette.getAttribute("opacity");
styleFillInput.value = styleFillOutput.value = vignette.getAttribute("fill");
styleFilterInput.value = vignette.getAttribute("filter");
}
@ -1043,37 +1027,36 @@ styleVignettePreset.addEventListener("change", function () {
styleVignetteHeight.value = digit(maskRect.getAttribute("height"));
styleVignetteRx.value = digit(maskRect.getAttribute("rx"));
styleVignetteRy.value = digit(maskRect.getAttribute("ry"));
styleVignetteBlur.value = styleVignetteBlurOutput.value = digit(maskRect.getAttribute("filter"));
styleVignetteBlur.value = digit(maskRect.getAttribute("filter"));
}
});
styleVignetteX.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("x", `${this.value}%`);
styleVignetteX.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("x", `${e.target.value}%`);
});
styleVignetteWidth.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("width", `${this.value}%`);
styleVignetteWidth.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("width", `${e.target.value}%`);
});
styleVignetteY.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("y", `${this.value}%`);
styleVignetteY.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("y", `${e.target.value}%`);
});
styleVignetteHeight.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("height", `${this.value}%`);
styleVignetteHeight.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("height", `${e.target.value}%`);
});
styleVignetteRx.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("rx", `${this.value}%`);
styleVignetteRx.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("rx", `${e.target.value}%`);
});
styleVignetteRy.addEventListener("input", function () {
byId("vignette-rect")?.setAttribute("ry", `${this.value}%`);
styleVignetteRy.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("ry", `${e.target.value}%`);
});
styleVignetteBlur.addEventListener("input", function () {
styleVignetteBlurOutput.value = this.value;
byId("vignette-rect")?.setAttribute("filter", `blur(${this.value}px)`);
styleVignetteBlur.addEventListener("input", e => {
byId("vignette-rect")?.setAttribute("filter", `blur(${e.target.value}px)`);
});
styleScaleBar.addEventListener("input", function (event) {
@ -1087,9 +1070,9 @@ styleScaleBar.addEventListener("input", function (event) {
else if (id === "styleScaleBarPositionX") scaleBar.attr("data-x", value);
else if (id === "styleScaleBarPositionY") scaleBar.attr("data-y", value);
else if (id === "styleScaleBarLabel") scaleBar.attr("data-label", value);
else if (id === "styleScaleBarBackgroundOpacityInput") scaleBarBack.attr("opacity", value);
else if (id === "styleScaleBarBackgroundFillInput") scaleBarBack.attr("fill", value);
else if (id === "styleScaleBarBackgroundStrokeInput") scaleBarBack.attr("stroke", value);
else if (id === "styleScaleBarBackgroundOpacity") scaleBarBack.attr("opacity", value);
else if (id === "styleScaleBarBackgroundFill") scaleBarBack.attr("fill", value);
else if (id === "styleScaleBarBackgroundStroke") scaleBarBack.attr("stroke", value);
else if (id === "styleScaleBarBackgroundStrokeWidth") scaleBarBack.attr("stroke-width", value);
else if (id === "styleScaleBarBackgroundFilter") scaleBarBack.attr("filter", value);
else if (id === "styleScaleBarBackgroundPaddingTop") scaleBarBack.attr("data-top", value);

View file

@ -258,15 +258,8 @@ window.UISubmap = (function () {
byId("latitudeInput").value = latitudeOutput.value;
// fix scale
distanceScale =
distanceScaleInput.value =
distanceScaleOutput.value =
rn((distanceScale = distanceScaleOutput.value / scale), 2);
populationRateInput.value = populationRateOutput.value = rn(
(populationRate = populationRateOutput.value / scale),
2
);
distanceScale = distanceScaleInput.value = rn(distanceScaleInput.value / scale, 2);
populationRate = populationRateInput.value = rn(populationRateInput.value / scale, 2);
customization = 0;
startResample(options);

View file

@ -77,7 +77,7 @@ toolsContent.addEventListener("click", function (event) {
function processFeatureRegeneration(event, button) {
if (button === "regenerateStateLabels") drawStateLabels();
else if (button === "regenerateReliefIcons") {
ReliefIcons();
ReliefIcons.draw();
if (!layerIsOn("toggleRelief")) toggleRelief();
} else if (button === "regenerateRoutes") {
regenerateRoutes();
@ -176,7 +176,7 @@ function recreateStates() {
const localSeed = generateSeed();
Math.random = aleaPRNG(localSeed);
const statesCount = +regionsOutput.value;
const statesCount = +byId("").value;
if (!statesCount) {
tip(`<i>States Number</i> option value is zero. No counties are generated`, false, "error");
return null;
@ -198,7 +198,7 @@ function recreateStates() {
const lockedStatesIds = lockedStates.map(s => s.i);
const lockedStatesCapitals = lockedStates.map(s => s.capital);
if (lockedStates.length === validStates.length) {
if (validStates.length && lockedStates.length === validStates.length) {
tip("Unable to regenerate as all states are locked", false, "error");
return null;
}
@ -317,7 +317,7 @@ function recreateStates() {
: pack.cultures[culture].type === "Nomadic"
? "Generic"
: pack.cultures[culture].type;
const expansionism = rn(Math.random() * powerInput.value + 1, 1);
const expansionism = rn(Math.random() * byId("sizeVariety").value + 1, 1);
const cultureType = pack.cultures[culture].type;
const coa = COA.generate(capital.coa, 0.3, null, cultureType);

View file

@ -17,27 +17,22 @@ function editUnits() {
};
// add listeners
byId("distanceUnitInput").addEventListener("change", changeDistanceUnit);
byId("distanceScaleOutput").addEventListener("input", changeDistanceScale);
byId("distanceScaleInput").addEventListener("change", changeDistanceScale);
byId("heightUnit").addEventListener("change", changeHeightUnit);
byId("heightExponentInput").addEventListener("input", changeHeightExponent);
byId("heightExponentOutput").addEventListener("input", changeHeightExponent);
byId("temperatureScale").addEventListener("change", changeTemperatureScale);
byId("distanceUnitInput").on("change", changeDistanceUnit);
byId("distanceScaleInput").on("change", changeDistanceScale);
byId("heightUnit").on("change", changeHeightUnit);
byId("heightExponentInput").on("input", changeHeightExponent);
byId("temperatureScale").on("change", changeTemperatureScale);
byId("populationRateOutput").addEventListener("input", changePopulationRate);
byId("populationRateInput").addEventListener("change", changePopulationRate);
byId("urbanizationOutput").addEventListener("input", changeUrbanizationRate);
byId("urbanizationInput").addEventListener("change", changeUrbanizationRate);
byId("urbanDensityOutput").addEventListener("input", changeUrbanDensity);
byId("urbanDensityInput").addEventListener("change", changeUrbanDensity);
byId("populationRateInput").on("change", changePopulationRate);
byId("urbanizationInput").on("change", changeUrbanizationRate);
byId("urbanDensityInput").on("change", changeUrbanDensity);
byId("addLinearRuler").addEventListener("click", addRuler);
byId("addOpisometer").addEventListener("click", toggleOpisometerMode);
byId("addRouteOpisometer").addEventListener("click", toggleRouteOpisometerMode);
byId("addPlanimeter").addEventListener("click", togglePlanimeterMode);
byId("removeRulers").addEventListener("click", removeAllRulers);
byId("unitsRestore").addEventListener("click", restoreDefaultUnits);
byId("addLinearRuler").on("click", addRuler);
byId("addOpisometer").on("click", toggleOpisometerMode);
byId("addRouteOpisometer").on("click", toggleRouteOpisometerMode);
byId("addPlanimeter").on("click", togglePlanimeterMode);
byId("removeRulers").on("click", removeAllRulers);
byId("unitsRestore").on("click", restoreDefaultUnits);
function changeDistanceUnit() {
if (this.value === "custom_name") {
@ -92,7 +87,6 @@ function editUnits() {
function restoreDefaultUnits() {
distanceScale = 3;
byId("distanceScaleOutput").value = distanceScale;
byId("distanceScaleInput").value = distanceScale;
unlock("distanceScale");
@ -110,16 +104,16 @@ function editUnits() {
calculateFriendlyGridSize();
// height exponent
heightExponentInput.value = heightExponentOutput.value = 1.8;
heightExponentInput.value = 1.8;
localStorage.removeItem("heightExponent");
calculateTemperatures();
renderScaleBar();
// population
populationRate = populationRateOutput.value = populationRateInput.value = 1000;
urbanization = urbanizationOutput.value = urbanizationInput.value = 1;
urbanDensity = urbanDensityOutput.value = urbanDensityInput.value = 10;
populationRate = populationRateInput.value = 1000;
urbanization = urbanizationInput.value = 1;
urbanDensity = urbanDensityInput.value = 10;
localStorage.removeItem("populationRate");
localStorage.removeItem("urbanization");
localStorage.removeItem("urbanDensity");