diff --git a/.github/ISSUE_TEMPLATE/01-bug-issues.md b/.github/ISSUE_TEMPLATE/01-bug-issues.md
index 0aff276d03..0b80ce44dd 100644
--- a/.github/ISSUE_TEMPLATE/01-bug-issues.md
+++ b/.github/ISSUE_TEMPLATE/01-bug-issues.md
@@ -9,6 +9,8 @@ about: Issues regarding encountered bugs.
**osu!lazer version:**
**Logs:**
+
diff --git a/.github/ISSUE_TEMPLATE/02-crash-issues.md b/.github/ISSUE_TEMPLATE/02-crash-issues.md
index 9c3ae33161..ada8de73c0 100644
--- a/.github/ISSUE_TEMPLATE/02-crash-issues.md
+++ b/.github/ISSUE_TEMPLATE/02-crash-issues.md
@@ -9,8 +9,10 @@ about: Issues regarding crashes or permanent freezes.
**osu!lazer version:**
**Logs:**
+
**Computer Specifications:**
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 6480612b2e..4e8af405a2 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -11,11 +11,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build osu! (Debug)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -28,11 +23,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build osu! (Release)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -45,11 +35,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build tests (Debug)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -62,11 +47,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build tests (Release)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -80,11 +60,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build osu! (Debug)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -98,11 +73,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build osu! (Release)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -116,11 +86,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build tournament tests (Debug)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -134,11 +99,6 @@
],
"cwd": "${workspaceRoot}",
"preLaunchTask": "Build tournament tests (Release)",
- "linux": {
- "env": {
- "LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
- }
- },
"console": "internalConsole"
},
{
@@ -169,4 +129,4 @@
"externalConsole": false
}
]
-}
\ No newline at end of file
+}
diff --git a/README.md b/README.md
index ae57b1d954..77c7eb9d2d 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ If you are looking to install or test osu! without setting up a development envi
**Latest build:**
-| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.x86_64.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
+| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
| ------------- | ------------- | ------------- | ------------- | ------------- |
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore31&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
diff --git a/osu.Android.props b/osu.Android.props
index 28fbdb3367..1c4a6ffe75 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -51,7 +51,7 @@
-
-
+
+
diff --git a/osu.Android/OsuGameAndroid.cs b/osu.Android/OsuGameAndroid.cs
index a91c010809..84f215f930 100644
--- a/osu.Android/OsuGameAndroid.cs
+++ b/osu.Android/OsuGameAndroid.cs
@@ -30,11 +30,6 @@ namespace osu.Android
}
}
- protected override void LoadComplete()
- {
- base.LoadComplete();
-
- Add(new SimpleUpdateManager());
- }
+ protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
}
}
\ No newline at end of file
diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs
index f70cc24159..f05ee48914 100644
--- a/osu.Desktop/OsuGameDesktop.cs
+++ b/osu.Desktop/OsuGameDesktop.cs
@@ -47,20 +47,25 @@ namespace osu.Desktop
return null;
}
+ protected override UpdateManager CreateUpdateManager()
+ {
+ switch (RuntimeInfo.OS)
+ {
+ case RuntimeInfo.Platform.Windows:
+ return new SquirrelUpdateManager();
+
+ default:
+ return new SimpleUpdateManager();
+ }
+ }
+
protected override void LoadComplete()
{
base.LoadComplete();
if (!noVersionOverlay)
- {
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
- if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
- Add(new SquirrelUpdateManager());
- else
- Add(new SimpleUpdateManager());
- }
-
LoadComponentAsync(new DiscordRichPresence(), Add);
}
diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs
index 74a9c05bf9..ed7bfb9a44 100644
--- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs
+++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs
@@ -7,7 +7,6 @@ using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
-using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
using osuTK;
@@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests
return beatmap;
}
- protected override Player CreatePlayer(Ruleset ruleset)
+ protected override TestPlayer CreatePlayer(Ruleset ruleset)
{
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
return base.CreatePlayer(ruleset);
diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs
index 6893e1e73b..86a00271e9 100644
--- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs
+++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs
@@ -3,8 +3,8 @@
using System;
using osu.Framework.Bindables;
-using osu.Framework.Caching;
using osu.Framework.Graphics;
+using osu.Framework.Layout;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mods;
using osuTK;
@@ -22,21 +22,13 @@ namespace osu.Game.Rulesets.Mania.Mods
private class ManiaFlashlight : Flashlight
{
- private readonly Cached flashlightProperties = new Cached();
+ private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
public ManiaFlashlight()
{
FlashlightSize = new Vector2(0, default_flashlight_size);
- }
- public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
- {
- if ((invalidation & Invalidation.DrawSize) > 0)
- {
- flashlightProperties.Invalidate();
- }
-
- return base.Invalidate(invalidation, source, shallPropagate);
+ AddLayout(flashlightProperties);
}
protected override void Update()
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs
index 31a4857805..43f9ae2783 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs
@@ -2,13 +2,13 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using osu.Framework.Caching;
using osuTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Layout;
using osu.Game.Graphics;
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
@@ -65,6 +65,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
}
}
};
+
+ AddLayout(subtractionCache);
}
protected override void LoadComplete()
@@ -100,15 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
}
}
- private readonly Cached subtractionCache = new Cached();
-
- public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
- {
- if ((invalidation & Invalidation.DrawSize) > 0)
- subtractionCache.Invalidate();
-
- return base.Invalidate(invalidation, source, shallPropagate);
- }
+ private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
protected override void Update()
{
diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs
index a28de7ea58..bfe9f1085b 100644
--- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs
+++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs
@@ -115,9 +115,8 @@ namespace osu.Game.Rulesets.Mania.UI
{
Anchor = Anchor.TopCentre,
Origin = Anchor.Centre,
- AutoSizeAxes = Axes.Both,
+ RelativeSizeAxes = Axes.Both,
Y = HIT_TARGET_POSITION + 150,
- BypassAutoSizeAxes = Axes.Both
},
topLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
}
diff --git a/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs
new file mode 100644
index 0000000000..69415b70e3
--- /dev/null
+++ b/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs
@@ -0,0 +1,86 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using NUnit.Framework;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Testing;
+using osu.Framework.Utils;
+using osu.Game.Graphics.Containers;
+using osu.Game.Rulesets.Osu.Mods;
+using osu.Game.Rulesets.Osu.Objects.Drawables;
+using osu.Game.Tests.Visual;
+
+namespace osu.Game.Rulesets.Osu.Tests.Mods
+{
+ public class TestSceneOsuModDifficultyAdjust : ModTestScene
+ {
+ public TestSceneOsuModDifficultyAdjust()
+ : base(new OsuRuleset())
+ {
+ }
+
+ [Test]
+ public void TestNoAdjustment() => CreateModTest(new ModTestData
+ {
+ Mod = new OsuModDifficultyAdjust(),
+ Autoplay = true,
+ PassCondition = checkSomeHit
+ });
+
+ [Test]
+ public void TestCircleSize1() => CreateModTest(new ModTestData
+ {
+ Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 1 } },
+ Autoplay = true,
+ PassCondition = () => checkSomeHit() && checkObjectsScale(0.78f)
+ });
+
+ [Test]
+ public void TestCircleSize10() => CreateModTest(new ModTestData
+ {
+ Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 10 } },
+ Autoplay = true,
+ PassCondition = () => checkSomeHit() && checkObjectsScale(0.15f)
+ });
+
+ [Test]
+ public void TestApproachRate1() => CreateModTest(new ModTestData
+ {
+ Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } },
+ Autoplay = true,
+ PassCondition = () => checkSomeHit() && checkObjectsPreempt(1680)
+ });
+
+ [Test]
+ public void TestApproachRate10() => CreateModTest(new ModTestData
+ {
+ Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 10 } },
+ Autoplay = true,
+ PassCondition = () => checkSomeHit() && checkObjectsPreempt(450)
+ });
+
+ private bool checkObjectsPreempt(double target)
+ {
+ var objects = Player.ChildrenOfType();
+ if (!objects.Any())
+ return false;
+
+ return objects.All(o => o.HitObject.TimePreempt == target);
+ }
+
+ private bool checkObjectsScale(float target)
+ {
+ var objects = Player.ChildrenOfType();
+ if (!objects.Any())
+ return false;
+
+ return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType().First().Children.OfType().Single().Scale.X, target));
+ }
+
+ private bool checkSomeHit()
+ {
+ return Player.ScoreProcessor.JudgedHits >= 2;
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs
index 94ca2d4cd1..87da7ef417 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneFollowPoints.cs
@@ -2,9 +2,12 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Testing;
+using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu.Objects;
@@ -114,6 +117,22 @@ namespace osu.Game.Rulesets.Osu.Tests
assertGroups();
}
+ [Test]
+ public void TestStackedObjects()
+ {
+ addObjectsStep(() => new OsuHitObject[]
+ {
+ new HitCircle { Position = new Vector2(300, 100) },
+ new HitCircle
+ {
+ Position = new Vector2(300, 300),
+ StackHeight = 20
+ },
+ });
+
+ assertDirections();
+ }
+
private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[]
{
new HitCircle { Position = new Vector2(100, 100) },
@@ -207,6 +226,33 @@ namespace osu.Game.Rulesets.Osu.Tests
});
}
+ private void assertDirections()
+ {
+ AddAssert("group directions are correct", () =>
+ {
+ for (int i = 0; i < hitObjectContainer.Count; i++)
+ {
+ DrawableOsuHitObject expectedStart = getObject(i);
+ DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null;
+
+ if (expectedEnd == null)
+ continue;
+
+ var points = getGroup(i).ChildrenOfType().ToArray();
+ if (points.Length == 0)
+ continue;
+
+ float expectedDirection = MathF.Atan2(expectedStart.Position.Y - expectedEnd.Position.Y, expectedStart.Position.X - expectedEnd.Position.X);
+ float realDirection = MathF.Atan2(expectedStart.Position.Y - points[^1].Position.Y, expectedStart.Position.X - points[^1].Position.X);
+
+ if (!Precision.AlmostEquals(expectedDirection, realDirection))
+ throw new AssertionException($"Expected group {i} in direction {expectedDirection}, but was {realDirection}.");
+ }
+
+ return true;
+ });
+ }
+
private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index];
private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index];
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs
index 412effe176..19736a7709 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOsuFlashlight.cs
@@ -3,13 +3,13 @@
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
-using osu.Game.Screens.Play;
+using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
{
- protected override Player CreatePlayer(Ruleset ruleset)
+ protected override TestPlayer CreatePlayer(Ruleset ruleset)
{
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs
index 4da1b1dae0..d39e24fc1f 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSkinFallbacks.cs
@@ -18,7 +18,6 @@ using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Osu.Objects.Drawables;
-using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osu.Game.Storyboards;
using osu.Game.Tests.Visual;
@@ -56,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests
private void checkNextHitObject(string skin) =>
AddUntilStep($"check skin from {skin}", () =>
{
- var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType().FirstOrDefault();
+ var firstObject = Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType().FirstOrDefault();
if (firstObject == null)
return false;
@@ -75,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.Tests
[Resolved]
private AudioManager audio { get; set; }
- protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
+ protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin);
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
index 5cf571d961..ea006ec607 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerRotation.cs
@@ -11,7 +11,6 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
-using osu.Game.Tests.Visual;
using osuTK;
using System.Collections.Generic;
using System.Linq;
@@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests
base.SetUpSteps();
AddUntilStep("wait for track to start running", () => track.IsRunning);
- AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First());
+ AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First());
}
[Test]
@@ -89,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{
AddStep($"seek to {time}", () => track.Seek(time));
- AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100));
+ AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs
index 921b23cb13..3e9c0f341b 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs
@@ -104,8 +104,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
return;
}
- Vector2 startPosition = osuStart.EndPosition;
- Vector2 endPosition = osuEnd.Position;
+ Vector2 startPosition = osuStart.StackedEndPosition;
+ Vector2 endPosition = osuEnd.StackedPosition;
double endTime = osuEnd.StartTime;
Vector2 distanceVector = endPosition - startPosition;
diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
index 4e86662ec6..37df5ec540 100644
--- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
+++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
@@ -5,7 +5,6 @@ using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using osu.Framework.Allocation;
-using osu.Framework.Caching;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Batches;
using osu.Framework.Graphics.OpenGL.Vertices;
@@ -14,6 +13,7 @@ using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input;
using osu.Framework.Input.Events;
+using osu.Framework.Layout;
using osu.Framework.Timing;
using osuTK;
using osuTK.Graphics;
@@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
// -1 signals that the part is unusable, and should not be drawn
parts[i].InvalidationID = -1;
}
+
+ AddLayout(partSizeCache);
}
[BackgroundDependencyLoader]
@@ -72,20 +74,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
}
}
- private readonly Cached partSizeCache = new Cached();
+ private readonly LayoutValue partSizeCache = new LayoutValue(Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence);
private Vector2 partSize => partSizeCache.IsValid
? partSizeCache.Value
: (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy);
- public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
- {
- if ((invalidation & (Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence)) > 0)
- partSizeCache.Invalidate();
-
- return base.Invalidate(invalidation, source, shallPropagate);
- }
-
///
/// The amount of time to fade the cursor trail pieces.
///
@@ -97,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
{
base.Update();
- Invalidate(Invalidation.DrawNode, shallPropagate: false);
+ Invalidate(Invalidation.DrawNode);
const int fade_clock_reset_threshold = 1000000;
diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs
index ccacc50de1..303f0163b1 100644
--- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs
+++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs
@@ -1,23 +1,16 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
-using osu.Framework.Allocation;
using osu.Game.Beatmaps;
-using osu.Game.Rulesets.Judgements;
-using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects;
-using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests
{
public class TestSceneSwellJudgements : PlayerTestScene
{
- protected new TestPlayer Player => (TestPlayer)base.Player;
-
public TestSceneSwellJudgements()
: base(new TaikoRuleset())
{
@@ -49,25 +42,5 @@ namespace osu.Game.Rulesets.Taiko.Tests
return beatmap;
}
-
- protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer();
-
- protected class TestPlayer : Player
- {
- public readonly List Results = new List();
-
- public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
-
- public TestPlayer()
- : base(false, false)
- {
- }
-
- [BackgroundDependencyLoader]
- private void load()
- {
- ScoreProcessor.NewJudgement += r => Results.Add(r);
- }
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs
index 140433a523..2ab041e191 100644
--- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs
+++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs
@@ -4,11 +4,9 @@
using System.Linq;
using NUnit.Framework;
using osu.Game.Beatmaps;
-using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Beatmaps;
using osu.Game.Rulesets.Taiko.Mods;
using osu.Game.Rulesets.Taiko.Objects;
-using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Taiko.Tests
@@ -22,10 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
protected override bool AllowFail => true;
- protected override Player CreatePlayer(Ruleset ruleset)
+ protected override TestPlayer CreatePlayer(Ruleset ruleset)
{
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
- return new ScoreAccessiblePlayer();
+ return base.CreatePlayer(ruleset);
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
@@ -49,20 +47,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
AddStep("Setup judgements", () =>
{
judged = false;
- ((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
+ Player.ScoreProcessor.NewJudgement += b => judged = true;
});
AddUntilStep("swell judged", () => judged);
AddAssert("not failed", () => !Player.HasFailed);
}
-
- private class ScoreAccessiblePlayer : TestPlayer
- {
- public ScoreAccessiblePlayer()
- : base(false, false)
- {
- }
-
- public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs
index b7db3307ad..1253b7c8ae 100644
--- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs
+++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs
@@ -2,8 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Bindables;
-using osu.Framework.Caching;
using osu.Framework.Graphics;
+using osu.Framework.Layout;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.UI;
@@ -30,13 +30,15 @@ namespace osu.Game.Rulesets.Taiko.Mods
private class TaikoFlashlight : Flashlight
{
- private readonly Cached flashlightProperties = new Cached();
+ private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
private readonly TaikoPlayfield taikoPlayfield;
public TaikoFlashlight(TaikoPlayfield taikoPlayfield)
{
this.taikoPlayfield = taikoPlayfield;
FlashlightSize = new Vector2(0, getSizeFor(0));
+
+ AddLayout(flashlightProperties);
}
private float getSizeFor(int combo)
@@ -56,16 +58,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
protected override string FragmentShader => "CircularFlashlight";
- public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
- {
- if ((invalidation & Invalidation.DrawSize) > 0)
- {
- flashlightProperties.Invalidate();
- }
-
- return base.Invalidate(invalidation, source, shallPropagate);
- }
-
protected override void Update()
{
base.Update();
diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
index 6d014ca1ca..06a155e78b 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
@@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Background
private DummySongSelect songSelect;
private TestPlayerLoader playerLoader;
- private TestPlayer player;
+ private LoadBlockingTestPlayer player;
private BeatmapManager manager;
private RulesetStore rulesets;
@@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Background
public void PlayerLoaderSettingsHoverTest()
{
setupUserSettings();
- AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer { BlockLoad = true })));
+ AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true })));
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
AddStep("Trigger background preview", () =>
@@ -268,7 +268,7 @@ namespace osu.Game.Tests.Visual.Background
{
setupUserSettings();
- AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer(allowPause))));
+ AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer(allowPause))));
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
@@ -347,7 +347,7 @@ namespace osu.Game.Tests.Visual.Background
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
}
- private class TestPlayer : Visual.TestPlayer
+ private class LoadBlockingTestPlayer : TestPlayer
{
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
@@ -360,7 +360,7 @@ namespace osu.Game.Tests.Visual.Background
public readonly Bindable ReplacesBackground = new Bindable();
public readonly Bindable IsPaused = new Bindable();
- public TestPlayer(bool allowPause = true)
+ public LoadBlockingTestPlayer(bool allowPause = true)
: base(allowPause)
{
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
index 4daab8d137..756f31e0bf 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs
@@ -5,7 +5,6 @@ using System.ComponentModel;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
-using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Storyboards;
@@ -14,20 +13,22 @@ namespace osu.Game.Tests.Visual.Gameplay
[Description("Player instantiated with an autoplay mod.")]
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
{
+ protected new TestPlayer Player => (TestPlayer)base.Player;
+
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
protected override Player CreatePlayer(Ruleset ruleset)
{
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
- return new ScoreAccessiblePlayer();
+ return new TestPlayer(false, false);
}
protected override void AddCheckSteps()
{
- AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0);
- AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
+ AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0);
+ AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
AddStep("rewind", () => track.Seek(-10000));
- AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
+ AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
}
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
@@ -38,18 +39,5 @@ namespace osu.Game.Tests.Visual.Gameplay
return working;
}
-
- private class ScoreAccessiblePlayer : TestPlayer
- {
- public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
- public new HUDOverlay HUDOverlay => base.HUDOverlay;
-
- public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
-
- public ScoreAccessiblePlayer()
- : base(false, false)
- {
- }
- }
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs
index 78c3b22fb9..310746d179 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
@@ -11,12 +10,8 @@ using osu.Framework.Utils;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
-using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects;
-using osu.Game.Rulesets.Scoring;
-using osu.Game.Rulesets.UI;
-using osu.Game.Screens.Play;
using osu.Game.Storyboards;
using osuTK;
@@ -24,8 +19,6 @@ namespace osu.Game.Tests.Visual.Gameplay
{
public class TestSceneGameplayRewinding : PlayerTestScene
{
- private RulesetExposingPlayer player => (RulesetExposingPlayer)Player;
-
[Resolved]
private AudioManager audioManager { get; set; }
@@ -48,13 +41,13 @@ namespace osu.Game.Tests.Visual.Gameplay
{
AddUntilStep("wait for track to start running", () => track.IsRunning);
addSeekStep(3000);
- AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
- AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
- AddStep("clear results", () => player.AppliedResults.Clear());
+ AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
+ AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
+ AddStep("clear results", () => Player.Results.Clear());
addSeekStep(0);
- AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
- AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
- AddAssert("no results triggered", () => player.AppliedResults.Count == 0);
+ AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
+ AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
+ AddAssert("no results triggered", () => Player.Results.Count == 0);
}
private void addSeekStep(double time)
@@ -62,13 +55,13 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep($"seek to {time}", () => track.Seek(time));
// Allow a few frames of lenience
- AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
+ AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
}
- protected override Player CreatePlayer(Ruleset ruleset)
+ protected override TestPlayer CreatePlayer(Ruleset ruleset)
{
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
- return new RulesetExposingPlayer();
+ return base.CreatePlayer(ruleset);
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
@@ -89,29 +82,5 @@ namespace osu.Game.Tests.Visual.Gameplay
return beatmap;
}
-
- private class RulesetExposingPlayer : Player
- {
- public readonly List AppliedResults = new List();
-
- public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
-
- public new HUDOverlay HUDOverlay => base.HUDOverlay;
-
- public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
-
- public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
-
- public RulesetExposingPlayer()
- : base(false, false)
- {
- }
-
- [BackgroundDependencyLoader]
- private void load()
- {
- ScoreProcessor.NewJudgement += r => AppliedResults.Add(r);
- }
- }
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs
index ad5bab4681..944e6ca6be 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs
@@ -11,7 +11,6 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
-using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Play;
using osuTK;
using osuTK.Input;
@@ -282,14 +281,10 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override bool AllowFail => true;
- protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer();
+ protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PausePlayer();
protected class PausePlayer : TestPlayer
{
- public new HealthProcessor HealthProcessor => base.HealthProcessor;
-
- public new HUDOverlay HUDOverlay => base.HUDOverlay;
-
public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs
index 3513b6c25a..a83320048b 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePauseWhenInactive.cs
@@ -9,15 +9,12 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
-using osu.Game.Screens.Play;
namespace osu.Game.Tests.Visual.Gameplay
{
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
public class TestScenePauseWhenInactive : PlayerTestScene
{
- protected new TestPlayer Player => (TestPlayer)base.Player;
-
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
@@ -46,6 +43,6 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
}
- protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
+ protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
index 100f99d130..175f909a5a 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerLoader.cs
@@ -9,7 +9,6 @@ using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
-using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Utils;
@@ -307,17 +306,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
}
- private class TestPlayer : Visual.TestPlayer
- {
- public new Bindable> Mods => base.Mods;
-
- public TestPlayer(bool allowPause = true, bool showResults = true)
- : base(allowPause, showResults)
- {
- }
- }
-
- protected class SlowLoadPlayer : Visual.TestPlayer
+ protected class SlowLoadPlayer : TestPlayer
{
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false);
diff --git a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs
index 70d71d0952..0d64eb651f 100644
--- a/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs
+++ b/osu.Game.Tests/Visual/Navigation/OsuGameTestScene.cs
@@ -62,14 +62,7 @@ namespace osu.Game.Tests.Visual.Navigation
var frameworkConfig = host.Dependencies.Get();
frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity).Disabled = false;
- Game = new TestOsuGame(LocalStorage, API);
- Game.SetHost(host);
-
- // todo: this can be removed once we can run audio tracks without a device present
- // see https://github.com/ppy/osu/issues/1302
- Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
-
- Add(Game);
+ CreateGame();
});
AddUntilStep("Wait for load", () => Game.IsLoaded);
@@ -78,6 +71,18 @@ namespace osu.Game.Tests.Visual.Navigation
ConfirmAtMainMenu();
}
+ protected void CreateGame()
+ {
+ Game = new TestOsuGame(LocalStorage, API);
+ Game.SetHost(host);
+
+ // todo: this can be removed once we can run audio tracks without a device present
+ // see https://github.com/ppy/osu/issues/1302
+ Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
+
+ Add(Game);
+ }
+
protected void PushAndConfirm(Func newScreen)
{
Screen screen = null;
@@ -97,12 +102,17 @@ namespace osu.Game.Tests.Visual.Navigation
public new SettingsPanel Settings => base.Settings;
+ public new MusicController MusicController => base.MusicController;
+
public new OsuConfigManager LocalConfig => base.LocalConfig;
public new Bindable Beatmap => base.Beatmap;
public new Bindable Ruleset => base.Ruleset;
+ // if we don't do this, when running under nUnit the version that gets populated is that of nUnit.
+ public override string Version => "test game";
+
protected override Loader CreateLoader() => new TestLoader();
public new void PerformFromScreen(Action action, IEnumerable validScreens = null) => base.PerformFromScreen(action, validScreens);
diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
index 8258cc9465..9d603ac471 100644
--- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
@@ -114,6 +114,22 @@ namespace osu.Game.Tests.Visual.Navigation
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
}
+ [Test]
+ public void TestWaitForNextTrackInMenu()
+ {
+ bool trackCompleted = false;
+
+ AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded);
+ AddStep("Seek close to end", () =>
+ {
+ Game.MusicController.SeekTo(Game.Beatmap.Value.Track.Length - 1000);
+ Game.Beatmap.Value.Track.Completed += () => trackCompleted = true;
+ });
+
+ AddUntilStep("Track was completed", () => trackCompleted);
+ AddUntilStep("Track was restarted", () => Game.Beatmap.Value.Track.IsRunning);
+ }
+
private void pushEscape() =>
AddStep("Press escape", () => pressAndRelease(Key.Escape));
diff --git a/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
new file mode 100644
index 0000000000..c0b77b580e
--- /dev/null
+++ b/osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
@@ -0,0 +1,41 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.Utils;
+using osu.Game.Configuration;
+
+namespace osu.Game.Tests.Visual.Navigation
+{
+ public class TestSettingsMigration : OsuGameTestScene
+ {
+ public override void RecycleLocalStorage()
+ {
+ base.RecycleLocalStorage();
+
+ using (var config = new OsuConfigManager(LocalStorage))
+ {
+ config.Set(OsuSetting.Version, "2020.101.0");
+ config.Set(OsuSetting.DisplayStarsMaximum, 10.0);
+ }
+ }
+
+ [Test]
+ public void TestDisplayStarsMigration()
+ {
+ AddAssert("config has migrated value", () => Precision.AlmostEquals(Game.LocalConfig.Get(OsuSetting.DisplayStarsMaximum), 10.1));
+
+ AddStep("set value again", () => Game.LocalConfig.Set(OsuSetting.DisplayStarsMaximum, 10));
+
+ AddStep("force save config", () => Game.LocalConfig.Save());
+
+ AddStep("remove game", () => Remove(Game));
+
+ AddStep("create game again", CreateGame);
+
+ AddUntilStep("Wait for load", () => Game.IsLoaded);
+
+ AddAssert("config did not migrate value", () => Precision.AlmostEquals(Game.LocalConfig.Get(OsuSetting.DisplayStarsMaximum), 10));
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs
index 54f06d6ad2..80fcef2ed2 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs
@@ -2,9 +2,11 @@
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
+using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Game.Rulesets;
using osu.Game.Users;
using osuTK;
@@ -13,13 +15,19 @@ namespace osu.Game.Tests.Visual.Online
[TestFixture]
public class TestSceneUserPanel : OsuTestScene
{
- private readonly UserPanel peppy;
+ private readonly Bindable activity = new Bindable();
- public TestSceneUserPanel()
+ private UserPanel peppy;
+
+ [Resolved]
+ private RulesetStore rulesetStore { get; set; }
+
+ [SetUp]
+ public void SetUp() => Schedule(() =>
{
UserPanel flyte;
- Add(new FillFlowContainer
+ Child = new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -44,34 +52,38 @@ namespace osu.Game.Tests.Visual.Online
SupportLevel = 3,
}) { Width = 300 },
},
- });
+ };
flyte.Status.Value = new UserStatusOnline();
peppy.Status.Value = null;
- }
-
- [Test]
- public void UserStatusesTests()
- {
- AddStep("online", () => { peppy.Status.Value = new UserStatusOnline(); });
- AddStep(@"do not disturb", () => { peppy.Status.Value = new UserStatusDoNotDisturb(); });
- AddStep(@"offline", () => { peppy.Status.Value = new UserStatusOffline(); });
- AddStep(@"null status", () => { peppy.Status.Value = null; });
- }
-
- [Test]
- public void UserActivitiesTests()
- {
- Bindable activity = new Bindable();
-
peppy.Activity.BindTo(activity);
+ });
- AddStep("idle", () => { activity.Value = null; });
- AddStep("spectating", () => { activity.Value = new UserActivity.Spectating(); });
- AddStep("solo", () => { activity.Value = new UserActivity.SoloGame(null, null); });
- AddStep("choosing", () => { activity.Value = new UserActivity.ChoosingBeatmap(); });
- AddStep("editing", () => { activity.Value = new UserActivity.Editing(null); });
- AddStep("modding", () => { activity.Value = new UserActivity.Modding(); });
+ [Test]
+ public void TestUserStatus()
+ {
+ AddStep("online", () => peppy.Status.Value = new UserStatusOnline());
+ AddStep("do not disturb", () => peppy.Status.Value = new UserStatusDoNotDisturb());
+ AddStep("offline", () => peppy.Status.Value = new UserStatusOffline());
+ AddStep("null status", () => peppy.Status.Value = null);
}
+
+ [Test]
+ public void TestUserActivity()
+ {
+ AddStep("set online status", () => peppy.Status.Value = new UserStatusOnline());
+
+ AddStep("idle", () => activity.Value = null);
+ AddStep("spectating", () => activity.Value = new UserActivity.Spectating());
+ AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0));
+ AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1));
+ AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2));
+ AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3));
+ AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap());
+ AddStep("editing", () => activity.Value = new UserActivity.Editing(null));
+ AddStep("modding", () => activity.Value = new UserActivity.Modding());
+ }
+
+ private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.SoloGame(null, rulesetStore.GetRuleset(rulesetId));
}
}
diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs
new file mode 100644
index 0000000000..014cd4663b
--- /dev/null
+++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingEditorScreen.cs
@@ -0,0 +1,25 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Game.Tournament.Models;
+using osu.Game.Tournament.Screens.Editors;
+
+namespace osu.Game.Tournament.Tests.Screens
+{
+ public class TestSceneSeedingEditorScreen : LadderTestScene
+ {
+ [Cached]
+ private readonly LadderInfo ladder = new LadderInfo();
+
+ public TestSceneSeedingEditorScreen()
+ {
+ var match = TestSceneSeedingScreen.CreateSampleSeededMatch();
+
+ Add(new SeedingEditorScreen(match.Team1.Value)
+ {
+ Width = 0.85f // create room for control panel
+ });
+ }
+ }
+}
diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs
new file mode 100644
index 0000000000..335a6c80a1
--- /dev/null
+++ b/osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs
@@ -0,0 +1,127 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Game.Beatmaps;
+using osu.Game.Tournament.Models;
+using osu.Game.Tournament.Screens.TeamIntro;
+using osu.Game.Users;
+
+namespace osu.Game.Tournament.Tests.Screens
+{
+ public class TestSceneSeedingScreen : LadderTestScene
+ {
+ [Cached]
+ private readonly LadderInfo ladder = new LadderInfo();
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ ladder.CurrentMatch.Value = CreateSampleSeededMatch();
+
+ Add(new SeedingScreen
+ {
+ FillMode = FillMode.Fit,
+ FillAspectRatio = 16 / 9f
+ });
+ }
+
+ public static TournamentMatch CreateSampleSeededMatch() => new TournamentMatch
+ {
+ Team1 =
+ {
+ Value = new TournamentTeam
+ {
+ FlagName = { Value = "JP" },
+ FullName = { Value = "Japan" },
+ LastYearPlacing = { Value = 10 },
+ Seed = { Value = "Low" },
+ SeedingResults =
+ {
+ new SeedingResult
+ {
+ Mod = { Value = "NM" },
+ Seed = { Value = 10 },
+ Beatmaps =
+ {
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 12345672,
+ Seed = { Value = 24 },
+ },
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 1234567,
+ Seed = { Value = 12 },
+ },
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 1234567,
+ Seed = { Value = 16 },
+ }
+ }
+ },
+ new SeedingResult
+ {
+ Mod = { Value = "DT" },
+ Seed = { Value = 5 },
+ Beatmaps =
+ {
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 234567,
+ Seed = { Value = 3 },
+ },
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 234567,
+ Seed = { Value = 6 },
+ },
+ new SeedingBeatmap
+ {
+ BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
+ Score = 234567,
+ Seed = { Value = 12 },
+ }
+ }
+ }
+ },
+ Players =
+ {
+ new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 12 } } },
+ new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 16 } } },
+ new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 20 } } },
+ new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24 } } },
+ new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 30 } } },
+ }
+ }
+ },
+ Team2 =
+ {
+ Value = new TournamentTeam
+ {
+ FlagName = { Value = "US" },
+ FullName = { Value = "United States" },
+ Players =
+ {
+ new User { Username = "Hello" },
+ new User { Username = "Hello" },
+ new User { Username = "Hello" },
+ new User { Username = "Hello" },
+ new User { Username = "Hello" },
+ }
+ }
+ },
+ Round =
+ {
+ Value = new TournamentRound { Name = { Value = "Quarterfinals" } }
+ }
+ };
+ }
+}
diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs
index 5cb35a506f..1a2faa76c1 100644
--- a/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs
+++ b/osu.Game.Tournament.Tests/Screens/TestSceneTeamWinScreen.cs
@@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
+ match.Completed.Value = true;
ladder.CurrentMatch.Value = match;
Add(new TeamWinScreen
diff --git a/osu.Game.Tournament/Components/ControlPanel.cs b/osu.Game.Tournament/Components/ControlPanel.cs
index a9bb1bf42f..fa5c941f1a 100644
--- a/osu.Game.Tournament/Components/ControlPanel.cs
+++ b/osu.Game.Tournament/Components/ControlPanel.cs
@@ -5,7 +5,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osuTK;
using osuTK.Graphics;
@@ -35,7 +34,7 @@ namespace osu.Game.Tournament.Components
RelativeSizeAxes = Axes.Both,
Colour = new Color4(54, 54, 54, 255)
},
- new OsuSpriteText
+ new TournamentSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
diff --git a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs
index 361bd92770..99116d4a17 100644
--- a/osu.Game.Tournament/Components/DrawableTournamentTeam.cs
+++ b/osu.Game.Tournament/Components/DrawableTournamentTeam.cs
@@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Models;
namespace osu.Game.Tournament.Components
@@ -19,7 +18,7 @@ namespace osu.Game.Tournament.Components
public readonly TournamentTeam Team;
protected readonly Sprite Flag;
- protected readonly OsuSpriteText AcronymText;
+ protected readonly TournamentSpriteText AcronymText;
[UsedImplicitly]
private Bindable acronym;
@@ -37,9 +36,9 @@ namespace osu.Game.Tournament.Components
FillMode = FillMode.Fit
};
- AcronymText = new OsuSpriteText
+ AcronymText = new TournamentSpriteText
{
- Font = OsuFont.GetFont(weight: FontWeight.Regular),
+ Font = OsuFont.Torus.With(weight: FontWeight.Regular),
};
}
diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs
index 8a46da9565..48ea36a8f3 100644
--- a/osu.Game.Tournament/Components/SongBar.cs
+++ b/osu.Game.Tournament/Components/SongBar.cs
@@ -13,7 +13,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets;
using osu.Game.Screens.Menu;
using osuTK;
@@ -262,7 +261,7 @@ namespace osu.Game.Tournament.Components
static void cp(SpriteText s, Color4 colour)
{
s.Colour = colour;
- s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15);
+ s.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 15);
}
for (var i = 0; i < tuples.Length; i++)
@@ -278,9 +277,9 @@ namespace osu.Game.Tournament.Components
});
}
- AddText(new OsuSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f)));
+ AddText(new TournamentSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f)));
AddText(" ", s => cp(s, OsuColour.Gray(0.33f)));
- AddText(new OsuSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f)));
+ AddText(new TournamentSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f)));
}
}
}
diff --git a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
index 51483a0964..394ffe304e 100644
--- a/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
+++ b/osu.Game.Tournament/Components/TournamentBeatmapPanel.cs
@@ -15,7 +15,6 @@ using osu.Framework.Localisation;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Models;
using osuTK;
using osuTK.Graphics;
@@ -77,14 +76,14 @@ namespace osu.Game.Tournament.Components
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = new LocalisedString((
$"{Beatmap.Metadata.ArtistUnicode ?? Beatmap.Metadata.Artist} - {Beatmap.Metadata.TitleUnicode ?? Beatmap.Metadata.Title}",
$"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")),
- Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true),
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold),
},
new FillFlowContainer
{
@@ -95,28 +94,28 @@ namespace osu.Game.Tournament.Components
Direction = FillDirection.Horizontal,
Children = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = "mapper",
Padding = new MarginPadding { Right = 5 },
- Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
+ Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
},
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = Beatmap.Metadata.AuthorString,
Padding = new MarginPadding { Right = 20 },
- Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = "difficulty",
Padding = new MarginPadding { Right = 5 },
- Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
+ Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
},
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = Beatmap.Version,
- Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
},
}
}
diff --git a/osu.Game.Tournament/Models/SeedingBeatmap.cs b/osu.Game.Tournament/Models/SeedingBeatmap.cs
new file mode 100644
index 0000000000..2cd6fa7188
--- /dev/null
+++ b/osu.Game.Tournament/Models/SeedingBeatmap.cs
@@ -0,0 +1,23 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Bindables;
+using osu.Game.Beatmaps;
+
+namespace osu.Game.Tournament.Models
+{
+ public class SeedingBeatmap
+ {
+ public int ID;
+
+ public BeatmapInfo BeatmapInfo;
+
+ public long Score;
+
+ public Bindable Seed = new BindableInt
+ {
+ MinValue = 1,
+ MaxValue = 64
+ };
+ }
+}
diff --git a/osu.Game.Tournament/Models/SeedingResult.cs b/osu.Game.Tournament/Models/SeedingResult.cs
new file mode 100644
index 0000000000..87aaf8bf36
--- /dev/null
+++ b/osu.Game.Tournament/Models/SeedingResult.cs
@@ -0,0 +1,21 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using osu.Framework.Bindables;
+
+namespace osu.Game.Tournament.Models
+{
+ public class SeedingResult
+ {
+ public List Beatmaps = new List();
+
+ public Bindable Mod = new Bindable();
+
+ public Bindable Seed = new BindableInt
+ {
+ MinValue = 1,
+ MaxValue = 64
+ };
+ }
+}
diff --git a/osu.Game.Tournament/Models/TournamentTeam.cs b/osu.Game.Tournament/Models/TournamentTeam.cs
index 54b8a35180..7fca75cea4 100644
--- a/osu.Game.Tournament/Models/TournamentTeam.cs
+++ b/osu.Game.Tournament/Models/TournamentTeam.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Game.Users;
@@ -29,6 +30,32 @@ namespace osu.Game.Tournament.Models
///
public Bindable Acronym = new Bindable(string.Empty);
+ public BindableList SeedingResults = new BindableList();
+
+ public double AverageRank
+ {
+ get
+ {
+ var ranks = Players.Select(p => p.Statistics?.Ranks.Global)
+ .Where(i => i.HasValue)
+ .Select(i => i.Value)
+ .ToArray();
+
+ if (ranks.Length == 0)
+ return 0;
+
+ return ranks.Average();
+ }
+ }
+
+ public Bindable Seed = new Bindable(string.Empty);
+
+ public Bindable LastYearPlacing = new BindableInt
+ {
+ MinValue = 1,
+ MaxValue = 64
+ };
+
[JsonProperty]
public BindableList Players { get; set; } = new BindableList();
diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin b/osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin
deleted file mode 100644
index 42cfdf08de..0000000000
Binary files a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light.bin and /dev/null differ
diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png b/osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png
deleted file mode 100644
index 332d9ca056..0000000000
Binary files a/osu.Game.Tournament/Resources/Fonts/Aquatico-Light_0.png and /dev/null differ
diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin b/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin
deleted file mode 100644
index 3047c2eb3e..0000000000
Binary files a/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular.bin and /dev/null differ
diff --git a/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png b/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png
deleted file mode 100644
index 1252d233d3..0000000000
Binary files a/osu.Game.Tournament/Resources/Fonts/Aquatico-Regular_0.png and /dev/null differ
diff --git a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs
index 549ff26018..4126f2db65 100644
--- a/osu.Game.Tournament/Screens/Drawings/Components/Group.cs
+++ b/osu.Game.Tournament/Screens/Drawings/Components/Group.cs
@@ -8,7 +8,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osuTK;
@@ -43,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
Colour = new Color4(54, 54, 54, 255)
},
// Group name
- new OsuSpriteText
+ new TournamentSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
@@ -51,7 +50,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
Position = new Vector2(0, 7f),
Text = $"GROUP {name.ToUpperInvariant()}",
- Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 8),
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 8),
Colour = new Color4(255, 204, 34, 255),
},
teams = new FillFlowContainer
@@ -134,7 +133,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
AcronymText.Anchor = Anchor.TopCentre;
AcronymText.Origin = Anchor.TopCentre;
AcronymText.Text = team.Acronym.Value.ToUpperInvariant();
- AcronymText.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10);
+ AcronymText.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 10);
InternalChildren = new Drawable[]
{
diff --git a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs
index 5efa0a1e69..8be66ff98c 100644
--- a/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs
+++ b/osu.Game.Tournament/Screens/Drawings/DrawingsScreen.cs
@@ -14,7 +14,6 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Drawings.Components;
@@ -29,7 +28,7 @@ namespace osu.Game.Tournament.Screens.Drawings
private ScrollingTeamContainer teamsContainer;
private GroupContainer groupsContainer;
- private OsuSpriteText fullTeamNameText;
+ private TournamentSpriteText fullTeamNameText;
private readonly List allTeams = new List();
@@ -109,18 +108,18 @@ namespace osu.Game.Tournament.Screens.Drawings
RelativeSizeAxes = Axes.X,
},
// Scrolling team name
- fullTeamNameText = new OsuSpriteText
+ fullTeamNameText = new TournamentSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.TopCentre,
Position = new Vector2(0, 45f),
- Colour = OsuColour.Gray(0.33f),
+ Colour = OsuColour.Gray(0.95f),
Alpha = 0,
- Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42),
+ Font = OsuFont.Torus.With(weight: FontWeight.Light, size: 42),
}
}
},
diff --git a/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs
new file mode 100644
index 0000000000..e68946aaf2
--- /dev/null
+++ b/osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs
@@ -0,0 +1,288 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Bindables;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Beatmaps;
+using osu.Game.Graphics;
+using osu.Game.Online.API;
+using osu.Game.Online.API.Requests;
+using osu.Game.Overlays.Settings;
+using osu.Game.Rulesets;
+using osu.Game.Tournament.Components;
+using osu.Game.Tournament.Models;
+using osuTK;
+
+namespace osu.Game.Tournament.Screens.Editors
+{
+ public class SeedingEditorScreen : TournamentEditorScreen
+ {
+ private readonly TournamentTeam team;
+
+ protected override BindableList Storage => team.SeedingResults;
+
+ public SeedingEditorScreen(TournamentTeam team)
+ {
+ this.team = team;
+ }
+
+ public class SeeingResultRow : CompositeDrawable, IModelBacked
+ {
+ public SeedingResult Model { get; }
+
+ [Resolved]
+ private LadderInfo ladderInfo { get; set; }
+
+ public SeeingResultRow(TournamentTeam team, SeedingResult round)
+ {
+ Model = round;
+
+ Masking = true;
+ CornerRadius = 10;
+
+ SeedingBeatmapEditor beatmapEditor = new SeedingBeatmapEditor(round)
+ {
+ Width = 0.95f
+ };
+
+ InternalChildren = new Drawable[]
+ {
+ new Box
+ {
+ Colour = OsuColour.Gray(0.1f),
+ RelativeSizeAxes = Axes.Both,
+ },
+ new FillFlowContainer
+ {
+ Margin = new MarginPadding(5),
+ Padding = new MarginPadding { Right = 160 },
+ Spacing = new Vector2(5),
+ Direction = FillDirection.Full,
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Children = new Drawable[]
+ {
+ new SettingsTextBox
+ {
+ LabelText = "Mod",
+ Width = 0.33f,
+ Bindable = Model.Mod
+ },
+ new SettingsSlider
+ {
+ LabelText = "Seed",
+ Width = 0.33f,
+ Bindable = Model.Seed
+ },
+ new SettingsButton
+ {
+ Width = 0.2f,
+ Margin = new MarginPadding(10),
+ Text = "Add beatmap",
+ Action = () => beatmapEditor.CreateNew()
+ },
+ beatmapEditor
+ }
+ },
+ new DangerousSettingsButton
+ {
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ RelativeSizeAxes = Axes.None,
+ Width = 150,
+ Text = "Delete result",
+ Action = () =>
+ {
+ Expire();
+ team.SeedingResults.Remove(Model);
+ },
+ }
+ };
+
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+ }
+
+ public class SeedingBeatmapEditor : CompositeDrawable
+ {
+ private readonly SeedingResult round;
+ private readonly FillFlowContainer flow;
+
+ public SeedingBeatmapEditor(SeedingResult round)
+ {
+ this.round = round;
+
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+
+ InternalChild = flow = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Vertical,
+ LayoutDuration = 200,
+ LayoutEasing = Easing.OutQuint,
+ ChildrenEnumerable = round.Beatmaps.Select(p => new SeedingBeatmapRow(round, p))
+ };
+ }
+
+ public void CreateNew()
+ {
+ var user = new SeedingBeatmap();
+ round.Beatmaps.Add(user);
+ flow.Add(new SeedingBeatmapRow(round, user));
+ }
+
+ public class SeedingBeatmapRow : CompositeDrawable
+ {
+ private readonly SeedingResult result;
+ public SeedingBeatmap Model { get; }
+
+ [Resolved]
+ protected IAPIProvider API { get; private set; }
+
+ private readonly Bindable beatmapId = new Bindable();
+
+ private readonly Bindable score = new Bindable();
+
+ private readonly Container drawableContainer;
+
+ public SeedingBeatmapRow(SeedingResult result, SeedingBeatmap beatmap)
+ {
+ this.result = result;
+ Model = beatmap;
+
+ Margin = new MarginPadding(10);
+
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+
+ Masking = true;
+ CornerRadius = 5;
+
+ InternalChildren = new Drawable[]
+ {
+ new Box
+ {
+ Colour = OsuColour.Gray(0.2f),
+ RelativeSizeAxes = Axes.Both,
+ },
+ new FillFlowContainer
+ {
+ Margin = new MarginPadding(5),
+ Padding = new MarginPadding { Right = 160 },
+ Spacing = new Vector2(5),
+ Direction = FillDirection.Horizontal,
+ AutoSizeAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ new SettingsNumberBox
+ {
+ LabelText = "Beatmap ID",
+ RelativeSizeAxes = Axes.None,
+ Width = 200,
+ Bindable = beatmapId,
+ },
+ new SettingsSlider
+ {
+ LabelText = "Seed",
+ RelativeSizeAxes = Axes.None,
+ Width = 200,
+ Bindable = beatmap.Seed
+ },
+ new SettingsTextBox
+ {
+ LabelText = "Score",
+ RelativeSizeAxes = Axes.None,
+ Width = 200,
+ Bindable = score,
+ },
+ drawableContainer = new Container
+ {
+ Size = new Vector2(100, 70),
+ },
+ }
+ },
+ new DangerousSettingsButton
+ {
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ RelativeSizeAxes = Axes.None,
+ Width = 150,
+ Text = "Delete Beatmap",
+ Action = () =>
+ {
+ Expire();
+ result.Beatmaps.Remove(beatmap);
+ },
+ }
+ };
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(RulesetStore rulesets)
+ {
+ beatmapId.Value = Model.ID.ToString();
+ beatmapId.BindValueChanged(idString =>
+ {
+ int parsed;
+
+ int.TryParse(idString.NewValue, out parsed);
+
+ Model.ID = parsed;
+
+ if (idString.NewValue != idString.OldValue)
+ Model.BeatmapInfo = null;
+
+ if (Model.BeatmapInfo != null)
+ {
+ updatePanel();
+ return;
+ }
+
+ var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID });
+
+ req.Success += res =>
+ {
+ Model.BeatmapInfo = res.ToBeatmap(rulesets);
+ updatePanel();
+ };
+
+ req.Failure += _ =>
+ {
+ Model.BeatmapInfo = null;
+ updatePanel();
+ };
+
+ API.Queue(req);
+ }, true);
+
+ score.Value = Model.Score.ToString();
+ score.BindValueChanged(str => long.TryParse(str.NewValue, out Model.Score));
+ }
+
+ private void updatePanel()
+ {
+ drawableContainer.Clear();
+
+ if (Model.BeatmapInfo != null)
+ {
+ drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, result.Mod.Value)
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ Width = 300
+ };
+ }
+ }
+ }
+ }
+ }
+
+ protected override SeeingResultRow CreateDrawable(SeedingResult model) => new SeeingResultRow(team, model);
+ }
+}
diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
index 494dd73edd..ca8bce1cca 100644
--- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
+++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs
@@ -57,6 +57,9 @@ namespace osu.Game.Tournament.Screens.Editors
private readonly Container drawableContainer;
+ [Resolved(canBeNull: true)]
+ private TournamentSceneManager sceneManager { get; set; }
+
[Resolved]
private LadderInfo ladderInfo { get; set; }
@@ -113,6 +116,18 @@ namespace osu.Game.Tournament.Screens.Editors
Width = 0.2f,
Bindable = Model.FlagName
},
+ new SettingsTextBox
+ {
+ LabelText = "Seed",
+ Width = 0.2f,
+ Bindable = Model.Seed
+ },
+ new SettingsSlider
+ {
+ LabelText = "Last Year Placement",
+ Width = 0.33f,
+ Bindable = Model.LastYearPlacing
+ },
new SettingsButton
{
Width = 0.11f,
@@ -131,7 +146,17 @@ namespace osu.Game.Tournament.Screens.Editors
ladderInfo.Teams.Remove(Model);
},
},
- playerEditor
+ playerEditor,
+ new SettingsButton
+ {
+ Width = 0.2f,
+ Margin = new MarginPadding(10),
+ Text = "Edit seeding results",
+ Action = () =>
+ {
+ sceneManager?.SetScreen(new SeedingEditorScreen(team));
+ }
+ },
}
},
};
diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs
index 9e1888b44b..ce17c392d0 100644
--- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs
+++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchHeader.cs
@@ -5,9 +5,9 @@ using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
@@ -30,7 +30,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
new TournamentLogo(),
new RoundDisplay
{
- Y = 10,
+ Y = 5,
Anchor = Anchor.BottomCentre,
Origin = Anchor.TopCentre,
},
@@ -51,9 +51,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
{
private readonly TeamColour teamColour;
- private readonly Color4 red = new Color4(129, 68, 65, 255);
- private readonly Color4 blue = new Color4(41, 91, 97, 255);
-
private readonly Bindable currentMatch = new Bindable();
private readonly Bindable currentTeam = new Bindable();
private readonly Bindable currentTeamScore = new Bindable();
@@ -106,7 +103,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
private void teamChanged(TournamentTeam team)
{
- var colour = teamColour == TeamColour.Red ? red : blue;
+ var colour = teamColour == TeamColour.Red ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
var flip = teamColour != TeamColour.Red;
InternalChildren = new Drawable[]
@@ -169,13 +166,13 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
Children = new Drawable[]
{
Flag,
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = team?.FullName.Value.ToUpper() ?? "???",
X = (flip ? -1 : 1) * 90,
Y = -10,
Colour = colour,
- Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 20),
+ Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 20),
Origin = anchor,
Anchor = anchor,
},
@@ -188,10 +185,31 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
{
private readonly Bindable currentMatch = new Bindable();
+ private readonly TournamentSpriteText text;
+
public RoundDisplay()
{
Width = 200;
Height = 20;
+
+ Masking = true;
+ CornerRadius = 10;
+
+ InternalChildren = new Drawable[]
+ {
+ new Box
+ {
+ Colour = OsuColour.Gray(0.18f),
+ RelativeSizeAxes = Axes.Both,
+ },
+ text = new TournamentSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Colour = Color4.White,
+ Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 16),
+ },
+ };
}
[BackgroundDependencyLoader]
@@ -201,20 +219,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
currentMatch.BindTo(ladder.CurrentMatch);
}
- private void matchChanged(ValueChangedEvent match)
- {
- InternalChildren = new Drawable[]
- {
- new OsuSpriteText
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- Colour = Color4.White,
- Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round",
- Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 18),
- },
- };
- }
+ private void matchChanged(ValueChangedEvent match) =>
+ text.Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round";
}
}
}
diff --git a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs
index cc7903f2fa..fcf1469278 100644
--- a/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs
+++ b/osu.Game.Tournament/Screens/Gameplay/Components/MatchScoreDisplay.cs
@@ -123,8 +123,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
public bool Winning
{
set => DisplayedCountSpriteText.Font = value
- ? TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 60)
- : TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Light, size: 40);
+ ? OsuFont.Torus.With(weight: FontWeight.Regular, size: 60)
+ : OsuFont.Torus.With(weight: FontWeight.Light, size: 40);
}
}
}
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs
index 031d6bf3d2..88d7b95b0c 100644
--- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs
+++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableMatchTeam.cs
@@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
@@ -26,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{
private readonly TournamentMatch match;
private readonly bool losers;
- private OsuSpriteText scoreText;
+ private TournamentSpriteText scoreText;
private Box background;
private readonly Bindable score = new Bindable();
@@ -69,7 +68,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft;
AcronymText.Padding = new MarginPadding { Left = 50 };
- AcronymText.Font = OsuFont.GetFont(size: 24);
+ AcronymText.Font = OsuFont.Torus.With(size: 24);
if (match != null)
{
@@ -119,11 +118,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
Alpha = 0.8f,
RelativeSizeAxes = Axes.Both,
},
- scoreText = new OsuSpriteText
+ scoreText = new TournamentSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
- Font = OsuFont.GetFont(size: 20),
+ Font = OsuFont.Torus.With(size: 20),
}
}
}
@@ -184,7 +183,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint);
- scoreText.Font = AcronymText.Font = OsuFont.GetFont(weight: winner ? FontWeight.Bold : FontWeight.Regular);
+ scoreText.Font = AcronymText.Font = OsuFont.Torus.With(weight: winner ? FontWeight.Bold : FontWeight.Regular);
}
public MenuItem[] ContextMenuItems
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs
index dacd98d3b8..d14ebb4d03 100644
--- a/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs
+++ b/osu.Game.Tournament/Screens/Ladder/Components/DrawableTournamentRound.cs
@@ -6,7 +6,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Models;
using osuTK.Graphics;
@@ -22,8 +21,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
public DrawableTournamentRound(TournamentRound round, bool losers = false)
{
- OsuSpriteText textName;
- OsuSpriteText textDescription;
+ TournamentSpriteText textName;
+ TournamentSpriteText textDescription;
AutoSizeAxes = Axes.Both;
InternalChild = new FillFlowContainer
@@ -32,15 +31,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
- textDescription = new OsuSpriteText
+ textDescription = new TournamentSpriteText
{
Colour = Color4.Black,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre
},
- textName = new OsuSpriteText
+ textName = new TournamentSpriteText
{
- Font = OsuFont.GetFont(weight: FontWeight.Bold),
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold),
Colour = Color4.Black,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
index 8ab083ddaf..4aea7ff4c0 100644
--- a/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
+++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderEditorSettings.cs
@@ -9,7 +9,6 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Input.Events;
-using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Settings;
using osu.Game.Screens.Play.PlayerSettings;
using osu.Game.Tournament.Components;
@@ -126,66 +125,5 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
});
}
}
-
- private class SettingsTeamDropdown : LadderSettingsDropdown
- {
- public SettingsTeamDropdown(BindableList teams)
- {
- foreach (var t in teams.Prepend(new TournamentTeam()))
- add(t);
-
- teams.CollectionChanged += (_, args) =>
- {
- switch (args.Action)
- {
- case NotifyCollectionChangedAction.Add:
- args.NewItems.Cast().ForEach(add);
- break;
-
- case NotifyCollectionChangedAction.Remove:
- args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i));
- break;
- }
- };
- }
-
- private readonly List refBindables = new List();
-
- private T boundReference(T obj)
- where T : IBindable
- {
- obj = (T)obj.GetBoundCopy();
- refBindables.Add(obj);
- return obj;
- }
-
- private void add(TournamentTeam team)
- {
- Control.AddDropdownItem(team);
- boundReference(team.FullName).BindValueChanged(_ =>
- {
- Control.RemoveDropdownItem(team);
- Control.AddDropdownItem(team);
- });
- }
- }
-
- private class LadderSettingsDropdown : SettingsDropdown
- {
- protected override OsuDropdown CreateDropdown() => new DropdownControl();
-
- private new class DropdownControl : SettingsDropdown.DropdownControl
- {
- protected override DropdownMenu CreateMenu() => new Menu();
-
- private new class Menu : OsuDropdownMenu
- {
- public Menu()
- {
- MaxHeight = 200;
- }
- }
- }
- }
}
}
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/LadderSettingsDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettingsDropdown.cs
new file mode 100644
index 0000000000..347e4d91e0
--- /dev/null
+++ b/osu.Game.Tournament/Screens/Ladder/Components/LadderSettingsDropdown.cs
@@ -0,0 +1,26 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Graphics.UserInterface;
+using osu.Game.Overlays.Settings;
+
+namespace osu.Game.Tournament.Screens.Ladder.Components
+{
+ public class LadderSettingsDropdown : SettingsDropdown
+ {
+ protected override OsuDropdown CreateDropdown() => new DropdownControl();
+
+ private new class DropdownControl : SettingsDropdown.DropdownControl
+ {
+ protected override DropdownMenu CreateMenu() => new Menu();
+
+ private new class Menu : OsuDropdownMenu
+ {
+ public Menu()
+ {
+ MaxHeight = 200;
+ }
+ }
+ }
+ }
+}
diff --git a/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs
new file mode 100644
index 0000000000..a630e51e44
--- /dev/null
+++ b/osu.Game.Tournament/Screens/Ladder/Components/SettingsTeamDropdown.cs
@@ -0,0 +1,55 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using osu.Framework.Bindables;
+using osu.Framework.Extensions.IEnumerableExtensions;
+using osu.Game.Tournament.Models;
+
+namespace osu.Game.Tournament.Screens.Ladder.Components
+{
+ public class SettingsTeamDropdown : LadderSettingsDropdown
+ {
+ public SettingsTeamDropdown(BindableList teams)
+ {
+ foreach (var t in teams.Prepend(new TournamentTeam()))
+ add(t);
+
+ teams.CollectionChanged += (_, args) =>
+ {
+ switch (args.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ args.NewItems.Cast().ForEach(add);
+ break;
+
+ case NotifyCollectionChangedAction.Remove:
+ args.OldItems.Cast().ForEach(i => Control.RemoveDropdownItem(i));
+ break;
+ }
+ };
+ }
+
+ private readonly List refBindables = new List();
+
+ private T boundReference(T obj)
+ where T : IBindable
+ {
+ obj = (T)obj.GetBoundCopy();
+ refBindables.Add(obj);
+ return obj;
+ }
+
+ private void add(TournamentTeam team)
+ {
+ Control.AddDropdownItem(team);
+ boundReference(team.FullName).BindValueChanged(_ =>
+ {
+ Control.RemoveDropdownItem(team);
+ Control.AddDropdownItem(team);
+ });
+ }
+ }
+}
diff --git a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
index 8ea366e1b4..293f6e0068 100644
--- a/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
+++ b/osu.Game.Tournament/Screens/Ladder/LadderScreen.cs
@@ -42,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Ladder
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
- new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
+ new TourneyVideo(storage.GetStream(@"videos/ladder.m4v"))
{
RelativeSizeAxes = Axes.Both,
Loop = true,
@@ -80,7 +80,7 @@ namespace osu.Game.Tournament.Screens.Ladder
break;
case NotifyCollectionChangedAction.Remove:
- foreach (var p in args.NewItems.Cast())
+ foreach (var p in args.OldItems.Cast())
{
foreach (var d in MatchesContainer.Where(d => d.Match == p))
d.Expire();
diff --git a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs
index c3875716b8..c42d0a6da3 100644
--- a/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs
+++ b/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs
@@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
-using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.IPC;
@@ -56,7 +55,7 @@ namespace osu.Game.Tournament.Screens.MapPool
{
Children = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = "Current Mode"
},
diff --git a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs
index 4b46264055..080570eac4 100644
--- a/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs
+++ b/osu.Game.Tournament/Screens/Schedule/ScheduleScreen.cs
@@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Platform;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Ladder.Components;
@@ -34,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Schedule
InternalChildren = new Drawable[]
{
- new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
+ new TourneyVideo(storage.GetStream(@"videos/schedule.m4v"))
{
RelativeSizeAxes = Axes.Both,
Loop = true,
@@ -107,20 +106,20 @@ namespace osu.Game.Tournament.Screens.Schedule
Height = 0.25f,
Children = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 },
Spacing = new Vector2(10, 0),
Text = match.NewValue.Round.Value?.Name.Value,
Colour = Color4.Black,
- Font = OsuFont.GetFont(size: 20)
+ Font = OsuFont.Torus.With(size: 20)
},
new ScheduleMatch(match.NewValue, false),
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"),
Colour = Color4.Black,
- Font = OsuFont.GetFont(size: 20)
+ Font = OsuFont.Torus.With(size: 20)
},
}
}
@@ -150,7 +149,7 @@ namespace osu.Game.Tournament.Screens.Schedule
Alpha = conditional ? 0.6f : 1,
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
});
- AddInternal(new OsuSpriteText
+ AddInternal(new TournamentSpriteText
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomLeft,
@@ -174,13 +173,13 @@ namespace osu.Game.Tournament.Screens.Schedule
Padding = new MarginPadding { Left = 30, Top = 30 };
InternalChildren = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
X = 30,
Text = title,
Colour = Color4.Black,
Spacing = new Vector2(10, 0),
- Font = OsuFont.GetFont(size: 30)
+ Font = OsuFont.Torus.With(size: 30)
},
content = new FillFlowContainer
{
diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/SetupScreen.cs
index 8e1481d87c..023582166c 100644
--- a/osu.Game.Tournament/Screens/SetupScreen.cs
+++ b/osu.Game.Tournament/Screens/SetupScreen.cs
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Graphics.UserInterfaceV2;
using osu.Game.Online.API;
@@ -147,7 +146,7 @@ namespace osu.Game.Tournament.Screens
public Action Action;
- private OsuSpriteText valueText;
+ private TournamentSpriteText valueText;
protected override Drawable CreateComponent() => new Container
{
@@ -155,7 +154,7 @@ namespace osu.Game.Tournament.Screens
RelativeSizeAxes = Axes.X,
Children = new Drawable[]
{
- valueText = new OsuSpriteText
+ valueText = new TournamentSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
index 20928499bf..d809dfc994 100644
--- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
+++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
@@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Showcase
[BackgroundDependencyLoader]
private void load()
{
- AddInternal(new TournamentLogo(false));
+ AddInternal(new TournamentLogo());
}
}
}
diff --git a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs
index 1fee2b29e8..6ad5ccaf0c 100644
--- a/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs
+++ b/osu.Game.Tournament/Screens/Showcase/TournamentLogo.cs
@@ -11,20 +11,12 @@ namespace osu.Game.Tournament.Screens.Showcase
{
public class TournamentLogo : CompositeDrawable
{
- public TournamentLogo(bool includeRoundBackground = true)
+ public TournamentLogo()
{
RelativeSizeAxes = Axes.X;
Margin = new MarginPadding { Vertical = 5 };
- if (includeRoundBackground)
- {
- AutoSizeAxes = Axes.Y;
- }
- else
- {
- Masking = true;
- Height = 100;
- }
+ Height = 100;
}
[BackgroundDependencyLoader]
@@ -32,9 +24,11 @@ namespace osu.Game.Tournament.Screens.Showcase
{
InternalChild = new Sprite
{
- Texture = textures.Get("game-screen-logo"),
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
+ FillMode = FillMode.Fit,
+ RelativeSizeAxes = Axes.Both,
+ Texture = textures.Get("game-screen-logo"),
};
}
}
diff --git a/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
new file mode 100644
index 0000000000..db5363c155
--- /dev/null
+++ b/osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
@@ -0,0 +1,316 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Bindables;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.Textures;
+using osu.Framework.Platform;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Tournament.Components;
+using osu.Game.Tournament.Models;
+using osu.Game.Tournament.Screens.Ladder.Components;
+using osuTK;
+using osuTK.Graphics;
+
+namespace osu.Game.Tournament.Screens.TeamIntro
+{
+ public class SeedingScreen : TournamentScreen, IProvideVideo
+ {
+ private Container mainContainer;
+
+ private readonly Bindable currentMatch = new Bindable();
+
+ private readonly Bindable currentTeam = new Bindable();
+
+ [BackgroundDependencyLoader]
+ private void load(Storage storage)
+ {
+ RelativeSizeAxes = Axes.Both;
+
+ InternalChildren = new Drawable[]
+ {
+ new TourneyVideo(storage.GetStream(@"videos/seeding.m4v"))
+ {
+ RelativeSizeAxes = Axes.Both,
+ Loop = true,
+ },
+ mainContainer = new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ },
+ new ControlPanel
+ {
+ Children = new Drawable[]
+ {
+ new TourneyButton
+ {
+ RelativeSizeAxes = Axes.X,
+ Text = "Show first team",
+ Action = () => currentTeam.Value = currentMatch.Value.Team1.Value,
+ },
+ new TourneyButton
+ {
+ RelativeSizeAxes = Axes.X,
+ Text = "Show second team",
+ Action = () => currentTeam.Value = currentMatch.Value.Team2.Value,
+ },
+ new SettingsTeamDropdown(LadderInfo.Teams)
+ {
+ LabelText = "Show specific team",
+ Bindable = currentTeam,
+ }
+ }
+ }
+ };
+
+ currentMatch.BindValueChanged(matchChanged);
+ currentMatch.BindTo(LadderInfo.CurrentMatch);
+
+ currentTeam.BindValueChanged(teamChanged, true);
+ }
+
+ private void teamChanged(ValueChangedEvent team)
+ {
+ if (team.NewValue == null)
+ {
+ mainContainer.Clear();
+ return;
+ }
+
+ showTeam(team.NewValue);
+ }
+
+ private void matchChanged(ValueChangedEvent match) =>
+ currentTeam.Value = currentMatch.Value.Team1.Value;
+
+ private void showTeam(TournamentTeam team)
+ {
+ mainContainer.Children = new Drawable[]
+ {
+ new LeftInfo(team) { Position = new Vector2(55, 150), },
+ new RightInfo(team) { Position = new Vector2(500, 150), },
+ };
+ }
+
+ private class RightInfo : CompositeDrawable
+ {
+ public RightInfo(TournamentTeam team)
+ {
+ FillFlowContainer fill;
+
+ Width = 400;
+
+ InternalChildren = new Drawable[]
+ {
+ fill = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Vertical,
+ },
+ };
+
+ foreach (var seeding in team.SeedingResults)
+ {
+ fill.Add(new ModRow(seeding.Mod.Value, seeding.Seed.Value));
+ foreach (var beatmap in seeding.Beatmaps)
+ fill.Add(new BeatmapScoreRow(beatmap));
+ }
+ }
+
+ private class BeatmapScoreRow : CompositeDrawable
+ {
+ public BeatmapScoreRow(SeedingBeatmap beatmap)
+ {
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+
+ InternalChildren = new Drawable[]
+ {
+ new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Horizontal,
+ Spacing = new Vector2(5),
+ Children = new Drawable[]
+ {
+ new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Title, Colour = Color4.Black, },
+ new TournamentSpriteText { Text = "by", Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
+ new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Artist, Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
+ }
+ },
+ new FillFlowContainer
+ {
+ AutoSizeAxes = Axes.Y,
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ Direction = FillDirection.Horizontal,
+ Spacing = new Vector2(40),
+ Children = new Drawable[]
+ {
+ new TournamentSpriteText { Text = beatmap.Score.ToString("#,0"), Colour = Color4.Black, Width = 80 },
+ new TournamentSpriteText { Text = "#" + beatmap.Seed.Value.ToString("#,0"), Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
+ }
+ },
+ };
+ }
+ }
+
+ private class ModRow : CompositeDrawable
+ {
+ private readonly string mods;
+ private readonly int seeding;
+
+ public ModRow(string mods, int seeding)
+ {
+ this.mods = mods;
+ this.seeding = seeding;
+
+ Padding = new MarginPadding { Vertical = 10 };
+
+ AutoSizeAxes = Axes.Y;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(TextureStore textures)
+ {
+ InternalChildren = new Drawable[]
+ {
+ new FillFlowContainer
+ {
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Horizontal,
+ Spacing = new Vector2(5),
+ Children = new Drawable[]
+ {
+ new Sprite
+ {
+ Texture = textures.Get($"mods/{mods.ToLower()}"),
+ Scale = new Vector2(0.5f)
+ },
+ new Container
+ {
+ Size = new Vector2(50, 16),
+ CornerRadius = 10,
+ Masking = true,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Black,
+ },
+ new TournamentSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Text = seeding.ToString("#,0"),
+ },
+ }
+ },
+ }
+ },
+ };
+ }
+ }
+ }
+
+ private class LeftInfo : CompositeDrawable
+ {
+ public LeftInfo(TournamentTeam team)
+ {
+ FillFlowContainer fill;
+
+ Width = 200;
+
+ if (team == null) return;
+
+ InternalChildren = new Drawable[]
+ {
+ fill = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Vertical,
+ Children = new Drawable[]
+ {
+ new TeamDisplay(team) { Margin = new MarginPadding { Bottom = 30 } },
+ new RowDisplay("Average Rank:", $"#{team.AverageRank:#,0}"),
+ new RowDisplay("Seed:", team.Seed.Value),
+ new RowDisplay("Last year's placing:", team.LastYearPlacing.Value > 0 ? $"#{team.LastYearPlacing:#,0}" : "0"),
+ new Container { Margin = new MarginPadding { Bottom = 30 } },
+ }
+ },
+ };
+
+ foreach (var p in team.Players)
+ fill.Add(new RowDisplay(p.Username, p.Statistics?.Ranks.Global?.ToString("\\##,0") ?? "-"));
+ }
+
+ internal class RowDisplay : CompositeDrawable
+ {
+ public RowDisplay(string left, string right)
+ {
+ AutoSizeAxes = Axes.Y;
+ RelativeSizeAxes = Axes.X;
+
+ var colour = OsuColour.Gray(0.3f);
+
+ InternalChildren = new Drawable[]
+ {
+ new TournamentSpriteText
+ {
+ Text = left,
+ Colour = colour,
+ Font = OsuFont.Torus.With(size: 22),
+ },
+ new TournamentSpriteText
+ {
+ Text = right,
+ Colour = colour,
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopLeft,
+ Font = OsuFont.Torus.With(size: 22, weight: FontWeight.Regular),
+ },
+ };
+ }
+ }
+
+ private class TeamDisplay : DrawableTournamentTeam
+ {
+ public TeamDisplay(TournamentTeam team)
+ : base(team)
+ {
+ AutoSizeAxes = Axes.Both;
+
+ Flag.RelativeSizeAxes = Axes.None;
+ Flag.Size = new Vector2(300, 200);
+ Flag.Scale = new Vector2(0.3f);
+
+ InternalChild = new FillFlowContainer
+ {
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(0, 5),
+ Children = new Drawable[]
+ {
+ Flag,
+ new OsuSpriteText
+ {
+ Text = team?.FullName.Value ?? "???",
+ Font = OsuFont.Torus.With(size: 32, weight: FontWeight.SemiBold),
+ Colour = Color4.Black,
+ },
+ }
+ };
+ }
+ }
+ }
+ }
+}
diff --git a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs
index 47c923ff30..6559113f55 100644
--- a/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs
+++ b/osu.Game.Tournament/Screens/TeamIntro/TeamIntroScreen.cs
@@ -7,12 +7,9 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Platform;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
-using osu.Game.Tournament.Screens.Showcase;
using osuTK;
-using osuTK.Graphics;
namespace osu.Game.Tournament.Screens.TeamIntro
{
@@ -29,12 +26,11 @@ namespace osu.Game.Tournament.Screens.TeamIntro
InternalChildren = new Drawable[]
{
- new TourneyVideo(storage.GetStream(@"BG Team - Both OWC.m4v"))
+ new TourneyVideo(storage.GetStream(@"videos/teamintro.m4v"))
{
RelativeSizeAxes = Axes.Both,
Loop = true,
},
- new TournamentLogo(false),
mainContainer = new Container
{
RelativeSizeAxes = Axes.Both,
@@ -75,8 +71,9 @@ namespace osu.Game.Tournament.Screens.TeamIntro
{
RelativeSizeAxes = Axes.Both,
Height = 0.25f,
- Anchor = Anchor.BottomCentre,
- Origin = Anchor.BottomCentre,
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ Y = 180,
}
};
}
@@ -85,8 +82,6 @@ namespace osu.Game.Tournament.Screens.TeamIntro
{
public RoundDisplay(TournamentMatch match)
{
- var col = OsuColour.Gray(0.33f);
-
InternalChildren = new Drawable[]
{
new FillFlowContainer
@@ -98,31 +93,13 @@ namespace osu.Game.Tournament.Screens.TeamIntro
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
- new OsuSpriteText
+ new TournamentSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
- Colour = col,
- Text = "COMING UP NEXT",
- Spacing = new Vector2(2, 0),
- Font = OsuFont.GetFont(size: 15, weight: FontWeight.Black)
- },
- new OsuSpriteText
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Colour = col,
+ Colour = OsuColour.Gray(0.33f),
Text = match.Round.Value?.Name.Value ?? "Unknown Round",
- Spacing = new Vector2(10, 0),
- Font = OsuFont.GetFont(size: 50, weight: FontWeight.Light)
- },
- new OsuSpriteText
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Colour = col,
- Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"),
- Font = OsuFont.GetFont(size: 20)
+ Font = OsuFont.Torus.With(size: 26, weight: FontWeight.Light)
},
}
}
@@ -132,21 +109,19 @@ namespace osu.Game.Tournament.Screens.TeamIntro
private class TeamWithPlayers : CompositeDrawable
{
- private readonly Color4 red = new Color4(129, 68, 65, 255);
- private readonly Color4 blue = new Color4(41, 91, 97, 255);
-
public TeamWithPlayers(TournamentTeam team, bool left = false)
{
FillFlowContainer players;
- var colour = left ? red : blue;
+ var colour = left ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
InternalChildren = new Drawable[]
{
- new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour)
+ new TeamDisplay(team)
{
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
- Origin = Anchor.Centre,
+ Origin = Anchor.TopCentre,
RelativePositionAxes = Axes.Both,
- X = (left ? -1 : 1) * 0.36f,
+ X = (left ? -1 : 1) * 0.3145f,
+ Y = -0.077f,
},
players = new FillFlowContainer
{
@@ -157,7 +132,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
RelativePositionAxes = Axes.Both,
- X = (left ? -1 : 1) * 0.66f,
+ X = (left ? -1 : 1) * 0.58f,
},
};
@@ -165,10 +140,10 @@ namespace osu.Game.Tournament.Screens.TeamIntro
{
foreach (var p in team.Players)
{
- players.Add(new OsuSpriteText
+ players.Add(new TournamentSpriteText
{
Text = p.Username,
- Font = OsuFont.GetFont(size: 24),
+ Font = OsuFont.Torus.With(size: 24),
Colour = colour,
Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
@@ -179,7 +154,7 @@ namespace osu.Game.Tournament.Screens.TeamIntro
private class TeamDisplay : DrawableTournamentTeam
{
- public TeamDisplay(TournamentTeam team, string teamName, Color4 colour)
+ public TeamDisplay(TournamentTeam team)
: base(team)
{
AutoSizeAxes = Axes.Both;
@@ -187,33 +162,24 @@ namespace osu.Game.Tournament.Screens.TeamIntro
Flag.Anchor = Flag.Origin = Anchor.TopCentre;
Flag.RelativeSizeAxes = Axes.None;
Flag.Size = new Vector2(300, 200);
- Flag.Scale = new Vector2(0.4f);
- Flag.Margin = new MarginPadding { Bottom = 20 };
+ Flag.Scale = new Vector2(0.32f);
InternalChild = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
- Spacing = new Vector2(0, 5),
+ Spacing = new Vector2(160),
Children = new Drawable[]
{
Flag,
- new OsuSpriteText
+ new TournamentSpriteText
{
- Text = team?.FullName.Value.ToUpper() ?? "???",
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light),
- Colour = Color4.Black,
+ Text = team?.FullName.Value ?? "???",
+ Font = OsuFont.Torus.With(size: 20, weight: FontWeight.Regular),
+ Colour = OsuColour.Gray(0.2f),
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
},
- new OsuSpriteText
- {
- Text = teamName.ToUpper(),
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Regular),
- Colour = colour,
- Origin = Anchor.TopCentre,
- Anchor = Anchor.TopCentre,
- }
}
};
}
diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
index a0216c5db3..30b86f8421 100644
--- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
+++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
@@ -7,10 +7,8 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Platform;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using osu.Game.Tournament.Models;
-using osu.Game.Tournament.Screens.Showcase;
using osuTK;
using osuTK.Graphics;
@@ -33,22 +31,18 @@ namespace osu.Game.Tournament.Screens.TeamWin
InternalChildren = new Drawable[]
{
- blueWinVideo = new TourneyVideo(storage.GetStream(@"BG Team - Win Blue.m4v"))
+ blueWinVideo = new TourneyVideo(storage.GetStream(@"videos/teamwin-blue.m4v"))
{
Alpha = 1,
RelativeSizeAxes = Axes.Both,
Loop = true,
},
- redWinVideo = new TourneyVideo(storage.GetStream(@"BG Team - Win Red.m4v"))
+ redWinVideo = new TourneyVideo(storage.GetStream(@"videos/teamwin-red.m4v"))
{
Alpha = 0,
RelativeSizeAxes = Axes.Both,
Loop = true,
},
- new TournamentLogo(false)
- {
- Y = 40,
- },
mainContainer = new Container
{
RelativeSizeAxes = Axes.Both,
@@ -85,141 +79,99 @@ namespace osu.Game.Tournament.Screens.TeamWin
mainContainer.Children = new Drawable[]
{
+ new TeamFlagDisplay(match.Winner)
+ {
+ Size = new Vector2(300, 200),
+ Scale = new Vector2(0.5f),
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ X = -387,
+ },
+ new TournamentSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.TopLeft,
+ Position = new Vector2(78, -70),
+ Colour = OsuColour.Gray(0.33f),
+ Text = match.Round.Value?.Name.Value ?? "Unknown Round",
+ Font = OsuFont.Torus.With(size: 30, weight: FontWeight.Regular)
+ },
new TeamWithPlayers(match.Winner, redWin)
{
RelativeSizeAxes = Axes.Both,
Width = 0.5f,
Height = 0.6f,
Anchor = Anchor.Centre,
- Origin = Anchor.Centre
+ Origin = Anchor.TopLeft,
+ Position = new Vector2(78, 0),
},
- new RoundDisplay(match)
- {
- RelativeSizeAxes = Axes.Both,
- Height = 0.25f,
- Anchor = Anchor.BottomCentre,
- Origin = Anchor.BottomCentre,
- }
};
}
- private class RoundDisplay : CompositeDrawable
- {
- public RoundDisplay(TournamentMatch match)
- {
- var col = OsuColour.Gray(0.33f);
-
- InternalChildren = new Drawable[]
- {
- new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Direction = FillDirection.Vertical,
- Spacing = new Vector2(0, 10),
- Children = new Drawable[]
- {
- new OsuSpriteText
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Colour = col,
- Text = "WINNER",
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 15, FontWeight.Regular),
- },
- new OsuSpriteText
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Colour = col,
- Text = match.Round.Value?.Name.Value ?? "Unknown Round",
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 50, FontWeight.Light),
- Spacing = new Vector2(10, 0),
- },
- new OsuSpriteText
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- Colour = col,
- Text = match.Date.Value.ToUniversalTime().ToString("dd MMMM HH:mm UTC"),
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 20, FontWeight.Light),
- },
- }
- }
- };
- }
- }
-
private class TeamWithPlayers : CompositeDrawable
{
- private readonly Color4 red = new Color4(129, 68, 65, 255);
- private readonly Color4 blue = new Color4(41, 91, 97, 255);
-
public TeamWithPlayers(TournamentTeam team, bool left = false)
{
- var colour = left ? red : blue;
+ FillFlowContainer players;
+
+ var colour = left ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
InternalChildren = new Drawable[]
{
- new TeamDisplay(team, left ? "Team Red" : "Team Blue", colour)
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- },
new FillFlowContainer
{
Direction = FillDirection.Vertical,
AutoSizeAxes = Axes.Both,
- Spacing = new Vector2(0, 5),
- Padding = new MarginPadding(20),
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- RelativePositionAxes = Axes.Both,
- },
- };
- }
-
- private class TeamDisplay : DrawableTournamentTeam
- {
- public TeamDisplay(TournamentTeam team, string teamName, Color4 colour)
- : base(team)
- {
- AutoSizeAxes = Axes.Both;
-
- Flag.Anchor = Flag.Origin = Anchor.TopCentre;
- Flag.RelativeSizeAxes = Axes.None;
- Flag.Size = new Vector2(300, 200);
- Flag.Scale = new Vector2(0.4f);
- Flag.Margin = new MarginPadding { Bottom = 20 };
-
- InternalChild = new FillFlowContainer
- {
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Vertical,
- Spacing = new Vector2(0, 5),
Children = new Drawable[]
{
- Flag,
- new OsuSpriteText
+ new TournamentSpriteText
{
- Text = team?.FullName.Value.ToUpper() ?? "???",
- Font = TournamentFont.GetFont(TournamentTypeface.Aquatico, 40, FontWeight.Light),
+ Text = "WINNER",
+ Font = OsuFont.Torus.With(size: 24, weight: FontWeight.SemiBold),
Colour = Color4.Black,
- Origin = Anchor.TopCentre,
- Anchor = Anchor.TopCentre,
},
- new OsuSpriteText
+ new TournamentSpriteText
{
- Text = teamName.ToUpper(),
- Font = OsuFont.GetFont(size: 20),
- Colour = colour,
- Origin = Anchor.TopCentre,
- Anchor = Anchor.TopCentre,
- }
+ Text = team?.FullName.Value ?? "???",
+ Font = OsuFont.Torus.With(size: 30, weight: FontWeight.SemiBold),
+ Colour = Color4.Black,
+ },
+ players = new FillFlowContainer
+ {
+ Direction = FillDirection.Vertical,
+ AutoSizeAxes = Axes.Both,
+ Padding = new MarginPadding { Top = 10 },
+ },
}
- };
+ },
+ };
+
+ if (team != null)
+ {
+ foreach (var p in team.Players)
+ {
+ players.Add(new TournamentSpriteText
+ {
+ Text = p.Username,
+ Font = OsuFont.Torus.With(size: 24),
+ Colour = colour,
+ Anchor = left ? Anchor.CentreRight : Anchor.CentreLeft,
+ Origin = left ? Anchor.CentreRight : Anchor.CentreLeft,
+ });
+ }
}
}
}
+
+ private class TeamFlagDisplay : DrawableTournamentTeam
+ {
+ public TeamFlagDisplay(TournamentTeam team)
+ : base(team)
+ {
+ InternalChildren = new Drawable[]
+ {
+ Flag
+ };
+ }
+ }
}
}
diff --git a/osu.Game.Tournament/TournamentFont.cs b/osu.Game.Tournament/TournamentFont.cs
deleted file mode 100644
index 32f0264562..0000000000
--- a/osu.Game.Tournament/TournamentFont.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
-// See the LICENCE file in the repository root for full licence text.
-
-using osu.Framework.Graphics.Sprites;
-using osu.Game.Graphics;
-
-namespace osu.Game.Tournament
-{
- public static class TournamentFont
- {
- ///
- /// The default font size.
- ///
- public const float DEFAULT_FONT_SIZE = 16;
-
- ///
- /// Retrieves a .
- ///
- /// The font typeface.
- /// The size of the text in local space. For a value of 16, a single line will have a height of 16px.
- /// The font weight.
- /// Whether the font is italic.
- /// Whether all characters should be spaced the same distance apart.
- /// The .
- public static FontUsage GetFont(TournamentTypeface typeface = TournamentTypeface.Aquatico, float size = DEFAULT_FONT_SIZE, FontWeight weight = FontWeight.Medium, bool italics = false, bool fixedWidth = false)
- => new FontUsage(GetFamilyString(typeface), size, GetWeightString(typeface, weight), italics, fixedWidth);
-
- ///
- /// Retrieves the string representation of a .
- ///
- /// The .
- /// The string representation.
- public static string GetFamilyString(TournamentTypeface typeface)
- {
- switch (typeface)
- {
- case TournamentTypeface.Aquatico:
- return "Aquatico";
- }
-
- return null;
- }
-
- ///
- /// Retrieves the string representation of a .
- ///
- /// The .
- /// The .
- /// The string representation of in the specified .
- public static string GetWeightString(TournamentTypeface typeface, FontWeight weight)
- => GetWeightString(GetFamilyString(typeface), weight);
-
- ///
- /// Retrieves the string representation of a .
- ///
- /// The family string.
- /// The .
- /// The string representation of in the specified .
- public static string GetWeightString(string family, FontWeight weight)
- {
- string weightString = weight.ToString();
-
- // Only exo has an explicit "regular" weight, other fonts do not
- if (weight == FontWeight.Regular && family != GetFamilyString(TournamentTypeface.Aquatico))
- weightString = string.Empty;
-
- return weightString;
- }
- }
-
- public enum TournamentTypeface
- {
- Aquatico
- }
-}
diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs
index 7dbcf37af6..608fc5f04a 100644
--- a/osu.Game.Tournament/TournamentGame.cs
+++ b/osu.Game.Tournament/TournamentGame.cs
@@ -3,11 +3,15 @@
using osu.Framework.Graphics;
using osu.Game.Graphics.Cursor;
+using osuTK.Graphics;
namespace osu.Game.Tournament
{
public class TournamentGame : TournamentGameBase
{
+ public static readonly Color4 COLOUR_RED = new Color4(144, 0, 0, 255);
+ public static readonly Color4 COLOUR_BLUE = new Color4(0, 84, 144, 255);
+
protected override void LoadComplete()
{
base.LoadComplete();
diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs
index 1c94856a4e..435f315c8d 100644
--- a/osu.Game.Tournament/TournamentGameBase.cs
+++ b/osu.Game.Tournament/TournamentGameBase.cs
@@ -18,7 +18,6 @@ using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
-using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests;
using osu.Game.Tournament.IPC;
using osu.Game.Tournament.Models;
@@ -54,9 +53,6 @@ namespace osu.Game.Tournament
{
Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly));
- AddFont(Resources, @"Resources/Fonts/Aquatico-Regular");
- AddFont(Resources, @"Resources/Fonts/Aquatico-Light");
-
Textures.AddStore(new TextureLoaderStore(new ResourceStore(new StorageBackedResourceStore(storage))));
this.storage = storage;
@@ -104,10 +100,10 @@ namespace osu.Game.Tournament
Colour = Color4.Red,
RelativeSizeAxes = Axes.Both,
},
- new OsuSpriteText
+ new TournamentSpriteText
{
Text = "Please make the window wider",
- Font = OsuFont.Default.With(weight: "bold"),
+ Font = OsuFont.Torus.With(weight: FontWeight.Bold),
Colour = Color4.White,
Padding = new MarginPadding(20)
}
@@ -124,10 +120,9 @@ namespace osu.Game.Tournament
using (var sr = new StreamReader(stream))
ladder = JsonConvert.DeserializeObject(sr.ReadToEnd());
}
- else
- {
+
+ if (ladder == null)
ladder = new LadderInfo();
- }
if (ladder.Ruleset.Value == null)
ladder.Ruleset.Value = RulesetStore.AvailableRulesets.First();
@@ -205,9 +200,11 @@ namespace osu.Game.Tournament
{
foreach (var p in t.Players)
{
- if (p.Username == null || p.Statistics == null)
+ if (string.IsNullOrEmpty(p.Username) || p.Statistics == null)
+ {
PopulateUser(p);
- addedInfo = true;
+ addedInfo = true;
+ }
}
}
@@ -243,6 +240,24 @@ namespace osu.Game.Tournament
}
}
+ foreach (var t in ladder.Teams)
+ {
+ foreach (var s in t.SeedingResults)
+ {
+ foreach (var b in s.Beatmaps)
+ {
+ if (b.BeatmapInfo == null && b.ID > 0)
+ {
+ var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = b.ID });
+ req.Perform(API);
+ b.BeatmapInfo = req.Result?.ToBeatmap(RulesetStore);
+
+ addedInfo = true;
+ }
+ }
+ }
+ }
+
return addedInfo;
}
diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs
index de3d685c31..9f5f2b6827 100644
--- a/osu.Game.Tournament/TournamentSceneManager.cs
+++ b/osu.Game.Tournament/TournamentSceneManager.cs
@@ -61,7 +61,7 @@ namespace osu.Game.Tournament
//Masking = true,
Children = new Drawable[]
{
- video = new TourneyVideo(storage.GetStream("BG Logoless - OWC.m4v"))
+ video = new TourneyVideo(storage.GetStream("videos/main.m4v"))
{
Loop = true,
RelativeSizeAxes = Axes.Both,
@@ -80,6 +80,7 @@ namespace osu.Game.Tournament
new ShowcaseScreen(),
new MapPoolScreen(),
new TeamIntroScreen(),
+ new SeedingScreen(),
new DrawingsScreen(),
new GameplayScreen(),
new TeamWinScreen()
@@ -121,6 +122,7 @@ namespace osu.Game.Tournament
new ScreenButton(typeof(LadderScreen)) { Text = "Bracket", RequestSelection = SetScreen },
new Separator(),
new ScreenButton(typeof(TeamIntroScreen)) { Text = "TeamIntro", RequestSelection = SetScreen },
+ new ScreenButton(typeof(SeedingScreen)) { Text = "Seeding", RequestSelection = SetScreen },
new Separator(),
new ScreenButton(typeof(MapPoolScreen)) { Text = "MapPool", RequestSelection = SetScreen },
new ScreenButton(typeof(GameplayScreen)) { Text = "Gameplay", RequestSelection = SetScreen },
@@ -146,8 +148,20 @@ namespace osu.Game.Tournament
private Drawable currentScreen;
private ScheduledDelegate scheduledHide;
+ private Drawable temporaryScreen;
+
+ public void SetScreen(Drawable screen)
+ {
+ currentScreen?.Hide();
+ currentScreen = null;
+
+ screens.Add(temporaryScreen = screen);
+ }
+
public void SetScreen(Type screenType)
{
+ temporaryScreen?.Expire();
+
var target = screens.FirstOrDefault(s => s.GetType() == screenType);
if (target == null || currentScreen == target) return;
diff --git a/osu.Game.Tournament/TournamentSpriteText.cs b/osu.Game.Tournament/TournamentSpriteText.cs
new file mode 100644
index 0000000000..e550dfbfae
--- /dev/null
+++ b/osu.Game.Tournament/TournamentSpriteText.cs
@@ -0,0 +1,16 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+
+namespace osu.Game.Tournament
+{
+ public class TournamentSpriteText : OsuSpriteText
+ {
+ public TournamentSpriteText()
+ {
+ Font = OsuFont.Torus;
+ }
+ }
+}
diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs
index ce959e9057..21de654670 100644
--- a/osu.Game/Configuration/OsuConfigManager.cs
+++ b/osu.Game/Configuration/OsuConfigManager.cs
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using osu.Framework.Bindables;
using osu.Framework.Configuration;
using osu.Framework.Configuration.Tracking;
using osu.Framework.Extensions;
@@ -126,6 +127,35 @@ namespace osu.Game.Configuration
public OsuConfigManager(Storage storage)
: base(storage)
{
+ Migrate();
+ }
+
+ public void Migrate()
+ {
+ // arrives as 2020.123.0
+ var rawVersion = Get(OsuSetting.Version);
+
+ if (rawVersion.Length < 6)
+ return;
+
+ var pieces = rawVersion.Split('.');
+
+ // on a fresh install or when coming from a non-release build, execution will end here.
+ // we don't want to run migrations in such cases.
+ if (!int.TryParse(pieces[0], out int year)) return;
+ if (!int.TryParse(pieces[1], out int monthDay)) return;
+
+ int combined = (year * 10000) + monthDay;
+
+ if (combined < 20200305)
+ {
+ // the maximum value of this setting was changed.
+ // if we don't manually increase this, it causes song select to filter out beatmaps the user expects to see.
+ var maxStars = (BindableDouble)GetOriginalBindable(OsuSetting.DisplayStarsMaximum);
+
+ if (maxStars.Value == 10)
+ maxStars.Value = maxStars.MaxValue;
+ }
}
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs
index b9c7b26e3e..590e4b2a5c 100644
--- a/osu.Game/Graphics/Backgrounds/Triangles.cs
+++ b/osu.Game/Graphics/Backgrounds/Triangles.cs
@@ -129,7 +129,7 @@ namespace osu.Game.Graphics.Backgrounds
{
base.Update();
- Invalidate(Invalidation.DrawNode, shallPropagate: false);
+ Invalidate(Invalidation.DrawNode);
if (CreateNewTriangles)
addTriangles(false);
diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs
index 9d886c457f..07a50c39e1 100644
--- a/osu.Game/Graphics/Containers/SectionsContainer.cs
+++ b/osu.Game/Graphics/Containers/SectionsContainer.cs
@@ -6,6 +6,7 @@ using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Layout;
namespace osu.Game.Graphics.Containers
{
@@ -142,15 +143,17 @@ namespace osu.Game.Graphics.Containers
public void ScrollToTop() => scrollContainer.ScrollTo(0);
- public override void InvalidateFromChild(Invalidation invalidation, Drawable source = null)
+ protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source)
{
- base.InvalidateFromChild(invalidation, source);
+ var result = base.OnInvalidate(invalidation, source);
- if ((invalidation & Invalidation.DrawSize) != 0)
+ if (source == InvalidationSource.Child && (invalidation & Invalidation.DrawSize) != 0)
{
- if (source == ExpandableHeader) //We need to recalculate the positions if the ExpandableHeader changed its size
- lastKnownScroll = -1;
+ lastKnownScroll = -1;
+ result = true;
}
+
+ return result;
}
private float lastKnownScroll;
diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs
index 22250d4a56..841936d2c5 100644
--- a/osu.Game/Graphics/OsuFont.cs
+++ b/osu.Game/Graphics/OsuFont.cs
@@ -17,7 +17,9 @@ namespace osu.Game.Graphics
///
public static FontUsage Default => GetFont();
- public static FontUsage Numeric => GetFont(Typeface.Venera, weight: FontWeight.Regular);
+ public static FontUsage Numeric => GetFont(Typeface.Venera, weight: FontWeight.Bold);
+
+ public static FontUsage Torus => GetFont(Typeface.Torus, weight: FontWeight.Regular);
///
/// Retrieves a .
@@ -45,6 +47,9 @@ namespace osu.Game.Graphics
case Typeface.Venera:
return "Venera";
+
+ case Typeface.Torus:
+ return "Torus";
}
return null;
@@ -65,16 +70,7 @@ namespace osu.Game.Graphics
/// The family string.
/// The .
/// The string representation of in the specified .
- public static string GetWeightString(string family, FontWeight weight)
- {
- string weightString = weight.ToString();
-
- // Only exo has an explicit "regular" weight, other fonts do not
- if (family != GetFamilyString(Typeface.Exo) && weight == FontWeight.Regular)
- weightString = string.Empty;
-
- return weightString;
- }
+ public static string GetWeightString(string family, FontWeight weight) => weight.ToString();
}
public static class OsuFontExtensions
@@ -102,15 +98,39 @@ namespace osu.Game.Graphics
{
Exo,
Venera,
+ Torus
}
public enum FontWeight
{
- Light,
- Regular,
- Medium,
- SemiBold,
- Bold,
- Black
+ ///
+ /// Equivalent to weight 300.
+ ///
+ Light = 300,
+
+ ///
+ /// Equivalent to weight 400.
+ ///
+ Regular = 400,
+
+ ///
+ /// Equivalent to weight 500.
+ ///
+ Medium = 500,
+
+ ///
+ /// Equivalent to weight 600.
+ ///
+ SemiBold = 600,
+
+ ///
+ /// Equivalent to weight 700.
+ ///
+ Bold = 700,
+
+ ///
+ /// Equivalent to weight 900.
+ ///
+ Black = 900
}
}
diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs
index 439a6002d8..60cb35b4c4 100644
--- a/osu.Game/Graphics/UserInterface/ExpandingBar.cs
+++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs
@@ -13,17 +13,17 @@ namespace osu.Game.Graphics.UserInterface
///
public class ExpandingBar : Circle
{
- private bool isCollapsed;
+ private bool expanded = true;
- public bool IsCollapsed
+ public bool Expanded
{
- get => isCollapsed;
+ get => expanded;
set
{
- if (value == isCollapsed)
+ if (value == expanded)
return;
- isCollapsed = value;
+ expanded = value;
updateState();
}
}
@@ -83,19 +83,21 @@ namespace osu.Game.Graphics.UserInterface
updateState();
}
- public void Collapse() => IsCollapsed = true;
+ public void Collapse() => Expanded = false;
- public void Expand() => IsCollapsed = false;
+ public void Expand() => Expanded = true;
private void updateState()
{
- float newSize = IsCollapsed ? CollapsedSize : ExpandedSize;
- Easing easingType = IsCollapsed ? Easing.Out : Easing.OutElastic;
+ float newSize = expanded ? ExpandedSize : CollapsedSize;
+ Easing easingType = expanded ? Easing.OutElastic : Easing.Out;
if (RelativeSizeAxes == Axes.X)
this.ResizeHeightTo(newSize, 400, easingType);
else
this.ResizeWidthTo(newSize, 400, easingType);
+
+ this.FadeTo(expanded ? 1 : 0.5f, 100, Easing.OutQuint);
}
}
}
diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs
index 6d65b77cbf..42b523fc5c 100644
--- a/osu.Game/Graphics/UserInterface/LineGraph.cs
+++ b/osu.Game/Graphics/UserInterface/LineGraph.cs
@@ -4,11 +4,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using osu.Framework.Caching;
using osuTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Lines;
+using osu.Framework.Layout;
using osuTK.Graphics;
namespace osu.Game.Graphics.UserInterface
@@ -83,17 +83,11 @@ namespace osu.Game.Graphics.UserInterface
PathRadius = 1
}
});
+
+ AddLayout(pathCached);
}
- public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
- {
- if ((invalidation & Invalidation.DrawSize) > 0)
- pathCached.Invalidate();
-
- return base.Invalidate(invalidation, source, shallPropagate);
- }
-
- private readonly Cached pathCached = new Cached();
+ private readonly LayoutValue pathCached = new LayoutValue(Invalidation.DrawSize);
protected override void Update()
{
diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
index ea274284ac..e83d899469 100644
--- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
+++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
@@ -31,8 +31,9 @@ namespace osu.Game.Input.Bindings
/// A reference to identify the current . Used to lookup mappings. Null for global mappings.
/// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts.
/// Specify how to deal with multiple matches of s and s.
- public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None)
- : base(simultaneousMode)
+ /// Specify how to deal with exact matches.
+ public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None, KeyCombinationMatchingMode matchingMode = KeyCombinationMatchingMode.Any)
+ : base(simultaneousMode, matchingMode)
{
this.ruleset = ruleset;
this.variant = variant;
diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
index 7763577a14..71771abede 100644
--- a/osu.Game/Input/Bindings/GlobalActionContainer.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -15,6 +15,7 @@ namespace osu.Game.Input.Bindings
private readonly Drawable handler;
public GlobalActionContainer(OsuGameBase game)
+ : base(matchingMode: KeyCombinationMatchingMode.Modifiers)
{
if (game is IKeyBindingHandler)
handler = game;
@@ -38,6 +39,9 @@ namespace osu.Game.Input.Bindings
new KeyBinding(InputKey.Escape, GlobalAction.Back),
new KeyBinding(InputKey.ExtraMouseButton1, GlobalAction.Back),
+ new KeyBinding(InputKey.Up, GlobalAction.SelectPrevious),
+ new KeyBinding(InputKey.Down, GlobalAction.SelectNext),
+
new KeyBinding(InputKey.Space, GlobalAction.Select),
new KeyBinding(InputKey.Enter, GlobalAction.Select),
new KeyBinding(InputKey.KeypadEnter, GlobalAction.Select),
@@ -54,10 +58,11 @@ namespace osu.Game.Input.Bindings
public IEnumerable AudioControlKeyBindings => new[]
{
- new KeyBinding(InputKey.Up, GlobalAction.IncreaseVolume),
- new KeyBinding(InputKey.MouseWheelUp, GlobalAction.IncreaseVolume),
- new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume),
- new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume),
+ new KeyBinding(new[] { InputKey.Alt, InputKey.Up }, GlobalAction.IncreaseVolume),
+ new KeyBinding(new[] { InputKey.Alt, InputKey.MouseWheelUp }, GlobalAction.IncreaseVolume),
+ new KeyBinding(new[] { InputKey.Alt, InputKey.Down }, GlobalAction.DecreaseVolume),
+ new KeyBinding(new[] { InputKey.Alt, InputKey.MouseWheelDown }, GlobalAction.DecreaseVolume),
+
new KeyBinding(InputKey.F4, GlobalAction.ToggleMute),
new KeyBinding(InputKey.TrackPrevious, GlobalAction.MusicPrev),
@@ -141,5 +146,11 @@ namespace osu.Game.Input.Bindings
[Description("Toggle now playing overlay")]
ToggleNowPlaying,
+
+ [Description("Previous Selection")]
+ SelectPrevious,
+
+ [Description("Next Selection")]
+ SelectNext,
}
}
diff --git a/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.Designer.cs b/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.Designer.cs
new file mode 100644
index 0000000000..22316b0380
--- /dev/null
+++ b/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.Designer.cs
@@ -0,0 +1,506 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using osu.Game.Database;
+
+namespace osu.Game.Migrations
+{
+ [DbContext(typeof(OsuDbContext))]
+ [Migration("20200302094919_RefreshVolumeBindings")]
+ partial class RefreshVolumeBindings
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApproachRate");
+
+ b.Property("CircleSize");
+
+ b.Property("DrainRate");
+
+ b.Property("OverallDifficulty");
+
+ b.Property("SliderMultiplier");
+
+ b.Property("SliderTickRate");
+
+ b.HasKey("ID");
+
+ b.ToTable("BeatmapDifficulty");
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AudioLeadIn");
+
+ b.Property("BPM");
+
+ b.Property("BaseDifficultyID");
+
+ b.Property("BeatDivisor");
+
+ b.Property("BeatmapSetInfoID");
+
+ b.Property("Countdown");
+
+ b.Property("DistanceSpacing");
+
+ b.Property("GridSize");
+
+ b.Property("Hash");
+
+ b.Property("Hidden");
+
+ b.Property("Length");
+
+ b.Property("LetterboxInBreaks");
+
+ b.Property("MD5Hash");
+
+ b.Property("MetadataID");
+
+ b.Property("OnlineBeatmapID");
+
+ b.Property("Path");
+
+ b.Property("RulesetID");
+
+ b.Property("SpecialStyle");
+
+ b.Property("StackLeniency");
+
+ b.Property("StarDifficulty");
+
+ b.Property("Status");
+
+ b.Property("StoredBookmarks");
+
+ b.Property("TimelineZoom");
+
+ b.Property("Version");
+
+ b.Property("WidescreenStoryboard");
+
+ b.HasKey("ID");
+
+ b.HasIndex("BaseDifficultyID");
+
+ b.HasIndex("BeatmapSetInfoID");
+
+ b.HasIndex("Hash");
+
+ b.HasIndex("MD5Hash");
+
+ b.HasIndex("MetadataID");
+
+ b.HasIndex("OnlineBeatmapID")
+ .IsUnique();
+
+ b.HasIndex("RulesetID");
+
+ b.ToTable("BeatmapInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Artist");
+
+ b.Property("ArtistUnicode");
+
+ b.Property("AudioFile");
+
+ b.Property("AuthorString")
+ .HasColumnName("Author");
+
+ b.Property("BackgroundFile");
+
+ b.Property("PreviewTime");
+
+ b.Property("Source");
+
+ b.Property("Tags");
+
+ b.Property("Title");
+
+ b.Property("TitleUnicode");
+
+ b.Property("VideoFile");
+
+ b.HasKey("ID");
+
+ b.ToTable("BeatmapMetadata");
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("BeatmapSetInfoID");
+
+ b.Property("FileInfoID");
+
+ b.Property("Filename")
+ .IsRequired();
+
+ b.HasKey("ID");
+
+ b.HasIndex("BeatmapSetInfoID");
+
+ b.HasIndex("FileInfoID");
+
+ b.ToTable("BeatmapSetFileInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("DateAdded");
+
+ b.Property("DeletePending");
+
+ b.Property("Hash");
+
+ b.Property("MetadataID");
+
+ b.Property("OnlineBeatmapSetID");
+
+ b.Property("Protected");
+
+ b.Property("Status");
+
+ b.HasKey("ID");
+
+ b.HasIndex("DeletePending");
+
+ b.HasIndex("Hash")
+ .IsUnique();
+
+ b.HasIndex("MetadataID");
+
+ b.HasIndex("OnlineBeatmapSetID")
+ .IsUnique();
+
+ b.ToTable("BeatmapSetInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Key")
+ .HasColumnName("Key");
+
+ b.Property("RulesetID");
+
+ b.Property("SkinInfoID");
+
+ b.Property("StringValue")
+ .HasColumnName("Value");
+
+ b.Property("Variant");
+
+ b.HasKey("ID");
+
+ b.HasIndex("SkinInfoID");
+
+ b.HasIndex("RulesetID", "Variant");
+
+ b.ToTable("Settings");
+ });
+
+ modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Hash");
+
+ b.Property("ReferenceCount");
+
+ b.HasKey("ID");
+
+ b.HasIndex("Hash")
+ .IsUnique();
+
+ b.HasIndex("ReferenceCount");
+
+ b.ToTable("FileInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("IntAction")
+ .HasColumnName("Action");
+
+ b.Property("KeysString")
+ .HasColumnName("Keys");
+
+ b.Property("RulesetID");
+
+ b.Property("Variant");
+
+ b.HasKey("ID");
+
+ b.HasIndex("IntAction");
+
+ b.HasIndex("RulesetID", "Variant");
+
+ b.ToTable("KeyBinding");
+ });
+
+ modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Available");
+
+ b.Property("InstantiationInfo");
+
+ b.Property("Name");
+
+ b.Property("ShortName");
+
+ b.HasKey("ID");
+
+ b.HasIndex("Available");
+
+ b.HasIndex("ShortName")
+ .IsUnique();
+
+ b.ToTable("RulesetInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("FileInfoID");
+
+ b.Property("Filename")
+ .IsRequired();
+
+ b.Property("ScoreInfoID");
+
+ b.HasKey("ID");
+
+ b.HasIndex("FileInfoID");
+
+ b.HasIndex("ScoreInfoID");
+
+ b.ToTable("ScoreFileInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Accuracy")
+ .HasColumnType("DECIMAL(1,4)");
+
+ b.Property("BeatmapInfoID");
+
+ b.Property("Combo");
+
+ b.Property("Date");
+
+ b.Property("DeletePending");
+
+ b.Property("Hash");
+
+ b.Property("MaxCombo");
+
+ b.Property("ModsJson")
+ .HasColumnName("Mods");
+
+ b.Property("OnlineScoreID");
+
+ b.Property("PP");
+
+ b.Property("Rank");
+
+ b.Property("RulesetID");
+
+ b.Property("StatisticsJson")
+ .HasColumnName("Statistics");
+
+ b.Property("TotalScore");
+
+ b.Property("UserID")
+ .HasColumnName("UserID");
+
+ b.Property("UserString")
+ .HasColumnName("User");
+
+ b.HasKey("ID");
+
+ b.HasIndex("BeatmapInfoID");
+
+ b.HasIndex("OnlineScoreID")
+ .IsUnique();
+
+ b.HasIndex("RulesetID");
+
+ b.ToTable("ScoreInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("FileInfoID");
+
+ b.Property("Filename")
+ .IsRequired();
+
+ b.Property("SkinInfoID");
+
+ b.HasKey("ID");
+
+ b.HasIndex("FileInfoID");
+
+ b.HasIndex("SkinInfoID");
+
+ b.ToTable("SkinFileInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
+ {
+ b.Property("ID")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Creator");
+
+ b.Property("DeletePending");
+
+ b.Property("Hash");
+
+ b.Property("Name");
+
+ b.HasKey("ID");
+
+ b.HasIndex("DeletePending");
+
+ b.HasIndex("Hash")
+ .IsUnique();
+
+ b.ToTable("SkinInfo");
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
+ {
+ b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
+ .WithMany()
+ .HasForeignKey("BaseDifficultyID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
+ .WithMany("Beatmaps")
+ .HasForeignKey("BeatmapSetInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
+ .WithMany("Beatmaps")
+ .HasForeignKey("MetadataID");
+
+ b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
+ .WithMany()
+ .HasForeignKey("RulesetID")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
+ {
+ b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
+ .WithMany("Files")
+ .HasForeignKey("BeatmapSetInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
+ .WithMany()
+ .HasForeignKey("FileInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
+ {
+ b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
+ .WithMany("BeatmapSets")
+ .HasForeignKey("MetadataID");
+ });
+
+ modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
+ {
+ b.HasOne("osu.Game.Skinning.SkinInfo")
+ .WithMany("Settings")
+ .HasForeignKey("SkinInfoID");
+ });
+
+ modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
+ {
+ b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
+ .WithMany()
+ .HasForeignKey("FileInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.Scoring.ScoreInfo")
+ .WithMany("Files")
+ .HasForeignKey("ScoreInfoID");
+ });
+
+ modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
+ {
+ b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
+ .WithMany("Scores")
+ .HasForeignKey("BeatmapInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
+ .WithMany()
+ .HasForeignKey("RulesetID")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
+ {
+ b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
+ .WithMany()
+ .HasForeignKey("FileInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("osu.Game.Skinning.SkinInfo")
+ .WithMany("Files")
+ .HasForeignKey("SkinInfoID")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.cs b/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.cs
new file mode 100644
index 0000000000..ec4475971c
--- /dev/null
+++ b/osu.Game/Migrations/20200302094919_RefreshVolumeBindings.cs
@@ -0,0 +1,16 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace osu.Game.Migrations
+{
+ public partial class RefreshVolumeBindings : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.Sql("DELETE FROM KeyBinding WHERE action in (6,7)");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ }
+ }
+}
diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs
index a6d9d1f3cb..bc4fc3342d 100644
--- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs
+++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs
@@ -43,7 +43,7 @@ namespace osu.Game.Migrations
b.Property("ID")
.ValueGeneratedOnAdd();
- b.Property("AudioLeadIn");
+ b.Property("AudioLeadIn");
b.Property("BPM");
diff --git a/osu.Game/Online/API/Requests/GetRoomRequest.cs b/osu.Game/Online/API/Requests/GetRoomRequest.cs
new file mode 100644
index 0000000000..531e1857de
--- /dev/null
+++ b/osu.Game/Online/API/Requests/GetRoomRequest.cs
@@ -0,0 +1,19 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Game.Online.Multiplayer;
+
+namespace osu.Game.Online.API.Requests
+{
+ public class GetRoomRequest : APIRequest
+ {
+ private readonly int roomId;
+
+ public GetRoomRequest(int roomId)
+ {
+ this.roomId = roomId;
+ }
+
+ protected override string Target => $"rooms/{roomId}";
+ }
+}
diff --git a/osu.Game/Online/Leaderboards/DrawableRank.cs b/osu.Game/Online/Leaderboards/DrawableRank.cs
index 50cb58c6ab..20bda4601f 100644
--- a/osu.Game/Online/Leaderboards/DrawableRank.cs
+++ b/osu.Game/Online/Leaderboards/DrawableRank.cs
@@ -58,7 +58,7 @@ namespace osu.Game.Online.Leaderboards
Spacing = new Vector2(-3, 0),
Padding = new MarginPadding { Top = 5 },
Colour = getRankNameColour(),
- Font = OsuFont.GetFont(Typeface.Venera, 25),
+ Font = OsuFont.Numeric.With(size: 25),
Text = getRankName(),
ShadowColour = Color4.Black.Opacity(0.3f),
ShadowOffset = new Vector2(0, 0.08f),
diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs
index c55822c407..d074ac9775 100644
--- a/osu.Game/Online/Multiplayer/Room.cs
+++ b/osu.Game/Online/Multiplayer/Room.cs
@@ -59,8 +59,8 @@ namespace osu.Game.Online.Multiplayer
public Bindable MaxParticipants { get; private set; } = new Bindable();
[Cached]
- [JsonIgnore]
- public BindableList Participants { get; private set; } = new BindableList();
+ [JsonProperty("recent_participants")]
+ public BindableList RecentParticipants { get; private set; } = new BindableList();
[Cached]
public Bindable ParticipantCount { get; private set; } = new Bindable();
@@ -124,10 +124,10 @@ namespace osu.Game.Online.Multiplayer
Playlist.AddRange(other.Playlist);
}
- if (!Participants.SequenceEqual(other.Participants))
+ if (!RecentParticipants.SequenceEqual(other.RecentParticipants))
{
- Participants.Clear();
- Participants.AddRange(other.Participants);
+ RecentParticipants.Clear();
+ RecentParticipants.AddRange(other.RecentParticipants);
}
Position = other.Position;
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index a73d5b57c4..1b2fd658f4 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -25,6 +25,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
using osu.Framework.Input.Bindings;
+using osu.Framework.Input.Events;
using osu.Framework.Platform;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
@@ -42,6 +43,7 @@ using osu.Game.Overlays.Volume;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Screens.Select;
+using osu.Game.Updater;
using osu.Game.Utils;
using LogLevel = osu.Framework.Logging.LogLevel;
@@ -389,24 +391,35 @@ namespace osu.Game
protected virtual Loader CreateLoader() => new Loader();
+ protected virtual UpdateManager CreateUpdateManager() => new UpdateManager();
+
protected override Container CreateScalingContainer() => new ScalingContainer(ScalingMode.Everything);
#region Beatmap progression
private void beatmapChanged(ValueChangedEvent beatmap)
{
- var nextBeatmap = beatmap.NewValue;
- if (nextBeatmap?.Track != null)
- nextBeatmap.Track.Completed += currentTrackCompleted;
-
- var oldBeatmap = beatmap.OldValue;
- if (oldBeatmap?.Track != null)
- oldBeatmap.Track.Completed -= currentTrackCompleted;
+ beatmap.OldValue?.CancelAsyncLoad();
updateModDefaults();
- oldBeatmap?.CancelAsyncLoad();
- nextBeatmap?.BeginAsyncLoad();
+ var newBeatmap = beatmap.NewValue;
+
+ if (newBeatmap != null)
+ {
+ newBeatmap.Track.Completed += () => Scheduler.AddOnce(() => trackCompleted(newBeatmap));
+ newBeatmap.BeginAsyncLoad();
+ }
+
+ void trackCompleted(WorkingBeatmap b)
+ {
+ // the source of track completion is the audio thread, so the beatmap may have changed before firing.
+ if (Beatmap.Value != b)
+ return;
+
+ if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled)
+ MusicController.NextTrack();
+ }
}
private void modsChanged(ValueChangedEvent> mods)
@@ -427,12 +440,6 @@ namespace osu.Game
}
}
- private void currentTrackCompleted() => Schedule(() =>
- {
- if (!Beatmap.Value.Track.Looping && !Beatmap.Disabled)
- musicController.NextTrack();
- });
-
#endregion
private ScheduledDelegate performFromMainMenuTask;
@@ -584,7 +591,7 @@ namespace osu.Game
loadComponentSingleFile(new OnScreenDisplay(), Add, true);
- loadComponentSingleFile(musicController = new MusicController(), Add, true);
+ loadComponentSingleFile(MusicController = new MusicController(), Add, true);
loadComponentSingleFile(notifications = new NotificationOverlay
{
@@ -627,6 +634,7 @@ namespace osu.Game
chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible;
Add(externalLinkOpener = new ExternalLinkOpener());
+ Add(CreateUpdateManager()); // dependency on notification overlay
// side overlays which cancel each other.
var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications };
@@ -805,6 +813,13 @@ namespace osu.Game
return d;
}
+ protected override bool OnScroll(ScrollEvent e)
+ {
+ // forward any unhandled mouse scroll events to the volume control.
+ volume.Adjust(GlobalAction.IncreaseVolume, e.ScrollDelta.Y, e.IsPrecise);
+ return true;
+ }
+
public bool OnPressed(GlobalAction action)
{
if (introScreen == null) return false;
@@ -885,7 +900,7 @@ namespace osu.Game
private ScalingContainer screenContainer;
- private MusicController musicController;
+ protected MusicController MusicController { get; private set; }
protected override bool OnExiting()
{
@@ -943,7 +958,7 @@ namespace osu.Game
{
OverlayActivationMode.Value = newOsuScreen.InitialOverlayActivationMode;
- musicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
+ MusicController.AllowRateAdjustments = newOsuScreen.AllowRateAdjustments;
if (newOsuScreen.HideOverlaysOnEnter)
CloseAllOverlays();
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 07c9d37a86..b2277e2abf 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -97,7 +97,7 @@ namespace osu.Game
public bool IsDeployedBuild => AssemblyVersion.Major > 0;
- public string Version
+ public virtual string Version
{
get
{
@@ -157,9 +157,14 @@ namespace osu.Game
AddFont(Resources, @"Fonts/Exo2.0-Black");
AddFont(Resources, @"Fonts/Exo2.0-BlackItalic");
- AddFont(Resources, @"Fonts/Venera");
+ AddFont(Resources, @"Fonts/Torus-SemiBold");
+ AddFont(Resources, @"Fonts/Torus-Bold");
+ AddFont(Resources, @"Fonts/Torus-Regular");
+ AddFont(Resources, @"Fonts/Torus-Light");
+
AddFont(Resources, @"Fonts/Venera-Light");
- AddFont(Resources, @"Fonts/Venera-Medium");
+ AddFont(Resources, @"Fonts/Venera-Bold");
+ AddFont(Resources, @"Fonts/Venera-Black");
runMigrations();
@@ -206,6 +211,10 @@ namespace osu.Game
Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));
Beatmap = new NonNullableBindable(defaultBeatmap);
+
+ // ScheduleAfterChildren is safety against something in the current frame accessing the previous beatmap's track
+ // and potentially causing a reload of it after just unloading.
+ // Note that the reason for this being added *has* been resolved, so it may be feasible to removed this if required.
Beatmap.BindValueChanged(b => ScheduleAfterChildren(() =>
{
// compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)
diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
index 446a075ae4..31c1439c8f 100644
--- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
+++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
@@ -59,7 +59,7 @@ namespace osu.Game.Overlays.BeatmapSet
if (online.Ranked.HasValue)
{
- fields.Add(new Field("ranked", online.Ranked.Value, OsuFont.GetFont(weight: FontWeight.Bold)));
+ fields.Add(new Field(online.Status.ToString().ToLowerInvariant(), online.Ranked.Value, OsuFont.GetFont(weight: FontWeight.Bold)));
}
else if (online.LastUpdated.HasValue)
{
diff --git a/osu.Game/Overlays/Changelog/ChangelogHeader.cs b/osu.Game/Overlays/Changelog/ChangelogHeader.cs
index 8663ec586b..dcadbf4cf5 100644
--- a/osu.Game/Overlays/Changelog/ChangelogHeader.cs
+++ b/osu.Game/Overlays/Changelog/ChangelogHeader.cs
@@ -4,9 +4,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
@@ -22,6 +24,8 @@ namespace osu.Game.Overlays.Changelog
private const string listing_string = "listing";
+ private Box streamsBackground;
+
public ChangelogHeader()
{
TabControl.AddItem(listing_string);
@@ -40,6 +44,12 @@ namespace osu.Game.Overlays.Changelog
};
}
+ [BackgroundDependencyLoader]
+ private void load(OverlayColourProvider colourProvider)
+ {
+ streamsBackground.Colour = colourProvider.Background5;
+ }
+
private ChangelogHeaderTitle title;
private void showBuild(ValueChangedEvent e)
@@ -72,7 +82,21 @@ namespace osu.Game.Overlays.Changelog
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
- Streams = new UpdateStreamBadgeArea(),
+ streamsBackground = new Box
+ {
+ RelativeSizeAxes = Axes.Both
+ },
+ new Container
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Padding = new MarginPadding
+ {
+ Horizontal = 65,
+ Vertical = 20
+ },
+ Child = Streams = new UpdateStreamBadgeArea()
+ }
}
};
diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs
index 10aca31441..6786bbc49f 100644
--- a/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs
+++ b/osu.Game/Overlays/Changelog/UpdateStreamBadge.cs
@@ -26,7 +26,6 @@ namespace osu.Game.Overlays.Changelog
private readonly APIUpdateStream stream;
- private Container fadeContainer;
private FillFlowContainer text;
private ExpandingBar expandingBar;
@@ -44,47 +43,39 @@ namespace osu.Game.Overlays.Changelog
AddRange(new Drawable[]
{
- fadeContainer = new Container
+ text = new FillFlowContainer
{
- RelativeSizeAxes = Axes.Both,
- Children = new Drawable[]
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Vertical,
+ Margin = new MarginPadding { Top = 6 },
+ Children = new[]
{
- text = new FillFlowContainer
+ new OsuSpriteText
{
- AutoSizeAxes = Axes.X,
- RelativeSizeAxes = Axes.Y,
- Direction = FillDirection.Vertical,
- Margin = new MarginPadding { Top = 6 },
- Children = new[]
- {
- new OsuSpriteText
- {
- Text = stream.DisplayName,
- Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black),
- },
- new OsuSpriteText
- {
- Text = stream.LatestBuild.DisplayVersion,
- Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular),
- },
- new OsuSpriteText
- {
- Text = stream.LatestBuild.Users > 0 ? $"{"user".ToQuantity(stream.LatestBuild.Users, "N0")} online" : null,
- Font = OsuFont.GetFont(size: 10),
- Colour = colourProvider.Foreground1
- },
- }
+ Text = stream.DisplayName,
+ Font = OsuFont.GetFont(size: 12, weight: FontWeight.Black),
},
- expandingBar = new ExpandingBar
+ new OsuSpriteText
{
- Anchor = Anchor.TopCentre,
- Colour = stream.Colour,
- ExpandedSize = 4,
- CollapsedSize = 2,
- IsCollapsed = true
+ Text = stream.LatestBuild.DisplayVersion,
+ Font = OsuFont.GetFont(size: 16, weight: FontWeight.Regular),
+ },
+ new OsuSpriteText
+ {
+ Text = stream.LatestBuild.Users > 0 ? $"{"user".ToQuantity(stream.LatestBuild.Users, "N0")} online" : null,
+ Font = OsuFont.GetFont(size: 10),
+ Colour = colourProvider.Foreground1
},
}
},
+ expandingBar = new ExpandingBar
+ {
+ Anchor = Anchor.TopCentre,
+ Colour = stream.Colour,
+ ExpandedSize = 4,
+ CollapsedSize = 2,
+ Expanded = true
+ },
new HoverClickSounds()
});
@@ -109,38 +100,41 @@ namespace osu.Game.Overlays.Changelog
private void updateState()
{
- // Expand based on the local state
- bool shouldExpand = Active.Value || IsHovered;
+ // highlighted regardless if we are hovered
+ bool textHighlighted = IsHovered;
+ bool barExpanded = IsHovered;
- // Expand based on whether no build is selected and the badge area is hovered
- shouldExpand |= SelectedTab.Value == null && !externalDimRequested;
-
- if (shouldExpand)
+ if (SelectedTab.Value == null)
{
- expandingBar.Expand();
- fadeContainer.FadeTo(1, transition_duration);
+ // at listing, all badges are highlighted when user is not hovering any badge.
+ textHighlighted |= !userHoveringArea;
+ barExpanded |= !userHoveringArea;
}
else
{
- expandingBar.Collapse();
- fadeContainer.FadeTo(0.5f, transition_duration);
+ // bar is always expanded when active
+ barExpanded |= Active.Value;
+
+ // text is highlighted only when hovered or active (but not if in selection mode)
+ textHighlighted |= Active.Value && !userHoveringArea;
}
- text.FadeTo(externalDimRequested && !IsHovered ? 0.5f : 1, transition_duration);
+ expandingBar.Expanded = barExpanded;
+ text.FadeTo(textHighlighted ? 1 : 0.5f, transition_duration, Easing.OutQuint);
}
- private bool externalDimRequested;
+ private bool userHoveringArea;
- public void EnableDim()
+ public bool UserHoveringArea
{
- externalDimRequested = true;
- updateState();
- }
+ set
+ {
+ if (value == userHoveringArea)
+ return;
- public void DisableDim()
- {
- externalDimRequested = false;
- updateState();
+ userHoveringArea = value;
+ updateState();
+ }
}
}
}
diff --git a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs
index 639c0d9780..ffb622dd37 100644
--- a/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs
+++ b/osu.Game/Overlays/Changelog/UpdateStreamBadgeArea.cs
@@ -6,25 +6,16 @@ using osu.Framework.Input.Events;
using osu.Game.Online.API.Requests.Responses;
using System.Collections.Generic;
using System.Linq;
-using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.UserInterface;
-using osu.Framework.Allocation;
namespace osu.Game.Overlays.Changelog
{
public class UpdateStreamBadgeArea : TabControl
{
- [BackgroundDependencyLoader]
- private void load(OverlayColourProvider colourProvider)
+ public UpdateStreamBadgeArea()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
-
- AddInternal(new Box
- {
- RelativeSizeAxes = Axes.Both,
- Colour = colourProvider.Background5,
- });
}
public void Populate(List