1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 11:42:56 +08:00

Implement ability to switch between volume meters

This commit is contained in:
Derrick Timmermans 2021-07-04 14:47:07 +02:00
parent 49090a0d1b
commit d1553f0864
No known key found for this signature in database
GPG Key ID: 8681B60806EF4A17
4 changed files with 91 additions and 15 deletions

View File

@ -103,6 +103,9 @@ namespace osu.Game.Input.Bindings
new KeyBinding(new[] { InputKey.Alt, InputKey.Up }, GlobalAction.IncreaseVolume),
new KeyBinding(new[] { InputKey.Alt, InputKey.Down }, GlobalAction.DecreaseVolume),
new KeyBinding(new[] { InputKey.Alt, InputKey.Left }, GlobalAction.PreviousVolumeMeter),
new KeyBinding(new[] { InputKey.Alt, InputKey.Right }, GlobalAction.NextVolumeMeter),
new KeyBinding(new[] { InputKey.Control, InputKey.F4 }, GlobalAction.ToggleMute),
new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev),
@ -263,5 +266,11 @@ namespace osu.Game.Input.Bindings
[Description("Toggle skin editor")]
ToggleSkinEditor,
[Description("Previous volume meter")]
PreviousVolumeMeter,
[Description("Next volume meter")]
NextVolumeMeter,
}
}

View File

@ -30,6 +30,8 @@ namespace osu.Game.Overlays.Volume
return true;
case GlobalAction.ToggleMute:
case GlobalAction.NextVolumeMeter:
case GlobalAction.PreviousVolumeMeter:
ActionRequested?.Invoke(action);
return true;
}

View File

@ -12,6 +12,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events;
@ -27,6 +28,11 @@ namespace osu.Game.Overlays.Volume
{
public class VolumeMeter : Container, IKeyBindingHandler<GlobalAction>
{
[Resolved(canBeNull: true)]
private Bindable<VolumeMeter> focusedMeter { get; set; }
private bool isFocused => focusedMeter == null || focusedMeter.Value == this;
private CircularProgress volumeCircle;
private CircularProgress volumeCircleGlow;
@ -41,6 +47,8 @@ namespace osu.Game.Overlays.Volume
private Sample sample;
private double sampleLastPlaybackTime;
public Action<VolumeMeter> RequestFocus;
public VolumeMeter(string name, float circleSize, Color4 meterColour)
{
this.circleSize = circleSize;
@ -310,20 +318,32 @@ namespace osu.Game.Overlays.Volume
private const float transition_length = 500;
public void Focus()
{
if (focusedMeter != null)
focusedMeter.Value = this;
this.ScaleTo(1.04f, transition_length, Easing.OutExpo);
}
public void Unfocus()
{
this.ScaleTo(1f, transition_length, Easing.OutExpo);
}
protected override bool OnHover(HoverEvent e)
{
this.ScaleTo(1.04f, transition_length, Easing.OutExpo);
Focus();
return false;
}
protected override void OnHoverLost(HoverLostEvent e)
{
this.ScaleTo(1f, transition_length, Easing.OutExpo);
}
public bool OnPressed(GlobalAction action)
{
if (!IsHovered)
if (!IsHovered || !isFocused)
return false;
switch (action)

View File

@ -19,6 +19,7 @@ using osuTK.Graphics;
namespace osu.Game.Overlays
{
[Cached]
public class VolumeOverlay : VisibilityContainer
{
private const float offset = 10;
@ -32,6 +33,8 @@ namespace osu.Game.Overlays
public Bindable<bool> IsMuted { get; } = new Bindable<bool>();
private FillFlowContainer<VolumeMeter> volumeMeters;
[BackgroundDependencyLoader]
private void load(AudioManager audio, OsuColour colours)
{
@ -53,7 +56,7 @@ namespace osu.Game.Overlays
Margin = new MarginPadding(10),
Current = { BindTarget = IsMuted }
},
new FillFlowContainer
volumeMeters = new FillFlowContainer<VolumeMeter>
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
@ -61,7 +64,7 @@ namespace osu.Game.Overlays
Origin = Anchor.CentreLeft,
Spacing = new Vector2(0, offset),
Margin = new MarginPadding { Left = offset },
Children = new Drawable[]
Children = new VolumeMeter[]
{
volumeMeterEffect = new VolumeMeter("EFFECTS", 125, colours.BlueDarker),
volumeMeterMaster = new VolumeMeter("MASTER", 150, colours.PinkDarker),
@ -81,8 +84,13 @@ namespace osu.Game.Overlays
else
audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment);
});
focusedMeter.BindValueChanged(meter => meter.OldValue?.Unfocus());
}
[Cached]
private Bindable<VolumeMeter> focusedMeter = new Bindable<VolumeMeter>();
protected override void LoadComplete()
{
base.LoadComplete();
@ -93,6 +101,23 @@ namespace osu.Game.Overlays
muteButton.Current.ValueChanged += _ => Show();
}
public bool HandleAction(GlobalAction action)
{
if (!IsLoaded) return false;
switch (action)
{
case GlobalAction.DecreaseVolume:
case GlobalAction.IncreaseVolume:
return Adjust(action);
case GlobalAction.NextVolumeMeter:
return true;
}
return true;
}
public bool Adjust(GlobalAction action, float amount = 1, bool isPrecise = false)
{
if (!IsLoaded) return false;
@ -102,25 +127,32 @@ namespace osu.Game.Overlays
case GlobalAction.DecreaseVolume:
if (State.Value == Visibility.Hidden)
Show();
else if (volumeMeterMusic.IsHovered)
volumeMeterMusic.Decrease(amount, isPrecise);
else if (volumeMeterEffect.IsHovered)
volumeMeterEffect.Decrease(amount, isPrecise);
else
volumeMeterMaster.Decrease(amount, isPrecise);
focusedMeter.Value.Decrease(amount, isPrecise);
return true;
case GlobalAction.IncreaseVolume:
if (State.Value == Visibility.Hidden)
Show();
else if (volumeMeterMusic.IsHovered)
volumeMeterMusic.Increase(amount, isPrecise);
else if (volumeMeterEffect.IsHovered)
volumeMeterEffect.Increase(amount, isPrecise);
else
volumeMeterMaster.Increase(amount, isPrecise);
focusedMeter.Value.Increase(amount, isPrecise);
return true;
case GlobalAction.NextVolumeMeter:
if (State.Value == Visibility.Hidden)
Show();
else
focusShift(1);
return true;
case GlobalAction.PreviousVolumeMeter:
if (State.Value == Visibility.Hidden)
Show();
else
focusShift(-1);
return true;
case GlobalAction.ToggleMute:
Show();
muteButton.Current.Value = !muteButton.Current.Value;
@ -130,10 +162,23 @@ namespace osu.Game.Overlays
return false;
}
private void focusShift(int direction = 1)
{
Show();
var newIndex = volumeMeters.IndexOf(focusedMeter.Value) + direction;
if (newIndex < 0)
newIndex += volumeMeters.Count;
volumeMeters.Children[newIndex % volumeMeters.Count].Focus();
}
private ScheduledDelegate popOutDelegate;
public override void Show()
{
if (State.Value == Visibility.Hidden)
volumeMeterMaster.Focus();
if (State.Value == Visibility.Visible)
schedulePopOut();