* Added Jukebox, along with music for jukebox * Fixed Jukebox meta.json copyright * Removed songs I couldn't find a license for. * Renamed files to solve check failures from spaces * Added missing attributions.yml * Fixed lack of description in Jukebox * Jukebox is now constructable. * Change Jukebox menu to FancyWindow * Moved Jukebox messages out of jukebox component * Removed Jukebox OnValueChanged. * JukeboxComp now uses AutoGenerateComponentState * Removed state code, since it's auto generated * Fixed various Jukebox code to match conventions. * Updated Standard.yml to match changed song list. * fixes * Jukebox workin * Fix * Polishing * Finalising * Revert * bad * jukey * Reviews * name * Update submodule to 218.2.0 --------- Co-authored-by: iNVERTED <alextjorgensen@gmail.com>
120 lines
3.3 KiB
C#
120 lines
3.3 KiB
C#
using Content.Shared.Audio.Jukebox;
|
|
using Robust.Client.Audio;
|
|
using Robust.Client.Player;
|
|
using Robust.Shared.Audio.Components;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Content.Client.Audio.Jukebox;
|
|
|
|
public sealed class JukeboxBoundUserInterface : BoundUserInterface
|
|
{
|
|
[Dependency] private readonly IPlayerManager _player = default!;
|
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
|
|
|
[ViewVariables]
|
|
private JukeboxMenu? _menu;
|
|
|
|
public JukeboxBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
|
{
|
|
IoCManager.InjectDependencies(this);
|
|
}
|
|
|
|
protected override void Open()
|
|
{
|
|
base.Open();
|
|
|
|
_menu = new JukeboxMenu();
|
|
_menu.OnClose += Close;
|
|
_menu.OpenCentered();
|
|
|
|
_menu.OnPlayPressed += args =>
|
|
{
|
|
if (args)
|
|
{
|
|
SendMessage(new JukeboxPlayingMessage());
|
|
}
|
|
else
|
|
{
|
|
SendMessage(new JukeboxPauseMessage());
|
|
}
|
|
};
|
|
|
|
_menu.OnStopPressed += () =>
|
|
{
|
|
SendMessage(new JukeboxStopMessage());
|
|
};
|
|
|
|
_menu.OnSongSelected += SelectSong;
|
|
|
|
_menu.SetTime += SetTime;
|
|
PopulateMusic();
|
|
Reload();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reloads the attached menu if it exists.
|
|
/// </summary>
|
|
public void Reload()
|
|
{
|
|
if (_menu == null || !EntMan.TryGetComponent(Owner, out JukeboxComponent? jukebox))
|
|
return;
|
|
|
|
_menu.SetAudioStream(jukebox.AudioStream);
|
|
|
|
if (_protoManager.TryIndex(jukebox.SelectedSongId, out var songProto))
|
|
{
|
|
var length = EntMan.System<AudioSystem>().GetAudioLength(songProto.Path.Path.ToString());
|
|
_menu.SetSelectedSong(songProto.Name, (float) length.TotalSeconds);
|
|
}
|
|
else
|
|
{
|
|
_menu.SetSelectedSong(string.Empty, 0f);
|
|
}
|
|
}
|
|
|
|
public void PopulateMusic()
|
|
{
|
|
_menu?.Populate(_protoManager.EnumeratePrototypes<JukeboxPrototype>());
|
|
}
|
|
|
|
public void SelectSong(ProtoId<JukeboxPrototype> songid)
|
|
{
|
|
SendMessage(new JukeboxSelectedMessage(songid));
|
|
}
|
|
|
|
public void SetTime(float time)
|
|
{
|
|
var sentTime = time;
|
|
|
|
// You may be wondering, what the fuck is this
|
|
// Well we want to be able to predict the playback slider change, of which there are many ways to do it
|
|
// We can't just use SendPredictedMessage because it will reset every tick and audio updates every frame
|
|
// so it will go BRRRRT
|
|
// Using ping gets us close enough that it SHOULD, MOST OF THE TIME, fall within the 0.1 second tolerance
|
|
// that's still on engine so our playback position never gets corrected.
|
|
if (EntMan.TryGetComponent(Owner, out JukeboxComponent? jukebox) &&
|
|
EntMan.TryGetComponent(jukebox.AudioStream, out AudioComponent? audioComp))
|
|
{
|
|
audioComp.PlaybackPosition = time;
|
|
}
|
|
|
|
SendMessage(new JukeboxSetTimeMessage(sentTime));
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
if (!disposing)
|
|
return;
|
|
|
|
if (_menu == null)
|
|
return;
|
|
|
|
_menu.OnClose -= Close;
|
|
_menu.Dispose();
|
|
_menu = null;
|
|
}
|
|
}
|
|
|