mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-13 13:04:03 +00:00
Integrate with addition of new setting in master.
This commit is contained in:
commit
6f7d0a4444
12
README.md
12
README.md
@ -1,15 +1,15 @@
|
|||||||
# shapez.io
|
# shapez.io
|
||||||
|
|
||||||
<img src="https://i.imgur.com/Y5Z2iqQ.png" alt="shapez.io Logo">
|
<img src="https://i.imgur.com/Y5Z2iqQ.png" alt="shapez.io Logo">
|
||||||
<img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot">
|
|
||||||
|
|
||||||
This is the source code for shapez.io, an open source base building game inspired by Factorio.
|
This is the source code for shapez.io, an open source base building game inspired by Factorio.
|
||||||
|
|
||||||
Your goal is to produce shapes by cutting, rotating, merging and painting parts of shapes.
|
Your goal is to produce shapes by cutting, rotating, merging and painting parts of shapes.
|
||||||
|
|
||||||
## Playing
|
- [Trello Board & Roadmap](https://trello.com/b/ISQncpJP/shapezio)
|
||||||
|
- [Free web version](https://shapez.io)
|
||||||
You can already play it [here](https://shapez.io).
|
- [itch.io Page](https://tobspr.itch.io/shapezio)
|
||||||
|
- [Steam Page](https://steam.shapez.io)
|
||||||
|
- [Official Discord](https://discord.com/invite/HN7EVzV) <- _Highly recommended to join!_
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@ -46,3 +46,5 @@ This project is based on ES5. Some ES2015 features are used but most of them are
|
|||||||
For most assets I use Adobe Photoshop, you can find them in `assets/`.
|
For most assets I use Adobe Photoshop, you can find them in `assets/`.
|
||||||
|
|
||||||
You will need a <a href="https://www.codeandweb.com/texturepacker" target="_blank">Texture Packer</a> license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when thats done.
|
You will need a <a href="https://www.codeandweb.com/texturepacker" target="_blank">Texture Packer</a> license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when thats done.
|
||||||
|
|
||||||
|
<img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot">
|
||||||
|
|||||||
9
gulp/.itch.toml
Normal file
9
gulp/.itch.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[[actions]]
|
||||||
|
name = "play"
|
||||||
|
path = "shapezio.exe"
|
||||||
|
platform = "windows"
|
||||||
|
|
||||||
|
[[actions]]
|
||||||
|
name = "play"
|
||||||
|
path = "play.sh"
|
||||||
|
platform = "linux"
|
||||||
@ -121,6 +121,8 @@ function gulptasksStandalone($, gulp, buildFolder) {
|
|||||||
* @param {boolean=} isRelease
|
* @param {boolean=} isRelease
|
||||||
*/
|
*/
|
||||||
function packageStandalone(platform, arch, cb, isRelease = false) {
|
function packageStandalone(platform, arch, cb, isRelease = false) {
|
||||||
|
const tomlFile = fs.readFileSync(path.join(__dirname, ".itch.toml"));
|
||||||
|
|
||||||
packager({
|
packager({
|
||||||
dir: tempDestBuildDir,
|
dir: tempDestBuildDir,
|
||||||
appCopyright: "Tobias Springer",
|
appCopyright: "Tobias Springer",
|
||||||
@ -150,17 +152,25 @@ function gulptasksStandalone($, gulp, buildFolder) {
|
|||||||
fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
|
fs.readFileSync(path.join(__dirname, "..", "LICENSE"))
|
||||||
);
|
);
|
||||||
|
|
||||||
const playablePath = appPath + "_playable";
|
fs.writeFileSync(path.join(appPath, ".itch.toml"), tomlFile);
|
||||||
fse.copySync(appPath, playablePath);
|
|
||||||
fs.writeFileSync(path.join(playablePath, "steam_appid.txt"), "1134480");
|
if (platform === "linux" || platform === "darwin") {
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(path.join(appPath, "play.sh"), "#!/usr/bin/env bash\n./shapezio\n");
|
||||||
path.join(playablePath, "play.bat"),
|
fs.chmodSync(path.join(appPath, "play.sh"), 0o775);
|
||||||
"start shapezio --dev --disable-direct-composition --in-process-gpu\r\n"
|
} else if (platform === "win32") {
|
||||||
);
|
// Optional: Create a playable copy. Shouldn't be required
|
||||||
fs.writeFileSync(
|
// const playablePath = appPath + "_playable";
|
||||||
path.join(playablePath, "play_local.bat"),
|
// fse.copySync(appPath, playablePath);
|
||||||
"start shapezio --local --dev --disable-direct-composition --in-process-gpu\r\n"
|
// fs.writeFileSync(path.join(playablePath, "steam_appid.txt"), "1134480");
|
||||||
);
|
// fs.writeFileSync(
|
||||||
|
// path.join(playablePath, "play.bat"),
|
||||||
|
// "start shapezio --dev --disable-direct-composition --in-process-gpu\r\n"
|
||||||
|
// );
|
||||||
|
// fs.writeFileSync(
|
||||||
|
// path.join(playablePath, "play_local.bat"),
|
||||||
|
// "start shapezio --local --dev --disable-direct-composition --in-process-gpu\r\n"
|
||||||
|
// );
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cb();
|
cb();
|
||||||
@ -182,10 +192,10 @@ function gulptasksStandalone($, gulp, buildFolder) {
|
|||||||
"standalone.package.prod",
|
"standalone.package.prod",
|
||||||
$.sequence("standalone.prepare", [
|
$.sequence("standalone.prepare", [
|
||||||
"standalone.package.prod.win64",
|
"standalone.package.prod.win64",
|
||||||
// "standalone.package.prod.linux64",
|
"standalone.package.prod.linux64",
|
||||||
|
"standalone.package.prod.darwin64",
|
||||||
// "standalone.package.prod.win32",
|
// "standalone.package.prod.win32",
|
||||||
// "standalone.package.prod.linux32",
|
// "standalone.package.prod.linux32",
|
||||||
// "standalone.package.prod.darwin64"
|
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,8 @@
|
|||||||
"tslint": "cd src/js && tsc",
|
"tslint": "cd src/js && tsc",
|
||||||
"lint": "npx eslint src/js",
|
"lint": "npx eslint src/js",
|
||||||
"prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*",
|
"prettier-all": "prettier --write src/**/*.* && prettier --write gulp/**/*.*",
|
||||||
"publishOnItch": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version",
|
"publishOnItchWindows": "butler push tmp_standalone_files/shapez.io-standalone-win32-x64 tobspr/shapezio:windows --userversion-file version",
|
||||||
|
"publishOnItchLinux": "butler push tmp_standalone_files/shapez.io-standalone-linux-x64 tobspr/shapezio:linux-experimental --userversion-file version",
|
||||||
"publishOnSteam": "cd gulp/steampipe && ./upload.bat",
|
"publishOnSteam": "cd gulp/steampipe && ./upload.bat",
|
||||||
"publishStandalone": "yarn publishOnItch && yarn publishOnSteam",
|
"publishStandalone": "yarn publishOnItch && yarn publishOnSteam",
|
||||||
"publishWeb": "cd gulp && yarn main.deploy.prod",
|
"publishWeb": "cd gulp && yarn main.deploy.prod",
|
||||||
|
|||||||
@ -11,7 +11,11 @@
|
|||||||
border-bottom-width: 0;
|
border-bottom-width: 0;
|
||||||
transition: transform 0.12s ease-in-out;
|
transition: transform 0.12s ease-in-out;
|
||||||
|
|
||||||
background: rgba(mix(#ddd, $colorBlueBright, 80%), 0.69);
|
background: rgba(mix(#ddd, $colorBlueBright, 90%), 0.75);
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
background: #222428;
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.visible) {
|
&:not(.visible) {
|
||||||
transform: translateX(-50%) translateY(#{D(100px)});
|
transform: translateX(-50%) translateY(#{D(100px)});
|
||||||
|
|||||||
@ -6,8 +6,12 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
color: #333438;
|
||||||
|
// text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.1);
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.1);
|
}
|
||||||
|
|
||||||
> .binding {
|
> .binding {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
@ -42,10 +46,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: $accentColorDark;
|
color: #333438;
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
// color: #fff;
|
||||||
|
@include DarkThemeOverride {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
@include S(margin-left, 5px);
|
@include S(margin-left, 5px);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,8 @@
|
|||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
grid-template-rows: 1fr 1fr;
|
grid-template-rows: 1fr 1fr;
|
||||||
@include S(margin-bottom, 4px);
|
@include S(margin-bottom, 4px);
|
||||||
color: #fff;
|
color: #333438;
|
||||||
text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2);
|
// text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2);
|
||||||
|
|
||||||
&.unpinable {
|
&.unpinable {
|
||||||
> canvas {
|
> canvas {
|
||||||
@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
> .goalLabel {
|
> .goalLabel {
|
||||||
@include S(font-size, 7px);
|
@include S(font-size, 7px);
|
||||||
opacity: 0.5;
|
opacity: 0.9;
|
||||||
align-self: start;
|
align-self: start;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@ -81,7 +81,6 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
@include S(width, 8px);
|
@include S(width, 8px);
|
||||||
@include S(height, 8px);
|
@include S(height, 8px);
|
||||||
opacity: 0.8;
|
|
||||||
@include S(top, 4px);
|
@include S(top, 4px);
|
||||||
@include S(left, -7px);
|
@include S(left, -7px);
|
||||||
background: uiResource("icons/current_goal_marker.png") center center / contain no-repeat;
|
background: uiResource("icons/current_goal_marker.png") center center / contain no-repeat;
|
||||||
|
|||||||
@ -38,13 +38,13 @@
|
|||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #000;
|
color: #333438;
|
||||||
@include S(padding-left, 11px);
|
@include S(padding-left, 11px);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat;
|
background: uiResource("icons/waypoint.png") left 50% / #{D(8px)} no-repeat;
|
||||||
opacity: 0.5;
|
opacity: 0.7;
|
||||||
@include S(margin-bottom, 1px);
|
@include S(margin-bottom, 1px);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|||||||
@ -36,6 +36,9 @@
|
|||||||
@include S(padding, 1px, 2px);
|
@include S(padding, 1px, 2px);
|
||||||
@include S(margin-right, 3px);
|
@include S(margin-right, 3px);
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
|
color: $colorBlueBright;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,9 @@
|
|||||||
<meta http-equiv="Expires" content="0" />
|
<meta http-equiv="Expires" content="0" />
|
||||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
<link rel="canonical" href="https://shapez.io" />
|
<link rel="canonical" href="https://shapez.io" />
|
||||||
|
|
||||||
|
<!-- a/b testing -->
|
||||||
|
<script src="https://www.googleoptimize.com/optimize.js?id=OPT-M5NHCV7"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body oncontextmenu="return false" style="background: #393747;"></body>
|
<body oncontextmenu="return false" style="background: #393747;"></body>
|
||||||
|
|||||||
@ -1,11 +1,25 @@
|
|||||||
export const CHANGELOG = [
|
export const CHANGELOG = [
|
||||||
{
|
{
|
||||||
version: "1.1.2",
|
version: "1.1.3",
|
||||||
date: "unreleased",
|
date: "01.06.2020",
|
||||||
entries: [
|
entries: [
|
||||||
|
"Added setting to configure zoom / mouse wheel / touchpad sensitivity",
|
||||||
|
"Fix belts being too slow when copied via blueprint (by Dimava)",
|
||||||
|
"Allow binding mouse buttons to actions (by Dimava)",
|
||||||
|
"Increase readability of certain HUD elements",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: "1.1.2",
|
||||||
|
date: "30.05.2020",
|
||||||
|
entries: [
|
||||||
|
"The official trailer is now ready! Check it out <a href='https://www.youtube.com/watch?v=KyorY1uIqiQ' target='_blank'>here</a>!",
|
||||||
|
"The <a href='https://steam.shapez.io' target='_blank'>steam page</a> is now live!",
|
||||||
|
"Experimental linux builds are now available! Please give me feedback on them in the discord",
|
||||||
"Allow hovering pinned shapes to enlarge them",
|
"Allow hovering pinned shapes to enlarge them",
|
||||||
|
"Allow deselecting blueprints with right click and 'Q'",
|
||||||
"Move default key for deleting from 'X' to 'DEL'",
|
"Move default key for deleting from 'X' to 'DEL'",
|
||||||
"Show confirmation when deleting > 100 buildings",
|
"Show confirmation when deleting more than 100 buildings",
|
||||||
"Reintroduce 'SPACE' keybinding to center on map",
|
"Reintroduce 'SPACE' keybinding to center on map",
|
||||||
"Improved keybinding hints",
|
"Improved keybinding hints",
|
||||||
"Fixed some keybindings showing as 'undefined'",
|
"Fixed some keybindings showing as 'undefined'",
|
||||||
|
|||||||
@ -311,7 +311,7 @@ export class ClickDetector {
|
|||||||
const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
const position = /** @type {typeof ClickDetector} */ (this.constructor).extractPointerPosition(event);
|
||||||
|
|
||||||
if (event instanceof MouseEvent) {
|
if (event instanceof MouseEvent) {
|
||||||
const isRightClick = event.which == 3;
|
const isRightClick = event.button === 2;
|
||||||
if (isRightClick) {
|
if (isRightClick) {
|
||||||
// Ignore right clicks
|
// Ignore right clicks
|
||||||
this.rightClick.dispatch(position, event);
|
this.rightClick.dispatch(position, event);
|
||||||
@ -384,7 +384,7 @@ export class ClickDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event instanceof MouseEvent) {
|
if (event instanceof MouseEvent) {
|
||||||
const isRightClick = event.which == 3;
|
const isRightClick = event.button === 2;
|
||||||
if (isRightClick) {
|
if (isRightClick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export const globalConfig = {
|
|||||||
|
|
||||||
debug: {
|
debug: {
|
||||||
/* dev:start */
|
/* dev:start */
|
||||||
fastGameEnter: true,
|
// fastGameEnter: true,
|
||||||
// noArtificialDelays: true,
|
// noArtificialDelays: true,
|
||||||
// disableSavegameWrite: true,
|
// disableSavegameWrite: true,
|
||||||
// showEntityBounds: true,
|
// showEntityBounds: true,
|
||||||
|
|||||||
@ -141,8 +141,13 @@ export class InputDistributor {
|
|||||||
bindToEvents() {
|
bindToEvents() {
|
||||||
window.addEventListener("popstate", this.handleBackButton.bind(this), false);
|
window.addEventListener("popstate", this.handleBackButton.bind(this), false);
|
||||||
document.addEventListener("backbutton", this.handleBackButton.bind(this), false);
|
document.addEventListener("backbutton", this.handleBackButton.bind(this), false);
|
||||||
window.addEventListener("keydown", this.handleKeydown.bind(this));
|
|
||||||
window.addEventListener("keyup", this.handleKeyup.bind(this));
|
window.addEventListener("keydown", this.handleKeyMouseDown.bind(this));
|
||||||
|
window.addEventListener("keyup", this.handleKeyMouseUp.bind(this));
|
||||||
|
|
||||||
|
window.addEventListener("mousedown", this.handleKeyMouseDown.bind(this));
|
||||||
|
window.addEventListener("mouseup", this.handleKeyMouseUp.bind(this));
|
||||||
|
|
||||||
window.addEventListener("blur", this.handleBlur.bind(this));
|
window.addEventListener("blur", this.handleBlur.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,25 +187,28 @@ export class InputDistributor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {KeyboardEvent} event
|
* @param {KeyboardEvent | MouseEvent} event
|
||||||
*/
|
*/
|
||||||
handleKeydown(event) {
|
handleKeyMouseDown(event) {
|
||||||
|
const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||||
if (
|
if (
|
||||||
event.keyCode === 9 || // TAB
|
keyCode === 4 || // MB4
|
||||||
event.keyCode === 16 || // SHIFT
|
keyCode === 5 || // MB5
|
||||||
event.keyCode === 17 || // CTRL
|
keyCode === 9 || // TAB
|
||||||
event.keyCode === 18 || // ALT
|
keyCode === 16 || // SHIFT
|
||||||
(event.keyCode >= 112 && event.keyCode < 122) // F1 - F10
|
keyCode === 17 || // CTRL
|
||||||
|
keyCode === 18 || // ALT
|
||||||
|
(keyCode >= 112 && keyCode < 122) // F1 - F10
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInitial = !this.keysDown.has(event.keyCode);
|
const isInitial = !this.keysDown.has(keyCode);
|
||||||
this.keysDown.add(event.keyCode);
|
this.keysDown.add(keyCode);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.forwardToReceiver("keydown", {
|
this.forwardToReceiver("keydown", {
|
||||||
keyCode: event.keyCode,
|
keyCode: keyCode,
|
||||||
shift: event.shiftKey,
|
shift: event.shiftKey,
|
||||||
alt: event.altKey,
|
alt: event.altKey,
|
||||||
initial: isInitial,
|
initial: isInitial,
|
||||||
@ -210,8 +218,7 @@ export class InputDistributor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = event.keyCode;
|
if (keyCode === 27) {
|
||||||
if (code === 27) {
|
|
||||||
// Escape key
|
// Escape key
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -220,13 +227,14 @@ export class InputDistributor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {KeyboardEvent} event
|
* @param {KeyboardEvent | MouseEvent} event
|
||||||
*/
|
*/
|
||||||
handleKeyup(event) {
|
handleKeyMouseUp(event) {
|
||||||
this.keysDown.delete(event.keyCode);
|
const keyCode = event instanceof MouseEvent ? event.button + 1 : event.keyCode;
|
||||||
|
this.keysDown.delete(keyCode);
|
||||||
|
|
||||||
this.forwardToReceiver("keyup", {
|
this.forwardToReceiver("keyup", {
|
||||||
keyCode: event.keyCode,
|
keyCode: keyCode,
|
||||||
shift: event.shiftKey,
|
shift: event.shiftKey,
|
||||||
alt: event.altKey,
|
alt: event.altKey,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -24,9 +24,7 @@ export const BOTTOM = new Vector(0, 1);
|
|||||||
export const LEFT = new Vector(-1, 0);
|
export const LEFT = new Vector(-1, 0);
|
||||||
export const ALL_DIRECTIONS = [TOP, RIGHT, BOTTOM, LEFT];
|
export const ALL_DIRECTIONS = [TOP, RIGHT, BOTTOM, LEFT];
|
||||||
|
|
||||||
export const thousand = 1000;
|
const bigNumberSuffixTranslationKeys = ["thousands", "millions", "billions", "trillions"];
|
||||||
export const million = 1000 * 1000;
|
|
||||||
export const billion = 1000 * 1000 * 1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the build id
|
* Returns the build id
|
||||||
@ -435,21 +433,20 @@ export function formatBigNumber(num, divider = ".") {
|
|||||||
|
|
||||||
if (num < 1000) {
|
if (num < 1000) {
|
||||||
return sign + "" + num;
|
return sign + "" + num;
|
||||||
|
} else {
|
||||||
|
let leadingDigits = num;
|
||||||
|
let suffix = "";
|
||||||
|
for (let suffixIndex = 0; suffixIndex < bigNumberSuffixTranslationKeys.length; ++suffixIndex) {
|
||||||
|
leadingDigits = leadingDigits / 1000;
|
||||||
|
suffix = T.global.suffix[bigNumberSuffixTranslationKeys[suffixIndex]];
|
||||||
|
if (leadingDigits < 1000) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (num > 10000) {
|
|
||||||
return Math_floor(num / 1000.0) + "k";
|
|
||||||
}
|
}
|
||||||
|
const leadingDigitsRounded = round1Digit(leadingDigits);
|
||||||
let rest = num;
|
const leadingDigitsNoTrailingDecimal = leadingDigitsRounded.toString().replace(".0", "");
|
||||||
let out = "";
|
return sign + leadingDigitsNoTrailingDecimal + suffix;
|
||||||
|
|
||||||
while (rest >= 1000) {
|
|
||||||
out = (rest % 1000).toString().padStart(3, "0") + (out !== "" ? divider : "") + out;
|
|
||||||
rest = Math_floor(rest / 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out = rest + divider + out;
|
|
||||||
return sign + out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -440,11 +440,11 @@ export class Camera extends BasicSerializableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.touchPostMoveVelocity = new Vector(0, 0);
|
this.touchPostMoveVelocity = new Vector(0, 0);
|
||||||
if (event.which === 1) {
|
if (event.button === 0) {
|
||||||
this.combinedSingleTouchStartHandler(event.clientX, event.clientY);
|
this.combinedSingleTouchStartHandler(event.clientX, event.clientY);
|
||||||
} else if (event.which === 2) {
|
} else if (event.button === 1) {
|
||||||
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.middle);
|
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.middle);
|
||||||
} else if (event.which === 3) {
|
} else if (event.button === 2) {
|
||||||
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.right);
|
this.downPreHandler.dispatch(new Vector(event.clientX, event.clientY), enumMouseButton.right);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -464,7 +464,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.which === 1) {
|
if (event.button === 0) {
|
||||||
this.combinedSingleTouchMoveHandler(event.clientX, event.clientY);
|
this.combinedSingleTouchMoveHandler(event.clientX, event.clientY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +503,7 @@ export class Camera extends BasicSerializableObject {
|
|||||||
// event.stopPropagation();
|
// event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
const delta = Math.sign(event.deltaY) * -0.15;
|
const delta = Math.sign(event.deltaY) * -0.15 * this.root.app.settings.getScrollWheelSensitivity();
|
||||||
assert(Number.isFinite(delta), "Got invalid delta in mouse wheel event: " + event.deltaY);
|
assert(Number.isFinite(delta), "Got invalid delta in mouse wheel event: " + event.deltaY);
|
||||||
assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel);
|
assert(Number.isFinite(this.zoomLevel), "Got invalid zoom level *before* wheel: " + this.zoomLevel);
|
||||||
this.zoomLevel *= 1 + delta;
|
this.zoomLevel *= 1 + delta;
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export class ItemEjectorComponent extends Component {
|
|||||||
|
|
||||||
return new ItemEjectorComponent({
|
return new ItemEjectorComponent({
|
||||||
slots: slotsCopy,
|
slots: slotsCopy,
|
||||||
instantEject: false,
|
instantEject: this.instantEject,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,8 @@ export class GameHUD {
|
|||||||
this.parts = {
|
this.parts = {
|
||||||
processingOverlay: new HUDProcessingOverlay(this.root),
|
processingOverlay: new HUDProcessingOverlay(this.root),
|
||||||
buildingsToolbar: new HUDBuildingsToolbar(this.root),
|
buildingsToolbar: new HUDBuildingsToolbar(this.root),
|
||||||
buildingPlacer: new HUDBuildingPlacer(this.root),
|
|
||||||
blueprintPlacer: new HUDBlueprintPlacer(this.root),
|
blueprintPlacer: new HUDBlueprintPlacer(this.root),
|
||||||
|
buildingPlacer: new HUDBuildingPlacer(this.root),
|
||||||
unlockNotification: new HUDUnlockNotification(this.root),
|
unlockNotification: new HUDUnlockNotification(this.root),
|
||||||
gameMenu: new HUDGameMenu(this.root),
|
gameMenu: new HUDGameMenu(this.root),
|
||||||
massSelector: new HUDMassSelector(this.root),
|
massSelector: new HUDMassSelector(this.root),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
//www.youtube.com/watch?v=KyorY1uIqiQimport { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
@ -36,6 +36,9 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
|||||||
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
|
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
|
||||||
.add(this.abortPlacement, this);
|
.add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||||
|
keyActionMapper
|
||||||
|
.getBinding(KEYMAPPINGS.placement.abortBuildingPlacement)
|
||||||
|
.add(this.abortPlacement, this);
|
||||||
|
|
||||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||||
|
|||||||
@ -89,6 +89,16 @@ for (const categoryId in KEYMAPPINGS) {
|
|||||||
*/
|
*/
|
||||||
export function getStringForKeyCode(code) {
|
export function getStringForKeyCode(code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
case 1:
|
||||||
|
return "LMB";
|
||||||
|
case 2:
|
||||||
|
return "MMB";
|
||||||
|
case 3:
|
||||||
|
return "RMB";
|
||||||
|
case 4:
|
||||||
|
return "MB4";
|
||||||
|
case 5:
|
||||||
|
return "MB5";
|
||||||
case 8:
|
case 8:
|
||||||
return "⌫";
|
return "⌫";
|
||||||
case 9:
|
case 9:
|
||||||
|
|||||||
@ -66,11 +66,6 @@ export class GoogleAnalyticsImpl extends AnalyticsInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trackUiClick(elementName) {
|
trackUiClick(elementName) {
|
||||||
// Only track a fraction of clicks to not annoy google analytics
|
|
||||||
if (Math_random() < 0.9) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const stateKey = this.app.stateMgr.getCurrentState().key;
|
const stateKey = this.app.stateMgr.getCurrentState().key;
|
||||||
const fullSelector = stateKey + ">" + elementName;
|
const fullSelector = stateKey + ">" + elementName;
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { createLogger } from "../core/logging";
|
|||||||
import { ExplainedResult } from "../core/explained_result";
|
import { ExplainedResult } from "../core/explained_result";
|
||||||
import { THEMES, THEME, applyGameTheme } from "../game/theme";
|
import { THEMES, THEME, applyGameTheme } from "../game/theme";
|
||||||
import { IS_DEMO } from "../core/config";
|
import { IS_DEMO } from "../core/config";
|
||||||
|
import { T } from "../translations";
|
||||||
|
|
||||||
const logger = createLogger("application_settings");
|
const logger = createLogger("application_settings");
|
||||||
|
|
||||||
@ -18,27 +19,45 @@ export const uiScales = [
|
|||||||
{
|
{
|
||||||
id: "super_small",
|
id: "super_small",
|
||||||
size: 0.6,
|
size: 0.6,
|
||||||
label: "Super small",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "small",
|
id: "small",
|
||||||
size: 0.8,
|
size: 0.8,
|
||||||
label: "Small",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "regular",
|
id: "regular",
|
||||||
size: 1,
|
size: 1,
|
||||||
label: "Regular",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "large",
|
id: "large",
|
||||||
size: 1.2,
|
size: 1.2,
|
||||||
label: "Large",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "huge",
|
id: "huge",
|
||||||
size: 1.4,
|
size: 1.4,
|
||||||
label: "Huge",
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const scrollWheelSensitivities = [
|
||||||
|
{
|
||||||
|
id: "super_slow",
|
||||||
|
scale: 0.25,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "slow",
|
||||||
|
scale: 0.5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "regular",
|
||||||
|
scale: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "fast",
|
||||||
|
scale: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "super_fast",
|
||||||
|
scale: 4,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -47,7 +66,7 @@ export const allApplicationSettings = [
|
|||||||
new EnumSetting("uiScale", {
|
new EnumSetting("uiScale", {
|
||||||
options: uiScales.sort((a, b) => a.size - b.size),
|
options: uiScales.sort((a, b) => a.size - b.size),
|
||||||
valueGetter: scale => scale.id,
|
valueGetter: scale => scale.id,
|
||||||
textGetter: scale => scale.label,
|
textGetter: scale => T.settings.labels.uiScale.scales[scale.id],
|
||||||
category: categoryApp,
|
category: categoryApp,
|
||||||
restartRequired: false,
|
restartRequired: false,
|
||||||
changeCb:
|
changeCb:
|
||||||
@ -56,6 +75,7 @@ export const allApplicationSettings = [
|
|||||||
*/
|
*/
|
||||||
(app, id) => app.updateAfterUiScaleChanged(),
|
(app, id) => app.updateAfterUiScaleChanged(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new BoolSetting(
|
new BoolSetting(
|
||||||
"fullscreen",
|
"fullscreen",
|
||||||
categoryApp,
|
categoryApp,
|
||||||
@ -86,6 +106,18 @@ export const allApplicationSettings = [
|
|||||||
*/
|
*/
|
||||||
(app, value) => app.sound.setMusicMuted(value)
|
(app, value) => app.sound.setMusicMuted(value)
|
||||||
),
|
),
|
||||||
|
new EnumSetting("scrollWheelSensitivity", {
|
||||||
|
options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale),
|
||||||
|
valueGetter: scale => scale.id,
|
||||||
|
textGetter: scale => T.settings.labels.scrollWheelSensitivity.sensitivity[scale.id],
|
||||||
|
category: categoryApp,
|
||||||
|
restartRequired: false,
|
||||||
|
changeCb:
|
||||||
|
/**
|
||||||
|
* @param {Application} app
|
||||||
|
*/
|
||||||
|
(app, id) => app.updateAfterUiScaleChanged(),
|
||||||
|
}),
|
||||||
|
|
||||||
// GAME
|
// GAME
|
||||||
new EnumSetting("theme", {
|
new EnumSetting("theme", {
|
||||||
@ -133,6 +165,7 @@ class SettingsStorage {
|
|||||||
this.musicMuted = false;
|
this.musicMuted = false;
|
||||||
this.theme = "light";
|
this.theme = "light";
|
||||||
this.refreshRate = "60";
|
this.refreshRate = "60";
|
||||||
|
this.scrollWheelSensitivity = "regular";
|
||||||
|
|
||||||
this.alwaysMultiplace = false;
|
this.alwaysMultiplace = false;
|
||||||
this.abortPlacementOnDeletion = true;
|
this.abortPlacementOnDeletion = true;
|
||||||
@ -209,6 +242,17 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScrollWheelSensitivity() {
|
||||||
|
const id = this.getAllSettings().scrollWheelSensitivity;
|
||||||
|
for (let i = 0; i < scrollWheelSensitivities.length; ++i) {
|
||||||
|
if (scrollWheelSensitivities[i].id === id) {
|
||||||
|
return scrollWheelSensitivities[i].scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.error("Unknown scroll wheel sensitivity id:", id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
getIsFullScreen() {
|
getIsFullScreen() {
|
||||||
return this.getAllSettings().fullscreen;
|
return this.getAllSettings().fullscreen;
|
||||||
}
|
}
|
||||||
@ -295,7 +339,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return 8;
|
return 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {{settings: SettingsStorage, version: number}} data */
|
/** @param {{settings: SettingsStorage, version: number}} data */
|
||||||
@ -318,10 +362,15 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.version < 8) {
|
if (data.version < 8) {
|
||||||
data.settings.abortPlacementOnDeletion = true;
|
data.settings.scrollWheelSensitivity = "regular";
|
||||||
data.version = 8;
|
data.version = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.version < 9) {
|
||||||
|
data.settings.abortPlacementOnDeletion = true;
|
||||||
|
data.version = 9;
|
||||||
|
}
|
||||||
|
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,9 @@ import { BaseSavegameInterface } from "./savegame_interface";
|
|||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { SavegameInterface_V1000 } from "./schemas/1000";
|
import { SavegameInterface_V1000 } from "./schemas/1000";
|
||||||
import { getSavegameInterface } from "./savegame_interface_registry";
|
import { getSavegameInterface, savegameInterfaces } from "./savegame_interface_registry";
|
||||||
import { SavegameInterface_V1001 } from "./schemas/1001";
|
import { SavegameInterface_V1001 } from "./schemas/1001";
|
||||||
|
import { SavegameInterface_V1002 } from "./schemas/1002";
|
||||||
|
|
||||||
const logger = createLogger("savegame");
|
const logger = createLogger("savegame");
|
||||||
|
|
||||||
@ -30,6 +31,11 @@ export class Savegame extends ReadWriteProxy {
|
|||||||
|
|
||||||
/** @type {import("./savegame_typedefs").SavegameData} */
|
/** @type {import("./savegame_typedefs").SavegameData} */
|
||||||
this.currentData = this.getDefaultData();
|
this.currentData = this.getDefaultData();
|
||||||
|
|
||||||
|
assert(
|
||||||
|
savegameInterfaces[Savegame.getCurrentVersion()],
|
||||||
|
"Savegame interface not defined: " + Savegame.getCurrentVersion()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////// RW Proxy Impl //////////
|
//////// RW Proxy Impl //////////
|
||||||
@ -38,14 +44,14 @@ export class Savegame extends ReadWriteProxy {
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
static getCurrentVersion() {
|
static getCurrentVersion() {
|
||||||
return 1001;
|
return 1002;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {typeof BaseSavegameInterface}
|
* @returns {typeof BaseSavegameInterface}
|
||||||
*/
|
*/
|
||||||
static getReaderClass() {
|
static getReaderClass() {
|
||||||
return SavegameInterface_V1001;
|
return savegameInterfaces[Savegame.getCurrentVersion()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,6 +88,11 @@ export class Savegame extends ReadWriteProxy {
|
|||||||
data.version = 1001;
|
data.version = 1001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.version === 1001) {
|
||||||
|
SavegameInterface_V1002.migrate1001to1002(data);
|
||||||
|
data.version = 1002;
|
||||||
|
}
|
||||||
|
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,13 @@ import { BaseSavegameInterface } from "./savegame_interface";
|
|||||||
import { SavegameInterface_V1000 } from "./schemas/1000";
|
import { SavegameInterface_V1000 } from "./schemas/1000";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { SavegameInterface_V1001 } from "./schemas/1001";
|
import { SavegameInterface_V1001 } from "./schemas/1001";
|
||||||
|
import { SavegameInterface_V1002 } from "./schemas/1002";
|
||||||
|
|
||||||
/** @type {Object.<number, typeof BaseSavegameInterface>} */
|
/** @type {Object.<number, typeof BaseSavegameInterface>} */
|
||||||
const interfaces = {
|
export const savegameInterfaces = {
|
||||||
1000: SavegameInterface_V1000,
|
1000: SavegameInterface_V1000,
|
||||||
1001: SavegameInterface_V1001,
|
1001: SavegameInterface_V1001,
|
||||||
|
1002: SavegameInterface_V1002,
|
||||||
};
|
};
|
||||||
|
|
||||||
const logger = createLogger("savegame_interface_registry");
|
const logger = createLogger("savegame_interface_registry");
|
||||||
@ -27,7 +29,7 @@ export function getSavegameInterface(savegame) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const interfaceClass = interfaces[version];
|
const interfaceClass = savegameInterfaces[version];
|
||||||
if (!interfaceClass) {
|
if (!interfaceClass) {
|
||||||
logger.warn("Version", version, "has no implemented interface!");
|
logger.warn("Version", version, "has no implemented interface!");
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
37
src/js/savegame/schemas/1002.js
Normal file
37
src/js/savegame/schemas/1002.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { createLogger } from "../../core/logging.js";
|
||||||
|
import { T } from "../../translations.js";
|
||||||
|
import { SavegameInterface_V1001 } from "./1001.js";
|
||||||
|
|
||||||
|
const schema = require("./1002.json");
|
||||||
|
const logger = createLogger("savegame_interface/1002");
|
||||||
|
|
||||||
|
export class SavegameInterface_V1002 extends SavegameInterface_V1001 {
|
||||||
|
getVersion() {
|
||||||
|
return 1002;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSchemaUncached() {
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../savegame_typedefs.js").SavegameData} data
|
||||||
|
*/
|
||||||
|
static migrate1001to1002(data) {
|
||||||
|
logger.log("Migrating 1001 to 1002");
|
||||||
|
const dump = data.dump;
|
||||||
|
if (!dump) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entities = dump.entities;
|
||||||
|
for (let i = 0; i < entities.length; ++i) {
|
||||||
|
const entity = entities[i];
|
||||||
|
const beltComp = entity.components.Belt;
|
||||||
|
const ejectorComp = entity.components.ItemEjector;
|
||||||
|
if (beltComp && ejectorComp) {
|
||||||
|
ejectorComp.instantEject = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/js/savegame/schemas/1002.json
Normal file
5
src/js/savegame/schemas/1002.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [],
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
@ -105,6 +105,10 @@ export class KeybindingsState extends TextualGameState {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
// Enter
|
// Enter
|
||||||
keyCode === 13 ||
|
keyCode === 13 ||
|
||||||
@ -122,8 +126,8 @@ export class KeybindingsState extends TextualGameState {
|
|||||||
});
|
});
|
||||||
|
|
||||||
dialog.inputReciever.backButton.add(() => {});
|
dialog.inputReciever.backButton.add(() => {});
|
||||||
|
|
||||||
this.dialogs.internalShowDialog(dialog);
|
this.dialogs.internalShowDialog(dialog);
|
||||||
|
|
||||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,13 @@ global:
|
|||||||
# How big numbers are rendered, e.g. "10,000"
|
# How big numbers are rendered, e.g. "10,000"
|
||||||
thousandsDivider: ","
|
thousandsDivider: ","
|
||||||
|
|
||||||
|
# The suffix for large numbers, e.g. 1.3k, 400.2M, etc.
|
||||||
|
suffix:
|
||||||
|
thousands: k
|
||||||
|
millions: M
|
||||||
|
billions: B
|
||||||
|
trillions: T
|
||||||
|
|
||||||
# Shown for infinitely big numbers
|
# Shown for infinitely big numbers
|
||||||
infinite: inf
|
infinite: inf
|
||||||
|
|
||||||
@ -127,7 +134,7 @@ dialogs:
|
|||||||
|
|
||||||
editKeybinding:
|
editKeybinding:
|
||||||
title: Change Keybinding
|
title: Change Keybinding
|
||||||
desc: Press the key you want to assign, or escape to cancel.
|
desc: Press the key or mouse button you want to assign, or escape to cancel.
|
||||||
|
|
||||||
resetKeybindingsConfirmation:
|
resetKeybindingsConfirmation:
|
||||||
title: Reset keybindings
|
title: Reset keybindings
|
||||||
@ -511,6 +518,23 @@ settings:
|
|||||||
title: Interface scale
|
title: Interface scale
|
||||||
description: >-
|
description: >-
|
||||||
Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale.
|
Changes the size of the user interface. The interface will still scale based on your device resolution, but this setting controls the amount of scale.
|
||||||
|
scales:
|
||||||
|
super_small: Super small
|
||||||
|
small: Small
|
||||||
|
regular: Regular
|
||||||
|
large: Large
|
||||||
|
huge: Huge
|
||||||
|
|
||||||
|
scrollWheelSensitivity:
|
||||||
|
title: Zoom sensitivity
|
||||||
|
description: >-
|
||||||
|
Changes how sensitive the zoom is (Either mouse wheel or trackpad).
|
||||||
|
sensitivity:
|
||||||
|
super_slow: Super slow
|
||||||
|
slow: Slow
|
||||||
|
regular: Regular
|
||||||
|
fast: Fast
|
||||||
|
super_fast: Super fast
|
||||||
|
|
||||||
fullscreen:
|
fullscreen:
|
||||||
title: Fullscreen
|
title: Fullscreen
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user