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

138 lines
3.3 KiB
C#
Raw Normal View History

using Godot;
2025-06-12 09:03:02 +00:00
using System.Collections.Generic;
namespace Rokojori
{
[Tool][GlobalClass]
public partial class PlaySound:Action
{
[Export]
2025-06-12 09:03:02 +00:00
public AudioStreamPlayer3D player;
2025-07-25 15:35:19 +00:00
[Export]
public SelectorFlag overdrivePreventionFlag;
2025-07-25 08:13:35 +00:00
[Export]
public Duration overdrivePreventionDuration;
2025-06-12 09:03:02 +00:00
2025-07-25 15:35:19 +00:00
2025-06-12 09:03:02 +00:00
[ExportGroup("Randomize Playback Position")]
[Export]
public bool randomizePlaybackPosition = false;
[Export]
public Duration durationPerSound;
[Export]
2025-07-25 15:35:19 +00:00
public float cutBufferLengths = 0;
[Export]
2025-06-12 09:03:02 +00:00
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()
{
2025-07-25 15:35:19 +00:00
var audioManager = Unique<AudioManager>.Get();
2025-07-25 08:13:35 +00:00
2025-07-25 15:35:19 +00:00
if ( overdrivePreventionDuration != null && overdrivePreventionFlag != null )
{
if ( ! audioManager.CanPlay( overdrivePreventionFlag, overdrivePreventionDuration.GetDurationInSeconds() ) )
2025-07-25 08:13:35 +00:00
{
2025-07-25 15:35:19 +00:00
this.LogInfo( "Can't play sound, prevention" );
2025-07-25 08:13:35 +00:00
return;
}
2025-07-25 15:35:19 +00:00
2025-07-25 08:13:35 +00:00
}
2025-07-25 15:35:19 +00:00
2025-07-25 08:13:35 +00:00
2025-06-12 09:03:02 +00:00
var offset = 0f;
var player = generatePools ? GetFreePlayer() : this.player;
2025-07-25 15:35:19 +00:00
if ( ! IsInstanceValid( player ) )
{
this.LogInfo( "Can't play sound, invalid" );
return;
}
2025-06-12 09:03:02 +00:00
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 );
2025-07-25 15:35:19 +00:00
this.LogInfo( "Play sound", offset, HierarchyName.Of( player ) );
if ( overdrivePreventionFlag != null )
{
audioManager.RecordSoundPlaying( overdrivePreventionFlag );
}
2025-06-12 09:03:02 +00:00
if ( randomizePlaybackPosition )
{
var tl = TimeLineManager.Ensure( durationPerSound.timeLine );
var start = tl.position;
2025-07-25 15:35:19 +00:00
var stopDuration = ( durationPerSound.GetDurationInSeconds() - audioManager.bufferCutLength * cutBufferLengths ) / player.PitchScale;
TimeLineManager.ScheduleSpanIn( durationPerSound.timeLine, 0, stopDuration,
2025-06-12 09:03:02 +00:00
( span, type )=>
{
var timeNow = tl.position;
var elapsed = timeNow - start;
var phase = span.phase;
if ( type == TimeLineSpanUpdateType.End )
{
player.Stop();
player.Playing = false;
}
}
);
}
}
}
}