Re-enable instruments with fallback when MIDI isn't available.

This commit is contained in:
Pieter-Jan Briers
2020-03-30 18:36:58 +02:00
parent ebe5ffe33e
commit ff36b2dcc7
3 changed files with 152 additions and 96 deletions

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Content.Shared.GameObjects.Components.Instruments; using Content.Shared.GameObjects.Components.Instruments;
using JetBrains.Annotations;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Client.Audio.Midi; using Robust.Client.Audio.Midi;
using Robust.Shared.Audio.Midi; using Robust.Shared.Audio.Midi;
@@ -28,6 +29,7 @@ namespace Content.Client.GameObjects.Components.Instruments
[Dependency] private readonly IGameTiming _timing; [Dependency] private readonly IGameTiming _timing;
#pragma warning restore 649 #pragma warning restore 649
[CanBeNull]
private IMidiRenderer _renderer; private IMidiRenderer _renderer;
private int _instrumentProgram = 1; private int _instrumentProgram = 1;
@@ -42,8 +44,14 @@ namespace Content.Client.GameObjects.Components.Instruments
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public bool LoopMidi public bool LoopMidi
{ {
get => _renderer.LoopMidi; get => _renderer?.LoopMidi ?? false;
set => _renderer.LoopMidi = value; set
{
if (_renderer != null)
{
_renderer.LoopMidi = value;
}
}
} }
/// <summary> /// <summary>
@@ -53,33 +61,41 @@ namespace Content.Client.GameObjects.Components.Instruments
public int InstrumentProgram public int InstrumentProgram
{ {
get => _instrumentProgram; get => _instrumentProgram;
set { set
{
_instrumentProgram = value; _instrumentProgram = value;
if (_renderer != null)
{
_renderer.MidiProgram = _instrumentProgram; _renderer.MidiProgram = _instrumentProgram;
} }
} }
}
/// <summary> /// <summary>
/// Whether there's a midi song being played or not. /// Whether there's a midi song being played or not.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public bool IsMidiOpen => _renderer.Status == MidiRendererStatus.File; public bool IsMidiOpen => _renderer?.Status == MidiRendererStatus.File;
/// <summary> /// <summary>
/// Whether the midi renderer is listening for midi input or not. /// Whether the midi renderer is listening for midi input or not.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public bool IsInputOpen => _renderer.Status == MidiRendererStatus.Input; public bool IsInputOpen => _renderer?.Status == MidiRendererStatus.Input;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_renderer = _midiManager.GetNewRenderer(); _renderer = _midiManager.GetNewRenderer();
if (_renderer != null)
{
_renderer.MidiProgram = _instrumentProgram; _renderer.MidiProgram = _instrumentProgram;
_renderer.TrackingEntity = Owner; _renderer.TrackingEntity = Owner;
_renderer.OnMidiPlayerFinished += () => { OnMidiPlaybackEnded?.Invoke(); }; _renderer.OnMidiPlayerFinished += () => { OnMidiPlaybackEnded?.Invoke(); };
} }
}
protected override void Shutdown() protected override void Shutdown()
{ {
@@ -93,9 +109,16 @@ namespace Content.Client.GameObjects.Components.Instruments
serializer.DataField(ref _instrumentProgram, "program", 1); serializer.DataField(ref _instrumentProgram, "program", 1);
} }
public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null) public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null,
IComponent component = null)
{ {
base.HandleMessage(message, netChannel, component); base.HandleMessage(message, netChannel, component);
if (_renderer == null)
{
return;
}
switch (message) switch (message)
{ {
case InstrumentMidiEventMessage midiEventMessage: case InstrumentMidiEventMessage midiEventMessage:
@@ -107,8 +130,8 @@ namespace Content.Client.GameObjects.Components.Instruments
case InstrumentStopMidiMessage _: case InstrumentStopMidiMessage _:
_renderer.StopAllNotes(); _renderer.StopAllNotes();
if(IsInputOpen) CloseInput(); if (IsInputOpen) CloseInput();
if(IsMidiOpen) CloseMidi(); if (IsMidiOpen) CloseMidi();
break; break;
} }
} }
@@ -116,7 +139,7 @@ namespace Content.Client.GameObjects.Components.Instruments
/// <inheritdoc cref="MidiRenderer.OpenInput"/> /// <inheritdoc cref="MidiRenderer.OpenInput"/>
public bool OpenInput() public bool OpenInput()
{ {
if (_renderer.OpenInput()) if (_renderer != null && _renderer.OpenInput())
{ {
_renderer.OnMidiEvent += RendererOnMidiEvent; _renderer.OnMidiEvent += RendererOnMidiEvent;
return true; return true;
@@ -128,28 +151,37 @@ namespace Content.Client.GameObjects.Components.Instruments
/// <inheritdoc cref="MidiRenderer.CloseInput"/> /// <inheritdoc cref="MidiRenderer.CloseInput"/>
public bool CloseInput() public bool CloseInput()
{ {
if (!_renderer.CloseInput()) return false; if (_renderer == null || !_renderer.CloseInput())
{
return false;
}
_renderer.OnMidiEvent -= RendererOnMidiEvent; _renderer.OnMidiEvent -= RendererOnMidiEvent;
return true; return true;
} }
/// <inheritdoc cref="MidiRenderer.OpenMidi(string)"/> /// <inheritdoc cref="MidiRenderer.OpenMidi(string)"/>
public bool OpenMidi(string filename) public bool OpenMidi(string filename)
{ {
if (!_renderer.OpenMidi(filename)) return false; if (_renderer == null || !_renderer.OpenMidi(filename))
{
return false;
}
_renderer.OnMidiEvent += RendererOnMidiEvent; _renderer.OnMidiEvent += RendererOnMidiEvent;
return true; return true;
} }
/// <inheritdoc cref="MidiRenderer.CloseMidi"/> /// <inheritdoc cref="MidiRenderer.CloseMidi"/>
public bool CloseMidi() public bool CloseMidi()
{ {
if (!_renderer.CloseMidi()) return false; if (_renderer == null || !_renderer.CloseMidi())
{
return false;
}
_renderer.OnMidiEvent -= RendererOnMidiEvent; _renderer.OnMidiEvent -= RendererOnMidiEvent;
return true; return true;
} }
/// <summary> /// <summary>

View File

@@ -1,10 +1,13 @@
using Content.Client.GameObjects.Components.Instruments; using Content.Client.GameObjects.Components.Instruments;
using Content.Client.UserInterface;
using Robust.Client.Audio.Midi; using Robust.Client.Audio.Midi;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Interfaces.UserInterface; using Robust.Client.Interfaces.UserInterface;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log; using Robust.Shared.Log;
using Robust.Shared.Maths; using Robust.Shared.Maths;
@@ -27,7 +30,7 @@ namespace Content.Client.Instruments
public InstrumentMenu(InstrumentBoundUserInterface owner) public InstrumentMenu(InstrumentBoundUserInterface owner)
{ {
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
Title = "Instrument"; Title = Loc.GetString("Instrument");
_owner = owner; _owner = owner;
@@ -55,7 +58,7 @@ namespace Content.Client.Instruments
midiInputButton = new Button() midiInputButton = new Button()
{ {
Text = "MIDI Input", Text = Loc.GetString("MIDI Input"),
TextAlign = Label.AlignMode.Center, TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
@@ -73,7 +76,7 @@ namespace Content.Client.Instruments
var midiFileButton = new Button() var midiFileButton = new Button()
{ {
Text = "Open File", Text = Loc.GetString("Play MIDI File"),
TextAlign = Label.AlignMode.Center, TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
@@ -91,7 +94,7 @@ namespace Content.Client.Instruments
midiLoopButton = new Button() midiLoopButton = new Button()
{ {
Text = "Loop", Text = Loc.GetString("Loop"),
TextAlign = Label.AlignMode.Center, TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
@@ -110,7 +113,7 @@ namespace Content.Client.Instruments
midiStopButton = new Button() midiStopButton = new Button()
{ {
Text = "Stop", Text = Loc.GetString("Stop"),
TextAlign = Label.AlignMode.Center, TextAlign = Label.AlignMode.Center,
SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsHorizontal = SizeFlags.FillExpand,
SizeFlagsStretchRatio = 1, SizeFlagsStretchRatio = 1,
@@ -132,6 +135,26 @@ namespace Content.Client.Instruments
margin.AddChild(vBox); margin.AddChild(vBox);
if (!_midiManager.IsAvailable)
{
margin.AddChild(new PanelContainer
{
MouseFilter = MouseFilterMode.Stop,
PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.90f)},
Children =
{
new Label
{
Align = Label.AlignMode.Center,
SizeFlagsVertical = SizeFlags.ShrinkCenter,
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
StyleClasses = {NanoStyle.StyleClassLabelBig},
Text = Loc.GetString("MIDI support is currently\nnot available on your platform.")
}
}
});
}
Contents.AddChild(margin); Contents.AddChild(margin);
} }
@@ -148,7 +171,8 @@ namespace Content.Client.Instruments
private async void MidiFileButtonOnOnPressed(BaseButton.ButtonEventArgs obj) private async void MidiFileButtonOnOnPressed(BaseButton.ButtonEventArgs obj)
{ {
var filename = await _fileDialogManager.OpenFile(); var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi"));
var filename = await _fileDialogManager.OpenFile(filters);
if (filename == null) return; if (filename == null) return;
@@ -160,7 +184,7 @@ namespace Content.Client.Instruments
if (!_owner.Instrument.OpenMidi(filename)) return; if (!_owner.Instrument.OpenMidi(filename)) return;
MidiPlaybackSetButtonsDisabled(false); MidiPlaybackSetButtonsDisabled(false);
if(midiInputButton.Pressed) if (midiInputButton.Pressed)
midiInputButton.Pressed = false; midiInputButton.Pressed = false;
} }

View File

@@ -1,70 +1,70 @@
# - type: entity - type: entity
# name: BaseInstrument name: BaseInstrument
# id: BaseInstrument id: BaseInstrument
# abstract: true abstract: true
# components: components:
# - type: Instrument - type: Instrument
# handheld: false handheld: false
#
# - type: Clickable - type: Clickable
# - type: InteractionOutline - type: InteractionOutline
#
# - type: Collidable - type: Collidable
# shapes: shapes:
# - !type:PhysShapeAabb - !type:PhysShapeAabb
# layer: 31 layer: 31
#
# - type: SnapGrid - type: SnapGrid
# offset: Center offset: Center
#
# - type: Damageable - type: Damageable
# - type: Destructible - type: Destructible
# thresholdvalue: 50 thresholdvalue: 50
#
# - type: UserInterface - type: UserInterface
# interfaces: interfaces:
# - key: enum.InstrumentUiKey.Key - key: enum.InstrumentUiKey.Key
# type: InstrumentBoundUserInterface type: InstrumentBoundUserInterface
#
# - type: entity - type: entity
# name: Piano name: Piano
# parent: BaseInstrument parent: BaseInstrument
# id: PianoInstrument id: PianoInstrument
# description: Play Needles Piano Now. description: Play Needles Piano Now.
# components: components:
# - type: Instrument - type: Instrument
# program: 1 program: 1
# - type: Sprite - type: Sprite
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: piano state: piano
# - type: Icon - type: Icon
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: piano state: piano
#
# - type: entity - type: entity
# name: Minimoog name: Minimoog
# parent: BaseInstrument parent: BaseInstrument
# id: MinimoogInstrument id: MinimoogInstrument
# components: components:
# - type: Instrument - type: Instrument
# program: 7 program: 7
# - type: Sprite - type: Sprite
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: minimoog state: minimoog
# - type: Icon - type: Icon
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: minimoog state: minimoog
#
# - type: entity - type: entity
# name: Xylophone name: Xylophone
# parent: BaseInstrument parent: BaseInstrument
# id: XylophoneInstrument id: XylophoneInstrument
# components: components:
# - type: Instrument - type: Instrument
# program: 13 program: 13
# - type: Sprite - type: Sprite
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: xylophone state: xylophone
# - type: Icon - type: Icon
# sprite: Objects/Instruments/musician.rsi sprite: Objects/Instruments/musician.rsi
# state: xylophone state: xylophone