rokojori_action_library/Runtime/Actions/Audio/MusicChannelPlayer.cs

90 lines
2.1 KiB
C#

using Godot;
namespace Rokojori;
[Tool]
[GlobalClass]
public partial class MusicChannelPlayer:Node
{
[Export]
public MusicChannel channel;
[Export]
public MusicData currentMusic;
[Export]
public AudioStreamPlayer currentPlayer;
public void TweenVolume( AudioStreamPlayer target, float duration, float toVolume, bool clear, System.Action onReady = null )
{
var tl = TimeLineManager.Ensure( null );
var start = tl.position;
var fromVolume = target.VolumeLinear;
TimeLineManager.ScheduleSpanIn( tl, 0, duration,
( span, type )=>
{
if ( ! GodotObject.IsInstanceValid( target ) )
{
return;
}
var lerpedVolume = Mathf.Lerp( fromVolume, toVolume, span.phase );
target.VolumeLinear = lerpedVolume;
if ( type == TimeLineSpanUpdateType.End && clear )
{
if ( clear )
{
ClearAudioPlayer( target );
}
if ( onReady != null )
{
onReady();
}
}
},
this
);
}
async void ClearAudioPlayer( AudioStreamPlayer target )
{
await this.RequestNextFrame();
target.DeleteSelf();
}
public void SchedulePlayer( MusicData nextMusic, float duration, System.Action onReady )
{
if ( currentMusic != null )
{
this.LogInfo( "Muting:", currentMusic );
TweenVolume( currentPlayer, duration, 0f, true );
currentMusic = null;
currentPlayer = null;
}
this.LogInfo( "Playing:", nextMusic );
var name = FilePath.Absolute( nextMusic.audio.ResourcePath ).fileName;
var nextPlayer = this.CreateChild<AudioStreamPlayer>( "Player " + name );
nextPlayer.VolumeLinear = 0f;
nextPlayer.Stream = nextMusic.audio;
nextPlayer.PitchScale = MathAudio.SemitonesToFrequencyScaler( nextMusic.pitchSemitonesOffset );
nextPlayer.Bus = channel.audioBus;
currentMusic = nextMusic;
currentPlayer = nextPlayer;
TweenVolume( nextPlayer, duration, nextMusic.volume, false, onReady );
nextPlayer.Play();
}
}