diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 221e4746cb..0000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,8 +0,0 @@ -Add any details pertaining to developers above the break. - -- [ ] Depends on #PR -- Closes #ISSUE - ---- - -Add a sentence or two describing this change in plain english. This will be displayed on the [changelog](https://osu.ppy.sh/home/changelog). A single screenshot or short gif is also welcomed. \ No newline at end of file diff --git a/.gitignore b/.gitignore index f95a04e517..6186cb870d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,9 @@ *.userprefs ### Cake ### -tools/* -!tools/cakebuild.csproj +tools/** +build/tools/** + # Build results bin/[Dd]ebug/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 10c6f02314..c3306c2db7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -68,6 +68,20 @@ } }, "console": "internalConsole" + }, + { + "name": "Cake: Debug Script", + "type": "coreclr", + "request": "launch", + "program": "${workspaceRoot}/build/tools/Cake.CoreCLR/0.30.0/Cake.dll", + "args": [ + "${workspaceRoot}/build/build.cake", + "--debug", + "--verbosity=diagnostic" + ], + "cwd": "${workspaceRoot}/build", + "stopAtEntry": true, + "externalConsole": false } ] } diff --git a/build.ps1 b/build.ps1 index 9968673c90..c6a0bf6d4a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -41,27 +41,28 @@ Param( [switch]$ShowDescription, [Alias("WhatIf", "Noop")] [switch]$DryRun, - [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [Parameter(Position = 0, Mandatory = $false, ValueFromRemainingArguments = $true)] [string[]]$ScriptArgs ) Write-Host "Preparing to run build script..." # Determine the script root for resolving other paths. -if(!$PSScriptRoot){ +if(!$PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } # Resolve the paths for resources used for debugging. -$TOOLS_DIR = Join-Path $PSScriptRoot "tools" -$CAKE_CSPROJ = Join-Path $TOOLS_DIR "cakebuild.csproj" +$BUILD_DIR = Join-Path $PSScriptRoot "build" +$TOOLS_DIR = Join-Path $BUILD_DIR "tools" +$CAKE_CSPROJ = Join-Path $BUILD_DIR "cakebuild.csproj" # Install the required tools locally. Write-Host "Restoring cake tools..." Invoke-Expression "dotnet restore `"$CAKE_CSPROJ`" --packages `"$TOOLS_DIR`"" | Out-Null # Find the Cake executable -$CAKE_EXECUTABLE = (Get-ChildItem -Path ./tools/cake.coreclr/ -Filter Cake.dll -Recurse).FullName +$CAKE_EXECUTABLE = (Get-ChildItem -Path "$TOOLS_DIR/cake.coreclr/" -Filter Cake.dll -Recurse).FullName # Build Cake arguments $cakeArguments = @("$Script"); @@ -75,5 +76,7 @@ $cakeArguments += $ScriptArgs # Start Cake Write-Host "Running build script..." +Push-Location -Path $BUILD_DIR Invoke-Expression "dotnet `"$CAKE_EXECUTABLE`" $cakeArguments" +Pop-Location exit $LASTEXITCODE diff --git a/build.sh b/build.sh index caf1702f41..8f1ef5b455 100755 --- a/build.sh +++ b/build.sh @@ -6,12 +6,13 @@ echo "Preparing to run build script..." +cd build SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) TOOLS_DIR=$SCRIPT_DIR/tools CAKE_BINARY_PATH=$TOOLS_DIR/"cake.coreclr" SCRIPT="build.cake" -CAKE_CSPROJ=$TOOLS_DIR/"cakebuild.csproj" +CAKE_CSPROJ=$SCRIPT_DIR/"cakebuild.csproj" # Parse arguments. CAKE_ARGUMENTS=() diff --git a/build.cake b/build/build.cake similarity index 75% rename from build.cake rename to build/build.cake index bc7dfafb8c..81deeb3bc7 100644 --- a/build.cake +++ b/build/build.cake @@ -1,6 +1,7 @@ #addin "nuget:?package=CodeFileSanity&version=0.0.21" #addin "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.2" #tool "nuget:?package=NVika.MSBuild&version=1.0.1" +var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); /////////////////////////////////////////////////////////////////////////////// // ARGUMENTS @@ -9,30 +10,24 @@ var target = Argument("target", "Build"); var configuration = Argument("configuration", "Release"); -var osuSolution = new FilePath("./osu.sln"); +var rootDirectory = new DirectoryPath(".."); +var solution = rootDirectory.CombineWithFilePath("osu.sln"); /////////////////////////////////////////////////////////////////////////////// // TASKS /////////////////////////////////////////////////////////////////////////////// -Task("Restore") - .Does(() => { - DotNetCoreRestore(osuSolution.FullPath); - }); - Task("Compile") - .IsDependentOn("Restore") .Does(() => { - DotNetCoreBuild(osuSolution.FullPath, new DotNetCoreBuildSettings { + DotNetCoreBuild(solution.FullPath, new DotNetCoreBuildSettings { Configuration = configuration, - NoRestore = true, }); }); Task("Test") .IsDependentOn("Compile") .Does(() => { - var testAssemblies = GetFiles("**/*.Tests/bin/**/*.Tests.dll"); + var testAssemblies = GetFiles(rootDirectory + "/**/*.Tests/bin/**/*.Tests.dll"); DotNetCoreVSTest(testAssemblies, new DotNetCoreVSTestSettings { Logger = AppVeyor.IsRunningOnAppVeyor ? "Appveyor" : $"trx", @@ -46,9 +41,7 @@ Task("InspectCode") .WithCriteria(IsRunningOnWindows()) .IsDependentOn("Compile") .Does(() => { - var nVikaToolPath = GetFiles("./tools/NVika.MSBuild.*/tools/NVika.exe").First(); - - InspectCode(osuSolution, new InspectCodeSettings { + InspectCode(solution, new InspectCodeSettings { CachesHome = "inspectcode", OutputFile = "inspectcodereport.xml", }); @@ -59,7 +52,7 @@ Task("InspectCode") Task("CodeFileSanity") .Does(() => { ValidateCodeSanity(new ValidateCodeSanitySettings { - RootDirectory = ".", + RootDirectory = rootDirectory.FullPath, IsAppveyorBuild = AppVeyor.IsRunningOnAppVeyor }); }); diff --git a/tools/cakebuild.csproj b/build/cakebuild.csproj similarity index 100% rename from tools/cakebuild.csproj rename to build/cakebuild.csproj diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 5b67d528ae..b8a0e337b6 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -60,7 +60,7 @@ namespace osu.Desktop.Overlays { new OsuSpriteText { - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = game.Name }, new OsuSpriteText @@ -74,9 +74,8 @@ namespace osu.Desktop.Overlays { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Colour = colours.Yellow, - Font = @"Venera", Text = @"Development Build" }, new Sprite diff --git a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs index 91bc537902..01c57a6b9a 100644 --- a/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Catch.Tests/CatchDifficultyCalculatorTest.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Catch"; - [TestCase(3.8664391043534758, "diffcalc-test")] + [TestCase(4.2038001515546597d, "diffcalc-test")] public void Test(double expected, string name) => base.Test(expected, name); diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs index c6518cbf8a..75f5b18607 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { @@ -10,10 +9,5 @@ namespace osu.Game.Rulesets.Catch.Difficulty { public double ApproachRate; public int MaxCombo; - - public CatchDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index a0b813478d..2d3d94ea3d 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -1,148 +1,89 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; +using osu.Game.Rulesets.Catch.Difficulty.Skills; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { public class CatchDifficultyCalculator : DifficultyCalculator { - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 750; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.94; - private const double star_scaling_factor = 0.145; + protected override int SectionLength => 750; + + private readonly float halfCatchWidth; + public CatchDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { + var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty); + halfCatchWidth = catcher.CatchWidth * 0.5f; + + // We're only using 80% of the catcher's width to simulate imperfect gameplay. + halfCatchWidth *= 0.8f; } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new CatchDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new CatchDifficultyAttributes { Mods = mods }; - var catcher = new CatcherArea.Catcher(beatmap.BeatmapInfo.BaseDifficulty); - float halfCatchWidth = catcher.CatchWidth * 0.5f; + // this is the same as osu!, so there's potential to share the implementation... maybe + double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; - var difficultyHitObjects = new List(); - - foreach (var hitObject in beatmap.HitObjects) + return new CatchDifficultyAttributes { + StarRating = Math.Sqrt(skills[0].DifficultyValue()) * star_scaling_factor, + Mods = mods, + ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, + MaxCombo = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)) + }; + } + + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + CatchHitObject lastObject = null; + + foreach (var hitObject in beatmap.HitObjects.OfType()) + { + if (lastObject == null) + { + lastObject = hitObject; + continue; + } + switch (hitObject) { // We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations. case Fruit fruit: - difficultyHitObjects.Add(new CatchDifficultyHitObject(fruit, halfCatchWidth)); + yield return new CatchDifficultyHitObject(fruit, lastObject, clockRate, halfCatchWidth); + lastObject = hitObject; break; case JuiceStream _: - difficultyHitObjects.AddRange(hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet)).Select(o => new CatchDifficultyHitObject(o, halfCatchWidth))); + foreach (var nested in hitObject.NestedHitObjects.OfType().Where(o => !(o is TinyDroplet))) + { + yield return new CatchDifficultyHitObject(nested, lastObject, clockRate, halfCatchWidth); + lastObject = nested; + } break; } } - - difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new CatchDifficultyAttributes(mods, 0); - - // this is the same as osu!, so there's potential to share the implementation... maybe - double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; - double starRating = Math.Sqrt(calculateDifficulty(difficultyHitObjects, timeRate)) * star_scaling_factor; - - return new CatchDifficultyAttributes(mods, starRating) - { - ApproachRate = preempt > 1200.0 ? -(preempt - 1800.0) / 120.0 : -(preempt - 1200.0) / 150.0 + 5.0, - MaxCombo = difficultyHitObjects.Count - }; } - private bool calculateStrainValues(List objects, double timeRate) + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] { - CatchDifficultyHitObject lastObject = null; - - if (!objects.Any()) return false; - - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - foreach (var currentObject in objects) - { - if (lastObject != null) - currentObject.CalculateStrains(lastObject, timeRate); - - lastObject = currentObject; - } - - return true; - } - - private double calculateDifficulty(List objects, double timeRate) - { - // The strain step needs to be adjusted for the algorithm to be considered equal with speed changing mods - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - var highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - CatchDifficultyHitObject previousHitObject = null; - foreach (CatchDifficultyHitObject hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double decay = Math.Pow(CatchDifficultyHitObject.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.Strain * decay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - maximumStrain = Math.Max(hitObject.Strain, maximumStrain); - - previousHitObject = hitObject; - } - - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= decay_weight; - } - - return difficulty; - } + new Movement(), + }; } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs deleted file mode 100644 index fb16e117b1..0000000000 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyHitObject.cs +++ /dev/null @@ -1,130 +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 System; -using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Catch.UI; -using osuTK; - -namespace osu.Game.Rulesets.Catch.Difficulty -{ - public class CatchDifficultyHitObject - { - internal static readonly double DECAY_BASE = 0.20; - private const float normalized_hitobject_radius = 41.0f; - private const float absolute_player_positioning_error = 16f; - private readonly float playerPositioningError; - - internal CatchHitObject BaseHitObject; - - /// - /// Measures jump difficulty. CtB doesn't have something like button pressing speed or accuracy - /// - internal double Strain = 1; - - /// - /// This is required to keep track of lazy player movement (always moving only as far as necessary) - /// Without this quick repeat sliders / weirdly shaped streams might become ridiculously overrated - /// - internal float PlayerPositionOffset; - internal float LastMovement; - - internal float NormalizedPosition; - internal float ActualNormalizedPosition => NormalizedPosition + PlayerPositionOffset; - - internal CatchDifficultyHitObject(CatchHitObject baseHitObject, float catcherWidthHalf) - { - BaseHitObject = baseHitObject; - - // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. - float scalingFactor = normalized_hitobject_radius / catcherWidthHalf; - - playerPositioningError = absolute_player_positioning_error; // * scalingFactor; - NormalizedPosition = baseHitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; - } - - private const double direction_change_bonus = 12.5; - internal void CalculateStrains(CatchDifficultyHitObject previousHitObject, double timeRate) - { - // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. - // See Taiko feedback thread. - double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); - - // Update new position with lazy movement. - PlayerPositionOffset = - MathHelper.Clamp( - previousHitObject.ActualNormalizedPosition, - NormalizedPosition - (normalized_hitobject_radius - playerPositioningError), - NormalizedPosition + (normalized_hitobject_radius - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. - - NormalizedPosition; // Subtract HitObject position to obtain offset - - LastMovement = DistanceTo(previousHitObject); - double addition = spacingWeight(LastMovement); - - if (NormalizedPosition < previousHitObject.NormalizedPosition) - { - LastMovement = -LastMovement; - } - - CatchHitObject previousHitCircle = previousHitObject.BaseHitObject; - - double additionBonus = 0; - double sqrtTime = Math.Sqrt(Math.Max(timeElapsed, 25)); - - // Direction changes give an extra point! - if (Math.Abs(LastMovement) > 0.1) - { - if (Math.Abs(previousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(previousHitObject.LastMovement)) - { - double bonus = direction_change_bonus / sqrtTime; - - // Weight bonus by how - double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; - - // We want time to play a role twice here! - addition += bonus * bonusFactor; - - // Bonus for tougher direction switches and "almost" hyperdashes at this point - if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) - { - additionBonus += 0.3 * bonusFactor; - } - } - - // Base bonus for every movement, giving some weight to streams. - addition += 7.5 * Math.Min(Math.Abs(LastMovement), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtTime; - } - - // Bonus for "almost" hyperdashes at corner points - if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) - { - if (!previousHitCircle.HyperDash) - { - additionBonus += 1.0; - } - else - { - // After a hyperdash we ARE in the correct position. Always! - PlayerPositionOffset = 0; - } - - addition *= 1.0 + additionBonus * ((10 - previousHitCircle.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); - } - - addition *= 850.0 / Math.Max(timeElapsed, 25); - - Strain = previousHitObject.Strain * decay + addition; - } - - private static double spacingWeight(float distance) - { - return Math.Pow(distance, 1.3) / 500; - } - - internal float DistanceTo(CatchDifficultyHitObject other) - { - return Math.Abs(ActualNormalizedPosition - other.ActualNormalizedPosition); - } - } -} diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs new file mode 100644 index 0000000000..24e526ed19 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.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 System; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing +{ + public class CatchDifficultyHitObject : DifficultyHitObject + { + private const float normalized_hitobject_radius = 41.0f; + + public new CatchHitObject BaseObject => (CatchHitObject)base.BaseObject; + + public new CatchHitObject LastObject => (CatchHitObject)base.LastObject; + + public readonly float NormalizedPosition; + public readonly float LastNormalizedPosition; + + /// + /// Milliseconds elapsed since the start time of the previous , with a minimum of 25ms. + /// + public readonly double StrainTime; + + public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth) + : base(hitObject, lastObject, clockRate) + { + // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. + var scalingFactor = normalized_hitobject_radius / halfCatcherWidth; + + NormalizedPosition = BaseObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; + LastNormalizedPosition = LastObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; + + // Every strain interval is hard capped at the equivalent of 600 BPM streaming speed as a safety measure + StrainTime = Math.Max(25, DeltaTime); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs new file mode 100644 index 0000000000..d146153294 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -0,0 +1,85 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osuTK; + +namespace osu.Game.Rulesets.Catch.Difficulty.Skills +{ + public class Movement : Skill + { + private const float absolute_player_positioning_error = 16f; + private const float normalized_hitobject_radius = 41.0f; + private const double direction_change_bonus = 12.5; + + protected override double SkillMultiplier => 850; + protected override double StrainDecayBase => 0.2; + + protected override double DecayWeight => 0.94; + + private float? lastPlayerPosition; + private float lastDistanceMoved; + + protected override double StrainValueOf(DifficultyHitObject current) + { + var catchCurrent = (CatchDifficultyHitObject)current; + + if (lastPlayerPosition == null) + lastPlayerPosition = catchCurrent.LastNormalizedPosition; + + float playerPosition = MathHelper.Clamp( + lastPlayerPosition.Value, + catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), + catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) + ); + + float distanceMoved = playerPosition - lastPlayerPosition.Value; + + double distanceAddition = Math.Pow(Math.Abs(distanceMoved), 1.3) / 500; + double sqrtStrain = Math.Sqrt(catchCurrent.StrainTime); + + double bonus = 0; + + // Direction changes give an extra point! + if (Math.Abs(distanceMoved) > 0.1) + { + if (Math.Abs(lastDistanceMoved) > 0.1 && Math.Sign(distanceMoved) != Math.Sign(lastDistanceMoved)) + { + double bonusFactor = Math.Min(absolute_player_positioning_error, Math.Abs(distanceMoved)) / absolute_player_positioning_error; + + distanceAddition += direction_change_bonus / sqrtStrain * bonusFactor; + + // Bonus for tougher direction switches and "almost" hyperdashes at this point + if (catchCurrent.LastObject.DistanceToHyperDash <= 10 / CatchPlayfield.BASE_WIDTH) + bonus = 0.3 * bonusFactor; + } + + // Base bonus for every movement, giving some weight to streams. + distanceAddition += 7.5 * Math.Min(Math.Abs(distanceMoved), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtStrain; + } + + // Bonus for "almost" hyperdashes at corner points + if (catchCurrent.LastObject.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) + { + if (!catchCurrent.LastObject.HyperDash) + bonus += 1.0; + else + { + // After a hyperdash we ARE in the correct position. Always! + playerPosition = catchCurrent.NormalizedPosition; + } + + distanceAddition *= 1.0 + bonus * ((10 - catchCurrent.LastObject.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); + } + + lastPlayerPosition = playerPosition; + lastDistanceMoved = distanceMoved; + + return distanceAddition / catchCurrent.StrainTime; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs index 4f5d7abfd4..82cda7df47 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.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.Graphics; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; @@ -55,9 +56,9 @@ namespace osu.Game.Rulesets.Catch.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index d79f106310..438bfaef55 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.UI { public class CatcherArea : Container { - public const float CATCHER_SIZE = 100; + public const float CATCHER_SIZE = 106.75f; protected internal readonly Catcher MovableCatcher; diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs index 05e2df796c..2c36e81190 100644 --- a/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Mania.Tests/ManiaDifficultyCalculatorTest.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Mania"; - [TestCase(2.2676066895468976, "diffcalc-test")] + [TestCase(2.3683365342338796d, "diffcalc-test")] public void Test(double expected, string name) => base.Test(expected, name); diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs index 32f455bb73..78e7768788 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs @@ -3,7 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 2f4b51e372..0bc2c3ea28 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,6 +14,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -141,7 +142,7 @@ namespace osu.Game.Rulesets.Mania.Tests { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = description } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs index 2f614ea14b..3ff665d2c8 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -2,17 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty { public class ManiaDifficultyAttributes : DifficultyAttributes { public double GreatHitWindow; - - public ManiaDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index b8588dbce2..59fed1031f 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -1,34 +1,24 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.Mods; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty { - internal class ManiaDifficultyCalculator : DifficultyCalculator + public class ManiaDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.018; - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size strain_step. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 400; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.9; - private readonly bool isForCurrentRuleset; public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) @@ -37,108 +27,70 @@ namespace osu.Game.Rulesets.Mania.Difficulty isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo); } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new ManiaDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new ManiaDifficultyAttributes { Mods = mods }; - var difficultyHitObjects = new List(); - - int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; - - // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. - // Note: Stable sort is done so that the ordering of hitobjects with equal start times doesn't change - difficultyHitObjects.AddRange(beatmap.HitObjects.Select(h => new ManiaHitObjectDifficulty((ManiaHitObject)h, columnCount)).OrderBy(h => h.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new ManiaDifficultyAttributes(mods, 0); - - double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - - return new ManiaDifficultyAttributes(mods, starRating) + return new ManiaDifficultyAttributes { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate + StarRating = difficultyValue(skills) * star_scaling_factor, + Mods = mods, + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, }; } - private bool calculateStrainValues(List objects, double timeRate) + private double difficultyValue(Skill[] skills) { - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (var hitObjectsEnumerator = objects.GetEnumerator()) + // Preprocess the strains to find the maximum overall + individual (aggregate) strain from each section + var overall = skills.OfType().Single(); + var aggregatePeaks = new List(Enumerable.Repeat(0.0, overall.StrainPeaks.Count)); + + foreach (var individual in skills.OfType()) { - if (!hitObjectsEnumerator.MoveNext()) - return false; - - ManiaHitObjectDifficulty current = hitObjectsEnumerator.Current; - - // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. - while (hitObjectsEnumerator.MoveNext()) + for (int i = 0; i < individual.StrainPeaks.Count; i++) { - var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, timeRate); - current = next; + double aggregate = individual.StrainPeaks[i] + overall.StrainPeaks[i]; + + if (aggregate > aggregatePeaks[i]) + aggregatePeaks[i] = aggregate; } - - return true; - } - } - - private double calculateDifficulty(List objects, double timeRate) - { - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - List highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - ManiaHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double individualDecay = Math.Pow(ManiaHitObjectDifficulty.INDIVIDUAL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - double overallDecay = Math.Pow(ManiaHitObjectDifficulty.OVERALL_DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.IndividualStrain * individualDecay + previousHitObject.OverallStrain * overallDecay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - double strain = hitObject.IndividualStrain + hitObject.OverallStrain; - maximumStrain = Math.Max(strain, maximumStrain); - - previousHitObject = hitObject; } - // Build the weighted sum over the highest strains for each interval + aggregatePeaks.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. + double difficulty = 0; double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - foreach (double strain in highestStrains) + // Difficulty is the weighted sum of the highest strains from every section. + foreach (double strain in aggregatePeaks) { - difficulty += weight * strain; - weight *= decay_weight; + difficulty += strain * weight; + weight *= 0.9; } return difficulty; } + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + for (int i = 1; i < beatmap.HitObjects.Count; i++) + yield return new ManiaDifficultyHitObject(beatmap.HitObjects[i], beatmap.HitObjects[i - 1], clockRate); + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) + { + int columnCount = ((ManiaBeatmap)beatmap).TotalColumns; + + var skills = new List { new Overall(columnCount) }; + + for (int i = 0; i < columnCount; i++) + skills.Add(new Individual(i, columnCount)); + + return skills.ToArray(); + } + protected override Mod[] DifficultyAdjustmentMods { get diff --git a/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.cs new file mode 100644 index 0000000000..29ba934e9f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Preprocessing/ManiaDifficultyHitObject.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.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Preprocessing +{ + public class ManiaDifficultyHitObject : DifficultyHitObject + { + public new ManiaHitObject BaseObject => (ManiaHitObject)base.BaseObject; + + public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs new file mode 100644 index 0000000000..059cd39641 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Individual.cs @@ -0,0 +1,47 @@ +// 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.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Skills +{ + public class Individual : Skill + { + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.125; + + private readonly double[] holdEndTimes; + + private readonly int column; + + public Individual(int column, int columnCount) + { + this.column = column; + + holdEndTimes = new double[columnCount]; + } + + protected override double StrainValueOf(DifficultyHitObject current) + { + var maniaCurrent = (ManiaDifficultyHitObject)current; + var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + + try + { + if (maniaCurrent.BaseObject.Column != column) + return 0; + + // We give a slight bonus if something is held meanwhile + return holdEndTimes.Any(t => t > endTime) ? 2.5 : 2; + } + finally + { + holdEndTimes[maniaCurrent.BaseObject.Column] = endTime; + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs new file mode 100644 index 0000000000..ed25173d38 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Overall.cs @@ -0,0 +1,56 @@ +// 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.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; +using osu.Game.Rulesets.Mania.Objects; + +namespace osu.Game.Rulesets.Mania.Difficulty.Skills +{ + public class Overall : Skill + { + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.3; + + private readonly double[] holdEndTimes; + + private readonly int columnCount; + + public Overall(int columnCount) + { + this.columnCount = columnCount; + + holdEndTimes = new double[columnCount]; + } + + protected override double StrainValueOf(DifficultyHitObject current) + { + var maniaCurrent = (ManiaDifficultyHitObject)current; + var endTime = (maniaCurrent.BaseObject as HoldNote)?.EndTime ?? maniaCurrent.BaseObject.StartTime; + + double holdFactor = 1.0; // Factor in case something else is held + double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly + + for (int i = 0; i < columnCount; i++) + { + // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... + if (current.BaseObject.StartTime < holdEndTimes[i] && endTime > holdEndTimes[i]) + holdAddition = 1.0; + + // ... this addition only is valid if there is _no_ other note with the same ending. + // Releasing multiple notes at the same time is just as easy as releasing one + if (endTime == holdEndTimes[i]) + holdAddition = 0; + + // We give a slight bonus if something is held meanwhile + if (holdEndTimes[i] > endTime) + holdFactor = 1.25; + } + + holdEndTimes[maniaCurrent.BaseObject.Column] = endTime; + + return (1 + holdAddition) * holdFactor; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs index 9bf14b0672..d64c5dbc6a 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/HoldNoteSelectionBlueprint.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 57728dd134..ba87fe6ed9 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -330,12 +330,12 @@ namespace osu.Game.Rulesets.Mania for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++) bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++)); - for (int i = 0; i < columns / 2; i++) - bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); - if (columns % 2 == 1) bindings.Add(new KeyBinding(SpecialKey, SpecialAction)); + for (int i = 0; i < columns / 2; i++) + bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); + nextNormalAction = currentNormalAction; return bindings; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs index baa757008f..6893e1e73b 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects; @@ -51,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Mods } } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 8b2da60a9e..777c0ae566 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; @@ -75,11 +76,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables AddNested(Tail); } - protected override void OnDirectionChanged(ScrollingDirection direction) + protected override void OnDirectionChanged(ValueChangedEvent e) { - base.OnDirectionChanged(direction); + base.OnDirectionChanged(e); - bodyPiece.Anchor = bodyPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index bc34648dd8..a78524011f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -3,7 +3,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; @@ -41,9 +41,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override bool ShouldBeAlive => AlwaysAlive || base.ShouldBeAlive; - protected virtual void OnDirectionChanged(ScrollingDirection direction) + protected virtual void OnDirectionChanged(ValueChangedEvent e) { - Anchor = Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 7ed8e89f95..c80681ea23 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.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.Extensions.Color4Extensions; using osuTK.Graphics; using osu.Framework.Graphics; @@ -31,11 +32,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables InternalChild = headPiece = new NotePiece(); } - protected override void OnDirectionChanged(ScrollingDirection direction) + protected override void OnDirectionChanged(ValueChangedEvent e) { - base.OnDirectionChanged(direction); + base.OnDirectionChanged(e); - headPiece.Anchor = headPiece.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + headPiece.Anchor = headPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 65a376a3a8..c5db6d7bd9 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -49,9 +49,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces private void load(IScrollingInfo scrollingInfo) { direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - colouredBox.Anchor = colouredBox.Origin = direction == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; + colouredBox.Anchor = colouredBox.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; }, true); } diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 5765817b63..70720a926b 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects public virtual int Column { - get => ColumnBindable; + get => ColumnBindable.Value; set => ColumnBindable.Value = value; } diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs deleted file mode 100644 index b6ea8c8665..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObjectDifficulty.cs +++ /dev/null @@ -1,112 +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.Game.Rulesets.Objects.Types; -using System; - -namespace osu.Game.Rulesets.Mania.Objects -{ - internal class ManiaHitObjectDifficulty - { - /// - /// Factor by how much individual / overall strain decays per second. - /// - /// - /// These values are results of tweaking a lot and taking into account general feedback. - /// - internal const double INDIVIDUAL_DECAY_BASE = 0.125; - internal const double OVERALL_DECAY_BASE = 0.30; - - internal ManiaHitObject BaseHitObject; - - private readonly int beatmapColumnCount; - - private readonly double endTime; - private readonly double[] heldUntil; - - /// - /// Measures jacks or more generally: repeated presses of the same button - /// - private readonly double[] individualStrains; - - internal double IndividualStrain - { - get - { - return individualStrains[BaseHitObject.Column]; - } - - set - { - individualStrains[BaseHitObject.Column] = value; - } - } - - /// - /// Measures note density in a way - /// - internal double OverallStrain = 1; - - public ManiaHitObjectDifficulty(ManiaHitObject baseHitObject, int columnCount) - { - BaseHitObject = baseHitObject; - - endTime = (baseHitObject as IHasEndTime)?.EndTime ?? baseHitObject.StartTime; - - beatmapColumnCount = columnCount; - heldUntil = new double[beatmapColumnCount]; - individualStrains = new double[beatmapColumnCount]; - - for (int i = 0; i < beatmapColumnCount; ++i) - { - individualStrains[i] = 0; - heldUntil[i] = 0; - } - } - - internal void CalculateStrains(ManiaHitObjectDifficulty previousHitObject, double timeRate) - { - // TODO: Factor in holds - double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double individualDecay = Math.Pow(INDIVIDUAL_DECAY_BASE, timeElapsed / 1000); - double overallDecay = Math.Pow(OVERALL_DECAY_BASE, timeElapsed / 1000); - - double holdFactor = 1.0; // Factor to all additional strains in case something else is held - double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly - - // Fill up the heldUntil array - for (int i = 0; i < beatmapColumnCount; ++i) - { - heldUntil[i] = previousHitObject.heldUntil[i]; - - // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... - if (BaseHitObject.StartTime < heldUntil[i] && endTime > heldUntil[i]) - { - holdAddition = 1.0; - } - - // ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1 - if (endTime == heldUntil[i]) - { - holdAddition = 0; - } - - // We give a slight bonus to everything if something is held meanwhile - if (heldUntil[i] > endTime) - { - holdFactor = 1.25; - } - - // Decay individual strains - individualStrains[i] = previousHitObject.individualStrains[i] * individualDecay; - } - - heldUntil[BaseHitObject.Column] = endTime; - - // Increase individual strain in own column - IndividualStrain += 2.0 * holdFactor; - - OverallStrain = previousHitObject.OverallStrain * overallDecay + (1.0 + holdAddition) * holdFactor; - } - } -} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 3e7884af6c..856ae8af33 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.UI.Components; @@ -82,15 +82,15 @@ namespace osu.Game.Rulesets.Mania.UI TopLevelContainer.Add(explosionContainer.CreateProxy()); - Direction.BindValueChanged(d => + Direction.BindValueChanged(dir => { hitTargetContainer.Padding = new MarginPadding { - Top = d == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, - Bottom = d == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, + Top = dir.NewValue == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - keyArea.Anchor = keyArea.Origin= d == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements) + if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value) return; explosionContainer.Add(new HitExplosion(judgedObject) @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Mania.UI public bool OnPressed(ManiaAction action) { - if (action != Action) + if (action != Action.Value) return false; var nextObject = diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index b7f291b5a2..b43580e0f3 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -48,9 +48,9 @@ namespace osu.Game.Rulesets.Mania.UI.Components }; direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - backgroundOverlay.Anchor = backgroundOverlay.Origin = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + backgroundOverlay.Anchor = backgroundOverlay.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; updateColours(); }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index 7f5687e600..cd47bb1183 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -49,9 +49,9 @@ namespace osu.Game.Rulesets.Mania.UI.Components private void load(IScrollingInfo scrollingInfo) { direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { - Anchor anchor = direction == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; + Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; hitTargetBar.Anchor = hitTargetBar.Origin = anchor; hitTargetLine.Anchor = hitTargetLine.Origin = anchor; diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs index a180ffbd3b..b7d8945808 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnKeyArea.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -64,11 +64,11 @@ namespace osu.Game.Rulesets.Mania.UI.Components }; direction.BindTo(scrollingInfo.Direction); - direction.BindValueChanged(direction => + direction.BindValueChanged(dir => { gradient.Colour = ColourInfo.GradientVertical( - direction == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), - direction == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); + dir.NewValue == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0), + dir.NewValue == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black); }, true); } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 1469924bb2..5874bac7f6 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.UI private void load() { if (JudgementText != null) - JudgementText.TextSize = 25; + JudgementText.Font = JudgementText.Font.With(size: 25); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 892ad584dc..b451e28088 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); Config.BindWith(ManiaSetting.ScrollDirection, configDirection); - configDirection.BindValueChanged(v => Direction.Value = (ScrollingDirection)v, true); + configDirection.BindValueChanged(direction => Direction.Value = (ScrollingDirection)direction.NewValue, true); Config.BindWith(ManiaSetting.ScrollTime, TimeRange); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index bce333ff34..a28de7ea58 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -136,12 +136,12 @@ namespace osu.Game.Rulesets.Mania.UI AddColumn(column); } - Direction.BindValueChanged(d => + Direction.BindValueChanged(dir => { barLineContainer.Padding = new MarginPadding { - Top = d == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, - Bottom = d == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, + Top = dir.NewValue == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0, }; }, true); } @@ -185,7 +185,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayResult || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements.Value) return; judgements.Clear(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index d6b88c1c5f..1aabf9a904 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -16,6 +16,7 @@ using osuTK.Graphics; using osu.Game.Rulesets.Mods; using System.Linq; using NUnit.Framework; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -313,7 +314,7 @@ namespace osu.Game.Rulesets.Osu.Tests Origin = Anchor.Centre, Text = result.IsHit ? "Hit!" : "Miss!", Colour = result.IsHit ? Color4.Green : Color4.Red, - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) }); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs new file mode 100644 index 0000000000..57effe01f1 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSliderInput.cs @@ -0,0 +1,372 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using osu.Framework.Screens; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Replays; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseSliderInput : RateAdjustedBeatmapTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SliderBall), + typeof(DrawableSlider), + typeof(DrawableSliderTick), + typeof(DrawableRepeatPoint), + typeof(DrawableOsuHitObject), + typeof(DrawableSliderHead), + typeof(DrawableSliderTail), + }; + + private const double time_before_slider = 250; + private const double time_slider_start = 1500; + private const double time_during_slide_1 = 2500; + private const double time_during_slide_2 = 3000; + private const double time_during_slide_3 = 3500; + private const double time_during_slide_4 = 3800; + + private List judgementResults; + private bool allJudgedFired; + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the latter pressed key + /// Expected Result: + /// A passing test case will have the cursor lose tracking on replay frame 3. + /// + [Test] + public void TestInvalidKeyTransfer() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the original key used to hit the slider + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestLeftBeforeSliderThenRightThenLettingGoOfLeft() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key on the slider head timed correctly + /// - Press the other key in the middle of the slider while holding the original key + /// - Release the new key that was pressed second + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3. + /// + [Test] + public void TestTrackingRetentionLeftRightLeft() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key that was held down before the slider started. + /// Expected Result: + /// A passing test case will have the cursor continue tracking on replay frame 3 + /// + [Test] + public void TestTrackingLeftBeforeSliderToRight() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + }); + + AddAssert("Tracking retained", assertGreatJudge); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down throughout the slider without pressing any other buttons. + /// Expected Result: + /// A passing test case will have the cursor track the slider, but miss the slider head. + /// + [Test] + public void TestTrackingPreclicked() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + }); + + AddAssert("Tracking retained, sliderhead miss", assertHeadMissTailTracked); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Hold the key down after the slider starts + /// - Move the cursor away from the slider body + /// - Move the cursor back onto the body + /// Expected Result: + /// A passing test case will have the cursor track the slider, miss the head, miss the ticks where its outside of the body, and resume tracking when the cursor returns. + /// + [Test] + public void TestTrackingReturnMidSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking re-acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key before a slider starts + /// - Press the other key on the slider head timed correctly while holding the original key + /// - Release the key used to hit the slider head + /// - While holding the first key, move the cursor away from the slider body + /// - Still holding the first key, move the cursor back to the slider body + /// Expected Result: + /// A passing test case will have the slider not track despite having the cursor return to the slider body. + /// + [Test] + public void TestTrackingReturnMidSliderKeyDownBefore() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking lost", assertMidSliderJudgementFail); + } + + /// + /// Scenario: + /// - Wait for the slider to reach a mid-point + /// - Press a key away from the slider body + /// - While holding down the key, move into the slider body + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestTrackingMidSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(150, 150), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(200, 200), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key before the slider starts + /// - Press another key on the slider head while holding the original key + /// - Move out of the slider body while releasing the two pressed keys + /// - Move back into the slider body while pressing any key. + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestMidSliderTrackingAcquired() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + [Test] + public void TestMidSliderTrackingAcquiredWithMouseDownOutsideSlider() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_before_slider }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton, OsuAction.RightButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.RightButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.RightButton }, Time = time_during_slide_2 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + /// + /// Scenario: + /// - Press a key on the slider head + /// - While holding the key, move outside of the slider body with the cursor + /// - Release the key while outside of the slider body + /// - Press the key again while outside of the slider body + /// - Move back into the slider body while holding the pressed key + /// Expected Result: + /// A passing test case will have the slider track the cursor after the cursor enters the slider body. + /// + [Test] + public void TestTrackingReleasedValidKey() + { + performTest(new List + { + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_slider_start }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_1 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Time = time_during_slide_2 }, + new OsuReplayFrame { Position = new Vector2(100, 100), Actions = { OsuAction.LeftButton }, Time = time_during_slide_3 }, + new OsuReplayFrame { Position = new Vector2(0, 0), Actions = { OsuAction.LeftButton }, Time = time_during_slide_4 }, + }); + + AddAssert("Tracking acquired", assertMidSliderJudgements); + } + + private bool assertGreatJudge() => judgementResults.Last().Type == HitResult.Great; + + private bool assertHeadMissTailTracked() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great && judgementResults.First().Type == HitResult.Miss; + + private bool assertMidSliderJudgements() => judgementResults[judgementResults.Count - 2].Type == HitResult.Great; + + private bool assertMidSliderJudgementFail() => judgementResults[judgementResults.Count - 2].Type == HitResult.Miss; + + private ScoreAccessibleReplayPlayer currentPlayer; + + private void performTest(List frames) + { + // Empty frame to be added as a workaround for first frame behavior. + // If an input exists on the first frame, the input would apply to the entire intro lead-in + // Likely requires some discussion regarding how first frame inputs should be handled. + frames.Insert(0, new OsuReplayFrame()); + + AddStep("load player", () => + { + Beatmap.Value = new TestWorkingBeatmap(new Beatmap + { + HitObjects = + { + new Slider + { + StartTime = time_slider_start, + Position = new Vector2(0, 0), + Path = new SliderPath(PathType.PerfectCurve, new[] + { + Vector2.Zero, + new Vector2(25, 0), + }, 25), + } + }, + ControlPointInfo = + { + DifficultyPoints = { new DifficultyControlPoint { SpeedMultiplier = 0.1f } } + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 }, + Ruleset = new OsuRuleset().RulesetInfo + }, + }, Clock); + + var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }) + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false + }; + + p.OnLoadComplete += _ => + { + p.ScoreProcessor.NewJudgement += result => + { + if (currentPlayer == p) judgementResults.Add(result); + }; + p.ScoreProcessor.AllJudged += () => + { + if (currentPlayer == p) allJudgedFired = true; + }; + }; + + LoadScreen(currentPlayer = p); + allJudgedFired = false; + judgementResults = new List(); + }); + + AddUntilStep(() => Beatmap.Value.Track.CurrentTime == 0, "Beatmap at 0"); + AddUntilStep(() => currentPlayer.IsCurrentScreen(), "Wait until player is loaded"); + AddUntilStep(() => allJudgedFired, "Wait for all judged"); + } + + private class ScoreAccessibleReplayPlayer : ReplayPlayer + { + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public ScoreAccessibleReplayPlayer(Score score) + : base(score) + { + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index fd54dc0260..6e991a1d08 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Difficulty { @@ -13,10 +12,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty public double ApproachRate; public double OverallDifficulty; public int MaxCombo; - - public OsuDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 3d0a1dc266..e2a1542574 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -1,10 +1,13 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; @@ -15,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty { public class OsuDifficultyCalculator : DifficultyCalculator { - private const int section_length = 400; private const double difficulty_multiplier = 0.0675; public OsuDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) @@ -23,58 +25,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty { } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new OsuDifficultyAttributes(mods, 0); - - OsuDifficultyBeatmap difficultyBeatmap = new OsuDifficultyBeatmap(beatmap.HitObjects.Cast().ToList(), timeRate); - Skill[] skills = - { - new Aim(), - new Speed() - }; - - double sectionLength = section_length * timeRate; - - // The first object doesn't generate a strain, so we begin with an incremented section end - double currentSectionEnd = Math.Ceiling(beatmap.HitObjects.First().StartTime / sectionLength) * sectionLength; - - foreach (OsuDifficultyHitObject h in difficultyBeatmap) - { - while (h.BaseObject.StartTime > currentSectionEnd) - { - foreach (Skill s in skills) - { - s.SaveCurrentPeak(); - s.StartNewSectionFrom(currentSectionEnd); - } - - currentSectionEnd += sectionLength; - } - - foreach (Skill s in skills) - s.Process(h); - } - - // The peak strain will not be saved for the last section in the above loop - foreach (Skill s in skills) - s.SaveCurrentPeak(); + if (beatmap.HitObjects.Count == 0) + return new OsuDifficultyAttributes { Mods = mods }; double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; // Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future - double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate; - double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / timeRate; + double hitWindowGreat = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate; + double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; int maxCombo = beatmap.HitObjects.Count; // Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above) maxCombo += beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); - return new OsuDifficultyAttributes(mods, starRating) + return new OsuDifficultyAttributes { + StarRating = starRating, + Mods = mods, AimStrain = aimRating, SpeedStrain = speedRating, ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5, @@ -83,6 +54,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty }; } + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + // The first jump is formed by the first two hitobjects of the map. + // If the map has less than two OsuHitObjects, the enumerator will not return anything. + for (int i = 1; i < beatmap.HitObjects.Count; i++) + { + var lastLast = i > 1 ? beatmap.HitObjects[i - 2] : null; + var last = beatmap.HitObjects[i - 1]; + var current = beatmap.HitObjects[i]; + + yield return new OsuDifficultyHitObject(current, lastLast, last, clockRate); + } + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] + { + new Aim(), + new Speed() + }; + protected override Mod[] DifficultyAdjustmentMods => new Mod[] { new OsuModDoubleTime(), diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs deleted file mode 100644 index 068564d50c..0000000000 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyBeatmap.cs +++ /dev/null @@ -1,50 +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 System.Collections; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Osu.Objects; - -namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing -{ - /// - /// An enumerable container wrapping input as - /// which contains extra data required for difficulty calculation. - /// - public class OsuDifficultyBeatmap : IEnumerable - { - private readonly IEnumerator difficultyObjects; - - /// - /// Creates an enumerator, which preprocesses a list of s recieved as input, wrapping them as - /// which contains extra data required for difficulty calculation. - /// - public OsuDifficultyBeatmap(List objects, double timeRate) - { - // Sort OsuHitObjects by StartTime - they are not correctly ordered in some cases. - // This should probably happen before the objects reach the difficulty calculator. - difficultyObjects = createDifficultyObjectEnumerator(objects.OrderBy(h => h.StartTime).ToList(), timeRate); - } - - /// - /// Returns an enumerator that enumerates all s in the . - /// - public IEnumerator GetEnumerator() => difficultyObjects; - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - private IEnumerator createDifficultyObjectEnumerator(List objects, double timeRate) - { - // The first jump is formed by the first two hitobjects of the map. - // If the map has less than two OsuHitObjects, the enumerator will not return anything. - for (int i = 1; i < objects.Count; i++) - { - var lastLast = i > 1 ? objects[i - 2] : null; - var last = objects[i - 1]; - var current = objects[i]; - - yield return new OsuDifficultyHitObject(lastLast, last, current, timeRate); - } - } - } -} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs index 1ec12adb3b..930c711783 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -1,24 +1,20 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Linq; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osuTK; namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing { - /// - /// A wrapper around extending it with additional data required for difficulty calculation. - /// - public class OsuDifficultyHitObject + public class OsuDifficultyHitObject : DifficultyHitObject { private const int normalized_radius = 52; - /// - /// The this refers to. - /// - public OsuHitObject BaseObject { get; } + protected new OsuHitObject BaseObject => (OsuHitObject)base.BaseObject; /// /// Normalized distance from the end position of the previous to the start position of this . @@ -30,40 +26,30 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing /// public double TravelDistance { get; private set; } - /// - /// Milliseconds elapsed since the StartTime of the previous . - /// - public double DeltaTime { get; private set; } - - /// - /// Milliseconds elapsed since the start time of the previous , with a minimum of 50ms. - /// - public double StrainTime { get; private set; } - /// /// Angle the player has to take to hit this . /// Calculated as the angle between the circles (current-2, current-1, current). /// public double? Angle { get; private set; } + /// + /// Milliseconds elapsed since the start time of the previous , with a minimum of 50ms. + /// + public readonly double StrainTime; + private readonly OsuHitObject lastLastObject; private readonly OsuHitObject lastObject; - private readonly double timeRate; - /// - /// Initializes the object calculating extra data required for difficulty calculation. - /// - public OsuDifficultyHitObject(OsuHitObject lastLastObject, OsuHitObject lastObject, OsuHitObject currentObject, double timeRate) + public OsuDifficultyHitObject(HitObject hitObject, HitObject lastLastObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) { - this.lastLastObject = lastLastObject; - this.lastObject = lastObject; - this.timeRate = timeRate; - - BaseObject = currentObject; + this.lastLastObject = (OsuHitObject)lastLastObject; + this.lastObject = (OsuHitObject)lastObject; setDistances(); - setTimingValues(); - // Calculate angle here + + // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure + StrainTime = Math.Max(50, DeltaTime); } private void setDistances() @@ -102,14 +88,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing } } - private void setTimingValues() - { - DeltaTime = (BaseObject.StartTime - lastObject.StartTime) / timeRate; - - // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure - StrainTime = Math.Max(50, DeltaTime); - } - private void computeSliderCursorPosition(Slider slider) { if (slider.LazyEndPosition != null) diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index b5e57985e9..e74f4933b2 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -17,33 +20,40 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected override double SkillMultiplier => 26.25; protected override double StrainDecayBase => 0.15; - protected override double StrainValueOf(OsuDifficultyHitObject current) + protected override double StrainValueOf(DifficultyHitObject current) { + if (current.BaseObject is Spinner) + return 0; + + var osuCurrent = (OsuDifficultyHitObject)current; + double result = 0; - const double scale = 90; - - double applyDiminishingExp(double val) => Math.Pow(val, 0.99); - if (Previous.Count > 0) { - if (current.Angle != null && current.Angle.Value > angle_bonus_begin) + var osuPrevious = (OsuDifficultyHitObject)Previous[0]; + + if (osuCurrent.Angle != null && osuCurrent.Angle.Value > angle_bonus_begin) { + const double scale = 90; + var angleBonus = Math.Sqrt( - Math.Max(Previous[0].JumpDistance - scale, 0) - * Math.Pow(Math.Sin(current.Angle.Value - angle_bonus_begin), 2) - * Math.Max(current.JumpDistance - scale, 0)); - result = 1.5 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, Previous[0].StrainTime); + Math.Max(osuPrevious.JumpDistance - scale, 0) + * Math.Pow(Math.Sin(osuCurrent.Angle.Value - angle_bonus_begin), 2) + * Math.Max(osuCurrent.JumpDistance - scale, 0)); + result = 1.5 * applyDiminishingExp(Math.Max(0, angleBonus)) / Math.Max(timing_threshold, osuPrevious.StrainTime); } } - double jumpDistanceExp = applyDiminishingExp(current.JumpDistance); - double travelDistanceExp = applyDiminishingExp(current.TravelDistance); + double jumpDistanceExp = applyDiminishingExp(osuCurrent.JumpDistance); + double travelDistanceExp = applyDiminishingExp(osuCurrent.TravelDistance); return Math.Max( - result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(current.StrainTime, timing_threshold), - (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / current.StrainTime + result + (jumpDistanceExp + travelDistanceExp + Math.Sqrt(travelDistanceExp * jumpDistanceExp)) / Math.Max(osuCurrent.StrainTime, timing_threshold), + (Math.Sqrt(travelDistanceExp * jumpDistanceExp) + jumpDistanceExp + travelDistanceExp) / osuCurrent.StrainTime ); } + + private double applyDiminishingExp(double val) => Math.Pow(val, 0.99); } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index e78691ce53..46a81a9480 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -2,7 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; +using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty.Skills { @@ -11,6 +14,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// public class Speed : Skill { + private const double single_spacing_threshold = 125; + private const double angle_bonus_begin = 5 * Math.PI / 6; private const double pi_over_4 = Math.PI / 4; private const double pi_over_2 = Math.PI / 2; @@ -22,9 +27,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills private const double max_speed_bonus = 45; // ~330BPM private const double speed_balancing_factor = 40; - protected override double StrainValueOf(OsuDifficultyHitObject current) + protected override double StrainValueOf(DifficultyHitObject current) { - double distance = Math.Min(SINGLE_SPACING_THRESHOLD, current.TravelDistance + current.JumpDistance); + if (current.BaseObject is Spinner) + return 0; + + var osuCurrent = (OsuDifficultyHitObject)current; + + double distance = Math.Min(single_spacing_threshold, osuCurrent.TravelDistance + osuCurrent.JumpDistance); double deltaTime = Math.Max(max_speed_bonus, current.DeltaTime); double speedBonus = 1.0; @@ -32,20 +42,20 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills speedBonus = 1 + Math.Pow((min_speed_bonus - deltaTime) / speed_balancing_factor, 2); double angleBonus = 1.0; - if (current.Angle != null && current.Angle.Value < angle_bonus_begin) + if (osuCurrent.Angle != null && osuCurrent.Angle.Value < angle_bonus_begin) { - angleBonus = 1 + Math.Pow(Math.Sin(1.5 * (angle_bonus_begin - current.Angle.Value)), 2) / 3.57; - if (current.Angle.Value < pi_over_2) + angleBonus = 1 + Math.Pow(Math.Sin(1.5 * (angle_bonus_begin - osuCurrent.Angle.Value)), 2) / 3.57; + if (osuCurrent.Angle.Value < pi_over_2) { angleBonus = 1.28; - if (distance < 90 && current.Angle.Value < pi_over_4) + if (distance < 90 && osuCurrent.Angle.Value < pi_over_4) angleBonus += (1 - angleBonus) * Math.Min((90 - distance) / 10, 1); else if (distance < 90) - angleBonus += (1 - angleBonus) * Math.Min((90 - distance) / 10, 1) * Math.Sin((pi_over_2 - current.Angle.Value) / pi_over_4); + angleBonus += (1 - angleBonus) * Math.Min((90 - distance) / 10, 1) * Math.Sin((pi_over_2 - osuCurrent.Angle.Value) / pi_over_4); } } - return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / SINGLE_SPACING_THRESHOLD, 3.5)) / current.StrainTime; + return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime; } } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs index 5958b32f33..7f6a60c400 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components PositionBindable.BindValueChanged(_ => UpdatePosition(), true); StackHeightBindable.BindValueChanged(_ => UpdatePosition()); - ScaleBindable.BindValueChanged(v => Scale = new Vector2(v), true); + ScaleBindable.BindValueChanged(scale => Scale = new Vector2(scale.NewValue), true); } protected virtual void UpdatePosition() => Position = hitCircle.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs index 44e61f30b0..315a5a2b9d 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitObjectPiece.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Objects; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs index dfc8bf4664..8fd1d6d6f9 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/SliderPiece.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs index cb9b5211d4..179fa1bc72 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components body.BorderColour = colours.Yellow; PositionBindable.BindValueChanged(_ => updatePosition(), true); - ScaleBindable.BindValueChanged(v => body.PathWidth = v * 64, true); + ScaleBindable.BindValueChanged(scale => body.PathWidth = scale.NewValue * 64, true); } private void updatePosition() => Position = slider.StackedPosition; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs index d2fec859b8..9d164ebe0b 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderCirclePiece.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components; using osu.Game.Rulesets.Osu.Objects; diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs index 7f91bc49eb..ae94848c81 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/Components/SpinnerPiece.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components PositionBindable.BindValueChanged(_ => updatePosition(), true); StackHeightBindable.BindValueChanged(_ => updatePosition()); - ScaleBindable.BindValueChanged(v => ring.Scale = new Vector2(v), true); + ScaleBindable.BindValueChanged(scale => ring.Scale = new Vector2(scale.NewValue), true); } private void updatePosition() => Position = spinner.Position; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs index 19b627b560..a203e23687 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { - scoreProcessor.Health.ValueChanged += val => { blinds.AnimateClosedness((float)val); }; + scoreProcessor.Health.ValueChanged += health => { blinds.AnimateClosedness((float)health.NewValue); }; } /// diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index ba82465a78..2c40d18f1b 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.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.Graphics; using osu.Framework.Input; using osu.Framework.Input.Events; @@ -41,9 +42,9 @@ namespace osu.Game.Rulesets.Osu.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs new file mode 100644 index 0000000000..65e9eb7a1d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -0,0 +1,74 @@ +// 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.Graphics; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModGrow : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Grow"; + + public override string Acronym => "GR"; + + public override FontAwesome Icon => FontAwesome.fa_arrows_v; + + public override ModType Type => ModType.Fun; + + public override string Description => "Hit them at the right size!"; + + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + { + switch (drawable) + { + case DrawableSpinner _: + continue; + default: + drawable.ApplyCustomUpdateState += ApplyCustomState; + break; + } + } + } + + protected virtual void ApplyCustomState(DrawableHitObject drawable, ArmedState state) + { + var h = (OsuHitObject)drawable.HitObject; + + // apply grow effect + switch (drawable) + { + case DrawableSliderHead _: + case DrawableSliderTail _: + // special cases we should *not* be scaling. + break; + case DrawableSlider _: + case DrawableHitCircle _: + { + using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + drawable.ScaleTo(0.5f).Then().ScaleTo(1, h.TimePreempt, Easing.OutSine); + break; + } + } + + // remove approach circles + switch (drawable) + { + case DrawableHitCircle circle: + // we don't want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.ApproachCircle.Hide(); + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index df0769982d..e909216508 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -3,8 +3,9 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osuTK; @@ -27,40 +28,60 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); + public OsuAction? HitAction => circle.HitAction; + + private readonly Container explodeContainer; + + private readonly Container scaleContainer; + public DrawableHitCircle(HitCircle h) : base(h) { Origin = Anchor.Centre; Position = HitObject.StackedPosition; - Scale = new Vector2(h.Scale); InternalChildren = new Drawable[] { - glow = new GlowPiece(), - circle = new CirclePiece + scaleContainer = new Container { - Hit = () => + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Child = explodeContainer = new Container { - if (AllJudged) - return false; + RelativeSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Children = new Drawable[] + { + glow = new GlowPiece(), + circle = new CirclePiece + { + Hit = () => + { + if (AllJudged) + return false; - UpdateResult(true); - return true; - }, + UpdateResult(true); + return true; + }, + }, + number = new NumberPiece + { + Text = (HitObject.IndexInCurrentCombo + 1).ToString(), + }, + ring = new RingPiece(), + flash = new FlashPiece(), + explode = new ExplodePiece(), + ApproachCircle = new ApproachCircle + { + Alpha = 0, + Scale = new Vector2(4), + } + } + } }, - number = new NumberPiece - { - Text = (HitObject.IndexInCurrentCombo + 1).ToString(), - }, - ring = new RingPiece(), - flash = new FlashPiece(), - explode = new ExplodePiece(), - ApproachCircle = new ApproachCircle - { - Alpha = 0, - Scale = new Vector2(4), - } }; //may not be so correct @@ -72,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); stackHeightBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(v => Scale = new Vector2(v)); + scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true); positionBindable.BindTo(HitObject.PositionBindable); stackHeightBindable.BindTo(HitObject.StackHeightBindable); @@ -131,6 +152,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); + circle.HitAction = null; + // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; @@ -156,8 +179,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.FadeOut(); number.FadeOut(); - this.FadeOut(800) - .ScaleTo(Scale * 1.5f, 400, Easing.OutQuad); + this.FadeOut(800); + explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); } Expire(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index ca9a27976e..b55ec10d1d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Rulesets.Objects; @@ -53,6 +53,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, Ball = new SliderBall(s, this) { + GetInitialHitAction = () => HeadCircle.HitAction, BypassAutoSizeAxes = Axes.Both, Scale = new Vector2(s.Scale), AlwaysPresent = true, @@ -99,10 +100,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables config.BindWith(OsuSetting.SnakingOutSliders, Body.SnakingOut); positionBindable.BindValueChanged(_ => Position = HitObject.StackedPosition); - scaleBindable.BindValueChanged(v => + scaleBindable.BindValueChanged(scale => { - Body.PathWidth = HitObject.Scale * 64; - Ball.Scale = new Vector2(HitObject.Scale); + Body.PathWidth = scale.NewValue * 64; + Ball.Scale = new Vector2(scale.NewValue); }); positionBindable.BindTo(HitObject.PositionBindable); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index e24efc6ffb..66b6f0f9ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osuTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 53f6aa5b76..23c5494cf5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index c411b562e4..936023d39d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Screens.Ranking; using osu.Game.Rulesets.Scoring; @@ -130,7 +130,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Colour = colours.BlueDark; glow.Colour = colours.BlueDark; - positionBindable.BindValueChanged(v => Position = v); + positionBindable.BindValueChanged(pos => Position = pos.NewValue); positionBindable.BindTo(HitObject.PositionBindable); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index b7e2748ca9..786cac7198 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public Func Hit; + public OsuAction? HitAction; + public CirclePiece() { Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2); @@ -35,7 +37,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { case OsuAction.LeftButton: case OsuAction.RightButton: - return IsHovered && (Hit?.Invoke() ?? false); + if (IsHovered && (Hit?.Invoke() ?? false)) + { + HitAction = action; + return true; + } + + break; } return false; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index bc354bc2b6..813cd51593 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; using osu.Game.Skinning; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -42,9 +43,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }, s => s.GetTexture("Play/osu/hitcircle") == null), number = new SkinnableSpriteText("Play/osu/number-text", _ => new OsuSpriteText { - Font = @"Venera", + Font = OsuFont.Numeric.With(size: 40), UseFullGlyphHeight = false, - TextSize = 40, }, restrictSize: false) { Text = @"1" diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index db9fee242a..afa7f22140 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.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 System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private Color4 accentColour = Color4.Black; + public Func GetInitialHitAction; + /// /// The colour that is used for the slider ball. /// @@ -145,20 +148,72 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private bool canCurrentlyTrack => Time.Current >= slider.StartTime && Time.Current < slider.EndTime; + /// + /// If the cursor moves out of the ball's radius we still need to be able to receive positional updates to stop tracking. + /// + public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true; + + /// + /// The point in time after which we can accept any key for tracking. Before this time, we may need to restrict tracking to the key used to hit the head circle. + /// + /// This is a requirement to stop the case where a player holds down one key (from before the slider) and taps the second key while maintaining full scoring (tracking) of sliders. + /// Visually, this special case can be seen below (time increasing from left to right): + /// + /// Z Z+X Z + /// o========o + /// + /// Without this logic, tracking would continue through the entire slider even though no key hold action is directly attributing to it. + /// + /// In all other cases, no special handling is required (either key being pressed is allowable as valid tracking). + /// + /// The reason for storing this as a time value (rather than a bool) is to correctly handle rewind scenarios. + /// + private double? timeToAcceptAnyKeyAfter; protected override void Update() { base.Update(); - if (Time.Current < slider.EndTime) + // from the point at which the head circle is hit, this will be non-null. + // it may be null if the head circle was missed. + var headCircleHitAction = GetInitialHitAction(); + + if (headCircleHitAction == null) + timeToAcceptAnyKeyAfter = null; + + var actions = drawableSlider?.OsuActionInputManager?.PressedActions; + + // if the head circle was hit with a specific key, tracking should only occur while that key is pressed. + if (headCircleHitAction != null && timeToAcceptAnyKeyAfter == null) { - // Make sure to use the base version of ReceivePositionalInputAt so that we correctly check the position. - Tracking = canCurrentlyTrack - && lastScreenSpaceMousePosition.HasValue - && ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) - && (drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + var otherKey = headCircleHitAction == OsuAction.RightButton ? OsuAction.LeftButton : OsuAction.RightButton; + + // we can return to accepting all keys if the initial head circle key is the *only* key pressed, or all keys have been released. + if (actions?.Contains(otherKey) != true) + timeToAcceptAnyKeyAfter = Time.Current; } + + Tracking = + // in valid time range + Time.Current >= slider.StartTime && Time.Current < slider.EndTime && + // in valid position range + lastScreenSpaceMousePosition.HasValue && base.ReceivePositionalInputAt(lastScreenSpaceMousePosition.Value) && + // valid action + (actions?.Any(isValidTrackingAction) ?? false); + } + + /// + /// Check whether a given user input is a valid tracking action. + /// + private bool isValidTrackingAction(OsuAction action) + { + bool headCircleHit = GetInitialHitAction().HasValue; + + // if the head circle was hit, we may not yet be allowed to accept any key, so we must use the initial hit action. + if (headCircleHit && (!timeToAcceptAnyKeyAfter.HasValue || Time.Current <= timeToAcceptAnyKeyAfter.Value)) + return action == GetInitialHitAction(); + + return action == OsuAction.LeftButton || action == OsuAction.RightButton; } public void UpdateProgress(double completionProgress) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs index 256cd088de..73b184bffe 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SnakingSliderBody.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Types; using osuTK; @@ -54,18 +54,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var spanProgress = slider.ProgressAt(completionProgress); double start = 0; - double end = SnakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadeIn, 0, 1) : 1; + double end = SnakingIn.Value ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadeIn, 0, 1) : 1; if (span >= slider.SpanCount() - 1) { if (Math.Min(span, slider.SpanCount() - 1) % 2 == 1) { start = 0; - end = SnakingOut ? spanProgress : 1; + end = SnakingOut.Value ? spanProgress : 1; } else { - start = SnakingOut ? spanProgress : 0; + start = SnakingOut.Value ? spanProgress : 0; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs index e4d09b9306..19f85bf4c3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -23,16 +24,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"0", - Font = @"Venera", - TextSize = 24 + Font = OsuFont.Numeric.With(size: 24) }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"SPINS PER MINUTE", - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Y = 30 } }; diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index a2e518ace4..364c182dd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using osuTK; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual Vector2 Position { - get => PositionBindable; + get => PositionBindable.Value; set => PositionBindable.Value = value; } @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Objects public int StackHeight { - get => StackHeightBindable; + get => StackHeightBindable.Value; set => StackHeightBindable.Value = value; } @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects public float Scale { - get => ScaleBindable; + get => ScaleBindable.Value; set => ScaleBindable.Value = value; } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index d47fed354a..c200b43d91 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -7,8 +7,8 @@ using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; using osu.Game.Rulesets.Objects; using System.Linq; +using osu.Framework.Bindables; using osu.Framework.Caching; -using osu.Framework.Configuration; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 29b00b8d5d..43a2ae0fbb 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Judgements; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 12d0a28a8f..200f4af3da 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -124,6 +124,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), + new OsuModGrow() }; default: return new Mod[] { }; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs similarity index 89% rename from osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs rename to osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index 0e9a906d85..d1ac77857d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -11,9 +11,9 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Replays { - public class OsuReplayInputHandler : FramedReplayInputHandler + public class OsuFramedReplayInputHandler : FramedReplayInputHandler { - public OsuReplayInputHandler(Replay replay) + public OsuFramedReplayInputHandler(Replay replay) : base(replay) { } diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index 3167e93923..325a0172b9 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -183,13 +183,13 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor }; this.beatmap.BindTo(beatmap); - this.beatmap.ValueChanged += v => calculateScale(); + this.beatmap.ValueChanged += _ => calculateScale(); cursorScale = config.GetBindable(OsuSetting.GameplayCursorSize); - cursorScale.ValueChanged += v => calculateScale(); + cursorScale.ValueChanged += _ => calculateScale(); autoCursorScale = config.GetBindable(OsuSetting.AutoCursorSize); - autoCursorScale.ValueChanged += v => calculateScale(); + autoCursorScale.ValueChanged += _ => calculateScale(); calculateScale(); } @@ -198,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { float scale = (float)cursorScale.Value; - if (autoCursorScale && beatmap.Value != null) + if (autoCursorScale.Value && beatmap.Value != null) { // if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier. scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY); diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index c4097ccb46..08f9e8785d 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.UI private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayResult || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements.Value) return; DrawableOsuJudgement explosion = new DrawableOsuJudgement(result, judgedObject) diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 86e5f8467d..935f9c5c0d 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.UI return null; } - protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay); + protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuFramedReplayInputHandler(replay); public override double GameplayStartTime { diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs index 299f84fb1f..e7b6d8615b 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoDifficultyCalculatorTest.cs @@ -13,8 +13,8 @@ namespace osu.Game.Rulesets.Taiko.Tests { protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko"; - [TestCase(2.9811336589467095, "diffcalc-test")] - [TestCase(2.9811336589467095, "diffcalc-test-strong")] + [TestCase(2.9811338051242915d, "diffcalc-test")] + [TestCase(2.9811338051242915d, "diffcalc-test-strong")] public void Test(double expected, string name) => base.Test(expected, name); diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 2c02649102..00e1b649d9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Ruleset = new TaikoRuleset().RulesetInfo }, ControlPointInfo = controlPointInfo - }); + }, Clock); Add(playfieldContainer = new Container { diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs new file mode 100644 index 0000000000..24345275c1 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs @@ -0,0 +1,20 @@ +// 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.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing +{ + public class TaikoDifficultyHitObject : DifficultyHitObject + { + public readonly bool HasTypeChange; + + public TaikoDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + : base(hitObject, lastObject, clockRate) + { + HasTypeChange = lastObject is RimHit != hitObject is RimHit; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs new file mode 100644 index 0000000000..c6fe273b50 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Strain.cs @@ -0,0 +1,95 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; +using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; +using osu.Game.Rulesets.Taiko.Objects; + +namespace osu.Game.Rulesets.Taiko.Difficulty.Skills +{ + public class Strain : Skill + { + private const double rhythm_change_base_threshold = 0.2; + private const double rhythm_change_base = 2.0; + + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 0.3; + + private ColourSwitch lastColourSwitch = ColourSwitch.None; + + private int sameColourCount = 1; + + protected override double StrainValueOf(DifficultyHitObject current) + { + double addition = 1; + + // We get an extra addition if we are not a slider or spinner + if (current.LastObject is Hit && current.BaseObject is Hit && current.DeltaTime < 1000) + { + if (hasColourChange(current)) + addition += 0.75; + + if (hasRhythmChange(current)) + addition += 1; + } + else + { + lastColourSwitch = ColourSwitch.None; + sameColourCount = 1; + } + + double additionFactor = 1; + + // Scale the addition factor linearly from 0.4 to 1 for DeltaTime from 0 to 50 + if (current.DeltaTime < 50) + additionFactor = 0.4 + 0.6 * current.DeltaTime / 50; + + return additionFactor * addition; + } + + private bool hasRhythmChange(DifficultyHitObject current) + { + // We don't want a division by zero if some random mapper decides to put two HitObjects at the same time. + if (current.DeltaTime == 0 || Previous.Count == 0 || Previous[0].DeltaTime == 0) + return false; + + double timeElapsedRatio = Math.Max(Previous[0].DeltaTime / current.DeltaTime, current.DeltaTime / Previous[0].DeltaTime); + + if (timeElapsedRatio >= 8) + return false; + + double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0; + + return difference > rhythm_change_base_threshold && difference < 1 - rhythm_change_base_threshold; + } + + private bool hasColourChange(DifficultyHitObject current) + { + var taikoCurrent = (TaikoDifficultyHitObject)current; + + if (!taikoCurrent.HasTypeChange) + { + sameColourCount++; + return false; + } + + var oldColourSwitch = lastColourSwitch; + var newColourSwitch = sameColourCount % 2 == 0 ? ColourSwitch.Even : ColourSwitch.Odd; + + lastColourSwitch = newColourSwitch; + sameColourCount = 1; + + // We only want a bonus if the parity of the color switch changes + return oldColourSwitch != ColourSwitch.None && oldColourSwitch != newColourSwitch; + } + + private enum ColourSwitch + { + None, + Even, + Odd + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index 3770f9601a..75d3807bba 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Difficulty; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Difficulty { @@ -10,10 +9,5 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { public double GreatHitWindow; public int MaxCombo; - - public TaikoDifficultyAttributes(Mod[] mods, double starRating) - : base(mods, starRating) - { - } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 2322446666..685ad9949b 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -1,137 +1,51 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; +using osu.Game.Rulesets.Taiko.Difficulty.Skills; using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty { - internal class TaikoDifficultyCalculator : DifficultyCalculator + public class TaikoDifficultyCalculator : DifficultyCalculator { private const double star_scaling_factor = 0.04125; - /// - /// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP. - /// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain. - /// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage. - /// - private const double strain_step = 400; - - /// - /// The weighting of each strain value decays to this number * it's previous value - /// - private const double decay_weight = 0.9; - public TaikoDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) { } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - if (!beatmap.HitObjects.Any()) - return new TaikoDifficultyAttributes(mods, 0); + if (beatmap.HitObjects.Count == 0) + return new TaikoDifficultyAttributes { Mods = mods }; - var difficultyHitObjects = new List(); - - foreach (var hitObject in beatmap.HitObjects) - difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject)); - - // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. - difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime)); - - if (!calculateStrainValues(difficultyHitObjects, timeRate)) - return new TaikoDifficultyAttributes(mods, 0); - - double starRating = calculateDifficulty(difficultyHitObjects, timeRate) * star_scaling_factor; - - return new TaikoDifficultyAttributes(mods, starRating) + return new TaikoDifficultyAttributes { - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be remoevd in the future - GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / timeRate, - MaxCombo = beatmap.HitObjects.Count(h => h is Hit) + StarRating = skills.Single().DifficultyValue() * star_scaling_factor, + Mods = mods, + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future + GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, + MaxCombo = beatmap.HitObjects.Count(h => h is Hit), }; } - private bool calculateStrainValues(List objects, double timeRate) + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { - // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. - using (var hitObjectsEnumerator = objects.GetEnumerator()) - { - if (!hitObjectsEnumerator.MoveNext()) return false; - - TaikoHitObjectDifficulty current = hitObjectsEnumerator.Current; - - // First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject. - while (hitObjectsEnumerator.MoveNext()) - { - var next = hitObjectsEnumerator.Current; - next?.CalculateStrains(current, timeRate); - current = next; - } - - return true; - } + for (int i = 1; i < beatmap.HitObjects.Count; i++) + yield return new TaikoDifficultyHitObject(beatmap.HitObjects[i], beatmap.HitObjects[i - 1], clockRate); } - private double calculateDifficulty(List objects, double timeRate) - { - double actualStrainStep = strain_step * timeRate; - - // Find the highest strain value within each strain step - List highestStrains = new List(); - double intervalEndTime = actualStrainStep; - double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval - - TaikoHitObjectDifficulty previousHitObject = null; - foreach (var hitObject in objects) - { - // While we are beyond the current interval push the currently available maximum to our strain list - while (hitObject.BaseHitObject.StartTime > intervalEndTime) - { - highestStrains.Add(maximumStrain); - - // The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay - // until the beginning of the next interval. - if (previousHitObject == null) - { - maximumStrain = 0; - } - else - { - double decay = Math.Pow(TaikoHitObjectDifficulty.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000); - maximumStrain = previousHitObject.Strain * decay; - } - - // Go to the next time interval - intervalEndTime += actualStrainStep; - } - - // Obtain maximum strain - maximumStrain = Math.Max(hitObject.Strain, maximumStrain); - - previousHitObject = hitObject; - } - - // Build the weighted sum over the highest strains for each interval - double difficulty = 0; - double weight = 1; - highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. - - foreach (double strain in highestStrains) - { - difficulty += weight * strain; - weight *= decay_weight; - } - - return difficulty; - } + protected override Skill[] CreateSkills(IBeatmap beatmap) => new Skill[] { new Strain() }; protected override Mod[] DifficultyAdjustmentMods => new Mod[] { diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs index c7e6771b80..b99ec57166 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.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.Caching; using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; @@ -48,9 +49,9 @@ namespace osu.Game.Rulesets.Taiko.Mods return default_flashlight_size; } - protected override void OnComboChange(int newCombo) + protected override void OnComboChange(ValueChangedEvent e) { - this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(newCombo)), FLASHLIGHT_FADE_DURATION); + this.TransformTo(nameof(FlashlightSize), new Vector2(0, getSizeFor(e.NewValue)), FLASHLIGHT_FADE_DURATION); } protected override string FragmentShader => "CircularFlashlight"; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs deleted file mode 100644 index 46dd7aa87f..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs +++ /dev/null @@ -1,127 +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 System; - -namespace osu.Game.Rulesets.Taiko.Objects -{ - internal class TaikoHitObjectDifficulty - { - /// - /// Factor by how much individual / overall strain decays per second. - /// - /// - /// These values are results of tweaking a lot and taking into account general feedback. - /// - internal const double DECAY_BASE = 0.30; - - private const double type_change_bonus = 0.75; - private const double rhythm_change_bonus = 1.0; - private const double rhythm_change_base_threshold = 0.2; - private const double rhythm_change_base = 2.0; - - internal TaikoHitObject BaseHitObject; - - /// - /// Measures note density in a way - /// - internal double Strain = 1; - - private double timeElapsed; - private int sameTypeSince = 1; - - private bool isRim => BaseHitObject is RimHit; - - public TaikoHitObjectDifficulty(TaikoHitObject baseHitObject) - { - BaseHitObject = baseHitObject; - } - - internal void CalculateStrains(TaikoHitObjectDifficulty previousHitObject, double timeRate) - { - // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. - // See Taiko feedback thread. - timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; - double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000); - - double addition = 1; - - // Only if we are no slider or spinner we get an extra addition - if (previousHitObject.BaseHitObject is Hit && BaseHitObject is Hit - && BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime < 1000) // And we only want to check out hitobjects which aren't so far in the past - { - addition += typeChangeAddition(previousHitObject); - addition += rhythmChangeAddition(previousHitObject); - } - - double additionFactor = 1.0; - // Scale AdditionFactor linearly from 0.4 to 1 for TimeElapsed from 0 to 50 - if (timeElapsed < 50.0) - additionFactor = 0.4 + 0.6 * timeElapsed / 50.0; - - Strain = previousHitObject.Strain * decay + addition * additionFactor; - } - - private TypeSwitch lastTypeSwitchEven = TypeSwitch.None; - private double typeChangeAddition(TaikoHitObjectDifficulty previousHitObject) - { - // If we don't have the same hit type, trigger a type change! - if (previousHitObject.isRim != isRim) - { - lastTypeSwitchEven = previousHitObject.sameTypeSince % 2 == 0 ? TypeSwitch.Even : TypeSwitch.Odd; - - // We only want a bonus if the parity of the type switch changes! - switch (previousHitObject.lastTypeSwitchEven) - { - case TypeSwitch.Even: - if (lastTypeSwitchEven == TypeSwitch.Odd) - return type_change_bonus; - break; - case TypeSwitch.Odd: - if (lastTypeSwitchEven == TypeSwitch.Even) - return type_change_bonus; - break; - } - } - // No type change? Increment counter and keep track of last type switch - else - { - lastTypeSwitchEven = previousHitObject.lastTypeSwitchEven; - sameTypeSince = previousHitObject.sameTypeSince + 1; - } - - return 0; - } - - private double rhythmChangeAddition(TaikoHitObjectDifficulty previousHitObject) - { - // We don't want a division by zero if some random mapper decides to put 2 HitObjects at the same time. - if (timeElapsed == 0 || previousHitObject.timeElapsed == 0) - return 0; - - double timeElapsedRatio = Math.Max(previousHitObject.timeElapsed / timeElapsed, timeElapsed / previousHitObject.timeElapsed); - - if (timeElapsedRatio >= 8) - return 0; - - double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0; - - if (isWithinChangeThreshold(difference)) - return rhythm_change_bonus; - - return 0; - } - - private bool isWithinChangeThreshold(double value) - { - return value > rhythm_change_base_threshold && value < 1 - rhythm_change_base_threshold; - } - - private enum TypeSwitch - { - None, - Even, - Odd - } - } -} diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 8dc9a2ca37..cb527adb98 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -225,7 +225,7 @@ namespace osu.Game.Rulesets.Taiko.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!DisplayJudgements) + if (!DisplayJudgements.Value) return; if (!judgedObject.DisplayResult) diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 002d6a7e8d..656ebcc7c2 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 795c2244a2..760a033aff 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -2,9 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.NonVisual @@ -15,7 +18,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestNoMods() { - var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(1, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -24,7 +27,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestSingleMod() { - var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(2, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -34,7 +37,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestDoubleMod() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(4, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -49,7 +52,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestIncompatibleMods() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -60,7 +63,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestDoubleIncompatibleMods() { - var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(8, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -83,7 +86,7 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestIncompatibleThroughBaseType() { - var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); + var combinations = new TestLegacyDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); @@ -136,9 +139,9 @@ namespace osu.Game.Tests.NonVisual public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; } - private class TestDifficultyCalculator : DifficultyCalculator + private class TestLegacyDifficultyCalculator : DifficultyCalculator { - public TestDifficultyCalculator(params Mod[] mods) + public TestLegacyDifficultyCalculator(params Mod[] mods) : base(null, null) { DifficultyAdjustmentMods = mods; @@ -146,7 +149,20 @@ namespace osu.Game.Tests.NonVisual protected override Mod[] DifficultyAdjustmentMods { get; } - protected override DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate) => throw new NotImplementedException(); + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + { + throw new NotImplementedException(); + } + + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + throw new NotImplementedException(); + } + + protected override Skill[] CreateSkills(IBeatmap beatmap) + { + throw new NotImplementedException(); + } } } } diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs new file mode 100644 index 0000000000..1c78b63499 --- /dev/null +++ b/osu.Game.Tests/NonVisual/LimitedCapacityStackTest.cs @@ -0,0 +1,115 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Rulesets.Difficulty.Utils; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class LimitedCapacityStackTest + { + private const int capacity = 3; + + private LimitedCapacityStack stack; + + [SetUp] + public void Setup() + { + stack = new LimitedCapacityStack(capacity); + } + + [Test] + public void TestEmptyStack() + { + Assert.AreEqual(0, stack.Count); + + Assert.Throws(() => + { + int unused = stack[0]; + }); + + int count = 0; + foreach (var unused in stack) + count++; + + Assert.AreEqual(0, count); + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + public void TestInRangeElements(int count) + { + // e.g. 0 -> 1 -> 2 + for (int i = 0; i < count; i++) + stack.Push(i); + + Assert.AreEqual(count, stack.Count); + + // e.g. 2 -> 1 -> 0 (reverse order) + for (int i = 0; i < stack.Count; i++) + Assert.AreEqual(count - 1 - i, stack[i]); + + // e.g. indices 3, 4, 5, 6 (out of range) + for (int i = stack.Count; i < stack.Count + capacity; i++) + { + Assert.Throws(() => + { + int unused = stack[i]; + }); + } + } + + [TestCase(4)] + [TestCase(5)] + [TestCase(6)] + public void TestOverflowElements(int count) + { + // e.g. 0 -> 1 -> 2 -> 3 + for (int i = 0; i < count; i++) + stack.Push(i); + + Assert.AreEqual(capacity, stack.Count); + + // e.g. 3 -> 2 -> 1 (reverse order) + for (int i = 0; i < stack.Count; i++) + Assert.AreEqual(count - 1 - i, stack[i]); + + // e.g. indices 3, 4, 5, 6 (out of range) + for (int i = stack.Count; i < stack.Count + capacity; i++) + { + Assert.Throws(() => + { + int unused = stack[i]; + }); + } + } + + [TestCase(1)] + [TestCase(2)] + [TestCase(3)] + [TestCase(4)] + [TestCase(5)] + [TestCase(6)] + public void TestEnumerator(int count) + { + // e.g. 0 -> 1 -> 2 -> 3 + for (int i = 0; i < count; i++) + stack.Push(i); + + int enumeratorCount = 0; + int expectedValue = count - 1; + + foreach (var item in stack) + { + Assert.AreEqual(expectedValue, item); + enumeratorCount++; + expectedValue--; + } + + Assert.AreEqual(stack.Count, enumeratorCount); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/TestCaseAutoplay.cs index 3f3d62377e..61339a6af8 100644 --- a/osu.Game.Tests/Visual/TestCaseAutoplay.cs +++ b/osu.Game.Tests/Visual/TestCaseAutoplay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual protected override void AddCheckSteps(Func player) { base.AddCheckSteps(player); - AddUntilStep(() => ((ScoreAccessiblePlayer)player()).ScoreProcessor.TotalScore > 0, "score above zero"); + AddUntilStep(() => ((ScoreAccessiblePlayer)player()).ScoreProcessor.TotalScore.Value > 0, "score above zero"); AddUntilStep(() => ((ScoreAccessiblePlayer)player()).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0), "key counter counted keys"); } diff --git a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs index 85ef5963a5..127ee9e482 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs @@ -15,6 +15,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osuTK.Graphics; using osu.Framework.Lists; +using osu.Game.Graphics; namespace osu.Game.Tests.Visual { @@ -196,8 +197,8 @@ namespace osu.Game.Tests.Visual { AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; - Add(new OsuSpriteText { Text = header + @": ", TextSize = text_size }); - Add(valueText = new OsuSpriteText { TextSize = text_size }); + Add(new OsuSpriteText { Text = header + @": ", Font = OsuFont.GetFont(size: text_size) }); + Add(valueText = new OsuSpriteText { Font = OsuFont.GetFont(size: text_size) }); Margin = new MarginPadding(margin); } } diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index e61bca9846..99bdb05394 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -147,7 +147,7 @@ namespace osu.Game.Tests.Visual private bool selectedBeatmapVisible() { - var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected); + var currentlySelected = carousel.Items.Find(s => s.Item is CarouselBeatmap && s.Item.State.Value == CarouselItemState.Selected); if (currentlySelected == null) return true; return currentlySelected.Item.Visible; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index d3056f0b13..31bb8b64a3 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual AddStep("show", () => { infoWedge.State = Visibility.Visible; - infoWedge.Beatmap = Beatmap; + infoWedge.Beatmap = Beatmap.Value; }); // select part is redundant, but wait for load isn't diff --git a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs index 6e60eb3306..749303b1bb 100644 --- a/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs +++ b/osu.Game.Tests/Visual/TestCaseChannelTabControl.cs @@ -69,7 +69,7 @@ namespace osu.Game.Tests.Visual }); channelTabControl.OnRequestLeave += channel => channelTabControl.RemoveChannel(channel); - channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.ToString(); + channelTabControl.Current.ValueChanged += channel => currentText.Text = "Currently selected channel: " + channel.NewValue.ToString(); AddStep("Add random private channel", addRandomPrivateChannel); AddAssert("There is only one channels", () => channelTabControl.Items.Count() == 2); diff --git a/osu.Game.Tests/Visual/TestCaseChatLink.cs b/osu.Game.Tests/Visual/TestCaseChatLink.cs index f119e6dc24..dc537348c9 100644 --- a/osu.Game.Tests/Visual/TestCaseChatLink.cs +++ b/osu.Game.Tests/Visual/TestCaseChatLink.cs @@ -13,10 +13,10 @@ using System; using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Bindables; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Overlays; -using osu.Framework.Configuration; namespace osu.Game.Tests.Visual { @@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual return true; } - bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast().All(sprite => sprite.Font == "Exo2.0-MediumItalic"); + bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast().All(sprite => sprite.Font.Italics); bool isShowingLinks() { diff --git a/osu.Game.Tests/Visual/TestCaseDrawableDate.cs b/osu.Game.Tests/Visual/TestCaseDrawableDate.cs index 839f2a82de..8d2182dd78 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableDate.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableDate.cs @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual } }; - drawableDate.Current.ValueChanged += v => flash.FadeOutFromOne(500); + drawableDate.Current.ValueChanged += _ => flash.FadeOutFromOne(500); } } } diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs index 66e13545d9..a52454d684 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock); Child = new ComposeScreen(); } } diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index a2f40f1903..9ae9b55546 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs b/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs index 6cb9a1abfd..244f3b9d3d 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSeekSnapping.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual } }; - Beatmap.Value = new TestWorkingBeatmap(testBeatmap); + Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock); Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock }; } diff --git a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs index b952582ef2..305924958b 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null); Add(new SummaryTimeline { diff --git a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs index c5abe03dbd..3f36365a05 100644 --- a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First())); AddStep("Hide overlay", () => failOverlay.Hide()); - AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected)); + AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected.Value)); } private void press(Key key) @@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => pauseOverlay.Show()); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -132,11 +132,11 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => failOverlay.Show()); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Hide overlay", () => failOverlay.Hide()); } @@ -149,11 +149,11 @@ namespace osu.Game.Tests.Visual AddStep("Show overlay", () => failOverlay.Show()); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected); + AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected.Value); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => failOverlay.Buttons.First().Selected); + AddAssert("First button selected", () => failOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => failOverlay.Hide()); } @@ -169,8 +169,8 @@ namespace osu.Game.Tests.Visual AddStep("Down arrow", () => press(Key.Down)); AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); - AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected); - AddAssert("Second button selected", () => secondButton.Selected); + AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected.Value); + AddAssert("Second button selected", () => secondButton.Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -190,8 +190,8 @@ namespace osu.Game.Tests.Visual AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); AddStep("Up arrow", () => press(Key.Up)); - AddAssert("Second button not selected", () => !secondButton.Selected); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); + AddAssert("Second button not selected", () => !secondButton.Selected.Value); + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); AddStep("Hide overlay", () => pauseOverlay.Hide()); } @@ -208,7 +208,7 @@ namespace osu.Game.Tests.Visual AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton)); AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero)); AddStep("Down arrow", () => press(Key.Down)); - AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); // Initial state condition + AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected.Value); // Initial state condition AddStep("Hide overlay", () => pauseOverlay.Hide()); } diff --git a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs index 046bd76f7e..f66bf34875 100644 --- a/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseHoldToConfirmOverlay.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Menu; @@ -22,7 +23,7 @@ namespace osu.Game.Tests.Visual Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Fired!", - TextSize = 50, + Font = OsuFont.GetFont(size: 50), Alpha = 0, }; diff --git a/osu.Game.Tests/Visual/TestCaseIdleTracker.cs b/osu.Game.Tests/Visual/TestCaseIdleTracker.cs index ea669af28c..8e8c4e38ae 100644 --- a/osu.Game.Tests/Visual/TestCaseIdleTracker.cs +++ b/osu.Game.Tests/Visual/TestCaseIdleTracker.cs @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual }, }; - idleTracker.IsIdle.BindValueChanged(idle => box.Colour = idle ? Color4.White : Color4.Black, true); + idleTracker.IsIdle.BindValueChanged(idle => box.Colour = idle.NewValue ? Color4.White : Color4.Black, true); } } } diff --git a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs index c87b91003b..13bc5e24d9 100644 --- a/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseLoungeRoomsContainer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Online.Multiplayer; diff --git a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs index fabeb0aaa4..45092c5b93 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchHostInfo.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Users; diff --git a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs index 317707a77e..a320fc88fa 100644 --- a/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMatchSettingsOverlay.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -52,16 +52,16 @@ namespace osu.Game.Tests.Visual Room.Playlist.Clear(); }); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); AddStep("set name", () => Room.Name.Value = "Room name"); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo })); - AddAssert("button enabled", () => settings.ApplyButton.Enabled); + AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value); AddStep("clear name", () => Room.Name.Value = ""); - AddAssert("button disabled", () => !settings.ApplyButton.Enabled); + AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value); } [Test] diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index e0c0b419af..99bc10d8cc 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Osu.Mods; using System.Linq; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Mods.Sections; diff --git a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs index fc4037f58b..804e3c5b1f 100644 --- a/osu.Game.Tests/Visual/TestCaseMultiScreen.cs +++ b/osu.Game.Tests/Visual/TestCaseMultiScreen.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using NUnit.Framework; -using osu.Framework.Screens; using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Lounge.Components; @@ -26,8 +25,6 @@ namespace osu.Game.Tests.Visual Multiplayer multi = new Multiplayer(); AddStep(@"show", () => LoadScreen(multi)); - AddWaitStep(5); - AddStep(@"exit", multi.Exit); } } } diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs index 109c2ed916..d6a3361cf2 100644 --- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual void setState(Visibility state) => AddStep(state.ToString(), () => manager.State = state); void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected); - manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; }; + manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; }; setState(Visibility.Visible); AddStep(@"simple #1", sendHelloNotification); diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index 78e90987b1..5fa818472c 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.MathUtils; using osu.Framework.Platform; @@ -187,8 +187,8 @@ namespace osu.Game.Tests.Visual AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); AddAssert("empty mods", () => !selectedMods.Value.Any()); - void onModChange(IEnumerable mods) => modChangeIndex = actionIndex++; - void onRulesetChange(RulesetInfo ruleset) => rulesetChangeIndex = actionIndex--; + void onModChange(ValueChangedEvent> e) => modChangeIndex = actionIndex++; + void onRulesetChange(ValueChangedEvent e) => rulesetChangeIndex = actionIndex--; } [Test] diff --git a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs b/osu.Game.Tests/Visual/TestCasePlaybackControl.cs index 15b96d394a..60fd2fa79b 100644 --- a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs +++ b/osu.Game.Tests/Visual/TestCasePlaybackControl.cs @@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual Size = new Vector2(200,100) }; - Beatmap.Value = new TestWorkingBeatmap(new Beatmap()); + Beatmap.Value = new TestWorkingBeatmap(new Beatmap(), Clock); Child = playback; } diff --git a/osu.Game.Tests/Visual/TestCasePollingComponent.cs b/osu.Game.Tests/Visual/TestCasePollingComponent.cs index 68c44c7758..63f4f88948 100644 --- a/osu.Game.Tests/Visual/TestCasePollingComponent.cs +++ b/osu.Game.Tests/Visual/TestCasePollingComponent.cs @@ -56,6 +56,7 @@ namespace osu.Game.Tests.Visual }); [Test] + [Ignore("polling is threaded, and it's very hard to hook into it correctly")] public void TestInstantPolling() { createPoller(true); @@ -106,8 +107,11 @@ namespace osu.Game.Tests.Visual private void checkCount(int checkValue) { - Logger.Log($"value is {count}"); - AddAssert($"count is {checkValue}", () => count == checkValue); + AddAssert($"count is {checkValue}", () => + { + Logger.Log($"value is {count}"); + return count == checkValue; + }); } private void createPoller(bool instant) => AddStep("create poller", () => diff --git a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs b/osu.Game.Tests/Visual/TestCaseScoreCounter.cs index e4e80e4017..3519ea67a6 100644 --- a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseScoreCounter.cs @@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual AddStep(@"Hit! :D", delegate { - score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0); + score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current.Value > 0 ? comboCounter.Current.Value - 1 : 0) / 25.0); comboCounter.Increment(); numerator++; denominator++; diff --git a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs index 7202861833..531c01158b 100644 --- a/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs +++ b/osu.Game.Tests/Visual/TestCaseScreenBreadcrumbControl.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual }, }; - breadcrumbs.Current.ValueChanged += s => titleText.Text = $"Changed to {s.ToString()}"; + breadcrumbs.Current.ValueChanged += screen => titleText.Text = $"Changed to {screen.NewValue.ToString()}"; breadcrumbs.Current.TriggerChange(); waitForCurrent(); diff --git a/osu.Game.Tests/Visual/TestCaseStoryboard.cs b/osu.Game.Tests/Visual/TestCaseStoryboard.cs index a4ad213116..fc62b8fe0c 100644 --- a/osu.Game.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Game.Tests/Visual/TestCaseStoryboard.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -58,15 +59,15 @@ namespace osu.Game.Tests.Visual Beatmap.ValueChanged += beatmapChanged; } - private void beatmapChanged(WorkingBeatmap working) - => loadStoryboard(working); + private void beatmapChanged(ValueChangedEvent e) + => loadStoryboard(e.NewValue); private void restart() { var track = Beatmap.Value.Track; track.Reset(); - loadStoryboard(Beatmap); + loadStoryboard(Beatmap.Value); track.Start(); } @@ -78,7 +79,7 @@ namespace osu.Game.Tests.Visual var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; storyboardContainer.Clock = decoupledClock; - storyboard = working.Storyboard.CreateDrawable(Beatmap); + storyboard = working.Storyboard.CreateDrawable(Beatmap.Value); storyboard.Passing = false; storyboardContainer.Add(storyboard); diff --git a/osu.Game.Tests/Visual/TestCaseTabControl.cs b/osu.Game.Tests/Visual/TestCaseTabControl.cs index 82f56cb0f8..ebf8f3bb30 100644 --- a/osu.Game.Tests/Visual/TestCaseTabControl.cs +++ b/osu.Game.Tests/Visual/TestCaseTabControl.cs @@ -33,9 +33,9 @@ namespace osu.Game.Tests.Visual filter.PinItem(GroupMode.All); filter.PinItem(GroupMode.RecentlyPlayed); - filter.Current.ValueChanged += newFilter => + filter.Current.ValueChanged += grouping => { - text.Text = "Currently Selected: " + newFilter.ToString(); + text.Text = "Currently Selected: " + grouping.NewValue.ToString(); }; } } diff --git a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs index 14f178a293..3ee617e092 100644 --- a/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/TestCaseUpdateableBeatmapBackgroundSprite.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; diff --git a/osu.Game.Tests/Visual/TestCaseWaveContainer.cs b/osu.Game.Tests/Visual/TestCaseWaveContainer.cs index 56dcfc3cbb..07a282a1a7 100644 --- a/osu.Game.Tests/Visual/TestCaseWaveContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseWaveContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Text = @"Wave Container", }, }, diff --git a/osu.Game/Audio/PreviewTrackManager.cs b/osu.Game/Audio/PreviewTrackManager.cs index 6de7d0e4f7..99c0d70ac9 100644 --- a/osu.Game/Audio/PreviewTrackManager.cs +++ b/osu.Game/Audio/PreviewTrackManager.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.IO.Stores; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 21739f16c2..2b559d5912 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -206,7 +206,17 @@ namespace osu.Game.Beatmaps PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. - Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); + Task.Factory.StartNew(() => + { + try + { + request.Perform(api); + } + catch (Exception e) + { + // no need to handle here as exceptions will filter down to request.Failure above. + } + }, TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); return true; } diff --git a/osu.Game/Beatmaps/BindableBeatmap.cs b/osu.Game/Beatmaps/BindableBeatmap.cs index ca03aac685..657dc06297 100644 --- a/osu.Game/Beatmaps/BindableBeatmap.cs +++ b/osu.Game/Beatmaps/BindableBeatmap.cs @@ -6,12 +6,12 @@ using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Audio; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Beatmaps { /// - /// A for the beatmap. + /// A for the beatmap. /// This should be used sparingly in-favour of . /// public abstract class BindableBeatmap : NonNullableBindable @@ -34,7 +34,7 @@ namespace osu.Game.Beatmaps this.audioManager = audioManager; - ValueChanged += registerAudioTrack; + ValueChanged += b => registerAudioTrack(b.NewValue); // If the track has changed prior to this being called, let's register it if (Value != Default) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs index 5e20ca8bc8..72b5f69eee 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetOnlineStatusPill.cs @@ -4,6 +4,7 @@ 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.Graphics; @@ -31,8 +32,8 @@ namespace osu.Game.Beatmaps.Drawables public float TextSize { - get => statusText.TextSize; - set => statusText.TextSize = value; + get => statusText.Font.Size; + set => statusText.Font = statusText.Font.With(size: value); } public MarginPadding TextPadding @@ -58,7 +59,7 @@ namespace osu.Game.Beatmaps.Drawables { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold) }, }; diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index d1d30a7c29..4d07fd234b 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps.Drawables public UpdateableBeatmapBackgroundSprite() { - Beatmap.BindValueChanged(b => Model = b); + Beatmap.BindValueChanged(b => Model = b.NewValue); } protected override Drawable CreateDrawable(BeatmapInfo model) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 18ff97e079..2e36d87024 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -2,16 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Audio.Track; -using osu.Framework.Configuration; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; -using System.Linq; using osu.Game.Storyboards; using osu.Framework.IO.File; using System.IO; +using System.Linq; using System.Threading; +using osu.Framework.Bindables; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -36,7 +36,7 @@ namespace osu.Game.Beatmaps BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - Mods.ValueChanged += mods => applyRateAdjustments(); + Mods.ValueChanged += _ => applyRateAdjustments(); beatmap = new RecyclableLazy(() => { diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs index e218f31f83..f547a7d3e1 100644 --- a/osu.Game/Configuration/DatabasedConfigManager.cs +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Game.Rulesets; @@ -60,9 +61,9 @@ namespace osu.Game.Configuration databasedSettings.Add(setting); } - bindable.ValueChanged += v => + bindable.ValueChanged += b => { - setting.Value = v; + setting.Value = b.NewValue; settings.Update(setting); }; } diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 613efe1801..1260a524b4 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -33,14 +33,14 @@ namespace osu.Game.Configuration Set(OsuSetting.Username, string.Empty); Set(OsuSetting.Token, string.Empty); - Set(OsuSetting.SavePassword, false).ValueChanged += val => + Set(OsuSetting.SavePassword, false).ValueChanged += enabled => { - if (val) Set(OsuSetting.SaveUsername, true); + if (enabled.NewValue) Set(OsuSetting.SaveUsername, true); }; - Set(OsuSetting.SaveUsername, true).ValueChanged += val => + Set(OsuSetting.SaveUsername, true).ValueChanged += enabled => { - if (!val) Set(OsuSetting.SavePassword, false); + if (!enabled.NewValue) Set(OsuSetting.SavePassword, false); }; Set(OsuSetting.ExternalLinkWarning, true); diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index b929217ae4..621eeea2b7 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -3,7 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; diff --git a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs index d23568e6be..a5b5b7af42 100644 --- a/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs +++ b/osu.Game/Graphics/Containers/HoldToConfirmContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 3c4d94e970..bf48631569 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -4,9 +4,9 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osuTK; -using osu.Framework.Configuration; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Audio; @@ -90,7 +90,7 @@ namespace osu.Game.Graphics.Containers switch (visibility) { case Visibility.Visible: - if (OverlayActivationMode != OverlayActivation.Disabled) + if (OverlayActivationMode.Value != OverlayActivation.Disabled) { if (PlaySamplesOnStateChange) samplePopIn?.Play(); } diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index f7d30dc109..f65a0a469a 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -6,8 +6,8 @@ using osu.Framework.Graphics; using osu.Framework.Input; using osuTK; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Game.Configuration; -using osu.Framework.Configuration; using osu.Framework.MathUtils; namespace osu.Game.Graphics.Containers @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.Containers parallaxEnabled = config.GetBindable(OsuSetting.MenuParallax); parallaxEnabled.ValueChanged += delegate { - if (!parallaxEnabled) + if (!parallaxEnabled.Value) { content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); content.Scale = new Vector2(1 + System.Math.Abs(ParallaxAmount)); @@ -65,7 +65,7 @@ namespace osu.Game.Graphics.Containers { base.Update(); - if (parallaxEnabled) + if (parallaxEnabled.Value) { Vector2 offset = (input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.Position) - DrawSize / 2) * ParallaxAmount; diff --git a/osu.Game/Graphics/Containers/ScalingContainer.cs b/osu.Game/Graphics/Containers/ScalingContainer.cs index a20c17cc8e..51f068d920 100644 --- a/osu.Game/Graphics/Containers/ScalingContainer.cs +++ b/osu.Game/Graphics/Containers/ScalingContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; @@ -74,10 +74,10 @@ namespace osu.Game.Graphics.Containers } } - private void scaleChanged(float value) + private void scaleChanged(ValueChangedEvent args) { - this.ScaleTo(new Vector2(value), 500, Easing.Out); - this.ResizeTo(new Vector2(1 / value), 500, Easing.Out); + this.ScaleTo(new Vector2(args.NewValue), 500, Easing.Out); + this.ResizeTo(new Vector2(1 / args.NewValue), 500, Easing.Out); } } @@ -108,7 +108,7 @@ namespace osu.Game.Graphics.Containers sizableContainer.FinishTransforms(); } - private bool requiresBackgroundVisible => (scalingMode == ScalingMode.Everything || scalingMode == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); + private bool requiresBackgroundVisible => (scalingMode.Value == ScalingMode.Everything || scalingMode.Value == ScalingMode.ExcludeOverlays) && (sizeX.Value != 1 || sizeY.Value != 1); private void updateSize() { @@ -137,8 +137,8 @@ namespace osu.Game.Graphics.Containers bool scaling = targetMode == null || scalingMode.Value == targetMode; - var targetSize = scaling ? new Vector2(sizeX, sizeY) : Vector2.One; - var targetPosition = scaling ? new Vector2(posX, posY) * (Vector2.One - targetSize) : Vector2.Zero; + var targetSize = scaling ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One; + var targetPosition = scaling ? new Vector2(posX.Value, posY.Value) * (Vector2.One - targetSize) : Vector2.Zero; bool requiresMasking = scaling && targetSize != Vector2.One; if (requiresMasking) diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 00014385c7..b8ea4e299c 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -3,7 +3,7 @@ using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 76c2345cd5..6e6f5f351e 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -3,7 +3,6 @@ using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using System; using JetBrains.Annotations; +using osu.Framework.Bindables; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; using osuTK.Input; @@ -80,7 +80,7 @@ namespace osu.Game.Graphics.Cursor activeCursor.AdditiveLayer.FadeInFromZero(800, Easing.OutQuint); } - if (e.Button == MouseButton.Left && cursorRotate) + if (e.Button == MouseButton.Left && cursorRotate.Value) { dragRotationState = DragRotationState.DragStarted; positionMouseDown = e.MousePosition; @@ -156,7 +156,7 @@ namespace osu.Game.Graphics.Cursor }; cursorScale = config.GetBindable(OsuSetting.MenuCursorSize); - cursorScale.ValueChanged += newScale => cursorContainer.Scale = new Vector2((float)newScale * base_scale); + cursorScale.ValueChanged += scale => cursorContainer.Scale = new Vector2((float)scale.NewValue * base_scale); cursorScale.TriggerChange(); } } diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 8f451054ac..ec4cbb808e 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -46,8 +46,6 @@ namespace osu.Game.Graphics.Cursor } } - private const float text_size = 16; - public OsuTooltip() { AutoSizeEasing = Easing.OutQuint; @@ -69,9 +67,8 @@ namespace osu.Game.Graphics.Cursor }, text = new OsuSpriteText { - TextSize = text_size, Padding = new MarginPadding(5), - Font = @"Exo2.0-Regular", + Font = OsuFont.GetFont(weight: FontWeight.Regular) } }; } diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index be1c9e0cfc..fc5abcdcb8 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -30,8 +30,7 @@ namespace osu.Game.Graphics public DrawableDate(DateTimeOffset date) { - Font = "Exo2.0-RegularItalic"; - + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true); Date = date; } diff --git a/osu.Game/Graphics/OsuFont.cs b/osu.Game/Graphics/OsuFont.cs new file mode 100644 index 0000000000..dc660fd159 --- /dev/null +++ b/osu.Game/Graphics/OsuFont.cs @@ -0,0 +1,117 @@ +// 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; + +namespace osu.Game.Graphics +{ + public struct OsuFont + { + /// + /// The default font size. + /// + public const float DEFAULT_FONT_SIZE = 16; + + /// + /// The default font. + /// + public static FontUsage Default => GetFont(); + + public static FontUsage Numeric => GetFont(Typeface.Venera, weight: FontWeight.Regular); + + /// + /// 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(Typeface typeface = Typeface.Exo, 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(Typeface typeface) + { + switch (typeface) + { + case Typeface.Exo: + return "Exo2.0"; + case Typeface.FontAwesome: + return "FontAwesome"; + case Typeface.Venera: + return "Venera"; + } + + return null; + } + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// The . + /// The string representation of in the specified . + public static string GetWeightString(Typeface typeface, FontWeight weight) + => GetWeightString(GetFamilyString(typeface), weight); + + /// + /// Retrieves the string representation of a . + /// + /// The . + /// 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 class OsuFontExtensions + { + /// + /// Creates a new by applying adjustments to this . + /// + /// The font typeface. If null, the value is copied from this . + /// The text size. If null, the value is copied from this . + /// The font weight. If null, the value is copied from this . + /// Whether the font is italic. If null, the value is copied from this . + /// Whether all characters should be spaced apart the same distance. If null, the value is copied from this . + /// The resulting . + public static FontUsage With(this FontUsage usage, Typeface? typeface = null, float? size = null, FontWeight? weight = null, bool? italics = null, bool? fixedWidth = null) + { + string familyString = typeface != null ? OsuFont.GetFamilyString(typeface.Value) : usage.Family; + string weightString = weight != null ? OsuFont.GetWeightString(familyString, weight.Value) : usage.Weight; + + return usage.With(familyString, size, weightString, italics, fixedWidth); + } + } + + public enum Typeface + { + Exo, + FontAwesome, + Venera, + } + + public enum FontWeight + { + Light, + Regular, + Medium, + SemiBold, + Bold, + Black + } +} diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index ef4209f6f3..a2ac71de93 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -127,7 +127,7 @@ namespace osu.Game.Graphics { base.Update(); - if (cursorVisibility == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) + if (cursorVisibility.Value == false && Interlocked.CompareExchange(ref screenShotTasks, 0, 0) == 0) cursorVisibility.Value = true; } diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index a0c025f4fa..ed771bb03f 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -9,12 +9,10 @@ namespace osu.Game.Graphics.Sprites { public class OsuSpriteText : SpriteText { - public const float FONT_SIZE = 16; - public OsuSpriteText() { Shadow = true; - TextSize = FONT_SIZE; + Font = OsuFont.Default; } } diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index b9196adda3..e40168d213 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -27,12 +27,12 @@ namespace osu.Game.Graphics.UserInterface { Height = 32; TabContainer.Spacing = new Vector2(padding, 0f); - Current.ValueChanged += tab => + Current.ValueChanged += index => { foreach (var t in TabContainer.Children.OfType()) { var tIndex = TabContainer.IndexOf(t); - var tabIndex = TabContainer.IndexOf(TabMap[tab]); + var tabIndex = TabContainer.IndexOf(TabMap[index.NewValue]); t.State = tIndex < tabIndex ? Visibility.Hidden : Visibility.Visible; t.Chevron.FadeTo(tIndex <= tabIndex ? 0f : 1f, 500, Easing.OutQuint); @@ -82,7 +82,7 @@ namespace osu.Game.Graphics.UserInterface public BreadcrumbTabItem(T value) : base(value) { - Text.TextSize = 18; + Text.Font = Text.Font.With(size: 18); Text.Margin = new MarginPadding { Vertical = 8 }; Padding = new MarginPadding { Right = padding + item_chevron_size }; Add(Chevron = new SpriteIcon diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 644f66a92d..2796db51a5 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.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 osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -12,7 +13,6 @@ using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Graphics.Containers; -using osu.Framework.Configuration; using osu.Framework.Input.Events; namespace osu.Game.Graphics.UserInterface @@ -141,8 +141,7 @@ namespace osu.Game.Graphics.UserInterface Text = Text, Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 28, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(size: 28, weight: FontWeight.Bold), Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.1f), Colour = Color4.White, @@ -197,18 +196,10 @@ namespace osu.Game.Graphics.UserInterface } } - private float textSize = 28; public float TextSize { - get - { - return textSize; - } - set - { - textSize = value; - spriteText.TextSize = value; - } + get => spriteText.Font.Size; + set => spriteText.Font = spriteText.Font.With(size: value); } public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => backgroundContainer.ReceivePositionalInputAt(screenSpacePos); @@ -242,9 +233,9 @@ namespace osu.Game.Graphics.UserInterface Selected.Value = false; } - private void selectionChanged(bool isSelected) + private void selectionChanged(ValueChangedEvent args) { - if (isSelected) + if (args.NewValue) { spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 0405a09a78..470297a83c 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -5,7 +5,7 @@ using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -41,9 +41,9 @@ namespace osu.Game.Graphics.UserInterface }, }; - Current.ValueChanged += newValue => + Current.ValueChanged += filled => { - if (newValue) + if (filled.NewValue) fill.FadeIn(200, Easing.OutQuint); else fill.FadeTo(0.01f, 200, Easing.OutQuint); //todo: remove once we figure why containers aren't drawing at all times diff --git a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs index 9d9f95662b..d64068f74c 100644 --- a/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuAnimatedButton.cs @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) { - Enabled.BindValueChanged(enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); + Enabled.BindValueChanged(enabled => this.FadeColour(enabled.NewValue ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 6ba461ad70..7a27f825f6 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -46,13 +47,13 @@ namespace osu.Game.Graphics.UserInterface new HoverClickSounds(HoverSampleSet.Loud), }); - Enabled.ValueChanged += enabled_ValueChanged; + Enabled.ValueChanged += enabledChanged; Enabled.TriggerChange(); } - private void enabled_ValueChanged(bool enabled) + private void enabledChanged(ValueChangedEvent e) { - this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } protected override bool OnHover(HoverEvent e) @@ -84,7 +85,7 @@ namespace osu.Game.Graphics.UserInterface Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold) }; } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index b71bdcc593..9f5fc503ad 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -4,7 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -86,9 +86,9 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - Current.ValueChanged += newValue => + Current.ValueChanged += enabled => { - if (newValue) + if (enabled.NewValue) sampleChecked?.Play(); else sampleUnchecked?.Play(); diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 0a1dfe8c41..7fcefee23a 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -149,7 +149,7 @@ namespace osu.Game.Graphics.UserInterface { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = text_size, + Font = OsuFont.GetFont(size: text_size), Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, }, BoldText = new OsuSpriteText @@ -158,8 +158,7 @@ namespace osu.Game.Graphics.UserInterface Alpha = 0, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), Margin = new MarginPadding { Horizontal = margin_horizontal, Vertical = MARGIN_VERTICAL }, } }; diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index c66a20a115..3fd0ead760 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - CurrentNumber.BindValueChanged(updateTooltipText, true); + CurrentNumber.BindValueChanged(current => updateTooltipText(current.NewValue), true); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 7089b7a79a..2db0325813 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -6,7 +6,7 @@ using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -107,7 +107,7 @@ namespace osu.Game.Graphics.UserInterface set { accentColour = value; - if (!Active) + if (!Active.Value) Text.Colour = value; } } @@ -128,14 +128,14 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - if (!Active) + if (!Active.Value) fadeActive(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - if (!Active) + if (!Active.Value) fadeInactive(); } @@ -159,7 +159,7 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = (value as IHasDescription)?.Description ?? (value as Enum)?.GetDescription() ?? value.ToString(), - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, Bar = new Box { @@ -173,7 +173,7 @@ namespace osu.Game.Graphics.UserInterface new HoverClickSounds() }; - Active.BindValueChanged(val => Text.Font = val ? @"Exo2.0-Bold" : @"Exo2.0", true); + Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } protected override void OnActivated() => fadeActive(); diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 0626534307..b56b9ec18f 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -31,7 +31,7 @@ namespace osu.Game.Graphics.UserInterface { accentColour = value; - if (Current) + if (Current.Value) { text.Colour = AccentColour; icon.Colour = AccentColour; @@ -67,7 +67,7 @@ namespace osu.Game.Graphics.UserInterface protected override void OnHoverLost(HoverLostEvent e) { - if (!Current) + if (!Current.Value) fadeOut(); base.OnHoverLost(e); @@ -94,11 +94,7 @@ namespace osu.Game.Graphics.UserInterface Direction = FillDirection.Horizontal, Children = new Drawable[] { - text = new OsuSpriteText - { - TextSize = 14, - Font = @"Exo2.0-Bold", - }, + text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, icon = new SpriteIcon { Size = new Vector2(14), @@ -118,9 +114,9 @@ namespace osu.Game.Graphics.UserInterface } }; - Current.ValueChanged += v => + Current.ValueChanged += selected => { - if (v) + if (selected.NewValue) { fadeIn(); icon.Icon = FontAwesome.fa_check_circle_o; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index a481edb06b..21cdfbf5af 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.UserInterface protected override SpriteText CreatePlaceholder() => new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(italics: true), Colour = new Color4(180, 180, 180, 255), Margin = new MarginPadding { Left = 2 }, }; @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.UserInterface base.OnFocusLost(e); } - protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), TextSize = CalculatedTextSize }; + protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; public virtual bool OnPressed(GlobalAction action) { diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index 904951da0e..cc3415e9d2 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -45,7 +45,7 @@ namespace osu.Game.Graphics.UserInterface Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Text = (value as Enum)?.GetDescription() ?? value.ToString(), - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, box = new Box { @@ -59,7 +59,7 @@ namespace osu.Game.Graphics.UserInterface new HoverClickSounds() }; - Active.BindValueChanged(val => Text.Font = val ? @"Exo2.0-Bold" : @"Exo2.0", true); + Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } [BackgroundDependencyLoader] @@ -70,14 +70,14 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { - if (!Active) + if (!Active.Value) slideActive(); return true; } protected override void OnHoverLost(HoverLostEvent e) { - if (!Active) + if (!Active.Value) slideInactive(); } diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 9205525af3..8254bdda7c 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface public PercentageCounter() { - DisplayedCountSpriteText.FixedWidth = true; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(fixedWidth: true); Current.Value = DisplayedCount = 1.0f; } @@ -41,7 +41,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index 6e261a8fa7..52cd69a76e 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -1,13 +1,13 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using System; using System.Collections.Generic; +using osu.Framework.Bindables; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface @@ -61,16 +61,11 @@ namespace osu.Game.Graphics.UserInterface public abstract void Increment(T amount); - private float textSize; public float TextSize { - get { return textSize; } - set - { - textSize = value; - DisplayedCountSpriteText.TextSize = value; - } + get => DisplayedCountSpriteText.Font.Size; + set => DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(size: value); } public Color4 AccentColour @@ -86,20 +81,17 @@ namespace osu.Game.Graphics.UserInterface { Children = new Drawable[] { - DisplayedCountSpriteText = new OsuSpriteText - { - Font = @"Venera" - }, + DisplayedCountSpriteText = new OsuSpriteText { Font = OsuFont.Numeric } }; TextSize = 40; AutoSizeAxes = Axes.Both; - DisplayedCount = Current; + DisplayedCount = Current.Value; - Current.ValueChanged += newValue => + Current.ValueChanged += val => { - if (IsLoaded) TransformCount(displayedCount, newValue); + if (IsLoaded) TransformCount(displayedCount, val.NewValue); }; } @@ -107,7 +99,7 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - DisplayedCountSpriteText.Text = FormatCount(Current); + DisplayedCountSpriteText.Text = FormatCount(Current.Value); } /// @@ -126,7 +118,7 @@ namespace osu.Game.Graphics.UserInterface public virtual void StopRolling() { FinishTransforms(false, nameof(DisplayedCount)); - DisplayedCount = Current; + DisplayedCount = Current.Value; } /// diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 944993d99c..63062cdc9d 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface /// How many leading zeroes the counter will have. public ScoreCounter(uint leading = 0) { - DisplayedCountSpriteText.FixedWidth = true; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(fixedWidth: true); LeadingZeroes = leading; } @@ -52,7 +52,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(double amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs index 6e01c69df5..f564a4b5a8 100644 --- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs @@ -19,7 +19,7 @@ namespace osu.Game.Graphics.UserInterface onPushed(null, stack.CurrentScreen); - Current.ValueChanged += newScreen => newScreen.MakeCurrent(); + Current.ValueChanged += current => current.NewValue.MakeCurrent(); } private void onPushed(IScreen lastScreen, IScreen newScreen) diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index b0657e707e..4717401c75 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -33,7 +33,7 @@ namespace osu.Game.Graphics.UserInterface public override void Increment(int amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index 31fe29fc3a..2375017878 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -27,7 +27,7 @@ namespace osu.Game.Graphics.UserInterface }); } - public IEnumerable FilterTerms => new[] { Text }; + public virtual IEnumerable FilterTerms => new[] { Text }; public bool MatchingFilter { diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs index ab010a9532..91e2456ef7 100644 --- a/osu.Game/Input/IdleTracker.cs +++ b/osu.Game/Input/IdleTracker.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 48b9b8a6d5..9e84fd6009 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -8,7 +8,7 @@ using System.Net; using System.Net.Http; using System.Threading; using Newtonsoft.Json.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Configuration; @@ -64,7 +64,7 @@ namespace osu.Game.Online.API thread.Start(); } - private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); + private void onTokenChanged(ValueChangedEvent e) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); private readonly List components = new List(); diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 600192cb85..096ab5d8c8 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Users; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index ca60506da9..e4533ecb3d 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Users; namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index ffe63e68ea..baf494ebf9 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Net.Http; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.IO.Network; namespace osu.Game.Online.API diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index c60c1e44ee..9ec39c5cb1 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Lists; using osu.Game.Users; diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs index ded7920cc1..8c6422afe3 100644 --- a/osu.Game/Online/Chat/ChannelManager.cs +++ b/osu.Game/Online/Chat/ChannelManager.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -55,7 +55,7 @@ namespace osu.Game.Online.Chat { CurrentChannel.ValueChanged += currentChannelChanged; - HighPollRate.BindValueChanged(high => TimeBetweenPolls = high ? 1000 : 6000, true); + HighPollRate.BindValueChanged(enabled => TimeBetweenPolls = enabled.NewValue ? 1000 : 6000, true); } /// @@ -84,7 +84,7 @@ namespace osu.Game.Online.Chat ?? new Channel(user); } - private void currentChannelChanged(Channel channel) => JoinChannel(channel); + private void currentChannelChanged(ValueChangedEvent e) => JoinChannel(e.NewValue); /// /// Ensure we run post actions in sequence, once at a time. @@ -131,7 +131,7 @@ namespace osu.Game.Online.Chat target.AddLocalEcho(message); // if this is a PM and the first message, we need to do a special request to create the PM channel - if (target.Type == ChannelType.PM && !target.Joined) + if (target.Type == ChannelType.PM && !target.Joined.Value) { var createNewPrivateMessageRequest = new CreateNewPrivateMessageRequest(target.Users.First(), message); @@ -331,7 +331,7 @@ namespace osu.Game.Online.Chat switch (channel.Type) { case ChannelType.Public: - var req = new JoinChannelRequest(channel, api.LocalUser); + var req = new JoinChannelRequest(channel, api.LocalUser.Value); req.Success += () => JoinChannel(channel, true); req.Failure += ex => LeaveChannel(channel); api.Queue(req); @@ -363,7 +363,7 @@ namespace osu.Game.Online.Chat if (channel.Joined.Value) { - api.Queue(new LeaveChannelRequest(channel, api.LocalUser)); + api.Queue(new LeaveChannelRequest(channel, api.LocalUser.Value)); channel.Joined.Value = false; } } diff --git a/osu.Game/Online/Chat/ExternalLinkOpener.cs b/osu.Game/Online/Chat/ExternalLinkOpener.cs index a2c5a3cf8c..495f1ac0b0 100644 --- a/osu.Game/Online/Chat/ExternalLinkOpener.cs +++ b/osu.Game/Online/Chat/ExternalLinkOpener.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Platform; using osu.Game.Configuration; @@ -27,7 +27,7 @@ namespace osu.Game.Online.Chat public void OpenUrlExternally(string url) { - if (externalLinkWarning) + if (externalLinkWarning.Value) dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url))); else host.OpenUrlExternally(url); diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index a3bcc91e1e..3dbd174760 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -90,9 +90,9 @@ namespace osu.Game.Online.Chat return; if (text[0] == '/') - ChannelManager?.PostCommand(text.Substring(1), Channel); + ChannelManager?.PostCommand(text.Substring(1), Channel.Value); else - ChannelManager?.PostMessage(text, target: Channel); + ChannelManager?.PostMessage(text, target: Channel.Value); textbox.Text = string.Empty; } @@ -111,13 +111,13 @@ namespace osu.Game.Online.Chat protected virtual ChatLine CreateMessage(Message message) => new StandAloneMessage(message); - private void channelChanged(Channel channel) + private void channelChanged(ValueChangedEvent e) { drawableChannel?.Expire(); - if (channel == null) return; + if (e.NewValue == null) return; - AddInternal(drawableChannel = new StandAloneDrawableChannel(channel) + AddInternal(drawableChannel = new StandAloneDrawableChannel(e.NewValue) { CreateChatLineAction = CreateMessage, Padding = new MarginPadding { Bottom = postingTextbox ? textbox_height : 0 } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 7373924612..34981bf849 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -75,9 +76,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-MediumItalic", - TextSize = 22, - // ReSharper disable once ImpureMethodCallOnReadonlyValueField + Font = OsuFont.GetFont(size: 22, italics: true), Text = RankPosition.ToString(), }, }, @@ -137,8 +136,7 @@ namespace osu.Game.Online.Leaderboards nameLabel = new OsuSpriteText { Text = user.Username, - Font = @"Exo2.0-BoldItalic", - TextSize = 23, + Font = OsuFont.GetFont(size: 23, weight: FontWeight.Bold, italics: true) }, new FillFlowContainer { @@ -187,7 +185,7 @@ namespace osu.Game.Online.Leaderboards Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa")), + scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), OsuFont.Numeric.With(size: 23), Color4.White, OsuColour.FromHex(@"83ccfa")), RankContainer = new Container { Size = new Vector2(40f, 20f), @@ -275,7 +273,7 @@ namespace osu.Game.Online.Leaderboards private class GlowingSpriteText : Container { - public GlowingSpriteText(string text, string font, int textSize, Color4 textColour, Color4 glowColour) + public GlowingSpriteText(string text, FontUsage font, Color4 textColour, Color4 glowColour) { AutoSizeAxes = Axes.Both; @@ -296,9 +294,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - FixedWidth = true, - TextSize = textSize, + Font = font.With(fixedWidth: true), Text = text, Colour = glowColour, Shadow = false, @@ -309,9 +305,7 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = font, - FixedWidth = true, - TextSize = textSize, + Font = font.With(fixedWidth: true), Text = text, Colour = textColour, Shadow = false, @@ -369,7 +363,7 @@ namespace osu.Game.Online.Leaderboards }, }, }, - new GlowingSpriteText(statistic.Value, @"Exo2.0-Bold", 17, Color4.White, OsuColour.FromHex(@"83ccfa")) + new GlowingSpriteText(statistic.Value, OsuFont.GetFont(size: 17, weight: FontWeight.Bold), Color4.White, OsuColour.FromHex(@"83ccfa")) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, diff --git a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs index 441db0d922..d4256e4a9d 100644 --- a/osu.Game/Online/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Online/Leaderboards/MessagePlaceholder.cs @@ -14,7 +14,7 @@ namespace osu.Game.Online.Leaderboards { AddIcon(FontAwesome.fa_exclamation_circle, cp => { - cp.TextSize = TEXT_SIZE; + cp.Font = cp.Font.With(size: TEXT_SIZE); cp.Padding = new MarginPadding { Right = 10 }; }); diff --git a/osu.Game/Online/Leaderboards/Placeholder.cs b/osu.Game/Online/Leaderboards/Placeholder.cs index 72f9502753..d38110a9d0 100644 --- a/osu.Game/Online/Leaderboards/Placeholder.cs +++ b/osu.Game/Online/Leaderboards/Placeholder.cs @@ -12,7 +12,7 @@ namespace osu.Game.Online.Leaderboards protected const float TEXT_SIZE = 22; protected Placeholder() - : base(cp => cp.TextSize = TEXT_SIZE) + : base(cp => cp.Font = cp.Font.With(size: TEXT_SIZE)) { Anchor = Anchor.Centre; Origin = Anchor.Centre; diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 2dcc7369f9..77236ce3c8 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Online.Multiplayer.RoomStatuses; using osu.Game.Users; @@ -86,7 +86,7 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("participant_count")] private int? participantCount { - get => ParticipantCount; + get => ParticipantCount.Value; set => ParticipantCount.Value = value ?? 0; } @@ -106,7 +106,7 @@ namespace osu.Game.Online.Multiplayer [JsonProperty("max_attempts", DefaultValueHandling = DefaultValueHandling.Ignore)] private int? maxAttempts { - get => MaxAttempts; + get => MaxAttempts.Value; set => MaxAttempts.Value = value; } @@ -118,19 +118,19 @@ namespace osu.Game.Online.Multiplayer public void CopyFrom(Room other) { - RoomID.Value = other.RoomID; - Name.Value = other.Name; + RoomID.Value = other.RoomID.Value; + Name.Value = other.Name.Value; if (other.Host.Value != null && Host.Value?.Id != other.Host.Value.Id) - Host.Value = other.Host; + Host.Value = other.Host.Value; - Status.Value = other.Status; - Availability.Value = other.Availability; - Type.Value = other.Type; - MaxParticipants.Value = other.MaxParticipants; + Status.Value = other.Status.Value; + Availability.Value = other.Availability.Value; + Type.Value = other.Type.Value; + MaxParticipants.Value = other.MaxParticipants.Value; ParticipantCount.Value = other.ParticipantCount.Value; Participants.Value = other.Participants.Value.ToArray(); - EndDate.Value = other.EndDate; + EndDate.Value = other.EndDate.Value; if (DateTimeOffset.Now >= EndDate.Value) Status.Value = new RoomStatusEnded(); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7b4ff3d295..9f6adc373c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework.Audio; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -174,15 +175,17 @@ namespace osu.Game // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); - ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; + ruleset.ValueChanged += r => configRuleset.Value = r.NewValue.ID ?? 0; // bind config int to database SkinInfo configSkin = LocalConfig.GetBindable(OsuSetting.Skin); - SkinManager.CurrentSkinInfo.ValueChanged += s => configSkin.Value = s.ID; - configSkin.ValueChanged += id => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == id) ?? SkinInfo.Default; + SkinManager.CurrentSkinInfo.ValueChanged += skin => configSkin.Value = skin.NewValue.ID; + configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; configSkin.TriggerChange(); LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust); + + IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); } private ExternalLinkOpener externalLinkOpener; @@ -513,9 +516,9 @@ namespace osu.Game }; } - OverlayActivationMode.ValueChanged += v => + OverlayActivationMode.ValueChanged += mode => { - if (v != OverlayActivation.All) CloseAllOverlays(); + if (mode.NewValue != OverlayActivation.All) CloseAllOverlays(); }; void updateScreenOffset() @@ -674,16 +677,12 @@ namespace osu.Game private readonly BindableDouble inactiveVolumeAdjust = new BindableDouble(); - protected override void OnDeactivated() + private void updateActiveState(bool isActive) { - base.OnDeactivated(); - Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); - } - - protected override void OnActivated() - { - base.OnActivated(); - Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + if (isActive) + Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + else + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); } public bool OnReleased(GlobalAction action) => false; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index b6fe20b3a8..487ef10ffb 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Reflection; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; @@ -209,7 +209,7 @@ namespace osu.Game // TODO: This is temporary until we reimplement the local FPS display. // It's just to allow end-users to access the framework FPS display without knowing the shortcut key. fpsDisplayVisible = LocalConfig.GetBindable(OsuSetting.ShowFpsDisplay); - fpsDisplayVisible.ValueChanged += val => { FrameStatisticsMode = val ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; + fpsDisplayVisible.ValueChanged += visible => { FrameStatisticsMode = visible.NewValue ? FrameStatisticsMode.Minimal : FrameStatisticsMode.None; }; fpsDisplayVisible.TriggerChange(); } diff --git a/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs index bb436dbb2c..87ff4dd398 100644 --- a/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs +++ b/osu.Game/Overlays/AccountCreation/ErrorTextFlowContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Overlays.AccountCreation private readonly List errorDrawables = new List(); public ErrorTextFlowContainer() - : base(cp => { cp.TextSize = 12; }) + : base(cp => cp.Font = cp.Font.With(size: 12)) { } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 407d2cfbf1..2fc00edbc1 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -61,10 +61,10 @@ namespace osu.Game.Overlays.AccountCreation { new OsuSpriteText { - TextSize = 20, Margin = new MarginPadding { Vertical = 10 }, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 20), Text = "Let's create an account!", }, usernameTextBox = new OsuTextBox @@ -129,13 +129,13 @@ namespace osu.Game.Overlays.AccountCreation usernameDescription.AddText("This will be your public presence. No profanity, no impersonation. Avoid exposing your own personal details, too!"); emailAddressDescription.AddText("Will be used for notifications, account verification and in the case you forget your password. No spam, ever."); - emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = "Exo2.0-Bold"); + emailAddressDescription.AddText(" Make sure to get it right!", cp => cp.Font = cp.Font.With(Typeface.Exo, weight: FontWeight.Bold)); passwordDescription.AddText("At least "); characterCheckText = passwordDescription.AddText("8 characters long"); passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); - passwordTextBox.Current.ValueChanged += text => { characterCheckText.ForEach(s => s.Colour = text.Length == 0 ? Color4.White : Interpolation.ValueAt(text.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; + passwordTextBox.Current.ValueChanged += password => { characterCheckText.ForEach(s => s.Colour = password.NewValue.Length == 0 ? Color4.White : Interpolation.ValueAt(password.NewValue.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; } protected override void Update() diff --git a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs index 3cc84e3562..4e2cc1ea00 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWarning.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWarning.cs @@ -83,14 +83,13 @@ namespace osu.Game.Overlays.AccountCreation }, new OsuSpriteText { - TextSize = 28, - Font = "Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Colour = Color4.Red, + Font = OsuFont.GetFont(size: 28, weight: FontWeight.Light), Text = "Warning! 注意!", }, - multiAccountExplanationText = new OsuTextFlowContainer(cp => { cp.TextSize = 12; }) + multiAccountExplanationText = new OsuTextFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y @@ -106,7 +105,7 @@ namespace osu.Game.Overlays.AccountCreation Text = "I understand. This account isn't for me.", Action = () => this.Push(new ScreenEntry()) }, - furtherAssistance = new LinkFlowContainer(cp => { cp.TextSize = 12; }) + furtherAssistance = new LinkFlowContainer(cp => cp.Font = cp.Font.With(size: 12)) { Margin = new MarginPadding { Top = 20 }, Anchor = Anchor.TopCentre, diff --git a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs index d4b8323394..f6ddb135ec 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenWelcome.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Settings; using osu.Game.Screens.Menu; @@ -40,17 +41,16 @@ namespace osu.Game.Overlays.AccountCreation }, new OsuSpriteText { - TextSize = 24, - Font = "Exo2.0-Light", Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Text = "New Player Registration", }, new OsuSpriteText { - TextSize = 12, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 12), Text = "let's get you started", }, new SettingsButton diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index c9907014ca..8a75cfea50 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -11,6 +11,8 @@ using osuTK; using osuTK.Graphics; using osu.Game.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; namespace osu.Game.Overlays.BeatmapSet { @@ -47,8 +49,8 @@ namespace osu.Game.Overlays.BeatmapSet fields.Children = new Drawable[] { - new Field("mapped by", BeatmapSet.Metadata.Author.Username, @"Exo2.0-RegularItalic"), - new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold") + new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), + new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold)) { Margin = new MarginPadding { Top = 5 }, }, @@ -56,11 +58,11 @@ namespace osu.Game.Overlays.BeatmapSet if (online.Ranked.HasValue) { - fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold")); + fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); } else if (online.LastUpdated.HasValue) { - fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), @"Exo2.0-Bold")); + fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); } } @@ -105,7 +107,7 @@ namespace osu.Game.Overlays.BeatmapSet private class Field : FillFlowContainer { - public Field(string first, string second, string secondFont) + public Field(string first, string second, FontUsage secondFont) { AutoSizeAxes = Axes.Both; Direction = FillDirection.Horizontal; @@ -115,13 +117,12 @@ namespace osu.Game.Overlays.BeatmapSet new OsuSpriteText { Text = $"{first} ", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, new OsuSpriteText { Text = second, - TextSize = 13, - Font = secondFont, + Font = secondFont.With(size: 13) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index af5998bfa1..ac2e5497af 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -136,9 +136,8 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - TextSize = 13, - Font = @"Exo2.0-Bold", Margin = new MarginPadding { Left = 10 }, + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), }, }, }, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index c2edaf01ed..9f4ec0e814 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -107,15 +107,13 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 20, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) }, starRating = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 13, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), Text = "Star Difficulty", Alpha = 0, Margin = new MarginPadding { Bottom = 1 }, @@ -140,7 +138,7 @@ namespace osu.Game.Overlays.BeatmapSet Beatmap.ValueChanged += b => { - showBeatmap(b); + showBeatmap(b.NewValue); updateDifficultyButtons(); }; } @@ -309,8 +307,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-SemiBoldItalic", - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 4d46d41c0f..edd886f0f2 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { private readonly bool noVideo; - public string TooltipText => button.Enabled ? "Download this beatmap" : "Login to download"; + public string TooltipText => button.Enabled.Value ? "Download this beatmap" : "Login to download"; private readonly IBindable localUser = new Bindable(); @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, } }, - new DownloadProgressBar(BeatmapSet) + new DownloadProgressBar(BeatmapSet.Value) { Depth = -2, Anchor = Anchor.BottomLeft, @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons return; } - beatmaps.Download(BeatmapSet, noVideo); + beatmaps.Download(BeatmapSet.Value, noVideo); }; localUser.BindTo(api.LocalUser); @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons State.BindValueChanged(state => { - switch (state) + switch (state.NewValue) { case DownloadState.Downloading: textSprites.Children = new Drawable[] @@ -118,8 +118,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Downloading...", - TextSize = 13, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) }, }; break; @@ -129,8 +128,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Importing...", - TextSize = 13, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) }, }; break; @@ -143,14 +141,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Download", - TextSize = 13, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) }, new OsuSpriteText { Text = BeatmapSet.Value.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, - TextSize = 11, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold) }, }; this.FadeIn(200); @@ -159,8 +155,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, true); } - private void userChanged(User user) => button.Enabled.Value = !(user is GuestUser); + private void userChanged(ValueChangedEvent e) => button.Enabled.Value = !(e.NewValue is GuestUser); - private void enabledChanged(bool enabled) => this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + private void enabledChanged(ValueChangedEvent e) => this.FadeColour(e.NewValue ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs index b672e7bf07..7824a78a14 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -53,9 +53,9 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }); - Favourited.ValueChanged += value => + Favourited.ValueChanged += favourited => { - if (value) + if (favourited.NewValue) { pink.FadeIn(200); icon.Icon = FontAwesome.fa_heart; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs index 12b4a7e2d7..269342525b 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/PreviewButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }; Action = () => playButton.Click(); - Playing.ValueChanged += newValue => progress.FadeTo(newValue ? 1 : 0, 100); + Playing.ValueChanged += playing => progress.FadeTo(playing.NewValue ? 1 : 0, 100); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 8721a1ce5a..95cf9e9d04 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -115,8 +115,7 @@ namespace osu.Game.Overlays.BeatmapSet { title = new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", - TextSize = 37, + Font = OsuFont.GetFont(size: 37, weight: FontWeight.Bold, italics: true) }, externalLink = new ExternalLinkButton { @@ -126,11 +125,7 @@ namespace osu.Game.Overlays.BeatmapSet }, } }, - artist = new OsuSpriteText - { - Font = @"Exo2.0-SemiBoldItalic", - TextSize = 25, - }, + artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.SemiBold, italics: true) }, new Container { RelativeSizeAxes = Axes.X, @@ -181,8 +176,8 @@ namespace osu.Game.Overlays.BeatmapSet }, }; - Picker.Beatmap.ValueChanged += b => Details.Beatmap = b; - Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b?.Ruleset.ShortName}/{b?.OnlineBeatmapID}"; + Picker.Beatmap.ValueChanged += b => Details.Beatmap = b.NewValue; + Picker.Beatmap.ValueChanged += b => externalLink.Link = $@"https://osu.ppy.sh/beatmapsets/{BeatmapSet.Value?.OnlineBeatmapSetID}#{b.NewValue?.Ruleset.ShortName}/{b.NewValue?.OnlineBeatmapID}"; } [BackgroundDependencyLoader] @@ -192,16 +187,16 @@ namespace osu.Game.Overlays.BeatmapSet State.BindValueChanged(_ => updateDownloadButtons()); - BeatmapSet.BindValueChanged(beatmapSet => + BeatmapSet.BindValueChanged(setInfo => { - Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = beatmapSet; + Picker.BeatmapSet = author.BeatmapSet = Details.BeatmapSet = setInfo.NewValue; - title.Text = beatmapSet?.Metadata.Title ?? string.Empty; - artist.Text = beatmapSet?.Metadata.Artist ?? string.Empty; - onlineStatusPill.Status = beatmapSet?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; - cover.BeatmapSet = beatmapSet; + title.Text = setInfo.NewValue?.Metadata.Title ?? string.Empty; + artist.Text = setInfo.NewValue?.Metadata.Artist ?? string.Empty; + onlineStatusPill.Status = setInfo.NewValue?.OnlineInfo.Status ?? BeatmapSetOnlineStatus.None; + cover.BeatmapSet = setInfo.NewValue; - if (beatmapSet != null) + if (setInfo.NewValue != null) { downloadButtonsContainer.FadeIn(transition_duration); favouriteButton.FadeIn(transition_duration); @@ -219,11 +214,12 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDownloadButtons() { if (BeatmapSet.Value == null) return; + switch (State.Value) { case DownloadState.LocallyAvailable: // temporary for UX until new design is implemented. - downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet) + downloadButtonsContainer.Child = new osu.Game.Overlays.Direct.DownloadButton(BeatmapSet.Value) { Width = 50, RelativeSizeAxes = Axes.Y @@ -232,12 +228,12 @@ namespace osu.Game.Overlays.BeatmapSet case DownloadState.Downloading: case DownloadState.Downloaded: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); break; default: - downloadButtonsContainer.Child = new DownloadButton(BeatmapSet); + downloadButtonsContainer.Child = new DownloadButton(BeatmapSet.Value); if (BeatmapSet.Value.OnlineInfo.HasVideo) - downloadButtonsContainer.Add(new DownloadButton(BeatmapSet, true)); + downloadButtonsContainer.Add(new DownloadButton(BeatmapSet.Value, true)); break; } } diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 3a32abe9cc..b6793d2609 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -156,7 +156,7 @@ namespace osu.Game.Overlays.BeatmapSet this.FadeIn(transition_duration); textFlow.Clear(); - textFlow.AddText(value, s => s.TextSize = 14); + textFlow.AddText(value, s => s.Font = s.Font.With(size: 14)); } } @@ -177,8 +177,7 @@ namespace osu.Game.Overlays.BeatmapSet header = new OsuSpriteText { Text = title, - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Shadow = false, Margin = new MarginPadding { Top = 20 }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs index 0eb8b325d3..7933bfd9b6 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; @@ -30,21 +31,14 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public float TextSize { - set - { - if (text.TextSize == value) return; - text.TextSize = value; - } - get { return text.TextSize; } + get => text.Font.Size; + set => text.Font = text.Font.With(size: value); } public ClickableUsername() { AutoSizeAxes = Axes.Both; - Child = text = new OsuSpriteText - { - Font = @"Exo2.0-BoldItalic", - }; + Child = text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }; } [BackgroundDependencyLoader(true)] diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 1f50385adc..c6c8315aeb 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Text = $"#{index + 1}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Left = side_margin } }, new DrawableFlag(score.User.Country) @@ -87,17 +87,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, Text = $@"{score.TotalScore:N0}", - Font = @"Venera", + Font = OsuFont.Numeric.With(fixedWidth: true), RelativePositionAxes = Axes.X, X = 0.75f, - FixedWidth = true, }, new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreRight, Text = $@"{score.Accuracy:P2}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), RelativePositionAxes = Axes.X, X = 0.85f }, @@ -106,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}", - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Right = side_margin } }, }; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index c9551cf6f8..c64bda9dfd 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -117,8 +117,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.TopRight, Origin = Anchor.BottomRight, Text = "#1", - TextSize = 40, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 40, weight: FontWeight.Bold, italics: true), Y = height / 4, Margin = new MarginPadding { Right = margin } }, @@ -222,15 +221,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { headerText = new OsuSpriteText { - TextSize = 14, Text = header, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }, - valueText = new OsuSpriteText - { - TextSize = 25, - Font = @"Exo2.0-RegularItalic", - } + valueText = new OsuSpriteText { Font = OsuFont.GetFont(size: 25, weight: FontWeight.Regular, italics: true) } }; } diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 28902561f4..0a844028fe 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Success Rate", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, successRate = new Bar { @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopRight, Origin = Anchor.TopCentre, - TextSize = 13, + Font = OsuFont.GetFont(size: 13), }, }, graphLabel = new OsuSpriteText @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Points of Failure", - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Margin = new MarginPadding { Vertical = 20 }, }, }, diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 1237b17214..ff8603c749 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -103,8 +103,8 @@ namespace osu.Game.Overlays header.Picker.Beatmap.ValueChanged += b => { - info.Beatmap = b; - scores.Beatmap = b; + info.Beatmap = b.NewValue; + scores.Beatmap = b.NewValue; }; } diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 3e2ef07ef2..a679f33e3a 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -87,9 +87,8 @@ namespace osu.Game.Overlays.Chat Drawable effectedUsername = username = new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) }; if (hasBackground) @@ -138,9 +137,7 @@ namespace osu.Game.Overlays.Chat { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-SemiBold", - FixedWidth = true, - TextSize = TextSize * 0.75f, + Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.Bold, fixedWidth: true) }, new MessageSender(message.Sender) { @@ -162,13 +159,13 @@ namespace osu.Game.Overlays.Chat { if (Message.IsAction) { - t.Font = @"Exo2.0-MediumItalic"; + t.Font = OsuFont.GetFont(italics: true); if (senderHasBackground) t.Colour = OsuColour.FromHex(message.Sender.Colour); } - t.TextSize = TextSize; + t.Font = t.Font.With(size: TextSize); }) { AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs index 23dedf251f..1dd888a3e9 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelListItem.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -54,7 +54,7 @@ namespace osu.Game.Overlays.Chat.Selection RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Action = () => { (channel.Joined ? OnRequestLeave : OnRequestJoin)?.Invoke(channel); }; + Action = () => { (channel.Joined.Value ? OnRequestLeave : OnRequestJoin)?.Invoke(channel); }; Children = new Drawable[] { @@ -89,8 +89,7 @@ namespace osu.Game.Overlays.Chat.Selection name = new OsuSpriteText { Text = channel.ToString(), - TextSize = text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold), Shadow = false, }, }, @@ -106,8 +105,7 @@ namespace osu.Game.Overlays.Chat.Selection topic = new OsuSpriteText { Text = channel.Topic, - TextSize = text_size, - Font = @"Exo2.0-SemiBold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.SemiBold), Shadow = false, }, }, @@ -130,8 +128,7 @@ namespace osu.Game.Overlays.Chat.Selection new OsuSpriteText { Text = @"0", - TextSize = text_size, - Font = @"Exo2.0-SemiBold", + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.SemiBold), Shadow = false, }, }, @@ -148,7 +145,7 @@ namespace osu.Game.Overlays.Chat.Selection joinedColour = colours.Blue; hoverColour = colours.Yellow; - joinedBind.ValueChanged += updateColour; + joinedBind.ValueChanged += joined => updateColour(joined.NewValue); joinedBind.BindTo(channel.Joined); joinedBind.TriggerChange(); diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs index 2af416f7c0..160bf05a2b 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSection.cs @@ -7,6 +7,7 @@ using System.Linq; using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; @@ -48,8 +49,7 @@ namespace osu.Game.Overlays.Chat.Selection { header = new OsuSpriteText { - TextSize = 15, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, ChannelFlow = new FillFlowContainer { diff --git a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs index 00de5fd5fd..feb47b9e8e 100644 --- a/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/Selection/ChannelSelectionOverlay.cs @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Chat.Selection new OsuSpriteText { Text = @"Chat Channels", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Shadow = false, }, search = new HeaderSearchTextBox @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Chat.Selection }, }; - search.Current.ValueChanged += newValue => sectionsFlow.SearchTerm = newValue; + search.Current.ValueChanged += term => sectionsFlow.SearchTerm = term.NewValue; } public void UpdateAvailableChannels(IEnumerable channels) diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs index d7d299a2cf..6ac6133fd0 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelSelectorTabItem.cs @@ -20,8 +20,8 @@ namespace osu.Game.Overlays.Chat.Tabs Icon.Alpha = 0; - Text.TextSize = 45; - TextBold.TextSize = 45; + Text.Font = Text.Font.With(size: 45); + TextBold.Font = Text.Font.With(size: 45); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs index ccf4af651b..7a43ca4b8c 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabControl.cs @@ -7,9 +7,9 @@ using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Chat; using osuTK; -using osu.Framework.Configuration; using System; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Chat.Tabs { @@ -110,7 +110,7 @@ namespace osu.Game.Overlays.Chat.Tabs if (tab == SelectedTab && totalTabs > 1) // Select the tab after tab-to-be-removed's index, or the tab before if current == last SelectTab(TabContainer[currentIndex == totalTabs ? currentIndex - 1 : currentIndex + 1]); - else if (totalTabs == 1 && !selectorTab.Active) + else if (totalTabs == 1 && !selectorTab.Active.Value) // Open channel selection overlay if all channel tabs will be closed after removing this tab SelectTab(selectorTab); diff --git a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs index 7acd56c864..95c5fbf8fa 100644 --- a/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/ChannelTabItem.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Chat.Tabs Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), - TextSize = 18, + Font = OsuFont.GetFont(size: 18) }, TextBold = new OsuSpriteText { @@ -99,8 +99,7 @@ namespace osu.Game.Overlays.Chat.Tabs Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = value.ToString(), - Font = @"Exo2.0-Bold", - TextSize = 18, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold) }, CloseButton = new TabCloseButton { @@ -127,7 +126,7 @@ namespace osu.Game.Overlays.Chat.Tabs if (IsRemovable && ShowCloseOnHover) CloseButton.FadeIn(200, Easing.OutQuint); - if (!Active) + if (!Active.Value) box.FadeColour(backgroundHover, TRANSITION_LENGTH, Easing.OutQuint); return true; } @@ -158,7 +157,7 @@ namespace osu.Game.Overlays.Chat.Tabs private void updateState() { - if (Active) + if (Active.Value) FadeActive(); else FadeInactive(); diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 821c942a57..5428279325 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -6,7 +6,7 @@ using System.Linq; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -162,8 +162,8 @@ namespace osu.Game.Overlays }, }; - channelTabControl.Current.ValueChanged += chat => channelManager.CurrentChannel.Value = chat; - channelTabControl.ChannelSelectorActive.ValueChanged += value => channelSelectionOverlay.State = value ? Visibility.Visible : Visibility.Hidden; + channelTabControl.Current.ValueChanged += current => channelManager.CurrentChannel.Value = current.NewValue; + channelTabControl.ChannelSelectorActive.ValueChanged += active => channelSelectionOverlay.State = active.NewValue ? Visibility.Visible : Visibility.Hidden; channelSelectionOverlay.StateChanged += state => { if (state == Visibility.Hidden && channelManager.CurrentChannel.Value == null) @@ -189,9 +189,9 @@ namespace osu.Game.Overlays channelSelectionOverlay.OnRequestLeave = channel => channelManager.LeaveChannel(channel); } - private void currentChannelChanged(Channel channel) + private void currentChannelChanged(ValueChangedEvent e) { - if (channel == null) + if (e.NewValue == null) { textbox.Current.Disabled = true; currentChannelContainer.Clear(false); @@ -199,18 +199,18 @@ namespace osu.Game.Overlays return; } - textbox.Current.Disabled = channel.ReadOnly; + textbox.Current.Disabled = e.NewValue.ReadOnly; - if (channelTabControl.Current.Value != channel) - Scheduler.Add(() => channelTabControl.Current.Value = channel); + if (channelTabControl.Current.Value != e.NewValue) + Scheduler.Add(() => channelTabControl.Current.Value = e.NewValue); - var loaded = loadedChannels.Find(d => d.Channel == channel); + var loaded = loadedChannels.Find(d => d.Channel == e.NewValue); if (loaded == null) { currentChannelContainer.FadeOut(500, Easing.OutQuint); loading.Show(); - loaded = new DrawableChannel(channel); + loaded = new DrawableChannel(e.NewValue); loadedChannels.Add(loaded); LoadComponentAsync(loaded, l => { @@ -328,11 +328,11 @@ namespace osu.Game.Overlays private void load(OsuConfigManager config, OsuColour colours, ChannelManager channelManager) { ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); - ChatHeight.ValueChanged += h => + ChatHeight.ValueChanged += height => { - chatContainer.Height = (float)h; - channelSelectionContainer.Height = 1f - (float)h; - tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200); + chatContainer.Height = (float)height.NewValue; + channelSelectionContainer.Height = 1f - (float)height.NewValue; + tabBackground.FadeTo(height.NewValue == 1 ? 1 : 0.8f, 200); }; ChatHeight.TriggerChange(); diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index bf98d6ec49..781d1a5b7e 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -171,7 +171,7 @@ namespace osu.Game.Overlays.Dialog }, }, }, - header = new OsuTextFlowContainer(t => t.TextSize = 25) + header = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 25)) { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, @@ -180,7 +180,7 @@ namespace osu.Game.Overlays.Dialog Padding = new MarginPadding(15), TextAnchor = Anchor.TopCentre, }, - body = new OsuTextFlowContainer(t => t.TextSize = 18) + body = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 18)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 4ee6ff9698..d6ac51b2d6 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -75,13 +75,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - TextSize = 18, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)), - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }, }, }, @@ -127,15 +126,14 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = "mapped by ", - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Shadow = false, Colour = colours.Gray5, }, new OsuSpriteText { Text = SetInfo.Metadata.Author.Username, - TextSize = 14, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true), Shadow = false, Colour = colours.BlueDark, }, @@ -150,7 +148,7 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = SetInfo.Metadata.Source, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Shadow = false, Colour = colours.Gray5, Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, @@ -239,6 +237,6 @@ namespace osu.Game.Overlays.Direct updateStatusContainer(); } - private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying ? 0 : 1, 120, Easing.InOutQuint); + private void updateStatusContainer() => statusContainer.FadeTo(IsHovered || PreviewPlaying.Value ? 0 : 1, 120, Easing.InOutQuint); } } diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index cb74ae54a6..7bf372dff7 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -95,13 +95,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)), - TextSize = 18, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)), - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true) }, } }, @@ -161,13 +160,12 @@ namespace osu.Game.Overlays.Direct new OsuSpriteText { Text = "mapped by ", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, new OsuSpriteText { Text = SetInfo.Metadata.Author.Username, - TextSize = 14, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) }, }, }, @@ -176,7 +174,7 @@ namespace osu.Game.Overlays.Direct Text = SetInfo.Metadata.Source, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, }, }, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index f8f6fd9b53..d7eae000b8 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -88,7 +88,7 @@ namespace osu.Game.Overlays.Direct { base.Update(); - if (PreviewPlaying && Preview != null && Preview.TrackLoaded) + if (PreviewPlaying.Value && Preview != null && Preview.TrackLoaded) { PreviewBar.Width = (float)(Preview.CurrentTime / Preview.Length); } @@ -108,7 +108,7 @@ namespace osu.Game.Overlays.Direct { content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); content.MoveToY(0, hover_transition_time, Easing.OutQuint); - if (FadePlayButton && !PreviewPlaying) + if (FadePlayButton && !PreviewPlaying.Value) PlayButton.FadeOut(120, Easing.InOutQuint); base.OnHoverLost(e); @@ -127,8 +127,11 @@ namespace osu.Game.Overlays.Direct base.LoadComplete(); this.FadeInFromZero(200, Easing.Out); - PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); - PreviewPlaying.ValueChanged += newValue => PreviewBar.FadeTo(newValue ? 1 : 0, 120, Easing.InOutQuint); + PreviewPlaying.ValueChanged += playing => + { + PlayButton.FadeTo(playing.NewValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); + PreviewBar.FadeTo(playing.NewValue ? 1 : 0, 120, Easing.InOutQuint); + }; } protected List GetDifficultyIcons() @@ -173,10 +176,7 @@ namespace osu.Game.Overlays.Direct Children = new Drawable[] { - text = new OsuSpriteText - { - Font = @"Exo2.0-SemiBoldItalic", - }, + text = new OsuSpriteText { Font = OsuFont.GetFont(weight: FontWeight.SemiBold, italics: true) }, new SpriteIcon { Icon = icon, diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 201a79f58a..f15413d522 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.Direct { base.LoadComplete(); - State.BindValueChanged(updateState, true); + State.BindValueChanged(state => updateState(state.NewValue), true); FinishTransforms(true); } @@ -85,10 +85,10 @@ namespace osu.Game.Overlays.Direct shakeContainer.Shake(); break; case DownloadState.LocallyAvailable: - game.PresentBeatmap(BeatmapSet); + game.PresentBeatmap(BeatmapSet.Value); break; default: - beatmaps.Download(BeatmapSet, noVideo); + beatmaps.Download(BeatmapSet.Value, noVideo); break; } }; diff --git a/osu.Game/Overlays/Direct/DownloadProgressBar.cs b/osu.Game/Overlays/Direct/DownloadProgressBar.cs index 4ac1aba7f5..9c2b1e5b63 100644 --- a/osu.Game/Overlays/Direct/DownloadProgressBar.cs +++ b/osu.Game/Overlays/Direct/DownloadProgressBar.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Direct State.BindValueChanged(state => { - switch (state) + switch (state.NewValue) { case DownloadState.NotDownloaded: progressBar.Current.Value = 0; diff --git a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs index d9eb827834..58be491daf 100644 --- a/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs +++ b/osu.Game/Overlays/Direct/DownloadTrackingComposite.cs @@ -4,7 +4,7 @@ using System; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Online.API.Requests; @@ -37,14 +37,14 @@ namespace osu.Game.Overlays.Direct { this.beatmaps = beatmaps; - BeatmapSet.BindValueChanged(set => + BeatmapSet.BindValueChanged(setInfo => { - if (set == null) + if (setInfo.NewValue == null) attachDownload(null); - else if (beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID).Any()) + else if (beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == setInfo.NewValue.OnlineBeatmapSetID).Any()) State.Value = DownloadState.LocallyAvailable; else - attachDownload(beatmaps.GetExistingDownload(set)); + attachDownload(beatmaps.GetExistingDownload(setInfo.NewValue)); }, true); beatmaps.BeatmapDownloadBegan += download => diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index f1ae435c73..d7e0760fc6 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Direct { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; - Ruleset.Value = ruleset ?? rulesets.GetRuleset(0); + Ruleset.Value = ruleset.Value ?? rulesets.GetRuleset(0); foreach (var r in rulesets.AvailableRulesets) modeButtons.Add(new RulesetToggleButton(Ruleset, r)); } @@ -68,9 +68,9 @@ namespace osu.Game.Overlays.Direct private readonly ConstrainedIconContainer iconContainer; - private void Bindable_ValueChanged(RulesetInfo obj) + private void Bindable_ValueChanged(ValueChangedEvent e) { - iconContainer.FadeTo(Ruleset.ID == obj?.ID ? 1f : 0.5f, 100); + iconContainer.FadeTo(Ruleset.ID == e.NewValue?.ID ? 1f : 0.5f, 100); } public override bool HandleNonPositionalInput => !bindable.Disabled && base.HandleNonPositionalInput; @@ -93,7 +93,7 @@ namespace osu.Game.Overlays.Direct Ruleset = ruleset; bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(bindable.Value); + Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); Action = () => bindable.Value = Ruleset; } diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs index 267590f19a..d1478cf3b6 100644 --- a/osu.Game/Overlays/Direct/Header.cs +++ b/osu.Game/Overlays/Direct/Header.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Direct protected override Color4 BackgroundColour => OsuColour.FromHex(@"252f3a"); protected override DirectTab DefaultTab => DirectTab.Search; - protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", TextSize = 25 }; + protected override Drawable CreateHeaderText() => new OsuSpriteText { Text = @"osu!direct", Font = OsuFont.GetFont(size: 25) }; protected override FontAwesome Icon => FontAwesome.fa_osu_chevron_down_o; public Header() diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 5e3ad3344e..e001c2d3ea 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -112,12 +112,12 @@ namespace osu.Game.Overlays.Direct base.OnHoverLost(e); } - private void playingStateChanged(bool playing) + private void playingStateChanged(ValueChangedEvent e) { - icon.Icon = playing ? FontAwesome.fa_stop : FontAwesome.fa_play; - icon.FadeColour(playing || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); + icon.Icon = e.NewValue ? FontAwesome.fa_stop : FontAwesome.fa_play; + icon.FadeColour(e.NewValue || IsHovered ? hoverColour : Color4.White, 120, Easing.InOutQuint); - if (playing) + if (e.NewValue) { if (BeatmapSet == null) { @@ -144,7 +144,7 @@ namespace osu.Game.Overlays.Direct preview.Stopped += () => Playing.Value = false; // user may have changed their mind. - if (Playing) + if (Playing.Value) preview.Start(); }); } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 7dd59bf0bc..d3881b6ef8 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; @@ -105,12 +105,11 @@ namespace osu.Game.Overlays new OsuSpriteText { Text = "Found ", - TextSize = 15, + Font = OsuFont.GetFont(size: 15) }, resultCountsText = new OsuSpriteText { - TextSize = 15, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold) }, } }, @@ -118,7 +117,7 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (text != string.Empty) + if (text.NewValue != string.Empty) { Header.Tabs.Current.Value = DirectTab.Search; @@ -133,13 +132,13 @@ namespace osu.Game.Overlays Filter.Tabs.Current.Value = DirectSortCriteria.Ranked; } }; - ((FilterControl)Filter).Ruleset.ValueChanged += ruleset => Scheduler.AddOnce(updateSearch); - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + ((FilterControl)Filter).Ruleset.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); Header.Tabs.Current.ValueChanged += tab => { - if (tab != DirectTab.Search) + if (tab.NewValue != DirectTab.Search) { currentQuery.Value = string.Empty; Filter.Tabs.Current.Value = (DirectSortCriteria)Header.Tabs.Current.Value; @@ -147,11 +146,11 @@ namespace osu.Game.Overlays } }; - currentQuery.ValueChanged += v => + currentQuery.ValueChanged += text => { queryChangedDebounce?.Cancel(); - if (string.IsNullOrEmpty(v)) + if (string.IsNullOrEmpty(text.NewValue)) Scheduler.AddOnce(updateSearch); else { @@ -164,9 +163,9 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); - Filter.Tabs.Current.ValueChanged += sortCriteria => + Filter.Tabs.Current.ValueChanged += tab => { - if (Header.Tabs.Current.Value != DirectTab.Search && sortCriteria != (DirectSortCriteria)Header.Tabs.Current.Value) + if (Header.Tabs.Current.Value != DirectTab.Search && tab.NewValue != (DirectSortCriteria)Header.Tabs.Current.Value) Header.Tabs.Current.Value = DirectTab.Search; Scheduler.AddOnce(updateSearch); @@ -274,9 +273,6 @@ namespace osu.Game.Overlays if (api == null) return; - if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) - return; - previewTrackManager.StopAnyPlaying(this); getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value ?? string.Empty, diff --git a/osu.Game/Overlays/HoldToConfirmOverlay.cs b/osu.Game/Overlays/HoldToConfirmOverlay.cs index 2854fdab50..154aff605a 100644 --- a/osu.Game/Overlays/HoldToConfirmOverlay.cs +++ b/osu.Game/Overlays/HoldToConfirmOverlay.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays } }; - Progress.ValueChanged += v => overlay.Alpha = (float)v; + Progress.ValueChanged += p => overlay.Alpha = (float)p.NewValue; } } } diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 3dad94c8fa..8a8ad0d964 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -349,8 +349,7 @@ namespace osu.Game.Overlays.KeyBinding }, Text = new OsuSpriteText { - Font = "Venera", - TextSize = 10, + Font = OsuFont.Numeric.With(size: 10), Margin = new MarginPadding(5), Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index d0382a4264..300563dc59 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -73,8 +73,7 @@ namespace osu.Game.Overlays Anchor = Anchor.Centre, Origin = Anchor.Centre, Y = 15, - TextSize = 12, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Text = @"back", }, } diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a7579b4d4b..2dedef8fb2 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -63,8 +63,7 @@ namespace osu.Game.Overlays.MedalSplash Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Medal Unlocked".ToUpperInvariant(), - TextSize = 24, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Alpha = 0f, Scale = new Vector2(1f / scale_when_unlocked), }, @@ -84,8 +83,7 @@ namespace osu.Game.Overlays.MedalSplash Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = medal.Name, - TextSize = 20, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold), Alpha = 0f, Scale = new Vector2(1f / scale_when_full), }, @@ -107,7 +105,7 @@ namespace osu.Game.Overlays.MedalSplash { s.Anchor = Anchor.TopCentre; s.Origin = Anchor.TopCentre; - s.TextSize = 16; + s.Font = s.Font.With(size: 16); }); medalContainer.OnLoadComplete = d => diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index e1fb8674de..f9cc19419c 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -14,6 +14,7 @@ using System; using System.Linq; using osu.Framework.Graphics.Cursor; using osu.Framework.Input.Events; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Mods @@ -275,7 +276,7 @@ namespace osu.Game.Overlays.Mods Y = 75, Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - TextSize = 18, + Font = OsuFont.GetFont(size: 18) }, new HoverClickSounds() }; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 0530f812e3..bf9efa75ea 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -11,6 +11,7 @@ using System; using System.Linq; using System.Collections.Generic; using osu.Framework.Input.Events; +using osu.Game.Graphics; namespace osu.Game.Overlays.Mods { @@ -123,7 +124,7 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopLeft, Anchor = Anchor.TopLeft, Position = new Vector2(0f, 0f), - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold) }, ButtonsContainer = new FillFlowContainer { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 386dd01ebd..f6cccdef5f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -4,7 +4,6 @@ using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -17,6 +16,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; @@ -74,28 +74,28 @@ namespace osu.Game.Overlays.Mods SelectedMods.UnbindAll(); } - private void rulesetChanged(RulesetInfo newRuleset) + private void rulesetChanged(ValueChangedEvent e) { - if (newRuleset == null) return; + if (e.NewValue == null) return; - var instance = newRuleset.CreateInstance(); + var instance = e.NewValue.CreateInstance(); foreach (ModSection section in ModSectionsContainer.Children) section.Mods = instance.GetModsFor(section.ModType); // attempt to re-select any already selected mods. // this may be the first time we are receiving the ruleset, in which case they will still match. - selectedModsChanged(SelectedMods.Value); + selectedModsChanged(new ValueChangedEvent>(SelectedMods.Value, SelectedMods.Value)); // write the mods back to the SelectedMods bindable in the case a change was not applicable. // this generally isn't required as the previous line will perform deselection; just here for safety. refreshSelectedMods(); } - private void selectedModsChanged(IEnumerable obj) + private void selectedModsChanged(ValueChangedEvent> e) { foreach (ModSection section in ModSectionsContainer.Children) - section.SelectTypes(obj.Select(m => m.GetType()).ToList()); + section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList()); updateMods(); } @@ -264,9 +264,8 @@ namespace osu.Game.Overlays.Mods { new OsuSpriteText { - Font = @"Exo2.0-Bold", Text = @"Gameplay Mods", - TextSize = 22, + Font = OsuFont.GetFont(size: 22, weight: FontWeight.Bold), Shadow = true, Margin = new MarginPadding { @@ -275,7 +274,7 @@ namespace osu.Game.Overlays.Mods }, new OsuTextFlowContainer(text => { - text.TextSize = 18; + text.Font = text.Font.With(size: 18); text.Shadow = true; }) { @@ -365,7 +364,7 @@ namespace osu.Game.Overlays.Mods new OsuSpriteText { Text = @"Score Multiplier:", - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Margin = new MarginPadding { Top = 5, @@ -374,8 +373,7 @@ namespace osu.Game.Overlays.Mods }, MultiplierLabel = new OsuSpriteText { - Font = @"Exo2.0-Bold", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5 @@ -383,9 +381,8 @@ namespace osu.Game.Overlays.Mods }, UnrankedLabel = new OsuSpriteText { - Font = @"Exo2.0-Bold", Text = @"(Unranked)", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5, diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index c2c10d999f..6bceade271 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -8,6 +8,7 @@ using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; using System; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Music { @@ -44,7 +45,7 @@ namespace osu.Game.Overlays.Music Search.Current.ValueChanged += current_ValueChanged; } - private void current_ValueChanged(string newValue) => FilterChanged?.Invoke(newValue); + private void current_ValueChanged(ValueChangedEvent e) => FilterChanged?.Invoke(e.NewValue); public Action ExitRequested; diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 7c7b78afc7..65f02e1839 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -100,7 +100,7 @@ namespace osu.Game.Overlays.Music titleBind = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title))); artistBind = localisation.GetLocalisedString(new LocalisedString((metadata.ArtistUnicode, metadata.Artist))); - artistBind.BindValueChanged(newText => recreateText(), true); + artistBind.BindValueChanged(_ => recreateText(), true); } private void recreateText() @@ -108,16 +108,11 @@ namespace osu.Game.Overlays.Music text.Clear(); //space after the title to put a space between the title and artist - titleSprites = text.AddText(titleBind.Value + @" ", sprite => - { - sprite.TextSize = 16; - sprite.Font = @"Exo2.0-Regular"; - }).OfType(); + titleSprites = text.AddText(titleBind.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)).OfType(); text.AddText(artistBind.Value, sprite => { - sprite.TextSize = 14; - sprite.Font = @"Exo2.0-Bold"; + sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); sprite.Colour = artistColour; sprite.Padding = new MarginPadding { Top = 1 }; }); diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index b388bb1632..b02ad242aa 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 5b1b7f4da9..8cbea63fe3 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 5218edd7d5..ff6bb4ee1a 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -107,20 +107,18 @@ namespace osu.Game.Overlays Origin = Anchor.BottomCentre, Anchor = Anchor.TopCentre, Position = new Vector2(0, 40), - TextSize = 25, + Font = OsuFont.GetFont(size: 25, italics: true), Colour = Color4.White, Text = @"Nothing to play", - Font = @"Exo2.0-MediumItalic" }, artist = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Position = new Vector2(0, 45), - TextSize = 15, + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold, italics: true), Colour = Color4.White, Text = @"Nothing to play", - Font = @"Exo2.0-BoldItalic" }, new Container { @@ -317,13 +315,13 @@ namespace osu.Game.Overlays private WorkingBeatmap current; private TransformDirection? queuedDirection; - private void beatmapChanged(WorkingBeatmap beatmap) + private void beatmapChanged(ValueChangedEvent e) { TransformDirection direction = TransformDirection.None; if (current != null) { - bool audioEquals = beatmap?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; + bool audioEquals = e.NewValue?.BeatmapInfo?.AudioEquals(current.BeatmapInfo) ?? false; if (audioEquals) direction = TransformDirection.None; @@ -336,13 +334,13 @@ namespace osu.Game.Overlays { //figure out the best direction based on order in playlist. var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.BeatmapSetInfo?.ID).Count(); + var next = beatmap == null ? -1 : beatmapSets.TakeWhile(b => b.ID != e.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TransformDirection.Prev : TransformDirection.Next; } } - current = beatmap; + current = e.NewValue; progressBar.CurrentTime = 0; diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 1a23e0d8ef..55b1f04528 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Threading; namespace osu.Game.Overlays @@ -80,7 +80,7 @@ namespace osu.Game.Overlays private ScheduledDelegate notificationsEnabler; private void updateProcessingMode() { - bool enabled = OverlayActivationMode == OverlayActivation.All || State == Visibility.Visible; + bool enabled = OverlayActivationMode.Value == OverlayActivation.All || State == Visibility.Visible; notificationsEnabler?.Cancel(); diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index afbacfac52..6b0e17a482 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -102,13 +102,13 @@ namespace osu.Game.Overlays.Notifications titleText = new OsuSpriteText { Text = title.ToUpperInvariant(), - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black) }, countText = new OsuSpriteText { Text = "3", Colour = colours.Yellow, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black) }, } }, diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index cf7b716665..efb66a7153 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -115,10 +115,7 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.Both, }); - Content.Add(textDrawable = new OsuTextFlowContainer(t => - { - t.TextSize = 16; - }) + Content.Add(textDrawable = new OsuTextFlowContainer { Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index 283a412b2a..91dab14a62 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Notifications } }); - Content.Add(textDrawable = new OsuTextFlowContainer(t => t.TextSize = 14) + Content.Add(textDrawable = new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 14)) { Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 42031ee07e..5e45fbf081 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -69,16 +69,14 @@ namespace osu.Game.Overlays textLine1 = new OsuSpriteText { Padding = new MarginPadding(10), - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), Spacing = new Vector2(1, 0), - TextSize = 14, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, textLine2 = new OsuSpriteText { - TextSize = 24, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 24, weight: FontWeight.Light), Padding = new MarginPadding { Left = 10, Right = 10 }, Anchor = Anchor.Centre, Origin = Anchor.BottomCentre, @@ -105,8 +103,7 @@ namespace osu.Game.Overlays Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Margin = new MarginPadding { Bottom = 15 }, - Font = @"Exo2.0-Bold", - TextSize = 12, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Alpha = 0.3f, }, } diff --git a/osu.Game/Overlays/Profile/Components/GradeBadge.cs b/osu.Game/Overlays/Profile/Components/GradeBadge.cs index 4280f89cdf..ca56780663 100644 --- a/osu.Game/Overlays/Profile/Components/GradeBadge.cs +++ b/osu.Game/Overlays/Profile/Components/GradeBadge.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Profile.Components @@ -36,8 +37,7 @@ namespace osu.Game.Overlays.Profile.Components { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - TextSize = 14, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) }); } diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index 56cceae79c..ff4d7a10dc 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -53,11 +53,10 @@ namespace osu.Game.Overlays.Profile.Header { badgeCountText = new OsuSpriteText { - Alpha = 0, - TextSize = 12, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Font = "Exo2.0-Regular" + Alpha = 0, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular) }, new Container { diff --git a/osu.Game/Overlays/Profile/Header/RankGraph.cs b/osu.Game/Overlays/Profile/Header/RankGraph.cs index 09880f044c..05161de4c0 100644 --- a/osu.Game/Overlays/Profile/Header/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/RankGraph.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -44,30 +44,26 @@ namespace osu.Game.Overlays.Profile.Header Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "No recent plays", - TextSize = 14, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Regular, italics: true) }, rankText = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = primary_textsize + Font = OsuFont.GetFont(size: primary_textsize, weight: FontWeight.Regular, italics: true), }, relativeText = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: secondary_textsize, weight: FontWeight.Regular, italics: true), Y = 25, - TextSize = secondary_textsize }, performanceText = new OsuSpriteText { Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Font = @"Exo2.0-RegularItalic", - TextSize = secondary_textsize + Font = OsuFont.GetFont(size: secondary_textsize, weight: FontWeight.Regular, italics: true) }, graph = new RankChartLineGraph { @@ -91,11 +87,11 @@ namespace osu.Game.Overlays.Profile.Header graph.Colour = colours.Yellow; } - private void userChanged(User user) + private void userChanged(ValueChangedEvent e) { placeholder.FadeIn(fade_duration, Easing.Out); - if (user?.Statistics?.Ranks.Global == null) + if (e.NewValue?.Statistics?.Ranks.Global == null) { rankText.Text = string.Empty; performanceText.Text = string.Empty; @@ -105,7 +101,7 @@ namespace osu.Game.Overlays.Profile.Header return; } - int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Ranks.Global.Value }; + int[] userRanks = e.NewValue.RankHistory?.Data ?? new[] { e.NewValue.Statistics.Ranks.Global.Value }; ranks = userRanks.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray(); if (ranks.Length > 1) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 524b709a83..56e34cf296 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -118,8 +118,7 @@ namespace osu.Game.Overlays.Profile usernameText = new OsuSpriteText { Text = user.Username, - Font = @"Exo2.0-RegularItalic", - TextSize = 30, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, italics: true) }, new ExternalLinkButton($@"https://osu.ppy.sh/users/{user.Id}") { @@ -166,7 +165,7 @@ namespace osu.Game.Overlays.Profile Y = cover_height, Colour = OsuColour.Gray(34), }, - infoTextLeft = new LinkFlowContainer(t => t.TextSize = 14) + infoTextLeft = new LinkFlowContainer(t => t.Font = t.Font.With(size: 14)) { X = UserProfileOverlay.CONTENT_X_MARGIN, Y = cover_height + 20, @@ -175,11 +174,7 @@ namespace osu.Game.Overlays.Profile ParagraphSpacing = 0.8f, LineSpacing = 0.2f }, - infoTextRight = new LinkFlowContainer(t => - { - t.TextSize = 14; - t.Font = @"Exo2.0-RegularItalic"; - }) + infoTextRight = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Regular, italics: true)) { X = UserProfileOverlay.CONTENT_X_MARGIN + info_width + 20, Y = cover_height + 20, @@ -222,7 +217,7 @@ namespace osu.Game.Overlays.Profile Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Y = 11, - TextSize = 20 + Font = OsuFont.GetFont(size: 20) } } }, @@ -354,19 +349,18 @@ namespace osu.Game.Overlays.Profile colourBar.Show(); } - void boldItalic(SpriteText t) => t.Font = @"Exo2.0-BoldItalic"; + void boldItalic(SpriteText t) => t.Font = t.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true); void lightText(SpriteText t) => t.Alpha = 0.8f; OsuSpriteText createScoreText(string text) => new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = text }; OsuSpriteText createScoreNumberText(string text) => new OsuSpriteText { - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Text = text diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index f5f628f07b..6da736432f 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.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 osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,7 +10,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK.Graphics; -using osu.Framework.Configuration; namespace osu.Game.Overlays.Profile { @@ -35,8 +35,7 @@ namespace osu.Game.Overlays.Profile new OsuSpriteText { Text = Title, - TextSize = 20, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, @@ -67,8 +66,6 @@ namespace osu.Game.Overlays.Profile Add(new OsuSpriteText { Text = @"coming soon!", - TextSize = 16, - Font = @"Exo2.0-Medium", Colour = Color4.Gray, Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index 3b673ec004..64c8260524 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -48,15 +49,13 @@ namespace osu.Game.Overlays.Profile.Sections { Text = new LocalisedString(($"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ", $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")), - TextSize = 15, - Font = "Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true) }, new OsuSpriteText { Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - TextSize = 12, Padding = new MarginPadding { Top = 3 }, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) }, }, }; diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 8bceafb8f3..0fc1398f5d 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs index 942723479a..b0609e685e 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osuTK; @@ -47,7 +48,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical new OsuSpriteText { Text = @"mapped by ", - TextSize = 12, + Font = OsuFont.GetFont(size: 12) }, mapperContainer = new OsuHoverContainer { @@ -57,8 +58,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical new OsuSpriteText { Text = beatmap.Metadata.AuthorString, - TextSize = 12, - Font = @"Exo2.0-MediumItalic" + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Medium, italics: true) } } }, @@ -78,16 +78,14 @@ namespace osu.Game.Overlays.Profile.Sections.Historical Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Text = playCount.ToString(), - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic" + Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold, italics: true) }, new OsuSpriteText { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Text = @"times played ", - TextSize = 12, - Font = @"Exo2.0-RegularItalic" + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true) }, } }); diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 5ec252b109..4757f676c8 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index 33b74a6d93..9d60851f6e 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -1,9 +1,9 @@ // 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 osuTK; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -63,10 +63,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu } }; - this.user.ValueChanged += newUser => + this.user.ValueChanged += u => { - total.Count = newUser?.Kudosu.Total ?? 0; - avaliable.Count = newUser?.Kudosu.Available ?? 0; + total.Count = u.NewValue?.Kudosu.Total ?? 0; + avaliable.Count = u.NewValue?.Kudosu.Available ?? 0; }; } @@ -107,21 +107,19 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Text = header + ":", - TextSize = 20, - Font = @"Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular, italics: true) }, valueText = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Text = "0", - TextSize = 40, + Font = OsuFont.GetFont(size: 40, weight: FontWeight.Regular, italics: true), UseFullGlyphHeight = false, - Font = @"Exo2.0-RegularItalic" } } }, - new OsuTextFlowContainer(t => { t.TextSize = 19; }) + new OsuTextFlowContainer(t => t.Font = t.Font.With(size: 19)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 6439475a7b..7164bc7cd1 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -3,9 +3,10 @@ using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -43,9 +44,8 @@ namespace osu.Game.Overlays.Profile.Sections { new OsuSpriteText { - TextSize = 15, Text = header, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular, italics: true), Margin = new MarginPadding { Top = 10, Bottom = 10 }, }, ItemsContainer = new FillFlowContainer @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.Profile.Sections Origin = Anchor.TopCentre, Child = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = "show more", Padding = new MarginPadding {Vertical = 10, Horizontal = 15 }, } @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.Profile.Sections }, MissingText = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = missing, Alpha = 0, }, @@ -93,13 +93,13 @@ namespace osu.Game.Overlays.Profile.Sections User.TriggerChange(); } - private void onUserChanged(User newUser) + private void onUserChanged(ValueChangedEvent e) { VisiblePages = 0; ItemsContainer.Clear(); ShowMoreButton.Hide(); - if (newUser != null) + if (e.NewValue != null) ShowMore(); } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index c612169cfb..843f9b7ef2 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -28,8 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Text = $"{pp:0}pp", Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 18, - Font = "Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }); if (weight.HasValue) @@ -40,8 +39,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, - TextSize = 11, - Font = "Exo2.0-RegularItalic", + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Regular, italics: true) }); } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index 147b8dffca..f4e08b8db1 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -46,8 +46,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Colour = colour.GrayA, - TextSize = 11, - Font = "Exo2.0-RegularItalic" + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Regular, italics: true) }; RightFlowContainer.Add(text); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index 094d6032fd..8bfca08fe7 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; @@ -23,8 +24,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Text = Score.TotalScore.ToString("#,###"), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - TextSize = 18, - Font = "Exo2.0-BoldItalic", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold, italics: true) }); } } diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index a2676350a2..95a18ccfa9 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.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 osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.API.Requests; @@ -9,6 +8,7 @@ using osu.Game.Users; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Overlays.Profile.Sections.Ranks { diff --git a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs index a91aa78b70..7e721ac807 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/DrawableRecentActivity.cs @@ -42,7 +42,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent RightFlowContainer.Add(new DrawableDate(activity.CreatedAt) { - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Colour = OsuColour.Gray(0xAA), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index b7de719305..4b4acb8fbc 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -1,11 +1,11 @@ // 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.Configuration; using osu.Framework.Graphics; using osu.Game.Online.API.Requests; using osu.Game.Users; using System.Linq; +using osu.Framework.Bindables; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Profile.Sections.Recent diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs index f5ec6c296a..f55e5f8c59 100644 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs @@ -1,8 +1,8 @@ // 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 osuTK; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -78,13 +78,13 @@ namespace osu.Game.Overlays.SearchableList }; bindable.ValueChanged += Bindable_ValueChanged; - Bindable_ValueChanged(bindable.Value); + Bindable_ValueChanged(new ValueChangedEvent(bindable.Value, bindable.Value)); Action = () => bindable.Value = this.style; } - private void Bindable_ValueChanged(PanelDisplayStyle style) + private void Bindable_ValueChanged(ValueChangedEvent e) { - icon.FadeTo(style == this.style ? 1.0f : 0.5f, 100); + icon.FadeTo(e.NewValue == style ? 1.0f : 0.5f, 100); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs index 6fff17ab26..39348a9ad7 100644 --- a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs +++ b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.SearchableList { public HeaderTabItem(T value) : base(value) { - Text.TextSize = 16; + Text.Font = Text.Font.With(size: 16); } } } diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 26c2f57f14..8ed196fd01 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -4,6 +4,7 @@ using System; using System.Runtime; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -34,8 +35,8 @@ namespace osu.Game.Overlays.Settings.Sections.Debug }; configLatencyMode = config.GetBindable(DebugSetting.ActiveGCMode); - configLatencyMode.BindValueChanged(v => latencyMode.Value = (LatencyMode)v, true); - latencyMode.BindValueChanged(v => configLatencyMode.Value = (GCLatencyMode)v); + configLatencyMode.BindValueChanged(mode => latencyMode.Value = (LatencyMode)mode.NewValue, true); + latencyMode.BindValueChanged(mode => configLatencyMode.Value = (GCLatencyMode)mode.NewValue); } private enum LatencyMode diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 4fad999577..4e1130690f 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -78,7 +78,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { Text = "ACCOUNT", Margin = new MarginPadding { Bottom = 5 }, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black), }, form = new LoginForm { @@ -134,8 +134,7 @@ namespace osu.Game.Overlays.Settings.Sections.General Anchor = Anchor.Centre, Origin = Anchor.Centre, Text = "Signed in", - TextSize = 18, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), Margin = new MarginPadding { Top = 5, Bottom = 5 }, }, }, @@ -152,9 +151,9 @@ namespace osu.Game.Overlays.Settings.Sections.General panel.Status.BindTo(api.LocalUser.Value.Status); - dropdown.Current.ValueChanged += newValue => + dropdown.Current.ValueChanged += action => { - switch (newValue) + switch (action.NewValue) { case UserAction.Online: api.LocalUser.Value.Status.Value = new UserStatusOnline(); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 9c5ef32251..628cdb944a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; @@ -127,9 +128,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = sizeFullscreen }; - windowModeDropdown.Bindable.BindValueChanged(windowMode => + windowModeDropdown.Bindable.BindValueChanged(mode => { - if (windowMode == WindowMode.Fullscreen) + if (mode.NewValue == WindowMode.Fullscreen) { resolutionDropdown.Show(); sizeFullscreen.TriggerChange(); @@ -142,12 +143,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics scalingMode.BindValueChanged(mode => { scalingSettings.ClearTransforms(); - scalingSettings.AutoSizeAxes = mode != ScalingMode.Off ? Axes.Y : Axes.None; + scalingSettings.AutoSizeAxes = mode.NewValue != ScalingMode.Off ? Axes.Y : Axes.None; - if (mode == ScalingMode.Off) + if (mode.NewValue == ScalingMode.Off) scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - scalingSettings.ForEach(s => s.TransferValueOnCommit = mode == ScalingMode.Everything); + scalingSettings.ForEach(s => s.TransferValueOnCommit = mode.NewValue == ScalingMode.Everything); }, true); } @@ -158,7 +159,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics /// A bindable which will propagate updates with a delay. private void bindPreviewEvent(Bindable bindable) { - bindable.ValueChanged += v => + bindable.ValueChanged += _ => { switch (scalingMode.Value) { diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index efe3d782ae..3f1e77d482 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input new SettingsButton { Text = "Key configuration", + TooltipText = "Change global shortcut keys and gameplay bindings", Action = keyConfig.ToggleVisibility }, }; diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 05b685a12b..4f2f3dfd1a 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Input; @@ -61,13 +62,13 @@ namespace osu.Game.Overlays.Settings.Sections.Input const string raw_mouse_handler = @"OsuTKRawMouseHandler"; const string standard_mouse_handler = @"OsuTKMouseHandler"; - ignoredInputHandler.Value = enabled ? standard_mouse_handler : raw_mouse_handler; + ignoredInputHandler.Value = enabled.NewValue ? standard_mouse_handler : raw_mouse_handler; }; ignoredInputHandler = config.GetBindable(FrameworkSetting.IgnoredInputHandlers); ignoredInputHandler.ValueChanged += handler => { - bool raw = !handler.Contains("Raw"); + bool raw = !handler.NewValue.Contains("Raw"); rawInputToggle.Value = raw; sensitivity.Bindable.Disabled = !raw; }; diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index 7361d671de..d1f47b6016 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -3,7 +3,7 @@ using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Graphics; @@ -76,8 +76,8 @@ namespace osu.Game.Overlays.Settings.Sections if (skinDropdown.Items.All(s => s.ID != configBindable.Value)) configBindable.Value = 0; - configBindable.BindValueChanged(v => dropdownBindable.Value = skinDropdown.Items.Single(s => s.ID == v), true); - dropdownBindable.BindValueChanged(v => configBindable.Value = v.ID); + configBindable.BindValueChanged(id => dropdownBindable.Value = skinDropdown.Items.Single(s => s.ID == id.NewValue), true); + dropdownBindable.BindValueChanged(skin => configBindable.Value = skin.NewValue.ID); } private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray()); diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 73cf855e18..ef98c28285 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,17 +1,33 @@ // 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 osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SettingsButton : TriangleButton + public class SettingsButton : TriangleButton, IHasTooltip { public SettingsButton() { RelativeSizeAxes = Axes.X; Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }; } + + public string TooltipText { get; set; } + + public override IEnumerable FilterTerms + { + get + { + if (TooltipText != null) + return base.FilterTerms.Append(TooltipText); + + return base.FilterTerms; + } + } } } diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index 7c50e2f254..e8c2c1ffe8 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -56,14 +56,13 @@ namespace osu.Game.Overlays.Settings Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = game.Name, - TextSize = 18, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Text = game.Version, Colour = DebugUtils.IsDebug ? colours.Red : Color4.White, }, diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index fceeec5166..fbf29f7ff5 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Settings new OsuSpriteText { Text = heading, - TextSize = 40, + Font = OsuFont.GetFont(size: 40), Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Settings { Colour = colours.Pink, Text = subheading, - TextSize = 18, + Font = OsuFont.GetFont(size: 18), Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index ed66408acd..de7e8bbd71 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -3,8 +3,8 @@ using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -119,8 +119,8 @@ namespace osu.Game.Overlays.Settings set { bindable = value; - bindable.ValueChanged += newValue => UpdateState(); - bindable.DisabledChanged += disabled => UpdateState(); + bindable.ValueChanged += _ => UpdateState(); + bindable.DisabledChanged += _ => UpdateState(); } } diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 4af9961ea8..cf8544af17 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Settings { new OsuSpriteText { - TextSize = header_size, + Font = OsuFont.GetFont(size: header_size), Text = Header, Colour = colours.Yellow, Margin = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 4d0b0de7f9..9a3eeac5d0 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -8,6 +8,7 @@ using osu.Game.Graphics.Sprites; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Game.Graphics; namespace osu.Game.Overlays.Settings { @@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Settings { Text = Header.ToUpperInvariant(), Margin = new MarginPadding { Bottom = 10, Left = SettingsOverlay.CONTENT_MARGINS, Right = SettingsOverlay.CONTENT_MARGINS }, - Font = @"Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black), }, FlowContent }); diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 802e97d92a..174d3a3de1 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -107,12 +107,12 @@ namespace osu.Game.Overlays SectionsContainer.SelectedSection.ValueChanged += section => { selectedSidebarButton.Selected = false; - selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section); + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section.NewValue); selectedSidebarButton.Selected = true; }; } - searchTextBox.Current.ValueChanged += newValue => SectionsContainer.SearchContainer.SearchTerm = newValue; + searchTextBox.Current.ValueChanged += term => SectionsContainer.SearchContainer.SearchTerm = term.NewValue; CreateSections()?.ForEach(AddSection); } diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index de738247ec..fb72051a41 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -32,13 +32,12 @@ namespace osu.Game.Overlays.Social new OsuSpriteText { Text = "social ", - TextSize = 25, + Font = OsuFont.GetFont(size: 25), }, browser = new OsuSpriteText { Text = "browser", - TextSize = 25, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(size: 25, weight: FontWeight.Light), }, }, }; diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 2f14446564..9ee255819a 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics; @@ -15,7 +16,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; -using osu.Framework.Configuration; using osu.Framework.Threading; namespace osu.Game.Overlays @@ -57,7 +57,7 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (!string.IsNullOrEmpty(text)) + if (!string.IsNullOrEmpty(text.NewValue)) { // force searching in players until searching for friends is supported Header.Tabs.Current.Value = SocialTab.AllPlayers; @@ -67,18 +67,18 @@ namespace osu.Game.Overlays } }; - Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); + Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); - Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; - Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue); + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); currentQuery.ValueChanged += query => { queryChangedDebounce?.Cancel(); - if (string.IsNullOrEmpty(query)) + if (string.IsNullOrEmpty(query.NewValue)) Scheduler.AddOnce(updateSearch); else queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 2dc9b15cc5..61b2014af8 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -10,7 +10,7 @@ using osu.Game.Graphics; using osuTK; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Input.Events; namespace osu.Game.Overlays.Toolbar @@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Toolbar { StateChanged += visibility => { - if (overlayActivationMode == OverlayActivation.Disabled) + if (overlayActivationMode.Value == OverlayActivation.Disabled) State = Visibility.Hidden; }; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 563411d833..32ab80d50f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -129,15 +129,13 @@ namespace osu.Game.Overlays.Toolbar Anchor = TooltipAnchor, Origin = TooltipAnchor, Shadow = true, - TextSize = 22, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 22, weight: FontWeight.Bold), }, tooltip2 = new OsuSpriteText { Anchor = TooltipAnchor, Origin = TooltipAnchor, Shadow = true, - TextSize = 16 } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 4b83e08292..2e1e2c0df8 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -47,11 +47,11 @@ namespace osu.Game.Overlays.Toolbar NotificationCount.ValueChanged += count => { - if (count == 0) + if (count.NewValue == 0) countDisplay.FadeOut(200, Easing.OutQuint); else { - countDisplay.Count = count; + countDisplay.Count = count.NewValue; countDisplay.FadeIn(200, Easing.OutQuint); } }; @@ -99,11 +99,10 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.Centre, Origin = Anchor.Centre, Y = -1, - TextSize = 14, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Padding = new MarginPadding(5), Colour = Color4.White, UseFullGlyphHeight = true, - Font = "Exo2.0-Bold", } }; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index 354a7b6b58..d01eab4dab 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -3,13 +3,13 @@ using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Input; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Rulesets; @@ -115,11 +115,11 @@ namespace osu.Game.Overlays.Toolbar Size = new Vector2(modeButtons.DrawSize.X, 1); } - private void rulesetChanged(RulesetInfo ruleset) + private void rulesetChanged(ValueChangedEvent e) { foreach (ToolbarRulesetButton m in modeButtons.Children.Cast()) { - bool isActive = m.Ruleset.ID == ruleset.ID; + bool isActive = m.Ruleset.ID == e.NewValue.ID; m.Active = isActive; if (isActive) activeButton = m; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 28a1d60c40..d47f3a7b16 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Online.API; using osu.Game.Users; using osuTK; @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Toolbar { AutoSizeAxes = Axes.X; - DrawableText.Font = @"Exo2.0-MediumItalic"; + DrawableText.Font = OsuFont.GetFont(italics: true); Add(new OpaqueBackground { Depth = 1 }); @@ -57,7 +58,7 @@ namespace osu.Game.Overlays.Toolbar break; case APIState.Online: Text = api.LocalUser.Value.Username; - avatar.User = api.LocalUser; + avatar.User = api.LocalUser.Value; break; } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index d897c6c299..80ed6128b8 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -126,16 +126,16 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both } }); - sectionsContainer.SelectedSection.ValueChanged += s => + sectionsContainer.SelectedSection.ValueChanged += section => { - if (lastSection != s) + if (lastSection != section.NewValue) { - lastSection = s; + lastSection = section.NewValue; tabs.Current.Value = lastSection; } }; - tabs.Current.ValueChanged += s => + tabs.Current.ValueChanged += section => { if (lastSection == null) { @@ -144,9 +144,9 @@ namespace osu.Game.Overlays tabs.Current.Value = lastSection; return; } - if (lastSection != s) + if (lastSection != section.NewValue) { - lastSection = s; + lastSection = section.NewValue; sectionsContainer.ScrollTo(lastSection); } }; diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index 2c46ed5517..6061ead2da 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -69,10 +69,10 @@ namespace osu.Game.Overlays.Volume } }); - Current.ValueChanged += newValue => + Current.ValueChanged += muted => { - icon.Icon = newValue ? FontAwesome.fa_volume_off : FontAwesome.fa_volume_up; - icon.Margin = new MarginPadding { Left = newValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths + icon.Icon = muted.NewValue ? FontAwesome.fa_volume_off : FontAwesome.fa_volume_up; + icon.Margin = new MarginPadding { Left = muted.NewValue ? width / 2 - 15 : width / 2 - 10 }; //Magic numbers to line up both icons because they're different widths }; Current.TriggerChange(); } diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index b7d13156de..da696e0fdd 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -4,7 +4,7 @@ using System; using System.Globalization; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -140,8 +140,7 @@ namespace osu.Game.Overlays.Volume { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = "Venera", - TextSize = 0.16f * circleSize + Font = OsuFont.Numeric.With(size: 0.16f * circleSize) }).WithEffect(new GlowEffect { Colour = Color4.Transparent, @@ -169,16 +168,16 @@ namespace osu.Game.Overlays.Volume { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = name } } } }; - Bindable.ValueChanged += newVolume => + Bindable.ValueChanged += volume => { this.TransformTo("DisplayVolume", - newVolume, + volume.NewValue, 400, Easing.OutQuint); }; @@ -218,7 +217,7 @@ namespace osu.Game.Overlays.Volume public double Volume { - get => Bindable; + get => Bindable.Value; private set => Bindable.Value = value; } diff --git a/osu.Game/Overlays/VolumeOverlay.cs b/osu.Game/Overlays/VolumeOverlay.cs index 95a1348941..e2e480ef53 100644 --- a/osu.Game/Overlays/VolumeOverlay.cs +++ b/osu.Game/Overlays/VolumeOverlay.cs @@ -3,7 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -74,9 +74,9 @@ namespace osu.Game.Overlays volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); - muteButton.Current.ValueChanged += mute => + muteButton.Current.ValueChanged += muted => { - if (mute) + if (muted.NewValue) audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); else audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment); @@ -113,7 +113,7 @@ namespace osu.Game.Overlays return true; case GlobalAction.ToggleMute: Show(); - muteButton.Current.Value = !muteButton.Current; + muteButton.Current.Value = !muteButton.Current.Value; return true; } diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs index d7654462d5..d808ee528e 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs @@ -7,8 +7,13 @@ namespace osu.Game.Rulesets.Difficulty { public class DifficultyAttributes { - public readonly Mod[] Mods; - public readonly double StarRating; + public Mod[] Mods; + + public double StarRating; + + public DifficultyAttributes() + { + } public DifficultyAttributes(Mod[] mods, double starRating) { diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 818d24508a..a5cb805300 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -7,12 +7,20 @@ using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Difficulty { public abstract class DifficultyCalculator { + /// + /// The length of each strain section. + /// + protected virtual int SectionLength => 400; + private readonly Ruleset ruleset; private readonly WorkingBeatmap beatmap; @@ -35,7 +43,7 @@ namespace osu.Game.Rulesets.Difficulty var clock = new StopwatchClock(); mods.OfType().ForEach(m => m.ApplyToClock(clock)); - return Calculate(playableBeatmap, mods, clock.Rate); + return calculate(playableBeatmap, mods, clock.Rate); } /// @@ -53,6 +61,44 @@ namespace osu.Game.Rulesets.Difficulty } } + private DifficultyAttributes calculate(IBeatmap beatmap, Mod[] mods, double clockRate) + { + var skills = CreateSkills(beatmap); + + if (!beatmap.HitObjects.Any()) + return CreateDifficultyAttributes(beatmap, mods, skills, clockRate); + + var difficultyHitObjects = CreateDifficultyHitObjects(beatmap, clockRate).OrderBy(h => h.BaseObject.StartTime).ToList(); + + double sectionLength = SectionLength * clockRate; + + // The first object doesn't generate a strain, so we begin with an incremented section end + double currentSectionEnd = Math.Ceiling(beatmap.HitObjects.First().StartTime / sectionLength) * sectionLength; + + foreach (DifficultyHitObject h in difficultyHitObjects) + { + while (h.BaseObject.StartTime > currentSectionEnd) + { + foreach (Skill s in skills) + { + s.SaveCurrentPeak(); + s.StartNewSectionFrom(currentSectionEnd); + } + + currentSectionEnd += sectionLength; + } + + foreach (Skill s in skills) + s.Process(h); + } + + // The peak strain will not be saved for the last section in the above loop + foreach (Skill s in skills) + s.SaveCurrentPeak(); + + return CreateDifficultyAttributes(beatmap, mods, skills, clockRate); + } + /// /// Creates all combinations which adjust the difficulty. /// @@ -96,12 +142,27 @@ namespace osu.Game.Rulesets.Difficulty protected virtual Mod[] DifficultyAdjustmentMods => Array.Empty(); /// - /// Calculates the difficulty of a using a specific combination. + /// Creates to describe beatmap's calculated difficulty. /// - /// The to compute the difficulty for. - /// The s that should be applied. - /// The rate of time in . - /// A structure containing the difficulty attributes. - protected abstract DifficultyAttributes Calculate(IBeatmap beatmap, Mod[] mods, double timeRate); + /// The whose difficulty was calculated. + /// The s that difficulty was calculated with. + /// The skills which processed the beatmap. + /// The rate at which the gameplay clock is run at. + protected abstract DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate); + + /// + /// Enumerates s to be processed from s in the . + /// + /// The providing the s to enumerate. + /// The rate at which the gameplay clock is run at. + /// The enumerated s. + protected abstract IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate); + + /// + /// Creates the s to calculate the difficulty of an . + /// + /// The whose difficulty will be calculated.The s. + protected abstract Skill[] CreateSkills(IBeatmap beatmap); } } diff --git a/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.cs new file mode 100644 index 0000000000..ebbffb5143 --- /dev/null +++ b/osu.Game/Rulesets/Difficulty/Preprocessing/DifficultyHitObject.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 osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Difficulty.Preprocessing +{ + /// + /// Wraps a and provides additional information to be used for difficulty calculation. + /// + public class DifficultyHitObject + { + /// + /// The this wraps. + /// + public readonly HitObject BaseObject; + + /// + /// The last which occurs before . + /// + public readonly HitObject LastObject; + + /// + /// Amount of time elapsed between and . + /// + public readonly double DeltaTime; + + /// + /// Creates a new . + /// + /// The which this wraps. + /// The last which occurs before in the beatmap. + /// The rate at which the gameplay clock is run at. + public DifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate) + { + BaseObject = hitObject; + LastObject = lastObject; + DeltaTime = (hitObject.StartTime - lastObject.StartTime) / clockRate; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs similarity index 68% rename from osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs rename to osu.Game/Rulesets/Difficulty/Skills/Skill.cs index 2f23552eb9..e8020ed185 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Skill.cs +++ b/osu.Game/Rulesets/Difficulty/Skills/Skill.cs @@ -3,20 +3,21 @@ using System; using System.Collections.Generic; -using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; -using osu.Game.Rulesets.Osu.Difficulty.Utils; -using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Difficulty.Preprocessing; +using osu.Game.Rulesets.Difficulty.Utils; -namespace osu.Game.Rulesets.Osu.Difficulty.Skills +namespace osu.Game.Rulesets.Difficulty.Skills { /// - /// Used to processes strain values of s, keep track of strain levels caused by the processed objects + /// Used to processes strain values of s, keep track of strain levels caused by the processed objects /// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects. /// public abstract class Skill { - protected const double SINGLE_SPACING_THRESHOLD = 125; - protected const double STREAM_SPACING_THRESHOLD = 110; + /// + /// The peak strain for each section of the beatmap. + /// + public IList StrainPeaks => strainPeaks; /// /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other. @@ -30,22 +31,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills protected abstract double StrainDecayBase { get; } /// - /// s that were processed previously. They can affect the strain values of the following objects. + /// The weight by which each strain value decays. /// - protected readonly History Previous = new History(2); // Contained objects not used yet + protected virtual double DecayWeight => 0.9; + + /// + /// s that were processed previously. They can affect the strain values of the following objects. + /// + protected readonly LimitedCapacityStack Previous = new LimitedCapacityStack(2); // Contained objects not used yet private double currentStrain = 1; // We keep track of the strain level at all times throughout the beatmap. private double currentSectionPeak = 1; // We also keep track of the peak strain level in the current section. + private readonly List strainPeaks = new List(); /// - /// Process an and update current strain values accordingly. + /// Process a and update current strain values accordingly. /// - public void Process(OsuDifficultyHitObject current) + public void Process(DifficultyHitObject current) { currentStrain *= strainDecay(current.DeltaTime); - if (!(current.BaseObject is Spinner)) - currentStrain += StrainValueOf(current) * SkillMultiplier; + currentStrain += StrainValueOf(current) * SkillMultiplier; currentSectionPeak = Math.Max(currentStrain, currentSectionPeak); @@ -64,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// /// Sets the initial strain level for a new section. /// - /// The beginning of the new section in milliseconds + /// The beginning of the new section in milliseconds. public void StartNewSectionFrom(double offset) { // The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries. @@ -74,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills } /// - /// Returns the calculated difficulty value representing all processed s. + /// Returns the calculated difficulty value representing all processed s. /// public double DifficultyValue() { @@ -87,16 +93,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills foreach (double strain in strainPeaks) { difficulty += strain * weight; - weight *= 0.9; + weight *= DecayWeight; } return difficulty; } /// - /// Calculates the strain value of an . This value is affected by previously processed objects. + /// Calculates the strain value of a . This value is affected by previously processed objects. /// - protected abstract double StrainValueOf(OsuDifficultyHitObject current); + protected abstract double StrainValueOf(DifficultyHitObject current); private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000); } diff --git a/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs similarity index 68% rename from osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs rename to osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs index e39351087e..95b7d9b19d 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Utils/History.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityStack.cs @@ -5,14 +5,16 @@ using System; using System.Collections; using System.Collections.Generic; -namespace osu.Game.Rulesets.Osu.Difficulty.Utils +namespace osu.Game.Rulesets.Difficulty.Utils { /// - /// An indexed stack with Push() only, which disposes items at the bottom after the capacity is full. - /// Indexing starts at the top of the stack. + /// An indexed stack with limited depth. Indexing starts at the top of the stack. /// - public class History : IEnumerable + public class LimitedCapacityStack : IEnumerable { + /// + /// The number of elements in the stack. + /// public int Count { get; private set; } private readonly T[] array; @@ -20,10 +22,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils private int marker; // Marks the position of the most recently added item. /// - /// Initializes a new instance of the History class that is empty and has the specified capacity. + /// Constructs a new . /// - /// The number of items the History can hold. - public History(int capacity) + /// The number of items the stack can hold. + public LimitedCapacityStack(int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException(); @@ -34,8 +36,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils } /// - /// The most recently added item is returned at index 0. + /// Retrieves the item at an index in the stack. /// + /// The index of the item to retrieve. The top of the stack is returned at index 0. public T this[int i] { get @@ -52,11 +55,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Utils } /// - /// Adds the item as the most recent one in the history. - /// The oldest item is disposed if the history is full. + /// Pushes an item to this . /// - public void Push(T item) // Overwrite the oldest item instead of shifting every item by one with every addition. + /// The item to push. + public void Push(T item) { + // Overwrite the oldest item instead of shifting every item by one with every addition. if (marker == 0) marker = capacity - 1; else diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 635e32d489..e557edf49f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 3ab62160cd..434ce4a721 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -4,7 +4,7 @@ using System; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index ced24b3308..0d6e11c649 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -58,10 +58,9 @@ namespace osu.Game.Rulesets.Judgements Child = new SkinnableDrawable($"Play/{Result.Type}", _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), - Font = @"Venera", + Font = OsuFont.Numeric.With(size: 12), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), - TextSize = 12 }, restrictSize: false) }; } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 7b5e70383c..e14eedd3dc 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -58,5 +58,7 @@ namespace osu.Game.Rulesets.Judgements /// The to find the numeric health increase for. /// The numeric health increase of . public double HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); + + public override string ToString() => $"AffectsCombo:{AffectsCombo} MaxResult:{MaxResult} MaxScore:{MaxNumericResult}"; } } diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index b1950f330e..d4ef5750b1 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -55,5 +55,7 @@ namespace osu.Game.Rulesets.Judgements { Judgement = judgement; } + + public override string ToString() => $"{Type} (Score:{Judgement.NumericResultFor(this)} HP:{Judgement.HealthIncreaseFor(this)} {Judgement})"; } } diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index 74acf80b7b..2a416b2705 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.Primitives; @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Mods } } - protected abstract void OnComboChange(int newCombo); + protected abstract void OnComboChange(ValueChangedEvent e); protected abstract string FragmentShader { get; } diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 465ead450c..2989ec2304 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -1,12 +1,12 @@ // 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.Configuration; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System.Collections.Generic; using System.Linq; +using osu.Framework.Bindables; namespace osu.Game.Rulesets.Mods { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility ? 1 : 0)) + foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) d.ApplyCustomUpdateState += ApplyHiddenState; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 06fe22a95e..fa45f7b60b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics.Primitives; using osu.Game.Audio; @@ -124,14 +124,14 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.LoadComplete(); - State.ValueChanged += state => + State.ValueChanged += armed => { - UpdateState(state); + UpdateState(armed.NewValue); // apply any custom state overrides - ApplyCustomUpdateState?.Invoke(this, state); + ApplyCustomUpdateState?.Invoke(this, armed.NewValue); - if (State == ArmedState.Hit) + if (armed.NewValue == ArmedState.Hit) PlaySamples(); }; diff --git a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs index c3f0279013..48fcfabc2f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; namespace osu.Game.Rulesets.Objects.Drawables diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 5283c5c3cf..0ebadd73d2 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets { AppDomain.CurrentDomain.AssemblyResolve += currentDomain_AssemblyResolve; - foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll")) + foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, $"{ruleset_library_prefix}.*.dll") + .Where(f => !Path.GetFileName(f).Contains("Tests"))) loadRulesetFromFile(file); } @@ -124,7 +125,7 @@ namespace osu.Game.Rulesets } catch (Exception e) { - Logger.Error(e, "Failed to load ruleset"); + Logger.Error(e, $"Failed to load ruleset {filename}"); } } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 45f2cbd7c8..1e7a324acf 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; @@ -168,11 +168,11 @@ namespace osu.Game.Rulesets.Scoring /// public virtual void PopulateScore(ScoreInfo score) { - score.TotalScore = (int)Math.Round(TotalScore); - score.Combo = Combo; - score.MaxCombo = HighestCombo; - score.Accuracy = Math.Round(Accuracy, 4); - score.Rank = Rank; + score.TotalScore = (int)Math.Round(TotalScore.Value); + score.Combo = Combo.Value; + score.MaxCombo = HighestCombo.Value; + score.Accuracy = Math.Round(Accuracy.Value, 4); + score.Rank = Rank.Value; score.Date = DateTimeOffset.Now; var hitWindows = CreateHitWindows(); @@ -298,8 +298,8 @@ namespace osu.Game.Rulesets.Scoring /// The to apply. protected virtual void ApplyResult(JudgementResult result) { - result.ComboAtJudgement = Combo; - result.HighestComboAtJudgement = HighestCombo; + result.ComboAtJudgement = Combo.Value; + result.HighestComboAtJudgement = HighestCombo.Value; JudgedHits++; @@ -371,10 +371,10 @@ namespace osu.Game.Rulesets.Scoring { default: case ScoringMode.Standardised: - return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; + return max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo.Value / maxHighestCombo) + bonusScore; case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) - return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); + return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) / 25); } } @@ -389,7 +389,7 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { MaxHits = JudgedHits; - maxHighestCombo = HighestCombo; + maxHighestCombo = HighestCombo.Value; maxBaseScore = baseScore; } diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 572f41b7e6..3b8a7353c6 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -7,8 +7,8 @@ using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 0d020238aa..1c29cf4e2b 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -13,7 +13,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using osu.Game.Configuration; @@ -96,10 +96,10 @@ namespace osu.Game.Rulesets.UI IsPaused.ValueChanged += paused => { - if (HasReplayLoaded) + if (HasReplayLoaded.Value) return; - KeyBindingInputManager.UseParentInput = !paused; + KeyBindingInputManager.UseParentInput = !paused.NewValue; }; Cursor = CreateCursor(); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 274a9475db..0065f195fc 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -1,9 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; @@ -121,6 +122,8 @@ namespace osu.Game.Rulesets.UI private const int max_catch_up_updates_per_frame = 50; + private const double sixty_frame_time = 1000.0 / 60; + public override bool UpdateSubTree() { requireMoreUpdateLoops = true; @@ -130,59 +133,64 @@ namespace osu.Game.Rulesets.UI while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) { - if (!base.UpdateSubTree()) - return false; + updateClock(); - UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); - - if (isAttached) + if (validState) { - // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated - // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before - // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead - // called manually at the correct time here. - base.Update(); + base.UpdateSubTree(); + UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); } } return true; } - protected override void Update() + private void updateClock() { if (parentClock == null) return; clock.Rate = parentClock.Rate; clock.IsRunning = parentClock.IsRunning; - if (!isAttached) - { - clock.CurrentTime = parentClock.CurrentTime; - } - else - { - double? newTime = replayInputHandler.SetFrameFromTime(parentClock.CurrentTime); + var newProposedTime = parentClock.CurrentTime; - if (newTime == null) + try + { + if (Math.Abs(clock.CurrentTime - newProposedTime) > sixty_frame_time * 1.2f) { - // we shouldn't execute for this time value. probably waiting on more replay data. - validState = false; - return; + newProposedTime = clock.Rate > 0 + ? Math.Min(newProposedTime, clock.CurrentTime + sixty_frame_time) + : Math.Max(newProposedTime, clock.CurrentTime - sixty_frame_time); } - clock.CurrentTime = newTime.Value; + if (!isAttached) + { + clock.CurrentTime = newProposedTime; + } + else + { + double? newTime = replayInputHandler.SetFrameFromTime(newProposedTime); + + if (newTime == null) + { + // we shouldn't execute for this time value. probably waiting on more replay data. + validState = false; + + requireMoreUpdateLoops = true; + clock.CurrentTime = newProposedTime; + return; + } + + clock.CurrentTime = newTime.Value; + } + + requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; } - - requireMoreUpdateLoops = clock.CurrentTime != parentClock.CurrentTime; - - // The manual clock time has changed in the above code. The framed clock now needs to be updated - // to ensure that the its time is valid for our children before input is processed - Clock.ProcessFrame(); - - if (!isAttached) + finally { - // For non-replay input handling, this provides equivalent input ordering as if Update was not overridden - base.Update(); + // The manual clock time has changed in the above code. The framed clock now needs to be updated + // to ensure that the its time is valid for our children before input is processed + Clock.ProcessFrame(); } } @@ -211,6 +219,7 @@ namespace osu.Game.Rulesets.UI return false; break; } + return base.Handle(e); } diff --git a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs index 49cdfea4d4..cd85932599 100644 --- a/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs +++ b/osu.Game/Rulesets/UI/Scrolling/IScrollingInfo.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling.Algorithms; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e29bfbc452..ed3534fb36 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index c08bb26dbc..bf2203e176 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.UI.Scrolling diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 26298588a9..7a60e0b021 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Lists; @@ -157,10 +157,10 @@ namespace osu.Game.Rulesets.UI.Scrolling switch (action) { case GlobalAction.IncreaseScrollSpeed: - this.TransformBindableTo(TimeRange, TimeRange - time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(TimeRange, TimeRange.Value - time_span_step, 200, Easing.OutQuint); return true; case GlobalAction.DecreaseScrollSpeed: - this.TransformBindableTo(TimeRange, TimeRange + time_span_step, 200, Easing.OutQuint); + this.TransformBindableTo(TimeRange, TimeRange.Value + time_span_step, 200, Easing.OutQuint); return true; } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 072da7c66e..0306f69755 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Threading; diff --git a/osu.Game/Screens/Edit/BindableBeatDivisor.cs b/osu.Game/Screens/Edit/BindableBeatDivisor.cs index 59fe45b9ec..bea4d9a7a4 100644 --- a/osu.Game/Screens/Edit/BindableBeatDivisor.cs +++ b/osu.Game/Screens/Edit/BindableBeatDivisor.cs @@ -3,7 +3,7 @@ using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Edit { diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index 726f6d2025..cb5078a479 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -3,7 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index 527900acf2..ae2ac61c90 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -110,7 +110,8 @@ namespace osu.Game.Screens.Edit.Components.Menus { public TextContainer() { - NormalText.TextSize = BoldText.TextSize = 14; + NormalText.Font = NormalText.Font.With(size: 14); + BoldText.Font = BoldText.Font.With(size: 14); NormalText.Margin = BoldText.Margin = new MarginPadding { Horizontal = 10, Vertical = MARGIN_VERTICAL }; } } diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 5d611d3bca..12d17f4f0f 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Edit.Components } }; - tabs.Current.ValueChanged += newValue => Beatmap.Value.Track.Tempo.Value = newValue; + tabs.Current.ValueChanged += tempo => Beatmap.Value.Track.Tempo.Value = tempo.NewValue; } protected override bool OnKeyDown(KeyDownEvent e) @@ -127,15 +127,14 @@ namespace osu.Game.Screens.Edit.Components Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Text = $"{value:0%}", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) }, textBold = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Text = $"{value:0%}", - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), Alpha = 0, }, }; @@ -163,9 +162,9 @@ namespace osu.Game.Screens.Edit.Components private void updateState() { - text.FadeColour(Active || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint); - text.FadeTo(Active ? 0 : 1, fade_duration, Easing.OutQuint); - textBold.FadeTo(Active ? 1 : 0, fade_duration, Easing.OutQuint); + text.FadeColour(Active.Value || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint); + text.FadeTo(Active.Value ? 0 : 1, fade_duration, Easing.OutQuint); + textBold.FadeTo(Active.Value ? 1 : 0, fade_duration, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs index 5d46f83ad3..1ad69afe91 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/DrawableRadioButton.cs @@ -80,10 +80,10 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons { base.LoadComplete(); - button.Selected.ValueChanged += v => + button.Selected.ValueChanged += selected => { updateSelectionState(); - if (v) + if (selected.NewValue) Selected?.Invoke(button); }; @@ -95,16 +95,16 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons if (!IsLoaded) return; - BackgroundColour = button.Selected ? selectedBackgroundColour : defaultBackgroundColour; - bubble.Colour = button.Selected ? selectedBubbleColour : defaultBubbleColour; + BackgroundColour = button.Selected.Value ? selectedBackgroundColour : defaultBackgroundColour; + bubble.Colour = button.Selected.Value ? selectedBubbleColour : defaultBubbleColour; } protected override bool OnClick(ClickEvent e) { - if (button.Selected) + if (button.Selected.Value) return true; - if (!Enabled) + if (!Enabled.Value) return true; button.Selected.Value = true; diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs index d35bb55449..3692c0437b 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Edit.Components.RadioButtons { diff --git a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs index eb433b1c0a..c6ecdde7f6 100644 --- a/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Components/RadioButtons/RadioButtonCollection.cs @@ -44,9 +44,9 @@ namespace osu.Game.Screens.Edit.Components.RadioButtons private RadioButton currentlySelected; private void addButton(RadioButton button) { - button.Selected.ValueChanged += v => + button.Selected.ValueChanged += selected => { - if (v) + if (selected.NewValue) { currentlySelected?.Deselect(); currentlySelected = button; diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index 3b58a3a1f7..0391074b11 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -6,6 +6,7 @@ using osu.Game.Graphics.Sprites; using System; using osu.Framework.Allocation; using osu.Framework.Timing; +using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Components { @@ -23,8 +24,7 @@ namespace osu.Game.Screens.Edit.Components { Origin = Anchor.BottomLeft, RelativePositionAxes = Axes.Y, - TextSize = 22, - FixedWidth = true, + Font = OsuFont.GetFont(size: 22, fixedWidth: true), Y = 0.5f, } }; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index edf7baf687..26d9614631 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -3,8 +3,8 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osuTK; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts Beatmap.ValueChanged += b => { updateRelativeChildSize(); - LoadBeatmap(b); + LoadBeatmap(b.NewValue); }; } diff --git a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs index f1bd70d4dd..3f7672ae08 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BeatDivisorControl.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit.Compose.Components }, new Drawable[] { - new TextFlowContainer(s => s.TextSize = 14) + new TextFlowContainer(s => s.Font = s.Font.With(size: 14)) { Padding = new MarginPadding { Horizontal = 15 }, Text = "beat snap divisor", @@ -157,12 +157,8 @@ namespace osu.Game.Screens.Edit.Compose.Components protected override void LoadComplete() { base.LoadComplete(); - - beatDivisor.ValueChanged += v => updateText(); - updateText(); + beatDivisor.BindValueChanged(val => Text = $"1/{val.NewValue}", true); } - - private void updateText() => Text = $"1/{beatDivisor.Value}"; } private class DivisorButton : IconButton @@ -219,9 +215,9 @@ namespace osu.Game.Screens.Edit.Compose.Components AddInternal(marker = new Marker()); - CurrentNumber.ValueChanged += v => + CurrentNumber.ValueChanged += div => { - marker.MoveToX(getMappedPosition(v), 100, Easing.OutQuint); + marker.MoveToX(getMappedPosition(div.NewValue), 100, Easing.OutQuint); marker.Flash(); }; } @@ -238,11 +234,11 @@ namespace osu.Game.Screens.Edit.Compose.Components { case Key.Right: beatDivisor.Next(); - OnUserChange(Current); + OnUserChange(Current.Value); return true; case Key.Left: beatDivisor.Previous(); - OnUserChange(Current); + OnUserChange(Current.Value); return true; default: return false; @@ -279,7 +275,7 @@ namespace osu.Game.Screens.Edit.Compose.Components var xPosition = (ToLocalSpace(screenSpaceMousePosition).X - RangePadding) / UsableWidth; CurrentNumber.Value = availableDivisors.OrderBy(d => Math.Abs(getMappedPosition(d) - xPosition)).First(); - OnUserChange(Current); + OnUserChange(Current.Value); } private float getMappedPosition(float divisor) => (float)Math.Pow((divisor - 1) / (availableDivisors.Last() - 1), 0.90f); diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs index b00d0b0b46..748c9e2ba3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/Timeline.cs @@ -3,7 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Audio; @@ -49,13 +49,13 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline // We don't want the centre marker to scroll AddInternal(new CentreMarker()); - WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible.NewValue ? 1 : 0, 200, Easing.OutQuint); Beatmap.BindTo(beatmap); Beatmap.BindValueChanged(b => { - waveform.Waveform = b.Waveform; - track = b.Track; + waveform.Waveform = b.NewValue.Waveform; + track = b.NewValue.Track; }, true); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs index 1244e834c1..806a55c931 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index b147679cca..c922e4ef4a 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Platform; @@ -222,11 +223,11 @@ namespace osu.Game.Screens.Edit private void exportBeatmap() => host.OpenFileExternally(Beatmap.Value.Save()); - private void onModeChanged(EditorScreenMode mode) + private void onModeChanged(ValueChangedEvent e) { currentScreen?.Exit(); - switch (mode) + switch (e.NewValue) { case EditorScreenMode.Compose: currentScreen = new ComposeScreen(); diff --git a/osu.Game/Screens/Edit/EditorClock.cs b/osu.Game/Screens/Edit/EditorClock.cs index 1660a1b703..8f65366650 100644 --- a/osu.Game/Screens/Edit/EditorClock.cs +++ b/osu.Game/Screens/Edit/EditorClock.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit public bool SeekSnapped(double position) { var timingPoint = ControlPointInfo.TimingPointAt(position); - double beatSnapLength = timingPoint.BeatLength / beatDivisor; + double beatSnapLength = timingPoint.BeatLength / beatDivisor.Value; // We will be snapping to beats within the timing point position -= timingPoint.Time; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Edit timingPoint = ControlPointInfo.TimingPoints[--activeIndex]; } - double seekAmount = timingPoint.BeatLength / beatDivisor * amount; + double seekAmount = timingPoint.BeatLength / beatDivisor.Value * amount; double seekTime = CurrentTime + seekAmount * direction; if (!snapped || ControlPointInfo.TimingPoints.Count == 0) diff --git a/osu.Game/Screens/Edit/EditorScreen.cs b/osu.Game/Screens/Edit/EditorScreen.cs index bfe0423c8a..045e5a1226 100644 --- a/osu.Game/Screens/Edit/EditorScreen.cs +++ b/osu.Game/Screens/Edit/EditorScreen.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; diff --git a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs index 3340daa6b8..50d524d1f5 100644 --- a/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs +++ b/osu.Game/Screens/Edit/Setup/Components/LabelledComponents/LabelledTextBox.cs @@ -38,8 +38,8 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents public float LabelTextSize { - get => label.TextSize; - set => label.TextSize = value; + get => label.Font.Size; + set => label.Font = label.Font.With(size: value); } public string PlaceholderText @@ -103,8 +103,7 @@ namespace osu.Game.Screens.Edit.Setup.Components.LabelledComponents Origin = Anchor.TopLeft, Padding = new MarginPadding { Left = default_label_left_padding, Top = default_label_top_padding }, Colour = Color4.White, - TextSize = default_label_text_size, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(size: default_label_text_size, weight: FontWeight.Bold), }, textBox = new OsuTextBox { diff --git a/osu.Game/Screens/IOsuScreen.cs b/osu.Game/Screens/IOsuScreen.cs index 9e28de5593..e665f401d9 100644 --- a/osu.Game/Screens/IOsuScreen.cs +++ b/osu.Game/Screens/IOsuScreen.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Overlays; diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index f73d6ba560..fc285fb724 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -118,7 +118,6 @@ namespace osu.Game.Screens.Menu AllowMultiline = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 16, Position = new Vector2(0, 35), Text = text } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 4a09bfe142..2669bb9342 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -8,7 +8,7 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader(true)] private void load(AudioManager audio, IdleTracker idleTracker) { - isIdle.ValueChanged += updateIdleState; + isIdle.ValueChanged += idle => updateIdleState(idle.NewValue); if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle); diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index c0ff37cc0b..14124d283f 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -64,25 +64,13 @@ namespace osu.Game.Screens.Menu } }; - textFlow.AddText("This is an ", t => - { - t.TextSize = 30; - t.Font = @"Exo2.0-Light"; - }); - textFlow.AddText("early development build", t => - { - t.TextSize = 30; - t.Font = @"Exo2.0-SemiBold"; - }); + textFlow.AddText("This is an ", t => t.Font = t.Font.With(Typeface.Exo, 30, FontWeight.Light)); + textFlow.AddText("early development build", t => t.Font = t.Font.With(Typeface.Exo, 30, FontWeight.SemiBold)); - textFlow.AddParagraph("Things may not work as expected", t => t.TextSize = 20); + textFlow.AddParagraph("Things may not work as expected", t => t.Font = t.Font.With(size: 20)); textFlow.NewParagraph(); - Action format = t => - { - t.TextSize = 15; - t.Font = @"Exo2.0-SemiBold"; - }; + Action format = t => t.Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold); textFlow.AddParagraph("Detailed bug reports are welcomed via github issues.", format); textFlow.NewParagraph(); @@ -102,7 +90,7 @@ namespace osu.Game.Screens.Menu supporterDrawables.Add(heart = textFlow.AddIcon(FontAwesome.fa_heart, t => { t.Padding = new MarginPadding { Left = 5 }; - t.TextSize = 12; + t.Font = t.Font.With(size: 12); t.Colour = colours.Pink; t.Origin = Anchor.Centre; }).First()); diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 10cfc4a299..2392d650a0 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.MathUtils; @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Menu BeatmapSetInfo setInfo = null; - if (!menuMusic) + if (!menuMusic.Value) { var sets = beatmaps.GetAllUsableBeatmapSets(); if (sets.Count > 0) @@ -93,13 +93,13 @@ namespace osu.Game.Screens.Menu { Beatmap.Value = introBeatmap; - if (menuVoice) + if (menuVoice.Value) welcome.Play(); Scheduler.AddDelayed(delegate { // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. - if (menuMusic) + if (menuMusic.Value) track.Start(); LoadComponentAsync(mainMenu = new MainMenu()); @@ -112,7 +112,6 @@ namespace osu.Game.Screens.Menu }, delay_step_two); } - logo.RelativePositionAxes = Axes.Both; logo.Colour = Color4.White; logo.Ripple = false; @@ -159,7 +158,7 @@ namespace osu.Game.Screens.Menu double fadeOutTime = EXIT_DELAY; //we also handle the exit transition. - if (menuVoice) + if (menuVoice.Value) seeya.Play(); else fadeOutTime = 500; diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index 03a5b7ff46..98640ef38c 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -102,9 +102,8 @@ namespace osu.Game.Screens.Menu Origin = Anchor.Centre, Text = "welcome", Padding = new MarginPadding { Bottom = 10 }, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), Alpha = 0, - TextSize = 42, Spacing = new Vector2(5), }, new CircularContainer diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 2534c57b1e..a45c80669c 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -3,7 +3,6 @@ using osuTK; using osuTK.Graphics; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.Colour; @@ -15,6 +14,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; namespace osu.Game.Screens.Menu { diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 04bc80ac87..6e1afb6b68 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -5,6 +5,7 @@ using osuTK; using osuTK.Graphics; using osuTK.Input; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Framework.Screens; @@ -53,10 +54,10 @@ namespace osu.Game.Screens.Menu buttons = new ButtonSystem { OnChart = delegate { this.Push(new ChartListing()); }, - OnDirect = delegate {this.Push(new OnlineListing()); }, - OnEdit = delegate {this.Push(new Editor()); }, + OnDirect = delegate { this.Push(new OnlineListing()); }, + OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, - OnMulti = delegate {this.Push(new Multiplayer()); }, + OnMulti = delegate { this.Push(new Multiplayer()); }, OnExit = this.Exit, } } @@ -99,7 +100,7 @@ namespace osu.Game.Screens.Menu public void LoadToSolo() => Schedule(onSolo); - private void onSolo() =>this.Push(consumeSongSelect()); + private void onSolo() => this.Push(consumeSongSelect()); private Screen consumeSongSelect() { @@ -157,7 +158,7 @@ namespace osu.Game.Screens.Menu .OnComplete(l => buttons.SetOsuLogo(null)); } - private void beatmap_ValueChanged(WorkingBeatmap newValue) + private void beatmap_ValueChanged(ValueChangedEvent e) { if (!this.IsCurrentScreen()) return; @@ -183,7 +184,7 @@ namespace osu.Game.Screens.Menu { base.OnResuming(last); - ((BackgroundScreenDefault)Background).Next(); + (Background as BackgroundScreenDefault)?.Next(); //we may have consumed our preloaded instance, so let's make another. preloadSongSelect(); @@ -200,7 +201,7 @@ namespace osu.Game.Screens.Menu { if (!e.Repeat && e.ControlPressed && e.ShiftPressed && e.Key == Key.D) { - this.Push(new Drawings()); + this.Push(new Drawings()); return true; } diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 7288cc8db5..ce0a38ba8d 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -4,7 +4,6 @@ using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -14,6 +13,7 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using System; +using osu.Framework.Bindables; namespace osu.Game.Screens.Menu { diff --git a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs index 7a513a7f5f..101ff8bf94 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTitle.cs @@ -25,10 +25,10 @@ namespace osu.Game.Screens.Multi.Components [BackgroundDependencyLoader] private void load() { - CurrentItem.BindValueChanged(v => updateText(), true); + CurrentItem.BindValueChanged(_ => updateText(), true); } - private float textSize = OsuSpriteText.FONT_SIZE; + private float textSize = OsuFont.DEFAULT_FONT_SIZE; public float TextSize { @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Multi.Components if (beatmap == null) textFlow.AddText("No beatmap selected", s => { - s.TextSize = TextSize; + s.Font = s.Font.With(size: TextSize); s.Colour = colours.PinkLight; }); else @@ -68,17 +68,17 @@ namespace osu.Game.Screens.Multi.Components new OsuSpriteText { Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)), - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize), }, new OsuSpriteText { Text = " - ", - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize), }, new OsuSpriteText { Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title)), - TextSize = TextSize, + Font = OsuFont.GetFont(size: TextSize), } }, null, LinkAction.OpenBeatmap, beatmap.OnlineBeatmapID.ToString(), "Open beatmap"); } diff --git a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs index 4f432a232c..23771451bd 100644 --- a/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/BeatmapTypeInfo.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Multi.Components Children = new Drawable[] { new BeatmapTitle(), - beatmapAuthor = new LinkFlowContainer(s => s.TextSize = 14) + beatmapAuthor = new LinkFlowContainer(s => s.Font = s.Font.With(size: 14)) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Multi.Components { beatmapAuthor.Clear(); - var beatmap = item?.Beatmap; + var beatmap = item.NewValue?.Beatmap; if (beatmap != null) { diff --git a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs index 5bbf4b064f..5bd002f8dc 100644 --- a/osu.Game/Screens/Multi/Components/DisableableTabControl.cs +++ b/osu.Game/Screens/Multi/Components/DisableableTabControl.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multi.Components protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return true; return base.OnClick(e); } diff --git a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs index 0d49f75b46..8ab23a620b 100644 --- a/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multi/Components/ModeTypeInfo.cs @@ -46,9 +46,9 @@ namespace osu.Game.Screens.Multi.Components }, }; - CurrentItem.BindValueChanged(updateBeatmap, true); + CurrentItem.BindValueChanged(item => updateBeatmap(item.NewValue), true); - Type.BindValueChanged(v => gameTypeContainer.Child = new DrawableGameType(v) { Size = new Vector2(height) }, true); + Type.BindValueChanged(type => gameTypeContainer.Child = new DrawableGameType(type.NewValue) { Size = new Vector2(height) }, true); } private void updateBeatmap(PlaylistItem item) diff --git a/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs b/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs index 06d5e585ab..512f79942d 100644 --- a/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs +++ b/osu.Game/Screens/Multi/Components/MultiplayerBackgroundSprite.cs @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Multi.Components InternalChild = sprite = CreateBackgroundSprite(); - CurrentItem.BindValueChanged(i => sprite.Beatmap.Value = i?.Beatmap, true); + CurrentItem.BindValueChanged(item => sprite.Beatmap.Value = item.NewValue?.Beatmap, true); } protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game/Screens/Multi/Components/ParticipantCount.cs b/osu.Game/Screens/Multi/Components/ParticipantCount.cs index 27bfc9a3f7..498eeb09b3 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantCount.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantCount.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Multi.Components @@ -34,25 +35,22 @@ namespace osu.Game.Screens.Multi.Components { count = new OsuSpriteText { - TextSize = text_size, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: text_size) }, slash = new OsuSpriteText { Text = @"/", - TextSize = text_size, - Font = @"Exo2.0-Light" + Font = OsuFont.GetFont(weight: FontWeight.Light, size: text_size) }, maxText = new OsuSpriteText { - TextSize = text_size, - Font = @"Exo2.0-Light" + Font = OsuFont.GetFont(weight: FontWeight.Light, size: text_size) }, } }; MaxParticipants.BindValueChanged(_ => updateMax(), true); - ParticipantCount.BindValueChanged(v => count.Text = v.ToString("#,0"), true); + ParticipantCount.BindValueChanged(c => count.Text = c.NewValue.ToString("#,0"), true); } private void updateMax() diff --git a/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs index 24a2d70b60..d799f846c2 100644 --- a/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs +++ b/osu.Game/Screens/Multi/Components/RoomStatusInfo.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -34,10 +34,9 @@ namespace osu.Game.Screens.Multi.Components { statusPart = new StatusPart { - TextSize = 14, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14) }, - endDatePart = new EndDatePart { TextSize = 14 } + endDatePart = new EndDatePart { Font = OsuFont.GetFont(size: 14) } } }; @@ -54,7 +53,7 @@ namespace osu.Game.Screens.Multi.Components public EndDatePart() : base(DateTimeOffset.UtcNow) { - EndDate.BindValueChanged(d => Date = d); + EndDate.BindValueChanged(date => Date = date.NewValue); } protected override string Format() diff --git a/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs b/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs index 6d573d0866..97af6674bf 100644 --- a/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs +++ b/osu.Game/Screens/Multi/Components/StatusColouredContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Multi.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - status.BindValueChanged(s => this.FadeColour(s.GetAppropriateColour(colours), transitionDuration), true); + status.BindValueChanged(s => this.FadeColour(s.NewValue.GetAppropriateColour(colours), transitionDuration), true); } } } diff --git a/osu.Game/Screens/Multi/Header.cs b/osu.Game/Screens/Multi/Header.cs index 687a28b7a6..0e958bf523 100644 --- a/osu.Game/Screens/Multi/Header.cs +++ b/osu.Game/Screens/Multi/Header.cs @@ -64,12 +64,11 @@ namespace osu.Game.Screens.Multi new OsuSpriteText { Text = "multiplayer ", - TextSize = 25, + Font = OsuFont.GetFont(size: 25) }, screenType = new OsuSpriteText { - TextSize = 25, - Font = @"Exo2.0-Light", + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 25) }, }, }, @@ -85,10 +84,10 @@ namespace osu.Game.Screens.Multi }, }; - breadcrumbs.Current.ValueChanged += s => + breadcrumbs.Current.ValueChanged += scren => { - if (s is IMultiplayerSubScreen mpScreen) - screenType.Text = mpScreen.ShortTitle.ToLowerInvariant(); + if (scren.NewValue is IMultiplayerSubScreen multiScreen) + screenType.Text = multiScreen.ShortTitle.ToLowerInvariant(); }; breadcrumbs.Current.TriggerChange(); diff --git a/osu.Game/Screens/Multi/IRoomManager.cs b/osu.Game/Screens/Multi/IRoomManager.cs index 980879d79a..f6c979851e 100644 --- a/osu.Game/Screens/Multi/IRoomManager.cs +++ b/osu.Game/Screens/Multi/IRoomManager.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.Multi diff --git a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs index afe2b70524..14d66389ca 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/DrawableRoom.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using osu.Framework; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -155,7 +155,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components Spacing = new Vector2(5f), Children = new Drawable[] { - new RoomName { TextSize = 18 }, + new RoomName { Font = OsuFont.GetFont(size: 18) }, new ParticipantInfo(), }, }, diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 950d475a30..87c4539756 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Graphics; using osu.Game.Overlays.SearchableList; using osuTK.Graphics; @@ -45,8 +45,8 @@ namespace osu.Game.Screens.Multi.Lounge.Components filter.Value = new FilterCriteria { SearchString = Search.Current.Value ?? string.Empty, - PrimaryFilter = Tabs.Current, - SecondaryFilter = DisplayStyleControl.Dropdown.Current + PrimaryFilter = Tabs.Current.Value, + SecondaryFilter = DisplayStyleControl.Dropdown.Current.Value }; } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs index 806bc92882..ca5e5f72c4 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/ParticipantInfo.cs @@ -81,28 +81,29 @@ namespace osu.Game.Screens.Multi.Lounge.Components summary = new OsuSpriteText { Text = "0 participants", - TextSize = 14, + Font = OsuFont.GetFont(size: 14) } }, }, }; - Host.BindValueChanged(v => + Host.BindValueChanged(host => { hostText.Clear(); flagContainer.Clear(); - if (v != null) + if (host.NewValue != null) { hostText.AddText("hosted by "); - hostText.AddLink(v.Username, null, LinkAction.OpenUserProfile, v.Id.ToString(), "Open profile", s => s.Font = "Exo2.0-BoldItalic"); - flagContainer.Child = new DrawableFlag(v.Country) { RelativeSizeAxes = Axes.Both }; + hostText.AddLink(host.NewValue.Username, null, LinkAction.OpenUserProfile, host.NewValue.Id.ToString(), "Open profile", + s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); + flagContainer.Child = new DrawableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both }; } }, true); - ParticipantCount.BindValueChanged(v => summary.Text = $"{v:#,0}{" participant".Pluralize(v == 1)}", true); + ParticipantCount.BindValueChanged(count => summary.Text = $"{count.NewValue:#,0}{" participant".Pluralize(count.NewValue == 1)}", true); - /*Participants.BindValueChanged(v => + /*Participants.BindValueChanged(e => { var ranks = v.Select(u => u.Statistics.Ranks.Global); levelRangeLower.Text = ranks.Min().ToString(); diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index 3e665ab27e..fd9c8d7b35 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -96,7 +96,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Current = Name }, }, @@ -135,8 +135,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components AutoSizeAxes = Axes.Both, Child = new StatusText { - TextSize = 14, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), } }, beatmapTypeInfo = new BeatmapTypeInfo(), @@ -192,7 +191,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components } else { - status.Value = Status; + status.Value = Status.Value; participantCount.FadeIn(transition_duration); beatmapTypeInfo.FadeIn(transition_duration); @@ -215,7 +214,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components [BackgroundDependencyLoader] private void load() { - status.BindValueChanged(s => Text = s.Message, true); + status.BindValueChanged(s => Text = s.NewValue.Message, true); } } diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs index baeac900ee..99a6de0064 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomsContainer.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components private void updateSorting() { foreach (var room in roomFlow) - roomFlow.SetLayoutPosition(room, room.Room.Position); + roomFlow.SetLayoutPosition(room, room.Room.Position.Value); } private void selectRoom(Room room) diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 71205dc199..dd1e060125 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Multi/Match/Components/Header.cs b/osu.Game/Screens/Multi/Match/Components/Header.cs index 9a0fdbd4e7..6a6a1f274c 100644 --- a/osu.Game/Screens/Multi/Match/Components/Header.cs +++ b/osu.Game/Screens/Multi/Match/Components/Header.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - CurrentItem.BindValueChanged(i => modDisplay.Current.Value = i?.RequiredMods, true); + CurrentItem.BindValueChanged(item => modDisplay.Current.Value = item.NewValue?.RequiredMods, true); beatmapButton.Action = () => RequestBeatmapSelection?.Invoke(); } @@ -126,7 +126,7 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - roomId.BindValueChanged(v => this.FadeTo(v.HasValue ? 0 : 1), true); + roomId.BindValueChanged(id => this.FadeTo(id.NewValue.HasValue ? 0 : 1), true); } } diff --git a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs index 8c9f99c446..f3412d0be7 100644 --- a/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/HeaderButton.cs @@ -41,8 +41,7 @@ namespace osu.Game.Screens.Multi.Match.Components Depth = -1, Origin = Anchor.Centre, Anchor = Anchor.Centre, - Font = @"Exo2.0-Light", - TextSize = 30, + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 30), }; } } diff --git a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs index 942e03b306..02c8929f44 100644 --- a/osu.Game/Screens/Multi/Match/Components/HostInfo.cs +++ b/osu.Game/Screens/Multi/Match/Components/HostInfo.cs @@ -1,9 +1,10 @@ // 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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; using osu.Game.Users; @@ -42,7 +43,7 @@ namespace osu.Game.Screens.Multi.Match.Components } }; - Host.BindValueChanged(updateHost); + Host.BindValueChanged(host => updateHost(host.NewValue)); } private void updateHost(User host) @@ -53,7 +54,8 @@ namespace osu.Game.Screens.Multi.Match.Components { linkContainer.AddText("hosted by"); linkContainer.NewLine(); - linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", s => s.Font = "Exo2.0-BoldItalic"); + linkContainer.AddLink(host.Username, null, LinkAction.OpenUserProfile, host.Id.ToString(), "View Profile", + s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true)); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/Info.cs b/osu.Game/Screens/Multi/Match/Components/Info.cs index b27c5b0ab4..a944d965bd 100644 --- a/osu.Game/Screens/Multi/Match/Components/Info.cs +++ b/osu.Game/Screens/Multi/Match/Components/Info.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new OsuSpriteText { - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Current = Name }, new RoomStatusInfo(), @@ -94,8 +94,8 @@ namespace osu.Game.Screens.Multi.Match.Components CurrentItem.BindValueChanged(item => { - viewBeatmapButton.Beatmap.Value = item?.Beatmap; - readyButton.Beatmap.Value = item?.Beatmap; + viewBeatmapButton.Beatmap.Value = item.NewValue?.Beatmap; + readyButton.Beatmap.Value = item.NewValue?.Beatmap; }, true); hostInfo.Host.BindTo(Host); diff --git a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs index 0b61637cd5..bd8e4c7335 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchChatDisplay.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Chat; using osu.Game.Online.Multiplayer; @@ -28,13 +28,13 @@ namespace osu.Game.Screens.Multi.Match.Components { base.LoadComplete(); - roomId.BindValueChanged(v => updateChannel(), true); + roomId.BindValueChanged(_ => updateChannel(), true); } private void updateChannel() { if (roomId.Value != null) - Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId, Type = ChannelType.Multiplayer, Name = $"#mp_{roomId.Value}" }); + Channel.Value = channelManager?.JoinChannel(new Channel { Id = channelId.Value, Type = ChannelType.Multiplayer, Name = $"#mp_{roomId.Value}" }); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 60604eeb5c..fff713f026 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Multi.Match.Components { roomId.BindValueChanged(id => { - if (id == null) + if (id.NewValue == null) return; Scores = null; diff --git a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs index 15749864b6..fc98db157b 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchPage.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchPage.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Multi.Match.Components { diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index c3169ebe94..b310e62d7c 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -4,7 +4,7 @@ using System; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -148,7 +148,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, typeLabel = new OsuSpriteText { - TextSize = 14, + Font = OsuFont.GetFont(size: 14), Colour = colours.Yellow }, }, @@ -264,12 +264,12 @@ namespace osu.Game.Screens.Multi.Match.Components processingOverlay = new ProcessingOverlay { Alpha = 0 } }; - TypePicker.Current.BindValueChanged(t => typeLabel.Text = t?.Name ?? string.Empty, true); - Name.BindValueChanged(n => NameField.Text = n, true); - Availability.BindValueChanged(a => AvailabilityPicker.Current.Value = a, true); - Type.BindValueChanged(t => TypePicker.Current.Value = t, true); - MaxParticipants.BindValueChanged(m => MaxParticipantsField.Text = m?.ToString(), true); - Duration.BindValueChanged(d => DurationField.Current.Value = d, true); + TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); + Name.BindValueChanged(name => NameField.Text = name.NewValue, true); + Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true); + Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); + MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true); + Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue, true); } protected override void Update() @@ -296,7 +296,7 @@ namespace osu.Game.Screens.Multi.Match.Components Duration.Value = DurationField.Current.Value; - manager?.CreateRoom(currentRoom, onSuccess, onError); + manager?.CreateRoom(currentRoom.Value, onSuccess, onError); processingOverlay.Show(); } @@ -364,8 +364,7 @@ namespace osu.Game.Screens.Multi.Match.Components { new OsuSpriteText { - TextSize = 12, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Text = title.ToUpper(), }, content = new Container diff --git a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs index 7ac1016e72..9e04bb6f60 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchTabControl.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; @@ -26,9 +26,9 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load() { - roomId.BindValueChanged(v => + roomId.BindValueChanged(id => { - if (v.HasValue) + if (id.NewValue.HasValue) { Items.ForEach(t => t.Enabled.Value = !(t is SettingsMatchPage)); Current.Value = new RoomMatchPage(); @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Multi.Match.Components : base(value) { enabled.BindTo(value.Enabled); - enabled.BindValueChanged(v => Colour = v ? Color4.White : Color4.Gray); + enabled.BindValueChanged(enabled => Colour = enabled.NewValue ? Color4.White : Color4.Gray, true); } protected override bool OnClick(ClickEvent e) diff --git a/osu.Game/Screens/Multi/Match/Components/Participants.cs b/osu.Game/Screens/Multi/Match/Components/Participants.cs index 1565d75c21..2d6099c65d 100644 --- a/osu.Game/Screens/Multi/Match/Components/Participants.cs +++ b/osu.Game/Screens/Multi/Match/Components/Participants.cs @@ -50,9 +50,9 @@ namespace osu.Game.Screens.Multi.Match.Components }, }; - Participants.BindValueChanged(v => + Participants.BindValueChanged(participants => { - usersFlow.Children = v.Select(u => new UserPanel(u) + usersFlow.Children = participants.NewValue.Select(u => new UserPanel(u) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index 50cf2addeb..3e4694e232 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Multi.Match.Components { beatmaps.ItemAdded += beatmapAdded; - Beatmap.BindValueChanged(updateBeatmap, true); + Beatmap.BindValueChanged(b => updateBeatmap(b.NewValue), true); } private void updateBeatmap(BeatmapInfo beatmap) @@ -77,7 +77,7 @@ namespace osu.Game.Screens.Multi.Match.Components return; } - bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate; + bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(gameBeatmap.Value.Track.Length) < endDate.Value; Enabled.Value = hasBeatmap && hasEnoughTime; } diff --git a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs index 4e6ebf2135..e9dbd6982d 100644 --- a/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs +++ b/osu.Game/Screens/Multi/Match/Components/RoomAvailabilityPicker.cs @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Multi.Match.Components { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = value.GetDescription(), }, }; diff --git a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs index e26a6b7e20..8d1ff21124 100644 --- a/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ViewBeatmapButton.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osuTK; @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Multi.Match.Components private void load() { if (osuGame != null) - Beatmap.BindValueChanged(updateAction, true); + Beatmap.BindValueChanged(beatmap => updateAction(beatmap.NewValue), true); } private void updateAction(BeatmapInfo beatmap) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index d97b32e54a..c3f7cea43e 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Multi.Match public MatchSubScreen(Room room) { - Title = room.RoomID.Value == null ? "New room" : room.Name; + Title = room.RoomID.Value == null ? "New room" : room.Name.Value; } [BackgroundDependencyLoader] @@ -146,10 +146,10 @@ namespace osu.Game.Screens.Multi.Match }, }; - header.Tabs.Current.BindValueChanged(t => + header.Tabs.Current.BindValueChanged(tab => { const float fade_duration = 500; - if (t is SettingsMatchPage) + if (tab.NewValue is SettingsMatchPage) { settings.Show(); info.FadeOut(fade_duration, Easing.OutQuint); @@ -188,15 +188,15 @@ namespace osu.Game.Screens.Multi.Match /// /// Handles propagation of the current playlist item's content to game-wide mechanisms. /// - private void currentItemChanged(PlaylistItem item) + private void currentItemChanged(ValueChangedEvent e) { // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info - var localBeatmap = item?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == item.Beatmap.OnlineBeatmapID); + var localBeatmap = e.NewValue?.Beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == e.NewValue.Beatmap.OnlineBeatmapID); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); - CurrentMods.Value = item?.RequiredMods ?? Enumerable.Empty(); - if (item?.Ruleset != null) - Ruleset.Value = item.Ruleset; + CurrentMods.Value = e.NewValue?.RequiredMods ?? Enumerable.Empty(); + if (e.NewValue?.Ruleset != null) + Ruleset.Value = e.NewValue.Ruleset; } /// @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Multi.Match { default: case GameTypeTimeshift _: - multiplayer?.Start(() => new TimeshiftPlayer(CurrentItem) + multiplayer?.Start(() => new TimeshiftPlayer(CurrentItem.Value) { Exited = () => leaderboard.RefreshScores() }); diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 32eea88fbc..dd01ae4160 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -135,7 +135,7 @@ namespace osu.Game.Screens.Multi protected override void LoadComplete() { base.LoadComplete(); - isIdle.BindValueChanged(updatePollingRate, true); + isIdle.BindValueChanged(idle => updatePollingRate(idle.NewValue), true); } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) diff --git a/osu.Game/Screens/Multi/MultiplayerComposite.cs b/osu.Game/Screens/Multi/MultiplayerComposite.cs index 245a6ac358..da6bba7865 100644 --- a/osu.Game/Screens/Multi/MultiplayerComposite.cs +++ b/osu.Game/Screens/Multi/MultiplayerComposite.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Users; diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index 71f6687cc6..d127bdc0ea 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -5,7 +5,7 @@ using System; using System.Diagnostics; using System.Threading; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.API; diff --git a/osu.Game/Screens/Multi/Ranking/MatchResults.cs b/osu.Game/Screens/Multi/Ranking/MatchResults.cs index db52a79ccb..fe68d7e849 100644 --- a/osu.Game/Screens/Multi/Ranking/MatchResults.cs +++ b/osu.Game/Screens/Multi/Ranking/MatchResults.cs @@ -18,9 +18,9 @@ namespace osu.Game.Screens.Multi.Ranking protected override IEnumerable CreateResultPages() => new IResultPageInfo[] { - new ScoreOverviewPageInfo(Score, Beatmap), - new LocalLeaderboardPageInfo(Score, Beatmap), - new RoomLeaderboardPageInfo(Score, Beatmap), + new ScoreOverviewPageInfo(Score, Beatmap.Value), + new LocalLeaderboardPageInfo(Score, Beatmap.Value), + new RoomLeaderboardPageInfo(Score, Beatmap.Value), }; } } diff --git a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs index 1b4c99d972..d20b021fc6 100644 --- a/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs +++ b/osu.Game/Screens/Multi/Ranking/Pages/RoomLeaderboardPage.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages Action gray = s => s.Colour = colours.GrayC; Action white = s => { - s.TextSize *= 1.4f; + s.Font = s.Font.With(size: s.Font.Size * 1.4f); s.Colour = colours.GrayF; }; @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Multi.Ranking.Pages rankText.AddText($"#{index + 1} ", s => { - s.Font = "Exo2.0-Bold"; + s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold); s.Colour = colours.YellowDark; }); diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index b1f021618f..c15a8471a1 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online; @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Multi public void CreateRoom(Room room, Action onSuccess = null, Action onError = null) { - room.Host.Value = api.LocalUser; + room.Host.Value = api.LocalUser.Value; var req = new CreateRoomRequest(room); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index b8d6fda97d..5034385969 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Framework.Screens; @@ -174,7 +174,7 @@ namespace osu.Game.Screens logo.FadeOut(300, Easing.OutQuint); logo.Anchor = Anchor.TopLeft; logo.Origin = Anchor.Centre; - logo.RelativePositionAxes = Axes.None; + logo.RelativePositionAxes = Axes.Both; logo.BeatMatching = true; logo.Triangles = true; logo.Ripple = true; diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index b51ce0d33f..84e5de76de 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Rulesets; diff --git a/osu.Game/Screens/Play/Break/BreakInfo.cs b/osu.Game/Screens/Play/Break/BreakInfo.cs index 39a5594450..a3d64d05a3 100644 --- a/osu.Game/Screens/Play/Break/BreakInfo.cs +++ b/osu.Game/Screens/Play/Break/BreakInfo.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Scoring; using osuTK; @@ -29,8 +30,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "current progress".ToUpperInvariant(), - TextSize = 15, - Font = "Exo2.0-Black", + Font = OsuFont.GetFont(weight: FontWeight.Black, size: 15), }, new FillFlowContainer { diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index d2b8b8c26a..4c5e228fa5 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -34,7 +34,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreRight, Text = name, - TextSize = 17, + Font = OsuFont.GetFont(size: 17), Margin = new MarginPadding { Right = margin } }, valueText = new OsuSpriteText @@ -42,8 +42,7 @@ namespace osu.Game.Screens.Play.Break Anchor = Anchor.Centre, Origin = Anchor.CentreLeft, Text = prefix + @"-", - TextSize = 17, - Font = "Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = margin } } }; @@ -51,9 +50,9 @@ namespace osu.Game.Screens.Play.Break Current.ValueChanged += currentValueChanged; } - private void currentValueChanged(T newValue) + private void currentValueChanged(ValueChangedEvent e) { - var newText = prefix + Format(newValue); + var newText = prefix + Format(e.NewValue); if (valueText.Text == newText) return; diff --git a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs index c85ce1b70b..2f5e43aebf 100644 --- a/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/Break/RemainingTimeCounter.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.Break @@ -19,8 +20,7 @@ namespace osu.Game.Screens.Play.Break { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 33, - Font = "Venera", + Font = OsuFont.Numeric.With(size: 33), }; } diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index dc0636c44f..bcd7452ba6 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -88,11 +88,10 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = Header, - Font = @"Exo2.0-Medium", + Font = OsuFont.GetFont(size: 30), Spacing = new Vector2(5, 0), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - TextSize = 30, Colour = colours.Yellow, Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f) @@ -176,7 +175,7 @@ namespace osu.Game.Screens.Play } }; - button.Selected.ValueChanged += s => buttonSelectionChanged(button, s); + button.Selected.ValueChanged += selected => buttonSelectionChanged(button, selected.NewValue); InternalButtons.Add(button); } @@ -260,22 +259,21 @@ namespace osu.Game.Screens.Play Text = "You've retried ", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 + Font = OsuFont.GetFont(size: 18), }, new OsuSpriteText { Text = $"{retries:n0}", - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 }, new OsuSpriteText { Text = $" time{(retries == 1 ? "" : "s")} in this session", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), - TextSize = 18 + Font = OsuFont.GetFont(size: 18), } }; } @@ -292,7 +290,7 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { - if (e.Repeat || e.Key != Key.Enter || !Selected) + if (e.Repeat || e.Key != Key.Enter || !Selected.Value) return false; Click(); diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index b45b1bb8a5..eb9db9745f 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -63,14 +63,14 @@ namespace osu.Game.Screens.Play.HUD TextSize = 80; - Current.ValueChanged += newValue => updateCount(newValue == 0); + Current.ValueChanged += combo => updateCount(combo.NewValue == 0); } protected override void LoadComplete() { base.LoadComplete(); - DisplayedCountSpriteText.Text = FormatCount(Current); + DisplayedCountSpriteText.Text = FormatCount(Current.Value); DisplayedCountSpriteText.Anchor = Anchor; DisplayedCountSpriteText.Origin = Origin; @@ -99,8 +99,9 @@ namespace osu.Game.Screens.Play.HUD set { textSize = value; - DisplayedCountSpriteText.TextSize = TextSize; - PopOutCount.TextSize = TextSize; + + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(size: TextSize); + PopOutCount.Font = PopOutCount.Font.With(size: TextSize); } } @@ -110,7 +111,7 @@ namespace osu.Game.Screens.Play.HUD /// public void Increment(int amount = 1) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } /// @@ -161,7 +162,7 @@ namespace osu.Game.Screens.Play.HUD private void updateCount(bool rolling) { int prev = previousValue; - previousValue = Current; + previousValue = Current.Value; if (!IsLoaded) return; @@ -172,14 +173,14 @@ namespace osu.Game.Screens.Play.HUD IsRolling = false; DisplayedCount = prev; - if (prev + 1 == Current) - OnCountIncrement(prev, Current); + if (prev + 1 == Current.Value) + OnCountIncrement(prev, Current.Value); else - OnCountChange(prev, Current); + OnCountChange(prev, Current.Value); } else { - OnCountRolling(displayedCount, Current); + OnCountRolling(displayedCount, Current.Value); IsRolling = true; } } diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index a45a1dbc68..3f6b1e29e6 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -26,7 +26,7 @@ namespace osu.Game.Screens.Play.HUD public override void Increment(long amount) { - Current.Value = Current + amount; + Current.Value = Current.Value + amount; } } } diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index cc3b4e8254..acd8656fb2 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; namespace osu.Game.Screens.Play.HUD @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Play.HUD protected HealthDisplay() { - Current.ValueChanged += newValue => SetHealth((float)newValue); + Current.ValueChanged += health => SetHealth((float)health.NewValue); } protected abstract void SetHealth(float value); diff --git a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs index a0bcc3460b..ca4cce8929 100644 --- a/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs +++ b/osu.Game/Screens/Play/HUD/HoldForMenuButton.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play.HUD text = new OsuSpriteText { Text = "hold for menu", - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft }, @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Play.HUD private void bind() { circularProgress.Current.BindTo(Progress); - Progress.ValueChanged += v => icon.Scale = new Vector2(1 + (float)v * 0.2f); + Progress.ValueChanged += progress => icon.Scale = new Vector2(1 + (float)progress.NewValue * 0.2f); } private bool pendingAnimation; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index d329902a2d..2c1293833f 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -14,6 +14,7 @@ using osu.Game.Rulesets.UI; using osuTK; using osu.Game.Graphics.Containers; using osu.Framework.Input.Events; +using osu.Game.Graphics; namespace osu.Game.Screens.Play.HUD { @@ -60,15 +61,14 @@ namespace osu.Game.Screens.Play.HUD Anchor = Anchor.BottomCentre, Origin = Anchor.TopCentre, Text = @"/ UNRANKED /", - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12) } }; Current.ValueChanged += mods => { iconsContainer.Clear(); - foreach (Mod mod in mods) + foreach (Mod mod in mods.NewValue) { iconsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.6f) }); } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 1b1862d587..b5f04c3474 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play Progress.Objects = rulesetContainer.Objects; Progress.AudioClock = offsetClock; - Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; + Progress.AllowSeeking = rulesetContainer.HasReplayLoaded.Value; Progress.OnSeek = pos => adjustableClock.Seek(pos); ModDisplay.Current.BindTo(working.Mods); @@ -104,10 +104,10 @@ namespace osu.Game.Screens.Play private void load(OsuConfigManager config, NotificationOverlay notificationOverlay) { showHud = config.GetBindable(OsuSetting.ShowInterface); - showHud.ValueChanged += hudVisibility => visibilityContainer.FadeTo(hudVisibility ? 1 : 0, duration); + showHud.ValueChanged += visible => visibilityContainer.FadeTo(visible.NewValue ? 1 : 0, duration); showHud.TriggerChange(); - if (!showHud && !hasShownNotificationOnce) + if (!showHud.Value && !hasShownNotificationOnce) { hasShownNotificationOnce = true; @@ -126,11 +126,11 @@ namespace osu.Game.Screens.Play replayLoaded.TriggerChange(); } - private void replayLoadedValueChanged(bool loaded) + private void replayLoadedValueChanged(ValueChangedEvent e) { - PlayerSettingsOverlay.ReplayLoaded = loaded; + PlayerSettingsOverlay.ReplayLoaded = e.NewValue; - if (loaded) + if (e.NewValue) { PlayerSettingsOverlay.Show(); ModDisplay.FadeIn(200); diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 9d8fb2a501..406cd3810e 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; 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 osuTK; using osuTK.Graphics; @@ -96,8 +97,7 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = Name, - Font = @"Venera", - TextSize = 12, + Font = OsuFont.Numeric.With(size: 12), Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index f033a20226..71e8da06ba 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index 8dae0ab964..0222cefdd3 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -4,7 +4,7 @@ using System; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play { if (!CanPause && !force) return; - if (IsPaused) return; + if (IsPaused.Value) return; // stop the seekable clock (stops the audio eventually) decoupledClock.Stop(); @@ -91,7 +91,7 @@ namespace osu.Game.Screens.Play public void Resume() { - if (!IsPaused) return; + if (!IsPaused.Value) return; IsPaused.Value = false; IsResuming = false; @@ -116,10 +116,10 @@ namespace osu.Game.Screens.Play protected override void Update() { // eagerly pause when we lose window focus (if we are locally playing). - if (!game.IsActive && CanPause) + if (!game.IsActive.Value && CanPause) Pause(); - if (!IsPaused) + if (!IsPaused.Value) framedClock.ProcessFrame(); base.Update(); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2ab207e47a..9198d1a646 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -8,7 +8,7 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -159,7 +159,7 @@ namespace osu.Game.Screens.Play // the final usable gameplay clock with user-set offsets applied. var offsetClock = new FramedOffsetClock(platformOffsetClock); - userAudioOffset.ValueChanged += v => offsetClock.Offset = v; + userAudioOffset.ValueChanged += offset => offsetClock.Offset = offset.NewValue; userAudioOffset.TriggerChange(); ScoreProcessor = RulesetContainer.CreateScoreProcessor(); @@ -173,7 +173,7 @@ namespace osu.Game.Screens.Play Retries = RestartCount, OnRetry = Restart, OnQuit = performUserRequestedExit, - CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, + CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded.Value, Children = new[] { storyboardContainer = new Container @@ -238,7 +238,7 @@ namespace osu.Game.Screens.Play RulesetContainer.IsPaused.BindTo(pauseContainer.IsPaused); - if (ShowStoryboard) + if (ShowStoryboard.Value) initializeStoryboard(false); // Bind ScoreProcessor to ourselves @@ -356,7 +356,7 @@ namespace osu.Game.Screens.Play this.Delay(750).Schedule(() => { - if (!pauseContainer.IsPaused) + if (!pauseContainer.IsPaused.Value) { adjustableClock.Start(); } @@ -405,7 +405,7 @@ namespace osu.Game.Screens.Play Background?.FadeColour(Color4.White, fadeOutDuration, Easing.OutQuint); } - protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !pauseContainer.IsPaused; + protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !pauseContainer.IsPaused.Value; private void initializeStoryboard(bool asyncLoad) { @@ -429,11 +429,11 @@ namespace osu.Game.Screens.Play base.UpdateBackgroundElements(); - if (ShowStoryboard && storyboard == null) + if (ShowStoryboard.Value && storyboard == null) initializeStoryboard(true); var beatmap = Beatmap.Value; - var storyboardVisible = ShowStoryboard && beatmap.Storyboard.HasDrawable; + var storyboardVisible = ShowStoryboard.Value && beatmap.Storyboard.HasDrawable; storyboardContainer? .FadeColour(OsuColour.Gray(BackgroundOpacity), BACKGROUND_FADE_DURATION, Easing.OutQuint) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index c55c05f61c..ac4cc30874 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -143,8 +143,6 @@ namespace osu.Game.Screens.Play { base.LogoArriving(logo, resuming); - logo.RelativePositionAxes = Axes.Both; - logo.ScaleTo(new Vector2(0.15f), 300, Easing.In); logo.MoveTo(new Vector2(0.5f), 300, Easing.In); logo.FadeIn(350); @@ -330,16 +328,14 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = new LocalisedString((metadata.TitleUnicode, metadata.Title)), - TextSize = 36, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 36, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, new OsuSpriteText { Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist)), - TextSize = 26, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 26, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, }, @@ -367,8 +363,7 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = beatmap?.BeatmapInfo?.Version, - TextSize = 26, - Font = @"Exo2.0-MediumItalic", + Font = OsuFont.GetFont(size: 26, italics: true), Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Margin = new MarginPadding diff --git a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index f752243c52..ebbed299f7 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -1,10 +1,11 @@ // 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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; +using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.PlayerSettings @@ -17,7 +18,7 @@ namespace osu.Game.Screens.Play.PlayerSettings public IAdjustableClock AdjustableClock { set; get; } - private readonly PlayerSliderBar sliderbar; + private readonly PlayerSliderBar rateSlider; private readonly OsuSpriteText multiplierText; @@ -42,11 +43,11 @@ namespace osu.Game.Screens.Play.PlayerSettings { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), } }, }, - sliderbar = new PlayerSliderBar + rateSlider = new PlayerSliderBar { Bindable = new BindableDouble(1) { @@ -69,9 +70,9 @@ namespace osu.Game.Screens.Play.PlayerSettings var clockRate = AdjustableClock.Rate; // can't trigger this line instantly as the underlying clock may not be ready to accept adjustments yet. - sliderbar.Bindable.ValueChanged += multiplier => AdjustableClock.Rate = clockRate * multiplier; + rateSlider.Bindable.ValueChanged += multiplier => AdjustableClock.Rate = clockRate * multiplier.NewValue; - sliderbar.Bindable.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier:0.0}x", true); + rateSlider.Bindable.BindValueChanged(multiplier => multiplierText.Text = $"{multiplier.NewValue:0.0}x", true); } } } diff --git a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index 7bf3a74f7e..49bcf0b8dc 100644 --- a/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -94,8 +94,7 @@ namespace osu.Game.Screens.Play.PlayerSettings Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, Text = Title.ToUpperInvariant(), - TextSize = 17, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = 10 }, }, button = new IconButton diff --git a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs index 7e01a84da2..c28a01155c 100644 --- a/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs +++ b/osu.Game/Screens/Play/ScreenWithBeatmapBackground.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Configuration; @@ -20,7 +20,7 @@ namespace osu.Game.Screens.Play protected const float BACKGROUND_FADE_DURATION = 800; - protected float BackgroundOpacity => 1 - (float)DimLevel; + protected float BackgroundOpacity => 1 - (float)DimLevel.Value; #region User Settings diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index d3db126ae4..f5983029e2 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -273,8 +273,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, RelativePositionAxes = Axes.Y, Y = 0.7f, - TextSize = 12, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 12), Origin = Anchor.Centre, Text = @"SKIP", }, @@ -313,7 +312,7 @@ namespace osu.Game.Screens.Play protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return false; sampleConfirm.Play(); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index ba67882d56..443df27b42 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -9,7 +9,7 @@ using System.Collections.Generic; using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Play { State = Visibility.Visible; - replayLoaded.ValueChanged += v => AllowSeeking = v; + replayLoaded.ValueChanged += loaded => AllowSeeking = loaded.NewValue; replayLoaded.TriggerChange(); } diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 7471eccff9..d24e484001 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -42,7 +42,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, Margin = new MarginPadding { Left = margin, @@ -53,14 +53,14 @@ namespace osu.Game.Screens.Play Origin = Anchor.BottomCentre, Anchor = Anchor.BottomCentre, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, }, timeLeft = new OsuSpriteText { Origin = Anchor.BottomRight, Anchor = Anchor.BottomRight, Colour = colours.BlueLighter, - Font = @"Venera", + Font = OsuFont.Numeric, Margin = new MarginPadding { Right = margin, diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 43c04997e9..09b5b7ea49 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -111,8 +111,7 @@ namespace osu.Game.Screens.Ranking.Pages Origin = Anchor.TopCentre, Colour = colours.PinkDarker, Shadow = false, - Font = @"Exo2.0-Bold", - TextSize = 16, + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = "total score", Margin = new MarginPadding { Bottom = 15 }, }, @@ -217,14 +216,14 @@ namespace osu.Game.Screens.Ranking.Pages new OsuSpriteText { Text = statistic.Value.ToString().PadLeft(4, '0'), Colour = colours.Gray7, - TextSize = 30, + Font = OsuFont.GetFont(size: 30), Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, new OsuSpriteText { Text = statistic.Key.GetDescription(), Colour = colours.Gray7, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Y = 26, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -307,24 +306,21 @@ namespace osu.Game.Screens.Ranking.Pages Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 24, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 24, italics: true), }, artist = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 20, - Font = @"Exo2.0-BoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 20, italics: true), }, versionMapper = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Shadow = false, - TextSize = 16, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), }, } } @@ -369,11 +365,10 @@ namespace osu.Game.Screens.Ranking.Pages }, new OsuSpriteText { - Font = @"Exo2.0-RegularItalic", - Text = user.Username, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - TextSize = 30, + Text = user.Username, + Font = OsuFont.GetFont(size: 30, weight: FontWeight.Regular, italics: true), Padding = new MarginPadding { Bottom = 10 }, } }; @@ -396,7 +391,7 @@ namespace osu.Game.Screens.Ranking.Pages public SlowScoreCounter(uint leading = 0) : base(leading) { DisplayedCountSpriteText.Shadow = false; - DisplayedCountSpriteText.Font = @"Venera-Light"; + DisplayedCountSpriteText.Font = DisplayedCountSpriteText.Font.With(Typeface.Venera, weight: FontWeight.Light); UseCommaSeparator = true; } } diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index a70d6bd87f..47ac472b9e 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -190,45 +190,43 @@ namespace osu.Game.Screens.Ranking }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, Text = $"{Score.MaxCombo}x", - TextSize = 40, RelativePositionAxes = Axes.X, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), X = 0.1f, Colour = colours.BlueDarker, - Anchor = Anchor.CentreLeft, - Origin = Anchor.BottomCentre, }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, Text = "max combo", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), RelativePositionAxes = Axes.X, X = 0.1f, Colour = colours.Gray6, - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, }, new OsuSpriteText { - Text = $"{Score.Accuracy:P2}", - TextSize = 40, - RelativePositionAxes = Axes.X, - Font = @"Exo2.0-Bold", - X = 0.9f, - Colour = colours.BlueDarker, Anchor = Anchor.CentreLeft, Origin = Anchor.BottomCentre, + Text = $"{Score.Accuracy:P2}", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 40), + RelativePositionAxes = Axes.X, + X = 0.9f, + Colour = colours.BlueDarker, }, new OsuSpriteText { + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, Text = "accuracy", - TextSize = 20, + Font = OsuFont.GetFont(size: 20), RelativePositionAxes = Axes.X, X = 0.9f, Colour = colours.Gray6, - Anchor = Anchor.CentreLeft, - Origin = Anchor.TopCentre, }, } }, @@ -268,12 +266,12 @@ namespace osu.Game.Screens.Ranking modeChangeButtons.AddItem(t); modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault(); - modeChangeButtons.Current.BindValueChanged(m => + modeChangeButtons.Current.BindValueChanged(page => { currentPage?.FadeOut(); currentPage?.Expire(); - currentPage = m?.CreatePage(); + currentPage = page.NewValue?.CreatePage(); if (currentPage != null) circleInner.Add(currentPage); diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index d250416b29..c8ca21d4ba 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -119,25 +119,25 @@ namespace osu.Game.Screens }, new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Text = GetType().Name, Colour = getColourFor(GetType()).Lighten(0.8f), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - TextSize = 50, + Font = OsuFont.GetFont(size: 50), }, new OsuSpriteText { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Text = "is not yet ready for use!", - TextSize = 20, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Font = OsuFont.GetFont(size: 20), }, new OsuSpriteText { - Text = "please check back a bit later.", - TextSize = 14, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Text = "please check back a bit later.", + Font = OsuFont.GetFont(size: 14), }, } }, diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 1670bf4de8..4490818a23 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -13,9 +13,9 @@ using osu.Framework.MathUtils; using System.Diagnostics; using System.Threading.Tasks; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Caching; using osu.Framework.Threading; -using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input.Events; using osu.Game.Beatmaps; @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select /// public BeatmapInfo SelectedBeatmap => selectedBeatmap?.Beatmap; - private CarouselBeatmap selectedBeatmap => selectedBeatmapSet?.Beatmaps.FirstOrDefault(s => s.State == CarouselItemState.Selected); + private CarouselBeatmap selectedBeatmap => selectedBeatmapSet?.Beatmaps.FirstOrDefault(s => s.State.Value == CarouselItemState.Selected); /// /// The currently selected beatmap set. @@ -130,7 +130,7 @@ namespace osu.Game.Screens.Select config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm); config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled); - RightClickScrollingEnabled.ValueChanged += v => RightMouseScrollbar = v; + RightClickScrollingEnabled.ValueChanged += enabled => RightMouseScrollbar = enabled.NewValue; RightClickScrollingEnabled.TriggerChange(); } @@ -196,7 +196,7 @@ namespace osu.Game.Screens.Select foreach (CarouselBeatmapSet set in beatmapSets) { - if (!bypassFilters && set.Filtered) + if (!bypassFilters && set.Filtered.Value) continue; var item = set.Beatmaps.FirstOrDefault(p => p.Beatmap.Equals(beatmap)); @@ -205,9 +205,9 @@ namespace osu.Game.Screens.Select // The beatmap that needs to be selected doesn't exist in this set continue; - if (!bypassFilters && item.Filtered) + if (!bypassFilters && item.Filtered.Value) // The beatmap exists in this set but is filtered, so look for the first unfiltered map in the set - item = set.Beatmaps.FirstOrDefault(b => !b.Filtered); + item = set.Beatmaps.FirstOrDefault(b => !b.Filtered.Value); if (item != null) { @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Select /// Whether to skip individual difficulties and only increment over full groups. public void SelectNext(int direction = 1, bool skipDifficulties = true) { - var visibleItems = Items.Where(s => !s.Item.Filtered).ToList(); + var visibleItems = Items.Where(s => !s.Item.Filtered.Value).ToList(); if (!visibleItems.Any()) return; @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Select { var item = visibleItems[currentIndex].Item; - if (item.Filtered || item.State == CarouselItemState.Selected) continue; + if (item.Filtered.Value || item.State.Value == CarouselItemState.Selected) continue; switch (item) { @@ -260,7 +260,7 @@ namespace osu.Game.Screens.Select if (skipDifficulties) select(set); else - select(direction > 0 ? set.Beatmaps.First(b => !b.Filtered) : set.Beatmaps.Last(b => !b.Filtered)); + select(direction > 0 ? set.Beatmaps.First(b => !b.Filtered.Value) : set.Beatmaps.Last(b => !b.Filtered.Value)); return; } } @@ -272,7 +272,7 @@ namespace osu.Game.Screens.Select /// True if a selection could be made, else False. public bool SelectNextRandom() { - var visibleSets = beatmapSets.Where(s => !s.Filtered).ToList(); + var visibleSets = beatmapSets.Where(s => !s.Filtered.Value).ToList(); if (!visibleSets.Any()) return false; @@ -288,7 +288,7 @@ namespace osu.Game.Screens.Select CarouselBeatmapSet set; - if (RandomAlgorithm == RandomSelectAlgorithm.RandomPermutation) + if (RandomAlgorithm.Value == RandomSelectAlgorithm.RandomPermutation) { var notYetVisitedSets = visibleSets.Except(previouslyVisitedRandomSets).ToList(); if (!notYetVisitedSets.Any()) @@ -303,7 +303,7 @@ namespace osu.Game.Screens.Select else set = visibleSets.ElementAt(RNG.Next(visibleSets.Count)); - var visibleBeatmaps = set.Beatmaps.Where(s => !s.Filtered).ToList(); + var visibleBeatmaps = set.Beatmaps.Where(s => !s.Filtered.Value).ToList(); select(visibleBeatmaps[RNG.Next(visibleBeatmaps.Count)]); return true; } @@ -314,9 +314,9 @@ namespace osu.Game.Screens.Select { var beatmap = randomSelectedBeatmaps.Pop(); - if (!beatmap.Filtered) + if (!beatmap.Filtered.Value) { - if (RandomAlgorithm == RandomSelectAlgorithm.RandomPermutation) + if (RandomAlgorithm.Value == RandomSelectAlgorithm.RandomPermutation) previouslyVisitedRandomSets.Remove(selectedBeatmapSet); select(beatmap); break; @@ -509,9 +509,9 @@ namespace osu.Game.Screens.Select foreach (var c in set.Beatmaps) { - c.State.ValueChanged += v => + c.State.ValueChanged += state => { - if (v == CarouselItemState.Selected) + if (state.NewValue == CarouselItemState.Selected) { selectedBeatmapSet = set; SelectionChanged?.Invoke(c.Beatmap); @@ -549,7 +549,7 @@ namespace osu.Game.Screens.Select case DrawableCarouselBeatmapSet set: lastSet = set; - set.MoveToX(set.Item.State == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); + set.MoveToX(set.Item.State.Value == CarouselItemState.Selected ? -100 : 0, 500, Easing.OutExpo); set.MoveToY(currentY, 750, Easing.OutExpo); break; case DrawableCarouselBeatmap beatmap: @@ -559,7 +559,7 @@ namespace osu.Game.Screens.Select void performMove(float y, float? startY = null) { if (startY != null) beatmap.MoveTo(new Vector2(0, startY.Value)); - beatmap.MoveToX(beatmap.Item.State == CarouselItemState.Selected ? -50 : 0, 500, Easing.OutExpo); + beatmap.MoveToX(beatmap.Item.State.Value == CarouselItemState.Selected ? -50 : 0, 500, Easing.OutExpo); beatmap.MoveToY(y, 750, Easing.OutExpo); } diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 002633e8b9..f66cd2b29a 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -4,7 +4,7 @@ using System; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Select private void invokeOnFilter() { - OnFilter?.Invoke(tabs.Current, modsCheckbox.Current); + OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value); } [BackgroundDependencyLoader] @@ -69,8 +69,8 @@ namespace osu.Game.Screens.Select }, }; - tabs.Current.ValueChanged += item => invokeOnFilter(); - modsCheckbox.Current.ValueChanged += item => invokeOnFilter(); + tabs.Current.ValueChanged += _ => invokeOnFilter(); + modsCheckbox.Current.ValueChanged += _ => invokeOnFilter(); } } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 161208f9ab..697fed599f 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Screens.Select.Details; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select @@ -137,8 +138,7 @@ namespace osu.Game.Screens.Select new OsuSpriteText { Text = "Points of Failure", - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, failRetryGraph = new FailRetryGraph { @@ -325,8 +325,7 @@ namespace osu.Game.Screens.Select Child = new OsuSpriteText { Text = title, - Font = @"Exo2.0-Bold", - TextSize = 14, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), }, }, }, @@ -353,7 +352,7 @@ namespace osu.Game.Screens.Select private void setTextAsync(string text) { - LoadComponentAsync(new OsuTextFlowContainer(s => s.TextSize = 14) + LoadComponentAsync(new OsuTextFlowContainer(s => s.Font = s.Font.With(size: 14)) { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 2a3fc03cc5..32e7215e69 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -8,7 +8,7 @@ using JetBrains.Annotations; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -203,9 +203,8 @@ namespace osu.Game.Screens.Select { VersionLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", Text = beatmapInfo.Version, - TextSize = 24, + Font = OsuFont.GetFont(size: 24, italics: true), }, } }, @@ -240,13 +239,11 @@ namespace osu.Game.Screens.Select { TitleLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", - TextSize = 28, + Font = OsuFont.GetFont(size: 28, italics: true), }, ArtistLabel = new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", - TextSize = 17, + Font = OsuFont.GetFont(size: 17, italics: true), }, MapperContainer = new FillFlowContainer { @@ -266,8 +263,8 @@ namespace osu.Game.Screens.Select } }; - titleBinding.BindValueChanged(value => setMetadata(metadata.Source)); - artistBinding.BindValueChanged(value => setMetadata(metadata.Source), true); + titleBinding.BindValueChanged(_ => setMetadata(metadata.Source)); + artistBinding.BindValueChanged(_ => setMetadata(metadata.Source), true); // no difficulty means it can't have a status to show if (beatmapInfo.Version == null) @@ -345,16 +342,13 @@ namespace osu.Game.Screens.Select { new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = "mapped by ", - TextSize = 15, + Font = OsuFont.GetFont(size: 15), }, new OsuSpriteText { - Font = @"Exo2.0-Bold", - // ReSharper disable once PossibleNullReferenceException (resharper broken?) Text = metadata.Author.Username, - TextSize = 15, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15), } }; } @@ -402,10 +396,9 @@ namespace osu.Game.Screens.Select Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Colour = new Color4(255, 221, 85, 255), - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17), Margin = new MarginPadding { Left = 30 }, Text = statistic.Content, - TextSize = 17, } }; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 206bbeb88e..8e7ea8f964 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel public override void Filter(FilterCriteria criteria) { base.Filter(criteria); - Filtered.Value = InternalChildren.All(i => i.Filtered); + Filtered.Value = InternalChildren.All(i => i.Filtered.Value); } public override string ToString() => BeatmapSet.ToString(); diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index dfbbd2d907..edb9d79ddb 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select.Carousel public virtual void AddChild(CarouselItem i) { - i.State.ValueChanged += v => ChildItemStateChanged(i, v); + i.State.ValueChanged += state => ChildItemStateChanged(i, state.NewValue); i.ChildID = ++currentChildID; InternalChildren.Add(i); } @@ -58,9 +58,9 @@ namespace osu.Game.Screens.Select.Carousel { if (items != null) InternalChildren = items; - State.ValueChanged += v => + State.ValueChanged += state => { - switch (v) + switch (state.NewValue) { case CarouselItemState.Collapsed: case CarouselItemState.NotSelected: @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Select.Carousel case CarouselItemState.Selected: InternalChildren.ForEach(c => { - if (c.State == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected; + if (c.State.Value == CarouselItemState.Collapsed) c.State.Value = CarouselItemState.NotSelected; }); break; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index e32e5fe366..67e8282b76 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -13,9 +13,9 @@ namespace osu.Game.Screens.Select.Carousel { public CarouselGroupEagerSelect() { - State.ValueChanged += v => + State.ValueChanged += state => { - if (v == CarouselItemState.Selected) + if (state.NewValue == CarouselItemState.Selected) attemptSelection(); }; } @@ -81,10 +81,10 @@ namespace osu.Game.Screens.Select.Carousel if (filteringChildren) return; // we only perform eager selection if we are a currently selected group. - if (State != CarouselItemState.Selected) return; + if (State.Value != CarouselItemState.Selected) return; // we only perform eager selection if none of our children are in a selected state already. - if (Children.Any(i => i.State == CarouselItemState.Selected)) return; + if (Children.Any(i => i.State.Value == CarouselItemState.Selected)) return; PerformSelection(); } @@ -92,8 +92,8 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void PerformSelection() { CarouselItem nextToSelect = - Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered) ?? - Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered); + Children.Skip(lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value) ?? + Children.Reverse().Skip(InternalChildren.Count - lastSelectedIndex).FirstOrDefault(i => !i.Filtered.Value); if (nextToSelect != null) nextToSelect.State.Value = CarouselItemState.Selected; diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index c7da9d73d0..a0f5969b3c 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Screens.Select.Carousel { @@ -16,7 +16,7 @@ namespace osu.Game.Screens.Select.Carousel /// /// This item is not in a hidden state. /// - public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered; + public bool Visible => State.Value != CarouselItemState.Collapsed && !Filtered.Value; public virtual List Drawables { @@ -37,9 +37,9 @@ namespace osu.Game.Screens.Select.Carousel { DrawableRepresentation = new Lazy(CreateDrawableRepresentation); - Filtered.ValueChanged += v => + Filtered.ValueChanged += filtered => { - if (v && State == CarouselItemState.Selected) + if (filtered.NewValue && State.Value == CarouselItemState.Selected) State.Value = CarouselItemState.NotSelected; }; } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 5d28bed4a6..00fce20ac3 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -100,25 +100,21 @@ namespace osu.Game.Screens.Select.Carousel { new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = beatmap.Version, - TextSize = 20, + Font = OsuFont.GetFont(size: 20), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, new OsuSpriteText { - Font = @"Exo2.0-Medium", Text = "mapped by", - TextSize = 16, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, new OsuSpriteText { - Font = @"Exo2.0-MediumItalic", Text = $"{(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author.Username}", - TextSize = 16, + Font = OsuFont.GetFont(italics: true), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, @@ -157,7 +153,7 @@ namespace osu.Game.Screens.Select.Carousel protected override bool OnClick(ClickEvent e) { - if (Item.State == CarouselItemState.Selected) + if (Item.State.Value == CarouselItemState.Selected) startRequested?.Invoke(beatmap); return base.OnClick(e); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index e5d12151d8..540d74a8d3 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -15,6 +15,7 @@ using osu.Framework.Graphics.UserInterface; 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.Graphics.UserInterface; using osu.Game.Overlays; @@ -63,16 +64,14 @@ namespace osu.Game.Screens.Select.Carousel { new OsuSpriteText { - Font = @"Exo2.0-BoldItalic", Text = new LocalisedString((beatmapSet.Metadata.TitleUnicode, beatmapSet.Metadata.Title)), - TextSize = 22, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true), Shadow = true, }, new OsuSpriteText { - Font = @"Exo2.0-SemiBoldItalic", Text = new LocalisedString((beatmapSet.Metadata.ArtistUnicode, beatmapSet.Metadata.Artist)), - TextSize = 17, + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true), Shadow = true, }, new FillFlowContainer @@ -109,7 +108,7 @@ namespace osu.Game.Screens.Select.Carousel { List items = new List(); - if (Item.State == CarouselItemState.NotSelected) + if (Item.State.Value == CarouselItemState.NotSelected) items.Add(new OsuMenuItem("Expand", MenuItemType.Highlighted, () => Item.State.Value = CarouselItemState.Selected)); if (beatmapSet.OnlineBeatmapSetID != null) @@ -189,7 +188,7 @@ namespace osu.Game.Screens.Select.Carousel : base(item.Beatmap) { filtered.BindTo(item.Filtered); - filtered.ValueChanged += v => Schedule(() => this.FadeTo(v ? 0.1f : 1, 100)); + filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); } } diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index c856f4c85a..2d897148c1 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -120,7 +120,7 @@ namespace osu.Game.Screens.Select.Details AutoSizeAxes = Axes.Y, Child = name = new OsuSpriteText { - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, bar = new Bar @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, }; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index 70ce6c0e87..db796ba5d2 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -70,7 +70,7 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "User Rating", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, ratingsBar = new Bar { @@ -87,14 +87,14 @@ namespace osu.Game.Screens.Select.Details negativeRatings = new OsuSpriteText { Text = "0", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, positiveRatings = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Text = @"0", - TextSize = 13, + Font = OsuFont.GetFont(size: 13) }, }, }, @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Rating Spread", - TextSize = 13, + Font = OsuFont.GetFont(size: 13), Margin = new MarginPadding { Top = 10, Bottom = 5 }, }, }, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 42f6606218..72a15e37e1 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -5,7 +5,7 @@ using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Select Group = group, Sort = sort, SearchText = searchTextBox.Text, - AllowConvertedBeatmaps = showConverted, + AllowConvertedBeatmaps = showConverted.Value, Ruleset = ruleset.Value }; @@ -146,12 +146,12 @@ namespace osu.Game.Screens.Select } }; - searchTextBox.Current.ValueChanged += t => FilterChanged?.Invoke(CreateCriteria()); + searchTextBox.Current.ValueChanged += _ => FilterChanged?.Invoke(CreateCriteria()); groupTabs.PinItem(GroupMode.All); groupTabs.PinItem(GroupMode.RecentlyPlayed); - groupTabs.Current.ValueChanged += val => Group = val; - sortTabs.Current.ValueChanged += val => Sort = val; + groupTabs.Current.ValueChanged += group => Group = group.NewValue; + sortTabs.Current.ValueChanged += sort => Sort = sort.NewValue; } public void Deactivate() @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Select sortTabs.AccentColour = colours.GreenLight; showConverted = config.GetBindable(OsuSetting.ShowConvertedBeatmaps); - showConverted.ValueChanged += val => updateCriteria(); + showConverted.ValueChanged += _ => updateCriteria(); ruleset.BindTo(parentRuleset); ruleset.BindValueChanged(_ => updateCriteria(), true); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 9750827553..4f1fd0188e 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index cb1f9234d8..6960739987 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -150,14 +150,14 @@ namespace osu.Game.Screens.Select.Options { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = @"", }, secondLine = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold), Text = @"", }, }, diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3be4dd8c0b..5ecbaf8d1f 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -10,7 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Audio.Track; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; @@ -285,7 +285,7 @@ namespace osu.Game.Screens.Select public void Edit(BeatmapInfo beatmap = null) { - Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap ?? beatmapNoDebounce); + Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap ?? beatmapNoDebounce); this.Push(new Editor()); } @@ -326,16 +326,16 @@ namespace osu.Game.Screens.Select private ScheduledDelegate selectionChangedDebounce; - private void workingBeatmapChanged(WorkingBeatmap beatmap) + private void workingBeatmapChanged(ValueChangedEvent e) { - if (beatmap is DummyWorkingBeatmap) return; + if (e.NewValue is DummyWorkingBeatmap) return; - if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(beatmap?.BeatmapInfo, false)) + if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch - if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != decoupledRuleset.Value) + if (e.NewValue?.BeatmapInfo?.Ruleset != null && e.NewValue.BeatmapInfo.Ruleset != decoupledRuleset.Value) { - Ruleset.Value = beatmap.BeatmapInfo.Ruleset; - Carousel.SelectBeatmap(beatmap.BeatmapInfo); + Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; + Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); } } @@ -444,7 +444,6 @@ namespace osu.Game.Screens.Select { base.LogoArriving(logo, resuming); - logo.RelativePositionAxes = Axes.Both; Vector2 position = new Vector2(0.95f, 0.96f); if (logo.Alpha > 0.8f) @@ -510,14 +509,15 @@ namespace osu.Game.Screens.Select public override bool OnExiting(IScreen next) { + if (base.OnExiting(next)) + return true; + if (ModSelect.State == Visibility.Visible) { ModSelect.Hide(); return true; } - FinaliseSelection(performStartAction: false); - beatmapInfoWedge.State = Visibility.Hidden; this.FadeOut(100); @@ -530,7 +530,7 @@ namespace osu.Game.Screens.Select SelectedMods.UnbindAll(); Beatmap.Value.Mods.Value = new Mod[] { }; - return base.OnExiting(next); + return false; } protected override void Dispose(bool isDisposing) @@ -599,9 +599,9 @@ namespace osu.Game.Screens.Select { // manual binding to parent ruleset to allow for delayed load in the incoming direction. rulesetNoDebounce = decoupledRuleset.Value = Ruleset.Value; - Ruleset.ValueChanged += updateSelectedRuleset; + Ruleset.ValueChanged += r => updateSelectedRuleset(r.NewValue); - decoupledRuleset.ValueChanged += r => Ruleset.Value = r; + decoupledRuleset.ValueChanged += r => Ruleset.Value = r.NewValue; decoupledRuleset.DisabledChanged += r => Ruleset.Disabled = r; Beatmap.BindDisabledChanged(disabled => Carousel.AllowSelection = !disabled, true); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 43b194d8d0..f8445a4a7d 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -23,6 +23,7 @@ using osuTK.Graphics; using osu.Framework.IO.Stores; using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; +using osu.Game.Graphics; namespace osu.Game.Screens.Tournament { @@ -151,8 +152,7 @@ namespace osu.Game.Screens.Tournament Alpha = 0, - Font = "Exo2.0-Light", - TextSize = 42f + Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42), } } }, @@ -175,8 +175,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.TopCentre, Text = "Control Panel", - TextSize = 22f, - Font = "Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22), }, new FillFlowContainer { diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game/Screens/Tournament/Group.cs index c9d477dbcd..4fed10b94d 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game/Screens/Tournament/Group.cs @@ -14,6 +14,7 @@ using osuTK; using osuTK.Graphics; using osu.Game.Screens.Tournament.Teams; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; namespace osu.Game.Screens.Tournament { @@ -52,8 +53,7 @@ namespace osu.Game.Screens.Tournament Position = new Vector2(0, 7f), Text = $"GROUP {name.ToUpperInvariant()}", - TextSize = 8f, - Font = @"Exo2.0-Bold", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 8), Colour = new Color4(255, 204, 34, 255), }, teams = new FillFlowContainer @@ -162,8 +162,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.TopCentre, Text = team.Acronym.ToUpperInvariant(), - TextSize = 10f, - Font = @"Exo2.0-Bold" + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10), } } } diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index d51c11c5f4..36e95f4038 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -4,7 +4,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -33,7 +33,7 @@ namespace osu.Game.Skinning public Drawable GetDrawableComponent(string componentName) { Drawable sourceDrawable; - if (beatmapSkins && (sourceDrawable = source.GetDrawableComponent(componentName)) != null) + if (beatmapSkins.Value && (sourceDrawable = source.GetDrawableComponent(componentName)) != null) return sourceDrawable; return fallbackSource?.GetDrawableComponent(componentName); } @@ -41,7 +41,7 @@ namespace osu.Game.Skinning public Texture GetTexture(string componentName) { Texture sourceTexture; - if (beatmapSkins && (sourceTexture = source.GetTexture(componentName)) != null) + if (beatmapSkins.Value && (sourceTexture = source.GetTexture(componentName)) != null) return sourceTexture; return fallbackSource.GetTexture(componentName); } @@ -49,7 +49,7 @@ namespace osu.Game.Skinning public SampleChannel GetSample(string sampleName) { SampleChannel sourceChannel; - if (beatmapHitsounds && (sourceChannel = source.GetSample(sampleName)) != null) + if (beatmapHitsounds.Value && (sourceChannel = source.GetSample(sampleName)) != null) return sourceChannel; return fallbackSource?.GetSample(sampleName); } @@ -58,7 +58,7 @@ namespace osu.Game.Skinning { TValue val; if ((source as Skin)?.Configuration is TConfiguration conf) - if (beatmapSkins && (val = query.Invoke(conf)) != null) + if (beatmapSkins.Value && (val = query.Invoke(conf)) != null) return val; return fallbackSource == null ? default : fallbackSource.GetValue(query); diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index f8831bd26f..f6bbbc8355 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -8,7 +8,7 @@ using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; using osu.Framework.Platform; @@ -42,10 +42,10 @@ namespace osu.Game.Skinning CurrentSkinInfo.Value = SkinInfo.Default; }; - CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = getSkin(info); + CurrentSkinInfo.ValueChanged += skin => CurrentSkin.Value = getSkin(skin.NewValue); CurrentSkin.ValueChanged += skin => { - if (skin.SkinInfo != CurrentSkinInfo.Value) + if (skin.NewValue.SkinInfo != CurrentSkinInfo.Value) throw new InvalidOperationException($"Setting {nameof(CurrentSkin)}'s value directly is not supported. Use {nameof(CurrentSkinInfo)} instead."); SourceChanged?.Invoke(); diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 94bb4f2525..02691da9a9 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -3,7 +3,7 @@ using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs index 1591823bc1..9fa481b8b6 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs @@ -4,7 +4,7 @@ using System.IO; using osu.Framework.Allocation; using osu.Framework.Audio.Sample; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Beatmaps; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 05cde37eb7..604260a38c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -3,7 +3,7 @@ using osuTK; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index bfbfed082a..90b5178169 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,29 +1,133 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osuTK; namespace osu.Game.Tests.Beatmaps { public class TestWorkingBeatmap : WorkingBeatmap { - public TestWorkingBeatmap(RulesetInfo ruleset) - : this(new TestBeatmap(ruleset)) + private readonly TrackVirtualManual track; + private readonly IBeatmap beatmap; + + /// + /// Create an instance which creates a for the provided ruleset when requested. + /// + /// The target ruleset. + /// A clock which should be used instead of a stopwatch for virtual time progression. + public TestWorkingBeatmap(RulesetInfo ruleset, IFrameBasedClock referenceClock) + : this(new TestBeatmap(ruleset), referenceClock) { } - public TestWorkingBeatmap(IBeatmap beatmap) + /// + /// Create an instance which provides the when requested. + /// + /// The beatmap + /// An optional clock which should be used instead of a stopwatch for virtual time progression. + public TestWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock referenceClock = null) : base(beatmap.BeatmapInfo) { this.beatmap = beatmap; + + if (referenceClock != null) + track = new TrackVirtualManual(referenceClock); } - private readonly IBeatmap beatmap; protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; - protected override Track GetTrack() => null; + protected override Track GetTrack() => track; + + /// + /// A virtual track which tracks a reference clock. + /// + public class TrackVirtualManual : Track + { + private readonly IFrameBasedClock referenceClock; + + private readonly ManualClock clock = new ManualClock(); + + private bool running; + + /// + /// Local offset added to the reference clock to resolve correct time. + /// + private double offset; + + public TrackVirtualManual(IFrameBasedClock referenceClock) + { + this.referenceClock = referenceClock; + Length = double.PositiveInfinity; + } + + public override bool Seek(double seek) + { + offset = MathHelper.Clamp(seek, 0, Length); + lastReferenceTime = null; + return true; + } + + public override void Start() + { + running = true; + } + + public override void Reset() + { + Seek(0); + base.Reset(); + } + + public override void Stop() + { + if (running) + { + running = false; + // on stopping, the current value should be transferred out of the clock, as we can no longer rely on + // the referenceClock (which will still be counting time). + offset = clock.CurrentTime; + lastReferenceTime = null; + } + } + + public override bool IsRunning => running; + + private double? lastReferenceTime; + + public override double CurrentTime => clock.CurrentTime; + + protected override void UpdateState() + { + base.UpdateState(); + + if (running) + { + double refTime = referenceClock.CurrentTime; + + if (!lastReferenceTime.HasValue) + { + // if the clock just started running, the current value should be transferred to the offset + // (to zero the progression of time). + offset -= refTime; + } + + lastReferenceTime = refTime; + } + + clock.CurrentTime = Math.Min((lastReferenceTime ?? 0) + offset, Length); + + if (CurrentTime >= Length) + { + Stop(); + RaiseCompleted(); + } + } + } } } diff --git a/osu.Game/Tests/Visual/EditorClockTestCase.cs b/osu.Game/Tests/Visual/EditorClockTestCase.cs index 3ce91ed052..7f36a0e142 100644 --- a/osu.Game/Tests/Visual/EditorClockTestCase.cs +++ b/osu.Game/Tests/Visual/EditorClockTestCase.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Input.Events; using osu.Framework.Timing; using osu.Game.Beatmaps; @@ -41,10 +42,10 @@ namespace osu.Game.Tests.Visual Beatmap.BindValueChanged(beatmapChanged, true); } - private void beatmapChanged(WorkingBeatmap working) + private void beatmapChanged(ValueChangedEvent e) { - Clock.ControlPointInfo = working.Beatmap.ControlPointInfo; - Clock.ChangeSource((IAdjustableClock)working.Track ?? new StopwatchClock()); + Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo; + Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock()); Clock.ProcessFrame(); } diff --git a/osu.Game/Tests/Visual/EditorTestCase.cs b/osu.Game/Tests/Visual/EditorTestCase.cs index bc5f937480..67a1cb6de3 100644 --- a/osu.Game/Tests/Visual/EditorTestCase.cs +++ b/osu.Game/Tests/Visual/EditorTestCase.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo); + Beatmap.Value = new TestWorkingBeatmap(ruleset.RulesetInfo, null); LoadComponentAsync(new Editor(), LoadScreen); } diff --git a/osu.Game/Tests/Visual/MultiplayerTestCase.cs b/osu.Game/Tests/Visual/MultiplayerTestCase.cs index 578ef6632c..bb866cf750 100644 --- a/osu.Game/Tests/Visual/MultiplayerTestCase.cs +++ b/osu.Game/Tests/Visual/MultiplayerTestCase.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Game.Online.Multiplayer; namespace osu.Game.Tests.Visual @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual protected Room Room { - get => currentRoom; + get => currentRoom.Value; set => currentRoom.Value = value; } diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index 6bff4c0291..2fbf6f7e46 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -5,7 +5,7 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Game.Beatmaps; diff --git a/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.cs new file mode 100644 index 0000000000..14b4af1e7d --- /dev/null +++ b/osu.Game/Tests/Visual/RateAdjustedBeatmapTestCase.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. + +namespace osu.Game.Tests.Visual +{ + /// + /// Test case which adjusts the beatmap's rate to match any speed adjustments in visual tests. + /// + public abstract class RateAdjustedBeatmapTestCase : ScreenTestCase + { + protected override void Update() + { + base.Update(); + + // note that this will override any mod rate application + Beatmap.Value.Track.Rate = Clock.Rate; + } + } +} diff --git a/osu.Game/Tests/Visual/ScrollingTestContainer.cs b/osu.Game/Tests/Visual/ScrollingTestContainer.cs index 43cfb61d1b..19d1e18939 100644 --- a/osu.Game/Tests/Visual/ScrollingTestContainer.cs +++ b/osu.Game/Tests/Visual/ScrollingTestContainer.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Lists; using osu.Game.Configuration; diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index a926a06295..5ff798c40d 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -16,7 +16,7 @@ using osuTK.Graphics; namespace osu.Game.Tests.Visual { - public abstract class TestCasePlayer : ScreenTestCase + public abstract class TestCasePlayer : RateAdjustedBeatmapTestCase { private readonly Ruleset ruleset; @@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual private Player loadPlayerFor(Ruleset r) { var beatmap = CreateBeatmap(r); - var working = new TestWorkingBeatmap(beatmap); + var working = new TestWorkingBeatmap(beatmap, Clock); workingWeakReferences.Add(working); @@ -121,14 +121,6 @@ namespace osu.Game.Tests.Visual return player; } - protected override void Update() - { - base.Update(); - - // note that this will override any mod rate application - Beatmap.Value.Track.Rate = Clock.Rate; - } - protected virtual Player CreatePlayer(Ruleset ruleset) => new Player { AllowPause = false, diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index fca1510182..fb586d6f58 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; @@ -65,7 +65,7 @@ namespace osu.Game.Users private void openProfile() { - if (!OpenOnClick) + if (!OpenOnClick.Value) return; if (user != null) @@ -78,7 +78,7 @@ namespace osu.Game.Users protected override bool OnClick(ClickEvent e) { - if (!Enabled) + if (!Enabled.Value) return false; return base.OnClick(e); } diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index 31e3de1f27..4039e45e3d 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -1,7 +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.Configuration; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index acffd5073b..745ebb75fc 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -3,7 +3,7 @@ using System; using Newtonsoft.Json; -using osu.Framework.Configuration; +using osu.Framework.Bindables; namespace osu.Game.Users { diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index b1bf0c15a5..4dfde04e07 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -5,7 +5,7 @@ using System; using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Configuration; +using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -116,8 +116,7 @@ namespace osu.Game.Users new OsuSpriteText { Text = user.Username, - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic", + Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 18, italics: true), }, infoContainer = new FillFlowContainer { @@ -173,7 +172,7 @@ namespace osu.Game.Users { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = @"Exo2.0-Semibold", + Font = OsuFont.GetFont(weight: FontWeight.SemiBold), }, }, }, @@ -191,8 +190,8 @@ namespace osu.Game.Users }); } - Status.ValueChanged += displayStatus; - Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); + Status.ValueChanged += status => displayStatus(status.NewValue); + Status.ValueChanged += status => statusBg.FadeColour(status.NewValue?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); base.Action = ViewProfile = () => { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6b94fa4f98..f464dafd3f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -16,7 +16,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d677ef4e21..bf38335e0c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + +