mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Implement ability to switch between volume meters
This commit is contained in:
parent
49090a0d1b
commit
d1553f0864
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user