CatStation/Content.Client/Instruments/UI/ChannelsControl.xaml.cs
Ataman 0c5b250f03
Instrument UI overhaul (#41604)
* Added base type for UI panels of MIDI input sources.

* Renamed BandMenu into BandMidiSource.

* Implemented the UI overhaul, skipping channels dialog functionality for now.

* Refactored for conventions and reordered type members.
Got rid of SetInstrument/ClearInstrument again.

* Decreased background opacity for UnavailableOverlay to improve readability.

* Localization

* Added text to InputMidiSource so players know what it does.

* Changed window MinSize to SetSize. Allows players to reduce window size if desired.

* Improved button looks by adding style classes.

* cleanup

* leftover cleanup

* Reverted fetching InstrumentSystem via IoCManager (crashes it, woops).

* added filter bar to file list

* refactored almost all system/manager interaction into instrument BUI

* text changed for instruments-component-menu-input-notice-label

* fixed InstrumentBoundUserInterface.Dispose not unsubscribing from everything

* minor cleanup

* finished configuration menu & cleanup

* Comments and fixes for InstrumentMidiSourceBase

* Fixed RA0051

* Removed unncecessary null check

* Added methods for accessing the selected track.

* Limited depth of search for instrument master to prevent deadlock.

* Cached system access

* Storing midis asynchronously

* Actual MIDI data now only loaded before playback.

* async removed from InstrumentBoundUserInterface.LoadStoredUserMidis

* Replaced GetComponent calls with TryGetComponent

* Localized MIDI playback track timer

* Searching for next track using raw index now

* Fixed CS0168

* XML comments, minor fixes and disabled MIDI library management while a track is playing.

* removed timers with simple watchdog and switched to MidiFileCollectionManager

* Missed one (timer)

* Changed access for MidiFileCollectionManager.UserMidiDirectory field to public.

* Added instrument config control for MIDI collection utilities.

* redesigned instrument config menu

* Removed rename function, updated adding implementation

* more redesigns

* fixed _isMidiFileDialogueWindowOpen not resetting correctly in certain cases.

* file scoped namespaces

* replaced EntityUid with Entity<InstrumentComponent>

* if spaces

* returning Tooltip instead of Control

* replaced SetEntity with public field

* readonly system fields

* InstrumentMenu MinSize

* xml comment for InstrumentMidiSourceBase

* small refactor

* more cleanup

* TryGetComponent to GetComponent on Open()

* more formatting issues

* switched to [Dependency] for systems

* playback improvements

* disable playback button if no file selected and playing

* activating shuffle now selects track if none is selected

* rearranged playback buttons

* channels overhauled

* Play/Stop label to Play only

* Removed all channel on/off

* Program now default channel name display selection

* improved RemoveButton.Disable behavior

* channels now toggable by clicking anywhere

* Shuffle no longer selects already selected track.

* Loop & Shuffle no longer both selectable at once

* minor improvements to channel item visuals

* minor channel toggle fixes

* xml docs & code cleanup

* `RefreshBandRequest` now sent automatically when band source becomes visible

* converted 5 items tuple to MidiChannelInfo record

* added markup support to instrument menu configuration header

* added note to midi channels config header explaining update behavior.
2026-07-26 16:50:28 +00:00

116 lines
3.6 KiB
C#

using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Audio.Midi;
namespace Content.Client.Instruments.UI;
[GenerateTypedNameReferences]
public sealed partial class ChannelsControl : Control
{
/// <summary>
/// Raised when a channel is toggled.
/// </summary>
public event Action<int, bool>? SwitchFilteredChannel;
/// <summary>
/// Raised when a selector button is pressed in order to display different channel names.
/// </summary>
public event Action? ChannelsUpdateRequest;
public ChannelsControl()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
TrackSelectorButton.OnPressed += OnSelectorButtonPressed;
InstrumentSelectorButton.OnPressed += OnSelectorButtonPressed;
ProgramSelectorButton.OnPressed += OnSelectorButtonPressed;
var group = new ButtonGroup();
TrackSelectorButton.Group = group;
InstrumentSelectorButton.Group = group;
ProgramSelectorButton.Group = group;
InitChannels();
}
protected override void VisibilityChanged(bool newVisible)
{
if (newVisible)
ChannelsUpdateRequest?.Invoke();
}
private void OnSelectorButtonPressed(BaseButton.ButtonEventArgs obj)
{
ChannelsUpdateRequest?.Invoke();
}
private void OnChannelSwitched(int id, bool state)
{
SwitchFilteredChannel?.Invoke(id, state);
}
private void InitChannels()
{
for (var i = 0; i < RobustMidiEvent.MaxChannels; i++)
{
var item = new ChannelItem
{
ChannelId = i,
};
ChannelsContainer.AddChild(item);
item.SwitchFilteredChannel += OnChannelSwitched;
}
}
/// <summary>
/// Replaces the current list of channels with the passed one.
/// </summary>
/// <remarks>
/// Calling this method overrides the toggle state of all channel items. Ensure to pass correct values.
/// </remarks>
/// <param name="channels">List of channels consisting of their index, display name and state.</param>
public void SetChannels(MidiChannelInfo[] channels)
{
TrackSelectorButton.Disabled = true;
InstrumentSelectorButton.Disabled = true;
ProgramSelectorButton.Disabled = true;
for (var i = 0; i < RobustMidiEvent.MaxChannels; i++)
{
if (i >= ChannelsContainer.ChildCount || i < 0)
return;
if (ChannelsContainer.Children[i] is not ChannelItem cItem)
return;
cItem.ChannelName = "";
cItem.ChannelState = false;
cItem.Visible = false;
if (i >= channels.Length)
continue;
var channel = channels[i];
if (channel.TrackName.Length > 0)
TrackSelectorButton.Disabled = false;
if (channel.InstrumentName.Length > 0)
InstrumentSelectorButton.Disabled = false;
if (channel.ProgramName.Length > 0)
ProgramSelectorButton.Disabled = false;
if (TrackSelectorButton.Pressed)
cItem.ChannelName = channel.TrackName;
if (InstrumentSelectorButton.Pressed)
cItem.ChannelName = channel.InstrumentName;
if (ProgramSelectorButton.Pressed)
cItem.ChannelName = channel.ProgramName;
cItem.ChannelState = channel.FilterState;
cItem.Visible = true;
}
}
}