Add an action to fade a sound or a music on a channel to a new volume (#3724)

This commit is contained in:
Oxey405
2022-04-28 11:17:46 +02:00
committed by GitHub
parent 14175c334e
commit cdddcafa68
4 changed files with 76 additions and 8 deletions

View File

@@ -343,6 +343,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsComplex();
extension
.AddAction(
"FadeSoundVolume",
_("Fade the volume of a sound played on a channel."),
_("Fade the volume of a sound played on a channel to the specified volume within the specified duration."),
_("Fade the sound on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddAction(
"FadeMusicVolume",
_("Fade the volume of a music played on a channel."),
_("Fade the volume of a music played on a channel to the specified volume within the specified duration."),
_("Fade the music on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddCondition("MusicPlaying",

View File

@@ -33,6 +33,8 @@ AudioExtension::AudioExtension() {
"gdjs.evtTools.sound.pauseMusicOnChannel");
GetAllActions()["RePlayMusicCanal"].SetFunctionName(
"gdjs.evtTools.sound.continueMusicOnChannel");
GetAllActions()["FadeMusicVolume"].SetFunctionName(
"gdjs.evtTools.sound.fadeMusicVolume");
GetAllActions()["PreloadMusic"].SetFunctionName(
"gdjs.evtTools.sound.preloadMusic");
@@ -44,6 +46,9 @@ AudioExtension::AudioExtension() {
"gdjs.evtTools.sound.unloadSound");
GetAllActions()["UnloadAllAudio"].SetFunctionName(
"gdjs.evtTools.sound.unloadAllAudio");
GetAllActions()["FadeSoundVolume"].SetFunctionName(
"gdjs.evtTools.sound.fadeSoundVolume");
GetAllConditions()["MusicPlaying"].SetFunctionName(
"gdjs.evtTools.sound.isMusicOnChannelPlaying");

View File

@@ -428,6 +428,35 @@ namespace gdjs {
runtimeScene
.getSoundManager()
.unloadAudio(soundFile, /* isMusic= */ true);
export const fadeSoundVolume = (
runtimeScene: gdjs.RuntimeScene,
channel: integer,
toVolume: float,
timeOfFade: float /* in seconds */
) => {
const sound = runtimeScene.getSoundManager().getSoundOnChannel(channel);
if (sound) sound.fade(sound.getVolume(), toVolume, timeOfFade * 1000);
else {
logger.error(
`Cannot fade the volume of a non-existing sound on channel ${channel}.`
);
}
};
export const fadeMusicVolume = (
runtimeScene: gdjs.RuntimeScene,
channel: integer,
toVolume: float,
timeOfFade: float /* in seconds */
) => {
const music = runtimeScene.getSoundManager().getMusicOnChannel(channel);
if (music) music.fade(music.getVolume(), toVolume, timeOfFade * 1000);
else {
logger.error(
`Cannot fade the volume of a non-existing music on channel ${channel}.`
);
}
};
}
}
}

View File

@@ -50,10 +50,14 @@ namespace gdjs {
private _howl: Howl;
/**
* The volume at which the sound is being played.
* The **initial** volume at which the sound is being played.
* Once the sound is started, this volume can be not in sync
* (in the case the sound is faded by Howler), so volume must
* be gotten from `this._howl` directly.
*
* This value is clamped between 0 and 1.
*/
private _volume: float;
private _initialVolume: float;
/**
* Whether the sound is being played in a loop or not.
@@ -80,7 +84,7 @@ namespace gdjs {
constructor(howl: Howl, volume: float, loop: boolean, rate: float) {
this._howl = howl;
this._volume = clampVolume(volume);
this._initialVolume = clampVolume(volume);
this._loop = loop;
this._rate = rate;
}
@@ -104,7 +108,7 @@ namespace gdjs {
this._id = newID;
// Set the howl properties as soon as the sound is played and we have its ID.
this._howl.volume(this._volume, newID); // this._volume is already clamped between 0 and 1.
this._howl.volume(this._initialVolume, newID); // this._initialVolume is already clamped between 0 and 1.
this._howl.loop(this._loop, newID);
// this._rate is not clamped, but we need to clamp it when passing it to Howler.js as it
// only supports a specific range.
@@ -223,7 +227,8 @@ namespace gdjs {
* @returns A float from 0 to 1.
*/
getVolume(): float {
return this._volume;
if (this._id === null) return this._initialVolume;
return this._howl.volume(this._id);
}
/**
@@ -232,10 +237,10 @@ namespace gdjs {
* @returns The current instance for chaining.
*/
setVolume(volume: float): this {
this._volume = clampVolume(volume);
this._initialVolume = clampVolume(volume);
// If the sound has already started playing, then change the value directly.
if (this._id !== null) this._howl.volume(this._volume, this._id);
if (this._id !== null) this._howl.volume(this._initialVolume, this._id);
return this;
}
@@ -295,7 +300,8 @@ namespace gdjs {
* @returns The current instance for chaining.
*/
fade(from: float, to: float, duration: float): this {
if (this._id !== null) this._howl.fade(from, to, duration, this._id);
if (this._id !== null)
this._howl.fade(clampVolume(from), clampVolume(to), duration, this._id);
return this;
}