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

@ -0,0 +1,78 @@
{
const style = /* css */ `
slider-input {
display: flex;
align-items: center;
gap: .4em;
}
`;
const styleElement = document.createElement("style");
styleElement.setAttribute("type", "text/css");
styleElement.innerHTML = style;
document.head.appendChild(styleElement);
}
{
const template = document.createElement("template");
template.innerHTML = /* html */ `
<input type="range" />
<input type="number" />
`;
class SliderInput extends HTMLElement {
constructor() {
super();
this.appendChild(template.content.cloneNode(true));
const range = this.querySelector("input[type=range]");
const number = this.querySelector("input[type=number]");
range.value = number.value = this.value || this.getAttribute("value") || 50;
range.min = number.min = this.getAttribute("min") || 0;
range.max = number.max = this.getAttribute("max") || 100;
range.step = number.step = this.getAttribute("step") || 1;
range.addEventListener("input", this.handleEvent.bind(this));
number.addEventListener("input", this.handleEvent.bind(this));
range.addEventListener("change", this.handleEvent.bind(this));
number.addEventListener("change", this.handleEvent.bind(this));
}
handleEvent(e) {
const value = e.target.value;
const isNaN = Number.isNaN(Number(value));
if (isNaN || value === "") return e.stopPropagation();
const range = this.querySelector("input[type=range]");
const number = this.querySelector("input[type=number]");
this.value = range.value = number.value = value;
this.dispatchEvent(
new CustomEvent(e.type, {
detail: {value},
bubbles: true,
composed: true
})
);
}
set value(value) {
const range = this.querySelector("input[type=range]");
const number = this.querySelector("input[type=number]");
range.value = number.value = value;
}
get value() {
const number = this.querySelector("input[type=number]");
return number.value;
}
get valueAsNumber() {
const number = this.querySelector("input[type=number]");
return number.valueAsNumber;
}
}
customElements.define("slider-input", SliderInput);
}

134
index.css
View file

@ -525,7 +525,48 @@ input[type="color"]::-webkit-color-swatch-wrapper {
font-size: smaller;
}
#options input[type="text"] {
border: 0px;
width: 62%;
font-size: smaller;
}
#options output {
text-align: right;
font-size: smaller;
}
#options input[type="number"] {
font-size: 0.8em;
border: 0;
text-align: right;
background-color: transparent;
width: 3.3em;
}
#options input[type="number"]::-webkit-inner-spin-button,
#options input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
#options input[type="number"]:hover {
outline: 1px solid var(--dark-solid);
}
#options input.paired {
text-align: center;
background-color: white;
}
#options input.long {
width: 100%;
background-color: white;
text-align: left;
}
#options input[type="range"] {
width: 100%;
height: 8px;
background: 0;
appearance: none;
@ -568,55 +609,7 @@ input[type="color"]::-webkit-color-swatch-wrapper {
height: 2px;
}
#options input[type="number"] {
font-size: 0.8em;
}
#options input[type="text"] {
border: 0px;
width: 62%;
font-size: smaller;
}
#optionsContent output {
text-align: right;
font-size: smaller;
}
#optionsContent input[type="number"] {
border: 0;
text-align: right;
background-color: transparent;
width: 3.3em;
-moz-appearance: textfield;
}
#optionsContent input[type="number"]::-webkit-inner-spin-button,
#optionsContent input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
#optionsContent input[type="number"]:hover {
outline: 1px solid var(--dark-solid);
}
#optionsContent input.paired {
text-align: center;
background-color: white;
}
#optionsContent input.long {
width: 100%;
background-color: white;
text-align: left;
}
#optionsContent input[type="range"] {
width: 100%;
}
#optionsContent select {
#options select {
width: 100%;
}
@ -641,19 +634,6 @@ input[type="color"]::-webkit-color-swatch-wrapper {
transform: translate(0px, 1px);
}
#styleElements input[type="range"] {
width: 64%;
}
#styleElements select {
width: 64%;
}
#styleElements input[type="number"] {
width: 6em;
border: 0;
}
#styleSelectFont > option {
font-size: 2em;
}
@ -724,9 +704,6 @@ input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0.45em 0.75em;
margin: 0.35em 0;
transition: 0.1s;
font-size: 1em;
text-transform: capitalize;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@ -1268,7 +1245,6 @@ i.resetButton:active {
padding: 0;
height: 2px;
background: #d4d4d4;
top: -0.35em;
position: relative;
appearance: none;
-webkit-appearance: none;
@ -1844,11 +1820,6 @@ div.editorLine {
padding: 0px 3px !important;
}
#unitsBody > div > * {
display: inline-block;
margin-bottom: 0.2em;
}
.unitsHeader {
margin: 0.8em 0 0 -1.1em;
font-weight: bold;
@ -1860,28 +1831,21 @@ div.editorLine {
margin: 6px 0 0 6px;
}
#unitsBody > div > div {
#unitsBody label {
display: inline-block;
width: 9em;
}
#unitsBody > div > input[type="range"] {
width: 7em;
}
#unitsBody > div > select,
#unitsBody > div > input[type="text"] {
width: 12em;
}
#unitsBody > div > input[type="number"] {
width: 4.35em;
}
#unitsBody > div > input,
#unitsBody > div > select {
width: 14.4em;
border: 1px solid #e9e9e9;
}
#unitsBody input[type="range"] {
width: 9em;
}
#unitsEditor i.icon-lock-open,
#unitsEditor i.icon-lock {
color: #626573;

View file

@ -138,7 +138,7 @@
}
</style>
<link rel="preload" href="index.css?v=1.99.00" as="style" onload="this.onload=null; this.rel='stylesheet'" />
<link rel="preload" href="index.css?v=1.99.05" as="style" onload="this.onload=null; this.rel='stylesheet'" />
<link rel="preload" href="icons.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
<link rel="preload" href="libs/jquery-ui.css" as="style" onload="this.onload=null; this.rel='stylesheet'" />
</head>
@ -836,27 +836,24 @@
</td>
</tr>
<tr data-tip="Terracing rate. Set to 0 (toggle off) to improve performance">
<tr data-tip="Terracing power. Set to 0 to toggle off">
<td>Terracing</td>
<td>
<input id="styleHeightmapTerracingInput" type="range" min="0" max="20" step="1" />
<output id="styleHeightmapTerracingOutput">0</output>
<slider-input id="styleHeightmapTerracing" min="0" max="20" step="1"></slider-input>
</td>
</tr>
<tr data-tip="Layers reduction rate. Increase to improve performance">
<td>Reduce layers</td>
<td>
<input id="styleHeightmapSkipInput" type="range" min="0" max="10" step="1" value="5" />
<output id="styleHeightmapSkipOutput">5</output>
<slider-input id="styleHeightmapSkip" min="0" max="10" step="1"></slider-input>
</td>
</tr>
<tr data-tip="Line simplification rate. Increase to slightly improve performance">
<td>Simplify line</td>
<td>
<input id="styleHeightmapSimplificationInput" type="range" min="0" max="10" step="1" value="0" />
<output id="styleHeightmapSimplificationOutput">0</output>
<slider-input id="styleHeightmapSimplification" min="0" max="10" step="1"></slider-input>
</td>
</tr>
@ -874,7 +871,7 @@
<tr data-tip="Select color scheme for the element">
<td>Color scheme</td>
<td>
<select id="styleHeightmapScheme"></select>
<select id="styleHeightmapScheme" style="width: 86%"></select>
<button
id="openCreateHeightmapSchemeButton"
data-tip="Click to add a custom heightmap color scheme"
@ -889,8 +886,7 @@
<tr data-tip="Set opacity. 0: transparent, 1: solid">
<td>Opacity</td>
<td>
<input id="styleOpacityInput" type="range" min="0" max="1" step="0.01" value=".4" />
<output id="styleOpacityOutput">0.4</output>
<slider-input id="styleOpacityInput" min="0" max="1" step="0.01"></slider-input>
</td>
</tr>
</tbody>
@ -899,8 +895,7 @@
<tr data-tip="Set maximum number of items in one column">
<td>Column items</td>
<td>
<input id="styleLegendColItems" type="range" min="1" max="30" step="1" value="8" />
<output id="styleLegendColItemsOutput">8</output>
<slider-input id="styleLegendColItems" min="1" max="30" step="1"></slider-input>
</td>
</tr>
@ -915,8 +910,7 @@
<tr data-tip="Set background opacity">
<td>Opacity</td>
<td>
<input id="styleLegendOpacity" type="range" min="0" max="1" step="0.01" value="1" />
<output id="styleLegendOpacityOutput">1</output>
<slider-input id="styleLegendOpacity" min="0" max="1" step=".01"></slider-input>
</td>
</tr>
</tbody>
@ -943,7 +937,7 @@
<tr data-tip="Select texture image. Big textures can highly affect performance">
<td>Image</td>
<td>
<select id="styleTextureInput">
<select id="styleTextureInput" style="width: 86%">
<option value="">No texture</option>
<option value="./images/textures/folded-paper-big.jpg">Folded paper big</option>
<option value="./images/textures/folded-paper-small.jpg">Folded paper small</option>
@ -1027,8 +1021,7 @@
<tr data-tip="Set vignette blue propagation (in pixels)">
<td>Blur</td>
<td>
<input id="styleVignetteBlur" type="range" min="0" max="400" step="1" value="50" />
<output id="styleVignetteBlurOutput">50</output>px
<slider-input id="styleVignetteBlur" min="0" max="400" step="1"></slider-input>
</td>
</tr>
</tbody>
@ -1053,8 +1046,7 @@
<tr data-tip="Set ocean pattern opacity">
<td>Pattern opacity</td>
<td>
<input id="styleOceanPatternOpacity" type="range" min="0" max="1" step=".01" value=".2" />
<output id="styleOceanPatternOpacityOutput">0.2</output>
<slider-input id="styleOceanPatternOpacity" min="0" max="1" step=".01"></slider-input>
</td>
</tr>
@ -1118,8 +1110,7 @@
<tr data-tip="Set wind (compass) rose size">
<td>Size</td>
<td>
<input id="styleCompassSizeInput" type="range" min=".02" max="1" step=".01" value=".25" />
<output id="styleCompassSizeOutput">.25</output>
<slider-input id="styleCompassSizeInput" min=".02" max="1" step=".01"></slider-input>
</td>
</tr>
@ -1147,8 +1138,7 @@
<tr data-tip="Define the size of relief icons. All relief icons will be regenerated">
<td>Size</td>
<td>
<input id="styleReliefSizeInput" data-stored="reliefSize" type="range" min=".2" max="4" step=".01" />
<output id="styleReliefSizeOutput"></output>
<slider-input id="styleReliefSize" min=".2" max="4" step=".01"></slider-input>
</td>
</tr>
@ -1157,23 +1147,14 @@
>
<td>Density</td>
<td>
<input
id="styleReliefDensityInput"
data-stored="reliefDensity"
type="range"
min=".3"
max=".8"
step=".01"
value=".4"
/>
<output id="styleReliefDensityOutput">.4</output>
<slider-input id="styleReliefDensity" min=".3" max=".8" step=".01"></slider-input>
</td>
</tr>
</tbody>
<tbody id="styleFill">
<tr data-tip="Set fill color">
<td>Fill</td>
<td>Fill color</td>
<td>
<input id="styleFillInput" type="color" value="#5E4FA2" />
<output id="styleFillOutput">#5E4FA2</output>
@ -1183,7 +1164,7 @@
<tbody id="styleStroke">
<tr data-tip="Set stroke color">
<td>Stroke</td>
<td>Stroke color</td>
<td>
<input id="styleStrokeInput" type="color" value="#5E4FA2" />
<output id="styleStrokeOutput">#5E4FA2</output>
@ -1195,8 +1176,7 @@
<tr data-tip="Set stroke width">
<td>Stroke width</td>
<td>
<input id="styleStrokeWidthInput" type="range" min="0" max="5" step=".01" value="1" />
<output id="styleStrokeWidthOutput">1</output>
<slider-input id="styleStrokeWidthInput" min="0" max="5" step=".01"></slider-input>
</td>
</tr>
</tbody>
@ -1229,7 +1209,7 @@
<tr data-tip="Select font">
<td>Font</td>
<td>
<select id="styleSelectFont"></select>
<select id="styleSelectFont" style="width: 85%"></select>
<button id="styleFontAdd" data-tip="Add a font" class="icon-plus sideButton"></button>
</td>
</tr>
@ -1241,7 +1221,7 @@
<td>
<button id="styleFontPlus" data-tip="Increase font" class="whiteButton">+</button>
<button id="styleFontMinus" data-tip="Descrease font" class="whiteButton">-</button>
<input id="styleFontSize" type="number" min=".5" max="100" step=".1" value="14" />
<input id="styleFontSize" type="number" min=".5" max="100" step=".1" />
</td>
</tr>
</tbody>
@ -1281,16 +1261,14 @@
<tr data-tip="Define transparency of temperature leyer. Set to 0 to make it fully transparent">
<td>Fill opacity</td>
<td>
<input id="styleTemperatureFillOpacityInput" type="range" min="0" max="1" step=".01" value=".3" />
<output id="styleTemperatureFillOpacityOutput">0.3</output>
<slider-input id="styleTemperatureFillOpacityInput" min="0" max="1" step=".01"></slider-input>
</td>
</tr>
<tr data-tip="Set labels size">
<td>Labels size</td>
<td>
<input id="styleTemperatureFontSizeInput" type="range" min="0" max="30" value="8" />
<output id="styleTemperatureFontSizeOutput">8</output>
<slider-input id="styleTemperatureFontSizeInput" min="0" max="30" step="1"></slider-input>
</td>
</tr>
@ -1307,8 +1285,7 @@
<tr data-tip="Set states fill opacity. 0: invisible, 1: solid">
<td>Body opacity</td>
<td>
<input id="styleStatesBodyOpacity" type="range" min="0" max="1" step="0.01" />
<output id="styleStatesBodyOpacityOutput"></output>
<slider-input id="styleStatesBodyOpacity" min="0" max="1" step="0.01"></slider-input>
</td>
</tr>
@ -1326,24 +1303,21 @@
<tr data-tip="Set states halo effect width">
<td>Halo width</td>
<td>
<input id="styleStatesHaloWidth" type="range" min="0" max="30" step=".1" value="10" />
<output id="styleStatesHaloWidthOutput">10</output>
<slider-input id="styleStatesHaloWidth" min="0" max="30" step="0.1"></slider-input>
</td>
</tr>
<tr data-tip="Set states halo effect opacity. 0: invisible, 1: solid">
<td>Halo opacity</td>
<td>
<input id="styleStatesHaloOpacity" type="range" min="0" max="1" step="0.01" value="1" />
<output id="styleStatesHaloOpacityOutput">1</output>
<slider-input id="styleStatesHaloOpacity" min="0" max="1" step="0.01"></slider-input>
</td>
</tr>
<tr data-tip="Select halo effect power (blur). Set to 0 to make it solid line" style="margin-bottom: 1em">
<td>Halo blur</td>
<td>
<input id="styleStatesHaloBlur" type="range" min="0" max="10" step="0.01" value="4" />
<output id="styleStatesHaloBlurOutput">4</output>
<slider-input id="styleStatesHaloBlur" min="0" max="10" step="0.01"></slider-input>
</td>
</tr>
</tbody>
@ -1352,22 +1326,20 @@
<tr data-tip="Set fill transparency. Set to 0 to make it fully transparent">
<td>Fill opacity</td>
<td>
<input id="styleArmiesFillOpacity" type="range" min="0" max="1" step=".01" value="1" />
<output id="styleArmiesFillOpacityOutput">1</output>
<slider-input id="styleArmiesFillOpacity" min="0" max="1" step=".01"></slider-input>
</td>
</tr>
<tr data-tip="Set regiment box size. All regiments will be redrawn on change (position will defaulted)">
<td>Box Size</td>
<td>
<input id="styleArmiesSize" type="range" min="1" max="10" step=".1" value="3" />
<output id="styleArmiesSizeOutput">3</output>
<slider-input id="styleArmiesSize" min="0" max="10" step=".1"></slider-input>
</td>
</tr>
</tbody>
<tbody id="styleEmblems">
<tr data-tip="Set state emblems size multiplier">
<td>State Size</td>
<td>State size</td>
<td>
<input
id="emblemsStateSizeInput"
@ -1382,7 +1354,7 @@
</tr>
<tr data-tip="Set province emblems size multiplier">
<td>Province Size</td>
<td>Province size</td>
<td>
<input
id="emblemsProvinceSizeInput"
@ -1397,7 +1369,7 @@
</tr>
<tr data-tip="Set burg emblems size multiplier">
<td>Burg Size</td>
<td>Burg size</td>
<td>
<input
id="emblemsBurgSizeInput"
@ -1495,15 +1467,14 @@
<tr data-tip="Set background opacity. 0: transparent, 1: solid">
<td>Back opacity</td>
<td>
<input id="styleScaleBarBackgroundOpacityInput" type="range" min="0" max="1" step="0.01" />
<output id="styleScaleBarBackgroundOpacityOutput"></output>
<slider-input id="styleScaleBarBackgroundOpacity" min="0" max="1" step=".01"></slider-input>
</td>
</tr>
<tr data-tip="Set background fill color">
<td>Back fill</td>
<td>
<input id="styleScaleBarBackgroundFillInput" type="color" />
<input id="styleScaleBarBackgroundFill" type="color" />
<output id="styleScaleBarBackgroundFillOutput"></output>
</td>
</tr>
@ -1511,7 +1482,7 @@
<tr data-tip="Set background stroke color and width">
<td>Back stroke</td>
<td>
<input id="styleScaleBarBackgroundStrokeInput" type="color" />
<input id="styleScaleBarBackgroundStroke" type="color" />
<output id="styleScaleBarBackgroundStrokeOutput"></output>
<span>Width </span>
@ -1712,53 +1683,41 @@
<tr data-tip="Define how many states and capitals should be generated">
<td>
<i data-locked="0" id="lock_regions" class="icon-lock-open"></i>
<i data-locked="0" id="lock_statesNumber" class="icon-lock-open"></i>
</td>
<td>States number</td>
<td>
<input id="regionsInput" data-stored="regions" type="range" min="0" max="99" value="13" />
</td>
<td>
<input id="regionsOutput" data-stored="regions" type="number" min="0" max="999" value="13" />
<td colspan="2">
<slider-input id="statesNumber" data-stored="statesNumber" min="0" max="100"></slider-input>
</td>
</tr>
<tr data-tip="Define burgs percentage to form a separate province">
<td>
<i data-locked="0" id="lock_provinces" class="icon-lock-open"></i>
<i data-locked="0" id="lock_provincesRatio" class="icon-lock-open"></i>
</td>
<td>Provinces ratio</td>
<td>
<input id="provincesInput" data-stored="provinces" type="range" min="0" max="100" value="30" />
</td>
<td>
<input id="provincesOutput" data-stored="provinces" type="number" min="0" max="100" value="30" />
<td colspan="2">
<slider-input id="provincesRatio" data-stored="provincesRatio" min="0" max="100"></slider-input>
</td>
</tr>
<tr data-tip="Define how much states and cultures can vary in size. Defines expansionism value">
<td>
<i data-locked="0" id="lock_power" class="icon-lock-open"></i>
<i data-locked="0" id="lock_sizeVariety" class="icon-lock-open"></i>
</td>
<td>Size variety</td>
<td>
<input id="powerInput" data-stored="power" type="range" min="0" max="10" step=".2" value="5" />
</td>
<td>
<input id="powerOutput" data-stored="power" type="number" min="0" max="10" step=".1" value="5" />
<td colspan="2">
<slider-input id="sizeVariety" data-stored="sizeVariety" min="0" max="10" step=".1"></slider-input>
</td>
</tr>
<tr data-tip="Set state and cultures growth rate. Defines how many lands will stay neutral">
<td>
<i data-locked="0" id="lock_neutral" class="icon-lock-open"></i>
<i data-locked="0" id="lock_growthRate" class="icon-lock-open"></i>
</td>
<td>Growth rate</td>
<td>
<input id="neutralInput" data-stored="neutral" type="range" min=".1" max="2" step=".1" value="1" />
</td>
<td>
<input id="neutralOutput" data-stored="neutral" type="number" min=".1" max="2" step=".1" value="1" />
<td colspan="2">
<slider-input id="growthRate" data-stored="growthRate" min=".1" max="2" step=".1"></slider-input>
</td>
</tr>
@ -1779,14 +1738,17 @@
data-tip="Define how many organized religions and cults should be generated. Cultures will have their own folk religions in any case"
>
<td>
<i data-locked="0" id="lock_religions" class="icon-lock-open"></i>
<i data-locked="0" id="lock_religionsNumber" class="icon-lock-open"></i>
</td>
<td>Religions number</td>
<td>
<input id="religionsInput" data-stored="religions" type="range" min="0" max="50" step="1" value="15" />
</td>
<td>
<output id="religionsOutput" data-stored="religions" value="auto"></output>
<td colspan="2">
<slider-input
id="religionsNumber"
data-stored="religionsNumber"
min="0"
max="50"
step="1"
></slider-input>
</td>
</tr>
@ -1815,22 +1777,16 @@
>
<td></td>
<td>Interface size</td>
<td>
<input id="uiSizeInput" data-stored="uiSize" type="range" min=".6" max="3" step=".1" />
</td>
<td>
<input id="uiSizeOutput" data-stored="uiSize" type="number" min=".6" max="3" step=".1" />
<td colspan="2">
<slider-input id="uiSize" data-stored="uiSize" min=".6" max="3" step=".1"></slider-input>
</td>
</tr>
<tr data-tip="Set tooltip size">
<td></td>
<td>Tooltip size</td>
<td>
<input id="tooltipSizeInput" data-stored="tooltipSize" type="range" min="4" max="32" value="14" />
</td>
<td>
<input id="tooltipSizeOutput" data-stored="tooltipSize" type="number" min="0" max="256" value="14" />
<td colspan="2">
<slider-input id="tooltipSize" data-stored="tooltipSize" min="1" max="32" value="14"></slider-input>
</td>
</tr>
@ -1850,11 +1806,8 @@
<tr data-tip="Set dialog and tool windows transparency">
<td></td>
<td>Transparency</td>
<td>
<input id="transparencyInput" data-stored="transparency" type="range" min="0" max="100" />
</td>
<td>
<input id="transparencyOutput" data-stored="transparency" type="number" min="0" max="100" />
<td colspan="2">
<slider-input id="transparencyInput" data-stored="transparency" min="0" max="100"></slider-input>
</td>
</tr>
@ -4123,72 +4076,24 @@
</div>
<div id="brushesSliders" style="display: none">
<div data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" style="padding-bottom: 1px">
<div style="width: 3.2em; display: inline-block"><i>Radius:</i></div>
<input
id="brushRadius"
oninput="tip('Brush radius: '+this.value); brushRadiusNumber.value = this.value"
type="range"
min="1"
max="99"
value="25"
style="width: 13em"
/>
<input
id="brushRadiusNumber"
oninput="tip('Brush radius: '+this.value); brushRadius.value = this.value"
type="number"
min="1"
max="99"
value="25"
style="border: 1px solid #d4d4d4"
/>
<div data-tip="Change brush size. Shortcut: + to increase; to decrease">
<slider-input id="heightmapBrushRadius" min="5" max="100" value="25">
<div style="width: 3.5em">Radius:</div>
</slider-input>
</div>
<div data-tip="Set the brush power">
<div style="width: 3.2em; display: inline-block"><i>Power:</i></div>
<input
id="brushPower"
oninput="tip('Brush power: '+this.value); brushPowerNumber.value = this.value"
type="range"
min="1"
max="10"
value="5"
style="width: 13em"
/>
<input
id="brushPowerNumber"
oninput="tip('Brush power: '+this.value); brushPower.value = this.value"
type="number"
min="1"
max="10"
value="5"
style="border: 1px solid #d4d4d4"
/>
<div data-tip="Change brush power">
<slider-input id="heightmapBrushPower" min="1" max="10" value="5">
<div style="width: 3.5em">Power:</div>
</slider-input>
</div>
</div>
<div id="lineSlider" style="display: none">
<div data-tip="Set change power">
<div style="width: 3.2em; display: inline-block"><i>Power:</i></div>
<input
id="linePower"
oninput="tip('Line power: '+this.value); linePowerNumber.value = this.value"
type="range"
min="-100"
max="100"
value="30"
style="width: 13em"
/>
<input
id="linePowerNumber"
oninput="tip('Line power: '+this.value); linePower.value = this.value"
type="number"
min="-100"
max="100"
value="30"
style="border: 1px solid #d4d4d4"
/>
<div data-tip="Change tool power. Shortcut: + to increase; to decrease">
<slider-input id="heightmapLinePower" min="-100" max="100" value="30">
<div style="width: 3.5em">Power:</div>
</slider-input>
</div>
</div>
@ -4454,26 +4359,10 @@
class="icon-brush"
></button>
<div id="biomesManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic"
>Brush radius:
<input
id="biomesManuallyBrush"
oninput="tip('Brush radius: '+this.value); biomesManuallyBrushNumber.value = this.value"
type="range"
min="5"
max="99"
value="15"
style="width: 4em"
/>
<input
id="biomesManuallyBrushNumber"
oninput="tip('Brush radius: '+this.value); biomesManuallyBrush.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">
Brush size:
<slider-input id="biomesBrush" min="5" max="100" value="15"></slider-input>
</div>
<button id="biomesManuallyApply" data-tip="Apply current assignment" class="icon-check"></button>
<button id="biomesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
</div>
@ -4698,26 +4587,10 @@
<button id="provincesManually" data-tip="Manually re-assign provinces" class="icon-brush"></button>
<div id="provincesManuallyButtons" style="display: none">
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic"
>Brush size:
<input
id="provincesManuallyBrush"
oninput="tip('Brush size: '+this.value); provincesManuallyBrushNumber.value = this.value"
type="range"
min="5"
max="99"
value="8"
style="width: 5em"
/>
<input
id="provincesManuallyBrushNumber"
oninput="tip('Brush size: '+this.value); provincesManuallyBrush.value = this.value"
type="number"
min="5"
max="99"
value="8"
/> </label
><br />
<div data-tip="Change brush size. Shortcut: + to increase; to decrease" style="margin-block: 0.3em">
Brush size:
<slider-input id="provincesBrush" min="5" max="100" value="8"></slider-input>
</div>
<button id="provincesManuallyApply" data-tip="Apply assignment" class="icon-check"></button>
<button id="provincesManuallyCancel" data-tip="Cancel assignment" class="icon-cancel"></button>
</div>
@ -5006,29 +4879,10 @@
<button id="zonesManually" data-tip="Re-assign zones" class="icon-brush"></button>
<div id="zonesManuallyButtons" style="display: none">
<div>
<label data-tip="Change brush size" data-shortcut="+ (increase), (decrease)" class="italic"
>Brush:
<input
id="zonesBrush"
oninput="tip('Brush size: '+this.value); zonesBrushNumber.value = this.value"
type="range"
min="5"
max="50"
value="7"
style="width: 9em"
/>
<input
id="zonesBrushNumber"
oninput="tip('Brush size: '+this.value); zonesBrush.value = this.value"
type="number"
min="5"
max="50"
value="7"
/>
</label>
<div data-tip="Change brush size. Shortcut: + to increase; to decrease" style="margin-block: 0.3em">
Brush size:
<slider-input id="zonesBrush" min="5" max="100" value="8"></slider-input>
</div>
<div>
<input id="zonesBrushLandOnly" class="checkbox" type="checkbox" checked />
<label for="zonesBrushLandOnly" class="checkbox-label"><i>Change land only</i></label>
@ -5253,11 +5107,11 @@
<div id="unitsBody" style="margin-left: 1.1em">
<div class="unitsHeader" style="margin-top: 0.4em">
<span class="icon-map-signs"></span>
<div>Distance:</div>
<label>Distance:</label>
</div>
<div data-tip="Select a distance unit or provide a custom name">
<div>Distance unit:</div>
<label>Distance unit:</label>
<select id="distanceUnitInput" data-stored="distanceUnit">
<option value="mi" selected>Mile (mi)</option>
<option value="km">Kilometer (km)</option>
@ -5269,34 +5123,25 @@
</select>
</div>
<i data-locked="0" id="lock_distanceScale" class="icon-lock-open"></i>
<div data-tip="Select how many distance units are in one pixel">
<div>1 map pixel =</div>
<input id="distanceScaleOutput" type="range" min=".01" max="20" step=".1" value="3" />
<input
id="distanceScaleInput"
data-stored="distanceScale"
type="number"
min=".01"
max="100"
step=".01"
value="3"
data-value="3"
/>
<i data-locked="0" id="lock_distanceScale" class="icon-lock-open"></i>
<slider-input id="distanceScaleInput" data-stored="distanceScale" min=".01" max="20" step=".1" value="3">
<label>1 map pixel:</label>
</slider-input>
</div>
<div data-tip='Area unit name, type "square" to add ² to the distance unit'>
<div>Area unit:</div>
<label>Area unit:</label>
<input id="areaUnit" data-stored="areaUnit" type="text" value="square" />
</div>
<div class="unitsHeader">
<span class="icon-signal"></span>
<div>Altitude:</div>
<label>Altitude:</label>
</div>
<div data-tip="Select an altitude unit or provide a custom name">
<div>Height unit:</div>
<label>Height unit:</label>
<select id="heightUnit" data-stored="heightUnit">
<option value="ft" selected>Feet (ft)</option>
<option value="m">Meters (m)</option>
@ -5308,26 +5153,25 @@
<div
data-tip="Set height exponent, i.e. a value for altitude change sharpness. Altitude affects temperature and hence biomes"
>
<div>Exponent:</div>
<input id="heightExponentOutput" type="range" min="1.5" max="2.2" value="2" step=".01" />
<input
<slider-input
id="heightExponentInput"
data-stored="heightExponent"
type="number"
min="1.5"
max="2.2"
value="2"
step=".01"
/>
value="2"
>
<label>Exponent:</label>
</slider-input>
</div>
<div class="unitsHeader" data-tip="Select Temperature scale">
<span class="icon-temperature-high"></span>
<div>Temperature:</div>
<label>Temperature:</label>
</div>
<div>
<div>Temperature scale:</div>
<label>Temperature scale:</label>
<select id="temperatureScale" data-stored="temperatureScale">
<option value="°C" selected>degree Celsius (°C)</option>
<option value="°F">degree Fahrenheit (°F)</option>
@ -5342,73 +5186,32 @@
<div class="unitsHeader">
<span class="icon-male"></span>
<div>Population:</div>
<label>Population:</label>
</div>
<div data-tip="Set how many people are in one population point">
<div>1 population point =</div>
<input
id="populationRateOutput"
data-stored="populationRate"
type="range"
min="10"
max="9990"
step="10"
value="1000"
/>
<input
<slider-input
id="populationRateInput"
data-stored="populationRate"
type="number"
min="10"
max="9990"
max="10000"
step="10"
value="1000"
/>
>
<label>1 population point:</label>
</slider-input>
</div>
<div data-tip="Set urbanization rate: burgs population relative to all population">
<div>Urbanization rate:</div>
<input
id="urbanizationOutput"
data-stored="urbanization"
type="range"
min=".01"
max="5"
step=".01"
value="1"
/>
<input
id="urbanizationInput"
data-stored="urbanization"
type="number"
min=".01"
max="5"
step=".01"
value="1"
/>
<slider-input id="urbanizationInput" data-stored="urbanization" min=".01" max="5" step=".01" value="1">
<label>Urbanization rate:</label>
</slider-input>
</div>
<div data-tip="Set urban density: average population per building in Medieval Fantasy City Generator">
<div>Urban density:</div>
<input
id="urbanDensityOutput"
data-stored="urbanDensity"
type="range"
min="1"
max="200"
step="1"
value="10"
/>
<input
id="urbanDensityInput"
data-stored="urbanDensity"
type="number"
min="1"
max="200"
step="1"
value="10"
/>
<slider-input id="urbanDensityInput" data-stored="urbanDensity" min="1" max="200" step="1" value="10">
<label>Urban density:</label>
</slider-input>
</div>
</div>
@ -8154,6 +7957,9 @@
</defs>
</svg>
<script src="components/fill-box.js"></script>
<script src="components/slider-input.js"></script>
<script src="libs/jquery-3.1.1.min.js"></script>
<script src="libs/jquery-ui.min.js"></script>
<script src="versioning.js"></script>
@ -8172,7 +7978,7 @@
<script src="utils/nodeUtils.js?v=1.99.00"></script>
<script src="utils/numberUtils.js?v=1.99.00"></script>
<script src="utils/polyfills.js?v=1.99.00"></script>
<script src="utils/probabilityUtils.js?v=1.99.00"></script>
<script src="utils/probabilityUtils.js?v=1.99.05"></script>
<script src="utils/stringUtils.js?v=1.99.00"></script>
<script src="utils/languageUtils.js?v=1.99.00"></script>
<script src="utils/unitUtils.js?v=1.99.00"></script>
@ -8183,15 +7989,15 @@
<script src="config/precreated-heightmaps.js"></script>
<script src="modules/heightmap-generator.js?v=1.99.00"></script>
<script src="modules/ocean-layers.js?v=1.99.00"></script>
<script src="modules/river-generator.js?v=1.99.00"></script>
<script src="modules/river-generator.js?v=1.99.05"></script>
<script src="modules/lakes.js?v=1.99.00"></script>
<script src="modules/biomes.js?v=1.99.00"></script>
<script src="modules/names-generator.js?v=1.87.14"></script>
<script src="modules/cultures-generator.js?v=1.99.00"></script>
<script src="modules/cultures-generator.js?v=1.99.05"></script>
<script src="modules/renderers/state-labels.js?v=1.96.04"></script>
<script src="modules/burgs-and-states.js?v=1.99.00"></script>
<script src="modules/burgs-and-states.js?v=1.99.05"></script>
<script src="modules/routes-generator.js?v=1.99.04"></script>
<script src="modules/religions-generator.js?v=1.99.00"></script>
<script src="modules/religions-generator.js?v=1.99.05"></script>
<script src="modules/military-generator.js?v=1.99.00"></script>
<script src="modules/markers-generator.js?v=1.99.00"></script>
<script src="modules/coa-generator.js?v=1.99.00"></script>
@ -8200,22 +8006,22 @@
<script src="libs/lineclip.min.js"></script>
<script src="libs/alea.min.js"></script>
<script src="modules/fonts.js?v=1.99.03"></script>
<script src="modules/ui/layers.js?v=1.99.00"></script>
<script src="modules/ui/layers.js?v=1.99.05"></script>
<script src="modules/ui/measurers.js?v=1.99.00"></script>
<script src="modules/ui/stylePresets.js?v=1.99.03"></script>
<script src="modules/ui/general.js?v=1.99.00"></script>
<script src="modules/ui/options.js?v=1.99.00"></script>
<script src="modules/ui/general.js?v=1.99.05"></script>
<script src="modules/ui/options.js?v=1.99.05"></script>
<script src="main.js?v=1.99.00"></script>
<script defer src="modules/relief-icons.js?v=1.99.00"></script>
<script defer src="modules/ui/style.js?v=1.99.00"></script>
<script defer src="modules/ui/editors.js?v=1.99.00"></script>
<script defer src="modules/relief-icons.js?v=1.99.05"></script>
<script defer src="modules/ui/style.js?v=1.99.05"></script>
<script defer src="modules/ui/editors.js?v=1.99.05"></script>
<script defer src="modules/ui/tools.js?v=1.99.00"></script>
<script defer src="modules/ui/world-configurator.js?v=1.99.00"></script>
<script defer src="modules/ui/heightmap-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/provinces-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/biomes-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/heightmap-editor.js?v=1.99.05"></script>
<script defer src="modules/ui/provinces-editor.js?v=1.99.05"></script>
<script defer src="modules/ui/biomes-editor.js?v=1.99.05"></script>
<script defer src="modules/ui/namesbase-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/elevation-profile.js?v=1.99.00"></script>
<script defer src="modules/ui/temperature-graph.js?v=1.99.00"></script>
@ -8229,12 +8035,12 @@
<script defer src="modules/ui/rivers-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/rivers-creator.js?v=1.99.00"></script>
<script defer src="modules/ui/relief-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/burg-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/units-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/burg-editor.js?v=1.99.05"></script>
<script defer src="modules/ui/units-editor.js?v=1.99.05"></script>
<script defer src="modules/ui/notes-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/diplomacy-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/zones-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/burgs-overview.js?v=1.99.00"></script>
<script defer src="modules/ui/burgs-overview.js?v=1.99.05"></script>
<script defer src="modules/ui/routes-overview.js?v=1.99.02"></script>
<script defer src="modules/ui/rivers-overview.js?v=1.99.00"></script>
<script defer src="modules/ui/military-overview.js?v=1.99.00"></script>
@ -8245,17 +8051,14 @@
<script defer src="modules/ui/emblems-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/markers-editor.js?v=1.99.00"></script>
<script defer src="modules/ui/3d.js?v=1.99.00"></script>
<script defer src="modules/ui/submap.js?v=1.99.00"></script>
<script defer src="modules/ui/hotkeys.js?v=1.99.00"></script>
<script defer src="modules/ui/submap.js?v=1.99.05"></script>
<script defer src="modules/ui/hotkeys.js?v=1.99.05"></script>
<script defer src="modules/coa-renderer.js?v=1.99.00"></script>
<script defer src="libs/rgbquant.min.js"></script>
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
<script defer src="modules/io/save.js?v=1.99.00"></script>
<script defer src="modules/io/load.js?v=1.99.01"></script>
<script defer src="modules/io/load.js?v=1.99.05"></script>
<script defer src="modules/io/cloud.js?v=1.99.00"></script>
<script defer src="modules/io/export.js?v=1.99.00"></script>
<!-- Web Components -->
<script defer src="components/fill-box.js"></script>
</body>
</html>

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;
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");

View file

@ -22,7 +22,14 @@ function each(n) {
return i => i % n === 0;
}
// random number (normal or gaussian distribution)
/* Random Gaussian number generator
* @param {number} expected - expected value
* @param {number} deviation - standard deviation
* @param {number} min - minimum value
* @param {number} max - maximum value
* @param {number} round - round value to n decimals
* @return {number} random number
*/
function gauss(expected = 100, deviation = 30, min = 0, max = 300, round = 0) {
return rn(minmax(d3.randomNormal(expected, deviation)(), min, max), round);
}

View file

@ -1,7 +1,7 @@
"use strict";
// version and caching control
const version = "1.99.04"; // generator version, update each time
const version = "1.99.05"; // generator version, update each time
{
document.title += " v" + version;