1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 08:43:01 +08:00

Merge branch 'master' into fix-ios-import

This commit is contained in:
Dean Herbert 2019-09-04 13:49:22 +09:00 committed by GitHub
commit de4c600fda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
350 changed files with 7170 additions and 2602 deletions

View File

@ -6,7 +6,7 @@ GEM
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3) atomos (0.1.3)
babosa (1.0.2) babosa (1.0.2)
claide (1.0.2) claide (1.0.3)
colored (1.2) colored (1.2)
colored2 (3.1.2) colored2 (3.1.2)
commander-fastlane (4.4.6) commander-fastlane (4.4.6)
@ -14,11 +14,11 @@ GEM
declarative (0.0.10) declarative (0.0.10)
declarative-option (0.1.0) declarative-option (0.1.0)
digest-crc (0.4.1) digest-crc (0.4.1)
domain_name (0.5.20180417) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.1) dotenv (2.7.5)
emoji_regex (1.0.1) emoji_regex (1.0.1)
excon (0.62.0) excon (0.66.0)
faraday (0.15.4) faraday (0.15.4)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6) faraday-cookie_jar (0.0.6)
@ -27,7 +27,7 @@ GEM
faraday_middleware (0.13.1) faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0) faraday (>= 0.7.4, < 1.0)
fastimage (2.1.5) fastimage (2.1.5)
fastlane (2.117.0) fastlane (2.129.0)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0) addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0) babosa (>= 1.0.2, < 2.0.0)
@ -46,8 +46,8 @@ GEM
google-cloud-storage (>= 1.15.0, < 2.0.0) google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0) highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0) json (< 3.0.0)
mini_magick (~> 4.5.1) jwt (~> 2.1.0)
multi_json mini_magick (>= 4.9.4, < 5.0.0)
multi_xml (~> 0.5) multi_xml (~> 0.5)
multipart-post (~> 2.0.0) multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0) plist (>= 3.1.0, < 4.0.0)
@ -56,15 +56,15 @@ GEM
security (= 0.1.3) security (= 0.1.3)
simctl (~> 1.6.3) simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0) slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 1.6.2, < 2.0.0) terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0) terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0) tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0) word_wrap (~> 1.0.0)
xcodeproj (>= 1.6.0, < 2.0.0) xcodeproj (>= 1.8.1, < 2.0.0)
xcpretty (~> 0.3.0) xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3) xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-clean_testflight_testers (0.2.0) fastlane-plugin-clean_testflight_testers (0.3.0)
fastlane-plugin-souyuz (0.8.1) fastlane-plugin-souyuz (0.8.1)
souyuz (>= 0.8.1) souyuz (>= 0.8.1)
fastlane-plugin-xamarin (0.6.3) fastlane-plugin-xamarin (0.6.3)
@ -79,7 +79,7 @@ GEM
signet (~> 0.9) signet (~> 0.9)
google-cloud-core (1.3.0) google-cloud-core (1.3.0)
google-cloud-env (~> 1.0) google-cloud-env (~> 1.0)
google-cloud-env (1.0.5) google-cloud-env (1.2.0)
faraday (~> 0.11) faraday (~> 0.11)
google-cloud-storage (1.16.0) google-cloud-storage (1.16.0)
digest-crc (~> 0.4) digest-crc (~> 0.4)
@ -102,17 +102,17 @@ GEM
memoist (0.16.0) memoist (0.16.0)
mime-types (3.2.2) mime-types (3.2.2)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812) mime-types-data (3.2019.0331)
mini_magick (4.5.1) mini_magick (4.9.5)
mini_portile2 (2.4.0) mini_portile2 (2.4.0)
multi_json (1.13.1) multi_json (1.13.1)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.0.0) multipart-post (2.0.0)
nanaimo (0.2.6) nanaimo (0.2.6)
naturally (2.2.0) naturally (2.2.0)
nokogiri (1.10.1) nokogiri (1.10.4)
mini_portile2 (~> 2.4.0) mini_portile2 (~> 2.4.0)
os (1.0.0) os (1.0.1)
plist (3.5.0) plist (3.5.0)
public_suffix (2.0.5) public_suffix (2.0.5)
representable (3.0.4) representable (3.0.4)
@ -121,7 +121,7 @@ GEM
uber (< 0.2.0) uber (< 0.2.0)
retriable (3.1.2) retriable (3.1.2)
rouge (2.0.7) rouge (2.0.7)
rubyzip (1.2.2) rubyzip (1.2.3)
security (0.1.3) security (0.1.3)
signet (0.11.0) signet (0.11.0)
addressable (~> 2.3) addressable (~> 2.3)
@ -136,20 +136,20 @@ GEM
fastlane (>= 2.29.0) fastlane (>= 2.29.0)
highline (~> 1.7) highline (~> 1.7)
nokogiri (~> 1.7) nokogiri (~> 1.7)
terminal-notifier (1.8.0) terminal-notifier (2.0.0)
terminal-table (1.8.0) terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1) unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.6.1) tty-cursor (0.7.0)
tty-screen (0.6.5) tty-screen (0.7.0)
tty-spinner (0.9.0) tty-spinner (0.9.1)
tty-cursor (~> 0.6.0) tty-cursor (~> 0.7)
uber (0.1.0) uber (0.1.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.5) unf_ext (0.0.7.6)
unicode-display_width (1.4.1) unicode-display_width (1.6.0)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.8.1) xcodeproj (1.12.0)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)

View File

@ -19,8 +19,9 @@ Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh
## Requirements ## Requirements
- A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed. - A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed.
- When running on linux, please have a system-wide ffmpeg installation available to support video decoding.
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
- When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). - When working with the codebase, we recommend using an IDE with intellisense and syntax highlighting, such as [Visual Studio 2017+](https://visualstudio.microsoft.com/vs/), [Jetbrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
- Note that there are **[additional requirements for Windows 7 and Windows 8.1](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore2x)** which you may need to manually install if your operating system is not up-to-date.
## Running osu! ## Running osu!

View File

@ -1,22 +1,6 @@
update_fastlane update_fastlane
default_platform(:ios)
platform :ios do platform :ios do
lane :testflight_prune_dry do
clean_testflight_testers(days_of_inactivity:45, dry_run: true)
end
# Specify a custom number for what's "inactive"
lane :testflight_prune do
clean_testflight_testers(days_of_inactivity: 45) # 120 days, so about 4 months
end
lane :update_version do |options|
options[:plist_path] = '../osu.iOS/Info.plist'
app_version(options)
end
desc 'Deploy to testflight' desc 'Deploy to testflight'
lane :beta do |options| lane :beta do |options|
update_version(options) update_version(options)
@ -62,4 +46,17 @@ platform :ios do
match(options) match(options)
end end
lane :update_version do |options|
options[:plist_path] = '../osu.iOS/Info.plist'
app_version(options)
end
lane :testflight_prune_dry do
clean_testflight_testers(days_of_inactivity:45, dry_run: true)
end
lane :testflight_prune do
clean_testflight_testers(days_of_inactivity: 45)
end
end end

View File

@ -16,21 +16,6 @@ or alternatively using `brew cask install fastlane`
# Available Actions # Available Actions
## iOS ## iOS
### ios testflight_prune_dry
```
fastlane ios testflight_prune_dry
```
### ios testflight_prune
```
fastlane ios testflight_prune
```
### ios update_version
```
fastlane ios update_version
```
### ios beta ### ios beta
``` ```
fastlane ios beta fastlane ios beta
@ -46,6 +31,21 @@ Compile the project
fastlane ios provision fastlane ios provision
``` ```
Install provisioning profiles using match Install provisioning profiles using match
### ios update_version
```
fastlane ios update_version
```
### ios testflight_prune_dry
```
fastlane ios testflight_prune_dry
```
### ios testflight_prune
```
fastlane ios testflight_prune
```
---- ----

View File

@ -49,9 +49,7 @@
<None Include="$(MSBuildThisFileDirectory)\osu.licenseheader"> <None Include="$(MSBuildThisFileDirectory)\osu.licenseheader">
<Link>osu.licenseheader</Link> <Link>osu.licenseheader</Link>
</None> </None>
<AndroidNativeLibrary Include="$(MSBuildThisFileDirectory)\osu.Android\lib\**\*.so"> <AndroidNativeLibrary Include="$(OutputPath)\**\*.so" />
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AndroidNativeLibrary>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@ -62,7 +60,7 @@
<Reference Include="Java.Interop" /> <Reference Include="Java.Interop" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.809.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2019.904.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.809.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2019.830.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -113,13 +113,14 @@ namespace osu.Desktop.Overlays
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, ChangelogOverlay changelog) private void load(OsuColour colours, ChangelogOverlay changelog, NotificationOverlay notificationOverlay)
{ {
Icon = FontAwesome.Solid.CheckSquare; Icon = FontAwesome.Solid.CheckSquare;
IconBackgound.Colour = colours.BlueDark; IconBackgound.Colour = colours.BlueDark;
Activated = delegate Activated = delegate
{ {
notificationOverlay.Hide();
changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version); changelog.ShowBuild(OsuGameBase.CLIENT_STREAM_NAME, version);
return true; return true;
}; };

View File

@ -13,14 +13,6 @@
<ItemGroup> <ItemGroup>
<None Include="Info.plist" /> <None Include="Info.plist" />
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />
<None Include="..\osu.iOS\libbass.a">
<Link>libbass.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\osu.iOS\libbass_fx.a">
<Link>libbass_fx.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<LinkDescription Include="..\osu.iOS\Linker.xml"> <LinkDescription Include="..\osu.iOS\Linker.xml">
<Link>Linker.xml</Link> <Link>Linker.xml</Link>
</LinkDescription> </LinkDescription>

View File

@ -15,6 +15,7 @@ using osu.Framework.Graphics.Sprites;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Game.Audio;
namespace osu.Game.Rulesets.Catch.Tests namespace osu.Game.Rulesets.Catch.Tests
{ {
@ -81,18 +82,18 @@ namespace osu.Game.Rulesets.Catch.Tests
remove { } remove { }
} }
public Drawable GetDrawableComponent(string componentName) public Drawable GetDrawableComponent(ISkinComponent component)
{ {
switch (componentName) switch (component.LookupName)
{ {
case "Play/Catch/fruit-catcher-idle": case "Gameplay/catch/fruit-catcher-idle":
return new CatcherCustomSkin(); return new CatcherCustomSkin();
} }
return null; return null;
} }
public SampleChannel GetSample(string sampleName) => public SampleChannel GetSample(ISampleInfo sampleInfo) =>
throw new NotImplementedException(); throw new NotImplementedException();
public Texture GetTexture(string componentName) => public Texture GetTexture(string componentName) =>

View File

@ -4,7 +4,7 @@
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" /> <PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">

View File

@ -23,10 +23,12 @@ namespace osu.Game.Rulesets.Catch
{ {
public class CatchRuleset : Ruleset public class CatchRuleset : Ruleset
{ {
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableCatchRuleset(this, beatmap, mods); public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableCatchRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap); public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);
public const string SHORT_NAME = "fruits";
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[] public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
{ {
new KeyBinding(InputKey.Z, CatchAction.MoveLeft), new KeyBinding(InputKey.Z, CatchAction.MoveLeft),
@ -117,7 +119,7 @@ namespace osu.Game.Rulesets.Catch
public override string Description => "osu!catch"; public override string Description => "osu!catch";
public override string ShortName => "fruits"; public override string ShortName => SHORT_NAME;
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };

View File

@ -0,0 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Catch
{
public class CatchSkinComponent : GameplaySkinComponent<CatchSkinComponents>
{
public CatchSkinComponent(CatchSkinComponents component)
: base(component)
{
}
protected override string RulesetPrefix => "catch"; // todo: use CatchRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
}
}

View File

@ -0,0 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Catch
{
public enum CatchSkinComponents
{
}
}

View File

@ -58,14 +58,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss);
} }
protected override bool UseTransformStateManagement => false; protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
protected override void UpdateState(ArmedState state) protected override void UpdateInitialTransforms() => this.FadeInFromZero(200);
protected override void UpdateStateTransforms(ArmedState state)
{ {
// TODO: update to use new state management.
using (BeginAbsoluteSequence(HitObject.StartTime - HitObject.TimePreempt))
this.FadeIn(200);
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
using (BeginAbsoluteSequence(endTime, true)) using (BeginAbsoluteSequence(endTime, true))

View File

@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
AccentColour = Color4.Red, AccentColour = Color4.Red,
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Alpha = 0.5f, Alpha = 0.5f,
Scale = new Vector2(1.333f) Scale = new Vector2(1.333f)
}); });

View File

@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Blending = BlendingMode.Additive; Blending = BlendingParameters.Additive;
Colour = Color4.White.Opacity(0.9f); Colour = Color4.White.Opacity(0.9f);
} }

View File

@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.UI
if (lastPlateableFruit == null) if (lastPlateableFruit == null)
return; return;
// this is required to make this run after the last caught fruit runs UpdateState at least once. // this is required to make this run after the last caught fruit runs updateState() at least once.
// TODO: find a better alternative // TODO: find a better alternative
if (lastPlateableFruit.IsLoaded) if (lastPlateableFruit.IsLoaded)
action(); action();
@ -201,7 +201,7 @@ namespace osu.Game.Rulesets.Catch.UI
additive.Scale = Scale; additive.Scale = Scale;
additive.Colour = HyperDashing ? Color4.Red : Color4.White; additive.Colour = HyperDashing ? Color4.Red : Color4.White;
additive.RelativePositionAxes = RelativePositionAxes; additive.RelativePositionAxes = RelativePositionAxes;
additive.Blending = BlendingMode.Additive; additive.Blending = BlendingParameters.Additive;
AdditiveTarget.Add(additive); AdditiveTarget.Add(additive);

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
InternalChild = new SkinnableSprite(@"Play/Catch/fruit-catcher-idle") InternalChild = new SkinnableSprite("Gameplay/catch/fruit-catcher-idle")
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,

View File

@ -25,11 +25,11 @@ namespace osu.Game.Rulesets.Catch.UI
protected override bool UserScrollSpeedAdjustment => false; protected override bool UserScrollSpeedAdjustment => false;
public DrawableCatchRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) public DrawableCatchRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {
Direction.Value = ScrollingDirection.Down; Direction.Value = ScrollingDirection.Down;
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450); TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.Beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
} }
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this);

View File

@ -13,14 +13,6 @@
<ItemGroup> <ItemGroup>
<None Include="Info.plist" /> <None Include="Info.plist" />
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />
<None Include="..\osu.iOS\libbass.a">
<Link>libbass.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\osu.iOS\libbass_fx.a">
<Link>libbass_fx.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<LinkDescription Include="..\osu.iOS\Linker.xml"> <LinkDescription Include="..\osu.iOS\Linker.xml">
<Link>Linker.xml</Link> <Link>Linker.xml</Link>
</LinkDescription> </LinkDescription>

View File

@ -4,7 +4,7 @@
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" /> <PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">

View File

@ -11,7 +11,9 @@ using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing; using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mania.Difficulty.Skills; using osu.Game.Rulesets.Mania.Difficulty.Skills;
using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Mods;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Mania.Difficulty namespace osu.Game.Rulesets.Mania.Difficulty
{ {
@ -32,12 +34,15 @@ namespace osu.Game.Rulesets.Mania.Difficulty
if (beatmap.HitObjects.Count == 0) if (beatmap.HitObjects.Count == 0)
return new ManiaDifficultyAttributes { Mods = mods, Skills = skills }; return new ManiaDifficultyAttributes { Mods = mods, Skills = skills };
HitWindows hitWindows = new ManiaHitWindows();
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
return new ManiaDifficultyAttributes return new ManiaDifficultyAttributes
{ {
StarRating = difficultyValue(skills) * star_scaling_factor, StarRating = difficultyValue(skills) * star_scaling_factor,
Mods = mods, Mods = mods,
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
GreatHitWindow = (int)(beatmap.HitObjects.First().HitWindows.Great / 2) / clockRate, GreatHitWindow = (int)(hitWindows.Great / 2) / clockRate,
Skills = skills Skills = skills
}; };
} }

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Edit
{ {
public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; public new IScrollingInfo ScrollingInfo => base.ScrollingInfo;
public DrawableManiaEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) public DrawableManiaEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {
} }

View File

@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.Edit
[Cached(Type = typeof(IManiaHitObjectComposer))] [Cached(Type = typeof(IManiaHitObjectComposer))]
public class ManiaHitObjectComposer : HitObjectComposer<ManiaHitObject>, IManiaHitObjectComposer public class ManiaHitObjectComposer : HitObjectComposer<ManiaHitObject>, IManiaHitObjectComposer
{ {
protected new DrawableManiaEditRuleset DrawableRuleset { get; private set; } private DrawableManiaEditRuleset drawableRuleset;
public ManiaHitObjectComposer(Ruleset ruleset) public ManiaHitObjectComposer(Ruleset ruleset)
: base(ruleset) : base(ruleset)
@ -33,23 +33,23 @@ namespace osu.Game.Rulesets.Mania.Edit
/// </summary> /// </summary>
/// <param name="screenSpacePosition">The screen-space position.</param> /// <param name="screenSpacePosition">The screen-space position.</param>
/// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns> /// <returns>The column which intersects with <paramref name="screenSpacePosition"/>.</returns>
public Column ColumnAt(Vector2 screenSpacePosition) => DrawableRuleset.GetColumnByPosition(screenSpacePosition); public Column ColumnAt(Vector2 screenSpacePosition) => drawableRuleset.GetColumnByPosition(screenSpacePosition);
private DependencyContainer dependencies; private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
=> dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); => dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
public int TotalColumns => ((ManiaPlayfield)DrawableRuleset.Playfield).TotalColumns; public int TotalColumns => ((ManiaPlayfield)drawableRuleset.Playfield).TotalColumns;
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
{ {
DrawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods); drawableRuleset = new DrawableManiaEditRuleset(ruleset, beatmap, mods);
// This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it
dependencies.CacheAs(DrawableRuleset.ScrollingInfo); dependencies.CacheAs(drawableRuleset.ScrollingInfo);
return DrawableRuleset; return drawableRuleset;
} }
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[] protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]

View File

@ -31,10 +31,12 @@ namespace osu.Game.Rulesets.Mania
{ {
public class ManiaRuleset : Ruleset public class ManiaRuleset : Ruleset
{ {
public override DrawableRuleset CreateDrawableRulesetWith(WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableManiaRuleset(this, beatmap, mods); public override DrawableRuleset CreateDrawableRulesetWith(IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods) => new DrawableManiaRuleset(this, beatmap, mods);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score);
public const string SHORT_NAME = "mania";
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods) public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
@ -163,7 +165,7 @@ namespace osu.Game.Rulesets.Mania
public override string Description => "osu!mania"; public override string Description => "osu!mania";
public override string ShortName => "mania"; public override string ShortName => SHORT_NAME;
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania }; public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania };

View File

@ -0,0 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Mania
{
public class ManiaSkinComponent : GameplaySkinComponent<ManiaSkinComponents>
{
public ManiaSkinComponent(ManiaSkinComponents component)
: base(component)
{
}
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
protected override string ComponentName => Component.ToString().ToLower();
}
}

View File

@ -0,0 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Rulesets.Mania
{
public enum ManiaSkinComponents
{
}
}

View File

@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Alpha = 0.2f; Alpha = 0.2f;
} }
protected override void UpdateState(ArmedState state) protected override void UpdateStateTransforms(ArmedState state)
{ {
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
@ -8,6 +9,7 @@ using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
@ -104,6 +106,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2;
} }
protected override void UpdateStateTransforms(ArmedState state)
{
using (BeginDelayedSequence(HitObject.Duration, true))
base.UpdateStateTransforms(state);
}
protected void BeginHold() protected void BeginHold()
{ {
holdStartTime = Time.Current; holdStartTime = Time.Current;
@ -202,6 +210,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
Debug.Assert(HitObject.HitWindows != null);
// Factor in the release lenience // Factor in the release lenience
timeOffset /= release_window_lenience; timeOffset /= release_window_lenience;

View File

@ -45,24 +45,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre; Anchor = Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
} }
}
public abstract class DrawableManiaHitObject<TObject> : DrawableManiaHitObject protected override void UpdateStateTransforms(ArmedState state)
where TObject : ManiaHitObject
{ {
public new readonly TObject HitObject;
protected DrawableManiaHitObject(TObject hitObject)
: base(hitObject)
{
HitObject = hitObject;
}
protected override bool UseTransformStateManagement => false;
protected override void UpdateState(ArmedState state)
{
// TODO: update to use new state management.
switch (state) switch (state)
{ {
case ArmedState.Miss: case ArmedState.Miss:
@ -75,4 +60,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
} }
} }
} }
public abstract class DrawableManiaHitObject<TObject> : DrawableManiaHitObject
where TObject : ManiaHitObject
{
public new readonly TObject HitObject;
protected DrawableManiaHitObject(TObject hitObject)
: base(hitObject)
{
HitObject = hitObject;
}
}
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Diagnostics;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -52,6 +53,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
Debug.Assert(HitObject.HitWindows != null);
if (!userTriggered) if (!userTriggered)
{ {
if (!HitObject.HitWindows.CanBeHit(timeOffset)) if (!HitObject.HitWindows.CanBeHit(timeOffset))

View File

@ -26,14 +26,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
public BodyPiece() public BodyPiece()
{ {
Blending = BlendingMode.Additive; Blending = BlendingParameters.Additive;
Children = new[] Children = new[]
{ {
Background = new Box { RelativeSizeAxes = Axes.Both }, Background = new Box { RelativeSizeAxes = Axes.Both },
Foreground = new BufferedContainer Foreground = new BufferedContainer
{ {
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
CacheDrawnFrameBuffer = true, CacheDrawnFrameBuffer = true,
Children = new Drawable[] Children = new Drawable[]

View File

@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
Name = "Top", Name = "Top",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.5f, Height = 0.5f,
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha)) Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha))
}, },
new Box new Box
@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.5f, Height = 0.5f,
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent) Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent)
} }
}; };

View File

@ -5,6 +5,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
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.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Mania.Objects namespace osu.Game.Rulesets.Mania.Objects
@ -99,5 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects
} }
public override Judgement CreateJudgement() => new HoldNoteJudgement(); public override Judgement CreateJudgement() => new HoldNoteJudgement();
protected override HitWindows CreateHitWindows() => null;
} }
} }

View File

@ -3,6 +3,7 @@
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.Objects;
namespace osu.Game.Rulesets.Mania.Objects namespace osu.Game.Rulesets.Mania.Objects
{ {
@ -12,5 +13,7 @@ namespace osu.Game.Rulesets.Mania.Objects
public class HoldNoteTick : ManiaHitObject public class HoldNoteTick : ManiaHitObject
{ {
public override Judgement CreateJudgement() => new HoldNoteTickJudgement(); public override Judgement CreateJudgement() => new HoldNoteTickJudgement();
protected override HitWindows CreateHitWindows() => null;
} }
} }

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Replays; using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
@ -77,13 +78,37 @@ namespace osu.Game.Rulesets.Mania.Replays
private IEnumerable<IActionPoint> generateActionPoints() private IEnumerable<IActionPoint> generateActionPoints()
{ {
foreach (var obj in Beatmap.HitObjects) for (int i = 0; i < Beatmap.HitObjects.Count; i++)
{ {
yield return new HitPoint { Time = obj.StartTime, Column = obj.Column }; var currentObject = Beatmap.HitObjects[i];
yield return new ReleasePoint { Time = ((obj as IHasEndTime)?.EndTime ?? obj.StartTime) + RELEASE_DELAY, Column = obj.Column }; var nextObjectInColumn = GetNextObject(i); // Get the next object that requires pressing the same button
double endTime = (currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime;
bool canDelayKeyUp = nextObjectInColumn == null ||
nextObjectInColumn.StartTime > endTime + RELEASE_DELAY;
double calculatedDelay = canDelayKeyUp ? RELEASE_DELAY : (nextObjectInColumn.StartTime - endTime) * 0.9;
yield return new HitPoint { Time = currentObject.StartTime, Column = currentObject.Column };
yield return new ReleasePoint { Time = endTime + calculatedDelay, Column = currentObject.Column };
} }
} }
protected override HitObject GetNextObject(int currentIndex)
{
int desiredColumn = Beatmap.HitObjects[currentIndex].Column;
for (int i = currentIndex + 1; i < Beatmap.HitObjects.Count; i++)
{
if (Beatmap.HitObjects[i].Column == desiredColumn)
return Beatmap.HitObjects[i];
}
return null;
}
private interface IActionPoint private interface IActionPoint
{ {
double Time { get; set; } double Time { get; set; }

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components
Name = "Background Gradient Overlay", Name = "Background Gradient Overlay",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Height = 0.5f, Height = 0.5f,
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Alpha = 0 Alpha = 0
} }
}; };

View File

@ -36,11 +36,13 @@ namespace osu.Game.Rulesets.Mania.UI
public IEnumerable<BarLine> BarLines; public IEnumerable<BarLine> BarLines;
protected override bool RelativeScaleBeatLengths => true;
protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config; protected new ManiaRulesetConfigManager Config => (ManiaRulesetConfigManager)base.Config;
private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>(); private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>();
public DrawableManiaRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {
// Generate the bar lines // Generate the bar lines

View File

@ -13,14 +13,6 @@
<ItemGroup> <ItemGroup>
<None Include="Info.plist" /> <None Include="Info.plist" />
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />
<None Include="..\osu.iOS\libbass.a">
<Link>libbass.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\osu.iOS\libbass_fx.a">
<Link>libbass_fx.a</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<LinkDescription Include="..\osu.iOS\Linker.xml"> <LinkDescription Include="..\osu.iOS\Linker.xml">
<Link>Linker.xml</Link> <Link>Linker.xml</Link>
</LinkDescription> </LinkDescription>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -2,12 +2,12 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.IO; using System.Text.RegularExpressions;
using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -28,38 +28,54 @@ namespace osu.Game.Rulesets.Osu.Tests
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio) private void load(AudioManager audio)
{ {
var skins = new SkinManager(LocalStorage, ContextFactory, null, audio); var dllStore = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll");
metricsSkin = getSkinFromResources(skins, "metrics_skin"); metricsSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/metrics_skin"), audio, true);
defaultSkin = getSkinFromResources(skins, "default_skin"); defaultSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/default_skin"), audio, false);
specialSkin = getSkinFromResources(skins, "special_skin"); specialSkin = new TestLegacySkin(new SkinInfo(), new NamespacedResourceStore<byte[]>(dllStore, "Resources/special_skin"), audio, true);
} }
public void SetContents(Func<Drawable> creationFunction) public void SetContents(Func<Drawable> creationFunction)
{ {
Cell(0).Child = new LocalSkinOverrideContainer(null) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); Cell(0).Child = createProvider(null, creationFunction);
Cell(1).Child = new LocalSkinOverrideContainer(metricsSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); Cell(1).Child = createProvider(metricsSkin, creationFunction);
Cell(2).Child = new LocalSkinOverrideContainer(defaultSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); Cell(2).Child = createProvider(defaultSkin, creationFunction);
Cell(3).Child = new LocalSkinOverrideContainer(specialSkin) { RelativeSizeAxes = Axes.Both }.WithChild(creationFunction()); Cell(3).Child = createProvider(specialSkin, creationFunction);
} }
private static Skin getSkinFromResources(SkinManager skins, string name) private Drawable createProvider(Skin skin, Func<Drawable> creationFunction)
{ {
using (var storage = new DllResourceStore("osu.Game.Rulesets.Osu.Tests.dll")) var mainProvider = new SkinProvidingContainer(skin);
return mainProvider
.WithChild(new SkinProvidingContainer(Ruleset.Value.CreateInstance().CreateLegacySkinProvider(mainProvider))
{ {
var tempName = Path.GetTempFileName(); Child = creationFunction()
});
}
File.Delete(tempName); private class TestLegacySkin : LegacySkin
Directory.CreateDirectory(tempName); {
private readonly bool extrapolateAnimations;
var files = storage.GetAvailableResources().Where(f => f.StartsWith($"Resources/{name}")); public TestLegacySkin(SkinInfo skin, IResourceStore<byte[]> storage, AudioManager audioManager, bool extrapolateAnimations)
: base(skin, storage, audioManager, "skin.ini")
{
this.extrapolateAnimations = extrapolateAnimations;
}
foreach (var file in files) public override Texture GetTexture(string componentName)
using (var stream = storage.GetStream(file)) {
using (var newFile = File.Create(Path.Combine(tempName, Path.GetFileName(file)))) // extrapolate frames to test longer animations
stream.CopyTo(newFile); if (extrapolateAnimations)
{
var match = Regex.Match(componentName, "-([0-9]*)");
return skins.GetSkin(skins.Import(tempName).Result); if (match.Length > 0 && int.TryParse(match.Groups[1].Value, out var number) && number < 60)
return base.GetTexture(componentName.Replace($"-{number}", $"-{number % 2}"));
}
return base.GetTexture(componentName);
} }
} }
} }

View File

@ -0,0 +1,35 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Tests
{
public class TestSceneDrawableJudgement : SkinnableTestScene
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(DrawableJudgement),
typeof(DrawableOsuJudgement)
};
public TestSceneDrawableJudgement()
{
foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Skip(1))
AddStep("Show " + result.GetDescription(), () => SetContents(() =>
new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
}));
}
}
}

View File

@ -6,29 +6,23 @@ using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Rulesets.UI;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneGameplayCursor : OsuTestScene, IProvideCursor public class TestSceneGameplayCursor : SkinnableTestScene
{ {
private GameplayCursorContainer cursorContainer;
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(CursorTrail) }; public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(CursorTrail) };
public CursorContainer Cursor => cursorContainer;
public bool ProvidingUserCursor => true;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Add(cursorContainer = new OsuCursorContainer { RelativeSizeAxes = Axes.Both }); SetContents(() => new OsuCursorContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
});
} }
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System.Diagnostics;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -13,8 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests
{ {
var drawableHitObject = base.CreateDrawableHitCircle(circle, auto); var drawableHitObject = base.CreateDrawableHitCircle(circle, auto);
Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), Debug.Assert(drawableHitObject.HitObject.HitWindows != null);
drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current);
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay);
return drawableHitObject; return drawableHitObject;
} }

View File

@ -0,0 +1,157 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Timing;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
[TestFixture]
public class TestSceneSkinFallbacks : PlayerTestScene
{
private readonly TestSource testUserSkin;
private readonly TestSource testBeatmapSkin;
public TestSceneSkinFallbacks()
: base(new OsuRuleset())
{
testUserSkin = new TestSource("user");
testBeatmapSkin = new TestSource("beatmap");
}
[Test]
public void TestBeatmapSkinDefault()
{
AddStep("enable user provider", () => testUserSkin.Enabled = true);
AddStep("enable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, true));
checkNextHitObject("beatmap");
AddStep("disable beatmap skin", () => LocalConfig.Set<bool>(OsuSetting.BeatmapSkins, false));
checkNextHitObject("user");
AddStep("disable user provider", () => testUserSkin.Enabled = false);
checkNextHitObject(null);
}
private void checkNextHitObject(string skin) =>
AddUntilStep($"check skin from {skin}", () =>
{
var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
if (firstObject == null)
return false;
var skinnable = firstObject.ApproachCircle.Child as SkinnableDrawable;
if (skin == null && skinnable?.Drawable is Sprite)
// check for default skin provider
return true;
var text = skinnable?.Drawable as SpriteText;
return text?.Text == skin;
});
[Resolved]
private AudioManager audio { get; set; }
protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) => new CustomSkinWorkingBeatmap(beatmap, Clock, audio, testBeatmapSkin);
public class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap
{
private readonly ISkinSource skin;
public CustomSkinWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock frameBasedClock, AudioManager audio, ISkinSource skin)
: base(beatmap, frameBasedClock, audio)
{
this.skin = skin;
}
protected override ISkin GetSkin() => skin;
}
public class SkinProvidingPlayer : TestPlayer
{
private readonly TestSource userSkin;
public SkinProvidingPlayer(TestSource userSkin)
{
this.userSkin = userSkin;
}
private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
dependencies.CacheAs<ISkinSource>(userSkin);
return dependencies;
}
}
public class TestSource : ISkinSource
{
private readonly string identifier;
public TestSource(string identifier)
{
this.identifier = identifier;
}
public Drawable GetDrawableComponent(ISkinComponent component)
{
if (!enabled) return null;
return new SpriteText
{
Text = identifier,
Font = OsuFont.Default.With(size: 30),
};
}
public Texture GetTexture(string componentName) => null;
public SampleChannel GetSample(ISampleInfo sampleInfo) => null;
public TValue GetValue<TConfiguration, TValue>(Func<TConfiguration, TValue> query) where TConfiguration : SkinConfiguration => default;
public event Action SourceChanged;
private bool enabled = true;
public bool Enabled
{
get => enabled;
set
{
if (value == enabled)
return;
enabled = value;
SourceChanged?.Invoke();
}
}
}
}
}

View File

@ -10,7 +10,6 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
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 osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -27,83 +26,96 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
namespace osu.Game.Rulesets.Osu.Tests namespace osu.Game.Rulesets.Osu.Tests
{ {
[TestFixture] [TestFixture]
public class TestSceneSlider : OsuTestScene public class TestSceneSlider : SkinnableTestScene
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(Slider),
typeof(SliderTick),
typeof(SliderTailCircle),
typeof(SliderBall), typeof(SliderBall),
typeof(SliderBody), typeof(SliderBody),
typeof(SliderTick), typeof(SnakingSliderBody),
typeof(DrawableSlider), typeof(DrawableSlider),
typeof(DrawableSliderTick), typeof(DrawableSliderTick),
typeof(DrawableSliderTail),
typeof(DrawableSliderHead),
typeof(DrawableRepeatPoint), typeof(DrawableRepeatPoint),
typeof(DrawableOsuHitObject) typeof(DrawableOsuHitObject)
}; };
private readonly Container content; private Container content;
protected override Container<Drawable> Content => content;
protected override Container<Drawable> Content
{
get
{
if (content == null)
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 }));
return content;
}
}
private int depthIndex; private int depthIndex;
public TestSceneSlider() public TestSceneSlider()
{ {
base.Content.Add(content = new OsuInputManager(new RulesetInfo { ID = 0 })); AddStep("Big Single", () => SetContents(() => testSimpleBig()));
AddStep("Medium Single", () => SetContents(() => testSimpleMedium()));
AddStep("Small Single", () => SetContents(() => testSimpleSmall()));
AddStep("Big 1 Repeat", () => SetContents(() => testSimpleBig(1)));
AddStep("Medium 1 Repeat", () => SetContents(() => testSimpleMedium(1)));
AddStep("Small 1 Repeat", () => SetContents(() => testSimpleSmall(1)));
AddStep("Big 2 Repeats", () => SetContents(() => testSimpleBig(2)));
AddStep("Medium 2 Repeats", () => SetContents(() => testSimpleMedium(2)));
AddStep("Small 2 Repeats", () => SetContents(() => testSimpleSmall(2)));
AddStep("Big Single", () => testSimpleBig()); AddStep("Slow Slider", () => SetContents(testSlowSpeed)); // slow long sliders take ages already so no repeat steps
AddStep("Medium Single", () => testSimpleMedium()); AddStep("Slow Short Slider", () => SetContents(() => testShortSlowSpeed()));
AddStep("Small Single", () => testSimpleSmall()); AddStep("Slow Short Slider 1 Repeats", () => SetContents(() => testShortSlowSpeed(1)));
AddStep("Big 1 Repeat", () => testSimpleBig(1)); AddStep("Slow Short Slider 2 Repeats", () => SetContents(() => testShortSlowSpeed(2)));
AddStep("Medium 1 Repeat", () => testSimpleMedium(1));
AddStep("Small 1 Repeat", () => testSimpleSmall(1));
AddStep("Big 2 Repeats", () => testSimpleBig(2));
AddStep("Medium 2 Repeats", () => testSimpleMedium(2));
AddStep("Small 2 Repeats", () => testSimpleSmall(2));
AddStep("Slow Slider", testSlowSpeed); // slow long sliders take ages already so no repeat steps AddStep("Fast Slider", () => SetContents(() => testHighSpeed()));
AddStep("Slow Short Slider", () => testShortSlowSpeed()); AddStep("Fast Slider 1 Repeat", () => SetContents(() => testHighSpeed(1)));
AddStep("Slow Short Slider 1 Repeats", () => testShortSlowSpeed(1)); AddStep("Fast Slider 2 Repeats", () => SetContents(() => testHighSpeed(2)));
AddStep("Slow Short Slider 2 Repeats", () => testShortSlowSpeed(2)); AddStep("Fast Short Slider", () => SetContents(() => testShortHighSpeed()));
AddStep("Fast Short Slider 1 Repeat", () => SetContents(() => testShortHighSpeed(1)));
AddStep("Fast Short Slider 2 Repeats", () => SetContents(() => testShortHighSpeed(2)));
AddStep("Fast Short Slider 6 Repeats", () => SetContents(() => testShortHighSpeed(6)));
AddStep("Fast Slider", () => testHighSpeed()); AddStep("Perfect Curve", () => SetContents(() => testPerfect()));
AddStep("Fast Slider 1 Repeat", () => testHighSpeed(1)); AddStep("Perfect Curve 1 Repeat", () => SetContents(() => testPerfect(1)));
AddStep("Fast Slider 2 Repeats", () => testHighSpeed(2)); AddStep("Perfect Curve 2 Repeats", () => SetContents(() => testPerfect(2)));
AddStep("Fast Short Slider", () => testShortHighSpeed());
AddStep("Fast Short Slider 1 Repeat", () => testShortHighSpeed(1));
AddStep("Fast Short Slider 2 Repeats", () => testShortHighSpeed(2));
AddStep("Fast Short Slider 6 Repeats", () => testShortHighSpeed(6));
AddStep("Perfect Curve", () => testPerfect()); AddStep("Linear Slider", () => SetContents(() => testLinear()));
AddStep("Perfect Curve 1 Repeat", () => testPerfect(1)); AddStep("Linear Slider 1 Repeat", () => SetContents(() => testLinear(1)));
AddStep("Perfect Curve 2 Repeats", () => testPerfect(2)); AddStep("Linear Slider 2 Repeats", () => SetContents(() => testLinear(2)));
AddStep("Linear Slider", () => testLinear()); AddStep("Bezier Slider", () => SetContents(() => testBezier()));
AddStep("Linear Slider 1 Repeat", () => testLinear(1)); AddStep("Bezier Slider 1 Repeat", () => SetContents(() => testBezier(1)));
AddStep("Linear Slider 2 Repeats", () => testLinear(2)); AddStep("Bezier Slider 2 Repeats", () => SetContents(() => testBezier(2)));
AddStep("Bezier Slider", () => testBezier()); AddStep("Linear Overlapping", () => SetContents(() => testLinearOverlapping()));
AddStep("Bezier Slider 1 Repeat", () => testBezier(1)); AddStep("Linear Overlapping 1 Repeat", () => SetContents(() => testLinearOverlapping(1)));
AddStep("Bezier Slider 2 Repeats", () => testBezier(2)); AddStep("Linear Overlapping 2 Repeats", () => SetContents(() => testLinearOverlapping(2)));
AddStep("Linear Overlapping", () => testLinearOverlapping()); AddStep("Catmull Slider", () => SetContents(() => testCatmull()));
AddStep("Linear Overlapping 1 Repeat", () => testLinearOverlapping(1)); AddStep("Catmull Slider 1 Repeat", () => SetContents(() => testCatmull(1)));
AddStep("Linear Overlapping 2 Repeats", () => testLinearOverlapping(2)); AddStep("Catmull Slider 2 Repeats", () => SetContents(() => testCatmull(2)));
AddStep("Catmull Slider", () => testCatmull()); AddStep("Big Single, Large StackOffset", () => SetContents(() => testSimpleBigLargeStackOffset()));
AddStep("Catmull Slider 1 Repeat", () => testCatmull(1)); AddStep("Big 1 Repeat, Large StackOffset", () => SetContents(() => testSimpleBigLargeStackOffset(1)));
AddStep("Catmull Slider 2 Repeats", () => testCatmull(2));
AddStep("Big Single, Large StackOffset", () => testSimpleBigLargeStackOffset()); AddStep("Distance Overflow", () => SetContents(() => testDistanceOverflow()));
AddStep("Big 1 Repeat, Large StackOffset", () => testSimpleBigLargeStackOffset(1)); AddStep("Distance Overflow 1 Repeat", () => SetContents(() => testDistanceOverflow(1)));
AddStep("Distance Overflow", () => testDistanceOverflow());
AddStep("Distance Overflow 1 Repeat", () => testDistanceOverflow(1));
} }
private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); private Drawable testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats);
private void testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10); private Drawable testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10);
private void testDistanceOverflow(int repeats = 0) private Drawable testDistanceOverflow(int repeats = 0)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -120,22 +132,22 @@ namespace osu.Game.Rulesets.Osu.Tests
StackHeight = 10 StackHeight = 10
}; };
addSlider(slider, 2, 2); return createDrawable(slider, 2, 2);
} }
private void testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats); private Drawable testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats);
private void testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats); private Drawable testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats);
private void testSlowSpeed() => createSlider(speedMultiplier: 0.5); private Drawable testSlowSpeed() => createSlider(speedMultiplier: 0.5);
private void testShortSlowSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 0.5); private Drawable testShortSlowSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 0.5);
private void testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15); private Drawable testHighSpeed(int repeats = 0) => createSlider(repeats: repeats, speedMultiplier: 15);
private void testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15); private Drawable testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15);
private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0) private Drawable createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -151,10 +163,10 @@ namespace osu.Game.Rulesets.Osu.Tests
StackHeight = stackHeight StackHeight = stackHeight
}; };
addSlider(slider, circleSize, speedMultiplier); return createDrawable(slider, circleSize, speedMultiplier);
} }
private void testPerfect(int repeats = 0) private Drawable testPerfect(int repeats = 0)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -170,12 +182,12 @@ namespace osu.Game.Rulesets.Osu.Tests
NodeSamples = createEmptySamples(repeats) NodeSamples = createEmptySamples(repeats)
}; };
addSlider(slider, 2, 3); return createDrawable(slider, 2, 3);
} }
private void testLinear(int repeats = 0) => createLinear(repeats); private Drawable testLinear(int repeats = 0) => createLinear(repeats);
private void createLinear(int repeats) private Drawable createLinear(int repeats)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -194,12 +206,12 @@ namespace osu.Game.Rulesets.Osu.Tests
NodeSamples = createEmptySamples(repeats) NodeSamples = createEmptySamples(repeats)
}; };
addSlider(slider, 2, 3); return createDrawable(slider, 2, 3);
} }
private void testBezier(int repeats = 0) => createBezier(repeats); private Drawable testBezier(int repeats = 0) => createBezier(repeats);
private void createBezier(int repeats) private Drawable createBezier(int repeats)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -217,12 +229,12 @@ namespace osu.Game.Rulesets.Osu.Tests
NodeSamples = createEmptySamples(repeats) NodeSamples = createEmptySamples(repeats)
}; };
addSlider(slider, 2, 3); return createDrawable(slider, 2, 3);
} }
private void testLinearOverlapping(int repeats = 0) => createOverlapping(repeats); private Drawable testLinearOverlapping(int repeats = 0) => createOverlapping(repeats);
private void createOverlapping(int repeats) private Drawable createOverlapping(int repeats)
{ {
var slider = new Slider var slider = new Slider
{ {
@ -241,12 +253,12 @@ namespace osu.Game.Rulesets.Osu.Tests
NodeSamples = createEmptySamples(repeats) NodeSamples = createEmptySamples(repeats)
}; };
addSlider(slider, 2, 3); return createDrawable(slider, 2, 3);
} }
private void testCatmull(int repeats = 0) => createCatmull(repeats); private Drawable testCatmull(int repeats = 0) => createCatmull(repeats);
private void createCatmull(int repeats = 0) private Drawable createCatmull(int repeats = 0)
{ {
var repeatSamples = new List<List<HitSampleInfo>>(); var repeatSamples = new List<List<HitSampleInfo>>();
for (int i = 0; i < repeats; i++) for (int i = 0; i < repeats; i++)
@ -267,7 +279,7 @@ namespace osu.Game.Rulesets.Osu.Tests
NodeSamples = repeatSamples NodeSamples = repeatSamples
}; };
addSlider(slider, 3, 1); return createDrawable(slider, 3, 1);
} }
private List<List<HitSampleInfo>> createEmptySamples(int repeats) private List<List<HitSampleInfo>> createEmptySamples(int repeats)
@ -278,7 +290,7 @@ namespace osu.Game.Rulesets.Osu.Tests
return repeatSamples; return repeatSamples;
} }
private void addSlider(Slider slider, float circleSize, double speedMultiplier) private Drawable createDrawable(Slider slider, float circleSize, double speedMultiplier)
{ {
var cpi = new ControlPointInfo(); var cpi = new ControlPointInfo();
cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier });
@ -296,7 +308,7 @@ namespace osu.Game.Rulesets.Osu.Tests
drawable.OnNewResult += onNewResult; drawable.OnNewResult += onNewResult;
Add(drawable); return drawable;
} }
private float judgementOffsetDirection = 1; private float judgementOffsetDirection = 1;

View File

@ -4,7 +4,7 @@
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" /> <PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.14.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" /> <PackageReference Update="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Project"> <PropertyGroup Label="Project">

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Difficulty.Skills; using osu.Game.Rulesets.Osu.Difficulty.Skills;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
@ -34,8 +35,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier; double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2; double starRating = aimRating + speedRating + Math.Abs(aimRating - speedRating) / 2;
HitWindows hitWindows = new OsuHitWindows();
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
// Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future // 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) / clockRate; double hitWindowGreat = (int)(hitWindows.Great / 2) / clockRate;
double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate; double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
int maxCombo = beatmap.HitObjects.Count; int maxCombo = beatmap.HitObjects.Count;

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
public class DrawableOsuEditRuleset : DrawableOsuRuleset public class DrawableOsuEditRuleset : DrawableOsuRuleset
{ {
public DrawableOsuEditRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) public DrawableOsuEditRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {
} }

View File

@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Edit
{ {
} }
protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, WorkingBeatmap beatmap, IReadOnlyList<Mod> mods) protected override DrawableRuleset<OsuHitObject> CreateDrawableRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList<Mod> mods)
=> new DrawableOsuEditRuleset(ruleset, beatmap, mods); => new DrawableOsuEditRuleset(ruleset, beatmap, mods);
protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[] protected override IReadOnlyList<HitObjectCompositionTool> CompositionTools => new HitObjectCompositionTool[]

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Osu.Judgements namespace osu.Game.Rulesets.Osu.Judgements
{ {
@ -9,8 +10,8 @@ namespace osu.Game.Rulesets.Osu.Judgements
{ {
public ComboResult ComboType; public ComboResult ComboType;
public OsuJudgementResult(Judgement judgement) public OsuJudgementResult(HitObject hitObject, Judgement judgement)
: base(judgement) : base(hitObject, judgement)
{ {
} }
} }

View File

@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.Osu.Mods
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(TextureStore textures) private void load(TextureStore textures)
{ {
Texture = textures.Get("Play/osu/blinds-panel"); Texture = textures.Get("Gameplay/osu/blinds-panel");
} }
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -38,7 +39,12 @@ namespace osu.Game.Rulesets.Osu.Mods
if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit) if ((osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime) || osuHit.IsHit)
continue; continue;
requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); if (osuHit is DrawableHitCircle && osuHit.IsHovered)
{
Debug.Assert(osuHit.HitObject.HitWindows != null);
requiresHit |= osuHit.HitObject.HitWindows.CanBeHit(relativetime);
}
requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner; requiresHold |= (osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered)) || osuHit is DrawableSpinner;
} }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Child = new SkinnableDrawable("Play/osu/followpoint", _ => new Container Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.FollowPoint), _ => new Container
{ {
Masking = true, Masking = true,
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
Child = new Box Child = new Box
{ {
Size = new Vector2(width), Size = new Vector2(width),
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Alpha = 0.5f, Alpha = 0.5f,

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Diagnostics;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -29,6 +30,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly HitArea hitArea; private readonly HitArea hitArea;
private readonly SkinnableDrawable mainContent;
public DrawableHitCircle(HitCircle h) public DrawableHitCircle(HitCircle h)
: base(h) : base(h)
{ {
@ -56,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return true; return true;
}, },
}, },
new SkinnableDrawable("Play/osu/hitcircle", _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), mainContent = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)),
ApproachCircle = new ApproachCircle ApproachCircle = new ApproachCircle
{ {
Alpha = 0, Alpha = 0,
@ -85,6 +88,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void CheckForResult(bool userTriggered, double timeOffset) protected override void CheckForResult(bool userTriggered, double timeOffset)
{ {
Debug.Assert(HitObject.HitWindows != null);
if (!userTriggered) if (!userTriggered)
{ {
if (!HitObject.HitWindows.CanBeHit(timeOffset)) if (!HitObject.HitWindows.CanBeHit(timeOffset))
@ -108,6 +113,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
base.UpdateInitialTransforms(); base.UpdateInitialTransforms();
mainContent.FadeInFromZero(HitObject.TimeFadeIn);
ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt));
ApproachCircle.ScaleTo(1f, HitObject.TimePreempt); ApproachCircle.ScaleTo(1f, HitObject.TimePreempt);
ApproachCircle.Expire(true); ApproachCircle.Expire(true);
@ -115,6 +122,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void UpdateStateTransforms(ArmedState state) protected override void UpdateStateTransforms(ArmedState state)
{ {
Debug.Assert(HitObject.HitWindows != null);
switch (state) switch (state)
{ {
case ArmedState.Idle: case ArmedState.Idle:

View File

@ -36,13 +36,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
protected override void UpdateInitialTransforms() => this.FadeIn(HitObject.TimeFadeIn);
private OsuInputManager osuActionInputManager; private OsuInputManager osuActionInputManager;
internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager);
protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength);
protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement);
} }
} }

View File

@ -32,10 +32,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Blending = BlendingMode.Additive; Blending = BlendingParameters.Additive;
Origin = Anchor.Centre; Origin = Anchor.Centre;
InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.ReverseArrow), _ => new SpriteIcon
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.Solid.ChevronRight, Icon = FontAwesome.Solid.ChevronRight,

View File

@ -93,6 +93,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
} }
} }
protected override void UpdateInitialTransforms()
{
base.UpdateInitialTransforms();
Body.FadeInFromZero(HitObject.TimeFadeIn);
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {

View File

@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2); Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Origin = Anchor.Centre; Origin = Anchor.Centre;
InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new CircularContainer InternalChild = scaleContainer = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderScorePoint), _ => new CircularContainer
{ {
Masking = true, Masking = true,
Origin = Anchor.Centre, Origin = Anchor.Centre,

View File

@ -31,13 +31,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private class SkinnableApproachCircle : SkinnableSprite private class SkinnableApproachCircle : SkinnableSprite
{ {
public SkinnableApproachCircle() public SkinnableApproachCircle()
: base("Play/osu/approachcircle") : base("Gameplay/osu/approachcircle")
{ {
} }
protected override Drawable CreateDefault(string name) protected override Drawable CreateDefault(ISkinComponent component)
{ {
var drawable = base.CreateDefault(name); var drawable = base.CreateDefault(component);
// account for the sprite being used for the default approach circle being taken from stable, // account for the sprite being used for the default approach circle being taken from stable,
// when hitcircles have 5px padding on each size. this should be removed if we update the sprite. // when hitcircles have 5px padding on each size. this should be removed if we update the sprite.

View File

@ -31,12 +31,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Texture = textures.Get(@"Play/osu/disc"), Texture = textures.Get(@"Gameplay/osu/disc"),
}, },
new TrianglesPiece new TrianglesPiece
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
Alpha = 0.5f, Alpha = 0.5f,
} }
}; };

View File

@ -3,7 +3,6 @@
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Skinning;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
@ -17,15 +16,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Blending = BlendingMode.Additive; Blending = BlendingParameters.Additive;
Alpha = 0; Alpha = 0;
Child = new SkinnableDrawable("Play/osu/hitcircle-explode", _ => new TrianglesPiece Child = new TrianglesPiece
{ {
Blending = BlendingMode.Additive, Blending = BlendingParameters.Additive,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Alpha = 0.2f, Alpha = 0.2f,
}, s => s.GetTexture("Play/osu/hitcircle") == null); };
} }
} }
} }

View File

@ -5,7 +5,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osuTK; using osuTK;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
@ -18,10 +17,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Anchor = Anchor.Centre; Anchor = Anchor.Centre;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Blending = BlendingMode.Additive; Blending = BlendingParameters.Additive;
Alpha = 0; Alpha = 0;
Child = new SkinnableDrawable("Play/osu/hitcircle-flash", name => new CircularContainer Child = new CircularContainer
{ {
Masking = true, Masking = true,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{ {
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
} }
}, s => s.GetTexture("Play/osu/hitcircle") == null); };
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More