Instrument band support, submodule update to 138.0.0 (#17995)
This commit is contained in:
committed by
GitHub
parent
69ff0ae2e6
commit
a2893dd6c3
@@ -1,20 +1,12 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Client.Interactable;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Client.Audio.Midi;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Timing;
|
||||
using static Robust.Client.UserInterface.Controls.BaseButton;
|
||||
using Range = Robust.Client.UserInterface.Controls.Range;
|
||||
@@ -24,29 +16,26 @@ namespace Content.Client.Instruments.UI
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class InstrumentMenu : DefaultWindow
|
||||
{
|
||||
[Dependency] private readonly IMidiManager _midiManager = default!;
|
||||
[Dependency] private readonly IFileDialogManager _fileDialogManager = default!;
|
||||
|
||||
private readonly InstrumentBoundUserInterface _owner;
|
||||
|
||||
public InstrumentMenu(InstrumentBoundUserInterface owner)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_owner = owner;
|
||||
|
||||
if (_owner.Instrument != null)
|
||||
{
|
||||
_owner.Instrument.OnMidiPlaybackEnded += InstrumentOnMidiPlaybackEnded;
|
||||
Title = IoCManager.Resolve<IEntityManager>().GetComponent<MetaDataComponent>(_owner.Instrument.Owner).EntityName;
|
||||
Title = _owner.Entities.GetComponent<MetaDataComponent>(_owner.Owner).EntityName;
|
||||
LoopButton.Disabled = !_owner.Instrument.IsMidiOpen;
|
||||
LoopButton.Pressed = _owner.Instrument.LoopMidi;
|
||||
ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive;
|
||||
StopButton.Disabled = !_owner.Instrument.IsMidiOpen;
|
||||
PlaybackSlider.MouseFilter = _owner.Instrument.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore;
|
||||
}
|
||||
|
||||
if (!_midiManager.IsAvailable)
|
||||
if (!_owner.MidiManager.IsAvailable)
|
||||
{
|
||||
UnavailableOverlay.Visible = true;
|
||||
// We return early as to not give the buttons behavior.
|
||||
@@ -54,8 +43,11 @@ namespace Content.Client.Instruments.UI
|
||||
}
|
||||
|
||||
InputButton.OnToggled += MidiInputButtonOnOnToggled;
|
||||
BandButton.OnPressed += BandButtonOnPressed;
|
||||
BandButton.OnToggled += BandButtonOnToggled;
|
||||
FileButton.OnPressed += MidiFileButtonOnOnPressed;
|
||||
LoopButton.OnToggled += MidiLoopButtonOnOnToggled;
|
||||
ChannelsButton.OnPressed += ChannelsButtonOnPressed;
|
||||
StopButton.OnPressed += MidiStopButtonOnPressed;
|
||||
PlaybackSlider.OnValueChanged += PlaybackSliderSeek;
|
||||
PlaybackSlider.OnKeyBindUp += PlaybackSliderKeyUp;
|
||||
@@ -63,6 +55,27 @@ namespace Content.Client.Instruments.UI
|
||||
MinSize = SetSize = new Vector2(400, 150);
|
||||
}
|
||||
|
||||
private void BandButtonOnPressed(ButtonEventArgs obj)
|
||||
{
|
||||
if (!PlayCheck())
|
||||
return;
|
||||
|
||||
_owner.OpenBandMenu();
|
||||
}
|
||||
|
||||
private void BandButtonOnToggled(ButtonToggledEventArgs obj)
|
||||
{
|
||||
if (obj.Pressed)
|
||||
return;
|
||||
|
||||
_owner.Instruments.SetMaster(_owner.Owner, null);
|
||||
}
|
||||
|
||||
private void ChannelsButtonOnPressed(ButtonEventArgs obj)
|
||||
{
|
||||
_owner.OpenChannelsMenu();
|
||||
}
|
||||
|
||||
private void InstrumentOnMidiPlaybackEnded()
|
||||
{
|
||||
MidiPlaybackSetButtonsDisabled(true);
|
||||
@@ -70,6 +83,9 @@ namespace Content.Client.Instruments.UI
|
||||
|
||||
public void MidiPlaybackSetButtonsDisabled(bool disabled)
|
||||
{
|
||||
if(disabled)
|
||||
_owner.CloseChannelsMenu();
|
||||
|
||||
LoopButton.Disabled = disabled;
|
||||
StopButton.Disabled = disabled;
|
||||
|
||||
@@ -79,8 +95,10 @@ namespace Content.Client.Instruments.UI
|
||||
|
||||
private async void MidiFileButtonOnOnPressed(ButtonEventArgs obj)
|
||||
{
|
||||
_owner.CloseBandMenu();
|
||||
|
||||
var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi"));
|
||||
await using var file = await _fileDialogManager.OpenFile(filters);
|
||||
await using var file = await _owner.FileDialogManager.OpenFile(filters);
|
||||
|
||||
// did the instrument menu get closed while waiting for the user to select a file?
|
||||
if (Disposed)
|
||||
@@ -89,7 +107,8 @@ namespace Content.Client.Instruments.UI
|
||||
// The following checks are only in place to prevent players from playing MIDI songs locally.
|
||||
// There are equivalents for these checks on the server.
|
||||
|
||||
if (file == null) return;
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
/*if (!_midiManager.IsMidiFile(filename))
|
||||
{
|
||||
@@ -107,7 +126,7 @@ namespace Content.Client.Instruments.UI
|
||||
await Task.WhenAll(Timer.Delay(100), file.CopyToAsync(memStream));
|
||||
|
||||
if (_owner.Instrument is not {} instrument
|
||||
|| !EntitySystem.Get<InstrumentSystem>().OpenMidi(instrument.Owner, memStream.GetBuffer().AsSpan(0, (int) memStream.Length), instrument))
|
||||
|| !_owner.Instruments.OpenMidi(_owner.Owner, memStream.GetBuffer().AsSpan(0, (int) memStream.Length), instrument))
|
||||
return;
|
||||
|
||||
MidiPlaybackSetButtonsDisabled(false);
|
||||
@@ -117,7 +136,7 @@ namespace Content.Client.Instruments.UI
|
||||
|
||||
private void MidiInputButtonOnOnToggled(ButtonToggledEventArgs obj)
|
||||
{
|
||||
var instrumentSystem = EntitySystem.Get<InstrumentSystem>();
|
||||
_owner.CloseBandMenu();
|
||||
|
||||
if (obj.Pressed)
|
||||
{
|
||||
@@ -126,55 +145,58 @@ namespace Content.Client.Instruments.UI
|
||||
|
||||
MidiStopButtonOnPressed(null);
|
||||
if(_owner.Instrument is {} instrument)
|
||||
instrumentSystem.OpenInput(instrument.Owner, instrument);
|
||||
_owner.Instruments.OpenInput(_owner.Owner, instrument);
|
||||
}
|
||||
else if (_owner.Instrument is { } instrument)
|
||||
{
|
||||
_owner.Instruments.CloseInput(_owner.Owner, false, instrument);
|
||||
_owner.CloseChannelsMenu();
|
||||
}
|
||||
else if(_owner.Instrument is {} instrument)
|
||||
instrumentSystem.CloseInput(instrument.Owner, false, instrument);
|
||||
}
|
||||
|
||||
private bool PlayCheck()
|
||||
{
|
||||
// TODO all of these checks should also be done server-side.
|
||||
|
||||
var instrumentEnt = _owner.Instrument?.Owner;
|
||||
var instrumentEnt = _owner.Owner;
|
||||
var instrument = _owner.Instrument;
|
||||
|
||||
// If either the entity or component are null, return.
|
||||
if (instrumentEnt == null || instrument == null)
|
||||
if (instrument == null)
|
||||
return false;
|
||||
|
||||
var localPlayer = IoCManager.Resolve<IPlayerManager>().LocalPlayer;
|
||||
var localPlayer = _owner.PlayerManager.LocalPlayer;
|
||||
|
||||
// If we don't have a player or controlled entity, we return.
|
||||
if (localPlayer?.ControlledEntity == null) return false;
|
||||
if (localPlayer?.ControlledEntity == null)
|
||||
return false;
|
||||
|
||||
// By default, allow an instrument to play itself and skip all other checks
|
||||
if (localPlayer.ControlledEntity == instrumentEnt)
|
||||
return true;
|
||||
|
||||
// If we're a handheld instrument, we might be in a container. Get it just in case.
|
||||
instrumentEnt.Value.TryGetContainerMan(out var conMan);
|
||||
instrumentEnt.TryGetContainerMan(out var conMan);
|
||||
|
||||
// If the instrument is handheld and we're not holding it, we return.
|
||||
if ((instrument.Handheld && (conMan == null
|
||||
|| conMan.Owner != localPlayer.ControlledEntity))) return false;
|
||||
if ((instrument.Handheld && (conMan == null || conMan.Owner != localPlayer.ControlledEntity)))
|
||||
return false;
|
||||
|
||||
var entSysMan = IoCManager.Resolve<IEntitySystemManager>();
|
||||
if (!entSysMan.GetEntitySystem<ActionBlockerSystem>().CanInteract(localPlayer.ControlledEntity.Value, instrumentEnt))
|
||||
if (!_owner.ActionBlocker.CanInteract(localPlayer.ControlledEntity.Value, instrumentEnt))
|
||||
return false;
|
||||
|
||||
// We check that we're in range unobstructed just in case.
|
||||
return entSysMan.GetEntitySystem<SharedInteractionSystem>().InRangeUnobstructed(localPlayer.ControlledEntity.Value, instrumentEnt.Value);
|
||||
return _owner.Interactions.InRangeUnobstructed(localPlayer.ControlledEntity.Value, instrumentEnt);
|
||||
}
|
||||
|
||||
private void MidiStopButtonOnPressed(ButtonEventArgs? obj)
|
||||
{
|
||||
MidiPlaybackSetButtonsDisabled(true);
|
||||
|
||||
if (_owner.Instrument is not { } instrument)
|
||||
if (_owner.Instrument is not {} instrument)
|
||||
return;
|
||||
|
||||
EntitySystem.Get<InstrumentSystem>().CloseMidi(instrument.Owner, false, instrument);
|
||||
_owner.Instruments.CloseMidi(_owner.Owner, false, instrument);
|
||||
_owner.CloseChannelsMenu();
|
||||
}
|
||||
|
||||
private void MidiLoopButtonOnOnToggled(ButtonToggledEventArgs obj)
|
||||
@@ -183,29 +205,45 @@ namespace Content.Client.Instruments.UI
|
||||
return;
|
||||
|
||||
_owner.Instrument.LoopMidi = obj.Pressed;
|
||||
_owner.Instrument.DirtyRenderer = true;
|
||||
_owner.Instruments.UpdateRenderer(_owner.Owner, _owner.Instrument);
|
||||
}
|
||||
|
||||
private void PlaybackSliderSeek(Range _)
|
||||
{
|
||||
// Do not seek while still grabbing.
|
||||
if (PlaybackSlider.Grabbed || _owner.Instrument is not {} instrument) return;
|
||||
if (PlaybackSlider.Grabbed || _owner.Instrument is not {} instrument)
|
||||
return;
|
||||
|
||||
EntitySystem.Get<InstrumentSystem>().SetPlayerTick(instrument.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
|
||||
_owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
|
||||
}
|
||||
|
||||
private void PlaybackSliderKeyUp(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
if (args.Function != EngineKeyFunctions.UIClick || _owner.Instrument is not {} instrument) return;
|
||||
if (args.Function != EngineKeyFunctions.UIClick || _owner.Instrument is not {} instrument)
|
||||
return;
|
||||
|
||||
EntitySystem.Get<InstrumentSystem>().SetPlayerTick(instrument.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
|
||||
_owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
_owner.CloseBandMenu();
|
||||
_owner.CloseChannelsMenu();
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
|
||||
if (_owner.Instrument == null) return;
|
||||
if (_owner.Instrument == null)
|
||||
return;
|
||||
|
||||
var hasMaster = _owner.Instrument.Master != null;
|
||||
BandButton.ToggleMode = hasMaster;
|
||||
BandButton.Pressed = hasMaster;
|
||||
BandButton.Disabled = _owner.Instrument.IsMidiOpen || _owner.Instrument.IsInputOpen;
|
||||
ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive;
|
||||
|
||||
if (!_owner.Instrument.IsMidiOpen)
|
||||
{
|
||||
@@ -214,7 +252,8 @@ namespace Content.Client.Instruments.UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlaybackSlider.Grabbed) return;
|
||||
if (PlaybackSlider.Grabbed)
|
||||
return;
|
||||
|
||||
PlaybackSlider.MaxValue = _owner.Instrument.PlayerTotalTick;
|
||||
PlaybackSlider.SetValueWithoutEvent(_owner.Instrument.PlayerTick);
|
||||
|
||||
Reference in New Issue
Block a user