Skip to content

Commit

Permalink
first
Browse files Browse the repository at this point in the history
  • Loading branch information
AwareFoxy committed Dec 5, 2024
1 parent 82fdd47 commit 127e69d
Show file tree
Hide file tree
Showing 10 changed files with 813 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Content.Client/Administration/UI/Tabs/AdminTab/AdminTab.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<cc:UICommandButton Command="callshuttle" Text="{Loc admin-player-actions-window-shuttle}" WindowType="{x:Type at:AdminShuttleWindow}"/>
<cc:CommandButton Command="adminlogs" Text="{Loc admin-player-actions-window-admin-logs}"/>
<cc:CommandButton Command="faxui" Text="{Loc admin-player-actions-window-admin-fax}"/>
<!-- Corvax-Next-AdminAudioPanel-Start -->
<cc:CommandButton Command="audiopanel" Text="{Loc admin-player-actions-window-audio-panel}"/>
<!-- Corvax-Next-AdminAudioPanel-End -->
</GridContainer>
</BoxContainer>
</Control>
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
using Content.Client.Eui;
using Content.Client._CorvaxNext.Administration.UI.Audio.Widgets;
using Content.Shared.Eui;
using Content.Shared._CorvaxNext.Administration.UI.Audio;
using Robust.Shared.Audio.Components;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Utility;

namespace Content.Client._CorvaxNext.Administration.UI.Audio;

public sealed partial class AdminAudioPanelEui : BaseEui
{
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IEntityManager _entity = default!;

private SharedAudioSystem _audioSystem;

private AdminAudioPanelEuiState? _state = null;
private AdminAudioPanel? _adminAudioPanel = null;

public AdminAudioPanelEui() : base()
{
IoCManager.InjectDependencies(this);
_audioSystem = _entitySystem.GetEntitySystem<SharedAudioSystem>();
}

public override void HandleState(EuiStateBase state)
{
if (state is AdminAudioPanelEuiState adminAudioPanelState)
{
_state = adminAudioPanelState;
UpdateUI();
}
}

public override void Opened()
{
_adminAudioPanel = new AdminAudioPanel();
_adminAudioPanel.OpenCentered();

_adminAudioPanel.OnPlayButtonEnabled += () => Play();
_adminAudioPanel.OnPauseButtonEnabled += () => Pause();
_adminAudioPanel.OnStopButtonEnabled += () => Stop();
_adminAudioPanel.OnAddTrackPressed += (track) => AddTrack(track);
_adminAudioPanel.OnPlaybackReleased += (ratio) => SetPlayback(ratio);
_adminAudioPanel.OnGlobalCheckboxToggled += (toggled) => ChangeGlobalToggled(toggled);
_adminAudioPanel.OnVolumeLineTextChanged += (volume) => SetVolume(volume);
_adminAudioPanel.OnSelectPlayer += (guid) => SelectPlayer(guid);
_adminAudioPanel.OnUnselectPlayer += (guid) => UnselectPlayer(guid);
}

public override void Closed()
{
if (_adminAudioPanel != null)
_adminAudioPanel.Close();
}

public void Play()
{
var message = new AdminAudioPanelEuiMessage.Play();
SendMessage(message);
}

public void Stop()
{
var message = new AdminAudioPanelEuiMessage.Stop();
SendMessage(message);
}

public void Pause()
{
var message = new AdminAudioPanelEuiMessage.Pause();
SendMessage(message);
}

public void SetPlayback(float ratio)
{
var message = new AdminAudioPanelEuiMessage.SetPlaybackPosition(ratio);
SendMessage(message);
}

public void AddTrack(string track)
{
var message = new AdminAudioPanelEuiMessage.AddTrack(track);
SendMessage(message);
}

public void ChangeGlobalToggled(bool toggled)
{
var message = new AdminAudioPanelEuiMessage.GlobalToggled(toggled);
SendMessage(message);
}

public void SetVolume(float volume)
{
var message = new AdminAudioPanelEuiMessage.SetVolume(volume);
SendMessage(message);
}

private void SelectPlayer(Guid player)
{
var message = new AdminAudioPanelEuiMessage.SelectPlayer(player);
SendMessage(message);
}

private void UnselectPlayer(Guid player)
{
var message = new AdminAudioPanelEuiMessage.UnselectPlayer(player);
SendMessage(message);
}

private void UpdateUI()
{
if (_adminAudioPanel is not { })
return;

if (_state is not { })
return;

var audioEntity = _entity.GetEntity(_state.Audio);

_adminAudioPanel.SetAudioStream(audioEntity);
_adminAudioPanel.UpdateGlobalToggled(_state.Global);
_adminAudioPanel.UpdatePlayersContainer(_state.Players, _state.SelectedPlayers);
_adminAudioPanel.UpdatePlayingState(_state.Playing);
_adminAudioPanel.UpdateQueue(_state.Queue);
_adminAudioPanel.UpdateVolume(_state.Volume);

if (_entity.TryGetComponent<AudioComponent>(audioEntity, out var audio))
{
_adminAudioPanel.UpdateCurrentTrackLabel(audio.FileName);
}
else
{
_adminAudioPanel.UpdateCurrentTrackLabel(Loc.GetString("admin-audio-panel-track-name-nothing-playing"));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<widgets:AdminAudioPanel xmlns="https://spacestation14.io"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:widgets="clr-namespace:Content.Client._CorvaxNext.Administration.UI.Audio.Widgets"
Title="{Loc 'admin-audio-panel-title'}"
SetSize="800 300"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Content.Client._CorvaxNext.Administration.UI.Audio.Widgets.AdminAudioPanel">
<BoxContainer Margin="4 0" Orientation="Horizontal">
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" SetWidth="250">
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#202028" />
</PanelContainer.PanelOverride>
<BoxContainer Name="TrackList" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<!-- Filled from .xaml.cs -->
</BoxContainer>
</PanelContainer>
<Control />
</ScrollContainer>
<BoxContainer Orientation="Vertical" MaxWidth="250">
<BoxContainer Orientation="Vertical">
<Label Text="{Loc 'admin-audio-panel-current-track-label'}" />
<Label Name="TrackName" Text="{Loc 'admin-audio-panel-track-name-nothing-playing'}" ClipText="True" />
<Slider Name="PlaybackSlider" HorizontalExpand="True" />
</BoxContainer>
<Label Name="DurationLabel" Text="00:00 / 00:00" HorizontalAlignment="Left" HorizontalExpand="True" />
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="False">
<Button Name="PlayButton" Text="{Loc 'admin-audio-panel-button-play-text'}" ToggleMode="True" />
<Button Name="PauseButton" Text="{Loc 'admin-audio-panel-button-pause-text'}" />
<Button Name="StopButton" Text="{Loc 'admin-audio-panel-button-stop-text'}" />
</BoxContainer>
<LineEdit Name="VolumeLine" HorizontalExpand="True" PlaceHolder="{Loc 'admin-audio-panel-volume-line-placeholder'}" Editable="True" />
<CheckBox Name="GlobalCheckbox" Text="{Loc 'admin-audio-panel-toggle-global-checkbox-label'}" />
<Control VerticalExpand="True" />
<LineEdit Name="TrackPathLine" HorizontalExpand="True" PlaceHolder="{Loc 'admin-audio-panel-trackpath-line-placeholder'}" Editable="True" />
<Button Name="AddTrackButton" Text="{Loc 'admin-audio-panel-add-track-button-text'}" />
</BoxContainer>
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" SetWidth="200">
<PanelContainer HorizontalExpand="True">
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#202028" />
</PanelContainer.PanelOverride>
<BoxContainer Name="PlayersContainer" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True">
<!-- Filled from .xaml.cs -->
</BoxContainer>
</PanelContainer>
</ScrollContainer>
</BoxContainer>
</widgets:AdminAudioPanel>
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
using Robust.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Utility;
using System.Linq;
using Robust.Shared.Timing;
using Robust.Shared.Audio.Components;
using Robust.Shared.Audio.Systems;

namespace Content.Client._CorvaxNext.Administration.UI.Audio.Widgets;

[GenerateTypedNameReferences]
public sealed partial class AdminAudioPanel : DefaultWindow
{
[Dependency] private readonly IEntityManager _entity = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;

private readonly SharedAudioSystem _audioSystem;

public event Action? OnPlayButtonEnabled;
public event Action? OnStopButtonEnabled;
public event Action? OnPauseButtonEnabled;
public event Action<float>? OnPlaybackReleased;
public event Action<float>? OnVolumeLineTextChanged;
public event Action<string>? OnAddTrackPressed;
public event Action<bool>? OnGlobalCheckboxToggled;
public event Action<Guid>? OnSelectPlayer;
public event Action<Guid>? OnUnselectPlayer;

private string _volumeLineText = "";
private EntityUid _audio;

public AdminAudioPanel()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);

_audioSystem = _entitySystem.GetEntitySystem<SharedAudioSystem>();

PlayButton.OnToggled += (args) =>
{
if (args.Button.Pressed)
{
OnPlayButtonEnabled?.Invoke();
}
else
{
PlayButton.Pressed = true;
}
};
StopButton.OnPressed += (args) =>
{
if (!PlayButton.Pressed)
return;

OnStopButtonEnabled?.Invoke();
PlayButton.Pressed = false;
};
PauseButton.OnPressed += (args) =>
{
if (!PlayButton.Pressed)
return;

OnPauseButtonEnabled?.Invoke();
PlayButton.Pressed = false;
};
PlaybackSlider.OnReleased += (slider) => OnPlaybackReleased?.Invoke(slider.Value);
VolumeLine.OnTextEntered += (args) =>
{
// performs validation of text the user is typing to field
// doesn't let type something that isn't a parsible value
if (float.TryParse(args.Text, out var result))
{
_volumeLineText = args.Text;
OnVolumeLineTextChanged?.Invoke(result);
}
else
{
args.Control.SetText(_volumeLineText);
}
};
AddTrackButton.OnPressed += (args) =>
{
OnAddTrackPressed?.Invoke(TrackPathLine.Text);
TrackPathLine.SetText("");
};
GlobalCheckbox.OnToggled += (args) => OnGlobalCheckboxToggled?.Invoke(args.Pressed);
}

public void SetAudioStream(EntityUid audio)
{
_audio = audio;
}

protected override void FrameUpdate(FrameEventArgs args)
{
if (_entity.TryGetComponent<AudioComponent>(_audio, out var audio))
{
var currentTrackLength = _audioSystem.GetAudioLength(audio.FileName);
var playbackPosition = TimeSpan.FromSeconds(audio.PlaybackPosition);

UpdateDurationLabel(playbackPosition, currentTrackLength);
if (!PlaybackSlider.Grabbed)
UpdatePlaybackPosition(currentTrackLength, playbackPosition);
}
}

public void UpdatePlayersContainer(Dictionary<Guid, string> players, HashSet<Guid> selectedPlayers)
{
PlayersContainer.RemoveAllChildren();

foreach (var player in players)
{
var newButton = new Button
{
ClipText = true,
ToggleMode = true,
Text = player.Value,
HorizontalExpand = true,
Pressed = selectedPlayers.FirstOrNull(selectedPlayer => selectedPlayer == player.Key) != null,
Disabled = GlobalCheckbox.Pressed,
};
newButton.OnToggled += (args) =>
{
if (args.Pressed)
{
OnSelectPlayer?.Invoke(player.Key);
}
else
{
OnUnselectPlayer?.Invoke(player.Key);
}
};

PlayersContainer.AddChild(newButton);
}
}

public void UpdatePlayingState(bool playing)
{
PlayButton.Pressed = playing;
}

public void UpdateGlobalToggled(bool toggled)
{
GlobalCheckbox.Pressed = toggled;
}

public void UpdatePlaybackPosition(TimeSpan currentTrackLength, TimeSpan playbackPosition)
{
PlaybackSlider.MaxValue = (float)currentTrackLength.TotalSeconds;
PlaybackSlider.SetValueWithoutEvent((float)playbackPosition.TotalSeconds);
}

public void UpdateDurationLabel(TimeSpan playbackPosition, TimeSpan currentTrackLength)
{
DurationLabel.Text = $@"{playbackPosition:mm\:ss} / {currentTrackLength:mm\:ss}";
}

public void UpdateCurrentTrackLabel(string currentTrack)
{
TrackName.Text = currentTrack.Split("/").Last();
}

public void UpdateQueue(Queue<string> queue)
{
TrackList.RemoveAllChildren();

foreach (var track in queue.ToList())
{
var label = new Label()
{
Text = track,
};
TrackList.AddChild(label);
}
}

public void UpdateVolume(float volume)
{
VolumeLine.SetText(volume.ToString());
_volumeLineText = volume.ToString();
}
}
Loading

0 comments on commit 127e69d

Please sign in to comment.