mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
Ocean heightmap and Scale bar styling change [v1.96] (#1045)
* Scale bar styling (#1025) * feat: style scale bar * feat: style scale bar - style presets --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com> * Ocean heightmap to v1.96 (#1044) * feat: allow to render ocean heightmap * feat: allow to render ocean heightmap - test * feat: allow to render ocean heightmap - fix issue * feat: allow to render ocean heightmap - cleanup --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com> * fix: scale bar size * fix: remove mask on terrs lavel * fix: regenerate heigtmap preview to use current graph size * Add the name of culture and namesbase in the name editor dialog (#1033) * Add the name of culture and namesbase in the name editor dialog Added the name of the culture and namesbase in the dialog "name editor". This tells information on the "click to generate a culture-specific name" It tells you the culture before changing name. * cultureName into cultureId + cultureName And deleted the incomplete code of showing culture name on datatip * refactor: leave culture name only --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com> * Added Burgs column to province editor (#1031) * Added Burgs column to province editor Added to province editor: + Burgs column + the number of Burgs, p.burgs.length + "icon-dot-circled" to go to overviewBurgs. + overviewBurgs Filtered by state id. + Fixed some typos. * fixed code as Azgaar suggested + Corrected provincesHeader distance in em. + const stateId = pack.provinces[p].state; - Deleted cell count. * deleted HTML code for provincesFooter cells - Deleted Total land cells number HTML from provincesFooter. * deleting totalCells in the code, maybe i will add provinceCells in the future. Deleted lines for const totalCells and for (+cells / totalCells) * 100 + "%"; * refactor: cleanup * refactor: cleanup --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com> * fix: burgs overview - add MFCG link back * feat: add more details to burgs export * feat: don't show auto-update dialog * feat: pump version * fix: #1041 * feat: update style presets --------- Co-authored-by: Azgaar <azgaar.fmg@yandex.com> Co-authored-by: Ángel Montero Lamas <angel.montero1@gmail.com>
This commit is contained in:
parent
845dc893d2
commit
374c21b3d7
38 changed files with 1304 additions and 608 deletions
18
index.css
18
index.css
|
|
@ -1876,12 +1876,6 @@ div.editorLine {
|
|||
margin: 0.4em 0 0 -0.9em;
|
||||
}
|
||||
|
||||
#barBackColor {
|
||||
width: 3.5em;
|
||||
padding: 0px;
|
||||
height: 1.2em;
|
||||
}
|
||||
|
||||
#ruler {
|
||||
cursor: move;
|
||||
fill: none;
|
||||
|
|
@ -1921,18 +1915,6 @@ div.editorLine {
|
|||
stroke: #737373;
|
||||
}
|
||||
|
||||
#scaleBar {
|
||||
stroke: none;
|
||||
fill: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#scaleBar text {
|
||||
fill: #353540;
|
||||
text-anchor: middle;
|
||||
font-family: var(--serif);
|
||||
}
|
||||
|
||||
#militaryOptionsTable select {
|
||||
border: 1px solid #d4d4d4;
|
||||
}
|
||||
|
|
|
|||
299
index.html
299
index.html
|
|
@ -138,7 +138,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<link rel="preload" href="index.css?v=1.95.00" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
||||
<link rel="preload" href="index.css?v=1.96.00" 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>
|
||||
|
|
@ -366,7 +366,9 @@
|
|||
</mask>
|
||||
</defs>
|
||||
<g id="viewbox"></g>
|
||||
<g id="scaleBar"></g>
|
||||
<g id="scaleBar">
|
||||
<rect id="scaleBarBack"></rect>
|
||||
</g>
|
||||
<g id="vignette" mask="url(#vignette-mask)">
|
||||
<rect x="0" y="0" width="100%" height="100%" />
|
||||
</g>
|
||||
|
|
@ -799,6 +801,7 @@
|
|||
<option value="rivers">Rivers</option>
|
||||
<option value="routes">Routes</option>
|
||||
<option value="ruler">Rulers</option>
|
||||
<option value="scaleBar">Scale Bar</option>
|
||||
<option value="regions" selected>States</option>
|
||||
<option value="temperature">Temperature</option>
|
||||
<option value="texture">Texture</option>
|
||||
|
|
@ -824,6 +827,63 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="styleHeightmap">
|
||||
<tr id="styleHeightmapRenderOceanOption" data-tip="Check to render ocean heights">
|
||||
<td colspan="2">
|
||||
<input id="styleHeightmapRenderOcean" class="checkbox" type="checkbox" />
|
||||
<label for="styleHeightmapRenderOcean" class="checkbox-label">Render ocean heights</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Terracing rate. Set to 0 (toggle off) to improve performance">
|
||||
<td>Terracing</td>
|
||||
<td>
|
||||
<input id="styleHeightmapTerracingInput" type="range" min="0" max="20" step="1" />
|
||||
<output id="styleHeightmapTerracingOutput">0</output>
|
||||
</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>
|
||||
</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>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Select line interpolation type">
|
||||
<td>Line style</td>
|
||||
<td>
|
||||
<select id="styleHeightmapCurve">
|
||||
<option value="curveBasisClosed" selected>Curved</option>
|
||||
<option value="curveLinear">Linear</option>
|
||||
<option value="curveStep">Rectangular</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Select color scheme for the element">
|
||||
<td>Color scheme</td>
|
||||
<td>
|
||||
<select id="styleHeightmapScheme"></select>
|
||||
<button
|
||||
id="openCreateHeightmapSchemeButton"
|
||||
data-tip="Click to add a custom heightmap color scheme"
|
||||
data-stops="#ffffff,#EEEECC,#D2B48C,#008000,#008080"
|
||||
class="icon-plus sideButton"
|
||||
></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="styleOpacity" style="display: none">
|
||||
<tr data-tip="Set opacity. 0: transparent, 1: solid">
|
||||
<td>Opacity</td>
|
||||
|
|
@ -1281,56 +1341,6 @@
|
|||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="styleHeightmap">
|
||||
<tr data-tip="Terracing rate. Set to 0 (toggle off) to improve performance">
|
||||
<td>Terracing</td>
|
||||
<td>
|
||||
<input id="styleHeightmapTerracingInput" type="range" min="0" max="20" step="1" />
|
||||
<output id="styleHeightmapTerracingOutput">0</output>
|
||||
</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>
|
||||
</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>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Select line interpolation type">
|
||||
<td>Line style</td>
|
||||
<td>
|
||||
<select id="styleHeightmapCurve">
|
||||
<option value="0" selected>Curved</option>
|
||||
<option value="1">Linear</option>
|
||||
<option value="2">Rectangular</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Select color scheme for the element">
|
||||
<td>Color scheme</td>
|
||||
<td>
|
||||
<select id="styleHeightmapScheme"></select>
|
||||
<button
|
||||
id="openCreateHeightmapSchemeButton"
|
||||
data-tip="Click to add a custom heightmap color scheme"
|
||||
data-stops="#ffffff,#EEEECC,#D2B48C,#008000,#008080"
|
||||
class="icon-plus sideButton"
|
||||
></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="styleArmies">
|
||||
<tr data-tip="Set fill transparency. Set to 0 to make it fully transparent">
|
||||
<td>Fill opacity</td>
|
||||
|
|
@ -1446,6 +1456,84 @@
|
|||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody id="styleScaleBar">
|
||||
<tr data-tip="Set bar and font size">
|
||||
<td>Size</td>
|
||||
<td>
|
||||
<span>Bar </span>
|
||||
<input id="styleScaleBarSize" type="number" min=".5" max="5" step=".1" />
|
||||
<span>Font </span>
|
||||
<input id="styleScaleBarFontSize" type="number" min="1" max="100" step=".1" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Set position of the Scale bar bottom right corner (in percents)">
|
||||
<td>Position</td>
|
||||
<td>
|
||||
<span>x </span>
|
||||
<input id="styleScaleBarPositionX" type="number" min="0" max="100" step="0.1" style="width: 5em" />
|
||||
<span>y </span>
|
||||
<input id="styleScaleBarPositionY" type="number" min="0" max="100" step="0.1" style="width: 5em" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Type scale bar label, leave blank to hide label">
|
||||
<td>Label</td>
|
||||
<td>
|
||||
<input id="styleScaleBarLabel" type="text" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Set background fill color">
|
||||
<td>Back fill</td>
|
||||
<td>
|
||||
<input id="styleScaleBarBackgroundFillInput" type="color" />
|
||||
<output id="styleScaleBarBackgroundFillOutput"></output>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Set background stroke color and width">
|
||||
<td>Back stroke</td>
|
||||
<td>
|
||||
<input id="styleScaleBarBackgroundStrokeInput" type="color" />
|
||||
<output id="styleScaleBarBackgroundStrokeOutput"></output>
|
||||
|
||||
<span>Width </span>
|
||||
<input
|
||||
id="styleScaleBarBackgroundStrokeWidth"
|
||||
type="number"
|
||||
min="0"
|
||||
max="10"
|
||||
step="0.1"
|
||||
style="width: 5em"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Set background element padding: top, right, bottom, left (in pixels)">
|
||||
<td>Back padding</td>
|
||||
<td style="display: flex; gap: 4px">
|
||||
<input id="styleScaleBarBackgroundPaddingTop" type="number" min="0" max="100" style="width: 5em" />
|
||||
<input id="styleScaleBarBackgroundPaddingRight" type="number" min="0" max="100" style="width: 5em" />
|
||||
<input id="styleScaleBarBackgroundPaddingBottom" type="number" min="0" max="100" style="width: 5em" />
|
||||
<input id="styleScaleBarBackgroundPaddingLeft" type="number" min="0" max="100" style="width: 5em" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Select background filter">
|
||||
<td>Back filter</td>
|
||||
<td><select id="styleScaleBarBackgroundFilter" /></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id="mapFilters" data-tip="Set a filter to be applied to the map in general">
|
||||
|
|
@ -4450,7 +4538,7 @@
|
|||
</div>
|
||||
|
||||
<div id="provincesEditor" class="dialog stable" style="display: none">
|
||||
<div id="provincesHeader" class="header" style="grid-template-columns: 11em 8em 8em 8em 5em 8em">
|
||||
<div id="provincesHeader" class="header" style="grid-template-columns: 11em 8em 8em 6em 6em 6em 8em">
|
||||
<div data-tip="Click to sort by province name" class="sortable alphabetically" data-sortby="name">
|
||||
Province
|
||||
</div>
|
||||
|
|
@ -4463,6 +4551,9 @@
|
|||
<div data-tip="Click to sort by province owner" class="sortable alphabetically" data-sortby="state">
|
||||
State
|
||||
</div>
|
||||
<div data-tip="Click to sort by province burgs count" class="sortable hide" data-sortby="burgs">
|
||||
Burgs
|
||||
</div>
|
||||
<div data-tip="Click to sort by province area" class="sortable hide" data-sortby="area">Area </div>
|
||||
<div data-tip="Click to sort by province population" class="sortable hide" data-sortby="population">
|
||||
Population
|
||||
|
|
@ -4475,6 +4566,9 @@
|
|||
<div data-tip="Provinces displayed" style="margin-left: 4px">
|
||||
Provinces: <span id="provincesFooterNumber">0</span>
|
||||
</div>
|
||||
<div data-tip="Total burgs number" style="margin-left: 12px">
|
||||
Burgs: <span id="provincesFooterBurgs">0</span>
|
||||
</div>
|
||||
<div data-tip="Average area" style="margin-left: 14px">
|
||||
Mean area: <span id="provincesFooterArea">0</span>
|
||||
</div>
|
||||
|
|
@ -4612,7 +4706,7 @@
|
|||
<span data-tip="Speak the name. You can change voice and language in options" class="speaker">🔊</span>
|
||||
<span
|
||||
id="provinceNameEditorShortCulture"
|
||||
data-tip="Generate culture-specific name"
|
||||
data-tip="Generate culture-specific name for the province"
|
||||
class="icon-book pointer"
|
||||
></span>
|
||||
<span id="provinceNameEditorShortRandom" data-tip="Generate random name" class="icon-globe pointer"></span>
|
||||
|
|
@ -4688,6 +4782,14 @@
|
|||
class="icon-arrows-cw pointer"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="provinceCultureName"
|
||||
data-tip="Dominant culture in the province. This defines culture-based naming. Can be changed via the Cultures Editor"
|
||||
style="margin-top: 0.2em"
|
||||
>
|
||||
Dominant culture: <span id="provinceCultureDisplay"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="namesbaseEditor" class="dialog stable textual" style="display: none">
|
||||
|
|
@ -5132,49 +5234,6 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div class="unitsHeader">
|
||||
<span class="icon-minus"></span>
|
||||
<div>Scale bar:</div>
|
||||
</div>
|
||||
|
||||
<div data-tip="Set scale bar size">
|
||||
<div>Bar size:</div>
|
||||
<input id="barSizeOutput" data-stored="barSize" type="range" min=".5" max="5" value="2" step=".1" />
|
||||
<input id="barSizeInput" data-stored="barSize" type="number" min=".5" max="5" value="2" step=".1" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Type scale bar label, leave blank to hide label">
|
||||
<div>Bar label:</div>
|
||||
<input id="barLabel" data-stored="barLabel" type="text" placeholder="hidden" value="" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Set background for Scale bar">
|
||||
<div>Bar background:</div>
|
||||
<input
|
||||
id="barBackOpacity"
|
||||
data-stored="barBackOpacity"
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
value=".2"
|
||||
step=".01"
|
||||
/>
|
||||
<input id="barBackColor" data-stored="barBackColor" type="color" value="#ffffff" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Set position of the Scale bar bottom right corner in percents">
|
||||
<div>Bar position:</div>
|
||||
x:<input id="barPosX" data-stored="barPosX" type="number" min="0" max="100" step=".1" value="99" /> y:<input
|
||||
id="barPosY"
|
||||
data-stored="barPosY"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
step=".1"
|
||||
value="99"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="unitsHeader">
|
||||
<span class="icon-male"></span>
|
||||
<div>Population:</div>
|
||||
|
|
@ -7963,7 +8022,7 @@
|
|||
<script src="utils/commonUtils.js?v=1.89.29"></script>
|
||||
<script src="utils/arrayUtils.js"></script>
|
||||
<script src="utils/colorUtils.js"></script>
|
||||
<script src="utils/graphUtils.js?v=1.93.12"></script>
|
||||
<script src="utils/graphUtils.js?v=1.96.00"></script>
|
||||
<script src="utils/nodeUtils.js"></script>
|
||||
<script src="utils/numberUtils.js?v=1.89.08"></script>
|
||||
<script src="utils/polyfills.js?v=1.95.03"></script>
|
||||
|
|
@ -7976,39 +8035,39 @@
|
|||
<script src="config/heightmap-templates.js"></script>
|
||||
<script src="config/precreated-heightmaps.js"></script>
|
||||
<script src="modules/heightmap-generator.js?v=1.88.00"></script>
|
||||
<script src="modules/ocean-layers.js?v=1.95.00"></script>
|
||||
<script src="modules/ocean-layers.js?v=1.96.00"></script>
|
||||
<script src="modules/river-generator.js?v=1.89.13"></script>
|
||||
<script src="modules/lakes.js"></script>
|
||||
<script src="modules/biomes.js"></script>
|
||||
<script src="modules/names-generator.js?v=1.87.14"></script>
|
||||
<script src="modules/cultures-generator.js?v=1.89.10"></script>
|
||||
<script src="modules/cultures-generator.js?v=1.96.00"></script>
|
||||
<script src="modules/renderers/state-labels.js"></script>
|
||||
<script src="modules/burgs-and-states.js?v=1.92.00"></script>
|
||||
<script src="modules/routes-generator.js"></script>
|
||||
<script src="modules/religions-generator.js?v=1.93.08"></script>
|
||||
<script src="modules/military-generator.js"></script>
|
||||
<script src="modules/military-generator.js?v=1.96.00"></script>
|
||||
<script src="modules/markers-generator.js?v=1.93.04"></script>
|
||||
<script src="modules/coa-generator.js?v=1.91.05"></script>
|
||||
<script src="modules/submap.js?v=1.94.01"></script>
|
||||
<script src="modules/submap.js?v=1.96.00"></script>
|
||||
<script src="libs/polylabel.min.js"></script>
|
||||
<script src="libs/lineclip.min.js"></script>
|
||||
<script src="libs/alea.min.js"></script>
|
||||
<script src="modules/fonts.js?v=1.89.18"></script>
|
||||
<script src="modules/ui/layers.js?v=1.94.00"></script>
|
||||
<script src="modules/ui/measurers.js?v=1.94.03"></script>
|
||||
<script src="modules/ui/stylePresets.js?v=1.95.00"></script>
|
||||
<script src="modules/ui/layers.js?v=1.96.00"></script>
|
||||
<script src="modules/ui/measurers.js?v=1.96.00"></script>
|
||||
<script src="modules/ui/stylePresets.js?v=1.96.00"></script>
|
||||
|
||||
<script src="modules/ui/general.js?v=1.94.01"></script>
|
||||
<script src="modules/ui/options.js?v=1.94.06"></script>
|
||||
<script src="main.js?v=1.94.05"></script>
|
||||
<script src="modules/ui/general.js?v=1.96.00"></script>
|
||||
<script src="modules/ui/options.js?v=1.96.00"></script>
|
||||
<script src="main.js?v=1.96.00"></script>
|
||||
|
||||
<script defer src="modules/relief-icons.js"></script>
|
||||
<script defer src="modules/ui/style.js?v=1.95.00"></script>
|
||||
<script defer src="modules/ui/editors.js?v=1.95.04"></script>
|
||||
<script defer src="modules/ui/style.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/editors.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/tools.js?v=1.95.01"></script>
|
||||
<script defer src="modules/ui/world-configurator.js?v=1.91.05"></script>
|
||||
<script defer src="modules/ui/heightmap-editor.js?v=1.93.00"></script>
|
||||
<script defer src="modules/ui/provinces-editor.js?v=1.92.00"></script>
|
||||
<script defer src="modules/ui/heightmap-editor.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/provinces-editor.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/biomes-editor.js?v=1.91.05"></script>
|
||||
<script defer src="modules/ui/namesbase-editor.js?v=1.95.02"></script>
|
||||
<script defer src="modules/ui/elevation-profile.js"></script>
|
||||
|
|
@ -8021,12 +8080,12 @@
|
|||
<script defer src="modules/ui/rivers-editor.js"></script>
|
||||
<script defer src="modules/ui/rivers-creator.js?v=1.89.13"></script>
|
||||
<script defer src="modules/ui/relief-editor.js"></script>
|
||||
<script defer src="modules/ui/burg-editor.js"></script>
|
||||
<script defer src="modules/ui/units-editor.js?v=1.94.02"></script>
|
||||
<script defer src="modules/ui/burg-editor.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/units-editor.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/notes-editor.js?v=1.93.09"></script>
|
||||
<script defer src="modules/ui/diplomacy-editor.js?v=1.88.04"></script>
|
||||
<script defer src="modules/ui/zones-editor.js"></script>
|
||||
<script defer src="modules/ui/burgs-overview.js?v=1.93.10"></script>
|
||||
<script defer src="modules/ui/burgs-overview.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/rivers-overview.js"></script>
|
||||
<script defer src="modules/ui/military-overview.js"></script>
|
||||
<script defer src="modules/ui/regiments-overview.js?v=1.89.20"></script>
|
||||
|
|
@ -8036,15 +8095,15 @@
|
|||
<script defer src="modules/ui/emblems-editor.js?v=1.91.00"></script>
|
||||
<script defer src="modules/ui/markers-editor.js"></script>
|
||||
<script defer src="modules/ui/3d.js?v=1.94.03"></script>
|
||||
<script defer src="modules/ui/submap.js?v=1.94.03"></script>
|
||||
<script defer src="modules/ui/submap.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/hotkeys.js?v=1.95.00"></script>
|
||||
<script defer src="modules/coa-renderer.js?v=1.94.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.93.02"></script>
|
||||
<script defer src="modules/io/load.js?v=1.95.00"></script>
|
||||
<script defer src="modules/io/cloud.js?v=1.94.04"></script>
|
||||
<script defer src="modules/io/export.js?v=1.95.05"></script>
|
||||
<script defer src="modules/io/save.js?v=1.96.00"></script>
|
||||
<script defer src="modules/io/load.js?v=1.96.00"></script>
|
||||
<script defer src="modules/io/cloud.js?v=1.96.00"></script>
|
||||
<script defer src="modules/io/export.js?v=1.96.00"></script>
|
||||
<script defer src="modules/io/formats.js"></script>
|
||||
|
||||
<!-- Web Components -->
|
||||
|
|
|
|||
2
libs/polylabel.min.js
vendored
2
libs/polylabel.min.js
vendored
|
|
@ -1 +1 @@
|
|||
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).polylabel=t()}}(function(){return function t(n,e,r){function o(a,u){if(!e[a]){if(!n[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(i)return i(a,!0);var h=new Error("Cannot find module '"+a+"'");throw h.code="MODULE_NOT_FOUND",h}var s=e[a]={exports:{}};n[a][0].call(s.exports,function(t){var e=n[a][1][t];return o(e||t)},s,s.exports,t,n,e,r)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,n,e){"use strict";var r=t("tinyqueue");function o(t,n){return n.max-t.max}function i(t,n,e,r){this.x=t,this.y=n,this.h=e,this.d=function(t,n,e){for(var r=!1,o=1/0,i=0;i<e.length;i++)for(var u=e[i],f=0,h=u.length,s=h-1;f<h;s=f++){var d=u[f],l=u[s];d[1]>n!=l[1]>n&&t<(l[0]-d[0])*(n-d[1])/(l[1]-d[1])+d[0]&&(r=!r),o=Math.min(o,a(t,n,d,l))}return(r?1:-1)*Math.sqrt(o)}(t,n,r),this.max=this.d+this.h*Math.SQRT2}function a(t,n,e,r){var o=e[0],i=e[1],a=r[0]-o,u=r[1]-i;if(0!==a||0!==u){var f=((t-o)*a+(n-i)*u)/(a*a+u*u);f>1?(o=r[0],i=r[1]):f>0&&(o+=a*f,i+=u*f)}return(a=t-o)*a+(u=n-i)*u}n.exports=function(t,n,e){var a,u,f,h;n=n||1;for(var s=0;s<t[0].length;s++){var d=t[0][s];(!s||d[0]<a)&&(a=d[0]),(!s||d[1]<u)&&(u=d[1]),(!s||d[0]>f)&&(f=d[0]),(!s||d[1]>h)&&(h=d[1])}for(var l=f-a,p=h-u,c=Math.min(l,p),v=c/2,g=new r(null,o),x=a;x<f;x+=c)for(var y=u;y<h;y+=c)g.push(new i(x+v,y+v,v,t));var w=function(t){for(var n=0,e=0,r=0,o=t[0],a=0,u=o.length,f=u-1;a<u;f=a++){var h=o[a],s=o[f],d=h[0]*s[1]-s[0]*h[1];e+=(h[0]+s[0])*d,r+=(h[1]+s[1])*d,n+=3*d}return new i(e/n,r/n,0,t)}(t),m=g.length;for(;g.length;){var b=g.pop();b.d>w.d&&(w=b,e&&console.log("found best %d after %d probes",Math.round(1e4*b.d)/1e4,m)),b.max-w.d<=n||(v=b.h/2,g.push(new i(b.x-v,b.y-v,v,t)),g.push(new i(b.x+v,b.y-v,v,t)),g.push(new i(b.x-v,b.y+v,v,t)),g.push(new i(b.x+v,b.y+v,v,t)),m+=4)}e&&(console.log("num probes: "+m),console.log("best distance: "+w.d));return[w.x,w.y]}},{tinyqueue:2}],2:[function(t,n,e){"use strict";function r(t,n){if(!(this instanceof r))return new r(t,n);if(this.data=t||[],this.length=this.data.length,this.compare=n||o,t)for(var e=Math.floor(this.length/2);e>=0;e--)this._down(e)}function o(t,n){return t<n?-1:t>n?1:0}function i(t,n,e){var r=t[n];t[n]=t[e],t[e]=r}n.exports=r,r.prototype={push:function(t){this.data.push(t),this.length++,this._up(this.length-1)},pop:function(){var t=this.data[0];return this.data[0]=this.data[this.length-1],this.length--,this.data.pop(),this._down(0),t},peek:function(){return this.data[0]},_up:function(t){for(var n=this.data,e=this.compare;t>0;){var r=Math.floor((t-1)/2);if(!(e(n[t],n[r])<0))break;i(n,r,t),t=r}},_down:function(t){for(var n=this.data,e=this.compare,r=this.length;;){var o=2*t+1,a=o+1,u=t;if(o<r&&e(n[o],n[u])<0&&(u=o),a<r&&e(n[a],n[u])<0&&(u=a),u===t)return;i(n,u,t),t=u}}}},{}]},{},[1])(1)});
|
||||
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).polylabel=t()}}(function(){return function t(n,e,r){function o(a,u){if(!e[a]){if(!n[a]){var f="function"==typeof require&&require;if(!u&&f)return f(a,!0);if(i)return i(a,!0);var h=new Error("Cannot find module '"+a+"'");throw h.code="MODULE_NOT_FOUND",h}var s=e[a]={exports:{}};n[a][0].call(s.exports,function(t){var e=n[a][1][t];return o(e||t)},s,s.exports,t,n,e,r)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,n,e){"use strict";var r=t("tinyqueue");function o(t,n){return n.max-t.max}function i(t,n,e,r){this.x=t,this.y=n,this.h=e,this.d=function(t,n,e){for(var r=!1,o=1/0,i=0;i<e.length;i++)for(var u=e[i],f=0,h=u.length,s=h-1;f<h;s=f++){var d=u[f],l=u[s];d[1]>n!=l[1]>n&&t<(l[0]-d[0])*(n-d[1])/(l[1]-d[1])+d[0]&&(r=!r),o=Math.min(o,a(t,n,d,l))}return(r?1:-1)*Math.sqrt(o)}(t,n,r),this.max=this.d+this.h*Math.SQRT2}function a(t,n,e,r){var o=e[0],i=e[1],a=r[0]-o,u=r[1]-i;if(0!==a||0!==u){var f=((t-o)*a+(n-i)*u)/(a*a+u*u);f>1?(o=r[0],i=r[1]):f>0&&(o+=a*f,i+=u*f)}return(a=t-o)*a+(u=n-i)*u}n.exports=function(t,n,e){var a,u,f,h;n=n||1;for(var s=0;s<t[0].length;s++){var d=t[0][s];(!s||d[0]<a)&&(a=d[0]),(!s||d[1]<u)&&(u=d[1]),(!s||d[0]>f)&&(f=d[0]),(!s||d[1]>h)&&(h=d[1])}for(var l=f-a,p=h-u,c=Math.min(l,p),v=c/2,g=new r(null,o),x=a;x<f;x+=c)for(var y=u;y<h;y+=c)g.push(new i(x+v,y+v,v,t));var w=function(t){for(var n=0,e=0,r=0,o=t[0],a=0,u=o.length,f=u-1;a<u;f=a++){var h=o[a],s=o[f],d=h[0]*s[1]-s[0]*h[1];e+=(h[0]+s[0])*d,r+=(h[1]+s[1])*d,n+=3*d}return new i(e/n,r/n,0,t)}(t),m=g.length;for(;g.length;){var b=g.pop();b.d>w.d&&(w=b,e&&console.info("found best %d after %d probes",Math.round(1e4*b.d)/1e4,m)),b.max-w.d<=n||(v=b.h/2,g.push(new i(b.x-v,b.y-v,v,t)),g.push(new i(b.x+v,b.y-v,v,t)),g.push(new i(b.x-v,b.y+v,v,t)),g.push(new i(b.x+v,b.y+v,v,t)),m+=4)}e&&(console.info("num probes: "+m),console.info("best distance: "+w.d));return[w.x,w.y]}},{tinyqueue:2}],2:[function(t,n,e){"use strict";function r(t,n){if(!(this instanceof r))return new r(t,n);if(this.data=t||[],this.length=this.data.length,this.compare=n||o,t)for(var e=Math.floor(this.length/2);e>=0;e--)this._down(e)}function o(t,n){return t<n?-1:t>n?1:0}function i(t,n,e){var r=t[n];t[n]=t[e],t[e]=r}n.exports=r,r.prototype={push:function(t){this.data.push(t),this.length++,this._up(this.length-1)},pop:function(){var t=this.data[0];return this.data[0]=this.data[this.length-1],this.length--,this.data.pop(),this._down(0),t},peek:function(){return this.data[0]},_up:function(t){for(var n=this.data,e=this.compare;t>0;){var r=Math.floor((t-1)/2);if(!(e(n[t],n[r])<0))break;i(n,r,t),t=r}},_down:function(t){for(var n=this.data,e=this.compare,r=this.length;;){var o=2*t+1,a=o+1,u=t;if(o<r&&e(n[o],n[u])<0&&(u=o),a<r&&e(n[a],n[u])<0&&(u=a),u===t)return;i(n,u,t),t=u}}}},{}]},{},[1])(1)});
|
||||
2
libs/three.min.js
vendored
2
libs/three.min.js
vendored
File diff suppressed because one or more lines are too long
53
main.js
53
main.js
|
|
@ -92,16 +92,19 @@ let fogging = viewbox
|
|||
let ruler = viewbox.append("g").attr("id", "ruler").style("display", "none");
|
||||
let debug = viewbox.append("g").attr("id", "debug");
|
||||
|
||||
// lake and coast groups
|
||||
lakes.append("g").attr("id", "freshwater");
|
||||
lakes.append("g").attr("id", "salt");
|
||||
lakes.append("g").attr("id", "sinkhole");
|
||||
lakes.append("g").attr("id", "frozen");
|
||||
lakes.append("g").attr("id", "lava");
|
||||
lakes.append("g").attr("id", "dry");
|
||||
|
||||
coastline.append("g").attr("id", "sea_island");
|
||||
coastline.append("g").attr("id", "lake_island");
|
||||
|
||||
terrs.append("g").attr("id", "oceanHeights");
|
||||
terrs.append("g").attr("id", "landHeights");
|
||||
|
||||
labels.append("g").attr("id", "states");
|
||||
labels.append("g").attr("id", "addedLabels");
|
||||
|
||||
|
|
@ -841,8 +844,8 @@ function openNearSeaLakes() {
|
|||
const LIMIT = 22; // max height that can be breached by water
|
||||
|
||||
for (const i of cells.i) {
|
||||
const lake = cells.f[i];
|
||||
if (features[lake].type !== "lake") continue; // not a lake cell
|
||||
const lakeFeatureId = cells.f[i];
|
||||
if (features[lakeFeatureId].type !== "lake") continue; // not a lake
|
||||
|
||||
check_neighbours: for (const c of cells.c[i]) {
|
||||
if (cells.t[c] !== 1 || cells.h[c] > LIMIT) continue; // water cannot break this
|
||||
|
|
@ -850,20 +853,24 @@ function openNearSeaLakes() {
|
|||
for (const n of cells.c[c]) {
|
||||
const ocean = cells.f[n];
|
||||
if (features[ocean].type !== "ocean") continue; // not an ocean
|
||||
removeLake(c, lake, ocean);
|
||||
removeLake(c, lakeFeatureId, ocean);
|
||||
break check_neighbours;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeLake(threshold, lake, ocean) {
|
||||
cells.h[threshold] = 19;
|
||||
cells.t[threshold] = -1;
|
||||
cells.f[threshold] = ocean;
|
||||
cells.c[threshold].forEach(function (c) {
|
||||
function removeLake(thresholdCellId, lakeFeatureId, oceanFeatureId) {
|
||||
cells.h[thresholdCellId] = 19;
|
||||
cells.t[thresholdCellId] = -1;
|
||||
cells.f[thresholdCellId] = oceanFeatureId;
|
||||
cells.c[thresholdCellId].forEach(function (c) {
|
||||
if (cells.h[c] >= 20) cells.t[c] = 1; // mark as coastline
|
||||
});
|
||||
features[lake].type = "ocean"; // mark former lake as ocean
|
||||
|
||||
cells.i.forEach(i => {
|
||||
if (cells.f[i] === lakeFeatureId) cells.f[i] = oceanFeatureId;
|
||||
});
|
||||
features[lakeFeatureId].type = "ocean"; // mark former lake as ocean
|
||||
}
|
||||
|
||||
TIME && console.timeEnd("openLakes");
|
||||
|
|
@ -1250,6 +1257,7 @@ function drawCoastline() {
|
|||
features[f].vertices = vchain;
|
||||
|
||||
const path = round(lineGen(points));
|
||||
|
||||
if (features[f].type === "lake") {
|
||||
landMask
|
||||
.append("path")
|
||||
|
|
@ -1347,22 +1355,14 @@ function drawCoastline() {
|
|||
// Re-mark features (ocean, lakes, islands)
|
||||
function reMarkFeatures() {
|
||||
TIME && console.time("reMarkFeatures");
|
||||
const cells = pack.cells,
|
||||
features = (pack.features = [0]);
|
||||
const cells = pack.cells;
|
||||
const features = (pack.features = [0]);
|
||||
|
||||
cells.f = new Uint16Array(cells.i.length); // cell feature number
|
||||
cells.t = new Int8Array(cells.i.length); // cell type: 1 = land along coast; -1 = water along coast;
|
||||
cells.haven = cells.i.length < 65535 ? new Uint16Array(cells.i.length) : new Uint32Array(cells.i.length); // cell haven (opposite water cell);
|
||||
cells.harbor = new Uint8Array(cells.i.length); // cell harbor (number of adjacent water cells);
|
||||
|
||||
const defineHaven = i => {
|
||||
const water = cells.c[i].filter(c => cells.h[c] < 20);
|
||||
const dist2 = water.map(c => (cells.p[i][0] - cells.p[c][0]) ** 2 + (cells.p[i][1] - cells.p[c][1]) ** 2);
|
||||
const closest = water[dist2.indexOf(Math.min.apply(Math, dist2))];
|
||||
|
||||
cells.haven[i] = closest;
|
||||
cells.harbor[i] = water.length;
|
||||
};
|
||||
|
||||
if (!cells.i.length) return; // no cells -> there is nothing to do
|
||||
for (let i = 1, queue = [0]; queue[0] !== -1; i++) {
|
||||
const start = queue[0]; // first cell
|
||||
|
|
@ -1403,6 +1403,15 @@ function reMarkFeatures() {
|
|||
// markupPackLand
|
||||
markup(pack.cells, 3, 1, 0);
|
||||
|
||||
function defineHaven(i) {
|
||||
const water = cells.c[i].filter(c => cells.h[c] < 20);
|
||||
const dist2 = water.map(c => (cells.p[i][0] - cells.p[c][0]) ** 2 + (cells.p[i][1] - cells.p[c][1]) ** 2);
|
||||
const closest = water[dist2.indexOf(Math.min.apply(Math, dist2))];
|
||||
|
||||
cells.haven[i] = closest;
|
||||
cells.harbor[i] = water.length;
|
||||
}
|
||||
|
||||
function defineOceanGroup(number) {
|
||||
if (number > grid.cells.i.length / 25) return "ocean";
|
||||
if (number > grid.cells.i.length / 100) return "sea";
|
||||
|
|
@ -1925,7 +1934,7 @@ function showStatistics() {
|
|||
|
||||
mapId = Date.now(); // unique map id is it's creation date number
|
||||
mapHistory.push({seed, width: graphWidth, height: graphHeight, template: heightmap, created: mapId});
|
||||
INFO && console.log(stats);
|
||||
INFO && console.info(stats);
|
||||
}
|
||||
|
||||
const regenerateMap = debounce(async function (options) {
|
||||
|
|
|
|||
|
|
@ -71,28 +71,31 @@ window.Cultures = (function () {
|
|||
return;
|
||||
}
|
||||
|
||||
const cell = (c.center = placeCenter(c.sort ? c.sort : i => cells.s[i]));
|
||||
centers.add(cells.p[cell]);
|
||||
const sortingFn = c.sort ? c.sort : i => cells.s[i];
|
||||
const center = placeCenter(sortingFn);
|
||||
|
||||
centers.add(cells.p[center]);
|
||||
c.center = center;
|
||||
c.i = newId;
|
||||
delete c.odd;
|
||||
delete c.sort;
|
||||
c.color = colors[i];
|
||||
c.type = defineCultureType(cell);
|
||||
c.type = defineCultureType(center);
|
||||
c.expansionism = defineCultureExpansionism(c.type);
|
||||
c.origins = [0];
|
||||
c.code = abbreviate(c.name, codes);
|
||||
codes.push(c.code);
|
||||
cultureIds[cell] = newId;
|
||||
cultureIds[center] = newId;
|
||||
if (emblemShape === "random") c.shield = getRandomShield();
|
||||
});
|
||||
|
||||
cells.culture = cultureIds;
|
||||
|
||||
function placeCenter(v) {
|
||||
function placeCenter(sortingFn) {
|
||||
let spacing = (graphWidth + graphHeight) / 2 / count;
|
||||
const MAX_ATTEMPTS = 100;
|
||||
|
||||
const sorted = [...populated].sort((a, b) => v(b) - v(a));
|
||||
const sorted = [...populated].sort((a, b) => sortingFn(b) - sortingFn(a));
|
||||
const max = Math.floor(sorted.length / 2);
|
||||
|
||||
let cellId = 0;
|
||||
|
|
|
|||
|
|
@ -736,4 +736,95 @@ export function resolveVersionConflicts(version) {
|
|||
.style("display", "none");
|
||||
vignette.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%");
|
||||
}
|
||||
|
||||
if (version < 1.96) {
|
||||
// v1.96 added ocean rendering for heightmap
|
||||
terrs.selectAll("*").remove();
|
||||
|
||||
const opacity = terrs.attr("opacity");
|
||||
const filter = terrs.attr("filter");
|
||||
const scheme = terrs.attr("scheme");
|
||||
const terracing = terrs.attr("terracing");
|
||||
const skip = terrs.attr("skip");
|
||||
const relax = terrs.attr("relax");
|
||||
|
||||
const curveTypes = {0: "curveBasisClosed", 1: "curveLinear", 2: "curveStep"};
|
||||
const curve = curveTypes[terrs.attr("curve")] || "curveBasisClosed";
|
||||
|
||||
terrs
|
||||
.attr("mask", null)
|
||||
.attr("scheme", null)
|
||||
.attr("terracing", null)
|
||||
.attr("skip", null)
|
||||
.attr("relax", null)
|
||||
.attr("curve", null);
|
||||
|
||||
terrs
|
||||
.append("g")
|
||||
.attr("id", "oceanHeights")
|
||||
.attr("data-render", 0)
|
||||
.attr("opacity", opacity)
|
||||
.attr("filter", filter)
|
||||
.attr("scheme", scheme)
|
||||
.attr("terracing", 0)
|
||||
.attr("skip", 0)
|
||||
.attr("relax", 1)
|
||||
.attr("curve", curve);
|
||||
terrs
|
||||
.append("g")
|
||||
.attr("id", "landHeights")
|
||||
.attr("opacity", opacity)
|
||||
.attr("scheme", scheme)
|
||||
.attr("filter", filter)
|
||||
.attr("terracing", terracing)
|
||||
.attr("skip", skip)
|
||||
.attr("relax", relax)
|
||||
.attr("curve", curve)
|
||||
.attr("mask", "url(#land)");
|
||||
|
||||
if (layerIsOn("toggleHeight")) drawHeightmap();
|
||||
|
||||
// v1.96.00 moved scaleBar options from units editor to style
|
||||
d3.select("#scaleBar").remove();
|
||||
|
||||
scaleBar = svg
|
||||
.insert("g", "#viewbox + *")
|
||||
.attr("id", "scaleBar")
|
||||
.attr("opacity", 1)
|
||||
.attr("fill", "#353540")
|
||||
.attr("data-bar-size", 2)
|
||||
.attr("font-size", 10)
|
||||
.attr("data-x", 99)
|
||||
.attr("data-y", 99)
|
||||
.attr("data-label", "");
|
||||
|
||||
scaleBar
|
||||
.append("rect")
|
||||
.attr("id", "scaleBarBack")
|
||||
.attr("opacity", 0.2)
|
||||
.attr("fill", "#ffffff")
|
||||
.attr("stroke", "#000000")
|
||||
.attr("stroke-width", 1)
|
||||
.attr("filter", "url(#blur5)")
|
||||
.attr("data-top", 20)
|
||||
.attr("data-right", 15)
|
||||
.attr("data-bottom", 15)
|
||||
.attr("data-left", 10);
|
||||
|
||||
drawScaleBar(scaleBar, scale);
|
||||
fitScaleBar(scaleBar, svgWidth, svgHeight);
|
||||
|
||||
if (!layerIsOn("toggleScaleBar")) scaleBar.style("display", "none");
|
||||
|
||||
// v1.96.00 changed coloring approach for regiments
|
||||
armies.selectAll(":scope > g").each(function () {
|
||||
const fill = this.getAttribute("fill");
|
||||
if (!fill) return;
|
||||
const darkerColor = d3.color(fill).darker().hex();
|
||||
this.setAttribute("color", darkerColor);
|
||||
this.querySelectorAll("g > rect:nth-child(2)").forEach(rect => {
|
||||
rect.setAttribute("fill", "currentColor");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,13 +434,13 @@ function editStateName(state) {
|
|||
modules.editStateName = true;
|
||||
|
||||
// add listeners
|
||||
byId("stateNameEditorShortCulture").on("click", regenerateShortNameCuture);
|
||||
byId("stateNameEditorShortCulture").on("click", regenerateShortNameCulture);
|
||||
byId("stateNameEditorShortRandom").on("click", regenerateShortNameRandom);
|
||||
byId("stateNameEditorAddForm").on("click", addCustomForm);
|
||||
byId("stateNameEditorCustomForm").on("change", addCustomForm);
|
||||
byId("stateNameEditorFullRegenerate").on("click", regenerateFullName);
|
||||
|
||||
function regenerateShortNameCuture() {
|
||||
function regenerateShortNameCulture() {
|
||||
const state = +stateNameEditor.dataset.state;
|
||||
const culture = pack.states[state].culture;
|
||||
const name = Names.getState(Names.getCultureShort(culture), culture);
|
||||
|
|
@ -1394,6 +1394,7 @@ function openStateMergeDialog() {
|
|||
|
||||
function mergeStates(statesToMerge, rulingStateId) {
|
||||
const rulingState = pack.states[rulingStateId];
|
||||
const rulingStateArmy = byId("army" + rulingStateId);
|
||||
|
||||
// remove states to be merged
|
||||
statesToMerge.forEach(stateId => {
|
||||
|
|
@ -1410,27 +1411,25 @@ function openStateMergeDialog() {
|
|||
emblems.select(`#stateEmblems > use[data-i='${stateId}']`).remove();
|
||||
|
||||
// add merged state regiments to the ruling state
|
||||
state.military.forEach(m => {
|
||||
const oldId = `regiment${stateId}-${m.i}`;
|
||||
|
||||
const newRegiment = {...m, i: rulingState.military.length};
|
||||
rulingState.military.push(newRegiment);
|
||||
|
||||
const newId = `regiment${rulingStateId}-${newRegiment.i}`;
|
||||
state.military.forEach(regiment => {
|
||||
const oldId = `regiment${stateId}-${regiment.i}`;
|
||||
const newIndex = rulingState.military.length;
|
||||
rulingState.military.push({...regiment, i: newIndex});
|
||||
const newId = `regiment${rulingStateId}-${newIndex}`;
|
||||
|
||||
const note = notes.find(n => n.id === oldId);
|
||||
if (note) note.id = newId;
|
||||
|
||||
const rulingStateArmy = armies.select("g#army" + rulingStateId);
|
||||
armies
|
||||
.select("g#army" + stateId)
|
||||
.selectAll("g")
|
||||
.each(function () {
|
||||
this.setAttribute("id", newId);
|
||||
rulingStateArmy.node().appendChild(this);
|
||||
});
|
||||
armies.select("g#army" + stateId).remove();
|
||||
const element = byId(oldId);
|
||||
if (element) {
|
||||
element.id = newId;
|
||||
element.dataset.state = rulingStateId;
|
||||
element.dataset.i = newIndex;
|
||||
rulingStateArmy.appendChild(element);
|
||||
}
|
||||
});
|
||||
|
||||
armies.select("g#army" + stateId).remove();
|
||||
});
|
||||
|
||||
// reassing burgs
|
||||
|
|
|
|||
|
|
@ -88,12 +88,6 @@ function getSettings() {
|
|||
heightUnit: heightUnit.value,
|
||||
heightExponent: heightExponentInput.value,
|
||||
temperatureScale: temperatureScale.value,
|
||||
barSize: barSizeInput.value,
|
||||
barLabel: barLabel.value,
|
||||
barBackOpacity: barBackOpacity.value,
|
||||
barBackColor: barBackColor.value,
|
||||
barPosX: barPosX.value,
|
||||
barPosY: barPosY.value,
|
||||
populationRate: populationRate,
|
||||
urbanization: urbanization,
|
||||
mapSize: mapSizeOutput.value,
|
||||
|
|
|
|||
|
|
@ -314,6 +314,6 @@ function confirmHeightmapEdit() {
|
|||
function getHeightmapPreview(heights) {
|
||||
const scheme = getColorScheme(byId("heightmapSelectionColorScheme").value);
|
||||
const renderOcean = byId("heightmapSelectionRenderOcean").checked;
|
||||
const dataUrl = drawHeights({heights, width: grid.cellsX, height: grid.cellsY, scheme, renderOcean});
|
||||
const dataUrl = drawHeights({heights, width: graph.cellsX, height: graph.cellsY, scheme, renderOcean});
|
||||
return dataUrl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ window.Cloud = (function () {
|
|||
|
||||
async save(fileName, contents) {
|
||||
const resp = await this.call("filesUpload", {path: "/" + fileName, contents});
|
||||
DEBUG && console.log("Dropbox response:", resp);
|
||||
DEBUG && console.info("Dropbox response:", resp);
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ window.Cloud = (function () {
|
|||
|
||||
// Callback function for auth window
|
||||
async setDropBoxToken(token) {
|
||||
DEBUG && console.log("Access token:", token);
|
||||
DEBUG && console.info("Access token:", token);
|
||||
setToken(this.name, token);
|
||||
await this.connect(token);
|
||||
this.authWindow.close();
|
||||
|
|
@ -131,7 +131,7 @@ window.Cloud = (function () {
|
|||
allow_download: true
|
||||
};
|
||||
const resp = await this.call("sharingCreateSharedLinkWithSettings", {path, settings});
|
||||
DEBUG && console.log("Dropbox link object:", resp.result);
|
||||
DEBUG && console.info("Dropbox link object:", resp.result);
|
||||
return resp.result.url;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ async function quickLoad() {
|
|||
async function loadFromDropbox() {
|
||||
const mapPath = byId("loadFromDropboxSelect")?.value;
|
||||
|
||||
DEBUG && console.log("Loading map from Dropbox:", mapPath);
|
||||
DEBUG && console.info("Loading map from Dropbox:", mapPath);
|
||||
const blob = await Cloud.providers.dropbox.load(mapPath);
|
||||
uploadMap(blob);
|
||||
}
|
||||
|
|
@ -183,22 +183,22 @@ function showUploadMessage(type, mapData, mapVersion) {
|
|||
title = "Newer file";
|
||||
canBeLoaded = false;
|
||||
} else if (type === "outdated") {
|
||||
message = `The map version (${mapVersion}) does not match the Generator version (${version}).<br>That is fine, click OK to the get map <b style="color: #005000">auto-updated</b>.<br>In case of issues please keep using an ${archive} of the Generator`;
|
||||
title = "Outdated file";
|
||||
canBeLoaded = true;
|
||||
INFO && console.info(`Loading map. Auto-update from ${mapVersion} to ${version}`);
|
||||
parseLoadedData(mapData, mapVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
alertMessage.innerHTML = message;
|
||||
const buttons = {
|
||||
OK: function () {
|
||||
$(this).dialog("close");
|
||||
if (canBeLoaded) parseLoadedData(mapData);
|
||||
if (canBeLoaded) parseLoadedData(mapData, mapVersion);
|
||||
}
|
||||
};
|
||||
$("#alert").dialog({title, buttons});
|
||||
}
|
||||
|
||||
async function parseLoadedData(data) {
|
||||
async function parseLoadedData(data, mapVersion) {
|
||||
try {
|
||||
// exit customization
|
||||
if (window.closeDialogs) closeDialogs();
|
||||
|
|
@ -218,6 +218,7 @@ async function parseLoadedData(data) {
|
|||
|
||||
INFO && console.group("Loaded Map " + seed);
|
||||
|
||||
// TODO: move all to options object
|
||||
void (function parseSettings() {
|
||||
const settings = data[1].split("|");
|
||||
if (settings[0]) applyOption(distanceUnitInput, settings[0]);
|
||||
|
|
@ -226,23 +227,16 @@ async function parseLoadedData(data) {
|
|||
if (settings[3]) applyOption(heightUnit, settings[3]);
|
||||
if (settings[4]) heightExponentInput.value = heightExponentOutput.value = settings[4];
|
||||
if (settings[5]) temperatureScale.value = settings[5];
|
||||
if (settings[6]) barSizeInput.value = barSizeOutput.value = settings[6];
|
||||
if (settings[7] !== undefined) barLabel.value = settings[7];
|
||||
if (settings[8] !== undefined) barBackOpacity.value = settings[8];
|
||||
if (settings[9]) barBackColor.value = settings[9];
|
||||
if (settings[10]) barPosX.value = settings[10];
|
||||
if (settings[11]) barPosY.value = settings[11];
|
||||
// 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[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];
|
||||
|
||||
if (settings[19]) options = JSON.parse(settings[19]);
|
||||
// setting 16 and 17 (temperature) are part of options now, kept as "" in newer versions for compatibility
|
||||
if (settings[16]) options.temperatureEquator = +settings[16];
|
||||
if (settings[17]) options.temperatureNorthPole = options.temperatureSouthPole = +settings[17];
|
||||
|
||||
if (settings[20]) mapName.value = settings[20];
|
||||
if (settings[21]) hideLabels.checked = +settings[21];
|
||||
if (settings[22]) stylePreset.value = settings[22];
|
||||
|
|
@ -462,16 +456,16 @@ async function parseLoadedData(data) {
|
|||
{
|
||||
// dynamically import and run auto-update script
|
||||
const versionNumber = parseFloat(params[0]);
|
||||
const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.95.00");
|
||||
const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.96.00");
|
||||
resolveVersionConflicts(versionNumber);
|
||||
}
|
||||
|
||||
{
|
||||
// add custom heightmap color scheme if any
|
||||
const scheme = terrs.attr("scheme");
|
||||
if (!(scheme in heightmapColorSchemes)) {
|
||||
addCustomColorScheme(scheme);
|
||||
}
|
||||
const oceanScheme = terrs.select("#oceanHeights").attr("scheme");
|
||||
const landScheme = terrs.select("#landHeights").attr("scheme");
|
||||
if (!(oceanScheme in heightmapColorSchemes)) addCustomColorScheme(oceanScheme);
|
||||
if (!(landScheme in heightmapColorSchemes)) addCustomColorScheme(landScheme);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -645,7 +639,7 @@ async function parseLoadedData(data) {
|
|||
ERROR && console.error(error);
|
||||
clearMainTip();
|
||||
|
||||
alertMessage.innerHTML = /* html */ `An error is occured on map loading. Select a different file to load, <br />generate a new random map or cancel the loading
|
||||
alertMessage.innerHTML = /* html */ `An error is occured on map loading. Select a different file to load, <br>generate a new random map or cancel the loading.<br>Map version: ${mapVersion}. Generator version: ${version}.
|
||||
<p id="errorBox">${parseError(error)}</p>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ function prepareMapData() {
|
|||
heightUnit.value,
|
||||
heightExponentInput.value,
|
||||
temperatureScale.value,
|
||||
barSizeInput.value,
|
||||
barLabel.value,
|
||||
barBackOpacity.value,
|
||||
barBackColor.value,
|
||||
barPosX.value,
|
||||
barPosY.value,
|
||||
"", // previously used for barSize.value
|
||||
"", // previously used for barLabel.value
|
||||
"", // previously used for barBackColor.value
|
||||
"", // previously used for barBackColor.value
|
||||
"", // previously used for barPosX.value
|
||||
"", // previously used for barPosY.value
|
||||
populationRate,
|
||||
urbanization,
|
||||
mapSizeOutput.value,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,18 @@ window.Military = (function () {
|
|||
|
||||
const expn = d3.sum(valid.map(s => s.expansionism)); // total expansion
|
||||
const area = d3.sum(valid.map(s => s.area)); // total area
|
||||
const rate = {x: 0, Ally: -0.2, Friendly: -0.1, Neutral: 0, Suspicion: 0.1, Enemy: 1, Unknown: 0, Rival: 0.5, Vassal: 0.5, Suzerain: -0.5};
|
||||
const rate = {
|
||||
x: 0,
|
||||
Ally: -0.2,
|
||||
Friendly: -0.1,
|
||||
Neutral: 0,
|
||||
Suspicion: 0.1,
|
||||
Enemy: 1,
|
||||
Unknown: 0,
|
||||
Rival: 0.5,
|
||||
Vassal: 0.5,
|
||||
Suzerain: -0.5
|
||||
};
|
||||
|
||||
const stateModifier = {
|
||||
melee: {Nomadic: 0.5, Highland: 1.2, Lake: 1, Naval: 0.7, Hunting: 1.2, River: 1.1},
|
||||
|
|
@ -24,14 +35,59 @@ window.Military = (function () {
|
|||
};
|
||||
|
||||
const cellTypeModifier = {
|
||||
nomadic: {melee: 0.2, ranged: 0.5, mounted: 3, machinery: 0.4, naval: 0.3, armored: 1.6, aviation: 1, magical: 0.5},
|
||||
wetland: {melee: 0.8, ranged: 2, mounted: 0.3, machinery: 1.2, naval: 1.0, armored: 0.2, aviation: 0.5, magical: 0.5},
|
||||
highland: {melee: 1.2, ranged: 1.6, mounted: 0.3, machinery: 3, naval: 1.0, armored: 0.8, aviation: 0.3, magical: 2}
|
||||
nomadic: {
|
||||
melee: 0.2,
|
||||
ranged: 0.5,
|
||||
mounted: 3,
|
||||
machinery: 0.4,
|
||||
naval: 0.3,
|
||||
armored: 1.6,
|
||||
aviation: 1,
|
||||
magical: 0.5
|
||||
},
|
||||
wetland: {
|
||||
melee: 0.8,
|
||||
ranged: 2,
|
||||
mounted: 0.3,
|
||||
machinery: 1.2,
|
||||
naval: 1.0,
|
||||
armored: 0.2,
|
||||
aviation: 0.5,
|
||||
magical: 0.5
|
||||
},
|
||||
highland: {
|
||||
melee: 1.2,
|
||||
ranged: 1.6,
|
||||
mounted: 0.3,
|
||||
machinery: 3,
|
||||
naval: 1.0,
|
||||
armored: 0.8,
|
||||
aviation: 0.3,
|
||||
magical: 2
|
||||
}
|
||||
};
|
||||
|
||||
const burgTypeModifier = {
|
||||
nomadic: {melee: 0.3, ranged: 0.8, mounted: 3, machinery: 0.4, naval: 1.0, armored: 1.6, aviation: 1, magical: 0.5},
|
||||
wetland: {melee: 1, ranged: 1.6, mounted: 0.2, machinery: 1.2, naval: 1.0, armored: 0.2, aviation: 0.5, magical: 0.5},
|
||||
nomadic: {
|
||||
melee: 0.3,
|
||||
ranged: 0.8,
|
||||
mounted: 3,
|
||||
machinery: 0.4,
|
||||
naval: 1.0,
|
||||
armored: 1.6,
|
||||
aviation: 1,
|
||||
magical: 0.5
|
||||
},
|
||||
wetland: {
|
||||
melee: 1,
|
||||
ranged: 1.6,
|
||||
mounted: 0.2,
|
||||
machinery: 1.2,
|
||||
naval: 1.0,
|
||||
armored: 0.2,
|
||||
aviation: 0.5,
|
||||
magical: 0.5
|
||||
},
|
||||
highland: {melee: 1.2, ranged: 2, mounted: 0.3, machinery: 3, naval: 1.0, armored: 0.8, aviation: 0.3, magical: 2}
|
||||
};
|
||||
|
||||
|
|
@ -40,8 +96,16 @@ window.Military = (function () {
|
|||
const d = s.diplomacy;
|
||||
|
||||
const expansionRate = minmax(s.expansionism / expn / (s.area / area), 0.25, 4); // how much state expansionism is realized
|
||||
const diplomacyRate = d.some(d => d === "Enemy") ? 1 : d.some(d => d === "Rival") ? 0.8 : d.some(d => d === "Suspicion") ? 0.5 : 0.1; // peacefulness
|
||||
const neighborsRateRaw = s.neighbors.map(n => (n ? pack.states[n].diplomacy[s.i] : "Suspicion")).reduce((s, r) => (s += rate[r]), 0.5);
|
||||
const diplomacyRate = d.some(d => d === "Enemy")
|
||||
? 1
|
||||
: d.some(d => d === "Rival")
|
||||
? 0.8
|
||||
: d.some(d => d === "Suspicion")
|
||||
? 0.5
|
||||
: 0.1; // peacefulness
|
||||
const neighborsRateRaw = s.neighbors
|
||||
.map(n => (n ? pack.states[n].diplomacy[s.i] : "Suspicion"))
|
||||
.reduce((s, r) => (s += rate[r]), 0.5);
|
||||
const neighborsRate = minmax(neighborsRateRaw, 0.3, 3); // neighbors rate
|
||||
s.alert = minmax(rn(expansionRate * diplomacyRate * neighborsRate, 2), 0.1, 5); // alert rate (area modifier)
|
||||
s.temp.platoons = [];
|
||||
|
|
@ -86,8 +150,10 @@ window.Military = (function () {
|
|||
|
||||
let modifier = cells.pop[i] / 100; // basic rural army in percentages
|
||||
if (culture !== stateObj.culture) modifier = stateObj.form === "Union" ? modifier / 1.2 : modifier / 2; // non-dominant culture
|
||||
if (religion !== cells.religion[stateObj.center]) modifier = stateObj.form === "Theocracy" ? modifier / 2.2 : modifier / 1.4; // non-dominant religion
|
||||
if (cells.f[i] !== cells.f[stateObj.center]) modifier = stateObj.type === "Naval" ? modifier / 1.2 : modifier / 1.8; // different landmass
|
||||
if (religion !== cells.religion[stateObj.center])
|
||||
modifier = stateObj.form === "Theocracy" ? modifier / 2.2 : modifier / 1.4; // non-dominant religion
|
||||
if (cells.f[i] !== cells.f[stateObj.center])
|
||||
modifier = stateObj.type === "Naval" ? modifier / 1.2 : modifier / 1.8; // different landmass
|
||||
const type = getType(i);
|
||||
|
||||
for (const unit of options.military) {
|
||||
|
|
@ -111,7 +177,17 @@ window.Military = (function () {
|
|||
n = 1;
|
||||
}
|
||||
|
||||
stateObj.temp.platoons.push({cell: i, a: total, t: total, x, y, u: unit.name, n, s: unit.separate, type: unit.type});
|
||||
stateObj.temp.platoons.push({
|
||||
cell: i,
|
||||
a: total,
|
||||
t: total,
|
||||
x,
|
||||
y,
|
||||
u: unit.name,
|
||||
n,
|
||||
s: unit.separate,
|
||||
type: unit.type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +229,17 @@ window.Military = (function () {
|
|||
n = 1;
|
||||
}
|
||||
|
||||
stateObj.temp.platoons.push({cell: b.cell, a: total, t: total, x, y, u: unit.name, n, s: unit.separate, type: unit.type});
|
||||
stateObj.temp.platoons.push({
|
||||
cell: b.cell,
|
||||
a: total,
|
||||
t: total,
|
||||
x,
|
||||
y,
|
||||
u: unit.name,
|
||||
n,
|
||||
s: unit.separate,
|
||||
type: unit.type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +347,8 @@ window.Military = (function () {
|
|||
const army = armies
|
||||
.append("g")
|
||||
.attr("id", "army" + s)
|
||||
.attr("fill", baseColor);
|
||||
.attr("fill", baseColor)
|
||||
.attr("color", darkerColor);
|
||||
|
||||
const g = army
|
||||
.selectAll("g")
|
||||
|
|
@ -282,7 +369,7 @@ window.Military = (function () {
|
|||
.attr("y", d => d.y)
|
||||
.text(d => getTotal(d));
|
||||
g.append("rect")
|
||||
.attr("fill", darkerColor)
|
||||
.attr("fill", "currentColor")
|
||||
.attr("x", d => x(d) - h)
|
||||
.attr("y", d => y(d))
|
||||
.attr("width", h)
|
||||
|
|
@ -304,12 +391,13 @@ window.Military = (function () {
|
|||
let army = armies.select("g#army" + s);
|
||||
if (!army.size()) {
|
||||
const baseColor = pack.states[s].color[0] === "#" ? pack.states[s].color : "#999";
|
||||
const darkerColor = d3.color(army.attr("fill")).darker().hex();
|
||||
army = armies
|
||||
.append("g")
|
||||
.attr("id", "army" + s)
|
||||
.attr("fill", baseColor);
|
||||
.attr("fill", baseColor)
|
||||
.attr("color", darkerColor);
|
||||
}
|
||||
const darkerColor = d3.color(army.attr("fill")).darker().hex();
|
||||
|
||||
const g = army
|
||||
.append("g")
|
||||
|
|
@ -320,7 +408,7 @@ window.Military = (function () {
|
|||
g.append("rect").attr("x", x1).attr("y", y1).attr("width", w).attr("height", h);
|
||||
g.append("text").attr("x", reg.x).attr("y", reg.y).text(getTotal(reg));
|
||||
g.append("rect")
|
||||
.attr("fill", darkerColor)
|
||||
.attr("fill", "currentColor")
|
||||
.attr("x", x1 - h)
|
||||
.attr("y", y1)
|
||||
.attr("width", h)
|
||||
|
|
@ -379,7 +467,13 @@ window.Military = (function () {
|
|||
// get default regiment emblem
|
||||
const getEmblem = function (r) {
|
||||
if (!r.n && !Object.values(r.u).length) return "🔰"; // "Newbie" regiment without troops
|
||||
if (!r.n && pack.states[r.state].form === "Monarchy" && pack.cells.burg[r.cell] && pack.burgs[pack.cells.burg[r.cell]].capital) return "👑"; // "Royal" regiment based in capital
|
||||
if (
|
||||
!r.n &&
|
||||
pack.states[r.state].form === "Monarchy" &&
|
||||
pack.cells.burg[r.cell] &&
|
||||
pack.burgs[pack.cells.burg[r.cell]].capital
|
||||
)
|
||||
return "👑"; // "Royal" regiment based in capital
|
||||
const mainUnit = Object.entries(r.u).sort((a, b) => b[1] - a[1])[0][0]; // unit with more troops in regiment
|
||||
const unit = options.military.find(u => u.name === mainUnit);
|
||||
return unit.icon;
|
||||
|
|
@ -400,7 +494,9 @@ window.Military = (function () {
|
|||
.map(t => `— ${t}: ${r.u[t]}`)
|
||||
.join("\r\n")
|
||||
: null;
|
||||
const troops = composition ? `\r\n\r\nRegiment composition in ${options.year} ${options.eraShort}:\r\n${composition}.` : "";
|
||||
const troops = composition
|
||||
? `\r\n\r\nRegiment composition in ${options.year} ${options.eraShort}:\r\n${composition}.`
|
||||
: "";
|
||||
|
||||
const campaign = s.campaigns ? ra(s.campaigns) : null;
|
||||
const year = campaign ? rand(campaign.start, campaign.end) : gauss(options.year - 100, 150, 1, options.year - 6);
|
||||
|
|
@ -409,5 +505,16 @@ window.Military = (function () {
|
|||
notes.push({id: `regiment${s.i}-${r.i}`, name: `${r.icon} ${r.name}`, legend});
|
||||
};
|
||||
|
||||
return {generate, redraw, getDefaultOptions, getName, generateNote, drawRegiments, drawRegiment, moveRegiment, getTotal, getEmblem};
|
||||
return {
|
||||
generate,
|
||||
redraw,
|
||||
getDefaultOptions,
|
||||
getName,
|
||||
generateNote,
|
||||
drawRegiments,
|
||||
drawRegiment,
|
||||
moveRegiment,
|
||||
getTotal,
|
||||
getEmblem
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ window.Submap = (function () {
|
|||
|
||||
const projection = options.projection;
|
||||
const inverse = options.inverse;
|
||||
const stage = s => INFO && console.log("SUBMAP:", s);
|
||||
const stage = s => INFO && console.info("SUBMAP:", s);
|
||||
const timeStart = performance.now();
|
||||
invokeActiveZooming();
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ window.Submap = (function () {
|
|||
seed = parentMap.seed;
|
||||
Math.random = aleaPRNG(seed);
|
||||
INFO && console.group("SubMap with seed: " + seed);
|
||||
DEBUG && console.log("Using Options:", options);
|
||||
DEBUG && console.info("Using Options:", options);
|
||||
|
||||
// create new grid
|
||||
applyGraphSize();
|
||||
|
|
@ -396,7 +396,7 @@ window.Submap = (function () {
|
|||
b.removed = true;
|
||||
return;
|
||||
}
|
||||
DEBUG && console.log(`Moving ${b.name} from ${cityCell} to ${newCell} near ${neighbor}.`);
|
||||
DEBUG && console.info(`Moving ${b.name} from ${cityCell} to ${newCell} near ${neighbor}.`);
|
||||
[b.x, b.y] = b.port ? getMiddlePoint(newCell, neighbor) : cells.p[newCell];
|
||||
if (b.port) b.port = cells.f[neighbor]; // copy feature number
|
||||
b.cell = newCell;
|
||||
|
|
|
|||
|
|
@ -126,51 +126,6 @@ function editBurg(id) {
|
|||
}
|
||||
}
|
||||
|
||||
// in °C, array from -1 °C; source: https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature
|
||||
function getTemperatureLikeness(temperature) {
|
||||
if (temperature < -5) return "Yakutsk";
|
||||
const cities = [
|
||||
"Snag (Yukon)",
|
||||
"Yellowknife (Canada)",
|
||||
"Okhotsk (Russia)",
|
||||
"Fairbanks (Alaska)",
|
||||
"Nuuk (Greenland)",
|
||||
"Murmansk", // -5 - 0
|
||||
"Arkhangelsk",
|
||||
"Anchorage",
|
||||
"Tromsø",
|
||||
"Reykjavik",
|
||||
"Riga",
|
||||
"Stockholm",
|
||||
"Halifax",
|
||||
"Prague",
|
||||
"Copenhagen",
|
||||
"London", // 1 - 10
|
||||
"Antwerp",
|
||||
"Paris",
|
||||
"Milan",
|
||||
"Batumi",
|
||||
"Rome",
|
||||
"Dubrovnik",
|
||||
"Lisbon",
|
||||
"Barcelona",
|
||||
"Marrakesh",
|
||||
"Alexandria", // 11 - 20
|
||||
"Tegucigalpa",
|
||||
"Guangzhou",
|
||||
"Rio de Janeiro",
|
||||
"Dakar",
|
||||
"Miami",
|
||||
"Jakarta",
|
||||
"Mogadishu",
|
||||
"Bangkok",
|
||||
"Aden",
|
||||
"Khartoum"
|
||||
]; // 21 - 30
|
||||
if (temperature > 30) return "Mecca";
|
||||
return cities[temperature + 5] || null;
|
||||
}
|
||||
|
||||
function dragBurgLabel() {
|
||||
const tr = parseTransform(this.getAttribute("transform"));
|
||||
const dx = +tr[0] - d3.event.x,
|
||||
|
|
@ -284,7 +239,9 @@ function editBurg(id) {
|
|||
alertMessage.innerHTML = /* html */ `Are you sure you want to remove ${
|
||||
basic || capital ? "all unlocked elements in the burg group" : "the entire burg group"
|
||||
}?
|
||||
<br />Please note that capital or locked burgs will not be deleted. <br /><br />Burgs to be removed: ${burgsToRemove.length}`;
|
||||
<br />Please note that capital or locked burgs will not be deleted. <br /><br />Burgs to be removed: ${
|
||||
burgsToRemove.length
|
||||
}`;
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
title: "Remove burg group",
|
||||
|
|
@ -433,7 +390,8 @@ function editBurg(id) {
|
|||
function addCustomMfcgLink() {
|
||||
const id = +elSelected.attr("data-id");
|
||||
const burg = pack.burgs[id];
|
||||
const message = "Enter custom link to the burg map. It can be a link to Medieval Fantasy City Generator or other tool. Keep empty to use MFCG seed";
|
||||
const message =
|
||||
"Enter custom link to the burg map. It can be a link to Medieval Fantasy City Generator or other tool. Keep empty to use MFCG seed";
|
||||
prompt(message, {default: burg.link || "", required: false}, link => {
|
||||
if (link) burg.link = link;
|
||||
else delete burg.link;
|
||||
|
|
@ -581,3 +539,48 @@ function editBurg(id) {
|
|||
unselect();
|
||||
}
|
||||
}
|
||||
|
||||
// in °C, array from -1 °C; source: https://en.wikipedia.org/wiki/List_of_cities_by_average_temperature
|
||||
function getTemperatureLikeness(temperature) {
|
||||
if (temperature < -5) return "Yakutsk";
|
||||
const cities = [
|
||||
"Snag (Yukon)",
|
||||
"Yellowknife (Canada)",
|
||||
"Okhotsk (Russia)",
|
||||
"Fairbanks (Alaska)",
|
||||
"Nuuk (Greenland)",
|
||||
"Murmansk", // -5 - 0
|
||||
"Arkhangelsk",
|
||||
"Anchorage",
|
||||
"Tromsø",
|
||||
"Reykjavik",
|
||||
"Riga",
|
||||
"Stockholm",
|
||||
"Halifax",
|
||||
"Prague",
|
||||
"Copenhagen",
|
||||
"London", // 1 - 10
|
||||
"Antwerp",
|
||||
"Paris",
|
||||
"Milan",
|
||||
"Batumi",
|
||||
"Rome",
|
||||
"Dubrovnik",
|
||||
"Lisbon",
|
||||
"Barcelona",
|
||||
"Marrakesh",
|
||||
"Alexandria", // 11 - 20
|
||||
"Tegucigalpa",
|
||||
"Guangzhou",
|
||||
"Rio de Janeiro",
|
||||
"Dakar",
|
||||
"Miami",
|
||||
"Jakarta",
|
||||
"Mogadishu",
|
||||
"Bangkok",
|
||||
"Aden",
|
||||
"Khartoum"
|
||||
]; // 21 - 30
|
||||
if (temperature > 30) return "Mecca";
|
||||
return cities[temperature + 5] || null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
"use strict";
|
||||
function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
||||
function overviewBurgs(settings = {stateId: null, cultureId: null}) {
|
||||
if (customization) return;
|
||||
closeDialogs("#burgsOverview, .stable");
|
||||
if (!layerIsOn("toggleIcons")) toggleIcons();
|
||||
|
|
@ -45,7 +45,7 @@ function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
|||
|
||||
function updateFilter() {
|
||||
const stateFilter = byId("burgsFilterState");
|
||||
const selectedState = options.stateId !== null ? options.stateId : stateFilter.value || -1;
|
||||
const selectedState = settings.stateId !== null ? settings.stateId : stateFilter.value || -1;
|
||||
stateFilter.options.length = 0; // remove all options
|
||||
stateFilter.options.add(new Option("all", -1, false, selectedState === -1));
|
||||
stateFilter.options.add(new Option(pack.states[0].name, 0, false, selectedState === 0));
|
||||
|
|
@ -53,7 +53,7 @@ function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
|||
statesSorted.forEach(s => stateFilter.options.add(new Option(s.name, s.i, false, s.i == selectedState)));
|
||||
|
||||
const cultureFilter = byId("burgsFilterCulture");
|
||||
const selectedCulture = options.cultureId !== null ? options.cultureId : cultureFilter.value || -1;
|
||||
const selectedCulture = settings.cultureId !== null ? settings.cultureId : cultureFilter.value || -1;
|
||||
cultureFilter.options.length = 0; // remove all options
|
||||
cultureFilter.options.add(new Option(`all`, -1, false, selectedCulture === -1));
|
||||
cultureFilter.options.add(new Option(pack.cultures[0].name, 0, false, selectedCulture === 0));
|
||||
|
|
@ -480,10 +480,7 @@ function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
|||
}
|
||||
|
||||
function downloadBurgsData() {
|
||||
let data = `Id,Burg,Province,Province Full Name,State,State Full Name,Culture,Religion,Population,X,Y,Latitude,Longitude,Elevation (${heightUnit.value}),Capital,Port,Citadel,Walls,Plaza,Temple,Shanty Town`; // headers
|
||||
if (options.showMFCGMap) data += `,City Generator Link`;
|
||||
data += "\n";
|
||||
|
||||
let data = `Id,Burg,Province,Province Full Name,State,State Full Name,Culture,Religion,Population,X,Y,Latitude,Longitude,Elevation (${heightUnit.value}),Temperature,Temperature likeness,Capital,Port,Citadel,Walls,Plaza,Temple,Shanty Town,Emblem,City Generator Link\n`; // headers
|
||||
const valid = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs
|
||||
|
||||
valid.forEach(b => {
|
||||
|
|
@ -504,6 +501,9 @@ function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
|||
data += getLatitude(b.y, 2) + ",";
|
||||
data += getLongitude(b.x, 2) + ",";
|
||||
data += parseInt(getHeight(pack.cells.h[b.cell])) + ",";
|
||||
const temperature = grid.cells.temp[pack.cells.g[b.cell]];
|
||||
data += convertTemperature(temperature) + ",";
|
||||
data += getTemperatureLikeness(temperature) + ",";
|
||||
|
||||
// add status data
|
||||
data += b.capital ? "capital," : ",";
|
||||
|
|
@ -513,7 +513,9 @@ function overviewBurgs(options = {stateId: null, cultureId: null}) {
|
|||
data += b.plaza ? "plaza," : ",";
|
||||
data += b.temple ? "temple," : ",";
|
||||
data += b.shanty ? "shanty town," : ",";
|
||||
if (options.showMFCGMap) data += getMFCGlink(b);
|
||||
data += b.coa ? JSON.stringify(b.coa).replace(/"/g, "").replace(/,/g, ";") + "," : ",";
|
||||
data += getMFCGlink(b);
|
||||
|
||||
data += "\n";
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1176,18 +1176,18 @@ function refreshAllEditors() {
|
|||
// dynamically loaded editors
|
||||
async function editStates() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/states-editor.js?v=1.93.10");
|
||||
const Editor = await import("../dynamic/editors/states-editor.js?v=1.96.00");
|
||||
Editor.open();
|
||||
}
|
||||
|
||||
async function editCultures() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.95.04");
|
||||
const Editor = await import("../dynamic/editors/cultures-editor.js?v=1.96.00");
|
||||
Editor.open();
|
||||
}
|
||||
|
||||
async function editReligions() {
|
||||
if (customization) return;
|
||||
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.89.10");
|
||||
const Editor = await import("../dynamic/editors/religions-editor.js?v=1.96.00");
|
||||
Editor.open();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,92 +188,135 @@ function restoreLayers() {
|
|||
}
|
||||
|
||||
function toggleHeight(event) {
|
||||
if (customization === 1) {
|
||||
tip("You cannot turn off the layer when heightmap is in edit mode", false, "error");
|
||||
return;
|
||||
}
|
||||
if (customization === 1) return tip("You cannot turn off the layer when heightmap is in edit mode", false, "error");
|
||||
|
||||
if (!terrs.selectAll("*").size()) {
|
||||
const children = terrs.selectAll("#oceanHeights > *, #landHeights > *");
|
||||
if (!children.size()) {
|
||||
turnButtonOn("toggleHeight");
|
||||
drawHeightmap();
|
||||
if (event && isCtrlClick(event)) editStyle("terrs");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("terrs");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("terrs");
|
||||
turnButtonOff("toggleHeight");
|
||||
terrs.selectAll("*").remove();
|
||||
children.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function drawHeightmap() {
|
||||
TIME && console.time("drawHeightmap");
|
||||
terrs.selectAll("*").remove();
|
||||
|
||||
const {cells, vertices} = pack;
|
||||
const n = cells.i.length;
|
||||
const used = new Uint8Array(cells.i.length);
|
||||
const paths = new Array(101).fill("");
|
||||
const ocean = terrs.select("#oceanHeights");
|
||||
const land = terrs.select("#landHeights");
|
||||
|
||||
const scheme = getColorScheme(terrs.attr("scheme"));
|
||||
const terracing = terrs.attr("terracing") / 10; // add additional shifted darker layer for pseudo-3d effect
|
||||
const skip = +terrs.attr("skip") + 1;
|
||||
const simplification = +terrs.attr("relax");
|
||||
ocean.selectAll("*").remove();
|
||||
land.selectAll("*").remove();
|
||||
|
||||
switch (+terrs.attr("curve")) {
|
||||
case 0:
|
||||
lineGen.curve(d3.curveBasisClosed);
|
||||
break;
|
||||
case 1:
|
||||
lineGen.curve(d3.curveLinear);
|
||||
break;
|
||||
case 2:
|
||||
lineGen.curve(d3.curveStep);
|
||||
break;
|
||||
default:
|
||||
lineGen.curve(d3.curveBasisClosed);
|
||||
const paths = new Array(101);
|
||||
|
||||
// ocean cells
|
||||
const renderOceanCells = Boolean(+ocean.attr("data-render"));
|
||||
if (renderOceanCells) {
|
||||
const {cells, vertices} = grid;
|
||||
const used = new Uint8Array(cells.i.length);
|
||||
|
||||
const skip = +ocean.attr("skip") + 1 || 1;
|
||||
const relax = +ocean.attr("relax") || 0;
|
||||
lineGen.curve(d3[ocean.attr("curve") || "curveBasisClosed"]);
|
||||
|
||||
let currentLayer = 0;
|
||||
const heights = Array.from(cells.i).sort((a, b) => cells.h[a] - cells.h[b]);
|
||||
|
||||
for (const i of heights) {
|
||||
const h = cells.h[i];
|
||||
if (h > currentLayer) currentLayer += skip;
|
||||
if (h < currentLayer) continue;
|
||||
if (currentLayer >= 20) break;
|
||||
if (used[i]) continue; // already marked
|
||||
const onborder = cells.c[i].some(n => cells.h[n] < h);
|
||||
if (!onborder) continue;
|
||||
const vertex = cells.v[i].find(v => vertices.c[v].some(i => cells.h[i] < h));
|
||||
const chain = connectVertices(cells, vertices, vertex, h, used);
|
||||
if (chain.length < 3) continue;
|
||||
const points = simplifyLine(chain, relax).map(v => vertices.p[v]);
|
||||
if (!paths[h]) paths[h] = "";
|
||||
paths[h] += round(lineGen(points));
|
||||
}
|
||||
}
|
||||
|
||||
let currentLayer = 20;
|
||||
const heights = cells.i.sort((a, b) => cells.h[a] - cells.h[b]);
|
||||
for (const i of heights) {
|
||||
const h = cells.h[i];
|
||||
if (h > currentLayer) currentLayer += skip;
|
||||
if (currentLayer > 100) break; // no layers possible with height > 100
|
||||
if (h < currentLayer) continue;
|
||||
if (used[i]) continue; // already marked
|
||||
const onborder = cells.c[i].some(n => cells.h[n] < h);
|
||||
if (!onborder) continue;
|
||||
const vertex = cells.v[i].find(v => vertices.c[v].some(i => cells.h[i] < h));
|
||||
const chain = connectVertices(vertex, h);
|
||||
if (chain.length < 3) continue;
|
||||
const points = simplifyLine(chain).map(v => vertices.p[v]);
|
||||
paths[h] += round(lineGen(points));
|
||||
// land cells
|
||||
{
|
||||
const {cells, vertices} = pack;
|
||||
const used = new Uint8Array(cells.i.length);
|
||||
|
||||
const skip = +land.attr("skip") + 1 || 1;
|
||||
const relax = +land.attr("relax") || 0;
|
||||
lineGen.curve(d3[land.attr("curve") || "curveBasisClosed"]);
|
||||
|
||||
let currentLayer = 20;
|
||||
const heights = Array.from(cells.i).sort((a, b) => cells.h[a] - cells.h[b]);
|
||||
for (const i of heights) {
|
||||
const h = cells.h[i];
|
||||
if (h > currentLayer) currentLayer += skip;
|
||||
if (h < currentLayer) continue;
|
||||
if (currentLayer > 100) break; // no layers possible with height > 100
|
||||
if (used[i]) continue; // already marked
|
||||
const onborder = cells.c[i].some(n => cells.h[n] < h);
|
||||
if (!onborder) continue;
|
||||
const vertex = cells.v[i].find(v => vertices.c[v].some(i => cells.h[i] < h));
|
||||
const chain = connectVertices(cells, vertices, vertex, h, used);
|
||||
if (chain.length < 3) continue;
|
||||
const points = simplifyLine(chain, relax).map(v => vertices.p[v]);
|
||||
if (!paths[h]) paths[h] = "";
|
||||
paths[h] += round(lineGen(points));
|
||||
}
|
||||
}
|
||||
|
||||
terrs
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", graphWidth)
|
||||
.attr("height", graphHeight)
|
||||
.attr("fill", scheme(0.8)); // draw base layer
|
||||
for (const i of d3.range(20, 101)) {
|
||||
if (paths[i].length < 10) continue;
|
||||
const color = getColor(i, scheme);
|
||||
if (terracing)
|
||||
terrs
|
||||
.append("path")
|
||||
.attr("d", paths[i])
|
||||
.attr("transform", "translate(.7,1.4)")
|
||||
.attr("fill", d3.color(color).darker(terracing))
|
||||
.attr("data-height", i);
|
||||
terrs.append("path").attr("d", paths[i]).attr("fill", color).attr("data-height", i);
|
||||
// render paths
|
||||
for (const height of d3.range(0, 101)) {
|
||||
const group = height < 20 ? ocean : land;
|
||||
const scheme = getColorScheme(group.attr("scheme"));
|
||||
|
||||
if (height === 0 && renderOceanCells) {
|
||||
// draw base ocean layer
|
||||
group
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", graphWidth)
|
||||
.attr("height", graphHeight)
|
||||
.attr("fill", scheme(1));
|
||||
}
|
||||
|
||||
if (height === 20) {
|
||||
// draw base land layer
|
||||
group
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", graphWidth)
|
||||
.attr("height", graphHeight)
|
||||
.attr("fill", scheme(0.8));
|
||||
}
|
||||
|
||||
if (paths[height] && paths[height].length >= 10) {
|
||||
const terracing = group.attr("terracing") / 10 || 0;
|
||||
const color = getColor(height, scheme);
|
||||
|
||||
if (terracing) {
|
||||
group
|
||||
.append("path")
|
||||
.attr("d", paths[height])
|
||||
.attr("transform", "translate(.7,1.4)")
|
||||
.attr("fill", d3.color(color).darker(terracing))
|
||||
.attr("data-height", height);
|
||||
}
|
||||
group.append("path").attr("d", paths[height]).attr("fill", color).attr("data-height", height);
|
||||
}
|
||||
}
|
||||
|
||||
// connect vertices to chain
|
||||
function connectVertices(start, h) {
|
||||
function connectVertices(cells, vertices, start, h, used) {
|
||||
const n = cells.i.length;
|
||||
const chain = []; // vertices chain to form a path
|
||||
for (let i = 0, current = start; i === 0 || (current !== start && i < 20000); i++) {
|
||||
const prev = chain[chain.length - 1]; // previous vertex in chain
|
||||
|
|
@ -295,7 +338,7 @@ function drawHeightmap() {
|
|||
return chain;
|
||||
}
|
||||
|
||||
function simplifyLine(chain) {
|
||||
function simplifyLine(chain, simplification) {
|
||||
if (!simplification) return chain;
|
||||
const n = simplification + 1; // filter each nth element
|
||||
return chain.filter((d, i) => i % n === 0);
|
||||
|
|
@ -1670,10 +1713,7 @@ function toggleLabels(event) {
|
|||
invokeActiveZooming();
|
||||
if (event && isCtrlClick(event)) editStyle("labels");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("labels");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("labels");
|
||||
turnButtonOff("toggleLabels");
|
||||
labels.style("display", "none");
|
||||
}
|
||||
|
|
@ -1685,10 +1725,7 @@ function toggleIcons(event) {
|
|||
$("#icons").fadeIn();
|
||||
if (event && isCtrlClick(event)) editStyle("burgIcons");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("burgIcons");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("burgIcons");
|
||||
turnButtonOff("toggleIcons");
|
||||
$("#icons").fadeOut();
|
||||
}
|
||||
|
|
@ -1701,10 +1738,7 @@ function toggleRulers(event) {
|
|||
rulers.draw();
|
||||
ruler.style("display", null);
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("ruler");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("ruler");
|
||||
turnButtonOff("toggleRulers");
|
||||
ruler.selectAll("*").remove();
|
||||
ruler.style("display", "none");
|
||||
|
|
@ -1715,17 +1749,113 @@ function toggleScaleBar(event) {
|
|||
if (!layerIsOn("toggleScaleBar")) {
|
||||
turnButtonOn("toggleScaleBar");
|
||||
$("#scaleBar").fadeIn();
|
||||
if (event && isCtrlClick(event)) editUnits();
|
||||
if (event && isCtrlClick(event)) editStyle("scaleBar");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editUnits();
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("scaleBar");
|
||||
$("#scaleBar").fadeOut();
|
||||
turnButtonOff("toggleScaleBar");
|
||||
}
|
||||
}
|
||||
|
||||
function drawScaleBar(scaleBar, scaleLevel) {
|
||||
if (!scaleBar.size() || scaleBar.style("display") === "none") return;
|
||||
|
||||
const distanceScale = +distanceScaleInput.value;
|
||||
const unit = distanceUnitInput.value;
|
||||
const size = +scaleBar.attr("data-bar-size");
|
||||
|
||||
const length = (function () {
|
||||
const init = 100;
|
||||
let val = (init * size * distanceScale) / scaleLevel; // bar length in distance unit
|
||||
if (val > 900) val = rn(val, -3); // round to 1000
|
||||
else if (val > 90) val = rn(val, -2); // round to 100
|
||||
else if (val > 9) val = rn(val, -1); // round to 10
|
||||
else val = rn(val); // round to 1
|
||||
const length = (val * scaleLevel) / distanceScale; // actual length in pixels on this scale
|
||||
return length;
|
||||
})();
|
||||
|
||||
scaleBar.select("#scaleBarContent").remove(); // redraw content every time
|
||||
const content = scaleBar.append("g").attr("id", "scaleBarContent");
|
||||
|
||||
const lines = content.append("g");
|
||||
lines
|
||||
.append("line")
|
||||
.attr("x1", 0.5)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", length + size - 0.5)
|
||||
.attr("y2", 0)
|
||||
.attr("stroke-width", size)
|
||||
.attr("stroke", "white");
|
||||
lines
|
||||
.append("line")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", size)
|
||||
.attr("x2", length + size)
|
||||
.attr("y2", size)
|
||||
.attr("stroke-width", size)
|
||||
.attr("stroke", "#3d3d3d");
|
||||
lines
|
||||
.append("line")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", length + size)
|
||||
.attr("y2", 0)
|
||||
.attr("stroke-width", rn(size * 3, 2))
|
||||
.attr("stroke-dasharray", size + " " + rn(length / 5 - size, 2))
|
||||
.attr("stroke", "#3d3d3d");
|
||||
|
||||
const texts = content.append("g").attr("text-anchor", "middle").attr("font-family", "var(--serif)");
|
||||
texts
|
||||
.selectAll("text")
|
||||
.data(d3.range(0, 6))
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", d => rn((d * length) / 5, 2))
|
||||
.attr("y", 0)
|
||||
.attr("dy", "-.6em")
|
||||
.text(d => rn((((d * length) / 5) * distanceScale) / scaleLevel) + (d < 5 ? "" : " " + unit));
|
||||
|
||||
const label = scaleBar.attr("data-label");
|
||||
if (label) {
|
||||
texts
|
||||
.append("text")
|
||||
.attr("x", (length + 1) / 2)
|
||||
.attr("dy", ".6em")
|
||||
.attr("dominant-baseline", "text-before-edge")
|
||||
.text(label);
|
||||
}
|
||||
|
||||
const scaleBarBack = scaleBar.select("#scaleBarBack");
|
||||
if (scaleBarBack.size()) {
|
||||
const bbox = content.node().getBBox();
|
||||
const paddingTop = +scaleBarBack.attr("data-top") || 0;
|
||||
const paddingLeft = +scaleBarBack.attr("data-left") || 0;
|
||||
const paddingRight = +scaleBarBack.attr("data-right") || 0;
|
||||
const paddingBottom = +scaleBarBack.attr("data-bottom") || 0;
|
||||
|
||||
scaleBar
|
||||
.select("#scaleBarBack")
|
||||
.attr("x", -paddingLeft)
|
||||
.attr("y", -paddingTop)
|
||||
.attr("width", bbox.width + paddingRight)
|
||||
.attr("height", bbox.height + paddingBottom);
|
||||
}
|
||||
}
|
||||
|
||||
// fit ScaleBar to screen size
|
||||
function fitScaleBar(scaleBar, fullWidth, fullHeight) {
|
||||
if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return;
|
||||
|
||||
const posX = +scaleBar.attr("data-x") || 99;
|
||||
const posY = +scaleBar.attr("data-y") || 99;
|
||||
const bbox = scaleBar.select("rect").node().getBBox();
|
||||
|
||||
const x = rn((fullWidth * posX) / 100 - bbox.width + 10);
|
||||
const y = rn((fullHeight * posY) / 100 - bbox.height + 20);
|
||||
scaleBar.attr("transform", `translate(${x},${y})`);
|
||||
}
|
||||
|
||||
function toggleZones(event) {
|
||||
if (!layerIsOn("toggleZones")) {
|
||||
turnButtonOn("toggleZones");
|
||||
|
|
@ -1748,10 +1878,7 @@ function toggleEmblems(event) {
|
|||
$("#emblems").fadeIn();
|
||||
if (event && isCtrlClick(event)) editStyle("emblems");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("emblems");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("emblems");
|
||||
$("#emblems").fadeOut();
|
||||
turnButtonOff("toggleEmblems");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -532,101 +532,3 @@ class Planimeter extends Measurer {
|
|||
this.el.select("text").attr("x", c[0]).attr("y", c[1]).text(area);
|
||||
}
|
||||
}
|
||||
|
||||
// Scale bar
|
||||
function drawScaleBar(scaleBar, scaleLevel) {
|
||||
if (!scaleBar.size() || scaleBar.style("display") === "none") return;
|
||||
scaleBar.selectAll("*").remove(); // fully redraw every time
|
||||
|
||||
const distanceScale = +distanceScaleInput.value;
|
||||
const unit = distanceUnitInput.value;
|
||||
const size = +barSizeInput.value;
|
||||
|
||||
// calculate size
|
||||
const init = 100;
|
||||
let val = (init * size * distanceScale) / scaleLevel; // bar length in distance unit
|
||||
if (val > 900) val = rn(val, -3);
|
||||
// round to 1000
|
||||
else if (val > 90) val = rn(val, -2);
|
||||
// round to 100
|
||||
else if (val > 9) val = rn(val, -1);
|
||||
// round to 10
|
||||
else val = rn(val); // round to 1
|
||||
const length = (val * scaleLevel) / distanceScale; // actual length in pixels on this scale
|
||||
|
||||
scaleBar
|
||||
.append("line")
|
||||
.attr("x1", 0.5)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", length + size - 0.5)
|
||||
.attr("y2", 0)
|
||||
.attr("stroke-width", size)
|
||||
.attr("stroke", "white");
|
||||
scaleBar
|
||||
.append("line")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", size)
|
||||
.attr("x2", length + size)
|
||||
.attr("y2", size)
|
||||
.attr("stroke-width", size)
|
||||
.attr("stroke", "#3d3d3d");
|
||||
const dash = size + " " + rn(length / 5 - size, 2);
|
||||
scaleBar
|
||||
.append("line")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", length + size)
|
||||
.attr("y2", 0)
|
||||
.attr("stroke-width", rn(size * 3, 2))
|
||||
.attr("stroke-dasharray", dash)
|
||||
.attr("stroke", "#3d3d3d");
|
||||
|
||||
const fontSize = rn(5 * size, 1);
|
||||
scaleBar
|
||||
.selectAll("text")
|
||||
.data(d3.range(0, 6))
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", d => rn((d * length) / 5, 2))
|
||||
.attr("y", 0)
|
||||
.attr("dy", "-.6em")
|
||||
.attr("font-size", fontSize)
|
||||
.text(d => rn((((d * length) / 5) * distanceScale) / scaleLevel) + (d < 5 ? "" : " " + unit));
|
||||
|
||||
if (barLabel.value !== "") {
|
||||
scaleBar
|
||||
.append("text")
|
||||
.attr("x", (length + 1) / 2)
|
||||
.attr("y", 2 * size)
|
||||
.attr("dominant-baseline", "text-before-edge")
|
||||
.attr("font-size", fontSize)
|
||||
.text(barLabel.value);
|
||||
}
|
||||
|
||||
const bbox = scaleBar.node().getBBox();
|
||||
// append backbround rectangle
|
||||
scaleBar
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", -10)
|
||||
.attr("y", -20)
|
||||
.attr("width", bbox.width + 10)
|
||||
.attr("height", bbox.height + 15)
|
||||
.attr("stroke-width", size)
|
||||
.attr("stroke", "none")
|
||||
.attr("filter", "url(#blur5)")
|
||||
.attr("fill", barBackColor.value)
|
||||
.attr("opacity", +barBackOpacity.value);
|
||||
}
|
||||
|
||||
// fit ScaleBar to screen size
|
||||
function fitScaleBar(scaleBar, fullWidth, fullHeight) {
|
||||
if (!scaleBar.select("rect").size() || scaleBar.style("display") === "none") return;
|
||||
|
||||
const px = isNaN(+barPosX.value) ? 0.99 : barPosX.value / 100;
|
||||
const py = isNaN(+barPosY.value) ? 0.99 : barPosY.value / 100;
|
||||
const bbox = scaleBar.select("rect").node().getBBox();
|
||||
|
||||
const x = rn(fullWidth * px - bbox.width + 10);
|
||||
const y = rn(fullHeight * py - bbox.height + 20);
|
||||
scaleBar.attr("transform", `translate(${x},${y})`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ function changeEra() {
|
|||
}
|
||||
|
||||
async function openTemplateSelectionDialog() {
|
||||
const HeightmapSelectionDialog = await import("../dynamic/heightmap-selection.js?v=1.93.12");
|
||||
const HeightmapSelectionDialog = await import("../dynamic/heightmap-selection.js?v=1.96.00");
|
||||
HeightmapSelectionDialog.open();
|
||||
}
|
||||
|
||||
|
|
@ -774,7 +774,7 @@ function showExportPane() {
|
|||
}
|
||||
|
||||
async function exportToJson(type) {
|
||||
const {exportToJson} = await import("../dynamic/export-json.js?v=1.93.03");
|
||||
const {exportToJson} = await import("../dynamic/export-json.js?v=1.96.00");
|
||||
exportToJson(type);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@ function editProvinces() {
|
|||
cl = el.classList,
|
||||
line = el.parentNode,
|
||||
p = +line.dataset.id;
|
||||
const stateId = pack.provinces[p].state;
|
||||
|
||||
if (el.tagName === "FILL-BOX") changeFill(el);
|
||||
else if (cl.contains("name")) editProvinceName(p);
|
||||
else if (cl.contains("coaIcon")) editEmblem("province", "provinceCOA" + p, pack.provinces[p]);
|
||||
else if (cl.contains("icon-star-empty")) capitalZoomIn(p);
|
||||
else if (cl.contains("icon-flag-empty")) triggerIndependencePromps(p);
|
||||
else if (cl.contains("icon-dot-circled")) overviewBurgs({stateId});
|
||||
else if (cl.contains("culturePopulation")) changePopulation(p);
|
||||
else if (cl.contains("icon-pin")) toggleFog(p, cl);
|
||||
else if (cl.contains("icon-trash-empty")) removeProvince(p);
|
||||
|
|
@ -71,9 +73,8 @@ function editProvinces() {
|
|||
}
|
||||
|
||||
function collectStatistics() {
|
||||
const cells = pack.cells,
|
||||
provinces = pack.provinces,
|
||||
burgs = pack.burgs;
|
||||
const {cells, provinces, burgs} = pack;
|
||||
|
||||
provinces.forEach(p => {
|
||||
if (!p.i || p.removed) return;
|
||||
p.area = p.rural = p.urban = 0;
|
||||
|
|
@ -107,16 +108,18 @@ function editProvinces() {
|
|||
statesSorted.forEach(s => stateFilter.options.add(new Option(s.name, s.i, false, s.i == selectedState)));
|
||||
}
|
||||
|
||||
// add line for each state
|
||||
// add line for each province
|
||||
function provincesEditorAddLines() {
|
||||
const unit = " " + getAreaUnit();
|
||||
const selectedState = +document.getElementById("provincesFilterState").value;
|
||||
let filtered = pack.provinces.filter(p => p.i && !p.removed); // all valid burgs
|
||||
if (selectedState != -1) filtered = filtered.filter(p => p.state === selectedState); // filtered by state
|
||||
body.innerHTML = "";
|
||||
let lines = "",
|
||||
totalArea = 0,
|
||||
totalPopulation = 0;
|
||||
|
||||
let lines = "";
|
||||
let totalArea = 0;
|
||||
let totalPopulation = 0;
|
||||
let totalBurgs = 0;
|
||||
|
||||
for (const p of filtered) {
|
||||
const area = getArea(p.area);
|
||||
|
|
@ -128,6 +131,7 @@ function editProvinces() {
|
|||
rural
|
||||
)}; Urban population: ${si(urban)}`;
|
||||
totalPopulation += population;
|
||||
totalBurgs += p.burgs.length;
|
||||
|
||||
const stateName = pack.states[p.state].name;
|
||||
const capital = p.burg ? pack.burgs[p.burg].name : "";
|
||||
|
|
@ -144,6 +148,7 @@ function editProvinces() {
|
|||
data-state="${stateName}"
|
||||
data-area=${area}
|
||||
data-population=${population}
|
||||
data-burgs=${p.burgs.length}
|
||||
>
|
||||
<fill-box fill="${p.color}"></fill-box>
|
||||
<input data-tip="Province name. Click to change" class="name pointer" value="${p.name}" readonly />
|
||||
|
|
@ -163,6 +168,8 @@ function editProvinces() {
|
|||
${p.burgs.length ? getCapitalOptions(p.burgs, p.burg) : ""}
|
||||
</select>
|
||||
<input data-tip="Province owner" class="provinceOwner" value="${stateName}" disabled">
|
||||
<span data-tip="Click to overview province burgs" style="padding-right: 1px" class="icon-dot-circled pointer hide"></span>
|
||||
<div data-tip="Burgs count" class="provinceBurgs hide">${p.burgs.length}</div>
|
||||
<span data-tip="Province area" style="padding-right: 4px" class="icon-map-o hide"></span>
|
||||
<div data-tip="Province area" class="biomeArea hide">${si(area) + unit}</div>
|
||||
<span data-tip="${populationTip}" class="icon-male hide"></span>
|
||||
|
|
@ -179,11 +186,12 @@ function editProvinces() {
|
|||
body.innerHTML = lines;
|
||||
|
||||
// update footer
|
||||
provincesFooterNumber.innerHTML = filtered.length;
|
||||
provincesFooterArea.innerHTML = filtered.length ? si(totalArea / filtered.length) + unit : 0 + unit;
|
||||
provincesFooterPopulation.innerHTML = filtered.length ? si(totalPopulation / filtered.length) : 0;
|
||||
provincesFooterArea.dataset.area = totalArea;
|
||||
provincesFooterPopulation.dataset.population = totalPopulation;
|
||||
byId("provincesFooterNumber").innerHTML = filtered.length;
|
||||
byId("provincesFooterBurgs").innerHTML = totalBurgs;
|
||||
byId("provincesFooterArea").innerHTML = filtered.length ? si(totalArea / filtered.length) + unit : 0 + unit;
|
||||
byId("provincesFooterPopulation").innerHTML = filtered.length ? si(totalPopulation / filtered.length) : 0;
|
||||
byId("provincesFooterArea").dataset.area = totalArea;
|
||||
byId("provincesFooterPopulation").dataset.population = totalPopulation;
|
||||
|
||||
body.querySelectorAll("div.states").forEach(el => {
|
||||
el.addEventListener("click", selectProvinceOnLineClick);
|
||||
|
|
@ -294,7 +302,7 @@ function editProvinces() {
|
|||
// move all burgs to a new state
|
||||
province.burgs.forEach(b => (burgs[b].state = newStateId));
|
||||
|
||||
// difine new state attributes
|
||||
// define new state attributes
|
||||
const {cell: center, culture} = burgs[burgId];
|
||||
const color = getRandomColor();
|
||||
const coa = province.coa;
|
||||
|
|
@ -501,6 +509,9 @@ function editProvinces() {
|
|||
applyOption(provinceNameEditorSelectForm, p.formName);
|
||||
document.getElementById("provinceNameEditorFull").value = p.fullName;
|
||||
|
||||
const cultureId = pack.cells.culture[p.center];
|
||||
document.getElementById("provinceCultureDisplay").innerText = pack.cultures[cultureId].name;
|
||||
|
||||
$("#provinceNameEditor").dialog({
|
||||
resizable: false,
|
||||
title: "Change province name",
|
||||
|
|
@ -520,12 +531,12 @@ function editProvinces() {
|
|||
modules.editProvinceName = true;
|
||||
|
||||
// add listeners
|
||||
document.getElementById("provinceNameEditorShortCulture").addEventListener("click", regenerateShortNameCuture);
|
||||
document.getElementById("provinceNameEditorShortCulture").addEventListener("click", regenerateShortNameCulture);
|
||||
document.getElementById("provinceNameEditorShortRandom").addEventListener("click", regenerateShortNameRandom);
|
||||
document.getElementById("provinceNameEditorAddForm").addEventListener("click", addCustomForm);
|
||||
document.getElementById("provinceNameEditorFullRegenerate").addEventListener("click", regenerateFullName);
|
||||
|
||||
function regenerateShortNameCuture() {
|
||||
function regenerateShortNameCulture() {
|
||||
const province = +provinceNameEditor.dataset.province;
|
||||
const culture = pack.cells.culture[pack.provinces[province].center];
|
||||
const name = Names.getState(Names.getCultureShort(culture), culture);
|
||||
|
|
@ -576,12 +587,15 @@ function editProvinces() {
|
|||
function togglePercentageMode() {
|
||||
if (body.dataset.type === "absolute") {
|
||||
body.dataset.type = "percentage";
|
||||
const totalBurgs = +byId("provincesFooterBurgs").innerText;
|
||||
const totalArea = +provincesFooterArea.dataset.area;
|
||||
const totalPopulation = +provincesFooterPopulation.dataset.population;
|
||||
|
||||
body.querySelectorAll(":scope > div").forEach(function (el) {
|
||||
el.querySelector(".biomeArea").innerHTML = rn((+el.dataset.area / totalArea) * 100) + "%";
|
||||
el.querySelector(".culturePopulation").innerHTML = rn((+el.dataset.population / totalPopulation) * 100) + "%";
|
||||
const {cells, burgs, area, population} = el.dataset;
|
||||
el.querySelector(".provinceBurgs").innerText = rn((+burgs / totalBurgs) * 100) + "%";
|
||||
el.querySelector(".biomeArea").innerHTML = rn((+area / totalArea) * 100) + "%";
|
||||
el.querySelector(".culturePopulation").innerHTML = rn((+population / totalPopulation) * 100) + "%";
|
||||
});
|
||||
} else {
|
||||
body.dataset.type = "absolute";
|
||||
|
|
@ -1064,10 +1078,7 @@ function editProvinces() {
|
|||
|
||||
function downloadProvincesData() {
|
||||
const unit = areaUnit.value === "square" ? distanceUnitInput.value + "2" : areaUnit.value;
|
||||
let data =
|
||||
"Id,Province,Full Name,Form,State,Color,Capital,Area " +
|
||||
unit +
|
||||
",Total Population,Rural Population,Urban Population\n"; // headers
|
||||
let data = `Id,Province,Full Name,Form,State,Color,Capital,Area ${unit},Total Population,Rural Population,Urban Population,Burgs\n`; // headers
|
||||
|
||||
body.querySelectorAll(":scope > div").forEach(function (el) {
|
||||
const key = parseInt(el.dataset.id);
|
||||
|
|
@ -1081,8 +1092,9 @@ function editProvinces() {
|
|||
data += el.dataset.capital + ",";
|
||||
data += el.dataset.area + ",";
|
||||
data += el.dataset.population + ",";
|
||||
data += `${Math.round(provincePack.rural * populationRate)},`;
|
||||
data += `${Math.round(provincePack.urban * populationRate * urbanization)}\n`;
|
||||
data += Math.round(provincePack.rural * populationRate) + ",";
|
||||
data += Math.round(provincePack.urban * populationRate * urbanization) + ",";
|
||||
data += el.dataset.burgs + "\n";
|
||||
});
|
||||
|
||||
const name = getFileName("Provinces") + ".csv";
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
byId("styleFilterInput").innerHTML = allOptions;
|
||||
byId("styleStatesBodyFilter").innerHTML = allOptions;
|
||||
byId("styleScaleBarBackgroundFilter").innerHTML = allOptions;
|
||||
}
|
||||
|
||||
// store some style inputs as options
|
||||
|
|
@ -31,6 +32,7 @@ function editStyle(element, group) {
|
|||
|
||||
styleElementSelect.classList.add("glow");
|
||||
if (group) styleGroupSelect.classList.add("glow");
|
||||
|
||||
setTimeout(() => {
|
||||
styleElementSelect.classList.remove("glow");
|
||||
if (group) styleGroupSelect.classList.remove("glow");
|
||||
|
|
@ -81,10 +83,10 @@ function selectStyleElement() {
|
|||
styleIsOff.style.display = isLayerOff ? "block" : "none";
|
||||
|
||||
// active group element
|
||||
const group = styleGroupSelect.value;
|
||||
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders"].includes(styleElement)) {
|
||||
const gEl = group && el.select("#" + group);
|
||||
el = group && gEl.size() ? gEl : el.select("g");
|
||||
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders", "terrs"].includes(styleElement)) {
|
||||
const group = styleGroupSelect.value;
|
||||
const defaultGroupSelector = styleElement === "terrs" ? "#landHeights" : "g";
|
||||
el = group && el.select("#" + group).size() ? el.select("#" + group) : el.select(defaultGroupSelector);
|
||||
}
|
||||
|
||||
// opacity
|
||||
|
|
@ -94,13 +96,13 @@ function selectStyleElement() {
|
|||
}
|
||||
|
||||
// filter
|
||||
if (!["landmass", "legend", "regions"].includes(styleElement)) {
|
||||
if (!["landmass", "legend", "regions", "scaleBar"].includes(styleElement)) {
|
||||
styleFilter.style.display = "block";
|
||||
styleFilterInput.value = el.attr("filter") || "";
|
||||
}
|
||||
|
||||
// fill
|
||||
if (["rivers", "lakes", "landmass", "prec", "ice", "fogging", "vignette"].includes(styleElement)) {
|
||||
if (["rivers", "lakes", "landmass", "prec", "ice", "fogging", "scaleBar", "vignette"].includes(styleElement)) {
|
||||
styleFill.style.display = "block";
|
||||
styleFillInput.value = styleFillOutput.value = el.attr("fill");
|
||||
}
|
||||
|
|
@ -170,11 +172,14 @@ function selectStyleElement() {
|
|||
|
||||
if (styleElement === "terrs") {
|
||||
styleHeightmap.style.display = "block";
|
||||
styleHeightmapScheme.value = terrs.attr("scheme");
|
||||
styleHeightmapTerracingInput.value = styleHeightmapTerracingOutput.value = terrs.attr("terracing");
|
||||
styleHeightmapSkipInput.value = styleHeightmapSkipOutput.value = terrs.attr("skip");
|
||||
styleHeightmapSimplificationInput.value = styleHeightmapSimplificationOutput.value = terrs.attr("relax");
|
||||
styleHeightmapCurve.value = terrs.attr("curve");
|
||||
styleHeightmapRenderOceanOption.style.display = el.attr("id") === "oceanHeights" ? "block" : "none";
|
||||
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");
|
||||
styleHeightmapCurve.value = el.attr("curve");
|
||||
}
|
||||
|
||||
if (styleElement === "markers") {
|
||||
|
|
@ -336,7 +341,7 @@ function selectStyleElement() {
|
|||
|
||||
// update group options
|
||||
styleGroupSelect.options.length = 0; // remove all options
|
||||
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders"].includes(styleElement)) {
|
||||
if (["routes", "labels", "coastline", "lakes", "anchors", "burgIcons", "borders", "terrs"].includes(styleElement)) {
|
||||
const groups = byId(styleElement).querySelectorAll("g");
|
||||
groups.forEach(el => {
|
||||
if (el.id === "burgLabels") return;
|
||||
|
|
@ -356,6 +361,31 @@ function selectStyleElement() {
|
|||
if (auto) styleFilter.style.display = "none";
|
||||
}
|
||||
|
||||
if (styleElement === "scaleBar") {
|
||||
styleScaleBar.style.display = "block";
|
||||
|
||||
styleScaleBarSize.value = el.attr("data-bar-size");
|
||||
styleScaleBarFontSize.value = el.attr("font-size");
|
||||
styleScaleBarPositionX.value = el.attr("data-x") || "99";
|
||||
styleScaleBarPositionY.value = el.attr("data-y") || "99";
|
||||
styleScaleBarLabel.value = el.attr("data-label") || "";
|
||||
|
||||
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");
|
||||
styleScaleBarBackgroundStrokeWidth.value = scaleBarBack.attr("stroke-width");
|
||||
styleScaleBarBackgroundFilter.value = scaleBarBack.attr("filter");
|
||||
styleScaleBarBackgroundPaddingTop.value = scaleBarBack.attr("data-top");
|
||||
styleScaleBarBackgroundPaddingRight.value = scaleBarBack.attr("data-right");
|
||||
styleScaleBarBackgroundPaddingBottom.value = scaleBarBack.attr("data-bottom");
|
||||
styleScaleBarBackgroundPaddingLeft.value = scaleBarBack.attr("data-left");
|
||||
}
|
||||
}
|
||||
|
||||
if (styleElement === "vignette") {
|
||||
styleVignette.style.display = "block";
|
||||
|
||||
|
|
@ -519,18 +549,16 @@ outlineLayers.addEventListener("change", function () {
|
|||
});
|
||||
|
||||
styleHeightmapScheme.addEventListener("change", function () {
|
||||
terrs.attr("scheme", this.value);
|
||||
getEl().attr("scheme", this.value);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
openCreateHeightmapSchemeButton.addEventListener("click", function () {
|
||||
// start with current scheme
|
||||
this.dataset.stops = terrs.attr("scheme").startsWith("#")
|
||||
? terrs.attr("scheme")
|
||||
: (function () {
|
||||
const scheme = heightmapColorSchemes[terrs.attr("scheme")];
|
||||
return [0, 0.25, 0.5, 0.75, 1].map(scheme).map(toHEX).join(",");
|
||||
})();
|
||||
const scheme = getEl().attr("scheme");
|
||||
this.dataset.stops = scheme.startsWith("#")
|
||||
? scheme
|
||||
: (() => [0, 0.25, 0.5, 0.75, 1].map(heightmapColorSchemes[scheme]).map(toHEX).join(","))();
|
||||
|
||||
// render dialog base structure
|
||||
alertMessage.innerHTML = /* html */ `<div>
|
||||
|
|
@ -622,7 +650,7 @@ openCreateHeightmapSchemeButton.addEventListener("click", function () {
|
|||
if (stops in heightmapColorSchemes) return tip("This scheme already exists", false, "error");
|
||||
|
||||
addCustomColorScheme(stops);
|
||||
terrs.attr("scheme", stops);
|
||||
getEl().attr("scheme", stops);
|
||||
drawHeightmap();
|
||||
|
||||
handleClose();
|
||||
|
|
@ -644,23 +672,28 @@ openCreateHeightmapSchemeButton.addEventListener("click", function () {
|
|||
});
|
||||
});
|
||||
|
||||
styleHeightmapRenderOcean.addEventListener("change", function () {
|
||||
getEl().attr("data-render", +this.checked);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
styleHeightmapTerracingInput.addEventListener("input", function () {
|
||||
terrs.attr("terracing", this.value);
|
||||
getEl().attr("terracing", this.value);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
styleHeightmapSkipInput.addEventListener("input", function () {
|
||||
terrs.attr("skip", this.value);
|
||||
getEl().attr("skip", this.value);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
styleHeightmapSimplificationInput.addEventListener("input", function () {
|
||||
terrs.attr("relax", this.value);
|
||||
getEl().attr("relax", this.value);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
styleHeightmapCurve.addEventListener("change", function () {
|
||||
terrs.attr("curve", this.value);
|
||||
getEl().attr("curve", this.value);
|
||||
drawHeightmap();
|
||||
});
|
||||
|
||||
|
|
@ -957,7 +990,7 @@ function textureProvideURL() {
|
|||
}
|
||||
|
||||
function fetchTextureURL(url) {
|
||||
INFO && console.log("Provided URL is", url);
|
||||
INFO && console.info("Provided URL is", url);
|
||||
const img = new Image();
|
||||
img.onload = function () {
|
||||
const canvas = byId("texturePreview");
|
||||
|
|
@ -1043,6 +1076,44 @@ styleVignetteBlur.addEventListener("input", function () {
|
|||
byId("vignette-rect")?.setAttribute("filter", `blur(${this.value}px)`);
|
||||
});
|
||||
|
||||
styleScaleBar.addEventListener("input", function (event) {
|
||||
const scaleBarBack = scaleBar.select("#scaleBarBack");
|
||||
if (!scaleBarBack.size()) return;
|
||||
|
||||
const {id, value} = event.target;
|
||||
|
||||
if (id === "styleScaleBarSize") scaleBar.attr("data-bar-size", value);
|
||||
else if (id === "styleScaleBarFontSize") scaleBar.attr("font-size", value);
|
||||
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 === "styleScaleBarBackgroundStrokeWidth") scaleBarBack.attr("stroke-width", value);
|
||||
else if (id === "styleScaleBarBackgroundFilter") scaleBarBack.attr("filter", value);
|
||||
else if (id === "styleScaleBarBackgroundPaddingTop") scaleBarBack.attr("data-top", value);
|
||||
else if (id === "styleScaleBarBackgroundPaddingRight") scaleBarBack.attr("data-right", value);
|
||||
else if (id === "styleScaleBarBackgroundPaddingBottom") scaleBarBack.attr("data-bottom", value);
|
||||
else if (id === "styleScaleBarBackgroundPaddingLeft") scaleBarBack.attr("data-left", value);
|
||||
|
||||
if (
|
||||
[
|
||||
"styleScaleBarSize",
|
||||
"styleScaleBarPositionX",
|
||||
"styleScaleBarPositionY",
|
||||
"styleScaleBarLabel",
|
||||
"styleScaleBarBackgroundPaddingLeft",
|
||||
"styleScaleBarBackgroundPaddingTop",
|
||||
"styleScaleBarBackgroundPaddingRight",
|
||||
"styleScaleBarBackgroundPaddingBottom"
|
||||
].includes(id)
|
||||
) {
|
||||
drawScaleBar(scaleBar, scale);
|
||||
fitScaleBar(scaleBar, svgWidth, svgHeight);
|
||||
}
|
||||
});
|
||||
|
||||
function updateElements() {
|
||||
// burgIcons to desired size
|
||||
burgIcons.selectAll("g").each(function () {
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ function applyStyleWithUiRefresh(style) {
|
|||
|
||||
invokeActiveZooming();
|
||||
setPresetRemoveButtonVisibiliy();
|
||||
|
||||
drawScaleBar(scaleBar, scale);
|
||||
fitScaleBar(scaleBar, svgWidth, svgHeight);
|
||||
}
|
||||
|
||||
function addStylePreset() {
|
||||
|
|
@ -239,7 +242,18 @@ function addStylePreset() {
|
|||
"#oceanLayers": ["filter", "layers"],
|
||||
"#oceanBase": ["fill"],
|
||||
"#oceanicPattern": ["href", "opacity"],
|
||||
"#terrs": ["opacity", "scheme", "terracing", "skip", "relax", "curve", "filter", "mask"],
|
||||
"#terrs #oceanHeights": [
|
||||
"data-render",
|
||||
"opacity",
|
||||
"scheme",
|
||||
"terracing",
|
||||
"skip",
|
||||
"relax",
|
||||
"curve",
|
||||
"filter",
|
||||
"mask"
|
||||
],
|
||||
"#terrs #landHeights": ["opacity", "scheme", "terracing", "skip", "relax", "curve", "filter", "mask"],
|
||||
"#legend": [
|
||||
"data-size",
|
||||
"font-size",
|
||||
|
|
@ -301,7 +315,19 @@ function addStylePreset() {
|
|||
],
|
||||
"#fogging": ["opacity", "fill", "filter"],
|
||||
"#vignette": ["opacity", "fill", "filter"],
|
||||
"#vignette-rect": ["x", "y", "width", "height", "rx", "ry", "filter"]
|
||||
"#vignette-rect": ["x", "y", "width", "height", "rx", "ry", "filter"],
|
||||
"#scaleBar": ["opacity", "fill", "font-size", "data-bar-size", "data-x", "data-y", "data-label"],
|
||||
"#scaleBarBack": [
|
||||
"opacity",
|
||||
"fill",
|
||||
"stroke",
|
||||
"stroke-width",
|
||||
"filter",
|
||||
"data-top",
|
||||
"data-right",
|
||||
"data-bottom",
|
||||
"data-left"
|
||||
]
|
||||
};
|
||||
|
||||
for (const selector in attributes) {
|
||||
|
|
|
|||
|
|
@ -24,13 +24,6 @@ function editUnits() {
|
|||
byId("heightExponentInput").addEventListener("input", changeHeightExponent);
|
||||
byId("heightExponentOutput").addEventListener("input", changeHeightExponent);
|
||||
byId("temperatureScale").addEventListener("change", changeTemperatureScale);
|
||||
byId("barSizeOutput").addEventListener("input", renderScaleBar);
|
||||
byId("barSizeInput").addEventListener("input", renderScaleBar);
|
||||
byId("barLabel").addEventListener("input", renderScaleBar);
|
||||
byId("barPosX").addEventListener("input", fitScaleBar);
|
||||
byId("barPosY").addEventListener("input", fitScaleBar);
|
||||
byId("barBackOpacity").addEventListener("input", changeScaleBarOpacity);
|
||||
byId("barBackColor").addEventListener("input", changeScaleBarColor);
|
||||
|
||||
byId("populationRateOutput").addEventListener("input", changePopulationRate);
|
||||
byId("populationRateInput").addEventListener("change", changePopulationRate);
|
||||
|
|
@ -84,14 +77,6 @@ function editUnits() {
|
|||
if (layerIsOn("toggleTemp")) drawTemp();
|
||||
}
|
||||
|
||||
function changeScaleBarOpacity() {
|
||||
scaleBar.select("rect").attr("opacity", this.value);
|
||||
}
|
||||
|
||||
function changeScaleBarColor() {
|
||||
scaleBar.select("rect").attr("fill", this.value);
|
||||
}
|
||||
|
||||
function changePopulationRate() {
|
||||
populationRate = +this.value;
|
||||
}
|
||||
|
|
@ -129,19 +114,6 @@ function editUnits() {
|
|||
localStorage.removeItem("heightExponent");
|
||||
calculateTemperatures();
|
||||
|
||||
// scale bar
|
||||
barSizeOutput.value = barSizeInput.value = 2;
|
||||
barLabel.value = "";
|
||||
barBackOpacity.value = 0.2;
|
||||
barBackColor.value = "#ffffff";
|
||||
barPosX.value = barPosY.value = 99;
|
||||
|
||||
localStorage.removeItem("barSize");
|
||||
localStorage.removeItem("barLabel");
|
||||
localStorage.removeItem("barBackOpacity");
|
||||
localStorage.removeItem("barBackColor");
|
||||
localStorage.removeItem("barPosX");
|
||||
localStorage.removeItem("barPosY");
|
||||
renderScaleBar();
|
||||
|
||||
// population
|
||||
|
|
|
|||
|
|
@ -286,14 +286,25 @@
|
|||
"href": "./images/kiwiroo.png",
|
||||
"opacity": 0.4
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"scheme": "bright",
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 0,
|
||||
"opacity": 1,
|
||||
"scheme": "light",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#filter-sepia)",
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 1,
|
||||
"scheme": "light",
|
||||
"terracing": 0,
|
||||
"skip": 2,
|
||||
"relax": 1,
|
||||
"curve": 0,
|
||||
"filter": "url(#blur3)",
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#filter-sepia)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "0%",
|
||||
"ry": "0%",
|
||||
"filter": "blur(50px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,13 +286,24 @@
|
|||
"href": "",
|
||||
"opacity": 1
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 1,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 1,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(30px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 9,
|
||||
"data-bar-size": 1.5,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": null,
|
||||
"data-top": 18,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,13 +288,24 @@
|
|||
"href": "",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 0.5,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.5,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
|
|
@ -400,5 +411,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 8,
|
||||
"data-bar-size": 1.5,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "",
|
||||
"data-top": 17,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,14 +286,25 @@
|
|||
"href": "",
|
||||
"opacity": 0.15
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 1,
|
||||
"scheme": "monochrome",
|
||||
"scheme": "olive",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.8,
|
||||
"scheme": "livid",
|
||||
"terracing": 6,
|
||||
"skip": 0,
|
||||
"relax": 2,
|
||||
"curve": 0,
|
||||
"filter": "",
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#d0d0dc",
|
||||
"font-size": 11,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.3,
|
||||
"fill": "#05001f",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "",
|
||||
"data-top": 23,
|
||||
"data-right": 18,
|
||||
"data-bottom": 18,
|
||||
"data-left": 12
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,13 +286,24 @@
|
|||
"href": "./images/pattern1.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": null,
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 0,
|
||||
"opacity": 1,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 1,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,14 +288,25 @@
|
|||
"href": "./images/pattern3.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"opacity": 1,
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 0.8,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.8,
|
||||
"scheme": "bright",
|
||||
"terracing": 2,
|
||||
"skip": 1,
|
||||
"relax": 2,
|
||||
"curve": 0,
|
||||
"filter": "url(#filter-grayscale)",
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -400,5 +411,25 @@
|
|||
"rx": "10%",
|
||||
"ry": "10%",
|
||||
"filter": "blur(30px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#121212",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#607671",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,13 +286,24 @@
|
|||
"href": "./images/pattern1.png",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 0.4,
|
||||
"scheme": "light",
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#turbulence)",
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.4,
|
||||
"scheme": "bright",
|
||||
"terracing": 10,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#turbulence)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,14 +281,25 @@
|
|||
"href": "",
|
||||
"opacity": 0.2
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 1,
|
||||
"scheme": "monochrome",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": "url(#blur3)",
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#turbulence)",
|
||||
"mask": null
|
||||
},
|
||||
"#terrs #landHeights": {
|
||||
"opacity": 1,
|
||||
"scheme": "monochrome",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": "url(#turbulence)",
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -394,5 +405,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#ffffff",
|
||||
"font-size": 8,
|
||||
"data-bar-size": 1.5,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "",
|
||||
"data-top": 18,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,14 +286,25 @@
|
|||
"href": "",
|
||||
"opacity": 0.3
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 0.5,
|
||||
"scheme": "livid",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 1,
|
||||
"scheme": "livid",
|
||||
"terracing": 0,
|
||||
"skip": 10,
|
||||
"relax": 0,
|
||||
"curve": 0,
|
||||
"filter": "url(#blurFilter)",
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#b5c1d4",
|
||||
"font-size": 11,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.5,
|
||||
"fill": "#0a1e24",
|
||||
"stroke": "#40547a",
|
||||
"stroke-width": 1,
|
||||
"filter": "",
|
||||
"data-top": 22,
|
||||
"data-right": 15,
|
||||
"data-bottom": 16,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,14 +286,25 @@
|
|||
"href": "./images/kiwiroo.png",
|
||||
"opacity": 0.3
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 0,
|
||||
"opacity": 0.7,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.7,
|
||||
"scheme": "bright",
|
||||
"terracing": 0,
|
||||
"skip": 2,
|
||||
"relax": 1,
|
||||
"curve": 0,
|
||||
"filter": "",
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
"#legend": {
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(30px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,13 +286,24 @@
|
|||
"href": "./images/kiwiroo.png",
|
||||
"opacity": 0.5
|
||||
},
|
||||
"#terrs": {
|
||||
"#terrs > #oceanHeights": {
|
||||
"data-render": 1,
|
||||
"opacity": 0.5,
|
||||
"scheme": "light",
|
||||
"terracing": 0,
|
||||
"skip": 0,
|
||||
"relax": 1,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": null
|
||||
},
|
||||
"#terrs > #landHeights": {
|
||||
"opacity": 0.5,
|
||||
"scheme": "light",
|
||||
"terracing": 0,
|
||||
"skip": 5,
|
||||
"relax": 1,
|
||||
"curve": 0,
|
||||
"curve": "curveBasisClosed",
|
||||
"filter": null,
|
||||
"mask": "url(#land)"
|
||||
},
|
||||
|
|
@ -398,5 +409,25 @@
|
|||
"rx": "5%",
|
||||
"ry": "5%",
|
||||
"filter": "blur(20px)"
|
||||
},
|
||||
"#scaleBar": {
|
||||
"opacity": 1,
|
||||
"fill": "#353540",
|
||||
"font-size": 10,
|
||||
"data-bar-size": 2,
|
||||
"data-x": 99,
|
||||
"data-y": 99,
|
||||
"data-label": ""
|
||||
},
|
||||
"#scaleBarBack": {
|
||||
"opacity": 0.2,
|
||||
"fill": "#ffffff",
|
||||
"stroke": "#000000",
|
||||
"stroke-width": 1,
|
||||
"filter": "url(#blur5)",
|
||||
"data-top": 20,
|
||||
"data-right": 15,
|
||||
"data-bottom": 15,
|
||||
"data-left": 10
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ function drawCellsValue(data) {
|
|||
function drawPolygons(data) {
|
||||
const max = d3.max(data),
|
||||
min = d3.min(data),
|
||||
scheme = getColorScheme(terrs.attr("scheme"));
|
||||
scheme = getColorScheme(terrs.select("#landHeights").attr("scheme"));
|
||||
data = data.map(d => 1 - normalize(d, min, max));
|
||||
|
||||
debug.selectAll("polygon").remove();
|
||||
|
|
@ -338,7 +338,7 @@ function drawPolygons(data) {
|
|||
.data(data)
|
||||
.enter()
|
||||
.append("polygon")
|
||||
.attr("points", (d, i) => getPackPolygon(i))
|
||||
.attr("points", (d, i) => getGridPolygon(i))
|
||||
.attr("fill", d => scheme(d))
|
||||
.attr("stroke", d => scheme(d));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
// version and caching control
|
||||
const version = "1.95.05"; // generator version, update each time
|
||||
const version = "1.96.00"; // generator version, update each time
|
||||
|
||||
{
|
||||
document.title += " v" + version;
|
||||
|
|
@ -28,6 +28,8 @@ const version = "1.95.05"; // generator version, update each time
|
|||
|
||||
<ul>
|
||||
<strong>Latest changes:</strong>
|
||||
<li>Ability to render ocean heightmap</li>
|
||||
<li>Scale bar styling features</li>
|
||||
<li>Vignette visual layer and vignette styling options</li>
|
||||
<li>Ability to define custom heightmap color scheme</li>
|
||||
<li>New style preset Night and new heightmap color schemes</li>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue