Code/Demos/BeatPad/RackTracks.cs
using System.Collections.Generic;
namespace Sandbox.BeatPad;
// ordered set of active rack tracks, separate from the StepPattern hit grid so emptied tracks render until explicitly removed. no engine types; compiles headless.
public sealed class RackTracks
{
readonly List<int> _order = new();
readonly HashSet<int> _muted = new();
readonly HashSet<int> _soloed = new();
public int Count => _order.Count;
public IReadOnlyList<int> Order => _order;
static bool InRange(int pad) => pad >= 0 && pad < BeatPadKits.PadCount;
public bool Contains(int pad) => _order.Contains(pad);
public void EnsureTrack(int pad)
{
if (!InRange(pad) || _order.Contains(pad)) return;
_order.Add(pad);
}
public void Remove(int pad)
{
_order.Remove(pad);
_muted.Remove(pad);
_soloed.Remove(pad);
}
public void Clear()
{
_order.Clear();
_muted.Clear();
_soloed.Clear();
}
public bool IsMuted(int pad) => _muted.Contains(pad);
public bool IsSoloed(int pad) => _soloed.Contains(pad);
public bool AnySolo => _soloed.Count > 0;
public void ToggleMute(int pad)
{
if (!InRange(pad)) return;
if (!_muted.Add(pad)) _muted.Remove(pad);
}
public void ToggleSolo(int pad)
{
if (!InRange(pad)) return;
if (!_soloed.Add(pad)) _soloed.Remove(pad);
}
// A track sounds unless muted; if any track is soloed, only soloed tracks sound.
// Mute beats solo on the same track.
public bool ShouldPlay(int pad) => !IsMuted(pad) && (!AnySolo || IsSoloed(pad));
}