Code/Components/SoundHandler.cs
namespace SmallFishUtils;
/// <summary>
/// SoundSettings that are applied to the SoundHandle.
/// </summary>
public struct SoundSettings
{
/// <summary>
/// Override the pitch?
/// </summary>
public float? Pitch = null;
/// <summary>
/// Override the volume?
/// </summary>
public float? Volume = null;
/// <summary>
/// The time it takes for the sound to fade.
/// </summary>
public float FadeTime = 0;
/// <summary>
/// The mixer that the sound will play from.
/// </summary>
public string Mixer = "";
/// <summary>
/// Should we follow the GameObject?
/// </summary>
public bool Follow = true;
/// <summary>
/// When should the sound stop... if at all?
/// </summary>
public StopCondition StopOn = StopCondition.Destroy;
[Flags]
public enum StopCondition
{
None = 0, // The sound will stop when it is finished playing.
Destroy = 1 << 0, // The sound stops when the component is destroyed.
Disabled = 1 << 1 // The sound stops when the component is disabled.
}
public SoundSettings() { }
public void SetHandleSettings( SoundHandle handle )
{
if ( !Follow )
handle.FollowParent = false;
if ( Pitch.HasValue )
handle.Pitch = Pitch.Value;
if ( Volume.HasValue )
handle.Volume = Volume.Value;
if ( !string.IsNullOrEmpty( Mixer ) )
handle.TargetMixer = Sandbox.Audio.Mixer.FindMixerByName( Mixer );
}
}
/// <summary>
/// A component that handles the lifetime of sounds. If the parent GameObject is destroyed the
/// sounds are stopped as well.
/// </summary>
public sealed class SoundHandler : Component
{
public struct SoundConfig
{
[KeyProperty] public readonly string Name => Handle.IsValid() ? Handle.Name : "";
[Hide] public SoundHandle Handle;
[Hide] public SoundSettings Config;
}
[Property, ReadOnly]
public List<SoundConfig> ActiveSounds { get; set; } = new();
public void AddSound( SoundHandle handle, SoundSettings soundSettings )
{
if ( !handle.IsValid() )
return;
ActiveSounds.Add( new SoundConfig() { Handle = handle, Config = soundSettings } );
}
protected override void OnUpdate()
{
for ( int i = ActiveSounds.Count - 1; i >= 0; i-- )
{
var sound = ActiveSounds[i].Handle;
if ( !sound.IsValid() || sound.IsStopped || sound.Finished )
ActiveSounds.RemoveAt( i );
}
}
protected override void OnDisabled()
{
foreach ( var sound in ActiveSounds )
{
if ( sound.Handle.IsValid() && sound.Config.StopOn.HasFlag( SoundSettings.StopCondition.Disabled ) )
sound.Handle.Stop( sound.Config.FadeTime );
}
}
protected override void OnDestroy()
{
foreach ( var sound in ActiveSounds )
{
if ( sound.Handle.IsValid() && sound.Config.StopOn.HasFlag( SoundSettings.StopCondition.Destroy ) )
sound.Handle.Stop( sound.Config.FadeTime );
}
}
}