rj-action-library/Runtime/Actions/Node3D/PlaySound.cs

138 lines
3.3 KiB
C#

using Godot;
using System.Collections.Generic;
namespace Rokojori
{
[Tool][GlobalClass]
public partial class PlaySound:Action
{
[Export]
public AudioStreamPlayer3D player;
[Export]
public SelectorFlag overdrivePreventionFlag;
[Export]
public Duration overdrivePreventionDuration;
[ExportGroup("Randomize Playback Position")]
[Export]
public bool randomizePlaybackPosition = false;
[Export]
public Duration durationPerSound;
[Export]
public float cutBufferLengths = 0;
[Export]
public bool generatePools = true;
List<AudioStreamPlayer3D> players = new List<AudioStreamPlayer3D>();
AudioStreamPlayer3D GetFreePlayer()
{
if ( players.Count == 0 )
{
players.Add( player );
}
var freePlayer = players.Find( p => ! p.Playing );
if ( freePlayer != null )
{
return freePlayer;
}
var newPlayer = player.GetParent().CreateChild<AudioStreamPlayer3D>();
newPlayer.Stream = player.Stream;
newPlayer.VolumeDb = player.VolumeDb;
newPlayer.MaxDb = player.MaxDb;
newPlayer.UnitSize = player.UnitSize;
newPlayer.AttenuationModel = player.AttenuationModel;
players.Add( newPlayer );
return newPlayer;
}
protected override void _OnTrigger()
{
var audioManager = Unique<AudioManager>.Get();
if ( overdrivePreventionDuration != null && overdrivePreventionFlag != null )
{
if ( ! audioManager.CanPlay( overdrivePreventionFlag, overdrivePreventionDuration.GetDurationInSeconds() ) )
{
this.LogInfo( "Can't play sound, prevention" );
return;
}
}
var offset = 0f;
var player = generatePools ? GetFreePlayer() : this.player;
if ( ! IsInstanceValid( player ) )
{
this.LogInfo( "Can't play sound, invalid" );
return;
}
if ( randomizePlaybackPosition )
{
var random = LCG.WithSeed( networkSeed );
var length = player.Stream.GetLength();
var numOffsets = Mathf.FloorToInt( length / durationPerSound.GetDurationInSeconds() );
var randomIndex = random.IntegerExclusive( numOffsets );
offset = randomIndex * durationPerSound.GetDurationInSeconds();
// this.LogInfo( "Offset", numOffsets, randomIndex, offset );
}
player.Play( offset );
this.LogInfo( "Play sound", offset, HierarchyName.Of( player ) );
if ( overdrivePreventionFlag != null )
{
audioManager.RecordSoundPlaying( overdrivePreventionFlag );
}
if ( randomizePlaybackPosition )
{
var tl = TimeLineManager.Ensure( durationPerSound.timeLine );
var start = tl.position;
var stopDuration = ( durationPerSound.GetDurationInSeconds() - audioManager.bufferCutLength * cutBufferLengths ) / player.PitchScale;
TimeLineManager.ScheduleSpanIn( durationPerSound.timeLine, 0, stopDuration,
( span, type )=>
{
var timeNow = tl.position;
var elapsed = timeNow - start;
var phase = span.phase;
if ( type == TimeLineSpanUpdateType.End )
{
player.Stop();
player.Playing = false;
}
}
);
}
}
}
}