1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 10:23:03 +08:00

Merge branch 'master' into mod-grow-improvement

This commit is contained in:
Dean Herbert 2019-06-12 13:18:02 +09:00 committed by GitHub
commit b29b1bf254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 266 additions and 242 deletions

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Desktop.Overlays; using osu.Desktop.Overlays;
using osu.Framework.Graphics.Containers;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game; using osu.Game;
using osuTK.Input; using osuTK.Input;
@ -56,7 +55,7 @@ namespace osu.Desktop
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v => LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, v =>
{ {
Add(v); Add(v);
v.State = Visibility.Visible; v.Show();
}); });
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows) if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
@ -74,13 +73,11 @@ namespace osu.Desktop
{ {
case Intro _: case Intro _:
case MainMenu _: case MainMenu _:
if (versionManager != null) versionManager?.Show();
versionManager.State = Visibility.Visible;
break; break;
default: default:
if (versionManager != null) versionManager?.Hide();
versionManager.State = Visibility.Hidden;
break; break;
} }
} }

View File

@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
{ {
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return new CatchDifficultyAttributes { Mods = mods }; return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
// this is the same as osu!, so there's potential to share the implementation... maybe // this is the same as osu!, so there's potential to share the implementation... maybe
double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
@ -41,7 +41,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty
StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor, StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor,
Mods = mods, Mods = mods,
ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0,
MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)) MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)),
Skills = skills
}; };
} }

View File

@ -379,8 +379,8 @@ namespace osu.Game.Rulesets.Catch.UI
X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1); X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * speed, 0, 1);
// Correct overshooting. // Correct overshooting.
if (hyperDashDirection > 0 && hyperDashTargetPosition < X || if ((hyperDashDirection > 0 && hyperDashTargetPosition < X) ||
hyperDashDirection < 0 && hyperDashTargetPosition > X) (hyperDashDirection < 0 && hyperDashTargetPosition > X))
{ {
X = hyperDashTargetPosition; X = hyperDashTargetPosition;
SetHyperDashState(); SetHyperDashState();

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
{ {
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return new ManiaDifficultyAttributes { Mods = mods }; return new ManiaDifficultyAttributes { Mods = mods, Skills = skills };
return new ManiaDifficultyAttributes return new ManiaDifficultyAttributes
{ {
@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
Mods = mods, Mods = mods,
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate,
Skills = skills
}; };
} }

View File

@ -46,11 +46,11 @@ namespace osu.Game.Rulesets.Osu.Tests
AddStep("move mouse away", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.TopLeft)); AddStep("move mouse away", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.TopLeft));
AddStep("click", () => osuInputManager.GameClick()); AddStep("click", () => osuInputManager.GameClick());
AddAssert("not dismissed", () => !resumeFired && resume.State == Visibility.Visible); AddAssert("not dismissed", () => !resumeFired && resume.State.Value == Visibility.Visible);
AddStep("move mouse back", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre)); AddStep("move mouse back", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre));
AddStep("click", () => osuInputManager.GameClick()); AddStep("click", () => osuInputManager.GameClick());
AddAssert("dismissed", () => resumeFired && resume.State == Visibility.Hidden); AddAssert("dismissed", () => resumeFired && resume.State.Value == Visibility.Hidden);
} }
private class ManualOsuInputManager : OsuInputManager private class ManualOsuInputManager : OsuInputManager

View File

@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
break; break;
if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance
|| stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance) || (stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance))
{ {
stackBaseIndex = n; stackBaseIndex = n;

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
{ {
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return new OsuDifficultyAttributes { Mods = mods }; return new OsuDifficultyAttributes { Mods = mods, Skills = skills };
double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier;
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
@ -50,7 +50,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
SpeedStrain = speedRating, SpeedStrain = speedRating,
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5, ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
OverallDifficulty = (80 - hitWindowGreat) / 6, OverallDifficulty = (80 - hitWindowGreat) / 6,
MaxCombo = maxCombo MaxCombo = maxCombo,
Skills = skills
}; };
} }

View File

@ -37,11 +37,11 @@ namespace osu.Game.Rulesets.Osu.Mods
if (time < osuHit.HitObject.StartTime - relax_leniency) continue; if (time < osuHit.HitObject.StartTime - relax_leniency) continue;
if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit)
continue; continue;
requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime);
requiresHold |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner;
} }
if (requiresHit) if (requiresHit)

View File

@ -6,7 +6,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.OpenGL.Buffers; using osu.Framework.Graphics.Batches;
using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.OpenGL.Vertices;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders; using osu.Framework.Graphics.Shaders;
@ -57,7 +57,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
// InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node // InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node
// This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms // This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms
parts[i].InvalidationID = 1; parts[i].InvalidationID = 1;
parts[i].WasUpdated = true;
} }
} }
@ -149,7 +148,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
public Vector2 Position; public Vector2 Position;
public float Time; public float Time;
public long InvalidationID; public long InvalidationID;
public bool WasUpdated;
} }
private class TrailDrawNode : DrawNode private class TrailDrawNode : DrawNode
@ -164,16 +162,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private readonly TrailPart[] parts = new TrailPart[max_sprites]; private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2 size; private Vector2 size;
private readonly VertexBuffer<TexturedTrailVertex> vertexBuffer = new QuadVertexBuffer<TexturedTrailVertex>(max_sprites, BufferUsageHint.DynamicDraw); private readonly VertexBatch<TexturedTrailVertex> vertexBatch = new QuadBatch<TexturedTrailVertex>(max_sprites, 1);
public TrailDrawNode(CursorTrail source) public TrailDrawNode(CursorTrail source)
: base(source) : base(source)
{ {
for (int i = 0; i < max_sprites; i++) for (int i = 0; i < max_sprites; i++)
{
parts[i].InvalidationID = 0; parts[i].InvalidationID = 0;
parts[i].WasUpdated = false;
}
} }
public override void ApplyState() public override void ApplyState()
@ -194,56 +189,29 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
public override void Draw(Action<TexturedVertex2D> vertexAction) public override void Draw(Action<TexturedVertex2D> vertexAction)
{ {
shader.GetUniform<float>("g_FadeClock").UpdateValue(ref time);
int updateStart = -1, updateEnd = 0;
for (int i = 0; i < parts.Length; ++i)
{
if (parts[i].WasUpdated)
{
if (updateStart == -1)
updateStart = i;
updateEnd = i + 1;
int start = i * 4;
int end = start;
Vector2 pos = parts[i].Position;
float localTime = parts[i].Time;
DrawQuad(
texture,
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
DrawColourInfo.Colour,
null,
v => vertexBuffer.Vertices[end++] = new TexturedTrailVertex
{
Position = v.Position,
TexturePosition = v.TexturePosition,
Time = localTime + 1,
Colour = v.Colour,
});
parts[i].WasUpdated = false;
}
else if (updateStart != -1)
{
vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4);
updateStart = -1;
}
}
// Update all remaining vertices that have been changed.
if (updateStart != -1)
vertexBuffer.UpdateRange(updateStart * 4, updateEnd * 4);
base.Draw(vertexAction); base.Draw(vertexAction);
shader.Bind(); shader.Bind();
shader.GetUniform<float>("g_FadeClock").UpdateValue(ref time);
texture.TextureGL.Bind(); for (int i = 0; i < parts.Length; ++i)
vertexBuffer.Draw(); {
Vector2 pos = parts[i].Position;
float localTime = parts[i].Time;
DrawQuad(
texture,
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
DrawColourInfo.Colour,
null,
v => vertexBatch.Add(new TexturedTrailVertex
{
Position = v.Position,
TexturePosition = v.TexturePosition,
Time = localTime + 1,
Colour = v.Colour,
}));
}
shader.Unbind(); shader.Unbind();
} }
@ -252,7 +220,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
vertexBuffer.Dispose(); vertexBatch.Dispose();
} }
} }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.UI
private GameplayCursorContainer localCursorContainer; private GameplayCursorContainer localCursorContainer;
public override CursorContainer LocalCursor => State == Visibility.Visible ? localCursorContainer : null; public override CursorContainer LocalCursor => State.Value == Visibility.Visible ? localCursorContainer : null;
protected override string Message => "Click the orange cursor to resume"; protected override string Message => "Click the orange cursor to resume";

View File

@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
{ {
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return new TaikoDifficultyAttributes { Mods = mods }; return new TaikoDifficultyAttributes { Mods = mods, Skills = skills };
return new TaikoDifficultyAttributes return new TaikoDifficultyAttributes
{ {
@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate,
MaxCombo = beatmap.HitObjects.Count(h => h is Hit), MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
Skills = skills
}; };
} }

View File

@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override void AddCheckSteps() protected override void AddCheckSteps()
{ {
AddUntilStep("wait for fail", () => Player.HasFailed); AddUntilStep("wait for fail", () => Player.HasFailed);
AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State == Visibility.Visible); AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible);
} }
private class FailPlayer : TestPlayer private class FailPlayer : TestPlayer

View File

@ -97,7 +97,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Show overlay", () => pauseOverlay.Show());
AddStep("Press select", () => press(GlobalAction.Select)); AddStep("Press select", () => press(GlobalAction.Select));
AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible); AddAssert("Overlay still open", () => pauseOverlay.State.Value == Visibility.Visible);
AddStep("Hide overlay", () => pauseOverlay.Hide()); AddStep("Hide overlay", () => pauseOverlay.Hide());
} }
@ -237,7 +237,7 @@ namespace osu.Game.Tests.Visual.Gameplay
}); });
AddAssert("Action was triggered", () => triggered); AddAssert("Action was triggered", () => triggered);
AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden);
} }
/// <summary> /// <summary>
@ -272,7 +272,7 @@ namespace osu.Game.Tests.Visual.Gameplay
return triggered; return triggered;
}); });
AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden); AddAssert("Overlay is closed", () => pauseOverlay.State.Value == Visibility.Hidden);
} }
private void press(Key key) private void press(Key key)

View File

@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("pause overlay " + (isShown ? "shown" : "hidden"), () => Player.PauseOverlayVisible == isShown); AddAssert("pause overlay " + (isShown ? "shown" : "hidden"), () => Player.PauseOverlayVisible == isShown);
private void confirmClockRunning(bool isRunning) => private void confirmClockRunning(bool isRunning) =>
AddAssert("clock " + (isRunning ? "running" : "stopped"), () => Player.GameplayClockContainer.GameplayClock.IsRunning == isRunning); AddUntilStep("clock " + (isRunning ? "running" : "stopped"), () => Player.GameplayClockContainer.GameplayClock.IsRunning == isRunning);
protected override bool AllowFail => true; protected override bool AllowFail => true;
@ -203,9 +203,9 @@ namespace osu.Game.Tests.Visual.Gameplay
public new HUDOverlay HUDOverlay => base.HUDOverlay; public new HUDOverlay HUDOverlay => base.HUDOverlay;
public bool FailOverlayVisible => FailOverlay.State == Visibility.Visible; public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
public bool PauseOverlayVisible => PauseOverlay.State == Visibility.Visible; public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
public override void OnEntering(IScreen last) public override void OnEntering(IScreen last)
{ {

View File

@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
Origin = Anchor.TopRight, Origin = Anchor.TopRight,
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
State = Visibility.Visible, State = { Value = Visibility.Visible },
}); });
AddStep("Restart", restart); AddStep("Restart", restart);

View File

@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Menus
public TestSceneToolbar() public TestSceneToolbar()
{ {
var toolbar = new Toolbar { State = Visibility.Visible }; var toolbar = new Toolbar { State = { Value = Visibility.Visible } };
ToolbarNotificationButton notificationButton = null; ToolbarNotificationButton notificationButton = null;
AddStep("create toolbar", () => AddStep("create toolbar", () =>

View File

@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
settings = new TestRoomSettings settings = new TestRoomSettings
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
State = Visibility.Visible State = { Value = Visibility.Visible }
}; };
Child = settings; Child = settings;

View File

@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Online
api.Logout(); api.Logout();
api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true);
AddStep("show", () => accountCreation.State = Visibility.Visible); AddStep("show", () => accountCreation.Show());
AddStep("logout", () => api.Logout()); AddStep("logout", () => api.Logout());
} }
} }

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online
Children = new Drawable[] Children = new Drawable[]
{ {
channelManager, channelManager,
new ChatOverlay { State = Visibility.Visible } new ChatOverlay { State = { Value = Visibility.Visible } }
}; };
} }
} }

View File

@ -18,8 +18,24 @@ namespace osu.Game.Tests.Visual.Online
{ {
base.LoadComplete(); base.LoadComplete();
int fireCount = 0;
Add(overlay = new TestFullscreenOverlay()); Add(overlay = new TestFullscreenOverlay());
AddStep(@"toggle", overlay.ToggleVisibility);
overlay.State.ValueChanged += _ => fireCount++;
AddStep(@"show", overlay.Show);
AddAssert("fire count 1", () => fireCount == 1);
AddStep(@"show again", overlay.Show);
// this logic is specific to FullscreenOverlay
AddAssert("fire count 2", () => fireCount == 2);
AddStep(@"hide", overlay.Hide);
AddAssert("fire count 3", () => fireCount == 3);
} }
private class TestFullscreenOverlay : FullscreenOverlay private class TestFullscreenOverlay : FullscreenOverlay

View File

@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.Online
FlagName = @"TH", FlagName = @"TH",
}, },
}, },
Rank = ScoreRank.F, Rank = ScoreRank.D,
PP = 160, PP = 160,
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 123456, TotalScore = 123456,

View File

@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Settings
{ {
settings = new SettingsOverlay settings = new SettingsOverlay
{ {
State = Visibility.Visible State = { Value = Visibility.Visible }
}; };
Add(dialogOverlay = new DialogOverlay Add(dialogOverlay = new DialogOverlay
{ {

View File

@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic; using System.Collections.Generic;
@ -7,7 +7,6 @@ using JetBrains.Annotations;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("show", () => AddStep("show", () =>
{ {
infoWedge.State = Visibility.Visible; infoWedge.Show();
infoWedge.Beatmap = Beatmap.Value; infoWedge.Beatmap = Beatmap.Value;
}); });
@ -57,11 +56,11 @@ namespace osu.Game.Tests.Visual.SongSelect
AddWaitStep("wait for select", 3); AddWaitStep("wait for select", 3);
AddStep("hide", () => { infoWedge.State = Visibility.Hidden; }); AddStep("hide", () => { infoWedge.Hide(); });
AddWaitStep("wait for hide", 3); AddWaitStep("wait for hide", 3);
AddStep("show", () => { infoWedge.State = Visibility.Visible; }); AddStep("show", () => { infoWedge.Show(); });
foreach (var rulesetInfo in rulesets.AvailableRulesets) foreach (var rulesetInfo in rulesets.AvailableRulesets)
{ {

View File

@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.SongSelect
}, },
new ScoreInfo new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.D,
Accuracy = 0.6025, Accuracy = 0.6025,
MaxCombo = 244, MaxCombo = 244,
TotalScore = 1707827, TotalScore = 1707827,
@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.SongSelect
}, },
new ScoreInfo new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.D,
Accuracy = 0.5140, Accuracy = 0.5140,
MaxCombo = 244, MaxCombo = 244,
TotalScore = 1707827, TotalScore = 1707827,
@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.SongSelect
}, },
new ScoreInfo new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.D,
Accuracy = 0.4222, Accuracy = 0.4222,
MaxCombo = 244, MaxCombo = 244,
TotalScore = 1707827, TotalScore = 1707827,

View File

@ -176,7 +176,7 @@ namespace osu.Game.Tests.Visual.UserInterface
/// Checks if a cursor is visible. /// Checks if a cursor is visible.
/// </summary> /// </summary>
/// <param name="cursorContainer">The cursor to check.</param> /// <param name="cursorContainer">The cursor to check.</param>
private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State == Visibility.Visible; private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State.Value == Visibility.Visible;
/// <summary> /// <summary>
/// Checks if a cursor is at the current inputmanager screen position. /// Checks if a cursor is at the current inputmanager screen position.
@ -192,7 +192,7 @@ namespace osu.Game.Tests.Visual.UserInterface
public CursorContainer Cursor { get; } public CursorContainer Cursor { get; }
public bool ProvidingUserCursor { get; } public bool ProvidingUserCursor { get; }
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || SmoothTransition && !ProvidingUserCursor; public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => base.ReceivePositionalInputAt(screenSpacePos) || (SmoothTransition && !ProvidingUserCursor);
private readonly Box background; private readonly Box background;
@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.UserInterface
}, },
Cursor = new TestCursorContainer Cursor = new TestCursorContainer
{ {
State = providesUserCursor ? Visibility.Hidden : Visibility.Visible, State = { Value = providesUserCursor ? Visibility.Hidden : Visibility.Visible },
} }
}; };
} }

View File

@ -23,8 +23,8 @@ namespace osu.Game.Tests.Visual.UserInterface
}; };
Add(mc); Add(mc);
AddToggleStep(@"toggle visibility", state => mc.State = state ? Visibility.Visible : Visibility.Hidden); AddToggleStep(@"toggle visibility", state => mc.State.Value = state ? Visibility.Visible : Visibility.Hidden);
AddStep(@"show", () => mc.State = Visibility.Visible); AddStep(@"show", () => mc.Show());
AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state); AddToggleStep(@"toggle beatmap lock", state => Beatmap.Disabled = state);
} }
} }

View File

@ -45,7 +45,7 @@ namespace osu.Game.Tests.Visual.UserInterface
Content.Add(displayedCount); Content.Add(displayedCount);
void setState(Visibility state) => AddStep(state.ToString(), () => manager.State = state); void setState(Visibility state) => AddStep(state.ToString(), () => manager.State.Value = state);
void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected); void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; }; manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; };

View File

@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.UserInterface
var popup = new PopupDialog var popup = new PopupDialog
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
State = Framework.Graphics.Containers.Visibility.Visible, State = { Value = Framework.Graphics.Containers.Visibility.Visible },
Icon = FontAwesome.Solid.AssistiveListeningSystems, Icon = FontAwesome.Solid.AssistiveListeningSystems,
HeaderText = @"This is a test popup", HeaderText = @"This is a test popup",
BodyText = "I can say lots of stuff and even wrap my words!", BodyText = "I can say lots of stuff and even wrap my words!",

View File

@ -27,7 +27,7 @@ namespace osu.Game.Graphics.Containers
protected void BeginConfirm() protected void BeginConfirm()
{ {
if (confirming || !AllowMultipleFires && fired) return; if (confirming || (!AllowMultipleFires && fired)) return;
confirming = true; confirming = true;

View File

@ -54,7 +54,7 @@ namespace osu.Game.Graphics.Containers
samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in");
samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out");
StateChanged += onStateChanged; State.ValueChanged += onStateChanged;
} }
/// <summary> /// <summary>
@ -70,7 +70,7 @@ namespace osu.Game.Graphics.Containers
{ {
if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)) if (!base.ReceivePositionalInputAt(e.ScreenSpaceMousePosition))
{ {
State = Visibility.Hidden; Hide();
return true; return true;
} }
@ -82,7 +82,7 @@ namespace osu.Game.Graphics.Containers
switch (action) switch (action)
{ {
case GlobalAction.Back: case GlobalAction.Back:
State = Visibility.Hidden; Hide();
return true; return true;
case GlobalAction.Select: case GlobalAction.Select:
@ -94,9 +94,9 @@ namespace osu.Game.Graphics.Containers
public bool OnReleased(GlobalAction action) => false; public bool OnReleased(GlobalAction action) => false;
private void onStateChanged(Visibility visibility) private void onStateChanged(ValueChangedEvent<Visibility> state)
{ {
switch (visibility) switch (state.NewValue)
{ {
case Visibility.Visible: case Visibility.Visible:
if (OverlayActivationMode.Value != OverlayActivation.Disabled) if (OverlayActivationMode.Value != OverlayActivation.Disabled)
@ -105,7 +105,7 @@ namespace osu.Game.Graphics.Containers
if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this); if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this);
} }
else else
State = Visibility.Hidden; Hide();
break; break;

View File

@ -103,7 +103,7 @@ namespace osu.Game.Graphics.Containers
protected override void PopIn() protected override void PopIn()
{ {
foreach (var w in wavesContainer.Children) foreach (var w in wavesContainer.Children)
w.State = Visibility.Visible; w.Show();
this.FadeIn(100, Easing.OutQuint); this.FadeIn(100, Easing.OutQuint);
contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint);
@ -117,7 +117,7 @@ namespace osu.Game.Graphics.Containers
contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In);
foreach (var w in wavesContainer.Children) foreach (var w in wavesContainer.Children)
w.State = Visibility.Hidden; w.Hide();
this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint);
} }

View File

@ -29,7 +29,7 @@ namespace osu.Game.Graphics.Cursor
{ {
AddRangeInternal(new Drawable[] AddRangeInternal(new Drawable[]
{ {
Cursor = new MenuCursor { State = Visibility.Hidden }, Cursor = new MenuCursor { State = { Value = Visibility.Hidden } },
content = new Container { RelativeSizeAxes = Axes.Both } content = new Container { RelativeSizeAxes = Axes.Both }
}); });
} }

View File

@ -82,6 +82,10 @@ namespace osu.Game.Graphics.UserInterface
} }
} }
public override void Hide() => State = Visibility.Hidden;
public override void Show() => State = Visibility.Visible;
public BreadcrumbTabItem(T value) public BreadcrumbTabItem(T value)
: base(value) : base(value)
{ {

View File

@ -19,14 +19,14 @@ namespace osu.Game.Graphics.UserInterface
public class OsuAnimatedButton : OsuClickableContainer public class OsuAnimatedButton : OsuClickableContainer
{ {
/// <summary> /// <summary>
/// The colour that should be flashed when the <see cref="IconButton"/> is clicked. /// The colour that should be flashed when the <see cref="OsuAnimatedButton"/> is clicked.
/// </summary> /// </summary>
protected Color4 FlashColour = Color4.White.Opacity(0.3f); protected Color4 FlashColour = Color4.White.Opacity(0.3f);
private Color4 hoverColour = Color4.White.Opacity(0.1f); private Color4 hoverColour = Color4.White.Opacity(0.1f);
/// <summary> /// <summary>
/// The background colour of the <see cref="IconButton"/> while it is hovered. /// The background colour of the <see cref="OsuAnimatedButton"/> while it is hovered.
/// </summary> /// </summary>
protected Color4 HoverColour protected Color4 HoverColour
{ {

View File

@ -6,10 +6,9 @@ using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Containers;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
@ -33,27 +32,26 @@ namespace osu.Game.Graphics.UserInterface
public string LabelText public string LabelText
{ {
get => labelSpriteText?.Text;
set set
{ {
if (labelSpriteText != null) if (labelText != null)
labelSpriteText.Text = value; labelText.Text = value;
} }
} }
public MarginPadding LabelPadding public MarginPadding LabelPadding
{ {
get => labelSpriteText?.Padding ?? new MarginPadding(); get => labelText?.Padding ?? new MarginPadding();
set set
{ {
if (labelSpriteText != null) if (labelText != null)
labelSpriteText.Padding = value; labelText.Padding = value;
} }
} }
protected readonly Nub Nub; protected readonly Nub Nub;
private readonly SpriteText labelSpriteText; private readonly OsuTextFlowContainer labelText;
private SampleChannel sampleChecked; private SampleChannel sampleChecked;
private SampleChannel sampleUnchecked; private SampleChannel sampleUnchecked;
@ -62,24 +60,28 @@ namespace osu.Game.Graphics.UserInterface
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
const float nub_padding = 5;
Children = new Drawable[] Children = new Drawable[]
{ {
labelSpriteText = new OsuSpriteText(), labelText = new OsuTextFlowContainer
{
AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X,
Padding = new MarginPadding { Right = Nub.EXPANDED_SIZE + nub_padding }
},
Nub = new Nub Nub = new Nub
{ {
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 5 }, Margin = new MarginPadding { Right = nub_padding },
}, },
new HoverClickSounds() new HoverClickSounds()
}; };
Nub.Current.BindTo(Current); Nub.Current.BindTo(Current);
Current.DisabledChanged += disabled => Current.DisabledChanged += disabled => labelText.Alpha = Nub.Alpha = disabled ? 0.3f : 1;
{
labelSpriteText.Alpha = Nub.Alpha = disabled ? 0.3f : 1;
};
} }
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -34,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Alpha = 0.9f, Alpha = 0.9f,
}, },
new LoadingAnimation { State = Visibility.Visible } new LoadingAnimation { State = { Value = Visibility.Visible } }
}; };
} }

View File

@ -37,7 +37,7 @@ namespace osu.Game.Online.API
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser()); public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
protected bool HasLogin => authentication.Token.Value != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password); protected bool HasLogin => authentication.Token.Value != null || (!string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password));
private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource(); private readonly CancellationTokenSource cancellationToken = new CancellationTokenSource();

View File

@ -69,7 +69,7 @@ namespace osu.Game.Online.Chat
if (displayText.Length == 0 || linkText.Length == 0) continue; if (displayText.Length == 0 || linkText.Length == 0) continue;
// Check for encapsulated links // Check for encapsulated links
if (result.Links.Find(l => l.Index <= index && l.Index + l.Length >= index + m.Length || index <= l.Index && index + m.Length >= l.Index + l.Length) == null) if (result.Links.Find(l => (l.Index <= index && l.Index + l.Length >= index + m.Length) || (index <= l.Index && index + m.Length >= l.Index + l.Length)) == null)
{ {
result.Text = result.Text.Remove(index, m.Length).Insert(index, displayText); result.Text = result.Text.Remove(index, m.Length).Insert(index, displayText);

View File

@ -132,12 +132,12 @@ namespace osu.Game
public void CloseAllOverlays(bool hideToolbarElements = true) public void CloseAllOverlays(bool hideToolbarElements = true)
{ {
foreach (var overlay in overlays) foreach (var overlay in overlays)
overlay.State = Visibility.Hidden; overlay.Hide();
if (hideToolbarElements) if (hideToolbarElements)
{ {
foreach (var overlay in toolbarElements) foreach (var overlay in toolbarElements)
overlay.State = Visibility.Hidden; overlay.Hide();
} }
} }
@ -461,7 +461,7 @@ namespace osu.Game
loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true); loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true);
loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add); loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add);
chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible; chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible;
Add(externalLinkOpener = new ExternalLinkOpener()); Add(externalLinkOpener = new ExternalLinkOpener());
@ -470,9 +470,9 @@ namespace osu.Game
foreach (var overlay in singleDisplaySideOverlays) foreach (var overlay in singleDisplaySideOverlays)
{ {
overlay.StateChanged += state => overlay.State.ValueChanged += state =>
{ {
if (state == Visibility.Hidden) return; if (state.NewValue == Visibility.Hidden) return;
singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
}; };
@ -484,9 +484,9 @@ namespace osu.Game
foreach (var overlay in informationalOverlays) foreach (var overlay in informationalOverlays)
{ {
overlay.StateChanged += state => overlay.State.ValueChanged += state =>
{ {
if (state == Visibility.Hidden) return; if (state.NewValue == Visibility.Hidden) return;
informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
}; };
@ -498,12 +498,12 @@ namespace osu.Game
foreach (var overlay in singleDisplayOverlays) foreach (var overlay in singleDisplayOverlays)
{ {
overlay.StateChanged += state => overlay.State.ValueChanged += state =>
{ {
// informational overlays should be dismissed on a show or hide of a full overlay. // informational overlays should be dismissed on a show or hide of a full overlay.
informationalOverlays.ForEach(o => o.Hide()); informationalOverlays.ForEach(o => o.Hide());
if (state == Visibility.Hidden) return; if (state.NewValue == Visibility.Hidden) return;
singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide()); singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
}; };
@ -518,16 +518,16 @@ namespace osu.Game
{ {
float offset = 0; float offset = 0;
if (settings.State == Visibility.Visible) if (settings.State.Value == Visibility.Visible)
offset += ToolbarButton.WIDTH / 2; offset += ToolbarButton.WIDTH / 2;
if (notifications.State == Visibility.Visible) if (notifications.State.Value == Visibility.Visible)
offset -= ToolbarButton.WIDTH / 2; offset -= ToolbarButton.WIDTH / 2;
screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint); screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint);
} }
settings.StateChanged += _ => updateScreenOffset(); settings.State.ValueChanged += _ => updateScreenOffset();
notifications.StateChanged += _ => updateScreenOffset(); notifications.State.ValueChanged += _ => updateScreenOffset();
} }
public class GameIdleTracker : IdleTracker public class GameIdleTracker : IdleTracker
@ -768,7 +768,7 @@ namespace osu.Game
if (newOsuScreen.HideOverlaysOnEnter) if (newOsuScreen.HideOverlaysOnEnter)
CloseAllOverlays(); CloseAllOverlays();
else else
Toolbar.State = Visibility.Visible; Toolbar.Show();
} }
} }

View File

@ -109,7 +109,7 @@ namespace osu.Game.Overlays
break; break;
case APIState.Online: case APIState.Online:
State = Visibility.Hidden; Hide();
break; break;
} }
} }

View File

@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Text = "#1", Text = "#1",
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true) Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true)
}, },
rank = new DrawableRank(ScoreRank.F) rank = new DrawableRank(ScoreRank.D)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,

View File

@ -92,7 +92,7 @@ namespace osu.Game.Overlays
protected override bool OnClick(ClickEvent e) protected override bool OnClick(ClickEvent e)
{ {
State = Visibility.Hidden; Hide();
return true; return true;
} }

View File

@ -92,7 +92,7 @@ namespace osu.Game.Overlays
public void ShowListing() public void ShowListing()
{ {
Current.Value = null; Current.Value = null;
State = Visibility.Visible; Show();
} }
/// <summary> /// <summary>
@ -106,7 +106,7 @@ namespace osu.Game.Overlays
if (build == null) throw new ArgumentNullException(nameof(build)); if (build == null) throw new ArgumentNullException(nameof(build));
Current.Value = build; Current.Value = build;
State = Visibility.Visible; Show();
} }
public void ShowBuild([NotNull] string updateStream, [NotNull] string version) public void ShowBuild([NotNull] string updateStream, [NotNull] string version)
@ -123,7 +123,7 @@ namespace osu.Game.Overlays
ShowBuild(build); ShowBuild(build);
}); });
State = Visibility.Visible; Show();
} }
public override bool OnPressed(GlobalAction action) public override bool OnPressed(GlobalAction action)
@ -133,7 +133,7 @@ namespace osu.Game.Overlays
case GlobalAction.Back: case GlobalAction.Back:
if (Current.Value == null) if (Current.Value == null)
{ {
State = Visibility.Hidden; Hide();
} }
else else
{ {

View File

@ -56,7 +56,7 @@ namespace osu.Game.Overlays
private readonly Container channelSelectionContainer; private readonly Container channelSelectionContainer;
private readonly ChannelSelectionOverlay channelSelectionOverlay; private readonly ChannelSelectionOverlay channelSelectionOverlay;
public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || channelSelectionOverlay.State == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos); public override bool Contains(Vector2 screenSpacePos) => chatContainer.ReceivePositionalInputAt(screenSpacePos) || (channelSelectionOverlay.State.Value == Visibility.Visible && channelSelectionOverlay.ReceivePositionalInputAt(screenSpacePos));
public ChatOverlay() public ChatOverlay()
{ {
@ -130,7 +130,7 @@ namespace osu.Game.Overlays
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 1, Height = 1,
PlaceholderText = "type your message", PlaceholderText = "type your message",
Exit = () => State = Visibility.Hidden, Exit = Hide,
OnCommit = postMessage, OnCommit = postMessage,
ReleaseFocusOnCommit = false, ReleaseFocusOnCommit = false,
HoldFocus = true, HoldFocus = true,
@ -163,19 +163,19 @@ namespace osu.Game.Overlays
}; };
channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue;
channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State = active.NewValue ? Visibility.Visible : Visibility.Hidden; channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State.Value = active.NewValue ? Visibility.Visible : Visibility.Hidden;
channelSelectionOverlay.StateChanged += state => channelSelectionOverlay.State.ValueChanged += state =>
{ {
if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) if (state.NewValue == Visibility.Hidden && channelManager.CurrentChannel.Value == null)
{ {
channelSelectionOverlay.State = Visibility.Visible; channelSelectionOverlay.Show();
State = Visibility.Hidden; Hide();
return; return;
} }
channelTabControl.ChannelSelectorActive.Value = state == Visibility.Visible; channelTabControl.ChannelSelectorActive.Value = state.NewValue == Visibility.Visible;
if (state == Visibility.Visible) if (state.NewValue == Visibility.Visible)
{ {
textbox.HoldFocus = false; textbox.HoldFocus = false;
if (1f - ChatHeight.Value < channel_selection_min_height) if (1f - ChatHeight.Value < channel_selection_min_height)
@ -195,7 +195,7 @@ namespace osu.Game.Overlays
{ {
textbox.Current.Disabled = true; textbox.Current.Disabled = true;
currentChannelContainer.Clear(false); currentChannelContainer.Clear(false);
channelSelectionOverlay.State = Visibility.Visible; channelSelectionOverlay.Show();
return; return;
} }
@ -253,7 +253,7 @@ namespace osu.Game.Overlays
double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y; double targetChatHeight = startDragChatHeight - (e.MousePosition.Y - e.MouseDownPosition.Y) / Parent.DrawSize.Y;
// If the channel selection screen is shown, mind its minimum height // If the channel selection screen is shown, mind its minimum height
if (channelSelectionOverlay.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) if (channelSelectionOverlay.State.Value == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height)
targetChatHeight = 1f - channel_selection_min_height; targetChatHeight = 1f - channel_selection_min_height;
ChatHeight.Value = targetChatHeight; ChatHeight.Value = targetChatHeight;
@ -325,7 +325,7 @@ namespace osu.Game.Overlays
this.MoveToY(Height, transition_length, Easing.InSine); this.MoveToY(Height, transition_length, Easing.InSine);
this.FadeOut(transition_length, Easing.InSine); this.FadeOut(transition_length, Easing.InSine);
channelSelectionOverlay.State = Visibility.Hidden; channelSelectionOverlay.Hide();
textbox.HoldFocus = false; textbox.HoldFocus = false;
base.PopOut(); base.PopOut();

View File

@ -37,8 +37,8 @@ namespace osu.Game.Overlays
dialogContainer.Add(currentDialog); dialogContainer.Add(currentDialog);
currentDialog.Show(); currentDialog.Show();
currentDialog.StateChanged += state => onDialogOnStateChanged(dialog, state); currentDialog.State.ValueChanged += state => onDialogOnStateChanged(dialog, state.NewValue);
State = Visibility.Visible; Show();
} }
protected override bool PlaySamplesOnStateChange => false; protected override bool PlaySamplesOnStateChange => false;
@ -53,7 +53,7 @@ namespace osu.Game.Overlays
dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); dialog.Delay(PopupDialog.EXIT_DURATION).Expire();
if (dialog == currentDialog) if (dialog == currentDialog)
State = Visibility.Hidden; Hide();
} }
protected override void PopIn() protected override void PopIn()
@ -66,7 +66,7 @@ namespace osu.Game.Overlays
{ {
base.PopOut(); base.PopOut();
if (currentDialog?.State == Visibility.Visible) if (currentDialog?.State.Value == Visibility.Visible)
{ {
currentDialog.Hide(); currentDialog.Hide();
return; return;

View File

@ -252,7 +252,7 @@ namespace osu.Game.Overlays
if (!IsLoaded) if (!IsLoaded)
return; return;
if (State == Visibility.Hidden) if (State.Value == Visibility.Hidden)
return; return;
if (API == null) if (API == null)

View File

@ -4,6 +4,7 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
@ -40,6 +41,19 @@ namespace osu.Game.Overlays
}; };
} }
public override void Show()
{
if (State.Value == Visibility.Visible)
{
// re-trigger the state changed so we can potentially surface to front
State.TriggerChange();
}
else
{
base.Show();
}
}
protected override void PopIn() protected override void PopIn()
{ {
base.PopIn(); base.PopIn();

View File

@ -413,12 +413,12 @@ namespace osu.Game.Overlays.Mods
{ {
if (selectedMod != null) if (selectedMod != null)
{ {
if (State == Visibility.Visible) sampleOn?.Play(); if (State.Value == Visibility.Visible) sampleOn?.Play();
DeselectTypes(selectedMod.IncompatibleMods, true); DeselectTypes(selectedMod.IncompatibleMods, true);
} }
else else
{ {
if (State == Visibility.Visible) sampleOff?.Play(); if (State.Value == Visibility.Visible) sampleOff?.Play();
} }
refreshSelectedMods(); refreshSelectedMods();

View File

@ -71,7 +71,7 @@ namespace osu.Game.Overlays.Music
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
ExitRequested = () => State = Visibility.Hidden, ExitRequested = Hide,
FilterChanged = search => list.Filter(search), FilterChanged = search => list.Filter(search),
Padding = new MarginPadding(10), Padding = new MarginPadding(10),
}, },

View File

@ -200,7 +200,7 @@ namespace osu.Game.Overlays
beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved; beatmaps.ItemRemoved += handleBeatmapRemoved;
playlist.StateChanged += s => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint);
} }
private ScheduledDelegate seekDelegate; private ScheduledDelegate seekDelegate;
@ -449,7 +449,7 @@ namespace osu.Game.Overlays
// This is here mostly as a performance fix. // This is here mostly as a performance fix.
// If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent). // If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent).
playlist.State = Visibility.Hidden; playlist.Hide();
this.FadeOut(transition_length, Easing.OutQuint); this.FadeOut(transition_length, Easing.OutQuint);
dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint);

View File

@ -81,13 +81,13 @@ namespace osu.Game.Overlays
private void updateProcessingMode() private void updateProcessingMode()
{ {
bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State == Visibility.Visible; bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State.Value == Visibility.Visible;
notificationsEnabler?.Cancel(); notificationsEnabler?.Cancel();
if (enabled) if (enabled)
// we want a slight delay before toggling notifications on to avoid the user becoming overwhelmed. // we want a slight delay before toggling notifications on to avoid the user becoming overwhelmed.
notificationsEnabler = Scheduler.AddDelayed(() => processingPosts = true, State == Visibility.Visible ? 0 : 1000); notificationsEnabler = Scheduler.AddDelayed(() => processingPosts = true, State.Value == Visibility.Visible ? 0 : 1000);
else else
processingPosts = false; processingPosts = false;
} }
@ -96,7 +96,7 @@ namespace osu.Game.Overlays
{ {
base.LoadComplete(); base.LoadComplete();
StateChanged += _ => updateProcessingMode(); State.ValueChanged += _ => updateProcessingMode();
OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true); OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true);
} }
@ -128,7 +128,7 @@ namespace osu.Game.Overlays
section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth); section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth);
if (notification.IsImportant) if (notification.IsImportant)
State = Visibility.Visible; Show();
updateCounts(); updateCounts();
}); });

View File

@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
new LoadingAnimation new LoadingAnimation
{ {
State = Visibility.Visible, State = { Value = Visibility.Visible },
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
}, },

View File

@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
private Bindable<ScalingMode> scalingMode; private Bindable<ScalingMode> scalingMode;
private Bindable<Size> sizeFullscreen; private Bindable<Size> sizeFullscreen;
private readonly BindableList<WindowMode> windowModes = new BindableList<WindowMode>(); private readonly IBindableList<WindowMode> windowModes = new BindableList<WindowMode>();
private OsuGameBase game; private OsuGameBase game;
private SettingsDropdown<Size> resolutionDropdown; private SettingsDropdown<Size> resolutionDropdown;

View File

@ -14,7 +14,6 @@ namespace osu.Game.Overlays.Settings
public override string LabelText public override string LabelText
{ {
get => checkbox.LabelText;
set => checkbox.LabelText = value; set => checkbox.LabelText = value;
} }
} }

View File

@ -9,6 +9,7 @@ using osu.Game.Overlays.Settings.Sections;
using osuTK.Graphics; using osuTK.Graphics;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Bindables;
namespace osu.Game.Overlays namespace osu.Game.Overlays
{ {
@ -37,23 +38,23 @@ namespace osu.Game.Overlays
{ {
} }
public override bool AcceptsFocus => subPanels.All(s => s.State != Visibility.Visible); public override bool AcceptsFocus => subPanels.All(s => s.State.Value != Visibility.Visible);
private T createSubPanel<T>(T subPanel) private T createSubPanel<T>(T subPanel)
where T : SettingsSubPanel where T : SettingsSubPanel
{ {
subPanel.Depth = 1; subPanel.Depth = 1;
subPanel.Anchor = Anchor.TopRight; subPanel.Anchor = Anchor.TopRight;
subPanel.StateChanged += subPanelStateChanged; subPanel.State.ValueChanged += subPanelStateChanged;
subPanels.Add(subPanel); subPanels.Add(subPanel);
return subPanel; return subPanel;
} }
private void subPanelStateChanged(Visibility visibility) private void subPanelStateChanged(ValueChangedEvent<Visibility> state)
{ {
switch (visibility) switch (state.NewValue)
{ {
case Visibility.Visible: case Visibility.Visible:
Background.FadeTo(0.9f, 300, Easing.OutQuint); Background.FadeTo(0.9f, 300, Easing.OutQuint);
@ -73,7 +74,7 @@ namespace osu.Game.Overlays
} }
} }
protected override float ExpandedPosition => subPanels.Any(s => s.State == Visibility.Visible) ? -WIDTH : base.ExpandedPosition; protected override float ExpandedPosition => subPanels.Any(s => s.State.Value == Visibility.Visible) ? -WIDTH : base.ExpandedPosition;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()

View File

@ -84,10 +84,10 @@ namespace osu.Game.Overlays.Toolbar
} }
}; };
StateChanged += visibility => State.ValueChanged += visibility =>
{ {
if (overlayActivationMode.Value == OverlayActivation.Disabled) if (overlayActivationMode.Value == OverlayActivation.Disabled)
State = Visibility.Hidden; Hide();
}; };
if (osuGame != null) if (osuGame != null)

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
@ -15,6 +16,8 @@ namespace osu.Game.Overlays.Toolbar
private OverlayContainer stateContainer; private OverlayContainer stateContainer;
private readonly Bindable<Visibility> overlayState = new Bindable<Visibility>();
public OverlayContainer StateContainer public OverlayContainer StateContainer
{ {
get => stateContainer; get => stateContainer;
@ -22,10 +25,12 @@ namespace osu.Game.Overlays.Toolbar
{ {
stateContainer = value; stateContainer = value;
overlayState.UnbindBindings();
if (stateContainer != null) if (stateContainer != null)
{ {
Action = stateContainer.ToggleVisibility; Action = stateContainer.ToggleVisibility;
stateContainer.StateChanged += stateChanged; overlayState.BindTo(stateContainer.State);
} }
} }
} }
@ -40,18 +45,13 @@ namespace osu.Game.Overlays.Toolbar
Depth = 2, Depth = 2,
Alpha = 0, Alpha = 0,
}); });
overlayState.ValueChanged += stateChanged;
} }
protected override void Dispose(bool isDisposing) private void stateChanged(ValueChangedEvent<Visibility> state)
{ {
base.Dispose(isDisposing); switch (state.NewValue)
if (stateContainer != null)
stateContainer.StateChanged -= stateChanged;
}
private void stateChanged(Visibility state)
{
switch (state)
{ {
case Visibility.Hidden: case Visibility.Hidden:
stateBackground.FadeOut(200); stateBackground.FadeOut(200);

View File

@ -100,14 +100,14 @@ namespace osu.Game.Overlays
switch (action) switch (action)
{ {
case GlobalAction.DecreaseVolume: case GlobalAction.DecreaseVolume:
if (State == Visibility.Hidden) if (State.Value == Visibility.Hidden)
Show(); Show();
else else
volumeMeterMaster.Decrease(amount, isPrecise); volumeMeterMaster.Decrease(amount, isPrecise);
return true; return true;
case GlobalAction.IncreaseVolume: case GlobalAction.IncreaseVolume:
if (State == Visibility.Hidden) if (State.Value == Visibility.Hidden)
Show(); Show();
else else
volumeMeterMaster.Increase(amount, isPrecise); volumeMeterMaster.Increase(amount, isPrecise);
@ -126,7 +126,7 @@ namespace osu.Game.Overlays
public override void Show() public override void Show()
{ {
if (State == Visibility.Visible) if (State.Value == Visibility.Visible)
schedulePopOut(); schedulePopOut();
base.Show(); base.Show();

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Difficulty namespace osu.Game.Rulesets.Difficulty
@ -8,6 +9,7 @@ namespace osu.Game.Rulesets.Difficulty
public class DifficultyAttributes public class DifficultyAttributes
{ {
public Mod[] Mods; public Mod[] Mods;
public Skill[] Skills;
public double StarRating; public double StarRating;
@ -15,9 +17,10 @@ namespace osu.Game.Rulesets.Difficulty
{ {
} }
public DifficultyAttributes(Mod[] mods, double starRating) public DifficultyAttributes(Mod[] mods, Skill[] skills, double starRating)
{ {
Mods = mods; Mods = mods;
Skills = skills;
StarRating = starRating; StarRating = starRating;
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Utils; using osu.Game.Rulesets.Difficulty.Utils;
@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// <summary> /// <summary>
/// The peak strain for each <see cref="DifficultyCalculator.SectionLength"/> section of the beatmap. /// The peak strain for each <see cref="DifficultyCalculator.SectionLength"/> section of the beatmap.
/// </summary> /// </summary>
public IList<double> StrainPeaks => strainPeaks; public IReadOnlyList<double> StrainPeaks => strainPeaks;
/// <summary> /// <summary>
/// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
@ -84,13 +85,12 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// </summary> /// </summary>
public double DifficultyValue() public double DifficultyValue()
{ {
strainPeaks.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
double difficulty = 0; double difficulty = 0;
double weight = 1; double weight = 1;
// Difficulty is the weighted sum of the highest strains from every section. // Difficulty is the weighted sum of the highest strains from every section.
foreach (double strain in strainPeaks) // We're sorting from highest to lowest strain.
foreach (double strain in strainPeaks.OrderByDescending(d => d))
{ {
difficulty += strain * weight; difficulty += strain * weight;
weight *= DecayWeight; weight *= DecayWeight;

View File

@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Edit
/// </summary> /// </summary>
public readonly DrawableHitObject HitObject; public readonly DrawableHitObject HitObject;
protected override bool ShouldBeAlive => HitObject.IsAlive && HitObject.IsPresent || State == SelectionState.Selected; protected override bool ShouldBeAlive => (HitObject.IsAlive && HitObject.IsPresent) || State == SelectionState.Selected;
public override bool HandlePositionalInput => ShouldBeAlive; public override bool HandlePositionalInput => ShouldBeAlive;
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;

View File

@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
public override bool RemoveCompletedTransforms => false; public override bool RemoveCompletedTransforms => false;
protected override bool RequiresChildrenUpdate => true; protected override bool RequiresChildrenUpdate => true;
public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart; public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart);
public readonly Bindable<ArmedState> State = new Bindable<ArmedState>(); public readonly Bindable<ArmedState> State = new Bindable<ArmedState>();

View File

@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.UI
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
LastFrameState = State; LastFrameState = State.Value;
} }
} }
} }

View File

@ -136,9 +136,9 @@ namespace osu.Game.Scoring.Legacy
score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X;
else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0)
score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S;
else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) else if ((ratio300 > 0.8 && countMiss == 0) || ratio300 > 0.9)
score.Rank = ScoreRank.A; score.Rank = ScoreRank.A;
else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) else if ((ratio300 > 0.7 && countMiss == 0) || ratio300 > 0.8)
score.Rank = ScoreRank.B; score.Rank = ScoreRank.B;
else if (ratio300 > 0.6) else if (ratio300 > 0.6)
score.Rank = ScoreRank.C; score.Rank = ScoreRank.C;
@ -159,9 +159,9 @@ namespace osu.Game.Scoring.Legacy
score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X; score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.XH : ScoreRank.X;
else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0) else if (ratio300 > 0.9 && ratio50 <= 0.01 && countMiss == 0)
score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S; score.Rank = score.Mods.Any(m => m is ModHidden || m is ModFlashlight) ? ScoreRank.SH : ScoreRank.S;
else if (ratio300 > 0.8 && countMiss == 0 || ratio300 > 0.9) else if ((ratio300 > 0.8 && countMiss == 0) || ratio300 > 0.9)
score.Rank = ScoreRank.A; score.Rank = ScoreRank.A;
else if (ratio300 > 0.7 && countMiss == 0 || ratio300 > 0.8) else if ((ratio300 > 0.7 && countMiss == 0) || ratio300 > 0.8)
score.Rank = ScoreRank.B; score.Rank = ScoreRank.B;
else if (ratio300 > 0.6) else if (ratio300 > 0.6)
score.Rank = ScoreRank.C; score.Rank = ScoreRank.C;

View File

@ -7,10 +7,7 @@ namespace osu.Game.Scoring
{ {
public enum ScoreRank public enum ScoreRank
{ {
[Description(@"F")] [Description(@"D")]
F,
[Description(@"F")]
D, D,
[Description(@"C")] [Description(@"C")]

View File

@ -56,12 +56,12 @@ namespace osu.Game.Screens.Menu
case ButtonSystemState.Exit: case ButtonSystemState.Exit:
case ButtonSystemState.Initial: case ButtonSystemState.Initial:
case ButtonSystemState.EnteringMode: case ButtonSystemState.EnteringMode:
State = Visibility.Hidden; Hide();
break; break;
case ButtonSystemState.TopLevel: case ButtonSystemState.TopLevel:
case ButtonSystemState.Play: case ButtonSystemState.Play:
State = Visibility.Visible; Show();
break; break;
} }
@ -82,6 +82,10 @@ namespace osu.Game.Screens.Menu
} }
} }
public override void Hide() => State = Visibility.Hidden;
public override void Show() => State = Visibility.Visible;
public event Action<Visibility> StateChanged; public event Action<Visibility> StateChanged;
private class ButtonAreaBackground : Box, IStateful<ButtonAreaBackgroundState> private class ButtonAreaBackground : Box, IStateful<ButtonAreaBackgroundState>

View File

@ -69,6 +69,7 @@ namespace osu.Game.Screens.Play
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock(); sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock();
(sourceClock as IAdjustableAudioComponent)?.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false }; adjustableClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
@ -87,6 +88,8 @@ namespace osu.Game.Screens.Play
private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset;
private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1);
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
{ {
@ -122,6 +125,8 @@ namespace osu.Game.Screens.Play
Seek(GameplayClock.CurrentTime); Seek(GameplayClock.CurrentTime);
adjustableClock.Start(); adjustableClock.Start();
IsPaused.Value = false; IsPaused.Value = false;
this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In);
} }
/// <summary> /// <summary>
@ -143,7 +148,8 @@ namespace osu.Game.Screens.Play
public void Stop() public void Stop()
{ {
adjustableClock.Stop(); this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => adjustableClock.Stop());
IsPaused.Value = true; IsPaused.Value = true;
} }
@ -175,5 +181,11 @@ namespace osu.Game.Screens.Play
foreach (var mod in mods.OfType<IApplicableToClock>()) foreach (var mod in mods.OfType<IApplicableToClock>())
mod.ApplyToClock(sourceClock); mod.ApplyToClock(sourceClock);
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
(sourceClock as IAdjustableAudioComponent)?.RemoveAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
}
} }
} }

View File

@ -59,7 +59,7 @@ namespace osu.Game.Screens.Play
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
StateChanged += s => selectionIndex = -1; State.ValueChanged += s => selectionIndex = -1;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play.HUD
} }
}; };
State = Visibility.Visible; Show();
} }
protected override void PopIn() => this.FadeIn(fade_duration); protected override void PopIn() => this.FadeIn(fade_duration);

View File

@ -358,7 +358,7 @@ namespace osu.Game.Screens.Play
// There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer) // There is a chance that we could be in a paused state as the ruleset's internal clock (see FrameStabilityContainer)
// could process an extra frame after the GameplayClock is stopped. // could process an extra frame after the GameplayClock is stopped.
// In such cases we want the fail state to precede a user triggered pause. // In such cases we want the fail state to precede a user triggered pause.
if (PauseOverlay.State == Visibility.Visible) if (PauseOverlay.State.Value == Visibility.Visible)
PauseOverlay.Hide(); PauseOverlay.Hide();
failAnimation.Start(); failAnimation.Start();

View File

@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play
{ {
this.startTime = startTime; this.startTime = startTime;
State = Visibility.Visible; Show();
RelativePositionAxes = Axes.Both; RelativePositionAxes = Axes.Both;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
@ -136,7 +136,7 @@ namespace osu.Game.Screens.Play
protected override bool OnMouseMove(MouseMoveEvent e) protected override bool OnMouseMove(MouseMoveEvent e)
{ {
if (!e.HasAnyButtonPressed) if (!e.HasAnyButtonPressed)
fadeContainer.State = Visibility.Visible; fadeContainer.Show();
return base.OnMouseMove(e); return base.OnMouseMove(e);
} }
@ -181,7 +181,7 @@ namespace osu.Game.Screens.Play
if (!IsHovered && !IsDragged) if (!IsHovered && !IsDragged)
using (BeginDelayedSequence(1000)) using (BeginDelayedSequence(1000))
scheduledHide = Schedule(() => State = Visibility.Hidden); scheduledHide = Schedule(Hide);
break; break;
case Visibility.Hidden: case Visibility.Hidden:
@ -196,7 +196,7 @@ namespace osu.Game.Screens.Play
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
State = Visibility.Visible; Show();
} }
protected override bool OnMouseDown(MouseDownEvent e) protected override bool OnMouseDown(MouseDownEvent e)
@ -207,9 +207,13 @@ namespace osu.Game.Screens.Play
protected override bool OnMouseUp(MouseUpEvent e) protected override bool OnMouseUp(MouseUpEvent e)
{ {
State = Visibility.Visible; Show();
return base.OnMouseUp(e); return base.OnMouseUp(e);
} }
public override void Hide() => State = Visibility.Hidden;
public override void Show() => State = Visibility.Visible;
} }
private class Button : OsuClickableContainer private class Button : OsuClickableContainer

View File

@ -106,7 +106,7 @@ namespace osu.Game.Screens.Play
protected override void LoadComplete() protected override void LoadComplete()
{ {
State = Visibility.Visible; Show();
replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue;
replayLoaded.TriggerChange(); replayLoaded.TriggerChange();

View File

@ -275,7 +275,7 @@ namespace osu.Game.Screens.Ranking
currentPage = page.NewValue?.CreatePage(); currentPage = page.NewValue?.CreatePage();
if (currentPage != null) if (currentPage != null)
circleInner.Add(currentPage); LoadComponentAsync(currentPage, circleInner.Add);
}, true); }, true);
} }

View File

@ -360,13 +360,13 @@ namespace osu.Game.Screens.Select
protected override void PopIn() protected override void PopIn()
{ {
this.FadeIn(transition_duration, Easing.OutQuint); this.FadeIn(transition_duration, Easing.OutQuint);
loading.State = Visibility.Visible; loading.Show();
} }
protected override void PopOut() protected override void PopOut()
{ {
this.FadeOut(transition_duration, Easing.OutQuint); this.FadeOut(transition_duration, Easing.OutQuint);
loading.State = Visibility.Hidden; loading.Hide();
} }
} }
} }

View File

@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select
{ {
void removeOldInfo() void removeOldInfo()
{ {
State = beatmap == null ? Visibility.Hidden : Visibility.Visible; State.Value = beatmap == null ? Visibility.Hidden : Visibility.Visible;
Info?.FadeOut(250); Info?.FadeOut(250);
Info?.Expire(); Info?.Expire();

View File

@ -278,7 +278,7 @@ namespace osu.Game.Screens.Select
protected virtual void ExitFromBack() protected virtual void ExitFromBack()
{ {
if (ModSelect.State == Visibility.Visible) if (ModSelect.State.Value == Visibility.Visible)
{ {
ModSelect.Hide(); ModSelect.Hide();
return; return;
@ -520,7 +520,7 @@ namespace osu.Game.Screens.Select
if (base.OnExiting(next)) if (base.OnExiting(next))
return true; return true;
beatmapInfoWedge.State = Visibility.Hidden; beatmapInfoWedge.Hide();
this.FadeOut(100); this.FadeOut(100);

View File

@ -14,8 +14,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.518.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.609.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.607.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.611.1" />
<PackageReference Include="SharpCompress" Version="0.23.0" /> <PackageReference Include="SharpCompress" Version="0.23.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />

View File

@ -105,8 +105,8 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.518.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.518.0" />
<PackageReference Include="ppy.osu.Framework" Version="2019.607.0" /> <PackageReference Include="ppy.osu.Framework" Version="2019.611.1" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.607.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2019.611.1" />
<PackageReference Include="SharpCompress" Version="0.22.0" /> <PackageReference Include="SharpCompress" Version="0.22.0" />
<PackageReference Include="NUnit" Version="3.11.0" /> <PackageReference Include="NUnit" Version="3.11.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />