diff --git a/app/src/main/java/org/toop/app/layer/layers/OptionsPopup.java b/app/src/main/java/org/toop/app/layer/layers/OptionsPopup.java index 92ed790..3dcd1d9 100644 --- a/app/src/main/java/org/toop/app/layer/layers/OptionsPopup.java +++ b/app/src/main/java/org/toop/app/layer/layers/OptionsPopup.java @@ -38,6 +38,9 @@ public final class OptionsPopup extends Popup { final var volumeHeader = NodeBuilder.header(AppContext.getString("volume")); final var volumeSeparator = NodeBuilder.separator(); + final var fxVolumeHeader = NodeBuilder.header(AppContext.getString("fxVolume")); + final var fxVolumeSeparator = NodeBuilder.separator(); + final var themeHeader = NodeBuilder.header(AppContext.getString("theme")); final var themeSeparator = NodeBuilder.separator(); @@ -47,6 +50,7 @@ public final class OptionsPopup extends Popup { final var optionsContainer = new VerticalContainer(5); optionsContainer.addNodes(languageHeader, languageChoiceBox(), languageSeparator); optionsContainer.addNodes(volumeHeader, volumeSlider(), volumeSeparator); + optionsContainer.addNodes(fxVolumeHeader, fxVolumeSlider(), fxVolumeSeparator); optionsContainer.addNodes(themeHeader, themeChoiceBox(), themeSeparator); optionsContainer.addNodes(layoutSizeHeader, layoutSizeChoiceBox(), layoutSizeSeparator); optionsContainer.addNodes(fullscreenToggle()); @@ -104,6 +108,14 @@ public final class OptionsPopup extends Popup { }); } + private Slider fxVolumeSlider() { + return NodeBuilder.slider(100, settings.getFxVolume(), (volume) -> { + settings.setFxVolume(volume); + new EventFlow().addPostEvent(new AudioEvents.ChangeFxVolume(volume.doubleValue())).asyncPostEvent(); + }); + } + + private Label fullscreenToggle() { return NodeBuilder.toggle(AppContext.getString("windowed"), AppContext.getString("fullscreen"), !isWindowed, (fullscreen) -> { isWindowed = !fullscreen; diff --git a/app/src/main/resources/assets/localization/localization_ar.properties b/app/src/main/resources/assets/localization/localization_ar.properties index 3c518ce..acf6cfa 100644 --- a/app/src/main/resources/assets/localization/localization_ar.properties +++ b/app/src/main/resources/assets/localization/localization_ar.properties @@ -28,6 +28,7 @@ serverPort=\u0645\u0646\u0641\u0630 \u0627\u0644\u062e\u0627\u062f\u0645 start=\u0627\u0628\u062f\u0623 tictactoe=\u062a\u064a\u0643 \u062a\u0627\u0643 \u062a\u0648 volume=\u0627\u0644\u0635\u0648\u062a +fxVolume=Fx Volume windowed=\u0646\u0627\u0641\u0630\u064a yes=\u0646\u0639\u0645 diff --git a/app/src/main/resources/assets/localization/localization_de.properties b/app/src/main/resources/assets/localization/localization_de.properties index 8bfec8d..0250757 100644 --- a/app/src/main/resources/assets/localization/localization_de.properties +++ b/app/src/main/resources/assets/localization/localization_de.properties @@ -28,6 +28,7 @@ serverPort=Server-Port start=Start tictactoe=Tic Tac Toe volume=Lautst\u00e4rke +fxVolume=Fx Volume windowed=Fenstermodus yes=Ja diff --git a/app/src/main/resources/assets/localization/localization_en.properties b/app/src/main/resources/assets/localization/localization_en.properties index 94475d4..ea59939 100644 --- a/app/src/main/resources/assets/localization/localization_en.properties +++ b/app/src/main/resources/assets/localization/localization_en.properties @@ -28,6 +28,7 @@ serverPort=Server Port start=Start tictactoe=Tic Tac Toe volume=Volume +fxVolume=Fx Volume windowed=Windowed yes=Yes diff --git a/app/src/main/resources/assets/localization/localization_es.properties b/app/src/main/resources/assets/localization/localization_es.properties index 3130c68..953eb96 100644 --- a/app/src/main/resources/assets/localization/localization_es.properties +++ b/app/src/main/resources/assets/localization/localization_es.properties @@ -28,6 +28,7 @@ serverPort=Servidor-puerto start=Iniciar tictactoe=Tres en Raya volume=Volumen +fxVolume=Fx Volume windowed=Ventana yes=S\u00ed diff --git a/app/src/main/resources/assets/localization/localization_fr.properties b/app/src/main/resources/assets/localization/localization_fr.properties index 4b05aee..84a33dc 100644 --- a/app/src/main/resources/assets/localization/localization_fr.properties +++ b/app/src/main/resources/assets/localization/localization_fr.properties @@ -28,6 +28,7 @@ serverPort=Serveur-Port start=D\u00e9marrer tictactoe=Morpion volume=Volume +fxVolume=Fx Volume windowed=Fen\u00eatre yes=Oui diff --git a/app/src/main/resources/assets/localization/localization_hi.properties b/app/src/main/resources/assets/localization/localization_hi.properties index 6e38041..4ed491f 100644 --- a/app/src/main/resources/assets/localization/localization_hi.properties +++ b/app/src/main/resources/assets/localization/localization_hi.properties @@ -29,6 +29,7 @@ serverPort=\u0938\u0930\u094d\u0935\u0930 \u092a\u094b\u0930\u094d\u091f start=\u092b\u093f\u0930\u0942 tictactoe=\u091f\u093f\u0915 \u091f\u0948\u0915 \u091f\u094b volume=\u0935\u0949\u0932\u094d\u092f\u0947\u092e +fxVolume=Fx Volume windowed=\u0915\u094d\u0930\u094d\u0939 \u092e\u0947\u0902 yes=\u0939\u093e\u0907 diff --git a/app/src/main/resources/assets/localization/localization_it.properties b/app/src/main/resources/assets/localization/localization_it.properties index f64710a..abf6801 100644 --- a/app/src/main/resources/assets/localization/localization_it.properties +++ b/app/src/main/resources/assets/localization/localization_it.properties @@ -28,6 +28,7 @@ serverPort=Porta del server start=Inizia tictactoe=Tic Tac Toe volume=Volume +fxVolume=Fx Volume windowed=Finestra yes=S\u00ec diff --git a/app/src/main/resources/assets/localization/localization_ja.properties b/app/src/main/resources/assets/localization/localization_ja.properties index 084a4f4..3e77452 100644 --- a/app/src/main/resources/assets/localization/localization_ja.properties +++ b/app/src/main/resources/assets/localization/localization_ja.properties @@ -28,6 +28,7 @@ serverPort=\u30b5\u30fc\u30d0\u30fc \u30dd\u30fc\u30c8 start=\u59cb\u307e\u308a tictactoe=\u30bf\u30a4\u30af\u30bf\u30c3\u30c8\u30c8\u30a6 volume=\u30dc\u30ea\u30e5\u30fc\u30e0 +fxVolume=Fx Volume windowed=\u30a6\u30a3\u30f3\u30c9\u30a6 yes=\u306f\u3044 diff --git a/app/src/main/resources/assets/localization/localization_ka.properties b/app/src/main/resources/assets/localization/localization_ka.properties index 4efe8e2..7a858d1 100644 --- a/app/src/main/resources/assets/localization/localization_ka.properties +++ b/app/src/main/resources/assets/localization/localization_ka.properties @@ -28,6 +28,7 @@ serverPort=\u10e1\u10d0\u10e0\u10d7\u10d4\u10e0\u10d8 \u10e2\u10dd\u10e0\u10d7\u start=\u10e0\u10d0\u10d3\u10d4\u10e1 tictactoe=\u10e2\u10d8\u10d9\u10d8 \u10e2\u10d8\u10e9\u10d8 \u10e2\u10d8 volume=\u10d7\u10d0\u10e7\u10d8 +fxVolume=Fx Volume windowed=\u10e1\u10d0\u10db\u10d7\u10d8 yes=\u10d3\u10d0 diff --git a/app/src/main/resources/assets/localization/localization_ko.properties b/app/src/main/resources/assets/localization/localization_ko.properties index 614492e..802d670 100644 --- a/app/src/main/resources/assets/localization/localization_ko.properties +++ b/app/src/main/resources/assets/localization/localization_ko.properties @@ -28,6 +28,7 @@ serverPort=\uc11c\ubc84 \ud3ec\ud2b8 start=\uc2dc\uc791 tictactoe=\ud2f0\ud06c\ud0d0\ud1a0 volume=\ubcf4\ub7ec\uc6b4 +fxVolume=Fx Volume windowed=\ucc3d \ubaa8\ub4dc yes=\ub124 diff --git a/app/src/main/resources/assets/localization/localization_nl.properties b/app/src/main/resources/assets/localization/localization_nl.properties index bd92a66..f1ae2ad 100644 --- a/app/src/main/resources/assets/localization/localization_nl.properties +++ b/app/src/main/resources/assets/localization/localization_nl.properties @@ -28,6 +28,7 @@ serverPort=Serverpoort start=Start tictactoe=Boter Kaas en Eieren volume=Volume +fxVolume=Fx Volume windowed=Venstermodus yes=Ja diff --git a/app/src/main/resources/assets/localization/localization_ru.properties b/app/src/main/resources/assets/localization/localization_ru.properties index c959b0a..f722796 100644 --- a/app/src/main/resources/assets/localization/localization_ru.properties +++ b/app/src/main/resources/assets/localization/localization_ru.properties @@ -28,6 +28,7 @@ serverPort=\u041f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 start=\u0421\u0442\u0430\u0440\u0442 tictactoe=\u041a\u0440\u0435\u0441\u0442\u0438\u043a\u0438 volume=\u0413\u0440\u0430\u043c\u043c\u043e\u0444\u043e\u043d +fxVolume=Fx Volume windowed=\u041e\u043a\u043d\u043e yes=\u0414\u0430 diff --git a/app/src/main/resources/assets/localization/localization_zh.properties b/app/src/main/resources/assets/localization/localization_zh.properties index 884d0d4..28a2691 100644 --- a/app/src/main/resources/assets/localization/localization_zh.properties +++ b/app/src/main/resources/assets/localization/localization_zh.properties @@ -28,6 +28,7 @@ serverPort=\u670d\u52a1\u5668 \u7aef\u53e3 start=\u5f00\u59cb tictactoe=Tic Tac Toe volume=\u97f3\u91cf +fxVolume=Fx Volume windowed=\u7a97\u53e3\u6a21\u5f0f yes=\u662f diff --git a/framework/src/main/java/org/toop/framework/asset/resources/SettingsAsset.java b/framework/src/main/java/org/toop/framework/asset/resources/SettingsAsset.java index f1d7130..76b503e 100644 --- a/framework/src/main/java/org/toop/framework/asset/resources/SettingsAsset.java +++ b/framework/src/main/java/org/toop/framework/asset/resources/SettingsAsset.java @@ -16,6 +16,10 @@ public class SettingsAsset extends JsonAsset { return getContent().volume; } + public int getFxVolume() { + return getContent().fxVolume; + } + public Locale getLocale() { return Locale.forLanguageTag(getContent().locale); } @@ -37,6 +41,11 @@ public class SettingsAsset extends JsonAsset { save(); } + public void setFxVolume(int fxVolume) { + getContent().fxVolume = fxVolume; + save(); + } + public void setLocale(String locale) { getContent().locale = locale; save(); diff --git a/framework/src/main/java/org/toop/framework/audio/SoundManager.java b/framework/src/main/java/org/toop/framework/audio/SoundManager.java index ff9da6b..30036bd 100644 --- a/framework/src/main/java/org/toop/framework/audio/SoundManager.java +++ b/framework/src/main/java/org/toop/framework/audio/SoundManager.java @@ -25,6 +25,7 @@ public class SoundManager { private final SnowflakeGenerator idGenerator = new SnowflakeGenerator(); // TODO: Don't create a new generator private double volume = 1.0; + private double fxVolume = 1.0; public SoundManager() { // Get all Audio Resources and add them to a list. @@ -40,7 +41,9 @@ public class SoundManager { .listen(this::handleStopSound) .listen(this::handleMusicStart) .listen(this::handleVolumeChange) + .listen(this::handleFxVolumeChange) .listen(this::handleGetCurrentVolume) + .listen(this::handleGetCurrentFxVolume) .listen(AudioEvents.ClickButton.class, _ -> { try { playSound("medium-button-click.wav", false); @@ -68,13 +71,20 @@ public class SoundManager { this.audioResources.put(audioAsset.getName(), audioAsset.getResource()); } + private double limitVolume(double volume) { + if (volume > 1.0) return 1.0; + else return Math.max(volume, 0.0); + } + private void handleVolumeChange(AudioEvents.ChangeVolume event) { - double newVolume = event.newVolume() / 100; - if (newVolume > 1.0) this.volume = 1.0; - else this.volume = Math.max(newVolume, 0.0); + this.volume = limitVolume(event.newVolume() / 100); for (MediaPlayer mediaPlayer : this.activeMusic) { mediaPlayer.setVolume(this.volume); } + } + + private void handleFxVolumeChange(AudioEvents.ChangeFxVolume event) { + this.fxVolume = limitVolume(event.newVolume() / 100); for (Clip clip : this.activeSoundEffects.values()){ updateClipVolume(clip); } @@ -85,14 +95,19 @@ public class SoundManager { FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); float min = volumeControl.getMinimum(); float max = volumeControl.getMaximum(); - float dB = (float) (Math.log10(Math.max(volume, 0.0001)) * 20.0); // convert linear to dB + float dB = (float) (Math.log10(Math.max(fxVolume, 0.0001)) * 20.0); // convert linear to dB dB = Math.max(min, Math.min(max, dB)); volumeControl.setValue(dB); } } private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) { - new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeReponse(volume * 100, event.snowflakeId())) + new EventFlow().addPostEvent(new AudioEvents.GetCurrentVolumeResponse(volume * 100, event.snowflakeId())) + .asyncPostEvent(); + } + + private void handleGetCurrentFxVolume(AudioEvents.GetCurrentFxVolume event) { + new EventFlow().addPostEvent(new AudioEvents.GetCurrentFxVolumeResponse(fxVolume * 100, event.snowflakeId())) .asyncPostEvent(); } diff --git a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java index 28f3d7a..978ed4a 100644 --- a/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java +++ b/framework/src/main/java/org/toop/framework/audio/events/AudioEvents.java @@ -15,6 +15,7 @@ public class AudioEvents extends EventsBase { public record StartBackgroundMusic() implements EventWithoutSnowflake {} public record ChangeVolume(double newVolume) implements EventWithoutSnowflake {} + public record ChangeFxVolume(double newVolume) implements EventWithoutSnowflake {} public record GetCurrentVolume(long snowflakeId) implements EventWithSnowflake { @Override public Map result() { @@ -26,7 +27,7 @@ public class AudioEvents extends EventsBase { return snowflakeId; } } - public record GetCurrentVolumeReponse(double currentVolume, long snowflakeId) implements EventWithSnowflake { + public record GetCurrentVolumeResponse(double currentVolume, long snowflakeId) implements EventWithSnowflake { @Override public Map result() { return Map.of(); @@ -37,5 +38,30 @@ public class AudioEvents extends EventsBase { return snowflakeId; } } + + public record GetCurrentFxVolume(long snowflakeId) implements EventWithSnowflake { + @Override + public Map result() { + return Map.of(); + } + + @Override + public long eventSnowflake() { + return this.snowflakeId; + } + } + + public record GetCurrentFxVolumeResponse(double currentVolume, long snowflakeId) implements EventWithSnowflake { + @Override + public Map result() { + return Map.of(); + } + + @Override + public long eventSnowflake() { + return this.snowflakeId; + } + } + public record ClickButton() implements EventWithoutSnowflake {} } diff --git a/framework/src/main/java/org/toop/framework/settings/Settings.java b/framework/src/main/java/org/toop/framework/settings/Settings.java index 12cee8c..4150e6c 100644 --- a/framework/src/main/java/org/toop/framework/settings/Settings.java +++ b/framework/src/main/java/org/toop/framework/settings/Settings.java @@ -6,4 +6,5 @@ public class Settings { public String theme = "dark"; public String layoutSize = "medium"; public int volume = 15; + public int fxVolume = 20; }