mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-07 10:03:59 +00:00
Properly implement sound and music volumes, debounce writes
This commit is contained in:
parent
50e40888fd
commit
6042fcba62
@ -36,6 +36,7 @@
|
|||||||
"core-js": "3",
|
"core-js": "3",
|
||||||
"crc": "^3.8.0",
|
"crc": "^3.8.0",
|
||||||
"cssnano-preset-advanced": "^4.0.7",
|
"cssnano-preset-advanced": "^4.0.7",
|
||||||
|
"debounce-promise": "^3.1.2",
|
||||||
"email-validator": "^2.0.4",
|
"email-validator": "^2.0.4",
|
||||||
"eslint": "7.1.0",
|
"eslint": "7.1.0",
|
||||||
"fastdom": "^1.0.8",
|
"fastdom": "^1.0.8",
|
||||||
|
@ -351,12 +351,12 @@ canvas {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pressed {
|
.pressed:not(.noPressEffect) {
|
||||||
transform: scale(0.98) !important;
|
transform: scale(0.98) !important;
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pressedSmallElement {
|
.pressedSmallElement:not(.noPressEffect) {
|
||||||
transform: scale(0.88) !important;
|
transform: scale(0.88) !important;
|
||||||
animation: none !important;
|
animation: none !important;
|
||||||
}
|
}
|
||||||
@ -570,36 +570,46 @@ canvas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.range {
|
.rangeInputContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
label {
|
||||||
|
@include S(margin-right, 5px);
|
||||||
|
&,
|
||||||
|
& * {
|
||||||
|
@include PlainText;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.range-input {
|
input.rangeInput {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
width: 100px;
|
@include S(width, 100px);
|
||||||
height: 10px;
|
@include S(height, 16px);
|
||||||
transform: translate(7px, 2px);
|
|
||||||
&::-webkit-slider-runnable-track {
|
&::-webkit-slider-runnable-track {
|
||||||
background-color: darken($mainBgColor, 3);
|
background-color: darken($mainBgColor, 3);
|
||||||
color: darken($mainBgColor, 3);
|
color: darken($mainBgColor, 3);
|
||||||
height: 16px;
|
// @include S(height, 16px);
|
||||||
border-radius: 8px;
|
@include S(border-radius, 8px);
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
box-shadow: inset 0 0 0 10px $themeColor;
|
box-shadow: inset 0 0 0 D(10px) $themeColor;
|
||||||
background-color: transparent;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transition: 0.3s;
|
|
||||||
|
transition: box-shadow 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
box-shadow: inset 0 0 0 D(10px) lighten($themeColor, 15);
|
||||||
}
|
}
|
||||||
&:hover::-webkit-slider-thumb {
|
|
||||||
box-shadow: inset 0 0 0 10px lighten($themeColor, 15);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,19 +34,6 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
&.music {
|
|
||||||
background-image: uiResource("icons/music_on.png");
|
|
||||||
&.muted {
|
|
||||||
background-image: uiResource("icons/music_off.png");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.sfx {
|
|
||||||
background-image: uiResource("icons/sound_on.png");
|
|
||||||
&.muted {
|
|
||||||
background-image: uiResource("icons/sound_off.png");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.save {
|
&.save {
|
||||||
background-image: uiResource("icons/save.png");
|
background-image: uiResource("icons/save.png");
|
||||||
|
@ -22,11 +22,6 @@
|
|||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
@include S(margin-bottom, 5px);
|
@include S(margin-bottom, 5px);
|
||||||
|
|
||||||
label {
|
|
||||||
text-transform: uppercase;
|
|
||||||
@include Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desc {
|
.desc {
|
||||||
@include S(margin-top, 5px);
|
@include S(margin-top, 5px);
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
@ -37,6 +32,11 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
text-transform: uppercase;
|
||||||
|
@include Text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
|
@ -18,6 +18,7 @@ export const CHANGELOG = [
|
|||||||
"Tier 2 tunnels are now 9 tiles wide, so the gap between is 8 tiles (double the tier 1 range)",
|
"Tier 2 tunnels are now 9 tiles wide, so the gap between is 8 tiles (double the tier 1 range)",
|
||||||
"Updated and added new translations (Thanks to all contributors!)",
|
"Updated and added new translations (Thanks to all contributors!)",
|
||||||
"Added setting to be able to delete buildings while placing (inspired by hexy)",
|
"Added setting to be able to delete buildings while placing (inspired by hexy)",
|
||||||
|
"You can now adjust the sound and music volumes! (inspired by Yoshie2000)",
|
||||||
"Mark pinned shapes in statistics dialog and show them first (inspired by davidburhans)",
|
"Mark pinned shapes in statistics dialog and show them first (inspired by davidburhans)",
|
||||||
"Added setting to show chunk borders",
|
"Added setting to show chunk borders",
|
||||||
"Quad painters have been reworked! They now are integrated with the wires, and only paint the shape when the value is 1 (inspired by dengr1605)",
|
"Quad painters have been reworked! They now are integrated with the wires, and only paint the shape when the value is 1 (inspired by dengr1605)",
|
||||||
|
@ -12,6 +12,8 @@ import { decompressX64, compressX64 } from "./lzstring";
|
|||||||
import { asyncCompressor, compressionPrefix } from "./async_compression";
|
import { asyncCompressor, compressionPrefix } from "./async_compression";
|
||||||
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
|
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
|
||||||
|
|
||||||
|
const debounce = require("debounce-promise");
|
||||||
|
|
||||||
const logger = createLogger("read_write_proxy");
|
const logger = createLogger("read_write_proxy");
|
||||||
|
|
||||||
const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
||||||
@ -36,6 +38,11 @@ export class ReadWriteProxy {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a debounced handler to prevent double writes
|
||||||
|
*/
|
||||||
|
this.debouncedWrite = debounce(this.doWriteAsync.bind(this), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Methods to override
|
// -- Methods to override
|
||||||
@ -122,7 +129,8 @@ export class ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the data asychronously, fails if verify() fails
|
* Writes the data asychronously, fails if verify() fails.
|
||||||
|
* Debounces the operation by up to 50ms
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
writeAsync() {
|
writeAsync() {
|
||||||
@ -133,6 +141,14 @@ export class ReadWriteProxy {
|
|||||||
return Promise.reject(verifyResult.reason);
|
return Promise.reject(verifyResult.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.debouncedWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually writes the data asychronously
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
doWriteAsync() {
|
||||||
return asyncCompressor
|
return asyncCompressor
|
||||||
.compressObjectAsync(this.currentData)
|
.compressObjectAsync(this.currentData)
|
||||||
.then(compressed => {
|
.then(compressed => {
|
||||||
|
@ -88,19 +88,13 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
|
|
||||||
const menuButtons = makeDiv(this.element, null, ["menuButtons"]);
|
const menuButtons = makeDiv(this.element, null, ["menuButtons"]);
|
||||||
|
|
||||||
this.musicButton = makeDiv(menuButtons, null, ["button", "music"]);
|
|
||||||
this.sfxButton = makeDiv(menuButtons, null, ["button", "sfx"]);
|
|
||||||
this.saveButton = makeDiv(menuButtons, null, ["button", "save", "animEven"]);
|
this.saveButton = makeDiv(menuButtons, null, ["button", "save", "animEven"]);
|
||||||
this.settingsButton = makeDiv(menuButtons, null, ["button", "settings"]);
|
this.settingsButton = makeDiv(menuButtons, null, ["button", "settings"]);
|
||||||
|
|
||||||
this.trackClicks(this.musicButton, this.toggleMusic);
|
|
||||||
this.trackClicks(this.sfxButton, this.toggleSfx);
|
|
||||||
this.trackClicks(this.saveButton, this.startSave);
|
this.trackClicks(this.saveButton, this.startSave);
|
||||||
this.trackClicks(this.settingsButton, this.openSettings);
|
this.trackClicks(this.settingsButton, this.openSettings);
|
||||||
|
|
||||||
this.musicButton.classList.toggle("muted", this.root.app.settings.getAllSettings().musicMuted);
|
|
||||||
this.sfxButton.classList.toggle("muted", this.root.app.settings.getAllSettings().soundsMuted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
this.root.signals.gameSaved.add(this.onGameSaved, this);
|
||||||
}
|
}
|
||||||
@ -111,7 +105,7 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
|
|
||||||
// Update visibility of buttons
|
// Update visibility of buttons
|
||||||
for (let i = 0; i < this.visibilityToUpdate.length; ++i) {
|
for (let i = 0; i < this.visibilityToUpdate.length; ++i) {
|
||||||
const { button, condition, domAttach } = this.visibilityToUpdate[i];
|
const { condition, domAttach } = this.visibilityToUpdate[i];
|
||||||
domAttach.update(condition());
|
domAttach.update(condition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,17 +166,4 @@ export class HUDGameMenu extends BaseHUDPart {
|
|||||||
openSettings() {
|
openSettings() {
|
||||||
this.root.hud.parts.settingsMenu.show();
|
this.root.hud.parts.settingsMenu.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleMusic() {
|
|
||||||
const newValue = !this.root.app.settings.getAllSettings().musicMuted;
|
|
||||||
this.root.app.settings.updateSetting("musicMuted", newValue);
|
|
||||||
|
|
||||||
this.musicButton.classList.toggle("muted", newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSfx() {
|
|
||||||
const newValue = !this.root.app.settings.getAllSettings().soundsMuted;
|
|
||||||
this.root.app.settings.updateSetting("soundsMuted", newValue);
|
|
||||||
this.sfxButton.classList.toggle("muted", newValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,9 @@ export class SoundImplBrowser extends SoundInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
|
// NOTICE: We override the initialize() method here with custom logic because
|
||||||
|
// we have a sound sprites instance
|
||||||
|
|
||||||
this.sfxHandle = new SoundSpritesContainer();
|
this.sfxHandle = new SoundSpritesContainer();
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -198,11 +201,11 @@ export class SoundImplBrowser extends SoundInterface {
|
|||||||
this.music[musicPath] = music;
|
this.music[musicPath] = music;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.musicMuted = this.app.settings.getAllSettings().musicMuted;
|
this.musicVolume = this.app.settings.getAllSettings().musicVolume;
|
||||||
this.soundsMuted = this.app.settings.getAllSettings().soundsMuted;
|
this.soundVolume = this.app.settings.getAllSettings().soundVolume;
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.disableMusic) {
|
if (G_IS_DEV && globalConfig.debug.disableMusic) {
|
||||||
this.musicMuted = true;
|
this.musicVolume = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
@ -103,9 +103,6 @@ export class SoundInterface {
|
|||||||
|
|
||||||
this.pageIsVisible = true;
|
this.pageIsVisible = true;
|
||||||
|
|
||||||
this.musicMuted = false;
|
|
||||||
this.soundsMuted = false;
|
|
||||||
|
|
||||||
this.musicVolume = 1.0;
|
this.musicVolume = 1.0;
|
||||||
this.soundVolume = 1.0;
|
this.soundVolume = 1.0;
|
||||||
}
|
}
|
||||||
@ -127,13 +124,11 @@ export class SoundInterface {
|
|||||||
this.music[musicPath] = music;
|
this.music[musicPath] = music;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.musicMuted = this.app.settings.getAllSettings().musicMuted;
|
|
||||||
this.soundsMuted = this.app.settings.getAllSettings().soundsMuted;
|
|
||||||
this.musicVolume = this.app.settings.getAllSettings().musicVolume;
|
this.musicVolume = this.app.settings.getAllSettings().musicVolume;
|
||||||
this.soundVolume = this.app.settings.getAllSettings().soundVolume;
|
this.soundVolume = this.app.settings.getAllSettings().soundVolume;
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.disableMusic) {
|
if (G_IS_DEV && globalConfig.debug.disableMusic) {
|
||||||
this.musicMuted = true;
|
this.musicVolume = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@ -170,47 +165,6 @@ export class SoundInterface {
|
|||||||
return Promise.all(...promises);
|
return Promise.all(...promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the music is muted
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
getMusicMuted() {
|
|
||||||
return this.musicMuted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if sounds are muted
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
getSoundsMuted() {
|
|
||||||
return this.soundsMuted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if the music is muted
|
|
||||||
* @param {boolean} muted
|
|
||||||
*/
|
|
||||||
setMusicMuted(muted) {
|
|
||||||
this.musicMuted = muted;
|
|
||||||
if (this.musicMuted) {
|
|
||||||
if (this.currentMusic) {
|
|
||||||
this.currentMusic.stop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.currentMusic) {
|
|
||||||
this.currentMusic.play(this.musicVolume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if the sounds are muted
|
|
||||||
* @param {boolean} muted
|
|
||||||
*/
|
|
||||||
setSoundsMuted(muted) {
|
|
||||||
this.soundsMuted = muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the music volume
|
* Returns the music volume
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
@ -254,7 +208,7 @@ export class SoundInterface {
|
|||||||
this.pageIsVisible = pageIsVisible;
|
this.pageIsVisible = pageIsVisible;
|
||||||
if (this.currentMusic) {
|
if (this.currentMusic) {
|
||||||
if (pageIsVisible) {
|
if (pageIsVisible) {
|
||||||
if (!this.currentMusic.isPlaying() && !this.musicMuted) {
|
if (!this.currentMusic.isPlaying()) {
|
||||||
this.currentMusic.play(this.musicVolume);
|
this.currentMusic.play(this.musicVolume);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -267,9 +221,6 @@ export class SoundInterface {
|
|||||||
* @param {string} key
|
* @param {string} key
|
||||||
*/
|
*/
|
||||||
playUiSound(key) {
|
playUiSound(key) {
|
||||||
if (this.soundsMuted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.sounds[key]) {
|
if (!this.sounds[key]) {
|
||||||
logger.warn("Sound", key, "not found, probably not loaded yet");
|
logger.warn("Sound", key, "not found, probably not loaded yet");
|
||||||
return;
|
return;
|
||||||
@ -288,7 +239,7 @@ export class SoundInterface {
|
|||||||
logger.warn("Music", key, "not found, probably not loaded yet");
|
logger.warn("Music", key, "not found, probably not loaded yet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.pageIsVisible || this.soundsMuted) {
|
if (!this.pageIsVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +270,7 @@ export class SoundInterface {
|
|||||||
this.currentMusic.stop();
|
this.currentMusic.stop();
|
||||||
}
|
}
|
||||||
this.currentMusic = music;
|
this.currentMusic = music;
|
||||||
if (music && this.pageIsVisible && !this.musicMuted) {
|
if (music && this.pageIsVisible) {
|
||||||
logger.log("Starting", this.currentMusic.key);
|
logger.log("Starting", this.currentMusic.key);
|
||||||
music.play(this.musicVolume);
|
music.play(this.musicVolume);
|
||||||
}
|
}
|
||||||
|
@ -159,29 +159,13 @@ export const allApplicationSettings = [
|
|||||||
(app, id) => app.updateAfterUiScaleChanged(),
|
(app, id) => app.updateAfterUiScaleChanged(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new BoolSetting(
|
|
||||||
"soundsMuted",
|
|
||||||
enumCategories.general,
|
|
||||||
/**
|
|
||||||
* @param {Application} app
|
|
||||||
*/
|
|
||||||
(app, value) => app.sound.setSoundsMuted(value)
|
|
||||||
),
|
|
||||||
new RangeSetting(
|
new RangeSetting(
|
||||||
"soundVolume",
|
"soundVolume",
|
||||||
enumCategories.general,
|
enumCategories.general,
|
||||||
/**
|
/**
|
||||||
* @param {Application} app
|
* @param {Application} app
|
||||||
*/
|
*/
|
||||||
(app, value) => app.sound.setSoundVolume(value / 100.0)
|
(app, value) => app.sound.setSoundVolume(value)
|
||||||
),
|
|
||||||
new BoolSetting(
|
|
||||||
"musicMuted",
|
|
||||||
enumCategories.general,
|
|
||||||
/**
|
|
||||||
* @param {Application} app
|
|
||||||
*/
|
|
||||||
(app, value) => app.sound.setMusicMuted(value)
|
|
||||||
),
|
),
|
||||||
new RangeSetting(
|
new RangeSetting(
|
||||||
"musicVolume",
|
"musicVolume",
|
||||||
@ -189,7 +173,7 @@ export const allApplicationSettings = [
|
|||||||
/**
|
/**
|
||||||
* @param {Application} app
|
* @param {Application} app
|
||||||
*/
|
*/
|
||||||
(app, value) => app.sound.setMusicVolume(value / 100.0)
|
(app, value) => app.sound.setMusicVolume(value)
|
||||||
),
|
),
|
||||||
|
|
||||||
new BoolSetting(
|
new BoolSetting(
|
||||||
@ -302,8 +286,6 @@ class SettingsStorage {
|
|||||||
this.uiScale = "regular";
|
this.uiScale = "regular";
|
||||||
this.fullscreen = G_IS_STANDALONE;
|
this.fullscreen = G_IS_STANDALONE;
|
||||||
|
|
||||||
this.soundsMuted = false;
|
|
||||||
this.musicMuted = false;
|
|
||||||
this.soundVolume = 1.0;
|
this.soundVolume = 1.0;
|
||||||
this.musicVolume = 1.0;
|
this.musicVolume = 1.0;
|
||||||
|
|
||||||
@ -515,7 +497,17 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
const setting = allApplicationSettings[i];
|
const setting = allApplicationSettings[i];
|
||||||
const storedValue = settings[setting.id];
|
const storedValue = settings[setting.id];
|
||||||
if (!setting.validate(storedValue)) {
|
if (!setting.validate(storedValue)) {
|
||||||
return ExplainedResult.bad("Bad setting value for " + setting.id + ": " + storedValue);
|
return ExplainedResult.bad(
|
||||||
|
"Bad setting value for " +
|
||||||
|
setting.id +
|
||||||
|
": " +
|
||||||
|
storedValue +
|
||||||
|
" @ settings version " +
|
||||||
|
data.version +
|
||||||
|
" (latest is " +
|
||||||
|
this.getCurrentVersion() +
|
||||||
|
")"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
@ -529,7 +521,7 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurrentVersion() {
|
getCurrentVersion() {
|
||||||
return 24;
|
return 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {{settings: SettingsStorage, version: number}} data */
|
/** @param {{settings: SettingsStorage, version: number}} data */
|
||||||
@ -633,12 +625,21 @@ export class ApplicationSettings extends ReadWriteProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.version < 24) {
|
if (data.version < 24) {
|
||||||
data.settings.musicVolume = 1.0;
|
|
||||||
data.settings.soundVolume = 1.0;
|
|
||||||
data.settings.refreshRate = "60";
|
data.settings.refreshRate = "60";
|
||||||
data.version = 24;
|
data.version = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.version < 25) {
|
||||||
|
data.settings.musicVolume = 0.5;
|
||||||
|
data.settings.soundVolume = 0.5;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
delete data.settings.musicMuted;
|
||||||
|
// @ts-ignore
|
||||||
|
delete data.settings.soundsMuted;
|
||||||
|
data.version = 25;
|
||||||
|
}
|
||||||
|
|
||||||
return ExplainedResult.good();
|
return ExplainedResult.good();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,10 +227,10 @@ export class RangeSetting extends BaseSetting {
|
|||||||
category,
|
category,
|
||||||
changeCb = null,
|
changeCb = null,
|
||||||
enabled = true,
|
enabled = true,
|
||||||
defaultValue = 100,
|
defaultValue = 1.0,
|
||||||
minValue = 0,
|
minValue = 0,
|
||||||
maxValue = 100,
|
maxValue = 1.0,
|
||||||
stepSize = 1
|
stepSize = 0.0001
|
||||||
) {
|
) {
|
||||||
super(id, category, changeCb, enabled);
|
super(id, category, changeCb, enabled);
|
||||||
|
|
||||||
@ -247,9 +247,9 @@ export class RangeSetting extends BaseSetting {
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>${T.settings.labels[this.id].title}</label>
|
<label>${T.settings.labels[this.id].title}</label>
|
||||||
<div class="value range" data-setting="${this.id}">
|
<div class="value rangeInputContainer noPressEffect" data-setting="${this.id}">
|
||||||
<label class="range-label">${this.defaultValue}</label>
|
<label>${this.defaultValue}</label>
|
||||||
<input class="range-input" type="range" value="${this.defaultValue}" min="${
|
<input class="rangeInput" type="range" value="${this.defaultValue}" min="${
|
||||||
this.minValue
|
this.minValue
|
||||||
}" max="${this.maxValue}" step="${this.stepSize}">
|
}" max="${this.maxValue}" step="${this.stepSize}">
|
||||||
</div>
|
</div>
|
||||||
@ -265,33 +265,58 @@ export class RangeSetting extends BaseSetting {
|
|||||||
this.element = element;
|
this.element = element;
|
||||||
this.dialogs = dialogs;
|
this.dialogs = dialogs;
|
||||||
|
|
||||||
this.element.querySelector(".range-input").addEventListener("input", () => {
|
this.getRangeInputElement().addEventListener("input", () => {
|
||||||
|
this.updateLabels();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.getRangeInputElement().addEventListener("change", () => {
|
||||||
this.modify();
|
this.modify();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
syncValueToElement() {
|
syncValueToElement() {
|
||||||
const value = this.app.settings.getSetting(this.id);
|
const value = this.app.settings.getSetting(this.id);
|
||||||
/** @type {HTMLInputElement} */
|
this.setElementValue(value);
|
||||||
const rangeInput = this.element.querySelector(".range-input"),
|
}
|
||||||
rangeLabel = this.element.querySelector(".range-label");
|
|
||||||
rangeInput.value = value;
|
/**
|
||||||
rangeLabel.innerHTML = value;
|
* Sets the elements value to the given value
|
||||||
|
* @param {number} value
|
||||||
|
*/
|
||||||
|
setElementValue(value) {
|
||||||
|
const rangeInput = this.getRangeInputElement();
|
||||||
|
const rangeLabel = this.element.querySelector("label");
|
||||||
|
rangeInput.value = String(value);
|
||||||
|
rangeLabel.innerHTML = T.settings.rangeSliderPercentage.replace(
|
||||||
|
"<amount>",
|
||||||
|
String(Math.round(value * 100.0))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLabels() {
|
||||||
|
const value = Number(this.getRangeInputElement().value);
|
||||||
|
this.setElementValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {HTMLInputElement}
|
||||||
|
*/
|
||||||
|
getRangeInputElement() {
|
||||||
|
return this.element.querySelector("input.rangeInput");
|
||||||
}
|
}
|
||||||
|
|
||||||
modify() {
|
modify() {
|
||||||
/** @type {HTMLInputElement} */
|
const rangeInput = this.getRangeInputElement();
|
||||||
const rangeInput = this.element.querySelector(".range-input");
|
const newValue = Math.round(Number(rangeInput.value) * 100.0) / 100.0;
|
||||||
const newValue = Number(rangeInput.value);
|
|
||||||
this.app.settings.updateSetting(this.id, newValue);
|
this.app.settings.updateSetting(this.id, newValue);
|
||||||
this.syncValueToElement();
|
this.syncValueToElement();
|
||||||
|
console.log("SET", newValue);
|
||||||
if (this.changeCb) {
|
if (this.changeCb) {
|
||||||
this.changeCb(this.app, newValue);
|
this.changeCb(this.app, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(value) {
|
validate(value) {
|
||||||
return typeof value === "number";
|
return typeof value === "number" && value >= this.minValue && value <= this.maxValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,6 +728,8 @@ settings:
|
|||||||
prod: Production
|
prod: Production
|
||||||
buildDate: Built <at-date>
|
buildDate: Built <at-date>
|
||||||
|
|
||||||
|
rangeSliderPercentage: <amount> %
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
uiScale:
|
uiScale:
|
||||||
title: Interface scale
|
title: Interface scale
|
||||||
|
@ -2740,6 +2740,11 @@ cyclist@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||||
|
|
||||||
|
debounce-promise@^3.1.2:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/debounce-promise/-/debounce-promise-3.1.2.tgz#320fb8c7d15a344455cd33cee5ab63530b6dc7c5"
|
||||||
|
integrity sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
|
Loading…
Reference in New Issue
Block a user