1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 09:22:54 +08:00

Merge branch 'master' into expand-social-tab

This commit is contained in:
Aergwyn 2018-01-01 12:00:50 +01:00
commit cc4ef5d0aa
85 changed files with 558 additions and 272 deletions

36
COMPILING.md Normal file
View File

@ -0,0 +1,36 @@
# Linux
### 1. Requirements:
Mono >= 5.4.0 (>= 5.8.0 recommended)
Please check [here](http://www.mono-project.com/download/) for stable or [here](http://www.mono-project.com/download/alpha/) for an alpha release.
NuGet >= 4.4.0
msbuild
git
### 2. Cloning project
Clone the entire repository with submodules using
```
git clone https://github.com/ppy/osu --recursive
```
Then restore NuGet packages from the repository
```
nuget restore
```
### 3. Compiling
Simply run `msbuild` where `osu.sln` is located, this will create all binaries in `osu/osu.Desktop/bin/Debug`.
### 4. Optimizing
If you want additional performance you can change build type to Release with
```
msbuild -p:Configuration=Release
```
Additionally, mono provides an AOT utility which attempts to precompile binaries. You can utilize that by running
```
mono --aot ./osu\!.exe
```
### 5. Troubleshooting
You may run into trouble with NuGet versioning, as the one in packaging system is almost always out of date. Simply run
```
nuget
sudo nuget update -self
```
**Warning** NuGet creates few config files when it's run for the first time.
Do not run NuGet as root on the first run or you might run into very peculiar issues.

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="opentk-develop" value="https://www.myget.org/F/opentk-develop" />
</packageSources>
</configuration>

View File

@ -8,8 +8,11 @@ This is still heavily under development and is not intended for end-user use. Th
# Requirements # Requirements
- A desktop platform which can compile .NET 4.5 (tested on macOS, linux and windows). We recommend using [Visual Studio Code](https://code.visualstudio.com/) (all platforms) or [Visual Studio Community Edition](https://www.visualstudio.com/) (windows only), both of which are free. - A desktop platform that can compile .NET 4.6.1. We recommend using [Visual Studio Community Edition](https://www.visualstudio.com/) (Windows), [Visual Studio for Mac](https://www.visualstudio.com/vs/visual-studio-mac/) (macOS) or [MonoDevelop](http://www.monodevelop.com/download/) (Linux), all of which are free. [Visual Studio Code](https://code.visualstudio.com/) may also be used but requires further setup steps which are not covered here.
- Make sure you initialise and keep submodules up-to-date.
# Getting Started
- Clone the repository including submodules (`git clone --recurse-submodules https://github.com/ppy/osu`)
- Build in your IDE of choice (recommended IDEs automatically restore nuget packages; if you are using an alternative make sure to `nuget restore`)
# Contributing # Contributing

View File

@ -136,7 +136,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL"> <Reference Include="SharpCompress, Version=0.18.1.0, Culture=neutral, PublicKeyToken=afb0a02973931d96, processorArchitecture=MSIL">

View File

@ -6,7 +6,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<packages> <packages>
<package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" /> <package id="DeltaCompressionDotNet" version="1.1.0" targetFramework="net45" />
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" /> <package id="Mono.Cecil" version="0.9.6.4" targetFramework="net45" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
<package id="SharpCompress" version="0.18.1" targetFramework="net461" /> <package id="SharpCompress" version="0.18.1" targetFramework="net461" />
<package id="Splat" version="2.0.0" targetFramework="net45" /> <package id="Splat" version="2.0.0" targetFramework="net45" />
<package id="SQLitePCLRaw.bundle_green" version="1.1.8" targetFramework="net461" /> <package id="SQLitePCLRaw.bundle_green" version="1.1.8" targetFramework="net461" />

View File

@ -6,6 +6,7 @@ using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Objects.Drawable namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {

View File

@ -5,7 +5,6 @@ using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Judgements;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;

View File

@ -37,7 +37,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
</packages> </packages>

View File

@ -2,7 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Judgements namespace osu.Game.Rulesets.Mania.Judgements
{ {

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Judgements namespace osu.Game.Rulesets.Mania.Judgements
{ {
@ -24,4 +24,4 @@ namespace osu.Game.Rulesets.Mania.Judgements
} }
} }
} }
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Judgements namespace osu.Game.Rulesets.Mania.Judgements
{ {
@ -11,4 +11,4 @@ namespace osu.Game.Rulesets.Mania.Judgements
protected override int NumericResultFor(HitResult result) => 20; protected override int NumericResultFor(HitResult result) => 20;
} }
} }

View File

@ -2,7 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Judgements namespace osu.Game.Rulesets.Mania.Judgements
{ {

View File

@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects.Drawables namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {

View File

@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects.Drawables namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
@ -113,4 +114,4 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
UpdateJudgement(true); UpdateJudgement(true);
} }
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Objects.Drawables namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {

View File

@ -6,7 +6,6 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;

View File

@ -13,7 +13,7 @@ using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables;
using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.Timing;
using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.Timing;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;

View File

@ -37,7 +37,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
</packages> </packages>

View File

@ -4,7 +4,7 @@
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Judgements namespace osu.Game.Rulesets.Osu.Judgements
{ {
@ -34,4 +34,4 @@ namespace osu.Game.Rulesets.Osu.Judgements
public ComboResult Combo; public ComboResult Combo;
} }
} }

View File

@ -11,8 +11,11 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Osu.Mods namespace osu.Game.Rulesets.Osu.Mods
{ {
@ -23,13 +26,86 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModEasy : ModEasy public class OsuModEasy : ModEasy
{ {
} }
public class OsuModHidden : ModHidden public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects
{ {
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; public override string Description => @"Play with no approach circles and fading notes for a slight score advantage.";
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
private const double fade_in_duration_multiplier = 0.4;
private const double fade_out_duration_multiplier = 0.3;
private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT;
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
{
foreach (var d in drawables.OfType<DrawableOsuHitObject>())
{
d.ApplyCustomUpdateState += ApplyHiddenState;
d.FadeInDuration = preEmpt * fade_in_duration_multiplier;
}
}
protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state)
{
if (!(drawable is DrawableOsuHitObject d))
return;
var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration;
var fadeOutDuration = preEmpt * fade_out_duration_multiplier;
// new duration from completed fade in to end (before fading out)
var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime;
switch (drawable)
{
case DrawableHitCircle circle:
// we don't want to see the approach circle
circle.ApproachCircle.Hide();
// fade out immediately after fade in.
using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true))
circle.FadeOut(fadeOutDuration);
break;
case DrawableSlider slider:
using (slider.BeginAbsoluteSequence(fadeOutStartTime, true))
{
slider.Body.FadeOut(longFadeDuration, Easing.Out);
// delay a bit less to let the sliderball fade out peacefully instead of having a hard cut
using (slider.BeginDelayedSequence(longFadeDuration - fadeOutDuration, true))
slider.Ball.FadeOut(fadeOutDuration);
}
break;
case DrawableSpinner spinner:
// hide elements we don't care about.
spinner.Disc.Hide();
spinner.Ticks.Hide();
spinner.Background.Hide();
using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true))
{
spinner.FadeOut(fadeOutDuration);
// speed up the end sequence accordingly
switch (state)
{
case ArmedState.Hit:
spinner.ScaleTo(spinner.Scale * 1.2f, fadeOutDuration * 2, Easing.Out);
break;
case ArmedState.Miss:
spinner.ScaleTo(spinner.Scale * 0.8f, fadeOutDuration * 2, Easing.In);
break;
}
spinner.Expire();
}
break;
}
}
} }
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject> public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
@ -51,11 +127,6 @@ namespace osu.Game.Rulesets.Osu.Mods
slider.ControlPoints = newControlPoints; slider.ControlPoints = newControlPoints;
slider.Curve?.Calculate(); // Recalculate the slider curve slider.Curve?.Calculate(); // Recalculate the slider curve
} }
public void ApplyToHitObjects(RulesetContainer<OsuHitObject> rulesetContainer)
{
}
} }
public class OsuModSuddenDeath : ModSuddenDeath public class OsuModSuddenDeath : ModSuddenDeath
@ -96,7 +167,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModPerfect : ModPerfect public class OsuModPerfect : ModPerfect
{ {
} }
public class OsuModSpunOut : Mod public class OsuModSpunOut : Mod

View File

@ -6,8 +6,8 @@ using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly NumberPiece number; private readonly NumberPiece number;
private readonly GlowPiece glow; private readonly GlowPiece glow;
public DrawableHitCircle(OsuHitObject h) : base(h) public DrawableHitCircle(HitCircle h) : base(h)
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}, },
number = new NumberPiece number = new NumberPiece
{ {
Text = h is Spinner ? "S" : (HitObject.ComboIndex + 1).ToString(), Text = (HitObject.ComboIndex + 1).ToString(),
}, },
ring = new RingPiece(), ring = new RingPiece(),
flash = new FlashPiece(), flash = new FlashPiece(),
@ -88,25 +88,27 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.UpdatePreemptState(); base.UpdatePreemptState();
ApproachCircle.FadeIn(Math.Min(TIME_FADEIN * 2, TIME_PREEMPT)); ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT));
ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT); ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT);
} }
protected override void UpdateCurrentState(ArmedState state) protected override void UpdateCurrentState(ArmedState state)
{ {
double duration = ((HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime) - HitObject.StartTime; glow.FadeOut(400);
glow.Delay(duration).FadeOut(400);
switch (state) switch (state)
{ {
case ArmedState.Idle: case ArmedState.Idle:
this.Delay(duration + TIME_PREEMPT).FadeOut(TIME_FADEOUT); this.Delay(TIME_PREEMPT).FadeOut(500);
Expire(true); Expire(true);
// override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early.
LifetimeEnd = HitObject.StartTime + HitObject.HitWindowFor(HitResult.Miss);
break; break;
case ArmedState.Miss: case ArmedState.Miss:
ApproachCircle.FadeOut(50); ApproachCircle.FadeOut(50);
this.FadeOut(TIME_FADEOUT / 5); this.FadeOut(100);
Expire(); Expire();
break; break;
case ArmedState.Hit: case ArmedState.Hit:

View File

@ -12,7 +12,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
public const float TIME_PREEMPT = 600; public const float TIME_PREEMPT = 600;
public const float TIME_FADEIN = 400; public const float TIME_FADEIN = 400;
public const float TIME_FADEOUT = 500;
/// <summary>
/// The number of milliseconds used to fade in.
/// </summary>
public virtual double FadeInDuration { get; set; } = TIME_FADEIN;
public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - TIME_PREEMPT;
protected DrawableOsuHitObject(OsuHitObject hitObject) protected DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject) : base(hitObject)
@ -37,10 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
protected virtual void UpdatePreemptState() protected virtual void UpdatePreemptState() => this.FadeIn(FadeInDuration);
{
this.FadeIn(TIME_FADEIN);
}
protected virtual void UpdateCurrentState(ArmedState state) protected virtual void UpdateCurrentState(ArmedState state)
{ {

View File

@ -2,10 +2,10 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -24,4 +24,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.LoadComplete(); base.LoadComplete();
} }
} }
} }

View File

@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -24,19 +25,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
this.repeatPoint = repeatPoint; this.repeatPoint = repeatPoint;
this.drawableSlider = drawableSlider; this.drawableSlider = drawableSlider;
AutoSizeAxes = Axes.Both; Size = new Vector2(32 * repeatPoint.Scale);
Blending = BlendingMode.Additive; Blending = BlendingMode.Additive;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Scale = new Vector2(0.5f);
Children = new Drawable[] Children = new Drawable[]
{ {
new SpriteIcon new SpriteIcon
{ {
Icon = FontAwesome.fa_eercast, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Icon = FontAwesome.fa_eercast
Origin = Anchor.Centre,
Size = new Vector2(32),
} }
}; };
} }

View File

@ -10,6 +10,7 @@ using System.Linq;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -17,23 +18,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
private readonly Slider slider; private readonly Slider slider;
private readonly DrawableHitCircle initialCircle; public readonly DrawableHitCircle InitialCircle;
private readonly List<ISliderProgress> components = new List<ISliderProgress>(); private readonly List<ISliderProgress> components = new List<ISliderProgress>();
private readonly Container<DrawableSliderTick> ticks; private readonly Container<DrawableSliderTick> ticks;
private readonly Container<DrawableRepeatPoint> repeatPoints; private readonly Container<DrawableRepeatPoint> repeatPoints;
private readonly SliderBody body; public readonly SliderBody Body;
private readonly SliderBall ball; public readonly SliderBall Ball;
public DrawableSlider(Slider s) : base(s) public DrawableSlider(Slider s)
: base(s)
{ {
slider = s; slider = s;
Children = new Drawable[] Children = new Drawable[]
{ {
body = new SliderBody(s) Body = new SliderBody(s)
{ {
AccentColour = AccentColour, AccentColour = AccentColour,
Position = s.StackedPosition, Position = s.StackedPosition,
@ -41,16 +43,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}, },
ticks = new Container<DrawableSliderTick>(), ticks = new Container<DrawableSliderTick>(),
repeatPoints = new Container<DrawableRepeatPoint>(), repeatPoints = new Container<DrawableRepeatPoint>(),
ball = new SliderBall(s) Ball = new SliderBall(s)
{ {
Scale = new Vector2(s.Scale), Scale = new Vector2(s.Scale),
AccentColour = AccentColour, AccentColour = AccentColour,
AlwaysPresent = true, AlwaysPresent = true,
Alpha = 0 Alpha = 0
}, },
initialCircle = new DrawableHitCircle(new HitCircle InitialCircle = new DrawableHitCircle(new HitCircle
{ {
//todo: avoid creating this temporary HitCircle.
StartTime = s.StartTime, StartTime = s.StartTime,
Position = s.StackedPosition, Position = s.StackedPosition,
ComboIndex = s.ComboIndex, ComboIndex = s.ComboIndex,
@ -61,16 +62,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}) })
}; };
components.Add(body); components.Add(Body);
components.Add(ball); components.Add(Ball);
AddNested(initialCircle); AddNested(InitialCircle);
var repeatDuration = s.Curve.Distance / s.Velocity; var repeatDuration = s.Curve.Distance / s.Velocity;
foreach (var tick in s.NestedHitObjects.OfType<SliderTick>()) foreach (var tick in s.NestedHitObjects.OfType<SliderTick>())
{ {
var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration; var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration;
var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? TIME_FADEIN : TIME_FADEIN / 2); var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2);
var fadeOutTime = repeatStartTime + repeatDuration; var fadeOutTime = repeatStartTime + repeatDuration;
var drawableTick = new DrawableSliderTick(tick) var drawableTick = new DrawableSliderTick(tick)
@ -87,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
foreach (var repeatPoint in s.NestedHitObjects.OfType<RepeatPoint>()) foreach (var repeatPoint in s.NestedHitObjects.OfType<RepeatPoint>())
{ {
var repeatStartTime = s.StartTime + repeatPoint.RepeatIndex * repeatDuration; var repeatStartTime = s.StartTime + repeatPoint.RepeatIndex * repeatDuration;
var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? TIME_FADEIN : TIME_FADEIN / 2); var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2);
var fadeOutTime = repeatStartTime + repeatDuration; var fadeOutTime = repeatStartTime + repeatDuration;
var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this) var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this)
@ -105,11 +106,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private int currentRepeat; private int currentRepeat;
public bool Tracking; public bool Tracking;
public override double FadeInDuration
{
get { return base.FadeInDuration; }
set { InitialCircle.FadeInDuration = base.FadeInDuration = value; }
}
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
Tracking = ball.Tracking; Tracking = Ball.Tracking;
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
@ -120,11 +127,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
currentRepeat = repeat; currentRepeat = repeat;
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
if (!initialCircle.Judgements.Any(j => j.IsHit)) if (!InitialCircle.Judgements.Any(j => j.IsHit))
initialCircle.Position = slider.Curve.PositionAt(progress); InitialCircle.Position = slider.Curve.PositionAt(progress);
foreach (var c in components) c.UpdateProgress(progress, repeat); foreach (var c in components) c.UpdateProgress(progress, repeat);
foreach (var t in ticks.Children) t.Tracking = ball.Tracking; foreach (var t in ticks.Children) t.Tracking = Ball.Tracking;
} }
protected override void CheckForJudgements(bool userTriggered, double timeOffset) protected override void CheckForJudgements(bool userTriggered, double timeOffset)
@ -133,13 +140,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
var judgementsCount = ticks.Children.Count + repeatPoints.Children.Count + 1; var judgementsCount = ticks.Children.Count + repeatPoints.Children.Count + 1;
var judgementsHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit)) + repeatPoints.Children.Count(t => t.Judgements.Any(j => j.IsHit)); var judgementsHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit)) + repeatPoints.Children.Count(t => t.Judgements.Any(j => j.IsHit));
if (initialCircle.Judgements.Any(j => j.IsHit)) if (InitialCircle.Judgements.Any(j => j.IsHit))
judgementsHit++; judgementsHit++;
var hitFraction = (double)judgementsHit / judgementsCount; var hitFraction = (double)judgementsHit / judgementsCount;
if (hitFraction == 1 && initialCircle.Judgements.Any(j => j.Result == HitResult.Great)) if (hitFraction == 1 && InitialCircle.Judgements.Any(j => j.Result == HitResult.Great))
AddJudgement(new OsuJudgement { Result = HitResult.Great }); AddJudgement(new OsuJudgement { Result = HitResult.Great });
else if (hitFraction >= 0.5 && initialCircle.Judgements.Any(j => j.Result >= HitResult.Good)) else if (hitFraction >= 0.5 && InitialCircle.Judgements.Any(j => j.Result >= HitResult.Good))
AddJudgement(new OsuJudgement { Result = HitResult.Good }); AddJudgement(new OsuJudgement { Result = HitResult.Good });
else if (hitFraction > 0) else if (hitFraction > 0)
AddJudgement(new OsuJudgement { Result = HitResult.Meh }); AddJudgement(new OsuJudgement { Result = HitResult.Meh });
@ -150,21 +157,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void UpdateCurrentState(ArmedState state) protected override void UpdateCurrentState(ArmedState state)
{ {
ball.FadeIn(); Ball.FadeIn();
using (BeginDelayedSequence(slider.Duration, true)) using (BeginDelayedSequence(slider.Duration, true))
{ {
body.FadeOut(160); Body.FadeOut(160);
ball.FadeOut(160); Ball.FadeOut(160);
this.FadeOut(800) this.FadeOut(800)
.Expire(); .Expire();
} }
} }
public Drawable ProxiedLayer => initialCircle.ApproachCircle; public Drawable ProxiedLayer => InitialCircle.ApproachCircle;
public override Vector2 SelectionPoint => ToScreenSpace(body.Position); public override Vector2 SelectionPoint => ToScreenSpace(Body.Position);
public override Quad SelectionQuad => body.PathDrawQuad; public override Quad SelectionQuad => Body.PathDrawQuad;
} }
} }

View File

@ -8,6 +8,7 @@ using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {

View File

@ -13,6 +13,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
@ -20,13 +21,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
private readonly Spinner spinner; private readonly Spinner spinner;
private readonly SpinnerDisc disc; public readonly SpinnerDisc Disc;
private readonly SpinnerTicks ticks; public readonly SpinnerTicks Ticks;
private readonly SpinnerSpmCounter spmCounter; private readonly SpinnerSpmCounter spmCounter;
private readonly Container mainContainer; private readonly Container mainContainer;
private readonly SpinnerBackground background; public readonly SpinnerBackground Background;
private readonly Container circleContainer; private readonly Container circleContainer;
private readonly CirclePiece circle; private readonly CirclePiece circle;
private readonly GlowPiece glow; private readonly GlowPiece glow;
@ -84,20 +85,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Children = new Drawable[] Children = new Drawable[]
{ {
background = new SpinnerBackground Background = new SpinnerBackground
{ {
Alpha = 0.6f, Alpha = 0.6f,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
}, },
disc = new SpinnerDisc(spinner) Disc = new SpinnerDisc(spinner)
{ {
Scale = Vector2.Zero, Scale = Vector2.Zero,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
}, },
circleContainer.CreateProxy(), circleContainer.CreateProxy(),
ticks = new SpinnerTicks Ticks = new SpinnerTicks
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -114,22 +115,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}; };
} }
public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / spinner.SpinsRequired, 0, 1); public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / spinner.SpinsRequired, 0, 1);
protected override void CheckForJudgements(bool userTriggered, double timeOffset) protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{ {
if (Time.Current < HitObject.StartTime) return; if (Time.Current < HitObject.StartTime) return;
if (Progress >= 1 && !disc.Complete) if (Progress >= 1 && !Disc.Complete)
{ {
disc.Complete = true; Disc.Complete = true;
const float duration = 200; const float duration = 200;
disc.FadeAccent(completeColour, duration); Disc.FadeAccent(completeColour, duration);
background.FadeAccent(completeColour, duration); Background.FadeAccent(completeColour, duration);
background.FadeOut(duration); Background.FadeOut(duration);
circle.FadeColour(completeColour, duration); circle.FadeColour(completeColour, duration);
glow.FadeColour(completeColour, duration); glow.FadeColour(completeColour, duration);
@ -153,20 +154,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
normalColour = baseColour; normalColour = baseColour;
background.AccentColour = normalColour; Background.AccentColour = normalColour;
completeColour = colours.YellowLight.Opacity(0.75f); completeColour = colours.YellowLight.Opacity(0.75f);
disc.AccentColour = fillColour; Disc.AccentColour = fillColour;
circle.Colour = colours.BlueDark; circle.Colour = colours.BlueDark;
glow.Colour = colours.BlueDark; glow.Colour = colours.BlueDark;
} }
protected override void Update() protected override void Update()
{ {
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton); Disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
if (!spmCounter.IsPresent && disc.Tracking) if (!spmCounter.IsPresent && Disc.Tracking)
spmCounter.FadeIn(TIME_FADEIN); spmCounter.FadeIn(FadeInDuration);
base.Update(); base.Update();
} }
@ -175,14 +176,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.UpdateAfterChildren(); base.UpdateAfterChildren();
circle.Rotation = disc.Rotation; circle.Rotation = Disc.Rotation;
ticks.Rotation = disc.Rotation; Ticks.Rotation = Disc.Rotation;
spmCounter.SetRotation(disc.RotationAbsolute); spmCounter.SetRotation(Disc.RotationAbsolute);
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); Disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
symbol.RotateTo(disc.Rotation / 2, 500, Easing.OutQuint); symbol.RotateTo(Disc.Rotation / 2, 500, Easing.OutQuint);
} }
protected override void UpdatePreemptState() protected override void UpdatePreemptState()
@ -192,7 +193,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
circleContainer.ScaleTo(spinner.Scale * 0.3f); circleContainer.ScaleTo(spinner.Scale * 0.3f);
circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint);
disc.RotateTo(-720); Disc.RotateTo(-720);
symbol.RotateTo(-720); symbol.RotateTo(-720);
mainContainer mainContainer

View File

@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private const float idle_alpha = 0.2f; private const float idle_alpha = 0.2f;
private const float tracking_alpha = 0.4f; private const float tracking_alpha = 0.4f;
public override bool IsPresent => true; // handle input when hidden
public SpinnerDisc(Spinner s) public SpinnerDisc(Spinner s)
{ {
spinner = s; spinner = s;

View File

@ -7,7 +7,7 @@ using OpenTK;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects namespace osu.Game.Rulesets.Osu.Objects
{ {

View File

@ -9,9 +9,9 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Replays namespace osu.Game.Rulesets.Osu.Replays
{ {

View File

@ -41,10 +41,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
mods = Score.Mods; mods = Score.Mods;
accuracy = Score.Accuracy; accuracy = Score.Accuracy;
scoreMaxCombo = Score.MaxCombo; scoreMaxCombo = Score.MaxCombo;
count300 = Convert.ToInt32(Score.Statistics["300"]); count300 = Convert.ToInt32(Score.Statistics[HitResult.Great]);
count100 = Convert.ToInt32(Score.Statistics["100"]); count100 = Convert.ToInt32(Score.Statistics[HitResult.Good]);
count50 = Convert.ToInt32(Score.Statistics["50"]); count50 = Convert.ToInt32(Score.Statistics[HitResult.Meh]);
countMiss = Convert.ToInt32(Score.Statistics["x"]); countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]);
// Don't count scores made with supposedly unranked mods // Don't count scores made with supposedly unranked mods
if (mods.Any(m => !m.Ranked)) if (mods.Any(m => !m.Ranked))

View File

@ -6,7 +6,6 @@ using System.Linq;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
@ -33,8 +32,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
foreach (var obj in beatmap.HitObjects) foreach (var obj in beatmap.HitObjects)
{ {
var slider = obj as Slider; if (obj is Slider slider)
if (slider != null)
{ {
// Head // Head
AddJudgement(new OsuJudgement { Result = HitResult.Great }); AddJudgement(new OsuJudgement { Result = HitResult.Great });
@ -64,10 +62,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
{ {
base.PopulateScore(score); base.PopulateScore(score);
score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(HitResult.Great); score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great);
score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(HitResult.Good); score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good);
score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(HitResult.Meh); score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh);
score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(HitResult.Miss); score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss);
} }
protected override void OnNewJudgement(Judgement judgement) protected override void OnNewJudgement(Judgement judgement)

View File

@ -11,60 +11,106 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Osu.Mods;
using OpenTK.Graphics;
using osu.Game.Rulesets.Osu.Judgements;
using System.Collections.Generic;
using System;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[Ignore("getting CI working")] [Ignore("getting CI working")]
public class TestCaseHitCircle : OsuTestCase public class TestCaseHitCircle : OsuTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(HitCircle),
typeof(OsuModHidden),
typeof(DrawableHitCircle)
};
private readonly Container content; private readonly Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private bool auto; private bool auto;
private bool hidden;
private int depthIndex; private int depthIndex;
private int circleSize;
private float circleScale = 1;
public TestCaseHitCircle() public TestCaseHitCircle()
{ {
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
AddStep("Single", () => addSingle()); AddStep("Single", () => testSingle());
AddStep("Stream", addStream); AddStep("Stream", testStream);
AddToggleStep("Auto", v => auto = v); AddToggleStep("Auto", v => auto = v);
AddToggleStep("Hidden", v => hidden = v);
AddSliderStep("CircleSize", 0, 10, 0, s => circleSize = s);
AddSliderStep("CircleScale", 0.5f, 2, 1, s => circleScale = s);
} }
private void addSingle(double timeOffset = 0, Vector2? positionOffset = null) private void testSingle(double timeOffset = 0, Vector2? positionOffset = null)
{ {
positionOffset = positionOffset ?? Vector2.Zero; positionOffset = positionOffset ?? Vector2.Zero;
var circle = new HitCircle var circle = new HitCircle
{ {
StartTime = Time.Current + 1000 + timeOffset, StartTime = Time.Current + 1000 + timeOffset,
Position = positionOffset.Value Position = positionOffset.Value,
ComboColour = Color4.LightSeaGreen
}; };
circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 0 }); circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
var drawable = new DrawableHitCircle(circle) var drawable = new TestDrawableHitCircle(circle, auto)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Scale = new Vector2(circleScale),
Depth = depthIndex++ Depth = depthIndex++
}; };
if (auto) if (auto)
drawable.State.Value = ArmedState.Hit; drawable.State.Value = ArmedState.Hit;
if (hidden)
new OsuModHidden().ApplyToDrawableHitObjects(new [] { drawable });
Add(drawable); Add(drawable);
} }
private void addStream() private void testStream()
{ {
Vector2 pos = Vector2.Zero; Vector2 pos = Vector2.Zero;
for (int i = 0; i <= 1000; i += 100) for (int i = 0; i <= 1000; i += 100)
{ {
addSingle(i, pos); testSingle(i, pos);
pos += new Vector2(10); pos += new Vector2(10);
} }
} }
private class TestDrawableHitCircle : DrawableHitCircle
{
private readonly bool auto;
public TestDrawableHitCircle(HitCircle h, bool auto) : base(h)
{
this.auto = auto;
}
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{
if (auto && !userTriggered && timeOffset > 0)
{
// pretend we really hit it
AddJudgement(new OsuJudgement
{
Result = HitObject.ScoreResultForOffset(timeOffset)
});
}
base.CheckForJudgements(userTriggered, timeOffset);
}
}
} }
} }

View File

@ -13,37 +13,52 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Osu.Mods;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[Ignore("getting CI working")] [Ignore("getting CI working")]
public class TestCaseSlider : OsuTestCase public class TestCaseSlider : OsuTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(DrawableSlider) }; public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(Slider),
typeof(HitCircle),
typeof(OsuModHidden),
typeof(DrawableSlider),
typeof(DrawableHitCircle),
typeof(DrawableSliderTick),
typeof(DrawableRepeatPoint)
};
private readonly Container content; private readonly Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private bool hidden;
private int repeats;
private int depthIndex;
private int circleSize;
private float circleScale = 1;
private double speedMultiplier = 2; private double speedMultiplier = 2;
private double sliderMultiplier = 2; private double sliderMultiplier = 2;
private int depthIndex;
public TestCaseSlider() public TestCaseSlider()
{ {
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
AddStep("Single", () => addSingle()); AddStep("Single", () => testSingle());
AddStep("Repeated (1)", () => addRepeated(1)); AddStep("Stream", testStream);
AddStep("Repeated (2)", () => addRepeated(2)); AddStep("Repeated", () => testRepeated(repeats));
AddStep("Repeated (3)", () => addRepeated(3)); AddToggleStep("Hidden", v => hidden = v);
AddStep("Repeated (4)", () => addRepeated(4)); AddSliderStep("Repeats", 1, 10, 1, s => repeats = s);
AddStep("Stream", addStream); AddSliderStep("CircleSize", 0, 10, 0, s => circleSize = s);
AddSliderStep("CircleScale", 0.5f, 2, 1, s => circleScale = s);
AddSliderStep("SpeedMultiplier", 0.01, 10, 2, s => speedMultiplier = s); AddSliderStep("SpeedMultiplier", 0.1, 10, 2, s => speedMultiplier = s);
AddSliderStep("SliderMultiplier", 0.01, 10, 2, s => sliderMultiplier = s); AddSliderStep("SliderMultiplier", 0.1, 10, 2, s => sliderMultiplier = s);
} }
private void addSingle(double timeOffset = 0, Vector2? positionOffset = null) private void testSingle(double timeOffset = 0, Vector2? positionOffset = null)
{ {
positionOffset = positionOffset ?? Vector2.Zero; positionOffset = positionOffset ?? Vector2.Zero;
@ -51,32 +66,19 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
StartTime = Time.Current + 1000 + timeOffset, StartTime = Time.Current + 1000 + timeOffset,
Position = new Vector2(-200, 0) + positionOffset.Value, Position = new Vector2(-200, 0) + positionOffset.Value,
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2> ControlPoints = new List<Vector2>
{ {
new Vector2(-200, 0) + positionOffset.Value, new Vector2(-200, 0) + positionOffset.Value,
new Vector2(400, 0) + positionOffset.Value, new Vector2(400, 0) + positionOffset.Value,
}, },
Distance = 400, Distance = 400
}; };
var cpi = new ControlPointInfo(); addSlider(slider);
cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier });
var difficulty = new BeatmapDifficulty
{
SliderMultiplier = (float)sliderMultiplier,
CircleSize = 0
};
slider.ApplyDefaults(cpi, difficulty);
Add(new DrawableSlider(slider)
{
Anchor = Anchor.Centre,
Depth = depthIndex++
});
} }
private void addRepeated(int repeats) private void testRepeated(int repeats)
{ {
// The first run through the slider is considered a repeat // The first run through the slider is considered a repeat
repeats++; repeats++;
@ -89,6 +91,7 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
StartTime = Time.Current + 1000, StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0), Position = new Vector2(-200, 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2> ControlPoints = new List<Vector2>
{ {
new Vector2(-200, 0), new Vector2(-200, 0),
@ -99,32 +102,45 @@ namespace osu.Game.Rulesets.Osu.Tests
RepeatSamples = repeatSamples RepeatSamples = repeatSamples
}; };
addSlider(slider);
}
private void testStream()
{
Vector2 pos = Vector2.Zero;
for (int i = 0; i <= 1000; i += 100)
{
testSingle(i, pos);
pos += new Vector2(10);
}
}
private void addSlider(Slider slider)
{
var cpi = new ControlPointInfo(); var cpi = new ControlPointInfo();
cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier });
var difficulty = new BeatmapDifficulty var difficulty = new BeatmapDifficulty
{ {
SliderMultiplier = (float)sliderMultiplier, SliderMultiplier = (float)sliderMultiplier,
CircleSize = 0 CircleSize = circleSize
}; };
slider.ApplyDefaults(cpi, difficulty); slider.ApplyDefaults(cpi, difficulty);
Add(new DrawableSlider(slider)
var drawable = new DrawableSlider(slider)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Scale = new Vector2(circleScale),
Depth = depthIndex++ Depth = depthIndex++
}); };
}
private void addStream() if (hidden)
{ new OsuModHidden().ApplyToDrawableHitObjects(new [] { drawable });
Vector2 pos = Vector2.Zero;
for (int i = 0; i <= 1000; i += 100) Add(drawable);
{
addSingle(i, pos);
pos += new Vector2(10);
}
} }
} }
} }

View File

@ -1,11 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using OpenTK;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -15,30 +19,47 @@ namespace osu.Game.Rulesets.Osu.Tests
[Ignore("getting CI working")] [Ignore("getting CI working")]
public class TestCaseSpinner : OsuTestCase public class TestCaseSpinner : OsuTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(Spinner),
typeof(OsuModHidden),
typeof(DrawableSpinner)
};
private readonly Container content; private readonly Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
private bool hidden;
private int depthIndex; private int depthIndex;
private int circleSize;
private float circleScale = 1;
public TestCaseSpinner() public TestCaseSpinner()
{ {
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
AddStep("Single", addSingle); AddStep("Single", testSingle);
AddToggleStep("Hidden", v => hidden = v);
AddSliderStep("CircleSize", 0, 10, 0, s => circleSize = s);
AddSliderStep("CircleScale", 0.5f, 2, 1, s => circleScale = s);
} }
private void addSingle() private void testSingle()
{ {
var spinner = new Spinner { StartTime = Time.Current + 1000, EndTime = Time.Current + 4000 }; var spinner = new Spinner { StartTime = Time.Current + 1000, EndTime = Time.Current + 4000 };
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = 0 }); spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
var drawable = new DrawableSpinner(spinner) var drawable = new DrawableSpinner(spinner)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Scale = new Vector2(circleScale),
Depth = depthIndex++ Depth = depthIndex++
}; };
if (hidden)
new OsuModHidden().ApplyToDrawableHitObjects(new [] { drawable });
Add(drawable); Add(drawable);
} }
} }

View File

@ -35,16 +35,13 @@ namespace osu.Game.Rulesets.Osu.UI
protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h) protected override DrawableHitObject<OsuHitObject> GetVisualRepresentation(OsuHitObject h)
{ {
var circle = h as HitCircle; if (h is HitCircle circle)
if (circle != null)
return new DrawableHitCircle(circle); return new DrawableHitCircle(circle);
var slider = h as Slider; if (h is Slider slider)
if (slider != null)
return new DrawableSlider(slider); return new DrawableSlider(slider);
var spinner = h as Spinner; if (h is Spinner spinner)
if (spinner != null)
return new DrawableSpinner(spinner); return new DrawableSpinner(spinner);
return null; return null;
} }

View File

@ -38,7 +38,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
</packages> </packages>

View File

@ -1,7 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Judgements namespace osu.Game.Rulesets.Taiko.Judgements
{ {
@ -20,4 +20,4 @@ namespace osu.Game.Rulesets.Taiko.Judgements
} }
} }
} }
} }

View File

@ -2,7 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Judgements namespace osu.Game.Rulesets.Taiko.Judgements
{ {

View File

@ -13,6 +13,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {

View File

@ -4,6 +4,7 @@
using System; using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;

View File

@ -5,6 +5,7 @@ using System;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;

View File

@ -3,7 +3,7 @@
using System; using System;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables

View File

@ -14,6 +14,7 @@ using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {

View File

@ -4,7 +4,6 @@
using System.Linq; using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;

View File

@ -20,6 +20,7 @@ using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Tests namespace osu.Game.Rulesets.Taiko.Tests
{ {

View File

@ -6,6 +6,7 @@ using osu.Framework.Allocation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI
{ {
@ -49,4 +50,4 @@ namespace osu.Game.Rulesets.Taiko.UI
base.LoadComplete(); base.LoadComplete();
} }
} }
} }

View File

@ -37,7 +37,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
</packages> </packages>

View File

@ -160,9 +160,9 @@ namespace osu.Game.Tests.Visual
}; };
foreach(var s in scores) foreach(var s in scores)
{ {
s.Statistics.Add("300", RNG.Next(2000)); s.Statistics.Add(HitResult.Great, RNG.Next(2000));
s.Statistics.Add("100", RNG.Next(2000)); s.Statistics.Add(HitResult.Good, RNG.Next(2000));
s.Statistics.Add("50", RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
anotherScores = new[] anotherScores = new[]
@ -272,9 +272,9 @@ namespace osu.Game.Tests.Visual
}; };
foreach (var s in anotherScores) foreach (var s in anotherScores)
{ {
s.Statistics.Add("300", RNG.Next(2000)); s.Statistics.Add(HitResult.Great, RNG.Next(2000));
s.Statistics.Add("100", RNG.Next(2000)); s.Statistics.Add(HitResult.Good, RNG.Next(2000));
s.Statistics.Add("50", RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
topScore = new OnlineScore topScore = new OnlineScore
@ -299,9 +299,9 @@ namespace osu.Game.Tests.Visual
TotalScore = 987654321, TotalScore = 987654321,
Accuracy = 0.8487, Accuracy = 0.8487,
}; };
topScore.Statistics.Add("300", RNG.Next(2000)); topScore.Statistics.Add(HitResult.Great, RNG.Next(2000));
topScore.Statistics.Add("100", RNG.Next(2000)); topScore.Statistics.Add(HitResult.Good, RNG.Next(2000));
topScore.Statistics.Add("50", RNG.Next(2000)); topScore.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -15,6 +15,15 @@ namespace osu.Game.Tests.Visual
{ {
private BeatmapManager beatmaps; private BeatmapManager beatmaps;
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(Score),
typeof(Results),
typeof(ResultsPage),
typeof(ResultsPageScore),
typeof(ResultsPageRanking)
};
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(BeatmapManager beatmaps) private void load(BeatmapManager beatmaps)
{ {
@ -41,12 +50,12 @@ namespace osu.Game.Tests.Visual
MaxCombo = 123, MaxCombo = 123,
Rank = ScoreRank.A, Rank = ScoreRank.A,
Date = DateTimeOffset.Now, Date = DateTimeOffset.Now,
Statistics = new Dictionary<string, dynamic> Statistics = new Dictionary<HitResult, dynamic>
{ {
{ "300", 50 }, { HitResult.Great, 50 },
{ "100", 20 }, { HitResult.Good, 20 },
{ "50", 50 }, { HitResult.Meh, 50 },
{ "x", 1 } { HitResult.Miss, 1 }
}, },
User = new User User = new User
{ {

View File

@ -38,7 +38,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />

View File

@ -6,6 +6,6 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<packages> <packages>
<package id="DeepEqual" version="1.6.0.0" targetFramework="net461" /> <package id="DeepEqual" version="1.6.0.0" targetFramework="net461" />
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net461" /> <package id="System.ValueTuple" version="4.4.0" targetFramework="net461" />
</packages> </packages>

View File

@ -122,26 +122,26 @@ namespace osu.Game.Online.API.Requests
{ {
foreach (var kvp in value) foreach (var kvp in value)
{ {
string key = kvp.Key; HitResult newKey;
switch (key) switch (kvp.Key)
{ {
case @"count_300": case @"count_300":
key = @"300"; newKey = HitResult.Great;
break; break;
case @"count_100": case @"count_100":
key = @"100"; newKey = HitResult.Good;
break; break;
case @"count_50": case @"count_50":
key = @"50"; newKey = HitResult.Meh;
break; break;
case @"count_miss": case @"count_miss":
key = @"x"; newKey = HitResult.Miss;
break; break;
default: default:
continue; continue;
} }
Statistics.Add(key, kvp.Value); Statistics.Add(newKey, kvp.Value);
} }
} }
} }

View File

@ -12,6 +12,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Overlays.Profile.Sections.Ranks; using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users; using osu.Game.Users;
@ -48,7 +49,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Font = @"Exo2.0-RegularItalic", Font = @"Exo2.0-RegularItalic",
Margin = new MarginPadding { Left = side_margin } Margin = new MarginPadding { Left = side_margin }
}, },
new DrawableFlag(score.User.Country?.FlagName) new DrawableFlag(score.User.Country)
{ {
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
@ -104,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Text = $"{score.Statistics["300"]}/{score.Statistics["100"]}/{score.Statistics["50"]}", Text = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}",
Font = @"Exo2.0-RegularItalic", Font = @"Exo2.0-RegularItalic",
Margin = new MarginPadding { Right = side_margin } Margin = new MarginPadding { Right = side_margin }
}, },

View File

@ -52,13 +52,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
score = value; score = value;
avatar.User = username.User = score.User; avatar.User = username.User = score.User;
flag.FlagName = score.User.Country?.FlagName; flag.Country = score.User.Country;
date.Text = $@"achieved {score.Date:MMM d, yyyy}"; date.Text = $@"achieved {score.Date:MMM d, yyyy}";
rank.UpdateRank(score.Rank); rank.UpdateRank(score.Rank);
totalScore.Value = $@"{score.TotalScore:N0}"; totalScore.Value = $@"{score.TotalScore:N0}";
accuracy.Value = $@"{score.Accuracy:P2}"; accuracy.Value = $@"{score.Accuracy:P2}";
statistics.Value = $"{score.Statistics["300"]}/{score.Statistics["100"]}/{score.Statistics["50"]}"; statistics.Value = $"{score.Statistics[HitResult.Great]}/{score.Statistics[HitResult.Good]}/{score.Statistics[HitResult.Meh]}";
modsContainer.Clear(); modsContainer.Clear();
foreach (Mod mod in score.Mods) foreach (Mod mod in score.Mods)

View File

@ -204,13 +204,13 @@ namespace osu.Game.Overlays.Mods
{ {
iconsContainer.AddRange(new[] iconsContainer.AddRange(new[]
{ {
backgroundIcon = new ModIcon(Mods[1]) backgroundIcon = new PassThroughTooltipModIcon(Mods[1])
{ {
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
Position = new Vector2(1.5f), Position = new Vector2(1.5f),
}, },
foregroundIcon = new ModIcon(Mods[0]) foregroundIcon = new PassThroughTooltipModIcon(Mods[0])
{ {
Origin = Anchor.BottomRight, Origin = Anchor.BottomRight,
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,
@ -220,7 +220,7 @@ namespace osu.Game.Overlays.Mods
} }
else else
{ {
iconsContainer.Add(foregroundIcon = new ModIcon(Mod) iconsContainer.Add(foregroundIcon = new PassThroughTooltipModIcon(Mod)
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -259,5 +259,14 @@ namespace osu.Game.Overlays.Mods
Mod = mod; Mod = mod;
} }
private class PassThroughTooltipModIcon : ModIcon
{
public override string TooltipText => null;
public PassThroughTooltipModIcon(Mod mod) : base(mod)
{
}
}
} }
} }

View File

@ -109,7 +109,7 @@ namespace osu.Game.Overlays.Profile
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
Y = -48, Y = -48,
}, },
countryFlag = new DrawableFlag(user.Country?.FlagName) countryFlag = new DrawableFlag(user.Country)
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
@ -333,7 +333,7 @@ namespace osu.Game.Overlays.Profile
{ {
infoTextLeft.AddText("from "); infoTextLeft.AddText("from ");
infoTextLeft.AddText(user.Country.FullName, boldItalic); infoTextLeft.AddText(user.Country.FullName, boldItalic);
countryFlag.FlagName = user.Country.FlagName; countryFlag.Country = user.Country;
} }
infoTextLeft.NewParagraph(); infoTextLeft.NewParagraph();

View File

@ -1,20 +1,23 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK; using OpenTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
namespace osu.Game.Overlays.Profile namespace osu.Game.Overlays.Profile
{ {
public class SupporterIcon : CircularContainer public class SupporterIcon : CircularContainer, IHasTooltip
{ {
private readonly Box background; private readonly Box background;
public string TooltipText => "osu!supporter";
public SupporterIcon() public SupporterIcon()
{ {
Masking = true; Masking = true;

View File

@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Judgements namespace osu.Game.Rulesets.Judgements
{ {

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Judgements namespace osu.Game.Rulesets.Judgements
{ {

View File

@ -0,0 +1,20 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for <see cref="Mod"/>s that can be applied to <see cref="DrawableHitObject"/>s.
/// </summary>
public interface IApplicableToDrawableHitObjects
{
/// <summary>
/// Applies this <see cref="IApplicableToDrawableHitObjects"/> to a list of <see cref="DrawableHitObject"/>s.
/// </summary>
/// <param name="drawable">The list of <see cref="DrawableHitObject"/>s to apply to.</param>
void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables);
}
}

View File

@ -16,6 +16,7 @@ using osu.Game.Graphics;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using OpenTK; using OpenTK;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Drawables namespace osu.Game.Rulesets.Objects.Drawables
{ {
@ -122,6 +123,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
{ {
UpdateState(state); UpdateState(state);
// apply any custom state overrides
ApplyCustomUpdateState?.Invoke(this, state);
if (State == ArmedState.Hit) if (State == ArmedState.Hit)
PlaySamples(); PlaySamples();
}; };
@ -243,9 +247,15 @@ namespace osu.Game.Rulesets.Objects.Drawables
h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j);
h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j);
h.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s);
nestedHitObjects.Add(h); nestedHitObjects.Add(h);
} }
/// <summary>
/// Bind to apply a custom state which can override the default implementation.
/// </summary>
public event Action<DrawableHitObject, ArmedState> ApplyCustomUpdateState;
protected abstract void UpdateState(ArmedState state); protected abstract void UpdateState(ArmedState state);
} }
} }

View File

@ -3,7 +3,7 @@
using System.ComponentModel; using System.ComponentModel;
namespace osu.Game.Rulesets.Objects.Drawables namespace osu.Game.Rulesets.Scoring
{ {
public enum HitResult public enum HitResult
{ {

View File

@ -40,6 +40,6 @@ namespace osu.Game.Rulesets.Scoring
public DateTimeOffset Date; public DateTimeOffset Date;
public Dictionary<string, object> Statistics = new Dictionary<string, object>(); public Dictionary<HitResult, object> Statistics = new Dictionary<HitResult, object>();
} }
} }

View File

@ -8,7 +8,6 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Scoring namespace osu.Game.Rulesets.Scoring
{ {

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.UI
private readonly ModType type; private readonly ModType type;
public string TooltipText { get; } public virtual string TooltipText { get; }
public ModIcon(Mod mod) public ModIcon(Mod mod)
{ {

View File

@ -260,6 +260,9 @@ namespace osu.Game.Rulesets.UI
} }
Playfield.PostProcess(); Playfield.PostProcess();
foreach (var mod in Mods.OfType<IApplicableToDrawableHitObjects>())
mod.ApplyToDrawableHitObjects(Playfield.HitObjects.Objects);
} }
protected override void Update() protected override void Update()

View File

@ -27,7 +27,7 @@ namespace osu.Game.Screens.Multiplayer
set set
{ {
host.Text = value.Username; host.Text = value.Username;
flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName) { RelativeSizeAxes = Axes.Both } }; flagContainer.Children = new[] { new DrawableFlag(value.Country) { RelativeSizeAxes = Axes.Both } };
} }
} }

View File

@ -7,10 +7,10 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Screens.Play.HUD namespace osu.Game.Screens.Play.HUD
{ {

View File

@ -23,6 +23,7 @@ using osu.Game.Screens.Play;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users; using osu.Game.Users;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Extensions;
namespace osu.Game.Screens.Ranking namespace osu.Game.Screens.Ranking
{ {
@ -163,7 +164,7 @@ namespace osu.Game.Screens.Ranking
} }
}; };
statisticsContainer.ChildrenEnumerable = Score.Statistics.Select(s => new DrawableScoreStatistic(s)); statisticsContainer.ChildrenEnumerable = Score.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s));
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -186,9 +187,9 @@ namespace osu.Game.Screens.Ranking
private class DrawableScoreStatistic : Container private class DrawableScoreStatistic : Container
{ {
private readonly KeyValuePair<string, object> statistic; private readonly KeyValuePair<HitResult, object> statistic;
public DrawableScoreStatistic(KeyValuePair<string, object> statistic) public DrawableScoreStatistic(KeyValuePair<HitResult, object> statistic)
{ {
this.statistic = statistic; this.statistic = statistic;
@ -209,7 +210,7 @@ namespace osu.Game.Screens.Ranking
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
}, },
new OsuSpriteText { new OsuSpriteText {
Text = statistic.Key, Text = statistic.Key.GetDescription(),
Colour = colours.Gray7, Colour = colours.Gray7,
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Y = 26, Y = 26,
@ -250,16 +251,16 @@ namespace osu.Game.Screens.Ranking
{ {
Origin = Anchor.CentreLeft, Origin = Anchor.CentreLeft,
Anchor = Anchor.CentreLeft, Anchor = Anchor.CentreLeft,
Text = datetime.ToString("HH:mm"), Text = datetime.ToShortDateString(),
Padding = new MarginPadding { Left = 10, Right = 10, Top = 5, Bottom = 5 }, Padding = new MarginPadding { Horizontal = 10, Vertical = 5 },
Colour = Color4.White, Colour = Color4.White,
}, },
new OsuSpriteText new OsuSpriteText
{ {
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Text = datetime.ToString("yyyy/MM/dd"), Text = datetime.ToShortTimeString(),
Padding = new MarginPadding { Left = 10, Right = 10, Top = 5, Bottom = 5 }, Padding = new MarginPadding { Horizontal = 10, Vertical = 5 },
Colour = Color4.White, Colour = Color4.White,
} }
}; };

View File

@ -46,7 +46,7 @@ namespace osu.Game.Screens.Select.Carousel
{ {
if (songSelect != null) if (songSelect != null)
{ {
startRequested = songSelect.Start; startRequested = songSelect.FinaliseSelection;
editRequested = songSelect.Edit; editRequested = songSelect.Edit;
} }

View File

@ -7,6 +7,10 @@ namespace osu.Game.Screens.Select
{ {
protected override bool ShowFooter => false; protected override bool ShowFooter => false;
protected override void Start() => Exit(); protected override bool OnSelectionFinalised()
{
Exit();
return true;
}
} }
} }

View File

@ -14,7 +14,7 @@ namespace osu.Game.Screens.Select
HeaderText = @"You have no beatmaps!"; HeaderText = @"You have no beatmaps!";
BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps?"; BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps?";
Icon = FontAwesome.fa_trash_o; Icon = FontAwesome.fa_plane;
Buttons = new PopupDialogButton[] Buttons = new PopupDialogButton[]
{ {

View File

@ -145,7 +145,7 @@ namespace osu.Game.Screens.Select.Leaderboards
Masking = true, Masking = true,
Children = new Drawable[] Children = new Drawable[]
{ {
new DrawableFlag(Score.User?.Country?.FlagName) new DrawableFlag(Score.User?.Country)
{ {
Width = 30, Width = 30,
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,

View File

@ -5,6 +5,10 @@ namespace osu.Game.Screens.Select
{ {
public class MatchSongSelect : SongSelect public class MatchSongSelect : SongSelect
{ {
protected override void Start() => Exit(); protected override bool OnSelectionFinalised()
{
Exit();
return true;
}
} }
} }

View File

@ -124,9 +124,9 @@ namespace osu.Game.Screens.Select
return false; return false;
} }
protected override void Start() protected override bool OnSelectionFinalised()
{ {
if (player != null) return; if (player != null) return false;
// Ctrl+Enter should start map with autoplay enabled. // Ctrl+Enter should start map with autoplay enabled.
if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true) if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true)
@ -147,7 +147,12 @@ namespace osu.Game.Screens.Select
sampleConfirm?.Play(); sampleConfirm?.Play();
LoadComponentAsync(player = new PlayerLoader(new Player()), l => Push(player)); LoadComponentAsync(player = new PlayerLoader(new Player()), l =>
{
if (IsCurrentScreen) Push(player);
});
return true;
} }
} }
} }

View File

@ -227,13 +227,18 @@ namespace osu.Game.Screens.Select
Push(new Editor()); Push(new Editor());
} }
public void Start(BeatmapInfo beatmap) /// <summary>
/// Call to make a selection and perform the default action for this SongSelect.
/// </summary>
/// <param name="beatmap">An optional beatmap to override the current carousel selection.</param>
public void FinaliseSelection(BeatmapInfo beatmap = null)
{ {
// if we have a pending filter operation, we want to run it now. // if we have a pending filter operation, we want to run it now.
// it could change selection (ie. if the ruleset has been changed). // it could change selection (ie. if the ruleset has been changed).
Carousel.FlushPendingFilterOperations(); Carousel.FlushPendingFilterOperations();
Carousel.SelectBeatmap(beatmap); if (beatmap != null)
Carousel.SelectBeatmap(beatmap);
if (selectionChangedDebounce?.Completed == false) if (selectionChangedDebounce?.Completed == false)
{ {
@ -242,13 +247,14 @@ namespace osu.Game.Screens.Select
selectionChangedDebounce = null; selectionChangedDebounce = null;
} }
Start(); OnSelectionFinalised();
} }
/// <summary> /// <summary>
/// Called when a selection is made. /// Called when a selection is made.
/// </summary> /// </summary>
protected abstract void Start(); /// <returns>If a resultant action occurred that takes the user away from SongSelect.</returns>
protected abstract bool OnSelectionFinalised();
private ScheduledDelegate selectionChangedDebounce; private ScheduledDelegate selectionChangedDebounce;
@ -339,7 +345,7 @@ namespace osu.Game.Screens.Select
logo.Action = () => logo.Action = () =>
{ {
Start(); FinaliseSelection();
return false; return false;
}; };
} }
@ -462,7 +468,7 @@ namespace osu.Game.Screens.Select
{ {
case Key.KeypadEnter: case Key.KeypadEnter:
case Key.Enter: case Key.Enter:
Start(); FinaliseSelection();
return true; return true;
case Key.Delete: case Key.Delete:
if (state.Keyboard.ShiftPressed) if (state.Keyboard.ShiftPressed)

View File

@ -6,6 +6,7 @@ using Newtonsoft.Json;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
@ -26,36 +27,30 @@ namespace osu.Game.Users
public string FlagName; public string FlagName;
} }
public class DrawableFlag : Container public class DrawableFlag : Container, IHasTooltip
{ {
private readonly Sprite sprite; private readonly Sprite sprite;
private TextureStore textures; private TextureStore textures;
private string flagName; private Country country;
public string FlagName public Country Country
{ {
get { return flagName; } get { return country; }
set set
{ {
if (value == flagName) return; if (value == country)
flagName = value; return;
sprite.Texture = textures.Get($@"Flags/{flagName}");
country = value;
sprite.Texture = getFlagTexture();
} }
} }
[BackgroundDependencyLoader] public string TooltipText => country?.FullName;
private void load(TextureStore ts)
{
if (ts == null)
throw new ArgumentNullException(nameof(ts));
textures = ts; public DrawableFlag(Country country = null)
sprite.Texture = textures.Get($@"Flags/{flagName}");
}
public DrawableFlag(string name = null)
{ {
flagName = name ?? @"__"; this.country = country;
Children = new Drawable[] Children = new Drawable[]
{ {
@ -65,5 +60,17 @@ namespace osu.Game.Users
}, },
}; };
} }
[BackgroundDependencyLoader]
private void load(TextureStore ts)
{
if (ts == null)
throw new ArgumentNullException(nameof(ts));
textures = ts;
sprite.Texture = getFlagTexture();
}
private Texture getFlagTexture() => textures.Get($@"Flags/{country?.FlagName ?? @"__"}");
} }
} }

View File

@ -114,7 +114,7 @@ namespace osu.Game.Users
Spacing = new Vector2(5f, 0f), Spacing = new Vector2(5f, 0f),
Children = new Drawable[] Children = new Drawable[]
{ {
new DrawableFlag(user.Country?.FlagName) new DrawableFlag(user.Country)
{ {
Width = 30f, Width = 30f,
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,

View File

@ -144,7 +144,7 @@
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4"> <Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
<HintPath>$(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll</HintPath> <HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0.11\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="Remotion.Linq, Version=2.1.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL"> <Reference Include="Remotion.Linq, Version=2.1.0.0, Culture=neutral, PublicKeyToken=fee00910d6e5f53b, processorArchitecture=MSIL">
@ -311,6 +311,7 @@
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" /> <Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" /> <Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" />
<Compile Include="Overlays\Settings\Sections\Maintenance\DeleteAllBeatmapsDialog.cs" /> <Compile Include="Overlays\Settings\Sections\Maintenance\DeleteAllBeatmapsDialog.cs" />
<Compile Include="Rulesets\Mods\IApplicableToDrawableHitObject.cs" />
<Compile Include="Screens\Select\ImportFromStablePopup.cs" /> <Compile Include="Screens\Select\ImportFromStablePopup.cs" />
<Compile Include="Overlays\Settings\SettingsButton.cs" /> <Compile Include="Overlays\Settings\SettingsButton.cs" />
<Compile Include="Rulesets\Edit\Layers\Selection\OriginHandle.cs" /> <Compile Include="Rulesets\Edit\Layers\Selection\OriginHandle.cs" />
@ -612,7 +613,7 @@
<Compile Include="Rulesets\Objects\Drawables\ArmedState.cs" /> <Compile Include="Rulesets\Objects\Drawables\ArmedState.cs" />
<Compile Include="Rulesets\Objects\Drawables\DrawableHitObject.cs" /> <Compile Include="Rulesets\Objects\Drawables\DrawableHitObject.cs" />
<Compile Include="Rulesets\Objects\Drawables\DrawableScrollingHitObject.cs" /> <Compile Include="Rulesets\Objects\Drawables\DrawableScrollingHitObject.cs" />
<Compile Include="Rulesets\Objects\Drawables\HitResult.cs" /> <Compile Include="Rulesets\Scoring\HitResult.cs" />
<Compile Include="Rulesets\Objects\Drawables\IDrawableHitObjectWithProxiedApproach.cs" /> <Compile Include="Rulesets\Objects\Drawables\IDrawableHitObjectWithProxiedApproach.cs" />
<Compile Include="Rulesets\Objects\Drawables\IScrollingHitObject.cs" /> <Compile Include="Rulesets\Objects\Drawables\IScrollingHitObject.cs" />
<Compile Include="Rulesets\Objects\HitObject.cs" /> <Compile Include="Rulesets\Objects\HitObject.cs" />

View File

@ -66,7 +66,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
<package id="Microsoft.Extensions.Primitives" version="2.0.0" targetFramework="net461" /> <package id="Microsoft.Extensions.Primitives" version="2.0.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" /> <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
<package id="NUnit" version="3.8.1" targetFramework="net461" /> <package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00021" targetFramework="net461" /> <package id="ppy.OpenTK" version="3.0.11" targetFramework="net461" />
<package id="Remotion.Linq" version="2.1.2" targetFramework="net461" /> <package id="Remotion.Linq" version="2.1.2" targetFramework="net461" />
<package id="SharpCompress" version="0.18.1" targetFramework="net461" /> <package id="SharpCompress" version="0.18.1" targetFramework="net461" />
<package id="SQLitePCLRaw.bundle_green" version="1.1.8" targetFramework="net461" /> <package id="SQLitePCLRaw.bundle_green" version="1.1.8" targetFramework="net461" />