diff --git a/Content.Client/BoomBox/UI/BoomBoxBoundUi.cs b/Content.Client/BoomBox/UI/BoomBoxBoundUi.cs
index 1144f2c865f..b49009e8320 100644
--- a/Content.Client/BoomBox/UI/BoomBoxBoundUi.cs
+++ b/Content.Client/BoomBox/UI/BoomBoxBoundUi.cs
@@ -26,6 +26,12 @@ protected override void Open()
_window.PlusVolButtonPressed += OnPlusVolButtonPressed;
_window.StartButtonPressed += OnStartButtonPressed;
_window.StopButtonPressed += OnStopButtonPressed;
+ _window.PlaybackSliderChanged += OnPlaybackSliderChanged;
+ }
+
+ private void OnPlaybackSliderChanged(float newPosition)
+ {
+ SendMessage(new BoomBoxSetTimeMessage(newPosition)); // Отправка сообщения при изменении ползунка
}
private void OnMinusVolButtonPressed()
@@ -64,4 +70,4 @@ protected override void Dispose(bool disposing)
if (disposing)
_window?.Dispose();
}
-}
\ No newline at end of file
+}
diff --git a/Content.Client/BoomBox/UI/BoomBoxWindow.xaml b/Content.Client/BoomBox/UI/BoomBoxWindow.xaml
index fac87372437..0b5fb520a9a 100644
--- a/Content.Client/BoomBox/UI/BoomBoxWindow.xaml
+++ b/Content.Client/BoomBox/UI/BoomBoxWindow.xaml
@@ -1,7 +1,7 @@
+ MinSize="280 130"
+ SetSize="280 130">
+
-
\ No newline at end of file
+
diff --git a/Content.Client/BoomBox/UI/BoomBoxWindow.xaml.cs b/Content.Client/BoomBox/UI/BoomBoxWindow.xaml.cs
index b87a1937eb7..4f36a9c5dad 100644
--- a/Content.Client/BoomBox/UI/BoomBoxWindow.xaml.cs
+++ b/Content.Client/BoomBox/UI/BoomBoxWindow.xaml.cs
@@ -13,6 +13,9 @@ public sealed partial class BoomBoxWindow : DefaultWindow
public event Action? PlusVolButtonPressed;
public event Action? StartButtonPressed;
public event Action? StopButtonPressed;
+ public event Action? PlaybackSliderChanged;
+
+ private bool _isSliderDragging = false;
public BoomBoxWindow()
{
@@ -22,6 +25,7 @@ public BoomBoxWindow()
PlusVolButton.OnPressed += _ => PlusVolButtonPressed?.Invoke();
StartButton.OnPressed += _ => StartButtonPressed?.Invoke();
StopButton.OnPressed += _ => StopButtonPressed?.Invoke();
+ PlaybackSlider.OnValueChanged += args => PlaybackSliderChanged?.Invoke(args.Value);
}
public void UpdateState(BoomBoxUiState state)
@@ -30,5 +34,8 @@ public void UpdateState(BoomBoxUiState state)
PlusVolButton.Disabled = !state.CanPlusVol;
StartButton.Disabled = !state.CanStart;
StopButton.Disabled = !state.CanStop;
+
+ PlaybackSlider.MaxValue = state.SoundDuration;
+ PlaybackSlider.SetValueWithoutEvent(state.PlaybackPosition);
}
-}
\ No newline at end of file
+}
diff --git a/Content.Server/BoomBox/BoomBoxComponent.cs b/Content.Server/BoomBox/BoomBoxComponent.cs
index 87f87d49e1c..1735493164f 100644
--- a/Content.Server/BoomBox/BoomBoxComponent.cs
+++ b/Content.Server/BoomBox/BoomBoxComponent.cs
@@ -36,4 +36,6 @@ public sealed partial class BoomBoxComponent : Component
[DataField("slots")]
public Dictionary Slots = new();
-}
\ No newline at end of file
+ public float PlaybackPosition = 0f;
+ public float SoundDuration = 0f;
+}
diff --git a/Content.Server/BoomBox/BoomBoxSystem.cs b/Content.Server/BoomBox/BoomBoxSystem.cs
index ae3fac1e40c..891cb605414 100644
--- a/Content.Server/BoomBox/BoomBoxSystem.cs
+++ b/Content.Server/BoomBox/BoomBoxSystem.cs
@@ -55,13 +55,44 @@ public override void Initialize()
SubscribeLocalEvent(OnMinusVolButtonPressed);
SubscribeLocalEvent(OnStartButtonPressed);
SubscribeLocalEvent(OnStopButtonPressed);
+ SubscribeLocalEvent(OnSetTimeMessage);
}
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var component))
+ {
+ if (component.Stream != null && _audioSystem.IsPlaying(component.Stream))
+ {
+ component.PlaybackPosition += frameTime;
+ UpdateUserInterface(uid, component);
+
+ if (component.PlaybackPosition >= component.SoundDuration)
+ {
+ StopPlay(uid, component);
+ component.PlaybackPosition = 0f;
+ }
+ }
+ }
+ }
+
+ private void OnSetTimeMessage(EntityUid uid, BoomBoxComponent component, BoomBoxSetTimeMessage args)
+ {
+ if (component.Stream != null)
+ {
+ _audioSystem.SetPlaybackPosition(component.Stream, args.PlaybackPosition);
+ component.PlaybackPosition = args.PlaybackPosition;
+ }
+
+ UpdateUserInterface(uid, component);
+ }
// This method makes it possible to insert cassettes into the boombox
private void OnComponentInit(EntityUid uid, BoomBoxComponent component, ComponentInit args)
{
-
foreach (var slot in component.Slots)
{
_itemSlotsSystem.AddItemSlot(uid, slot.Key, slot.Value);
@@ -91,6 +122,8 @@ private void OnItemRemoved(EntityUid uid, BoomBoxComponent comp, EntRemovedFromC
// We change the value of this field to prevent the boombox from being turned on without a cassette.
comp.Inserted = false;
comp.Enabled = false;
+ comp.PlaybackPosition = 0f;
+ UpdateUserInterface(uid, comp);
}
// This method is an intermediate step where we embed additional checks.
@@ -106,14 +139,11 @@ private void UpdateSoundPath(EntityUid uid, BoomBoxComponent comp)
// This method updates the path to the music being played. That is why the initial value of the field is not particularly important
private void AddCurrentSoundPath(EntityUid uid, BoomBoxComponent comp, EntityUid added)
{
-
- var tagComp = EnsureComp(uid);
-
if (!TryComp(added, out var BoomBoxTapeComp) || BoomBoxTapeComp.SoundPath is null)
return;
-
comp.SoundPath = BoomBoxTapeComp.SoundPath;
+ comp.SoundDuration = (float) _audioSystem.GetAudioLength(comp.SoundPath).TotalSeconds;
}
private void OnMinusVolButtonPressed(EntityUid uid, BoomBoxComponent component, BoomBoxMinusVolMessage args)
@@ -141,8 +171,6 @@ private void OnToggleInterface(EntityUid uid, BoomBoxComponent component, AfterA
UpdateUserInterface(uid, component);
}
- // ----------------------------------------------------------------------------------------------------------------
-
private void UpdateUserInterface(EntityUid uid, BoomBoxComponent? component = null)
{
if (!Resolve(uid, ref component))
@@ -178,8 +206,7 @@ private void UpdateUserInterface(EntityUid uid, BoomBoxComponent? component = nu
canStop = false;
}
-
- var state = new BoomBoxUiState(canPlusVol, canMinusVol, canStop, canStart);
+ var state = new BoomBoxUiState(canPlusVol, canMinusVol, canStop, canStart, component.PlaybackPosition, component.SoundDuration);
_userInterface.SetUiState(uid, BoomBoxUiKey.Key, state);
}
@@ -222,6 +249,7 @@ private void StartPlay(EntityUid uid, BoomBoxComponent? component = null)
// We play music with these parameters. Be sure to set "WithLoop(true)" this will allow the music to play indefinitely.
component.Stream = _audioSystem.PlayPvs(component.SoundPath, uid, AudioParams.Default.WithVolume(component.Volume).WithLoop(true).WithMaxDistance(7f))?.Entity;
+ component.PlaybackPosition = 0f;
}
_signalSystem.InvokePort(uid, component.Port);
@@ -243,8 +271,8 @@ private void StopPlay(EntityUid uid, BoomBoxComponent? component = null)
// Turning off the looped audio stream
component.Stream = _audioSystem.Stop(component.Stream);
+ component.PlaybackPosition = 0f;
}
-
_signalSystem.InvokePort(uid, component.Port);
UpdateUserInterface(uid, component);
diff --git a/Content.Shared/BoomBox/SharedBoomBox.cs b/Content.Shared/BoomBox/SharedBoomBox.cs
index 183fa3fc30a..0e554bc71fa 100644
--- a/Content.Shared/BoomBox/SharedBoomBox.cs
+++ b/Content.Shared/BoomBox/SharedBoomBox.cs
@@ -15,17 +15,34 @@ public sealed class BoomBoxUiState : BoundUserInterfaceState
public bool CanMinusVol { get; }
public bool CanStop { get; }
public bool CanStart { get; }
+ public float PlaybackPosition { get; }
+ public float SoundDuration { get; }
public BoomBoxUiState(
bool canPlusVol,
bool canMinusVol,
bool canStop,
- bool canStart)
+ bool canStart,
+ float playbackPosition,
+ float soundDuration)
{
CanPlusVol = canPlusVol;
CanMinusVol = canMinusVol;
CanStop = canStop;
CanStart = canStart;
+ PlaybackPosition = playbackPosition;
+ SoundDuration = soundDuration;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class BoomBoxSetTimeMessage : BoundUserInterfaceMessage
+{
+ public float PlaybackPosition { get; }
+
+ public BoomBoxSetTimeMessage(float playbackPosition)
+ {
+ PlaybackPosition = playbackPosition;
}
}
@@ -47,4 +64,4 @@ public sealed class BoomBoxStartMessage : BoundUserInterfaceMessage
[Serializable, NetSerializable]
public sealed class BoomBoxStopMessage : BoundUserInterfaceMessage
{
-}
\ No newline at end of file
+}