using Content.Shared.Instruments; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Audio.Midi; using Robust.Shared.Utility; namespace Content.Client.Instruments.UI; [GenerateTypedNameReferences] public sealed partial class ChannelsMenu : DefaultWindow { [Dependency] private readonly IEntityManager _entityManager = null!; private readonly InstrumentBoundUserInterface _owner; public ChannelsMenu(InstrumentBoundUserInterface owner) : base() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _owner = owner; ChannelList.OnItemSelected += OnItemSelected; ChannelList.OnItemDeselected += OnItemDeselected; AllButton.OnPressed += OnAllPressed; ClearButton.OnPressed += OnClearPressed; DisplayTrackNames.OnPressed += OnDisplayTrackNamesPressed; } protected override void EnteredTree() { base.EnteredTree(); _owner.Instruments.OnChannelsUpdated += UpdateChannelList; } private void OnDisplayTrackNamesPressed(BaseButton.ButtonEventArgs obj) { DisplayTrackNames.SetClickPressed(!DisplayTrackNames.Pressed); Populate(); } private void UpdateChannelList() { Populate(); // This is kind of in-efficent because we don't filter for which instrument updated its channels, but idc } protected override void ExitedTree() { base.ExitedTree(); _owner.Instruments.OnChannelsUpdated -= UpdateChannelList; } private void OnItemSelected(ItemList.ItemListSelectedEventArgs args) { _owner.Instruments.SetFilteredChannel(_owner.Owner, (int)ChannelList[args.ItemIndex].Metadata!, false); } private void OnItemDeselected(ItemList.ItemListDeselectedEventArgs args) { _owner.Instruments.SetFilteredChannel(_owner.Owner, (int)ChannelList[args.ItemIndex].Metadata!, true); } private void OnAllPressed(BaseButton.ButtonEventArgs obj) { foreach (var item in ChannelList) { // TODO: Make this efficient jfc item.Selected = true; } } private void OnClearPressed(BaseButton.ButtonEventArgs obj) { foreach (var item in ChannelList) { // TODO: Make this efficient jfc item.Selected = false; } } /// /// Walks up the tree of instrument masters to find the truest master of them all. /// private ActiveInstrumentComponent ResolveActiveInstrument(InstrumentComponent? comp) { comp ??= _entityManager.GetComponent(_owner.Owner); var instrument = new Entity(_owner.Owner, comp); while (true) { if (instrument.Comp.Master == null) break; instrument = new Entity((EntityUid)instrument.Comp.Master, _entityManager.GetComponent((EntityUid)instrument.Comp.Master)); } return _entityManager.GetComponent(instrument.Owner); } public void Populate() { ChannelList.Clear(); var instrument = _entityManager.GetComponent(_owner.Owner); var activeInstrument = ResolveActiveInstrument(instrument); for (int i = 0; i < RobustMidiEvent.MaxChannels; i++) { var label = _owner.Loc.GetString("instrument-component-channel-name", ("number", i)); if (activeInstrument != null && activeInstrument.Tracks.TryGetValue(i, out var resolvedMidiChannel) && resolvedMidiChannel != null) { if (DisplayTrackNames.Pressed) { label = resolvedMidiChannel switch { { TrackName: not null, InstrumentName: not null } => Loc.GetString("instruments-component-channels-multi", ("channel", i), ("name", resolvedMidiChannel.TrackName), ("other", resolvedMidiChannel.InstrumentName)), { TrackName: not null } => Loc.GetString("instruments-component-channels-single", ("channel", i), ("name", resolvedMidiChannel.TrackName)), _ => label, }; } else { label = resolvedMidiChannel switch { { ProgramName: not null } => Loc.GetString("instruments-component-channels-single", ("channel", i), ("name", resolvedMidiChannel.ProgramName)), _ => label, }; } } var item = ChannelList.AddItem(label, null, true, i); item.Selected = !instrument?.FilteredChannels[i] ?? false; } } }