mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-23 12:31:24 +01:00
Merge remote-tracking branch 'upstream/master' into dev-submap
This commit is contained in:
commit
1d1cd0bb71
15 changed files with 594 additions and 607 deletions
35
dropbox.html
35
dropbox.html
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="utf-8" />
|
||||
<script type="text/javascript" src="https://unpkg.com/dropbox@10.8.0/dist/Dropbox-sdk.min.js"></script>
|
||||
<title>FMG Dropbox Auth</title>
|
||||
</head>
|
||||
|
|
@ -13,33 +13,36 @@
|
|||
window.
|
||||
*/
|
||||
const REDIRECT_URI = window.location.origin + window.location.pathname;
|
||||
const dbxAuth = new Dropbox.DropboxAuth({ clientId: 'sp7tzwm27u2w5ns', });
|
||||
const dbxAuth = new Dropbox.DropboxAuth({clientId: "pdr9ae64ip0qno4"});
|
||||
|
||||
const spObj = new URLSearchParams(window.location.search);
|
||||
const searchParams = Object.fromEntries(spObj.entries())
|
||||
const searchParams = Object.fromEntries(spObj.entries());
|
||||
|
||||
if (searchParams.code) getToken()
|
||||
if (searchParams.code) getToken();
|
||||
else doAuth(); // start authentication
|
||||
|
||||
function doAuth() {
|
||||
dbxAuth.getAuthenticationUrl(REDIRECT_URI, undefined, 'code', 'offline', undefined, undefined, true)
|
||||
.then(authUrl => {
|
||||
dbxAuth
|
||||
.getAuthenticationUrl(REDIRECT_URI, undefined, "code", "offline", undefined, undefined, true)
|
||||
.then(authUrl => {
|
||||
window.sessionStorage.clear();
|
||||
window.sessionStorage.setItem("codeVerifier", dbxAuth.codeVerifier);
|
||||
window.location.href = authUrl;
|
||||
})
|
||||
.catch((error) => console.error(error));
|
||||
};
|
||||
})
|
||||
.catch(error => console.error(error));
|
||||
}
|
||||
|
||||
function getToken() {
|
||||
dbxAuth.setCodeVerifier(window.sessionStorage.getItem('codeVerifier'));
|
||||
dbxAuth.getAccessTokenFromCode(REDIRECT_URI, searchParams.code)
|
||||
.then((resp) => {
|
||||
dbxAuth.setCodeVerifier(window.sessionStorage.getItem("codeVerifier"));
|
||||
dbxAuth
|
||||
.getAccessTokenFromCode(REDIRECT_URI, searchParams.code)
|
||||
.then(resp => {
|
||||
const token = resp.result.access_token;
|
||||
window.opener.Cloud.providers.dropbox.setDropBoxToken(token)
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
});
|
||||
window.opener.Cloud.providers.dropbox.setDropBoxToken(token);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
175
fonts.css
175
fonts.css
|
|
@ -1,175 +0,0 @@
|
|||
@font-face {
|
||||
font-family: 'Amatic SC';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Amatic SC Bold'), local('AmaticSC-Bold'), url(https://fonts.gstatic.com/s/amaticsc/v11/TUZ3zwprpvBS1izr_vOMscGKfrUC.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Architects Daughter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Architects Daughter Regular'), local('ArchitectsDaughter-Regular'), url(https://fonts.gstatic.com/s/architectsdaughter/v8/RXTgOOQ9AAtaVOHxx0IUBM3t7GjCYufj5TXV5VnA2p8.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Bitter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Bitter Regular'), local('Bitter-Regular'), url(https://fonts.gstatic.com/s/bitter/v12/zfs6I-5mjWQ3nxqccMoL2A.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Caesar Dressing';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Caesar Dressing'), local('CaesarDressing-Regular'), url(https://fonts.gstatic.com/s/caesardressing/v6/yYLx0hLa3vawqtwdswbotmK4vrRHdrz7.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Cinzel';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Cinzel Regular'), local('Cinzel-Regular'), url(https://fonts.gstatic.com/s/cinzel/v7/zOdksD_UUTk1LJF9z4tURA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Comfortaa';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Comfortaa Bold'), local('Comfortaa-Bold'), url(https://fonts.gstatic.com/s/comfortaa/v12/fND5XPYKrF2tQDwwfWZJI-gdm0LZdjqr5-oayXSOefg.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Dancing Script';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Dancing Script Bold'), local('DancingScript-Bold'), url(https://fonts.gstatic.com/s/dancingscript/v9/KGBfwabt0ZRLA5W1ywjowUHdOuSHeh0r6jGTOGdAKHA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fredericka the Great';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Fredericka the Great'), local('FrederickatheGreat'), url(https://fonts.gstatic.com/s/frederickathegreat/v6/9Bt33CxNwt7aOctW2xjbCstzwVKsIBVV--Sjxbc.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Gloria Hallelujah';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Gloria Hallelujah'), local('GloriaHallelujah'), url(https://fonts.gstatic.com/s/gloriahallelujah/v9/CA1k7SlXcY5kvI81M_R28cNDay8z-hHR7F16xrcXsJw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Great Vibes';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Great Vibes'), local('GreatVibes-Regular'), url(https://fonts.gstatic.com/s/greatvibes/v5/6q1c0ofG6NKsEhAc2eh-3Y4P5ICox8Kq3LLUNMylGO4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'IM Fell English';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('IM FELL English Roman'), local('IM_FELL_English_Roman'), url(https://fonts.gstatic.com/s/imfellenglish/v7/xwIisCqGFi8pff-oa9uSVAkYLEKE0CJQa8tfZYc_plY.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Kaushan Script';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Kaushan Script'), local('KaushanScript-Regular'), url(https://fonts.gstatic.com/s/kaushanscript/v6/qx1LSqts-NtiKcLw4N03IEd0sm1ffa_JvZxsF_BEwQk.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'MedievalSharp';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('MedievalSharp'), url(https://fonts.gstatic.com/s/medievalsharp/v9/EvOJzAlL3oU5AQl2mP5KdgptMqhwMg.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Metamorphous';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Metamorphous'), url(https://fonts.gstatic.com/s/metamorphous/v7/Wnz8HA03aAXcC39ZEX5y133EOyqs.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Montez';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Montez Regular'), local('Montez-Regular'), url(https://fonts.gstatic.com/s/montez/v8/aq8el3-0osHIcFK6bXAPkw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nova Script';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Nova Script Regular'), local('NovaScript-Regular'), url(https://fonts.gstatic.com/s/novascript/v10/7Au7p_IpkSWSTWaFWkumvlQKGFw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Orbitron';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Orbitron Regular'), local('Orbitron-Regular'), url(https://fonts.gstatic.com/s/orbitron/v9/HmnHiRzvcnQr8CjBje6GQvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Satisfy';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Satisfy Regular'), local('Satisfy-Regular'), url(https://fonts.gstatic.com/s/satisfy/v8/2OzALGYfHwQjkPYWELy-cw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Shadows Into Light';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Shadows Into Light'), local('ShadowsIntoLight'), url(https://fonts.gstatic.com/s/shadowsintolight/v7/clhLqOv7MXn459PTh0gXYFK2TSYBz0eNcHnp4YqE4Ts.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Uncial Antiqua';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Uncial Antiqua'), local('UncialAntiqua-Regular'), url(https://fonts.gstatic.com/s/uncialantiqua/v5/N0bM2S5WOex4OUbESzoESK-i-MfWQZQ.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Underdog';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Underdog'), local('Underdog-Regular'), url(https://fonts.gstatic.com/s/underdog/v6/CHygV-jCElj7diMroWSlWV8.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Yellowtail';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Yellowtail Regular'), local('Yellowtail-Regular'), url(https://fonts.gstatic.com/s/yellowtail/v8/GcIHC9QEwVkrA19LJU1qlPk_vArhqVIZ0nv9q090hN8.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
|
||||
}
|
||||
147
index.css
147
index.css
File diff suppressed because one or more lines are too long
86
index.html
86
index.html
|
|
@ -242,7 +242,7 @@
|
|||
|
||||
<div id="collapsible">
|
||||
<button id="optionsTrigger" data-t="tipOptionsTrigger" data-tip="Click to show options pane. Shortcut: Tab" class="options glow" onclick="showOptions(event)" style="padding:.6em .45em">►</button>
|
||||
<button id="regenerate" data-t="tipRegenerate" data-tip="Click to generate a new map. Shortcut: F2" onclick="regeneratePrompt()" class="options" style="display:none; padding:.6em 1em"><t data-t="newMap">New Map!</t></button>
|
||||
<button id="regenerate" data-t="tipRegenerate" data-tip="Click to generate a new map. Shortcut: F2" onclick="regeneratePrompt()" class="options" style="display: none"><t data-t="newMap">New Map!</t></button>
|
||||
</div>
|
||||
|
||||
<div id="options" style="display:none">
|
||||
|
|
@ -273,8 +273,8 @@
|
|||
<option value="landmass">Pure landmass</option>
|
||||
<option hidden value="custom">Custom (not saved)</option>
|
||||
</select>
|
||||
<button id="savePresetButton" data-tip="Click to save displayed layers as a new preset" class="icon-plus presetButton" style="display:none" onclick="savePreset()"></button>
|
||||
<button id="removePresetButton" data-tip="Click to remove current custom preset" class="icon-minus presetButton" style="display:none" onclick="removePreset()"></button>
|
||||
<button id="savePresetButton" data-tip="Click to save displayed layers as a new preset" class="icon-plus sideButton" style="display:none" onclick="savePreset()"></button>
|
||||
<button id="removePresetButton" data-tip="Click to remove current custom preset" class="icon-minus sideButton" style="display:none" 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>
|
||||
<ul data-tip="Click to toggle a layer, drag to raise or lower a layer. Ctrl + click to edit layer style" id="mapLayers">
|
||||
|
|
@ -326,8 +326,8 @@
|
|||
<option value="styleWatercolor" data-system=1>Watercolor</option>
|
||||
<option value="styleMonochrome" data-system=1>Monochrome</option>
|
||||
</select>
|
||||
<button id="addStyleButton" data-tip="Click to save current style as a new preset" class="icon-plus styleButton" style="display: inline-block" onclick="addStylePreset()"></button>
|
||||
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus styleButton" style="display: none" onclick="removeStylePreset()"></button>
|
||||
<button id="addStyleButton" data-tip="Click to save current style as a new preset" class="icon-plus sideButton" style="display: inline-block" onclick="addStylePreset()"></button>
|
||||
<button id="removeStyleButton" data-tip="Click to remove current custom style preset" class="icon-minus sideButton" style="display: none" onclick="removeStylePreset()"></button>
|
||||
|
||||
<p data-tip="Select an element to edit its style" style="display: inline-block;">Select element:</p>
|
||||
<select data-tip="Select an element to edit its style (list is ordered alphabetically)" id="styleElementSelect" style="width:42%">
|
||||
|
|
@ -458,7 +458,7 @@
|
|||
<option value="https://i2.wp.com/azgaar.files.wordpress.com/2019/07/iran-small.jpg">Iran small</option>
|
||||
<option value="https://i2.wp.com/azgaar.files.wordpress.com/2019/07/spain-small.jpg">Spain small</option>
|
||||
</select>
|
||||
<button data-tip="Click and provide a URL to image to be set as a texture" class="icon-plus styleButton" onclick="textureProvideURL()"></button>
|
||||
<button data-tip="Click and provide a URL to image to be set as a texture" class="icon-plus sideButton" onclick="textureProvideURL()"></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
|
@ -666,8 +666,7 @@
|
|||
<td>Font</td>
|
||||
<td>
|
||||
<select id="styleSelectFont"></select>
|
||||
<input id="styleInputFont" data-tip="Provide a link to @font-face declaration or type Google font name" type="text" placeholder="link to @font-face">
|
||||
<button id="styleFontAdd" data-tip="Add custom font from the web" class="icon-plus styleButton"></button>
|
||||
<button id="styleFontAdd" data-tip="Add a font" class="icon-plus sideButton"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
@ -1311,14 +1310,15 @@
|
|||
</tr> -->
|
||||
</table>
|
||||
|
||||
<button id="configureWorld" data-tip="Click to open world configurator to setup map position on Globe and World climate" onclick="editWorld()">Configure World</button>
|
||||
<button id="optionsReset" data-tip="Click to restore default options (page will be reloaded)" onclick="restoreDefaultOptions()">Reset to defaults</button>
|
||||
|
||||
<div>
|
||||
<button id="configureWorld" data-tip="Click to open world configurator to setup map position on Globe and World climate" onclick="editWorld()">Configure World</button>
|
||||
<button id="optionsReset" data-tip="Click to restore default options (page will be reloaded)" onclick="restoreDefaultOptions()">Reset to defaults</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="toolsContent" class="tabcontent">
|
||||
<p>Click to configure:</p>
|
||||
<div>
|
||||
<p>Click to configure:</p>
|
||||
<button id="editHeightmapButton" data-tip="Click to open Heightmap customization menu. Shortcut: Shift + H">Heightmap</button>
|
||||
<button id="editBiomesButton" data-tip="Click to open Biomes Editor. Shortcut: Shift + B">Biomes</button>
|
||||
<button id="editStatesButton" data-tip="Click to open States Editor. Shortcut: Shift + S">States</button>
|
||||
|
|
@ -1333,18 +1333,18 @@
|
|||
<button id="editNotesButton" data-tip="Click to open Notes Editor. Shortcut: Shift + O">Notes</button>
|
||||
</div>
|
||||
|
||||
<p>Click to overview:</p>
|
||||
<div>
|
||||
<p>Click to overview:</p>
|
||||
<button id="overviewBurgsButton" data-tip="Click to open Burgs Overview. Shortcut: Shift + T">Burgs</button>
|
||||
<button id="overviewRiversButton" data-tip="Click to open Rivers Overview. Shortcut: Shift + V">Rivers</button>
|
||||
<button id="overviewMilitaryButton" data-tip="Click to open Military Forces Overview. Shortcut: Shift + M">Military</button>
|
||||
<button id="overviewCellsButton" data-tip="Click to open Cell details view. Shortcut: Shift + E">Cells</button>
|
||||
</div>
|
||||
|
||||
<p>Click to regenerate:</p>
|
||||
<div id="regenerateFeature">
|
||||
<p>Click to regenerate:</p>
|
||||
<button id="regenerateStateLabels" data-tip="Click to update state labels placement based on current borders">State labels</button>
|
||||
<button id="regenerateReliefIcons" data-tip="Click to regenerate all relief icons based on current cell biome and elevation">Relief icons</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>
|
||||
<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>
|
||||
<button id="regeneratePopulation" data-tip="Click to recalculate rural and urban population">Population</button>
|
||||
|
|
@ -1360,8 +1360,8 @@
|
|||
<button id="regenerateZones" data-tip="Click to regenerate zones. Hold Ctrl and click to set zones number multiplier">Zones</button>
|
||||
</div>
|
||||
|
||||
<p>Click to add:</p>
|
||||
<div id="addFeature">
|
||||
<p>Click to add:</p>
|
||||
<button id="addBurgTool" data-tip="Click on map to place a burg. Hold <kbd>Shift</kbd> to add multiple. Shortcut: Shift + 1">Burg</button>
|
||||
<button id="addLabel" data-tip="Click on map to place label. Hold Shift to add multiple. Shortcut: Shift + 2">Label</button>
|
||||
<button id="addRiver" data-tip="Click on map to place a river. Hold Shift to add multiple. Shortcut: Shift + 3">River</button>
|
||||
|
|
@ -1385,8 +1385,8 @@
|
|||
<button data-tip="Preview heightmap in 3D scene" id="heightmap3DView">3D scene</button>
|
||||
</div>
|
||||
|
||||
<p>Options:</p>
|
||||
<div id="customizeOptions">
|
||||
<p>Options:</p>
|
||||
<div data-tip="Heightmap edit mode">Edit mode: <span id="heightmapEditMode"></span></div>
|
||||
<div data-tip="Render cells below the sea level (with height less than 20)">
|
||||
<input id="renderOcean" class="checkbox" type="checkbox">
|
||||
|
|
@ -1409,14 +1409,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<p>Statistics:</p>
|
||||
<div>
|
||||
<p>Statistics:</p>
|
||||
<span>Land cells: </span><span id="landmassCounter">0</span>
|
||||
<span style="margin-left:.9em">Mean height: </span><span id="landmassAverage">0</span>
|
||||
</div>
|
||||
|
||||
<p>Cell info:</p>
|
||||
<div>
|
||||
<p>Cell info:</p>
|
||||
<span>Coord: </span><span id="heightmapInfoX"></span>/<span id="heightmapInfoY"></span><br>
|
||||
<span>Cell: </span><span id="heightmapInfoCell"></span><br>
|
||||
<span>Height: </span><span id="heightmapInfoHeight"></span>
|
||||
|
|
@ -3351,6 +3351,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div id="addFontDialog" style="display: none" class="dialog">
|
||||
<span>There are 3 ways to add a custom font:</span>
|
||||
<p><strong>Google font</strong>. Open <a href="https://fonts.google.com/" target="_blank">Google Fonts</a>, find a font you like and enter its name to the field below.</p>
|
||||
<p><strong>Local font</strong>. If you have a font <a href="https://faqs.skillcrush.com/article/275-downloading-installing-a-font-on-your-computer" target="_blank">installed on your computer</a>, just provide the font name. Make sure the browser is reloaded after the installation. The font won't work on machines not having it installed. Good source of fonts are <a href="https://fontesk.com" target="_blank">Fontdesk</a> and <a href="https://www.dafont.com" target="_blank">DaFont</a>.</p>
|
||||
<p><strong>Font URL</strong>. Provide font name and link to the font file hosted online. The best free font hostings are <a href="https://fonts.google.com/" target="_blank">Google Fonts</a> and <a target="_blank" href="https://www.cdnfonts.com">CDN Fonts</a>. To get font file open the link to css provided by these services and manually copy the link to <code>woff2</code>.</p>
|
||||
<div style="margin-top: .3em" data-tip="Select font adding method">
|
||||
<select id="addFontMethod">
|
||||
<option value="googleFont" selected>Google font</option>
|
||||
<option value="localFont">Local font</option>
|
||||
<option value="fontURL" selected>Font URL</option>
|
||||
</select>
|
||||
<input id="addFontNameInput" placeholder="font family" style="width:15em">
|
||||
<input id="addFontURLInput" placeholder="font file URL" style="width:22.6em; margin-top:.1em">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="cellInfo" style="display: none" class="dialog stable">
|
||||
<p><b>Cell:</b> <span id="infoCell"></span> <b>X:</b> <span id="infoX"></span> <b>Y:</b> <span id="infoY"></span></p>
|
||||
<p><b>Latitude:</b> <span id="infoLat"></span></p>
|
||||
|
|
@ -3447,7 +3463,7 @@
|
|||
<div id="options3dBottom" style="margin-top: .2em">
|
||||
<button id="options3dUpdate" data-tip="Update the scene" class="icon-cw"></button>
|
||||
<button data-tip="Configure world and map size and climate settings" onclick="editWorld()" class="icon-globe"></button>
|
||||
<button id="options3dSave" data-tip="Save screenshot of the 3d scene" class="icon-button-screenshot"></button>
|
||||
<button id="options3dSave" data-tip="Save screenshot of the 3d scene" class="icon-button-screenshot"></button>
|
||||
<button id="options3dOBJSave" data-tip="Save OBJ file of the 3d scene" class="icon-download"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3480,11 +3496,9 @@
|
|||
<button onclick="saveGeoJSON_Rivers()" data-tip="Download rivers data in GeoJSON format">rivers</button>
|
||||
<button onclick="saveGeoJSON_Markers()" data-tip="Download markers data in GeoJSON format">markers</button>
|
||||
</div>
|
||||
<p style="font-style: italic">GeoJSON format is used in GIS tools such as QGIS. Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance</p>
|
||||
|
||||
<p style="font-style: italic">Generator uses pop-up window to download files. Please ensure your browser does not block popups.</p>
|
||||
|
||||
<p style="font-style: italic">It's also possible to export map to Foundry VTT, see <a href="https://github.com/Ethck/azgaar-foundry" target="_blank">the module.</a></p>
|
||||
<p>GeoJSON format is used in GIS tools such as QGIS. Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance.</p>
|
||||
<p>Generator uses pop-up window to download files. Please ensure your browser does not block popups.</p>
|
||||
<p>It's also possible to export map to <i>Foundry VTT</i>, see <a href="https://github.com/Ethck/azgaar-foundry" target="_blank">the module.</a></p>
|
||||
</div>
|
||||
|
||||
<div id="saveMapData" style="display: none" class="dialog">
|
||||
|
|
@ -3492,24 +3506,26 @@
|
|||
<strong>Save map to</strong>
|
||||
<button onclick="dowloadMap()" data-tip="Download .map file to your local disk. Shortcut: Ctrl + S">machine</button>
|
||||
<button onclick="saveToDropbox()" data-tip="Save .map file to your Dropbox">dropbox</button>
|
||||
<button onclick="quickSave()" data-tip="Save the project to browser storage (quick save). It can be unreliable. Shortcut: F6">browser</button>
|
||||
<button onclick="quickSave()" data-tip="Save the project to browser storage. It can be unreliable. Shortcut: F6">browser</button>
|
||||
</div>
|
||||
<p style="font-style: italic">Maps are saved in <i>.map</i> format, that can be loaded back via 'Load' in menu. Please keep noted that we do not keep any data on our side. There is no way to restore the progress if .map file is lost. Please keep old .map files on your machine or cloud storage as backups.</p>
|
||||
<p>Maps are saved in <i>.map</i> format, that can be loaded back via the <i>Load</i> in menu. There is no way to restore the progress if file is lost. Please keep old <i>.map</i> files on your machine or cloud storage as backups.</p>
|
||||
</div>
|
||||
|
||||
<div id="loadMapData" style="display: none" class="dialog">
|
||||
<div style="margin-bottom: .3em">Load map from</div>
|
||||
<div>
|
||||
<strong>Load map from</strong>
|
||||
<button onclick="mapToLoad.click()" data-tip="Load .map file from local disk">local disk</button>
|
||||
<button onclick="loadURL()" data-tip="Load .map file from URL (server should allow CORS)">URL</button>
|
||||
<button onclick="quickLoad()" data-tip="Load map from browser storage (if saved before)">storage</button>
|
||||
</div>
|
||||
<div id="loadFromDropbox">
|
||||
<p>From your Dropbox account:</p>
|
||||
<select style="margin-bottom:.3em">
|
||||
</select>
|
||||
<button onclick="loadFromDropbox()" data-tip="Load .map file from your Dropbox">Open</button>
|
||||
<button onclick="createSharableDropboxLink()" data-tip="Select .map file on dropbox and share a sharable link">Create link</button>
|
||||
<p style="margin-bottom: .3em">From your Dropbox account</p>
|
||||
<select id="loadFromDropboxSelect" style="width: 22em"></select>
|
||||
|
||||
<div id="loadFromDropboxButtons" style="margin-bottom: .3em">
|
||||
<button onclick="loadFromDropbox()" data-tip="Load .map file from your Dropbox">Open</button>
|
||||
<button onclick="createSharableDropboxLink()" data-tip="Select file and create a link to share with your friends">Create link</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: .3em">
|
||||
<div id="sharableLinkContainer" style="display: none">
|
||||
|
|
@ -3521,7 +3537,7 @@
|
|||
</div>
|
||||
|
||||
<div id="saveTilesScreen" style="display: none" class="dialog">
|
||||
<p style="font-style: italic">Map will be split into tiles and downloaded as a single zip file. Avoid saving to big images</p>
|
||||
<p>Map will be split into tiles and downloaded as a single zip file. Avoid saving to big images</p>
|
||||
<div data-tip="Number of columns" style="margin-bottom: .3em">
|
||||
<div class="label">Columns:</div>
|
||||
<input id="tileColsInput" data-stored="tileCols" type="range" min=2 max=20 value=8 style="width: 11em">
|
||||
|
|
|
|||
2
libs/dropins.min.js
vendored
Normal file
2
libs/dropins.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
main.js
6
main.js
|
|
@ -2,7 +2,7 @@
|
|||
// https://github.com/Azgaar/Fantasy-Map-Generator
|
||||
|
||||
"use strict";
|
||||
const version = "1.66"; // generator version1
|
||||
const version = "1.661"; // generator version
|
||||
document.title += " v" + version;
|
||||
|
||||
// Switches to disable/enable logging features
|
||||
|
|
@ -122,7 +122,6 @@ let customization = 0; // 0 - no; 1 = heightmap draw; 2 - states draw; 3 - add s
|
|||
|
||||
let biomesData = applyDefaultBiomesSystem();
|
||||
let nameBases = Names.getNameBases(); // cultures-related data
|
||||
const fonts = ["Almendra+SC", "Georgia", "Arial", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New", "Verdana", "Arial", "Impact"]; // default fonts
|
||||
|
||||
let color = d3.scaleSequential(d3.interpolateSpectral); // default color scheme
|
||||
const lineGen = d3.line().curve(d3.curveBasis); // d3 line generator with default curve interpolation
|
||||
|
|
@ -221,7 +220,7 @@ void (function checkLoadParameters() {
|
|||
})();
|
||||
|
||||
function generateMapOnLoad() {
|
||||
applyStyleOnLoad(); // apply default of previously selected style
|
||||
applyStyleOnLoad(); // apply default or previously selected style
|
||||
generate(); // generate map
|
||||
focusOn(); // based on searchParams focus on point, cell or burg from MFCG
|
||||
applyPreset(); // apply saved layers preset
|
||||
|
|
@ -379,6 +378,7 @@ function showWelcomeMessage() {
|
|||
alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version <b>${version}</b>.
|
||||
This version is compatible with ${changelog}, loaded <i>.map</i> files will be auto-updated.
|
||||
<ul>Main changes:
|
||||
<li>Add custom fonts dialog</li>
|
||||
<li>Save and load <i>.map</i> files to Dropbox</li>
|
||||
<li>Ability to add control points on river edit</li>
|
||||
<li>New heightmap template: Taklamakan</li>
|
||||
|
|
|
|||
134
modules/cloud.js
134
modules/cloud.js
|
|
@ -16,126 +16,124 @@ restore(): restore access tokens from storage if possible
|
|||
*/
|
||||
|
||||
window.Cloud = (function () {
|
||||
|
||||
// helpers to use in providers for token handling
|
||||
const lSKey = x => `auth-${x}`
|
||||
const setToken = (prov, key) => localStorage.setItem(lSKey(prov), key)
|
||||
const getToken = prov => localStorage.getItem(lSKey(prov))
|
||||
const lSKey = x => `auth-${x}`;
|
||||
const setToken = (prov, key) => localStorage.setItem(lSKey(prov), key);
|
||||
const getToken = prov => localStorage.getItem(lSKey(prov));
|
||||
|
||||
/**********************************************************/
|
||||
/* Dropbox provider */
|
||||
/**********************************************************/
|
||||
|
||||
const DBP = {
|
||||
name: 'dropbox',
|
||||
clientId: 'sp7tzwm27u2w5ns',
|
||||
name: "dropbox",
|
||||
clientId: "pdr9ae64ip0qno4",
|
||||
authWindow: undefined,
|
||||
token: null, // Access token
|
||||
api: null,
|
||||
|
||||
restore() {
|
||||
this.token = getToken(this.name)
|
||||
if (this.token) this.connect(this.token)
|
||||
this.token = getToken(this.name);
|
||||
if (this.token) this.connect(this.token);
|
||||
},
|
||||
|
||||
async call(name, param) {
|
||||
try {
|
||||
return await this.api[name](param)
|
||||
return await this.api[name](param);
|
||||
} catch (e) {
|
||||
if (e.name !== "DropboxResponseError") throw(e)
|
||||
if (e.name !== "DropboxResponseError") throw e;
|
||||
// retry with auth
|
||||
await this.auth()
|
||||
return await this.api[name](param)
|
||||
await this.auth();
|
||||
return await this.api[name](param);
|
||||
}
|
||||
},
|
||||
|
||||
connect(token) {
|
||||
const clientId = this.clientId
|
||||
const auth = new Dropbox.DropboxAuth({ clientId })
|
||||
auth.setAccessToken(token)
|
||||
this.api = new Dropbox.Dropbox({ auth })
|
||||
const clientId = this.clientId;
|
||||
const auth = new Dropbox.DropboxAuth({clientId});
|
||||
auth.setAccessToken(token);
|
||||
this.api = new Dropbox.Dropbox({auth});
|
||||
},
|
||||
|
||||
async save(fileName, contents) {
|
||||
if (!this.api) await this.auth()
|
||||
const resp = this.call('filesUpload', { path: '/' + fileName, contents })
|
||||
console.log("Dropbox response:", resp)
|
||||
return true
|
||||
if (!this.api) await this.auth();
|
||||
const resp = this.call("filesUpload", {path: "/" + fileName, contents});
|
||||
DEBUG && console.log("Dropbox response:", resp);
|
||||
return true;
|
||||
},
|
||||
|
||||
async load(path) {
|
||||
if (!this.api) await this.auth()
|
||||
const resp = await this.call('filesDownload', { path })
|
||||
const blob = resp.result.fileBlob
|
||||
if (!blob) throw(new Error('Invalid response from dropbox.'))
|
||||
return blob
|
||||
if (!this.api) await this.auth();
|
||||
const resp = await this.call("filesDownload", {path});
|
||||
const blob = resp.result.fileBlob;
|
||||
if (!blob) throw new Error("Invalid response from dropbox.");
|
||||
return blob;
|
||||
},
|
||||
|
||||
async list() {
|
||||
if (!this.api) return null
|
||||
const resp = await this.call('filesListFolder', { path: '' })
|
||||
return resp.result.entries.map(e => ({ name: e.name, path: e.path_lower }))
|
||||
if (!this.api) return null;
|
||||
const resp = await this.call("filesListFolder", {path: ""});
|
||||
return resp.result.entries.map(e => ({name: e.name, path: e.path_lower}));
|
||||
},
|
||||
|
||||
auth() {
|
||||
const url = window.location.origin + window.location.pathname + 'dropbox.html'
|
||||
this.authWindow = window.open(url, 'auth', 'width=640,height=480')
|
||||
// child window expected to call
|
||||
// window.opener.Cloud.providers.dropbox.setDropBoxToken (see below)
|
||||
return new Promise((resolve, reject) => {
|
||||
const watchDog = () => {
|
||||
this.authWindow.close()
|
||||
reject(new Error("Timeout. No auth for dropbox."))
|
||||
}
|
||||
setTimeout(watchDog, 120*1000)
|
||||
window.addEventListener('dropboxauth', e => {
|
||||
clearTimeout(watchDog)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
const url = window.location.origin + window.location.pathname + "dropbox.html";
|
||||
this.authWindow = window.open(url, "auth", "width=640,height=480");
|
||||
// child window expected to call
|
||||
// window.opener.Cloud.providers.dropbox.setDropBoxToken (see below)
|
||||
return new Promise((resolve, reject) => {
|
||||
const watchDog = () => {
|
||||
this.authWindow.close();
|
||||
reject(new Error("Timeout. No auth for dropbox."));
|
||||
};
|
||||
setTimeout(watchDog, 120 * 1000);
|
||||
window.addEventListener("dropboxauth", e => {
|
||||
clearTimeout(watchDog);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Callback function for auth window.
|
||||
setDropBoxToken(token) {
|
||||
console.log('Access token got:', token)
|
||||
setToken(this.name, token)
|
||||
this.connect(token)
|
||||
this.authWindow.close()
|
||||
window.dispatchEvent(new Event('dropboxauth'))
|
||||
DEBUG && console.log("Access token:", token);
|
||||
setToken(this.name, token);
|
||||
this.connect(token);
|
||||
this.authWindow.close();
|
||||
window.dispatchEvent(new Event("dropboxauth"));
|
||||
},
|
||||
|
||||
async getLink(path) {
|
||||
if (!this.api) await this.auth()
|
||||
let resp
|
||||
if (!this.api) await this.auth();
|
||||
let resp;
|
||||
|
||||
// already exists?
|
||||
resp = await this.call('sharingListSharedLinks', { path })
|
||||
if (resp.result.links.length)
|
||||
return resp.result.links[0].url
|
||||
resp = await this.call("sharingListSharedLinks", {path});
|
||||
if (resp.result.links.length) return resp.result.links[0].url;
|
||||
|
||||
// create new
|
||||
resp = await this.call('sharingCreateSharedLinkWithSettings', {
|
||||
resp = await this.call("sharingCreateSharedLinkWithSettings", {
|
||||
path,
|
||||
settings: {
|
||||
require_password: false,
|
||||
audience: 'public',
|
||||
access: 'viewer',
|
||||
requested_visibility: 'public',
|
||||
allow_download: true,
|
||||
audience: "public",
|
||||
access: "viewer",
|
||||
requested_visibility: "public",
|
||||
allow_download: true
|
||||
}
|
||||
})
|
||||
console.log("dropbox link object:", resp.result)
|
||||
return resp.result.url
|
||||
},
|
||||
}
|
||||
});
|
||||
DEBUG && console.log("Dropbox link object:", resp.result);
|
||||
return resp.result.url;
|
||||
}
|
||||
};
|
||||
|
||||
// register providers here:
|
||||
const providers = {
|
||||
dropbox: DBP,
|
||||
}
|
||||
dropbox: DBP
|
||||
};
|
||||
|
||||
// restore all providers at startup
|
||||
for (const p of Object.values(providers)) p.restore()
|
||||
for (const p of Object.values(providers)) p.restore();
|
||||
|
||||
return { providers }
|
||||
})()
|
||||
return {providers};
|
||||
})();
|
||||
|
|
|
|||
388
modules/fonts.js
388
modules/fonts.js
|
|
@ -1,141 +1,271 @@
|
|||
// helper finctions to work with fonts
|
||||
"use strict";
|
||||
|
||||
async function addFonts(url) {
|
||||
$("head").append('<link rel="stylesheet" type="text/css" href="' + url + '">');
|
||||
const fonts = [
|
||||
{family: "Arial"},
|
||||
{family: "Times New Roman"},
|
||||
{family: "Georgia"},
|
||||
{family: "Garamond"},
|
||||
{family: "Lucida Sans Unicode"},
|
||||
{family: "Courier New"},
|
||||
{family: "Verdana"},
|
||||
{family: "Impact"},
|
||||
{family: "Comic Sans MS"},
|
||||
{family: "Papyrus"},
|
||||
{
|
||||
family: "Almendra SC",
|
||||
src: "url(https://fonts.gstatic.com/s/almendrasc/v13/Iure6Yx284eebowr7hbyTaZOrLQ.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Amatic SC",
|
||||
src: "url(https://fonts.gstatic.com/s/amaticsc/v11/TUZ3zwprpvBS1izr_vOMscGKfrUC.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Architects Daughter",
|
||||
src: "url(https://fonts.gstatic.com/s/architectsdaughter/v8/RXTgOOQ9AAtaVOHxx0IUBM3t7GjCYufj5TXV5VnA2p8.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Bitter",
|
||||
src: "url(https://fonts.gstatic.com/s/bitter/v12/zfs6I-5mjWQ3nxqccMoL2A.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Caesar Dressing",
|
||||
src: "url(https://fonts.gstatic.com/s/caesardressing/v6/yYLx0hLa3vawqtwdswbotmK4vrRHdrz7.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Cinzel",
|
||||
src: "url(https://fonts.gstatic.com/s/cinzel/v7/zOdksD_UUTk1LJF9z4tURA.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Dancing Script",
|
||||
src: "url(https://fonts.gstatic.com/s/dancingscript/v9/KGBfwabt0ZRLA5W1ywjowUHdOuSHeh0r6jGTOGdAKHA.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Fredericka the Great",
|
||||
src: "url(https://fonts.gstatic.com/s/frederickathegreat/v6/9Bt33CxNwt7aOctW2xjbCstzwVKsIBVV--Sjxbc.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Gloria Hallelujah",
|
||||
src: "url(https://fonts.gstatic.com/s/gloriahallelujah/v9/CA1k7SlXcY5kvI81M_R28cNDay8z-hHR7F16xrcXsJw.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Great Vibes",
|
||||
src: "url(https://fonts.gstatic.com/s/greatvibes/v5/6q1c0ofG6NKsEhAc2eh-3Y4P5ICox8Kq3LLUNMylGO4.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "IM Fell English",
|
||||
src: "url(https://fonts.gstatic.com/s/imfellenglish/v7/xwIisCqGFi8pff-oa9uSVAkYLEKE0CJQa8tfZYc_plY.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Kaushan Script",
|
||||
src: "url(https://fonts.gstatic.com/s/kaushanscript/v6/qx1LSqts-NtiKcLw4N03IEd0sm1ffa_JvZxsF_BEwQk.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "MedievalSharp",
|
||||
src: "url(https://fonts.gstatic.com/s/medievalsharp/v9/EvOJzAlL3oU5AQl2mP5KdgptMqhwMg.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Metamorphous",
|
||||
src: "url(https://fonts.gstatic.com/s/metamorphous/v7/Wnz8HA03aAXcC39ZEX5y133EOyqs.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Montez",
|
||||
src: "url(https://fonts.gstatic.com/s/montez/v8/aq8el3-0osHIcFK6bXAPkw.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Nova Script",
|
||||
src: "url(https://fonts.gstatic.com/s/novascript/v10/7Au7p_IpkSWSTWaFWkumvlQKGFw.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Orbitron",
|
||||
src: "url(https://fonts.gstatic.com/s/orbitron/v9/HmnHiRzvcnQr8CjBje6GQvesZW2xOQ-xsNqO47m55DA.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Satisfy",
|
||||
src: "url(https://fonts.gstatic.com/s/satisfy/v8/2OzALGYfHwQjkPYWELy-cw.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Shadows Into Light",
|
||||
src: "url(https://fonts.gstatic.com/s/shadowsintolight/v7/clhLqOv7MXn459PTh0gXYFK2TSYBz0eNcHnp4YqE4Ts.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
},
|
||||
{
|
||||
family: "Uncial Antiqua",
|
||||
src: "url(https://fonts.gstatic.com/s/uncialantiqua/v5/N0bM2S5WOex4OUbESzoESK-i-MfWQZQ.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Underdog",
|
||||
src: "url(https://fonts.gstatic.com/s/underdog/v6/CHygV-jCElj7diMroWSlWV8.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
|
||||
},
|
||||
{
|
||||
family: "Yellowtail",
|
||||
src: "url(https://fonts.gstatic.com/s/yellowtail/v8/GcIHC9QEwVkrA19LJU1qlPk_vArhqVIZ0nv9q090hN8.woff2)",
|
||||
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215"
|
||||
}
|
||||
];
|
||||
|
||||
declareDefaultFonts(); // execute once on load
|
||||
|
||||
function declareFont(font) {
|
||||
const {family, src, ...rest} = font;
|
||||
if (!src) return;
|
||||
|
||||
const fontFace = new FontFace(family, src, {...rest, display: "block"});
|
||||
document.fonts.add(fontFace);
|
||||
addFontOption(family);
|
||||
}
|
||||
|
||||
function declareDefaultFonts() {
|
||||
fonts.forEach(font => {
|
||||
if (font.src) declareFont(font);
|
||||
else addFontOption(font.family);
|
||||
});
|
||||
}
|
||||
|
||||
function getUsedFonts(svg) {
|
||||
const usedFontFamilies = new Set();
|
||||
|
||||
const labelGroups = svg.querySelectorAll("#labels g");
|
||||
for (const labelGroup of labelGroups) {
|
||||
const font = labelGroup.getAttribute("font-family");
|
||||
if (font) usedFontFamilies.add(font);
|
||||
}
|
||||
|
||||
const provinceFont = provs.attr("font-family");
|
||||
if (provinceFont) usedFontFamilies.add(provinceFont);
|
||||
|
||||
const legend = svg.querySelector("#legend");
|
||||
const legendFont = legend?.getAttribute("font-family");
|
||||
if (legendFont) usedFontFamilies.add(legendFont);
|
||||
|
||||
const usedFonts = fonts.filter(font => usedFontFamilies.has(font.family));
|
||||
return usedFonts;
|
||||
}
|
||||
|
||||
function addFontOption(family) {
|
||||
const options = document.getElementById("styleSelectFont");
|
||||
// const existingOption = options.querySelector(`[value="${family}"]`);
|
||||
// if (existingOption) return;
|
||||
|
||||
const option = document.createElement("option");
|
||||
option.value = family;
|
||||
option.innerText = family;
|
||||
option.style.fontFamily = family;
|
||||
options.add(option);
|
||||
}
|
||||
|
||||
async function fetchGoogleFont(family) {
|
||||
const url = `https://fonts.googleapis.com/css2?family=${family.replace(/ /g, "+")}`;
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
const text = await resp.text();
|
||||
let s = document.createElement("style");
|
||||
s.innerHTML = text;
|
||||
document.head.appendChild(s);
|
||||
let styleSheet = Array.prototype.filter.call(document.styleSheets, sS => sS.ownerNode === s)[0];
|
||||
let FontRule = rule_1 => {
|
||||
let family = rule_1.style.getPropertyValue("font-family");
|
||||
let font = family.replace(/['"]+/g, "").replace(/ /g, "+");
|
||||
let weight = rule_1.style.getPropertyValue("font-weight");
|
||||
if (weight && weight !== "400") font += ":" + weight;
|
||||
if (fonts.indexOf(font) == -1) {
|
||||
fonts.push(font);
|
||||
fetched++;
|
||||
}
|
||||
};
|
||||
let fetched = 0;
|
||||
for (let r of styleSheet.cssRules) {
|
||||
FontRule(r);
|
||||
}
|
||||
document.head.removeChild(s);
|
||||
return fetched;
|
||||
|
||||
const fontFaceRules = text.match(/font-face\s*{[^}]+}/g);
|
||||
const fonts = fontFaceRules.map(fontFace => {
|
||||
const srcURL = fontFace.match(/url\(['"]?(.+?)['"]?\)/)[1];
|
||||
const src = `url(${srcURL})`;
|
||||
const unicodeRange = fontFace.match(/unicode-range: (.*?);/)?.[1];
|
||||
const variant = fontFace.match(/font-style: (.*?);/)?.[1];
|
||||
|
||||
const font = {family, src};
|
||||
if (unicodeRange) font.unicodeRange = unicodeRange;
|
||||
if (variant && variant !== "normal") font.variant = variant;
|
||||
return font;
|
||||
});
|
||||
|
||||
return fonts;
|
||||
} catch (err) {
|
||||
return ERROR && console.error(err);
|
||||
ERROR && console.error(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function loadUsedFonts() {
|
||||
const fontsInUse = getFontsList(svg);
|
||||
const fontsToLoad = fontsInUse.filter(font => !fonts.includes(font));
|
||||
if (fontsToLoad?.length) {
|
||||
const url = "https://fonts.googleapis.com/css?family=" + fontsToLoad.join("|");
|
||||
addFonts(url);
|
||||
}
|
||||
}
|
||||
|
||||
function getFontsList(svg) {
|
||||
const fontsInUse = [];
|
||||
|
||||
svg.selectAll("#labels > g").each(function () {
|
||||
if (!this.hasChildNodes()) return;
|
||||
const font = this.dataset.font;
|
||||
if (font) fontsInUse.push(font);
|
||||
});
|
||||
if (legend?.node()?.hasChildNodes()) fontsInUse.push(legend.attr("data-font"));
|
||||
|
||||
return [...new Set(fontsInUse)];
|
||||
}
|
||||
|
||||
// code from Kaiido's answer https://stackoverflow.com/questions/42402584/how-to-use-google-fonts-in-canvas-when-drawing-dom-objects-in-svg
|
||||
function GFontToDataURI(url) {
|
||||
if (!url) return Promise.resolve();
|
||||
return fetch(url) // first fecth the embed stylesheet page
|
||||
.then(resp => resp.text()) // we only need the text of it
|
||||
.then(text => {
|
||||
let s = document.createElement("style");
|
||||
s.innerHTML = text;
|
||||
document.head.appendChild(s);
|
||||
const styleSheet = Array.prototype.filter.call(document.styleSheets, sS => sS.ownerNode === s)[0];
|
||||
|
||||
const FontRule = rule => {
|
||||
const src = rule.style.getPropertyValue("src");
|
||||
const url = src ? src.split("url(")[1].split(")")[0] : "";
|
||||
return {rule, src, url: url.substring(url.length - 1, 1)};
|
||||
};
|
||||
const fontProms = [];
|
||||
|
||||
for (const r of styleSheet.cssRules) {
|
||||
let fR = FontRule(r);
|
||||
if (!fR.url) continue;
|
||||
|
||||
fontProms.push(
|
||||
fetch(fR.url) // fetch the actual font-file (.woff)
|
||||
.then(resp => resp.blob())
|
||||
.then(blob => {
|
||||
return new Promise(resolve => {
|
||||
let f = new FileReader();
|
||||
f.onload = e => resolve(f.result);
|
||||
f.readAsDataURL(blob);
|
||||
});
|
||||
})
|
||||
.then(dataURL => fR.rule.cssText.replace(fR.url, dataURL))
|
||||
);
|
||||
}
|
||||
document.head.removeChild(s); // clean up
|
||||
return Promise.all(fontProms); // wait for all this has been done
|
||||
});
|
||||
}
|
||||
|
||||
// fetch default fonts if not done before
|
||||
function loadDefaultFonts() {
|
||||
if (!$('link[href="fonts.css"]').length) {
|
||||
$("head").append('<link rel="stylesheet" type="text/css" href="fonts.css">');
|
||||
const fontsToAdd = ["Amatic+SC:700", "IM+Fell+English", "Great+Vibes", "MedievalSharp", "Metamorphous", "Nova+Script", "Uncial+Antiqua", "Underdog", "Caesar+Dressing", "Bitter", "Yellowtail", "Montez", "Shadows+Into+Light", "Fredericka+the+Great", "Orbitron", "Dancing+Script:700", "Architects+Daughter", "Kaushan+Script", "Gloria+Hallelujah", "Satisfy", "Comfortaa:700", "Cinzel"];
|
||||
fontsToAdd.forEach(function (f) {
|
||||
if (fonts.indexOf(f) === -1) fonts.push(f);
|
||||
});
|
||||
updateFontOptions();
|
||||
}
|
||||
}
|
||||
|
||||
function fetchFonts(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (url === "") return tip("Use a direct link to any @font-face declaration or just font name to fetch from Google Fonts");
|
||||
|
||||
if (url.indexOf("http") === -1) {
|
||||
url = url.replace(url.charAt(0), url.charAt(0).toUpperCase()).split(" ").join("+");
|
||||
url = "https://fonts.googleapis.com/css?family=" + url;
|
||||
}
|
||||
|
||||
addFonts(url).then(fetched => {
|
||||
if (fetched === undefined) return tip("Cannot fetch font for this value!", false, "error");
|
||||
if (fetched === 0) return tip("Already in the fonts list!", false, "error");
|
||||
|
||||
updateFontOptions();
|
||||
if (fetched === 1) {
|
||||
tip("Font " + fonts[fonts.length - 1] + " is fetched");
|
||||
} else if (fetched > 1) {
|
||||
tip(fetched + " fonts are added to the list");
|
||||
}
|
||||
resolve(fetched);
|
||||
});
|
||||
function readBlobAsDataURL(blob) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(reader.result);
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
// Update font list for Label and Burg Editors
|
||||
function updateFontOptions() {
|
||||
styleSelectFont.innerHTML = "";
|
||||
for (let i = 0; i < fonts.length; i++) {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = i;
|
||||
const font = fonts[i].split(":")[0].replace(/\+/g, " ");
|
||||
opt.style.fontFamily = opt.innerHTML = font;
|
||||
styleSelectFont.add(opt);
|
||||
}
|
||||
async function loadFontsAsDataURI(fonts) {
|
||||
const promises = fonts.map(async font => {
|
||||
const url = font.src.match(/url\(['"]?(.+?)['"]?\)/)[1];
|
||||
const resp = await fetch(url);
|
||||
const blob = await resp.blob();
|
||||
const dataURL = await readBlobAsDataURL(blob);
|
||||
|
||||
return {...font, src: `url('${dataURL}')`};
|
||||
});
|
||||
|
||||
return await Promise.all(promises);
|
||||
}
|
||||
|
||||
async function addGoogleFont(family) {
|
||||
const fontRanges = await fetchGoogleFont(family);
|
||||
if (!fontRanges) return tip("Cannot fetch Google font for this value", true, "error", 4000);
|
||||
tip(`Google font ${family} is loading...`, true, "warn", 4000);
|
||||
|
||||
const promises = fontRanges.map(range => {
|
||||
const {src, unicodeRange, variant} = range;
|
||||
const fontFace = new FontFace(family, src, {unicodeRange, variant, display: "block"});
|
||||
return fontFace.load();
|
||||
});
|
||||
|
||||
Promise.all(promises)
|
||||
.then(fontFaces => {
|
||||
fontFaces.forEach(fontFace => document.fonts.add(fontFace));
|
||||
fonts.push(...fontRanges);
|
||||
tip(`Google font ${family} is added to the list`, true, "success", 4000);
|
||||
addFontOption(family);
|
||||
document.getElementById("styleSelectFont").value = family;
|
||||
changeFont();
|
||||
})
|
||||
.catch(err => {
|
||||
tip(`Failed to load Google font ${family}`, true, "error", 4000);
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
function addLocalFont(family) {
|
||||
fonts.push({family});
|
||||
|
||||
const fontFace = new FontFace(family, `local(${family})`, {display: "block"});
|
||||
document.fonts.add(fontFace);
|
||||
tip(`Local font ${family} is added to the fonts list`, true, "success", 4000);
|
||||
addFontOption(family);
|
||||
document.getElementById("styleSelectFont").value = family;
|
||||
changeFont();
|
||||
}
|
||||
|
||||
function addWebFont(family, url) {
|
||||
const src = `url('${url}')`;
|
||||
fonts.push({family, src});
|
||||
|
||||
const fontFace = new FontFace(family, src, {display: "block"});
|
||||
document.fonts.add(fontFace);
|
||||
tip(`Font ${family} is added to the list`, true, "success", 4000);
|
||||
addFontOption(family);
|
||||
document.getElementById("styleSelectFont").value = family;
|
||||
changeFont();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ function quickLoad() {
|
|||
});
|
||||
}
|
||||
|
||||
async function loadFromDropbox(fileName) {
|
||||
const map = document.querySelector("#loadFromDropbox select").value;
|
||||
console.log('loading dropbox map', map);
|
||||
const blob = await Cloud.providers.dropbox.load(map);
|
||||
async function loadFromDropbox() {
|
||||
const mapPath = document.getElementById("loadFromDropboxSelect")?.value;
|
||||
|
||||
DEBUG && console.log("Loading map from Dropbox:", mapPath);
|
||||
const blob = await Cloud.providers.dropbox.load(mapPath);
|
||||
uploadMap(blob);
|
||||
}
|
||||
|
||||
|
|
@ -23,18 +24,18 @@ async function createSharableDropboxLink() {
|
|||
const mapFile = document.querySelector("#loadFromDropbox select").value;
|
||||
const sharableLink = document.getElementById("sharableLink");
|
||||
const sharableLinkContainer = document.getElementById("sharableLinkContainer");
|
||||
let url
|
||||
let url;
|
||||
try {
|
||||
url = await Cloud.providers.dropbox.getLink(mapFile);
|
||||
} catch {
|
||||
tip("Dropbox API error. Can not create link.", true, "error", 2000);
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
const fmg = window.location.href.split("?")[0];
|
||||
const reallink= `${fmg}?maplink=${url}`;
|
||||
const reallink = `${fmg}?maplink=${url}`;
|
||||
// voodoo magic required by the yellow god of CORS
|
||||
const link = reallink.replace('www.dropbox.com/s/', 'dl.dropboxusercontent.com/1/view/')
|
||||
const link = reallink.replace("www.dropbox.com/s/", "dl.dropboxusercontent.com/1/view/");
|
||||
const shortLink = link.slice(0, 50) + "...";
|
||||
|
||||
sharableLinkContainer.style.display = "block";
|
||||
|
|
@ -236,6 +237,15 @@ function parseLoadedData(data) {
|
|||
if (data[2]) mapCoordinates = JSON.parse(data[2]);
|
||||
if (data[4]) notes = JSON.parse(data[4]);
|
||||
if (data[33]) rulers.fromString(data[33]);
|
||||
if (data[34]) {
|
||||
const usedFonts = JSON.parse(data[34]);
|
||||
usedFonts.forEach(usedFont => {
|
||||
const {family: usedFamily, unicodeRange: usedRange, variant: usedVariant} = usedFont;
|
||||
const defaultFont = fonts.find(({family, unicodeRange, variant}) => family === usedFamily && unicodeRange === usedRange && variant === usedVariant);
|
||||
if (!defaultFont) fonts.push(usedFont);
|
||||
declareFont(usedFont);
|
||||
});
|
||||
}
|
||||
|
||||
const biomes = data[3].split("|");
|
||||
biomesData = applyDefaultBiomesSystem();
|
||||
|
|
@ -309,8 +319,6 @@ function parseLoadedData(data) {
|
|||
burgLabels = labels.select("#burgLabels");
|
||||
})();
|
||||
|
||||
loadUsedFonts();
|
||||
|
||||
void (function parseGridData() {
|
||||
grid = JSON.parse(data[6]);
|
||||
calculateVoronoi(grid, grid.points);
|
||||
|
|
@ -423,7 +431,7 @@ function parseLoadedData(data) {
|
|||
|
||||
// 1.0 adds a legend box
|
||||
legend = svg.append("g").attr("id", "legend");
|
||||
legend.attr("font-family", "Almendra SC").attr("data-font", "Almendra+SC").attr("font-size", 13).attr("data-size", 13).attr("data-x", 99).attr("data-y", 93).attr("stroke-width", 2.5).attr("stroke", "#812929").attr("stroke-dasharray", "0 4 10 4").attr("stroke-linecap", "round");
|
||||
legend.attr("font-family", "Almendra SC").attr("font-size", 13).attr("data-size", 13).attr("data-x", 99).attr("data-y", 93).attr("stroke-width", 2.5).attr("stroke", "#812929").attr("stroke-dasharray", "0 4 10 4").attr("stroke-linecap", "round");
|
||||
|
||||
// 1.0 separated drawBorders fron drawStates()
|
||||
stateBorders = borders.append("g").attr("id", "stateBorders");
|
||||
|
|
|
|||
|
|
@ -275,14 +275,22 @@ async function getMapURL(type, options = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
// load non-standard fonts
|
||||
const usedFonts = getFontsList(clone);
|
||||
const webSafe = ["Georgia", "Times+New+Roman", "Comic+Sans+MS", "Lucida+Sans+Unicode", "Courier+New", "Verdana", "Arial", "Impact"];
|
||||
const fontsToLoad = usedFonts.filter(font => !webSafe.includes(font));
|
||||
// TODO: add dataURL for all used fonts
|
||||
const usedFonts = getUsedFonts(cloneEl);
|
||||
const fontsToLoad = usedFonts.filter(font => font.src);
|
||||
if (fontsToLoad.length) {
|
||||
const url = "https://fonts.googleapis.com/css?family=" + fontsToLoad.join("|");
|
||||
const fontStyle = await GFontToDataURI(url);
|
||||
if (fontStyle) clone.select("defs").append("style").text(fontStyle.join("\n"));
|
||||
const dataURLfonts = await loadFontsAsDataURI(fontsToLoad);
|
||||
|
||||
const fontFaces = dataURLfonts
|
||||
.map(({family, src, unicodeRange = "", variant = "normal"}) => {
|
||||
return `@font-face {font-family: "${family}"; src: ${src}; unicode-range: ${unicodeRange}; font-variant: ${variant};}`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
style.innerHTML = fontFaces;
|
||||
cloneEl.querySelector("defs").appendChild(style);
|
||||
}
|
||||
|
||||
clone.remove();
|
||||
|
|
@ -378,6 +386,7 @@ function getMapData() {
|
|||
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
|
||||
const notesData = JSON.stringify(notes);
|
||||
const rulersString = rulers.toString();
|
||||
const fonts = JSON.stringify(getUsedFonts(svg.node()));
|
||||
|
||||
// save svg
|
||||
const cloneEl = document.getElementById("map").cloneNode(true);
|
||||
|
|
@ -414,7 +423,7 @@ function getMapData() {
|
|||
const pop = Array.from(pack.cells.pop).map(p => rn(p, 4));
|
||||
|
||||
// data format as below
|
||||
const mapData = [params, settings, coords, biomes, notesData, serializedSVG, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, packFeatures, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString].join("\r\n");
|
||||
const mapData = [params, settings, coords, biomes, notesData, serializedSVG, gridGeneral, grid.cells.h, grid.cells.prec, grid.cells.f, grid.cells.t, grid.cells.temp, packFeatures, cultures, states, burgs, pack.cells.biome, pack.cells.burg, pack.cells.conf, pack.cells.culture, pack.cells.fl, pop, pack.cells.r, pack.cells.road, pack.cells.s, pack.cells.state, pack.cells.religion, pack.cells.province, pack.cells.crossroad, religions, provinces, namesData, rivers, rulersString, fonts].join("\r\n");
|
||||
TIME && console.timeEnd("createMapData");
|
||||
return mapData;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,15 +32,20 @@ function tip(tip = "Tip is undefined", main, type, time) {
|
|||
else if (type === "warn") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #be5d08cc, #ffffff00)";
|
||||
else if (type === "success") tooltip.style.background = "linear-gradient(0.1turn, #ffffff00, #127912cc, #ffffff00)";
|
||||
|
||||
if (main) tooltip.dataset.main = tip; // set main tip
|
||||
if (time) setTimeout(() => (tooltip.dataset.main = ""), time); // clear main in some time
|
||||
if (main) {
|
||||
tooltip.dataset.main = tip;
|
||||
tooltip.dataset.color = tooltip.style.background;
|
||||
}
|
||||
if (time) setTimeout(() => clearMainTip(), time);
|
||||
}
|
||||
|
||||
function showMainTip() {
|
||||
tooltip.style.background = tooltip.dataset.color;
|
||||
tooltip.innerHTML = tooltip.dataset.main;
|
||||
}
|
||||
|
||||
function clearMainTip() {
|
||||
tooltip.dataset.color = "";
|
||||
tooltip.dataset.main = "";
|
||||
tooltip.innerHTML = "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ function editHeightmap() {
|
|||
<p>You can <i>keep</i> the data, but you won't be able to change the coastline.</p>
|
||||
<p>Try <i>risk</i> mode to change the coastline and keep the data. The data will be restored as much as possible, but it can cause unpredictable errors.</p>
|
||||
<p>Please <span class="pseudoLink" onclick=dowloadMap(); editHeightmap();>save the map</span> before editing the heightmap!</p>
|
||||
<p>Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.</p>`;
|
||||
<p style="margin-bottom: 0">Check out ${link("https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Heightmap-customization", "wiki")} for guidance.</p>`;
|
||||
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
|
|
|
|||
|
|
@ -663,7 +663,7 @@ function showSavePane() {
|
|||
$("#saveMapData").dialog({
|
||||
title: "Save map",
|
||||
resizable: false,
|
||||
width: "27em",
|
||||
width: "25em",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Close: function () {
|
||||
|
|
@ -699,7 +699,7 @@ async function showLoadPane() {
|
|||
$("#loadMapData").dialog({
|
||||
title: "Load map",
|
||||
resizable: false,
|
||||
width: "22em",
|
||||
width: "24em",
|
||||
position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Close: function () {
|
||||
|
|
@ -708,17 +708,23 @@ async function showLoadPane() {
|
|||
}
|
||||
});
|
||||
|
||||
const dpx = document.getElementById("loadFromDropbox");
|
||||
const dpf = dpx.querySelector("select");
|
||||
const loadFromDropboxButtons = document.getElementById("loadFromDropboxButtons");
|
||||
const fileSelect = document.getElementById("loadFromDropboxSelect");
|
||||
const files = await Cloud.providers.dropbox.list();
|
||||
dpx.style.display = files? "block" : "none";
|
||||
if (!files) return;
|
||||
while(dpf.firstChild) dpf.removeChild(dpf.firstChild);
|
||||
files.forEach(f => {
|
||||
const opt = document.createElement('option');
|
||||
opt.innerText = f.name;
|
||||
opt.value = f.path;
|
||||
dpf.appendChild(opt);
|
||||
|
||||
if (!files) {
|
||||
loadFromDropboxButtons.style.display = "none";
|
||||
fileSelect.innerHTML = `<option value="" disabled selected>Save files to Dropbox first</option>`;
|
||||
return;
|
||||
}
|
||||
|
||||
loadFromDropboxButtons.style.display = "block";
|
||||
fileSelect.innerHTML = "";
|
||||
files.forEach(file => {
|
||||
const opt = document.createElement("option");
|
||||
opt.innerText = file.name;
|
||||
opt.value = file.path;
|
||||
fileSelect.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -475,7 +475,7 @@ function addLabelOnClick() {
|
|||
const id = getNextId("label");
|
||||
|
||||
let group = labels.select("#addedLabels");
|
||||
if (!group.size()) group = labels.append("g").attr("id", "addedLabels").attr("fill", "#3e3e4b").attr("opacity", 1).attr("stroke", "#3a3a3a").attr("stroke-width", 0).attr("font-family", "Almendra SC").attr("data-font", "Almendra+SC").attr("font-size", 18).attr("data-size", 18).attr("filter", null);
|
||||
if (!group.size()) group = labels.append("g").attr("id", "addedLabels").attr("fill", "#3e3e4b").attr("opacity", 1).attr("stroke", "#3a3a3a").attr("stroke-width", 0).attr("font-family", "Almendra SC").attr("font-size", 18).attr("data-size", 18).attr("filter", null);
|
||||
|
||||
const example = group.append("text").attr("x", 0).attr("x", 0).text(name);
|
||||
const width = example.node().getBBox().width;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue