mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Instrument UI MinVolume slider (#41272)
* Added localization string for MIDI input volume. * Added MinVolume property to SharedInstrumentComponent & InstrumentComponentState. * Implemented MinVolume property into InstrumentSystem's. * Added UI slider for MinVolume to InstrumentMenu. * Added network event for updating MinVolume. * Removed unnecessary empty line. * Readability fix as suggested by Pok27 Co-authored-by: Pok <113675512+Pok27@users.noreply.github.com> * Added MinVolumeControl * Added MinVolumeControl to instrument menu configuration (and cleaned up Content.Client.InstrumentSystem.SetMinVolume) * Added label to MinVolumeSlider indicating the current value * Minor cleanup --------- Co-authored-by: Pok <113675512+Pok27@users.noreply.github.com>
This commit is contained in:
parent
d9943c9753
commit
82b7cfa947
7 changed files with 139 additions and 1 deletions
|
|
@ -15,6 +15,9 @@ namespace Content.Client.Instruments;
|
|||
|
||||
public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
||||
{
|
||||
private const int MidiMinVolume = 0;
|
||||
private const int MidiMaxVolume = 127;
|
||||
|
||||
[Dependency] private IClientNetManager _netManager = default!;
|
||||
[Dependency] private IMidiManager _midiManager = default!;
|
||||
[Dependency] private IGameTiming _gameTiming = default!;
|
||||
|
|
@ -38,6 +41,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
SubscribeNetworkEvent<InstrumentMidiEventEvent>(OnMidiEventRx);
|
||||
SubscribeNetworkEvent<InstrumentStartMidiEvent>(OnMidiStart);
|
||||
SubscribeNetworkEvent<InstrumentStopMidiEvent>(OnMidiStop);
|
||||
SubscribeNetworkEvent<InstrumentSetMidiMinVolumeEvent>(OnSetMidiMinVolume);
|
||||
|
||||
SubscribeLocalEvent<InstrumentComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<InstrumentComponent, ComponentHandleState>(OnHandleState);
|
||||
|
|
@ -75,6 +79,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
component.AllowProgramChange = state.AllowProgramChange;
|
||||
component.RespectMidiLimits = state.RespectMidiLimits;
|
||||
component.Master = EnsureEntity<InstrumentComponent>(state.Master, uid);
|
||||
component.MinVolume = state.MinVolume;
|
||||
component.FilteredChannels = state.FilteredChannels;
|
||||
|
||||
if (component.Playing)
|
||||
|
|
@ -96,6 +101,18 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
RaiseNetworkEvent(new InstrumentSetMasterEvent(GetNetEntity(uid), GetNetEntity(masterUid)));
|
||||
}
|
||||
|
||||
public void SetMinVolume(EntityUid uid, int volume)
|
||||
{
|
||||
if (!TryComp(uid, out InstrumentComponent? instrument))
|
||||
return;
|
||||
|
||||
var byteMinVolume = (byte)Math.Min(Math.Max(MidiMinVolume, volume), MidiMaxVolume);
|
||||
instrument.MinVolume = byteMinVolume;
|
||||
|
||||
RaiseNetworkEvent(new InstrumentSetMidiMinVolumeEvent(GetNetEntity(uid), byteMinVolume));
|
||||
UpdateRenderer(uid);
|
||||
}
|
||||
|
||||
public void SetFilteredChannel(EntityUid uid, int channel, bool value)
|
||||
{
|
||||
if (!TryComp(uid, out InstrumentComponent? instrument))
|
||||
|
|
@ -186,6 +203,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
UpdateRendererMaster(instrument);
|
||||
|
||||
instrument.Renderer.LoopMidi = instrument.LoopMidi;
|
||||
instrument.Renderer.MinVolume = instrument.MinVolume;
|
||||
}
|
||||
|
||||
private void UpdateRendererMaster(InstrumentComponent instrument)
|
||||
|
|
@ -418,6 +436,15 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
EndRenderer(GetEntity(ev.Uid), true);
|
||||
}
|
||||
|
||||
private void OnSetMidiMinVolume(InstrumentSetMidiMinVolumeEvent ev)
|
||||
{
|
||||
if (!TryComp(GetEntity(ev.Uid), out InstrumentComponent? instrument))
|
||||
return;
|
||||
|
||||
instrument.MinVolume = ev.MinVolume;
|
||||
UpdateRenderer(GetEntity(ev.Uid), instrument);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public sealed partial class InstrumentBoundUserInterface : BoundUserInterface
|
|||
|
||||
private readonly ChannelsControl _channelsControl = new();
|
||||
private readonly MidiCollectionUtilsControl _midiCollectionUtilsControl = new();
|
||||
private readonly MinVolumeControl _minVolumeControl = new();
|
||||
|
||||
private InstrumentMenu? _instrumentMenu;
|
||||
|
||||
|
|
@ -63,6 +64,9 @@ public sealed partial class InstrumentBoundUserInterface : BoundUserInterface
|
|||
_channelsControl.ChannelsUpdateRequest += OnChannelsUpdateRequest;
|
||||
_channelsControl.SwitchFilteredChannel += OnSwitchFilteredChannel;
|
||||
|
||||
_minVolumeControl.MinVolumeChanged += OnMinVolumeChanged;
|
||||
_minVolumeControl.MinVolume = instrument.MinVolume;
|
||||
|
||||
_instrumentMenu = this.CreateWindow<InstrumentMenu>();
|
||||
|
||||
if (EntMan.TryGetComponent<MetaDataComponent>(Owner, out var metaData))
|
||||
|
|
@ -84,6 +88,9 @@ public sealed partial class InstrumentBoundUserInterface : BoundUserInterface
|
|||
_instrumentMenu.AddConfigurationControl(
|
||||
_loc.GetString("instruments-component-midi-file-collection-label"),
|
||||
_midiCollectionUtilsControl);
|
||||
_instrumentMenu.AddConfigurationControl(
|
||||
_loc.GetString("instruments-component-menu-midi-min-volume-slider-label"),
|
||||
_minVolumeControl);
|
||||
}
|
||||
|
||||
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
||||
|
|
@ -139,6 +146,11 @@ public sealed partial class InstrumentBoundUserInterface : BoundUserInterface
|
|||
UpdateChannels();
|
||||
}
|
||||
|
||||
private void OnMinVolumeChanged(int volume)
|
||||
{
|
||||
_instruments.SetMinVolume(Owner, volume);
|
||||
}
|
||||
|
||||
private void OnMidiPlaybackEnded()
|
||||
{
|
||||
_fileSource.SelectNextTrack();
|
||||
|
|
|
|||
6
Content.Client/Instruments/UI/MinVolumeControl.xaml
Normal file
6
Content.Client/Instruments/UI/MinVolumeControl.xaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<Control xmlns="https://spacestation14.io">
|
||||
<BoxContainer Orientation="Horizontal" VerticalExpand="True" Margin="2 2 0 0">
|
||||
<Slider Name="MidiMinVolumeSlider" HorizontalExpand="True" MinValue="0" MaxValue="127" />
|
||||
<Label Name="MidiMinVolumeValueLabel" MinWidth="28" Margin="6 0 3 0" Align="Right" />
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
60
Content.Client/Instruments/UI/MinVolumeControl.xaml.cs
Normal file
60
Content.Client/Instruments/UI/MinVolumeControl.xaml.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Input;
|
||||
|
||||
namespace Content.Client.Instruments.UI;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class MinVolumeControl : Control
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised when the user changes the min volume for MIDI input.
|
||||
/// </summary>
|
||||
public event Action<int>? MinVolumeChanged;
|
||||
|
||||
public int MinVolume
|
||||
{
|
||||
get => (int)Math.Ceiling(MidiMinVolumeSlider.Value);
|
||||
set
|
||||
{
|
||||
MidiMinVolumeSlider.Value = value;
|
||||
UpdateLabel();
|
||||
}
|
||||
}
|
||||
|
||||
public MinVolumeControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
MidiMinVolumeSlider.OnValueChanged += OnMidiMinVolumeSliderValueChanged;
|
||||
MidiMinVolumeSlider.OnKeyBindUp += OnMidiMinVolumeSliderKeyUp;
|
||||
MidiMinVolumeSlider.Value = 0;
|
||||
}
|
||||
|
||||
private void OnMidiMinVolumeSliderValueChanged(Robust.Client.UserInterface.Controls.Range _)
|
||||
{
|
||||
UpdateLabel();
|
||||
|
||||
// Do not update while still grabbed.
|
||||
if (MidiMinVolumeSlider.Grabbed)
|
||||
return;
|
||||
|
||||
MinVolumeChanged?.Invoke(MinVolume);
|
||||
}
|
||||
|
||||
private void OnMidiMinVolumeSliderKeyUp(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
if (args.Function != EngineKeyFunctions.UIClick)
|
||||
return;
|
||||
|
||||
UpdateLabel();
|
||||
MinVolumeChanged?.Invoke(MinVolume);
|
||||
}
|
||||
|
||||
private void UpdateLabel()
|
||||
{
|
||||
MidiMinVolumeValueLabel.Text = ((int)Math.Ceiling(MidiMinVolumeSlider.Value)).ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
SubscribeNetworkEvent<InstrumentSetMasterEvent>(OnMidiSetMaster);
|
||||
SubscribeNetworkEvent<InstrumentSetFilteredChannelEvent>(OnMidiSetFilteredChannel);
|
||||
SubscribeNetworkEvent<InstrumentSetChannelsEvent>(OnMidiSetChannels);
|
||||
SubscribeNetworkEvent<InstrumentSetMidiMinVolumeEvent>(OnMidiSetMinVolume);
|
||||
|
||||
Subs.BuiEvents<InstrumentComponent>(InstrumentUiKey.Key, subs =>
|
||||
{
|
||||
|
|
@ -82,7 +83,8 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
AllowProgramChange = component.AllowProgramChange,
|
||||
RespectMidiLimits = component.RespectMidiLimits,
|
||||
Master = GetNetEntity(component.Master),
|
||||
FilteredChannels = component.FilteredChannels
|
||||
FilteredChannels = component.FilteredChannels,
|
||||
MinVolume = component.MinVolume,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +142,17 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
|
|||
Clean(uid, instrument);
|
||||
}
|
||||
|
||||
private void OnMidiSetMinVolume(InstrumentSetMidiMinVolumeEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
var uid = GetEntity(msg.Uid);
|
||||
|
||||
if (!TryComp(uid, out InstrumentComponent? instrument))
|
||||
return;
|
||||
|
||||
instrument.MinVolume = msg.MinVolume;
|
||||
|
||||
Dirty(uid, instrument);
|
||||
}
|
||||
|
||||
private void OnMidiSetChannels(InstrumentSetChannelsEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ public abstract partial class SharedInstrumentComponent : Component
|
|||
[DataField]
|
||||
public bool RespectMidiLimits { get; set; } = true;
|
||||
|
||||
[DataField]
|
||||
public byte MinVolume { get; set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public EntityUid? Master { get; set; } = null;
|
||||
|
||||
|
|
@ -63,10 +66,26 @@ public sealed class InstrumentComponentState : ComponentState
|
|||
public bool RespectMidiLimits;
|
||||
|
||||
public NetEntity? Master;
|
||||
public byte MinVolume;
|
||||
|
||||
public BitArray FilteredChannels = default!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This message is sent to the client to update midi min volume.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class InstrumentSetMidiMinVolumeEvent : EntityEventArgs
|
||||
{
|
||||
public NetEntity Uid { get; }
|
||||
public byte MinVolume { get; set; }
|
||||
|
||||
public InstrumentSetMidiMinVolumeEvent(NetEntity uid, byte minVolume)
|
||||
{
|
||||
Uid = uid;
|
||||
MinVolume = minVolume;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This message is sent to the client to completely stop midi input and midi playback.
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ instruments-component-midi-file-collection-size-label = {$count} MIDI files load
|
|||
instruments-component-midi-file-collection-open-dir-button = Open Folder
|
||||
instruments-component-midi-file-collection-reload-button = Reload Collection
|
||||
instruments-component-midi-file-collection-delete-all-button = Clear Collection
|
||||
instruments-component-menu-midi-min-volume-slider-label = MIDI Input Min Volume
|
||||
|
||||
|
||||
# SwappableInstrumentComponent
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue