mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-21 19:41:23 +01:00
Merge branch 'master' of https://github.com/Azgaar/Fantasy-Map-Generator into urquhart-routes
This commit is contained in:
commit
c4370774e4
27 changed files with 423 additions and 294 deletions
3
LICENSE
3
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright 2017-2021 Max Haniyeu (Azgaar), azgaar.fmg@yandex.com
|
||||
Copyright 2017-2024 Max Haniyeu (Azgaar), azgaar.fmg@yandex.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -14,6 +14,7 @@ copies or substantial portions of the Software.
|
|||
|
||||
You can produce, without restrictions, any derivative works from the original
|
||||
software and even reap commercial benefits from the sale of the secondary product.
|
||||
The derivates include created maps, map images, screenshots, videos, and other materials.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
|
|
|||
46
index.css
46
index.css
|
|
@ -436,6 +436,14 @@ button.options:hover {
|
|||
margin: 0.8em 0 0 0;
|
||||
}
|
||||
|
||||
#options .tip {
|
||||
color: #444;
|
||||
font-size: 0.9em;
|
||||
font-family: sans-serif;
|
||||
font-style: italic;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
#aboutContent {
|
||||
text-align: justify;
|
||||
}
|
||||
|
|
@ -733,7 +741,7 @@ input[type="color"]::-webkit-color-swatch-wrapper {
|
|||
background-color: var(--header-active);
|
||||
}
|
||||
|
||||
#toolsContent div {
|
||||
#toolsContent > .grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
margin: 0.2em 0;
|
||||
|
|
@ -757,7 +765,7 @@ input[type="color"]::-webkit-color-swatch-wrapper {
|
|||
|
||||
#viewMode > button {
|
||||
padding: 0.35em;
|
||||
margin: 0.2em 0.3em 0.6em 0.3em;
|
||||
margin: 0.3em 0.3em 0.6em 0.3em;
|
||||
float: left;
|
||||
width: 30.7%;
|
||||
}
|
||||
|
|
@ -2188,7 +2196,7 @@ svg.button {
|
|||
#worldControls input[type="number"] {
|
||||
border: 1px solid #e5e5e5;
|
||||
padding: 0px;
|
||||
width: 3.2em;
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
#worldControls i.icon-lock-open,
|
||||
|
|
@ -2247,10 +2255,6 @@ svg.button {
|
|||
fill: blue;
|
||||
}
|
||||
|
||||
#globeOutline {
|
||||
fill: url(#temperatureGradient);
|
||||
}
|
||||
|
||||
#globeArea {
|
||||
fill: white;
|
||||
fill-opacity: 0.3;
|
||||
|
|
@ -2261,6 +2265,11 @@ svg.button {
|
|||
stroke-width: 0.2;
|
||||
}
|
||||
|
||||
#globePrimeMeridian {
|
||||
stroke: blue;
|
||||
stroke-width: 1.4;
|
||||
}
|
||||
|
||||
#globeEquator {
|
||||
stroke: red;
|
||||
stroke-width: 1.4;
|
||||
|
|
@ -2382,6 +2391,29 @@ svg.button {
|
|||
background: #ccc;
|
||||
}
|
||||
|
||||
.separator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color: #222;
|
||||
margin: 0.8em 0 0 0;
|
||||
}
|
||||
.separator::before,
|
||||
.separator::after {
|
||||
content: "";
|
||||
flex: 1;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
.separator:not(:empty)::before {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
.separator:not(:empty)::after {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div,
|
||||
canvas {
|
||||
|
|
|
|||
288
index.html
288
index.html
|
|
@ -138,7 +138,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<link rel="preload" href="index.css?v=1.96.00" as="style" onload="this.onload=null; this.rel='stylesheet'" />
|
||||
<link rel="preload" href="index.css?v=1.98.01" 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>
|
||||
|
|
@ -380,7 +380,7 @@
|
|||
<rect x="-1%" y="-1%" width="102%" height="102%" fill="url(#oceanic)" />
|
||||
</svg>
|
||||
<svg id="loading-rose" width="100%" height="100%" viewBox="0 0 700 700">
|
||||
<use href="#rose" x="50%" y="50%" />
|
||||
<use href="#defs-compass-rose" x="50%" y="50%" />
|
||||
</svg>
|
||||
<div id="loading-typography">
|
||||
<div id="titleName">Azgaar's</div>
|
||||
|
|
@ -469,9 +469,7 @@
|
|||
onclick="removePreset()"
|
||||
></button>
|
||||
|
||||
<p data-tip="Click to toggle a layer, drag to raise or lower a layer. Ctrl + click to edit layer style">
|
||||
Displayed layers and layers order:
|
||||
</p>
|
||||
<p>Displayed layers and layers order:</p>
|
||||
<ul
|
||||
data-tip="Click to toggle a layer, drag to raise or lower a layer. Ctrl + click to edit layer style"
|
||||
id="mapLayers"
|
||||
|
|
@ -717,13 +715,15 @@
|
|||
<li
|
||||
id="toggleVignette"
|
||||
data-tip="Vignette (border fading): click to toggle. Ctrl + click to edit style"
|
||||
data-shortcut="[ (left bracket)"
|
||||
data-shortcut="[ (left square bracket)"
|
||||
onclick="toggleVignette(event)"
|
||||
class="solid"
|
||||
>
|
||||
Vignette
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tip">Click to toggle, drag to raise or lower the layer</div>
|
||||
<div class="tip">Ctrl + click to edit layer style</div>
|
||||
|
||||
<div id="viewMode" data-tip="Set view node">
|
||||
<p>View mode:</p>
|
||||
|
|
@ -1317,6 +1317,12 @@
|
|||
<td><select id="styleStatesBodyFilter" /></td>
|
||||
</tr>
|
||||
|
||||
<tr style="margin-top: 0.8em">
|
||||
<td style="font-style: italic">
|
||||
Halo is only rendered if "Rendering" option is set to "Best quality"!
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr data-tip="Set states halo effect width">
|
||||
<td>Halo width</td>
|
||||
<td>
|
||||
|
|
@ -2063,23 +2069,16 @@
|
|||
</div>
|
||||
|
||||
<div id="toolsContent" class="tabcontent">
|
||||
<p>Click to configure:</p>
|
||||
<div>
|
||||
<button
|
||||
id="editHeightmapButton"
|
||||
data-tip="Click to open Heightmap customization menu"
|
||||
data-shortcut="Shift + H"
|
||||
>
|
||||
Heightmap
|
||||
</button>
|
||||
<div class="separator">Edit</div>
|
||||
<div class="grid">
|
||||
<button id="editBiomesButton" data-tip="Click to open Biomes Editor" data-shortcut="Shift + B">
|
||||
Biomes
|
||||
</button>
|
||||
<button id="editStatesButton" data-tip="Click to open States Editor" data-shortcut="Shift + S">
|
||||
States
|
||||
<button id="overviewBurgsButton" data-tip="Click to open Burgs Overview" data-shortcut="Shift + T">
|
||||
Burgs
|
||||
</button>
|
||||
<button id="editProvincesButton" data-tip="Click to open Provinces Editor" data-shortcut="Shift + P">
|
||||
Provinces
|
||||
<button id="editCulturesButton" data-tip="Click to open Cultures Editor" data-shortcut="Shift + C">
|
||||
Cultures
|
||||
</button>
|
||||
<button
|
||||
id="editDiplomacyButton"
|
||||
|
|
@ -2088,40 +2087,18 @@
|
|||
>
|
||||
Diplomacy
|
||||
</button>
|
||||
<button id="editCulturesButton" data-tip="Click to open Cultures Editor" data-shortcut="Shift + C">
|
||||
Cultures
|
||||
</button>
|
||||
<button id="editNamesBaseButton" data-tip="Click to open Namesbase Editor" data-shortcut="Shift + N">
|
||||
Namesbase
|
||||
</button>
|
||||
<button id="editZonesButton" data-tip="Click to open Zones Editor" data-shortcut="Shift + Z">Zones</button>
|
||||
<button id="editReligions" data-tip="Click to open Religions Editor" data-shortcut="Shift + R">
|
||||
Religions
|
||||
</button>
|
||||
<button id="editEmblemButton" data-tip="Click to open Emblem Editor" data-shortcut="Shift + Y">
|
||||
Emblems
|
||||
</button>
|
||||
<button id="editUnitsButton" data-tip="Click to open Units Editor" data-shortcut="Shift + Q">Units</button>
|
||||
<button id="editNotesButton" data-tip="Click to open Notes Editor" data-shortcut="Shift + O">Notes</button>
|
||||
</div>
|
||||
|
||||
<p>Click to overview:</p>
|
||||
<div>
|
||||
<button
|
||||
id="overviewChartsButton"
|
||||
data-tip="Click to open Charts to overview cells data"
|
||||
data-shortcut="Shift + A"
|
||||
id="editHeightmapButton"
|
||||
data-tip="Click to open Heightmap customization menu"
|
||||
data-shortcut="Shift + H"
|
||||
>
|
||||
Charts
|
||||
Heightmap
|
||||
</button>
|
||||
<button id="overviewBurgsButton" data-tip="Click to open Burgs Overview" data-shortcut="Shift + T">
|
||||
Burgs
|
||||
</button>
|
||||
<button id="overviewRoutesButton" data-tip="Click to open Routes Overview" data-shortcut="Shift + U">
|
||||
Routes
|
||||
</button>
|
||||
<button id="overviewRiversButton" data-tip="Click to open Rivers Overview" data-shortcut="Shift + V">
|
||||
Rivers
|
||||
<button id="overviewMarkersButton" data-tip="Click to open Markers Overview" data-shortcut="Shift + K">
|
||||
Markers
|
||||
</button>
|
||||
<button
|
||||
id="overviewMilitaryButton"
|
||||
|
|
@ -2130,41 +2107,58 @@
|
|||
>
|
||||
Military
|
||||
</button>
|
||||
<button id="overviewMarkersButton" data-tip="Click to open Markers Overview" data-shortcut="Shift + K">
|
||||
Markers
|
||||
<button id="editNamesBaseButton" data-tip="Click to open Namesbase Editor" data-shortcut="Shift + N">
|
||||
Namesbase
|
||||
</button>
|
||||
<button id="overviewCellsButton" data-tip="Click to open Cell details view" data-shortcut="Shift + E">
|
||||
Cells
|
||||
<button id="editNotesButton" data-tip="Click to open Notes Editor" data-shortcut="Shift + O">Notes</button>
|
||||
<button id="editProvincesButton" data-tip="Click to open Provinces Editor" data-shortcut="Shift + P">
|
||||
Provinces
|
||||
</button>
|
||||
<button id="editReligions" data-tip="Click to open Religions Editor" data-shortcut="Shift + R">
|
||||
Religions
|
||||
</button>
|
||||
<button id="overviewRiversButton" data-tip="Click to open Rivers Overview" data-shortcut="Shift + V">
|
||||
Rivers
|
||||
</button>
|
||||
<button id="overviewRoutesButton" data-tip="Click to open Routes Overview" data-shortcut="Shift + U">
|
||||
Routes
|
||||
</button>
|
||||
<button id="editStatesButton" data-tip="Click to open States Editor" data-shortcut="Shift + S">
|
||||
States
|
||||
</button>
|
||||
<button id="editUnitsButton" data-tip="Click to open Units Editor" data-shortcut="Shift + Q">Units</button>
|
||||
<button id="editZonesButton" data-tip="Click to open Zones Editor" data-shortcut="Shift + Z">Zones</button>
|
||||
</div>
|
||||
|
||||
<p>Click to regenerate:</p>
|
||||
<div id="regenerateFeature">
|
||||
<div class="separator">Regenerate</div>
|
||||
<div id="regenerateFeature" class="grid">
|
||||
<button
|
||||
id="regenerateBurgs"
|
||||
data-tip="Click to regenerate all unlocked burgs and routes. States will remain as they are. Note: burgs are only generated in populated areas with culture assigned"
|
||||
>
|
||||
Burgs
|
||||
</button>
|
||||
<button id="regenerateCultures" data-tip="Click to regenerate non-locked cultures">Cultures</button>
|
||||
<button id="regenerateEmblems" data-tip="Click to regenerate all emblems">Emblems</button>
|
||||
<button id="regenerateIce" data-tip="Click to regenerate icebergs and glaciers">Ice</button>
|
||||
<button
|
||||
id="regenerateStateLabels"
|
||||
data-tip="Click to update state labels placement based on current borders"
|
||||
>
|
||||
Labels
|
||||
</button>
|
||||
<button
|
||||
id="regenerateReliefIcons"
|
||||
data-tip="Click to regenerate all relief icons based on current cell biome and elevation"
|
||||
>
|
||||
Relief
|
||||
<button id="regenerateMarkers" data-tip="Click to regenerate unlocked markers">
|
||||
Markers <i id="configRegenerateMarkers" class="icon-cog" data-tip="Click to set number multiplier"></i>
|
||||
</button>
|
||||
<button id="regenerateRoutes" data-tip="Click to regenerate all routes">Routes</button>
|
||||
<button id="regenerateRivers" data-tip="Click to regenerate all rivers (restore default state)">
|
||||
Rivers
|
||||
<button
|
||||
id="regenerateMilitary"
|
||||
data-tip="Click to recalculate military forces based on current military options"
|
||||
>
|
||||
Military
|
||||
</button>
|
||||
<button id="regeneratePopulation" data-tip="Click to recalculate rural and urban population">
|
||||
Population
|
||||
</button>
|
||||
<button
|
||||
id="regenerateStates"
|
||||
data-tip="Click to select new capitals and regenerate non-locked states. Emblems and military forces will be regenerated as well, burgs will remain as they are"
|
||||
>
|
||||
States
|
||||
</button>
|
||||
<button
|
||||
id="regenerateProvinces"
|
||||
data-tip="Click to regenerate non-locked provinces. States will remain as they are"
|
||||
|
|
@ -2172,23 +2166,21 @@
|
|||
Provinces
|
||||
</button>
|
||||
<button
|
||||
id="regenerateBurgs"
|
||||
data-tip="Click to regenerate all unlocked burgs and routes. States will remain as they are. Note: burgs are only generated in populated areas with culture assigned"
|
||||
id="regenerateReliefIcons"
|
||||
data-tip="Click to regenerate all relief icons based on current cell biome and elevation"
|
||||
>
|
||||
Burgs
|
||||
Relief
|
||||
</button>
|
||||
<button id="regenerateEmblems" data-tip="Click to regenerate all emblems">Emblems</button>
|
||||
<button id="regenerateReligions" data-tip="Click to regenerate non-locked religions">Religions</button>
|
||||
<button id="regenerateCultures" data-tip="Click to regenerate non-locked cultures">Cultures</button>
|
||||
<button
|
||||
id="regenerateMilitary"
|
||||
data-tip="Click to recalculate military forces based on current military options"
|
||||
>
|
||||
Military
|
||||
<button id="regenerateRivers" data-tip="Click to regenerate all rivers (restore default state)">
|
||||
Rivers
|
||||
</button>
|
||||
<button id="regenerateIce" data-tip="Click to regenerate icebergs and glaciers">Ice</button>
|
||||
<button id="regenerateMarkers" data-tip="Click to regenerate unlocked markers">
|
||||
Markers <i id="configRegenerateMarkers" class="icon-cog" data-tip="Click to set number multiplier"></i>
|
||||
<button id="regenerateRoutes" data-tip="Click to regenerate all routes">Routes</button>
|
||||
<button
|
||||
id="regenerateStates"
|
||||
data-tip="Click to select new capitals and regenerate non-locked states. Emblems and military forces will be regenerated as well, burgs will remain as they are"
|
||||
>
|
||||
States
|
||||
</button>
|
||||
<button
|
||||
id="regenerateZones"
|
||||
|
|
@ -2198,8 +2190,8 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<p>Click to add:</p>
|
||||
<div id="addFeature">
|
||||
<div class="separator">Add</div>
|
||||
<div id="addFeature" class="grid">
|
||||
<button
|
||||
id="addBurgTool"
|
||||
data-tip="Click on map to place a burg. Hold Shift to add multiple"
|
||||
|
|
@ -2214,14 +2206,6 @@
|
|||
>
|
||||
Label
|
||||
</button>
|
||||
<button
|
||||
id="addRiver"
|
||||
data-tip="Click on map to place a river. Hold Shift to add multiple"
|
||||
data-shortcut="Shift + 3"
|
||||
>
|
||||
River
|
||||
</button>
|
||||
<button id="addRoute" data-tip="Open route creation dialog" data-shortcut="Shift + 4">Route</button>
|
||||
<button
|
||||
id="addMarker"
|
||||
data-tip="Click on map to place a marker. Hold Shift to add multiple"
|
||||
|
|
@ -2229,10 +2213,36 @@
|
|||
>
|
||||
Marker
|
||||
</button>
|
||||
<button
|
||||
id="addRiver"
|
||||
data-tip="Click on map to place a river. Hold Shift to add multiple"
|
||||
data-shortcut="Shift + 3"
|
||||
>
|
||||
River
|
||||
</button>
|
||||
<<<<<<< HEAD
|
||||
<button id="addRoute" data-tip="Open route creation dialog" data-shortcut="Shift + 4">Route</button>
|
||||
=======
|
||||
<button id="addRoute" data-tip="Click on map to place a route" data-shortcut="Shift + 4">Route</button>
|
||||
</div>
|
||||
|
||||
<p>Click to create a new map:</p>
|
||||
<div>
|
||||
<div class="separator">Show</div>
|
||||
<div class="grid">
|
||||
<button id="overviewCellsButton" data-tip="Click to open Cell details view" data-shortcut="Shift + E">
|
||||
Cells
|
||||
</button>
|
||||
>>>>>>> 00abd5213b446922a60e2053eaca711a6d4067e2
|
||||
<button
|
||||
id="overviewChartsButton"
|
||||
data-tip="Click to open Charts to overview cells data"
|
||||
data-shortcut="Shift + A"
|
||||
>
|
||||
Charts
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="separator">Create</div>
|
||||
<div class="grid">
|
||||
<button id="openSubmapMenu" data-tip="Click to generate a submap from the current viewport">Submap</button>
|
||||
<button id="openResampleMenu" data-tip="Click to transform the map">Transform</button>
|
||||
</div>
|
||||
|
|
@ -2321,8 +2331,7 @@
|
|||
|
||||
<div id="aboutContent" class="tabcontent">
|
||||
<p>
|
||||
<a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is a
|
||||
free
|
||||
<a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is an
|
||||
<a href="https://github.com/Azgaar/Fantasy-Map-Generator/blob/master/LICENSE" target="_blank"
|
||||
>open source</a
|
||||
>
|
||||
|
|
@ -2341,7 +2350,7 @@
|
|||
<p>
|
||||
Join our <a href="https://discordapp.com/invite/X7E84HU" target="_blank">Discord server</a> and
|
||||
<a href="https://www.reddit.com/r/FantasyMapGenerator/" target="_blank">Reddit community</a> to ask
|
||||
questions, get help and share maps.
|
||||
questions, get help and share maps. The created maps can be used for free, even for commercial purposes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -2539,15 +2548,15 @@
|
|||
<i data-locked="0" id="lock_mapSize" class="icon-lock-open"></i>
|
||||
<label data-tip="Set map size relative to the world size">
|
||||
<i>Map size:</i>
|
||||
<input id="mapSizeInput" data-stored="mapSize" type="number" min="1" max="100" />%
|
||||
<input id="mapSizeOutput" data-stored="mapSize" type="range" min="1" max="100" />
|
||||
<input id="mapSizeInput" data-stored="mapSize" type="number" min="1" max="100" step="0.1" />%
|
||||
<input id="mapSizeOutput" data-stored="mapSize" type="range" min="1" max="100" step="0.1" />
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<i data-locked="0" id="lock_latitude" class="icon-lock-open"></i>
|
||||
<label data-tip="Set a North-South map shift">
|
||||
<label data-tip="Set a North-South map shift, set to 50 to make map center lie on Equator">
|
||||
<i>Latitudes:</i>
|
||||
<input id="latitudeInput" data-stored="latitude" type="number" min="0" max="100" step="1" />
|
||||
<input id="latitudeInput" data-stored="latitude" type="number" min="0" max="100" step="0.1" />
|
||||
<br /><i>N</i
|
||||
><input
|
||||
id="latitudeOutput"
|
||||
|
|
@ -2555,14 +2564,42 @@
|
|||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
step="1"
|
||||
step="0.1"
|
||||
style="width: 10.3em"
|
||||
/><i>S</i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label data-tip="Set precipitation - water amount clouds can bring. Defines rivers and biomes generation">
|
||||
<i data-locked="0" id="lock_longitude" class="icon-lock-open"></i>
|
||||
<label data-tip="Set a West-East map shift, set to 50 to make map center lie on Prime meridian">
|
||||
<i>Longitudes:</i>
|
||||
<input
|
||||
id="longitudeInput"
|
||||
data-stored="longitude"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
value="50"
|
||||
step="0.1"
|
||||
/>
|
||||
<br /><i>W</i
|
||||
><input
|
||||
id="longitudeOutput"
|
||||
data-stored="longitude"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
step="0.1"
|
||||
style="width: 10.3em"
|
||||
/><i>E</i>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
data-tip="Set precipitation - water amount clouds can bring. Defines rivers and biomes generation. Keep around 100% for default generation"
|
||||
>
|
||||
<i data-locked="0" id="lock_prec" class="icon-lock-open"></i>
|
||||
<i>Precipitation:</i>
|
||||
<input id="precInput" data-stored="prec" type="number" />%
|
||||
|
|
@ -2637,8 +2674,10 @@
|
|||
<text x="-15" y="190">60°</text>
|
||||
<text x="-15" y="204">90°</text>
|
||||
</g>
|
||||
<circle id="globeOutline" cx="100" cy="100" r="100" />
|
||||
<line id="globeEquator" x1="1" x2="199" y1="100" y2="100" />
|
||||
<circle id="globeGradient" cx="100" cy="100" r="100" fill="url(#temperatureGradient)" stroke="none" />
|
||||
<line id="globePrimeMeridian" x1="100" x2="100" y1="0" y2="200" />
|
||||
<line id="globeEquator" x1="1" x2="200" y1="100" y2="100" />
|
||||
<circle id="globeOutline" cx="100" cy="100" r="100" fill="none" />
|
||||
<path id="globeGraticule" />
|
||||
<path id="globeArea" />
|
||||
</svg>
|
||||
|
|
@ -2648,6 +2687,14 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 0.3em">
|
||||
<i>Presets:</i>
|
||||
<button id="wcWholeWorld" data-tip="Click to set map size to cover the whole world">Whole world</button>
|
||||
<button id="wcNorthern" data-tip="Click to set map size to cover the Northern latitudes">Northern</button>
|
||||
<button id="wcTropical" data-tip="Click to set map size to cover the Tropical latitudes">Tropical</button>
|
||||
<button id="wcSouthern" data-tip="Click to set map size to cover the Southern latitudes">Southern</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="labelEditor" class="dialog" style="display: none">
|
||||
|
|
@ -7894,18 +7941,19 @@
|
|||
</symbol>
|
||||
</g>
|
||||
|
||||
<g id="rose" stroke-width="1">
|
||||
<g id="sL" stroke="#3f3f3f">
|
||||
<g id="defs-compass-rose" stroke-width="1.1">
|
||||
<g id="rose-coord-line" stroke="#3f3f3f">
|
||||
<line id="sL1" x1="0" y1="-20000" x2="0" y2="20000" />
|
||||
<line id="sL2" x1="-20000" y1="0" x2="20000" y2="0" />
|
||||
</g>
|
||||
<use href="#sL" transform="rotate(45)" />
|
||||
<use href="#sL" transform="rotate(22.5)" />
|
||||
<use href="#sL" transform="rotate(-22.5)" />
|
||||
<use href="#sL" transform="rotate(11.25)" />
|
||||
<use href="#sL" transform="rotate(-11.25)" />
|
||||
<use href="#sL" transform="rotate(56.25)" />
|
||||
<use href="#sL" transform="rotate(-56.25)" />
|
||||
<use href="#rose-coord-line" transform="rotate(45)" />
|
||||
<use href="#rose-coord-line" transform="rotate(22.5)" />
|
||||
<use href="#rose-coord-line" transform="rotate(-22.5)" />
|
||||
<use href="#rose-coord-line" transform="rotate(11.25)" />
|
||||
<use href="#rose-coord-line" transform="rotate(-11.25)" />
|
||||
<use href="#rose-coord-line" transform="rotate(56.25)" />
|
||||
<use href="#rose-coord-line" transform="rotate(-56.25)" />
|
||||
|
||||
<g stroke-width="8" stroke-opacity="1" shape-rendering="geometricprecision">
|
||||
<circle r="9" stroke="#000000" fill="#1b1b1b" />
|
||||
<circle r="75" stroke="#008000" fill="#ffffff" fill-opacity=".1" />
|
||||
|
|
@ -8136,7 +8184,7 @@
|
|||
<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.96.00"></script>
|
||||
<script src="modules/ocean-layers.js?v=1.98.04"></script>
|
||||
<script src="modules/river-generator.js?v=1.89.13"></script>
|
||||
<script src="modules/lakes.js"></script>
|
||||
<script src="modules/biomes.js"></script>
|
||||
|
|
@ -8158,15 +8206,15 @@
|
|||
<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.96.00"></script>
|
||||
<script src="modules/ui/options.js?v=1.97.14"></script>
|
||||
<script src="main.js?v=1.97.11"></script>
|
||||
<script src="modules/ui/general.js?v=1.98.01"></script>
|
||||
<script src="modules/ui/options.js?v=1.98.04"></script>
|
||||
<script src="main.js?v=1.98.01"></script>
|
||||
|
||||
<script defer src="modules/relief-icons.js"></script>
|
||||
<script defer src="modules/ui/style.js?v=1.96.00"></script>
|
||||
<script defer src="modules/ui/editors.js?v=1.97.12"></script>
|
||||
<script defer src="modules/ui/tools.js?v=1.97.12"></script>
|
||||
<script defer src="modules/ui/world-configurator.js?v=1.98.00"></script>
|
||||
<script defer src="modules/ui/world-configurator.js?v=1.98.01"></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>
|
||||
|
|
@ -8204,10 +8252,10 @@
|
|||
<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.96.00"></script>
|
||||
<script defer src="modules/io/load.js?v=1.97.04"></script>
|
||||
<script defer src="modules/io/save.js?v=1.98.01"></script>
|
||||
<script defer src="modules/io/load.js?v=1.98.01"></script>
|
||||
<script defer src="modules/io/cloud.js?v=1.96.00"></script>
|
||||
<script defer src="modules/io/export.js?v=1.97.03"></script>
|
||||
<script defer src="modules/io/export.js?v=1.98.05"></script>
|
||||
|
||||
<!-- Web Components -->
|
||||
<script defer src="components/fill-box.js"></script>
|
||||
|
|
|
|||
125
main.js
125
main.js
|
|
@ -53,7 +53,7 @@ let biomes = viewbox.append("g").attr("id", "biomes");
|
|||
let cells = viewbox.append("g").attr("id", "cells");
|
||||
let gridOverlay = viewbox.append("g").attr("id", "gridOverlay");
|
||||
let coordinates = viewbox.append("g").attr("id", "coordinates");
|
||||
let compass = viewbox.append("g").attr("id", "compass");
|
||||
let compass = viewbox.append("g").attr("id", "compass").style("display", "none");
|
||||
let rivers = viewbox.append("g").attr("id", "rivers");
|
||||
let terrain = viewbox.append("g").attr("id", "terrain");
|
||||
let relig = viewbox.append("g").attr("id", "relig");
|
||||
|
|
@ -126,6 +126,9 @@ emblems.append("g").attr("id", "burgEmblems");
|
|||
emblems.append("g").attr("id", "provinceEmblems");
|
||||
emblems.append("g").attr("id", "stateEmblems");
|
||||
|
||||
// compass
|
||||
compass.append("use").attr("xlink:href", "#defs-compass-rose");
|
||||
|
||||
// fogging
|
||||
fogging.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%");
|
||||
fogging
|
||||
|
|
@ -195,10 +198,10 @@ let options = {
|
|||
};
|
||||
|
||||
let mapCoordinates = {}; // map coordinates on globe
|
||||
let populationRate = +document.getElementById("populationRateInput").value;
|
||||
let distanceScale = +document.getElementById("distanceScaleInput").value;
|
||||
let urbanization = +document.getElementById("urbanizationInput").value;
|
||||
let urbanDensity = +document.getElementById("urbanDensityInput").value;
|
||||
let populationRate = +byId("populationRateInput").value;
|
||||
let distanceScale = +byId("distanceScaleInput").value;
|
||||
let urbanization = +byId("urbanizationInput").value;
|
||||
let urbanDensity = +byId("urbanDensityInput").value;
|
||||
|
||||
applyStoredOptions();
|
||||
|
||||
|
|
@ -439,10 +442,10 @@ function handleZoom(isScaleChanged, isPositionChanged) {
|
|||
|
||||
// zoom image converter overlay
|
||||
if (customization === 1) {
|
||||
const canvas = document.getElementById("canvas");
|
||||
const canvas = byId("canvas");
|
||||
if (!canvas || canvas.style.opacity === "0") return;
|
||||
|
||||
const img = document.getElementById("imageToConvert");
|
||||
const img = byId("imageToConvert");
|
||||
if (!img) return;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
|
@ -524,7 +527,7 @@ function invokeActiveZooming() {
|
|||
+markers.attr("rescale") &&
|
||||
pack.markers?.forEach(marker => {
|
||||
const {i, x, y, size = 30, hidden} = marker;
|
||||
const el = !hidden && document.getElementById(`marker${i}`);
|
||||
const el = !hidden && byId(`marker${i}`);
|
||||
if (!el) return;
|
||||
|
||||
const zoomedSize = Math.max(rn(size / 5 + 24 / scale, 2), 1);
|
||||
|
|
@ -561,18 +564,18 @@ void (function addDragToUpload() {
|
|||
document.addEventListener("dragover", function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
document.getElementById("mapOverlay").style.display = null;
|
||||
byId("mapOverlay").style.display = null;
|
||||
});
|
||||
|
||||
document.addEventListener("dragleave", function (e) {
|
||||
document.getElementById("mapOverlay").style.display = "none";
|
||||
byId("mapOverlay").style.display = "none";
|
||||
});
|
||||
|
||||
document.addEventListener("drop", function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
const overlay = document.getElementById("mapOverlay");
|
||||
const overlay = byId("mapOverlay");
|
||||
overlay.style.display = "none";
|
||||
if (e.dataTransfer.items == null || e.dataTransfer.items.length !== 1) return; // no files or more than one
|
||||
const file = e.dataTransfer.items[0].getAsFile();
|
||||
|
|
@ -780,7 +783,7 @@ function addLakesInDeepDepressions() {
|
|||
TIME && console.time("addLakesInDeepDepressions");
|
||||
const {cells, features} = grid;
|
||||
const {c, h, b} = cells;
|
||||
const ELEVATION_LIMIT = +document.getElementById("lakeElevationLimitOutput").value;
|
||||
const ELEVATION_LIMIT = +byId("lakeElevationLimitOutput").value;
|
||||
if (ELEVATION_LIMIT === 80) return;
|
||||
|
||||
for (const i of cells.i) {
|
||||
|
|
@ -880,73 +883,77 @@ function openNearSeaLakes() {
|
|||
|
||||
// define map size and position based on template and random factor
|
||||
function defineMapSize() {
|
||||
const [size, latitude] = getSizeAndLatitude();
|
||||
const [size, latitude, longitude] = getSizeAndLatitude();
|
||||
const randomize = new URL(window.location.href).searchParams.get("options") === "default"; // ignore stored options
|
||||
if (randomize || !locked("mapSize")) mapSizeOutput.value = mapSizeInput.value = rn(size);
|
||||
if (randomize || !locked("latitude")) latitudeOutput.value = latitudeInput.value = rn(latitude);
|
||||
if (randomize || !locked("mapSize")) mapSizeOutput.value = mapSizeInput.value = size;
|
||||
if (randomize || !locked("latitude")) latitudeOutput.value = latitudeInput.value = latitude;
|
||||
if (randomize || !locked("longitude")) longitudeOutput.value = longitudeInput.value = longitude;
|
||||
|
||||
function getSizeAndLatitude() {
|
||||
const template = byId("templateInput").value; // heightmap template
|
||||
|
||||
if (template === "africa-centric") return [45, 53];
|
||||
if (template === "arabia") return [20, 35];
|
||||
if (template === "atlantics") return [42, 23];
|
||||
if (template === "britain") return [7, 20];
|
||||
if (template === "caribbean") return [15, 40];
|
||||
if (template === "east-asia") return [11, 28];
|
||||
if (template === "eurasia") return [38, 19];
|
||||
if (template === "europe") return [20, 16];
|
||||
if (template === "europe-accented") return [14, 22];
|
||||
if (template === "europe-and-central-asia") return [25, 10];
|
||||
if (template === "europe-central") return [11, 22];
|
||||
if (template === "europe-north") return [7, 18];
|
||||
if (template === "greenland") return [22, 7];
|
||||
if (template === "hellenica") return [8, 27];
|
||||
if (template === "iceland") return [2, 15];
|
||||
if (template === "indian-ocean") return [45, 55];
|
||||
if (template === "mediterranean-sea") return [10, 29];
|
||||
if (template === "middle-east") return [8, 31];
|
||||
if (template === "north-america") return [37, 17];
|
||||
if (template === "us-centric") return [66, 27];
|
||||
if (template === "us-mainland") return [16, 30];
|
||||
if (template === "world") return [78, 27];
|
||||
if (template === "world-from-pacific") return [75, 32];
|
||||
if (template === "africa-centric") return [45, 53, 38];
|
||||
if (template === "arabia") return [20, 35, 35];
|
||||
if (template === "atlantics") return [42, 23, 65];
|
||||
if (template === "britain") return [7, 20, 51.3];
|
||||
if (template === "caribbean") return [15, 40, 74.8];
|
||||
if (template === "east-asia") return [11, 28, 9.4];
|
||||
if (template === "eurasia") return [38, 19, 27];
|
||||
if (template === "europe") return [20, 16, 44.8];
|
||||
if (template === "europe-accented") return [14, 22, 44.8];
|
||||
if (template === "europe-and-central-asia") return [25, 10, 39.5];
|
||||
if (template === "europe-central") return [11, 22, 46.4];
|
||||
if (template === "europe-north") return [7, 18, 48.9];
|
||||
if (template === "greenland") return [22, 7, 55.8];
|
||||
if (template === "hellenica") return [8, 27, 43.5];
|
||||
if (template === "iceland") return [2, 15, 55.3];
|
||||
if (template === "indian-ocean") return [45, 55, 14];
|
||||
if (template === "mediterranean-sea") return [10, 29, 45.8];
|
||||
if (template === "middle-east") return [8, 31, 34.4];
|
||||
if (template === "north-america") return [37, 17, 87];
|
||||
if (template === "us-centric") return [66, 27, 100];
|
||||
if (template === "us-mainland") return [16, 30, 77.5];
|
||||
if (template === "world") return [78, 27, 40];
|
||||
if (template === "world-from-pacific") return [75, 32, 30]; // longitude doesn't fit
|
||||
|
||||
const part = grid.features.some(f => f.land && f.border); // if land goes over map borders
|
||||
const max = part ? 80 : 100; // max size
|
||||
const lat = () => gauss(P(0.5) ? 40 : 60, 20, 25, 75); // latitude shift
|
||||
|
||||
if (!part) {
|
||||
if (template === "Pangea") return [100, 50];
|
||||
if (template === "Shattered" && P(0.7)) return [100, 50];
|
||||
if (template === "Continents" && P(0.5)) return [100, 50];
|
||||
if (template === "Archipelago" && P(0.35)) return [100, 50];
|
||||
if (template === "High Island" && P(0.25)) return [100, 50];
|
||||
if (template === "Low Island" && P(0.1)) return [100, 50];
|
||||
if (template === "pangea") return [100, 50, 50];
|
||||
if (template === "shattered" && P(0.7)) return [100, 50, 50];
|
||||
if (template === "continents" && P(0.5)) return [100, 50, 50];
|
||||
if (template === "archipelago" && P(0.35)) return [100, 50, 50];
|
||||
if (template === "highIsland" && P(0.25)) return [100, 50, 50];
|
||||
if (template === "lowIsland" && P(0.1)) return [100, 50, 50];
|
||||
}
|
||||
|
||||
if (template === "Pangea") return [gauss(70, 20, 30, max), lat()];
|
||||
if (template === "Volcano") return [gauss(20, 20, 10, max), lat()];
|
||||
if (template === "Mediterranean") return [gauss(25, 30, 15, 80), lat()];
|
||||
if (template === "Peninsula") return [gauss(15, 15, 5, 80), lat()];
|
||||
if (template === "Isthmus") return [gauss(15, 20, 3, 80), lat()];
|
||||
if (template === "Atoll") return [gauss(5, 10, 2, max), lat()];
|
||||
if (template === "pangea") return [gauss(70, 20, 30, max), lat(), 50];
|
||||
if (template === "volcano") return [gauss(20, 20, 10, max), lat(), 50];
|
||||
if (template === "mediterranean") return [gauss(25, 30, 15, 80), lat(), 50];
|
||||
if (template === "peninsula") return [gauss(15, 15, 5, 80), lat(), 50];
|
||||
if (template === "isthmus") return [gauss(15, 20, 3, 80), lat(), 50];
|
||||
if (template === "atoll") return [gauss(3, 2, 1, 5, 1), lat(), 50];
|
||||
|
||||
return [gauss(30, 20, 15, max), lat()]; // Continents, Archipelago, High Island, Low Island
|
||||
return [gauss(30, 20, 15, max), lat(), 50]; // Continents, Archipelago, High Island, Low Island
|
||||
}
|
||||
}
|
||||
|
||||
// calculate map position on globe
|
||||
function calculateMapCoordinates() {
|
||||
const size = +document.getElementById("mapSizeOutput").value;
|
||||
const latShift = +document.getElementById("latitudeOutput").value;
|
||||
const sizeFraction = +byId("mapSizeOutput").value / 100;
|
||||
const latShift = +byId("latitudeOutput").value / 100;
|
||||
const lonShift = +byId("longitudeOutput").value / 100;
|
||||
|
||||
const latT = rn((size / 100) * 180, 1);
|
||||
const latN = rn(90 - ((180 - latT) * latShift) / 100, 1);
|
||||
const latT = rn(sizeFraction * 180, 1);
|
||||
const latN = rn(90 - (180 - latT) * latShift, 1);
|
||||
const latS = rn(latN - latT, 1);
|
||||
|
||||
const lon = rn(Math.min(((graphWidth / graphHeight) * latT) / 2, 180));
|
||||
mapCoordinates = {latT, latN, latS, lonT: lon * 2, lonW: -lon, lonE: lon};
|
||||
const lonT = rn(Math.min((graphWidth / graphHeight) * latT, 360), 1);
|
||||
const lonE = rn(180 - (360 - lonT) * lonShift, 1);
|
||||
const lonW = rn(lonE - lonT, 1);
|
||||
mapCoordinates = {latT, latN, latS, lonT, lonW, lonE};
|
||||
}
|
||||
|
||||
// temperature model, trying to follow real-world data
|
||||
|
|
@ -1759,7 +1766,7 @@ function addZones(number = 1) {
|
|||
}
|
||||
|
||||
function addEruption() {
|
||||
const volcano = document.getElementById("markers").querySelector("use[data-id='#marker_volcano']");
|
||||
const volcano = byId("markers").querySelector("use[data-id='#marker_volcano']");
|
||||
if (!volcano) return;
|
||||
|
||||
const x = +volcano.dataset.x,
|
||||
|
|
@ -1978,7 +1985,7 @@ function undraw() {
|
|||
.getElementById("deftemp")
|
||||
.querySelectorAll("path, clipPath, svg")
|
||||
.forEach(el => el.remove());
|
||||
document.getElementById("coas").innerHTML = ""; // remove auto-generated emblems
|
||||
byId("coas").innerHTML = ""; // remove auto-generated emblems
|
||||
notes = [];
|
||||
rulers = new Rulers();
|
||||
unfog();
|
||||
|
|
|
|||
|
|
@ -848,10 +848,23 @@ export function resolveVersionConflicts(version) {
|
|||
}
|
||||
|
||||
if (version < 1.98) {
|
||||
// v1.98.00 changed routes generation algorithm and data format
|
||||
// v1.98.00 changed compass layer and rose element id
|
||||
const rose = compass.select("use");
|
||||
rose.attr("xlink:href", "#defs-compass-rose");
|
||||
|
||||
if (!compass.selectAll("*").size()) {
|
||||
compass.style("display", "none");
|
||||
compass.append("use").attr("xlink:href", "#defs-compass-rose");
|
||||
shiftCompass();
|
||||
}
|
||||
}
|
||||
|
||||
if (version < 1.99) {
|
||||
// v1.99.00 changed routes generation algorithm and data format
|
||||
// 1. cells.road => cells.routes and now it an object of objects {i1: {i2: routeId, i3: routeId}}
|
||||
// 2. cells.crossroad is removed
|
||||
// 3. pack.routes is added as an array of objects
|
||||
// 4. rendering is changed
|
||||
// v1.98.00 changed compass layer and rose element id
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ function getSettings() {
|
|||
populationRate: populationRate,
|
||||
urbanization: urbanization,
|
||||
mapSize: mapSizeOutput.value,
|
||||
latitudeO: latitudeOutput.value,
|
||||
latitude: latitudeOutput.value,
|
||||
longitude: longitudeOutput.value,
|
||||
prec: precOutput.value,
|
||||
options: options,
|
||||
mapName: mapName.value,
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ async function exportToPngTiles() {
|
|||
imgSchema.src = urlSchema;
|
||||
await loadImage(imgSchema);
|
||||
|
||||
status.innerHTML = "Drawing schema...";
|
||||
status.innerHTML = "Rendering schema...";
|
||||
ctx.drawImage(imgSchema, 0, 0, canvas.width, canvas.height);
|
||||
const blob = await canvasToBlob(canvas, "image/png");
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
|
@ -95,9 +95,9 @@ async function exportToPngTiles() {
|
|||
|
||||
// download tiles
|
||||
const url = await getMapURL("tiles", {fullMap: true});
|
||||
const tilesX = +byId("tileColsInput").value;
|
||||
const tilesY = +byId("tileRowsInput").value;
|
||||
const scale = +byId("tileScaleInput").value;
|
||||
const tilesX = +byId("tileColsOutput").value || 2;
|
||||
const tilesY = +byId("tileRowsOutput").value || 2;
|
||||
const scale = +byId("tileScaleOutput").value || 1;
|
||||
const tolesTotal = tilesX * tilesY;
|
||||
|
||||
const tileW = (graphWidth / tilesX) | 0;
|
||||
|
|
@ -113,11 +113,17 @@ async function exportToPngTiles() {
|
|||
await loadImage(img);
|
||||
|
||||
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
function getRowLabel(row) {
|
||||
const first = row >= alphabet.length ? alphabet[Math.floor(row / alphabet.length) - 1] : "";
|
||||
const last = alphabet[row % alphabet.length];
|
||||
return first + last;
|
||||
}
|
||||
|
||||
for (let y = 0, row = 0, id = 1; y + tileH <= graphHeight; y += tileH, row++) {
|
||||
const rowName = alphabet[row % alphabet.length];
|
||||
const rowName = getRowLabel(row);
|
||||
|
||||
for (let x = 0, cell = 1; x + tileW <= graphWidth; x += tileW, cell++, id++) {
|
||||
status.innerHTML = `Drawing tile ${rowName}${cell} (${id} of ${tolesTotal})...`;
|
||||
status.innerHTML = `Rendering tile ${rowName}${cell} (${id} of ${tolesTotal})...`;
|
||||
ctx.drawImage(img, x, y, tileW, tileH, 0, 0, width, height);
|
||||
const blob = await canvasToBlob(canvas, "image/png");
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
|
@ -295,7 +301,7 @@ async function getMapURL(type, options) {
|
|||
|
||||
// add wind rose
|
||||
if (cloneEl.getElementById("compass")) {
|
||||
const rose = svgDefs.getElementById("rose");
|
||||
const rose = svgDefs.getElementById("defs-compass-rose");
|
||||
if (rose) cloneDefs.appendChild(rose.cloneNode(true));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ async function parseLoadedData(data, mapVersion) {
|
|||
if (settings[22]) stylePreset.value = settings[22];
|
||||
if (settings[23]) rescaleLabels.checked = +settings[23];
|
||||
if (settings[24]) urbanDensity = urbanDensityInput.value = urbanDensityOutput.value = +settings[24];
|
||||
if (settings[25]) longitudeInput.value = longitudeOutput.value = minmax(settings[25] || 50, 0, 100);
|
||||
})();
|
||||
|
||||
void (function applyOptionsToUI() {
|
||||
|
|
@ -458,7 +459,7 @@ async function parseLoadedData(data, mapVersion) {
|
|||
{
|
||||
// dynamically import and run auto-update script
|
||||
const versionNumber = parseFloat(params[0]);
|
||||
const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.97.04");
|
||||
const {resolveVersionConflicts} = await import("../dynamic/auto-update.js?v=1.98.00");
|
||||
resolveVersionConflicts(versionNumber);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ function prepareMapData() {
|
|||
+hideLabels.checked,
|
||||
stylePreset.value,
|
||||
+rescaleLabels.checked,
|
||||
urbanDensity
|
||||
urbanDensity,
|
||||
longitudeOutput.value
|
||||
].join("|");
|
||||
const coords = JSON.stringify(mapCoordinates);
|
||||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
|
|
|
|||
|
|
@ -1070,27 +1070,29 @@ function drawStates() {
|
|||
|
||||
const bodyData = body.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
|
||||
const gapData = gap.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
|
||||
const haloData = halo.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
|
||||
|
||||
const bodyString = bodyData.map(d => `<path id="state${d[1]}" d="${d[0]}" fill="${d[2]}" stroke="none"/>`).join("");
|
||||
const gapString = gapData.map(d => `<path id="state-gap${d[1]}" d="${d[0]}" fill="none" stroke="${d[2]}"/>`).join("");
|
||||
statesBody.html(bodyString + gapString);
|
||||
|
||||
const isOptimized = shapeRendering.value === "optimizeSpeed";
|
||||
if (!isOptimized) {
|
||||
const haloData = halo.map((p, s) => [p.length > 10 ? p : null, s, states[s].color]).filter(d => d[0]);
|
||||
|
||||
const haloString = haloData
|
||||
.map(d => {
|
||||
const stroke = d3.color(d[2]) ? d3.color(d[2]).darker().hex() : "#666666";
|
||||
return `<path id="state-border${d[1]}" d="${d[0]}" clip-path="url(#state-clip${d[1]})" stroke="${stroke}"/>`;
|
||||
})
|
||||
.join("");
|
||||
statesHalo.html(haloString);
|
||||
|
||||
const clipString = bodyData
|
||||
.map(d => `<clipPath id="state-clip${d[1]}"><use href="#state${d[1]}"/></clipPath>`)
|
||||
.join("");
|
||||
const haloString = haloData
|
||||
.map(
|
||||
d =>
|
||||
`<path id="state-border${d[1]}" d="${d[0]}" clip-path="url(#state-clip${d[1]})" stroke="${
|
||||
d3.color(d[2]) ? d3.color(d[2]).darker().hex() : "#666666"
|
||||
}"/>`
|
||||
)
|
||||
.join("");
|
||||
|
||||
statesBody.html(bodyString + gapString);
|
||||
defs.select("#statePaths").html(clipString);
|
||||
statesHalo.html(haloString);
|
||||
}
|
||||
|
||||
// connect vertices to chain
|
||||
function connectVertices(start, state) {
|
||||
const chain = []; // vertices chain to form a path
|
||||
const getType = c => {
|
||||
|
|
@ -1525,10 +1527,6 @@ function toggleCompass(event) {
|
|||
if (!layerIsOn("toggleCompass")) {
|
||||
turnButtonOn("toggleCompass");
|
||||
$("#compass").fadeIn();
|
||||
if (!compass.selectAll("*").size()) {
|
||||
compass.append("use").attr("xlink:href", "#rose");
|
||||
shiftCompass();
|
||||
}
|
||||
if (event && isCtrlClick(event)) editStyle("compass");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
|
|
|
|||
|
|
@ -644,17 +644,16 @@ function randomizeCultureSet() {
|
|||
function setRendering(value) {
|
||||
viewbox.attr("shape-rendering", value);
|
||||
|
||||
// if (value === "optimizeSpeed") {
|
||||
// // block some styles
|
||||
// coastline.select("#sea_island").style("filter", "none");
|
||||
// statesHalo.style("display", "none");
|
||||
// emblems.style("opacity", 1);
|
||||
// } else {
|
||||
// // remove style block
|
||||
// coastline.select("#sea_island").style("filter", null);
|
||||
// statesHalo.style("display", null);
|
||||
// emblems.style("opacity", null);
|
||||
// }
|
||||
if (value === "optimizeSpeed") {
|
||||
// block some styles
|
||||
coastline.select("#sea_island").style("filter", "none");
|
||||
statesHalo.style("display", "none");
|
||||
} else {
|
||||
// remove style block
|
||||
coastline.select("#sea_island").style("filter", null);
|
||||
statesHalo.style("display", null);
|
||||
if (pack.cells && statesHalo.selectAll("*").size() === 0) drawStates();
|
||||
}
|
||||
}
|
||||
|
||||
// generate current year and era name
|
||||
|
|
@ -902,9 +901,9 @@ function updateTilesOptions() {
|
|||
}
|
||||
|
||||
const tileSize = byId("tileSize");
|
||||
const tilesX = +byId("tileColsOutput").value;
|
||||
const tilesY = +byId("tileRowsOutput").value;
|
||||
const scale = +byId("tileScaleOutput").value;
|
||||
const tilesX = +byId("tileColsOutput").value || 2;
|
||||
const tilesY = +byId("tileRowsOutput").value || 2;
|
||||
const scale = +byId("tileScaleOutput").value || 1;
|
||||
|
||||
// calculate size
|
||||
const sizeX = graphWidth * scale * tilesX;
|
||||
|
|
@ -921,11 +920,16 @@ function updateTilesOptions() {
|
|||
const tileH = (graphHeight / tilesY) | 0;
|
||||
|
||||
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
function getRowLabel(row) {
|
||||
const first = row >= alphabet.length ? alphabet[Math.floor(row / alphabet.length) - 1] : "";
|
||||
const last = alphabet[row % alphabet.length];
|
||||
return first + last;
|
||||
}
|
||||
|
||||
for (let y = 0, row = 0; y + tileH <= graphHeight; y += tileH, row++) {
|
||||
for (let x = 0, column = 1; x + tileW <= graphWidth; x += tileW, column++) {
|
||||
rects.push(`<rect x=${x} y=${y} width=${tileW} height=${tileH} />`);
|
||||
const label = alphabet[row % alphabet.length] + column;
|
||||
labels.push(`<text x=${x + tileW / 2} y=${y + tileH / 2}>${label}</text>`);
|
||||
labels.push(`<text x=${x + tileW / 2} y=${y + tileH / 2}>${getRowLabel(row)}${column}</text>`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ async function getStylePreset(desiredPreset) {
|
|||
|
||||
async function fetchSystemPreset(preset) {
|
||||
try {
|
||||
const res = await fetch(`./styles/${preset}.json`);
|
||||
const res = await fetch(`./styles/${preset}.json?v=${version}`);
|
||||
return await res.json();
|
||||
} catch (err) {
|
||||
throw new Error("Cannot fetch style preset", preset);
|
||||
|
|
@ -198,7 +198,7 @@ function addStylePreset() {
|
|||
"mask"
|
||||
],
|
||||
"#compass": ["opacity", "transform", "filter", "mask", "shape-rendering"],
|
||||
"#rose": ["transform"],
|
||||
"#compass > use": ["transform"],
|
||||
"#relig": ["opacity", "stroke", "stroke-width", "filter"],
|
||||
"#cults": ["opacity", "stroke", "stroke-width", "stroke-dasharray", "stroke-linecap", "filter"],
|
||||
"#landmass": ["opacity", "fill", "filter"],
|
||||
|
|
|
|||
|
|
@ -5,18 +5,17 @@ function editWorld() {
|
|||
title: "Configure World",
|
||||
resizable: false,
|
||||
width: "minmax(40em, 85vw)",
|
||||
buttons: {
|
||||
"Whole World": () => applyWorldPreset(100, 50),
|
||||
Northern: () => applyWorldPreset(33, 25),
|
||||
Tropical: () => applyWorldPreset(33, 50),
|
||||
Southern: () => applyWorldPreset(33, 75)
|
||||
},
|
||||
buttons: {"Update world": updateWorld},
|
||||
open: function () {
|
||||
const buttons = $(this).dialog("widget").find(".ui-dialog-buttonset > button");
|
||||
buttons[0].addEventListener("mousemove", () => tip("Click to set map size to cover the whole World"));
|
||||
buttons[1].addEventListener("mousemove", () => tip("Click to set map size to cover the Northern latitudes"));
|
||||
buttons[2].addEventListener("mousemove", () => tip("Click to set map size to cover the Tropical latitudes"));
|
||||
buttons[3].addEventListener("mousemove", () => tip("Click to set map size to cover the Southern latitudes"));
|
||||
const checkbox = /* html */ `<div class="dontAsk" data-tip="Automatically update world on input changes and button clicks">
|
||||
<input id="wcAutoChange" class="checkbox" type="checkbox" checked />
|
||||
<label for="wcAutoChange" class="checkbox-label"><i>auto-apply changes</i></label>
|
||||
</div>`;
|
||||
const pane = this.parentElement.querySelector(".ui-dialog-buttonpane");
|
||||
pane.insertAdjacentHTML("afterbegin", checkbox);
|
||||
|
||||
const button = this.parentElement.querySelector(".ui-dialog-buttonset > button");
|
||||
button.on("mousemove", () => tip("Apply curreny settings to the map"));
|
||||
},
|
||||
close: function () {
|
||||
$(this).dialog("destroy");
|
||||
|
|
@ -34,12 +33,17 @@ function editWorld() {
|
|||
if (modules.editWorld) return;
|
||||
modules.editWorld = true;
|
||||
|
||||
byId("worldControls").addEventListener("input", e => updateWorld(e.target));
|
||||
globe.select("#globeWindArrows").on("click", changeWind);
|
||||
globe.select("#globeGraticule").attr("d", round(path(d3.geoGraticule()()))); // globe graticule
|
||||
const graticule = d3.geoGraticule();
|
||||
globe.select("#globeWindArrows").on("click", handleWindChange);
|
||||
globe.select("#globeGraticule").attr("d", round(path(graticule()))); // globe graticule
|
||||
updateWindDirections();
|
||||
|
||||
byId("restoreWinds").addEventListener("click", restoreDefaultWinds);
|
||||
byId("worldControls").on("input", handleControlsChange);
|
||||
byId("restoreWinds").on("click", restoreDefaultWinds);
|
||||
byId("wcWholeWorld").on("click", () => applyWorldPreset(100, 50));
|
||||
byId("wcNorthern").on("click", () => applyWorldPreset(33, 25));
|
||||
byId("wcTropical").on("click", () => applyWorldPreset(33, 50));
|
||||
byId("wcSouthern").on("click", () => applyWorldPreset(33, 75));
|
||||
|
||||
function updateInputValues() {
|
||||
byId("temperatureEquatorInput").value = options.temperatureEquator;
|
||||
|
|
@ -55,27 +59,27 @@ function editWorld() {
|
|||
byId("temperatureSouthPoleF").innerText = convertTemperature(options.temperatureSouthPole, "°F");
|
||||
}
|
||||
|
||||
function updateWorld(el) {
|
||||
if (el?.dataset.stored) {
|
||||
const stored = el.dataset.stored;
|
||||
byId(stored + "Input").value = el.value;
|
||||
byId(stored + "Output").value = el.value;
|
||||
lock(el.dataset.stored);
|
||||
function handleControlsChange({target}) {
|
||||
const stored = target.dataset.stored;
|
||||
byId(stored + "Input").value = target.value;
|
||||
byId(stored + "Output").value = target.value;
|
||||
lock(stored);
|
||||
|
||||
if (stored === "temperatureEquator") {
|
||||
options.temperatureEquator = Number(el.value);
|
||||
options.temperatureEquator = Number(target.value);
|
||||
byId("temperatureEquatorF").innerText = convertTemperature(options.temperatureEquator, "°F");
|
||||
}
|
||||
if (stored === "temperatureNorthPole") {
|
||||
options.temperatureNorthPole = Number(el.value);
|
||||
} else if (stored === "temperatureNorthPole") {
|
||||
options.temperatureNorthPole = Number(target.value);
|
||||
byId("temperatureNorthPoleF").innerText = convertTemperature(options.temperatureNorthPole, "°F");
|
||||
}
|
||||
if (stored === "temperatureSouthPole") {
|
||||
options.temperatureSouthPole = Number(el.value);
|
||||
} else if (stored === "temperatureSouthPole") {
|
||||
options.temperatureSouthPole = Number(target.value);
|
||||
byId("temperatureSouthPoleF").innerText = convertTemperature(options.temperatureSouthPole, "°F");
|
||||
}
|
||||
|
||||
if (byId("wcAutoChange").checked) updateWorld();
|
||||
}
|
||||
|
||||
function updateWorld() {
|
||||
updateGlobeTemperature();
|
||||
updateGlobePosition();
|
||||
calculateTemperatures();
|
||||
|
|
@ -130,6 +134,7 @@ function editWorld() {
|
|||
[mc.lonW, mc.latN],
|
||||
[mc.lonE, mc.latS]
|
||||
]);
|
||||
|
||||
globe.select("#globeArea").attr("d", round(path(area.outline()))); // map area
|
||||
}
|
||||
|
||||
|
|
@ -163,21 +168,22 @@ function editWorld() {
|
|||
});
|
||||
}
|
||||
|
||||
function changeWind() {
|
||||
function handleWindChange() {
|
||||
const arrow = d3.event.target.nextElementSibling;
|
||||
const tier = +arrow.dataset.tier;
|
||||
options.winds[tier] = (options.winds[tier] + 45) % 360;
|
||||
const tr = parseTransform(arrow.getAttribute("transform"));
|
||||
arrow.setAttribute("transform", `rotate(${options.winds[tier]} ${tr[1]} ${tr[2]})`);
|
||||
localStorage.setItem("winds", options.winds);
|
||||
|
||||
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map(c => ((90 - c) / 30) | 0);
|
||||
if (mapTiers.includes(tier)) updateWorld();
|
||||
if (byId("wcAutoChange").checked && mapTiers.includes(tier)) updateWorld();
|
||||
}
|
||||
|
||||
function restoreDefaultWinds() {
|
||||
const defaultWinds = [225, 45, 225, 315, 135, 315];
|
||||
const mapTiers = d3.range(mapCoordinates.latN, mapCoordinates.latS, -30).map(c => ((90 - c) / 30) | 0);
|
||||
const update = mapTiers.some(t => options.winds[t] != defaultWinds[t]);
|
||||
const update = byId("wcAutoChange").checked && mapTiers.some(t => options.winds[t] != defaultWinds[t]);
|
||||
options.winds = defaultWinds;
|
||||
updateWindDirections();
|
||||
if (update) updateWorld();
|
||||
|
|
@ -188,6 +194,6 @@ function editWorld() {
|
|||
byId("latitudeInput").value = byId("latitudeOutput").value = lat;
|
||||
lock("mapSize");
|
||||
lock("latitude");
|
||||
updateWorld();
|
||||
if (byId("wcAutoChange").checked) updateWorld();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
run_php_server.bat
Normal file
3
run_php_server.bat
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
start chrome.exe http://localhost:3000/
|
||||
@echo off
|
||||
php -S localhost:3000
|
||||
|
|
@ -72,8 +72,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(0.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@
|
|||
"mask": "",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.5,
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(0.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"#compass > use": {
|
||||
"transform": "translate(100 100) scale(0.3)"
|
||||
},
|
||||
"#relig": {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.5,
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.7,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(0.25)"
|
||||
},
|
||||
"#relig": {
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"transform": null
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
"opacity": 0.5,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
"mask": "url(#water)",
|
||||
"shape-rendering": "optimizespeed"
|
||||
},
|
||||
"#rose": {
|
||||
"#compass > use": {
|
||||
"transform": "translate(80 80) scale(.25)"
|
||||
},
|
||||
"#relig": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
// version and caching control
|
||||
const version = "1.98.00"; // generator version, update each time
|
||||
const version = "1.99.00"; // generator version, update each time
|
||||
|
||||
{
|
||||
document.title += " v" + version;
|
||||
|
|
@ -28,7 +28,11 @@ const version = "1.98.00"; // generator version, update each time
|
|||
|
||||
<ul>
|
||||
<strong>Latest changes:</strong>
|
||||
<<<<<<< HEAD
|
||||
<li>New routes generatation algorithm</li>
|
||||
=======
|
||||
<li>Configurable longitude</li>
|
||||
>>>>>>> 00abd5213b446922a60e2053eaca711a6d4067e2
|
||||
<li>Preview villages map</li>
|
||||
<li>Ability to render ocean heightmap</li>
|
||||
<li>Scale bar styling features</li>
|
||||
|
|
@ -41,6 +45,10 @@ const version = "1.98.00"; // generator version, update each time
|
|||
<li>North and South Poles temperature can be set independently</li>
|
||||
<li>More than 70 new heraldic charges</li>
|
||||
<li>Multi-color heraldic charges support</li>
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<li>New 3D scene options and improvements</li>
|
||||
>>>>>>> 00abd5213b446922a60e2053eaca711a6d4067e2
|
||||
</ul>
|
||||
|
||||
<p>Join our <a href="${discord}" target="_blank">Discord server</a> and <a href="${reddit}" target="_blank">Reddit community</a> to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue