diff --git a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/Audio.kt b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/Audio.kt index 4d4aeb441..685d0989c 100644 --- a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/Audio.kt +++ b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/Audio.kt @@ -7,9 +7,12 @@ package com.almasb.fxgl.audio import com.almasb.fxgl.core.Disposable +import javafx.beans.property.DoubleProperty +import javafx.beans.property.SimpleDoubleProperty -enum class AudioType { - MUSIC, SOUND +enum class AudioType(val volume: DoubleProperty) { + MUSIC(SimpleDoubleProperty(0.5)), + SOUND(SimpleDoubleProperty(0.5)) } /** @@ -19,6 +22,10 @@ enum class AudioType { */ abstract class Audio(val type: AudioType) { + internal fun mix(volume: Double) : Double { + return type.volume.value * volume + } + abstract fun setLooping(looping: Boolean) abstract fun setVolume(volume: Double) @@ -52,19 +59,49 @@ private val audio: Audio by lazy { fun getDummyAudio() = audio +abstract class Media(internal val audio : Audio) : Disposable { + + internal var isDisposed = false + internal val volume = SimpleDoubleProperty(1.0) + + init { + audio.type.volume.addListener { _, _, _ -> + audio.setVolume(volume.value) + } + volume.addListener { _, _, _ -> + audio.setVolume(volume.value) + } + } + + fun setVolume(value: Double) { + volume.value = value + } + + fun getVolume() : Double { + return volume.value + } + + fun volumeProperty() : DoubleProperty { + return volume + } + + fun setLooping(looping: Boolean) { + audio.setLooping(looping) + } + + override fun dispose() { + isDisposed = true + } +} + /** * Represents a long-term audio in mp3 file. * Use for background (looping) music or recorded dialogues. * * @author Almas Baimagambetov (AlmasB) (almaslvl@gmail.com) */ -class Music(val audio: Audio) : Disposable { +class Music(audio : Audio) : Media(audio) { - internal var isDisposed = false - - override fun dispose() { - isDisposed = true - } } /** @@ -72,11 +109,6 @@ class Music(val audio: Audio) : Disposable { * * @author Almas Baimagambetov (AlmasB) (almaslvl@gmail.com) */ -class Sound(val audio: Audio) : Disposable { - - internal var isDisposed = false +class Sound(audio : Audio) : Media(audio) { - override fun dispose() { - isDisposed = true - } } \ No newline at end of file diff --git a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/AudioPlayer.kt b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/AudioPlayer.kt index b55410fe8..66ebd2ef5 100644 --- a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/AudioPlayer.kt +++ b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/AudioPlayer.kt @@ -11,7 +11,6 @@ import com.almasb.fxgl.core.EngineService import com.almasb.fxgl.core.Inject import com.almasb.fxgl.core.collection.UnorderedArray import com.almasb.fxgl.logging.Logger -import javafx.beans.property.DoubleProperty import java.net.URL /** @@ -27,27 +26,11 @@ class AudioPlayer : EngineService() { private val activeMusic = UnorderedArray() private val activeSounds = UnorderedArray() - @Inject("globalMusicVolumeProperty") - private lateinit var musicVolume: DoubleProperty - - @Inject("globalSoundVolumeProperty") - private lateinit var soundVolume: DoubleProperty - @Inject("isPauseMusicWhenMinimized") private var isPauseMusicWhenMinimized = true private val loader = DesktopAndMobileAudioLoader() - override fun onMainLoopStarting() { - musicVolume.addListener { _, _, newVolume -> - activeMusic.forEach { it.audio.setVolume(newVolume.toDouble()) } - } - - soundVolume.addListener { _, _, newVolume -> - activeSounds.forEach { it.audio.setVolume(newVolume.toDouble()) } - } - } - override fun onMainLoopPausing() { if (isPauseMusicWhenMinimized) { pauseAllMusic() @@ -74,7 +57,6 @@ class AudioPlayer : EngineService() { if (!activeSounds.containsByIdentity(sound)) activeSounds.add(sound) - sound.audio.setVolume(soundVolume.value) sound.audio.play() } @@ -106,7 +88,6 @@ class AudioPlayer : EngineService() { activeMusic.add(music) } - music.audio.setVolume(musicVolume.value) music.audio.play() } @@ -192,4 +173,5 @@ class AudioPlayer : EngineService() { fun loadAudio(audioType: AudioType, url: URL, isMobile: Boolean): Audio { return loader.loadAudio(audioType, url, isMobile) } + } \ No newline at end of file diff --git a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAndMobileAudioLoader.kt b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAndMobileAudioLoader.kt index 0ce28efb7..f915690ef 100644 --- a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAndMobileAudioLoader.kt +++ b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAndMobileAudioLoader.kt @@ -66,7 +66,7 @@ class DesktopAndMobileAudioLoader : AudioLoader { } override fun setVolume(volume: Double) { - nativeAudio.ifPresent { it.setVolume(volume) } + nativeAudio.ifPresent { it.setVolume(mix(volume)) } } override fun setOnFinished(action: Runnable) { diff --git a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAudio.kt b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAudio.kt index 2011b21fd..f8ff3119d 100644 --- a/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAudio.kt +++ b/fxgl-core/src/main/kotlin/com/almasb/fxgl/audio/impl/DesktopAudio.kt @@ -21,7 +21,7 @@ class DesktopMusic(private val mediaPlayer: MediaPlayer) : Audio(AudioType.MUSIC } override fun setVolume(volume: Double) { - mediaPlayer.volume = volume + mediaPlayer.volume = mix(volume) } override fun setOnFinished(action: Runnable) { @@ -52,7 +52,7 @@ class DesktopSound(private val clip: AudioClip) : Audio(AudioType.SOUND) { } override fun setVolume(volume: Double) { - clip.volume = volume + clip.volume = mix(volume) } override fun setOnFinished(action: Runnable) { diff --git a/fxgl/src/main/kotlin/com/almasb/fxgl/app/Settings.kt b/fxgl/src/main/kotlin/com/almasb/fxgl/app/Settings.kt index 1d1b32de4..594f3ae1b 100644 --- a/fxgl/src/main/kotlin/com/almasb/fxgl/app/Settings.kt +++ b/fxgl/src/main/kotlin/com/almasb/fxgl/app/Settings.kt @@ -11,6 +11,7 @@ import com.almasb.fxgl.achievement.AchievementService import com.almasb.fxgl.app.scene.SceneFactory import com.almasb.fxgl.app.services.* import com.almasb.fxgl.audio.AudioPlayer +import com.almasb.fxgl.audio.AudioType import com.almasb.fxgl.core.EngineService import com.almasb.fxgl.core.math.FXGLMath import com.almasb.fxgl.core.serialization.Bundle @@ -765,28 +766,6 @@ class ReadOnlyGameSettings internal constructor( get() = gameDifficultyProp.value set(value) { gameDifficultyProp.value = value } - @get:JvmName("globalMusicVolumeProperty") - val globalMusicVolumeProperty = SimpleDoubleProperty(0.5) - - /** - * Set global music volume in the range [0..1], - * where 0 = 0%, 1 = 100%. - */ - var globalMusicVolume: Double - get() = globalMusicVolumeProperty.value - set(value) { globalMusicVolumeProperty.value = value } - - @get:JvmName("globalSoundVolumeProperty") - val globalSoundVolumeProperty = SimpleDoubleProperty(0.5) - - /** - * Set global sound volume in the range [0..1], - * where 0 = 0%, 1 = 100%. - */ - var globalSoundVolume: Double - get() = globalSoundVolumeProperty.value - set(value) { globalSoundVolumeProperty.value = value } - private val mouseSensitivityProp = SimpleDoubleProperty(mouseSensitivity) var mouseSensitivity: Double @@ -804,15 +783,16 @@ class ReadOnlyGameSettings internal constructor( override fun write(bundle: Bundle) { bundle.put("fullscreen", fullScreen.value) - bundle.put("globalMusicVolume", globalMusicVolume) - bundle.put("globalSoundVolume", globalSoundVolume) + + bundle.put("globalMusicVolume", AudioType.MUSIC.volume.value) + bundle.put("globalSoundVolume", AudioType.SOUND.volume.value) } override fun read(bundle: Bundle) { fullScreen.value = bundle.get("fullscreen") - globalMusicVolume = bundle.get("globalMusicVolume") - globalSoundVolume = bundle.get("globalSoundVolume") + AudioType.MUSIC.volume.value = bundle.get("globalMusicVolume") + AudioType.SOUND.volume.value = bundle.get("globalSoundVolume") applySettings() } diff --git a/fxgl/src/main/kotlin/com/almasb/fxgl/app/scene/FXGLDefaultMenu.kt b/fxgl/src/main/kotlin/com/almasb/fxgl/app/scene/FXGLDefaultMenu.kt index 52363b8cd..a960f65b5 100644 --- a/fxgl/src/main/kotlin/com/almasb/fxgl/app/scene/FXGLDefaultMenu.kt +++ b/fxgl/src/main/kotlin/com/almasb/fxgl/app/scene/FXGLDefaultMenu.kt @@ -10,6 +10,7 @@ import com.almasb.fxgl.animation.Animation import com.almasb.fxgl.animation.Interpolators import com.almasb.fxgl.app.ApplicationMode import com.almasb.fxgl.app.MenuItem +import com.almasb.fxgl.audio.AudioType import com.almasb.fxgl.core.math.FXGLMath.noise1D import com.almasb.fxgl.core.util.InputPredicates import com.almasb.fxgl.dsl.* @@ -699,7 +700,7 @@ open class FXGLDefaultMenu(type: MenuType) : FXGLMenu(type) { val sliderMusic = getUIFactoryService().newSlider() sliderMusic.min = 0.0 sliderMusic.max = 1.0 - sliderMusic.valueProperty().bindBidirectional(getSettings().globalMusicVolumeProperty) + sliderMusic.valueProperty().bindBidirectional(AudioType.MUSIC.volume) val textMusic = getUIFactoryService().newText(localizedStringProperty("menu.music.volume").concat(": ")) val percentMusic = getUIFactoryService().newText("") @@ -708,7 +709,7 @@ open class FXGLDefaultMenu(type: MenuType) : FXGLMenu(type) { val sliderSound = getUIFactoryService().newSlider() sliderSound.min = 0.0 sliderSound.max = 1.0 - sliderSound.valueProperty().bindBidirectional(getSettings().globalSoundVolumeProperty) + sliderSound.valueProperty().bindBidirectional(AudioType.SOUND.volume) val textSound = getUIFactoryService().newText(localizedStringProperty("menu.sound.volume").concat(": ")) val percentSound = getUIFactoryService().newText("")