mirror of
https://github.com/ppy/osu.git
synced 2025-01-06 20:33:08 +08:00
Merge branch 'master' into fix-hit-error-ticks-outside-bounds
This commit is contained in:
commit
5b8035052f
8
.github/ISSUE_TEMPLATE/00-mobile-issues.md
vendored
8
.github/ISSUE_TEMPLATE/00-mobile-issues.md
vendored
@ -1,8 +0,0 @@
|
||||
---
|
||||
name: Mobile Report
|
||||
about: ⚠ Due to current development priorities we are not accepting mobile reports at this time (unless you're willing to fix them yourself!)
|
||||
---
|
||||
|
||||
⚠ **PLEASE READ** ⚠: Due to prioritising finishing the client for desktop first we are not accepting reports related to mobile platforms for the time being, unless you're willing to fix them.
|
||||
If you'd like to report a problem or suggest a feature and then work on it, feel free to open an issue and highlight that you'd like to address it yourself in the issue body; mobile pull requests are also welcome.
|
||||
Otherwise, please check back in the future when the focus of development shifts towards mobile!
|
7
.github/ISSUE_TEMPLATE/01-bug-issues.md
vendored
7
.github/ISSUE_TEMPLATE/01-bug-issues.md
vendored
@ -8,4 +8,9 @@ about: Issues regarding encountered bugs.
|
||||
|
||||
**osu!lazer version:**
|
||||
|
||||
**Logs:**
|
||||
**Logs:**
|
||||
<!--
|
||||
*please attach logs here, which are located at:*
|
||||
- `%AppData%/osu/logs` *(on Windows),*
|
||||
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||
-->
|
||||
|
7
.github/ISSUE_TEMPLATE/02-crash-issues.md
vendored
7
.github/ISSUE_TEMPLATE/02-crash-issues.md
vendored
@ -8,6 +8,11 @@ about: Issues regarding crashes or permanent freezes.
|
||||
|
||||
**osu!lazer version:**
|
||||
|
||||
**Logs:**
|
||||
**Logs:**
|
||||
<!--
|
||||
*please attach logs here, which are located at:*
|
||||
- `%AppData%/osu/logs` *(on Windows),*
|
||||
- `~/.local/share/osu/logs` *(on Linux & macOS).*
|
||||
-->
|
||||
|
||||
**Computer Specifications:**
|
||||
|
42
.vscode/launch.json
vendored
42
.vscode/launch.json
vendored
@ -11,11 +11,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -28,11 +23,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -45,11 +35,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -62,11 +47,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tests/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -80,11 +60,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -98,11 +73,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build osu! (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Desktop/bin/Release/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -116,11 +86,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Debug)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -134,11 +99,6 @@
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "Build tournament tests (Release)",
|
||||
"linux": {
|
||||
"env": {
|
||||
"LD_LIBRARY_PATH": "${workspaceRoot}/osu.Game.Tournament.Tests/bin/Debug/netcoreapp3.1:${env:LD_LIBRARY_PATH}"
|
||||
}
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
@ -169,4 +129,4 @@
|
||||
"externalConsole": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ Rhythm is just a *click* away. The future of [osu!](https://osu.ppy.sh) and the
|
||||
|
||||
This project is under heavy development, but is in a stable state. Users are encouraged to try it out and keep it installed alongside the stable *osu!* client. It will continue to evolve to the point of eventually replacing the existing stable client as an update.
|
||||
|
||||
We are accepting bug reports (please report with as much detail as possible). Feature requests are also welcome, but understand that our focus is on completing the game to feature parity before adding new features. A few resources are available as starting points to getting involved and understanding the project:
|
||||
We are accepting bug reports (please report with as much detail as possible and follow the existing issue templates). Feature requests are also welcome, but understand that our focus is on completing the game to feature parity before adding new features. A few resources are available as starting points to getting involved and understanding the project:
|
||||
|
||||
- Detailed release changelogs are available on the [official osu! site](https://osu.ppy.sh/home/changelog/lazer).
|
||||
- You can learn more about our approach to [project management](https://github.com/ppy/osu/wiki/Project-management).
|
||||
@ -27,7 +27,7 @@ If you are looking to install or test osu! without setting up a development envi
|
||||
|
||||
**Latest build:**
|
||||
|
||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.x86_64.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
|
||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) | [Linux (x64)](https://github.com/ppy/osu/releases/latest/download/osu.AppImage) | [iOS(iOS 10+)](https://osu.ppy.sh/home/testflight) | [Android (5+)](https://github.com/ppy/osu/releases/latest/download/sh.ppy.osulazer.apk)
|
||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||
|
||||
- When running on Windows 7 or 8.1, **[additional prerequisites](https://docs.microsoft.com/en-us/dotnet/core/install/dependencies?tabs=netcore31&pivots=os-windows)** may be required to correctly run .NET Core applications if your operating system is not up-to-date with the latest service packs.
|
||||
|
@ -25,7 +25,6 @@
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<EnableLLVM>false</EnableLLVM>
|
||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>true</AndroidUseSharedRuntime>
|
||||
<EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
|
||||
@ -34,7 +33,6 @@
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<DebugType>None</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<EnableLLVM>true</EnableLLVM>
|
||||
<AndroidManagedSymbols>false</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
@ -53,7 +51,7 @@
|
||||
<Reference Include="Java.Interop" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.221.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.304.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.305.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -30,11 +30,6 @@ namespace osu.Android
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new SimpleUpdateManager());
|
||||
}
|
||||
protected override UpdateManager CreateUpdateManager() => new SimpleUpdateManager();
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
<AssemblyName>osu.Android</AssemblyName>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;arm64-v8a</AndroidSupportedAbis>
|
||||
<EnableLLVM>false</EnableLLVM> <!-- This currently causes random lockups during gameplay. https://github.com/mono/mono/issues/18973 -->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<MandroidI18n>cjk;mideast;other;rare;west</MandroidI18n>
|
||||
@ -52,4 +53,4 @@
|
||||
<AndroidResource Include="Resources\drawable\lazer.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -47,20 +47,25 @@ namespace osu.Desktop
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override UpdateManager CreateUpdateManager()
|
||||
{
|
||||
switch (RuntimeInfo.OS)
|
||||
{
|
||||
case RuntimeInfo.Platform.Windows:
|
||||
return new SquirrelUpdateManager();
|
||||
|
||||
default:
|
||||
return new SimpleUpdateManager();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
if (!noVersionOverlay)
|
||||
{
|
||||
LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
|
||||
|
||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows)
|
||||
Add(new SquirrelUpdateManager());
|
||||
else
|
||||
Add(new SimpleUpdateManager());
|
||||
}
|
||||
|
||||
LoadComponentAsync(new DiscordRichPresence(), Add);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return base.CreatePlayer(ruleset);
|
||||
|
@ -29,6 +29,12 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBananaShower()
|
||||
{
|
||||
AddUntilStep("player is done", () => !Player.ValidForResume);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
@ -40,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
}
|
||||
};
|
||||
|
||||
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true });
|
||||
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 3000, NewCombo = true });
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
@ -42,6 +42,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
AddStep("show droplet", () => SetContents(createDrawableDroplet));
|
||||
|
||||
AddStep("show tiny droplet", () => SetContents(createDrawableTinyDroplet));
|
||||
|
||||
foreach (FruitVisualRepresentation rep in Enum.GetValues(typeof(FruitVisualRepresentation)))
|
||||
AddStep($"show hyperdash {rep}", () => SetContents(() => createDrawable(rep, true)));
|
||||
}
|
||||
|
||||
private Drawable createDrawableTinyDroplet()
|
||||
@ -82,9 +85,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
};
|
||||
}
|
||||
|
||||
private Drawable createDrawable(FruitVisualRepresentation rep)
|
||||
private Drawable createDrawable(FruitVisualRepresentation rep, bool hyperdash = false)
|
||||
{
|
||||
Fruit fruit = new TestCatchFruit(rep) { Scale = 1.5f };
|
||||
Fruit fruit = new TestCatchFruit(rep)
|
||||
{
|
||||
Scale = 1.5f,
|
||||
HyperDashTarget = hyperdash ? new Banana() : null
|
||||
};
|
||||
|
||||
return new DrawableFruit(fruit)
|
||||
{
|
||||
|
56
osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs
Normal file
56
osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs
Normal file
@ -0,0 +1,56 @@
|
||||
// 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.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class TestSceneJuiceStream : PlayerTestScene
|
||||
{
|
||||
public TestSceneJuiceStream()
|
||||
: base(new CatchRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJuiceStreamEndingCombo()
|
||||
{
|
||||
AddUntilStep("player is done", () => !Player.ValidForResume);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 },
|
||||
Ruleset = ruleset
|
||||
},
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new JuiceStream
|
||||
{
|
||||
X = 0.5f,
|
||||
Path = new SliderPath(PathType.Linear, new[]
|
||||
{
|
||||
Vector2.Zero,
|
||||
new Vector2(0, 100)
|
||||
}),
|
||||
StartTime = 200
|
||||
},
|
||||
new Banana
|
||||
{
|
||||
X = 0.5f,
|
||||
StartTime = 1000,
|
||||
NewCombo = true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// 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.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects
|
||||
@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
|
||||
public override bool LastInCombo => true;
|
||||
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
|
||||
protected override void CreateNestedHitObjects()
|
||||
{
|
||||
base.CreateNestedHitObjects();
|
||||
|
@ -7,9 +7,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
@ -64,15 +62,24 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
|
||||
if (hitObject.HyperDash)
|
||||
{
|
||||
AddInternal(new Pulp
|
||||
AddInternal(new Circle
|
||||
{
|
||||
RelativePositionAxes = Axes.Both,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AccentColour = { Value = Color4.Red },
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0.5f,
|
||||
Scale = new Vector2(1.333f)
|
||||
BorderColour = Color4.Red,
|
||||
BorderThickness = 12f * RADIUS_ADJUST,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0.3f,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Red,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
/// </summary>
|
||||
private const float base_scoring_distance = 100;
|
||||
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
|
||||
public int RepeatCount { get; set; }
|
||||
|
||||
public double Velocity;
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Skinning
|
||||
@ -49,6 +50,23 @@ namespace osu.Game.Rulesets.Catch.Skinning
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
};
|
||||
|
||||
if (drawableCatchObject.HitObject.HyperDash)
|
||||
{
|
||||
var hyperDash = new Sprite
|
||||
{
|
||||
Texture = skin.GetTexture(lookupName),
|
||||
Colour = Color4.Red,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Depth = 1,
|
||||
Alpha = 0.7f,
|
||||
Scale = new Vector2(1.2f)
|
||||
};
|
||||
|
||||
AddInternal(hyperDash);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
@ -50,6 +50,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public void OnResult(DrawableCatchHitObject fruit, JudgementResult result)
|
||||
{
|
||||
if (result.Judgement is IgnoreJudgement)
|
||||
return;
|
||||
|
||||
void runAfterLoaded(Action action)
|
||||
{
|
||||
if (lastPlateableFruit == null)
|
||||
@ -89,7 +92,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
if (fruit.HitObject.LastInCombo)
|
||||
{
|
||||
if (((CatchJudgement)result.Judgement).ShouldExplodeFor(result))
|
||||
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
||||
runAfterLoaded(() => MovableCatcher.Explode());
|
||||
else
|
||||
MovableCatcher.Drop();
|
||||
|
@ -1,14 +0,0 @@
|
||||
// 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.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class HoldNoteJudgement : ManiaJudgement
|
||||
{
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
protected override int NumericResultFor(HitResult result) => 0;
|
||||
}
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Caching;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
@ -22,21 +22,13 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
|
||||
private class ManiaFlashlight : Flashlight
|
||||
{
|
||||
private readonly Cached flashlightProperties = new Cached();
|
||||
private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
|
||||
|
||||
public ManiaFlashlight()
|
||||
{
|
||||
FlashlightSize = new Vector2(0, default_flashlight_size);
|
||||
}
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
{
|
||||
flashlightProperties.Invalidate();
|
||||
}
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
AddLayout(flashlightProperties);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
public class BarLine : ManiaHitObject, IBarLine
|
||||
{
|
||||
public bool Major { get; set; }
|
||||
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +71,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateStateTransforms(ArmedState state)
|
||||
{
|
||||
}
|
||||
protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,13 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Caching;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
@ -65,6 +65,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AddLayout(subtractionCache);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -100,15 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Cached subtractionCache = new Cached();
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
subtractionCache.Invalidate();
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
@ -103,7 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
}
|
||||
}
|
||||
|
||||
public override Judgement CreateJudgement() => new HoldNoteJudgement();
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
|
||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||
}
|
||||
|
@ -115,9 +115,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Y = HIT_TARGET_POSITION + 150,
|
||||
BypassAutoSizeAxes = Axes.Both
|
||||
},
|
||||
topLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
|
@ -0,0 +1,86 @@
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public class TestSceneOsuModDifficultyAdjust : ModTestScene
|
||||
{
|
||||
public TestSceneOsuModDifficultyAdjust()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoAdjustment() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust(),
|
||||
Autoplay = true,
|
||||
PassCondition = checkSomeHit
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestCircleSize1() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 1 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsScale(0.78f)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestCircleSize10() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 10 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsScale(0.15f)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestApproachRate1() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsPreempt(1680)
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestApproachRate10() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 10 } },
|
||||
Autoplay = true,
|
||||
PassCondition = () => checkSomeHit() && checkObjectsPreempt(450)
|
||||
});
|
||||
|
||||
private bool checkObjectsPreempt(double target)
|
||||
{
|
||||
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||
if (!objects.Any())
|
||||
return false;
|
||||
|
||||
return objects.All(o => o.HitObject.TimePreempt == target);
|
||||
}
|
||||
|
||||
private bool checkObjectsScale(float target)
|
||||
{
|
||||
var objects = Player.ChildrenOfType<DrawableHitCircle>();
|
||||
if (!objects.Any())
|
||||
return false;
|
||||
|
||||
return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<ShakeContainer>().First().Children.OfType<Container>().Single().Scale.X, target));
|
||||
}
|
||||
|
||||
private bool checkSomeHit()
|
||||
{
|
||||
return Player.ScoreProcessor.JudgedHits >= 2;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public class TestSceneOsuModDoubleTime : ModTestScene
|
||||
{
|
||||
public TestSceneOsuModDoubleTime()
|
||||
: base(new OsuRuleset())
|
||||
{
|
||||
}
|
||||
|
||||
[TestCase(0.5)]
|
||||
[TestCase(1.01)]
|
||||
[TestCase(1.5)]
|
||||
[TestCase(2)]
|
||||
[TestCase(5)]
|
||||
public void TestSpeedChangeCustomisation(double rate)
|
||||
{
|
||||
var mod = new OsuModDoubleTime { SpeedChange = { Value = rate } };
|
||||
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = mod,
|
||||
PassCondition = () => Player.ScoreProcessor.JudgedHits >= 2 &&
|
||||
Precision.AlmostEquals(Player.GameplayClockContainer.GameplayClock.Rate, mod.SpeedChange.Value)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,12 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@ -114,6 +117,22 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
assertGroups();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStackedObjects()
|
||||
{
|
||||
addObjectsStep(() => new OsuHitObject[]
|
||||
{
|
||||
new HitCircle { Position = new Vector2(300, 100) },
|
||||
new HitCircle
|
||||
{
|
||||
Position = new Vector2(300, 300),
|
||||
StackHeight = 20
|
||||
},
|
||||
});
|
||||
|
||||
assertDirections();
|
||||
}
|
||||
|
||||
private void addMultipleObjectsStep() => addObjectsStep(() => new OsuHitObject[]
|
||||
{
|
||||
new HitCircle { Position = new Vector2(100, 100) },
|
||||
@ -207,6 +226,33 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
});
|
||||
}
|
||||
|
||||
private void assertDirections()
|
||||
{
|
||||
AddAssert("group directions are correct", () =>
|
||||
{
|
||||
for (int i = 0; i < hitObjectContainer.Count; i++)
|
||||
{
|
||||
DrawableOsuHitObject expectedStart = getObject(i);
|
||||
DrawableOsuHitObject expectedEnd = i < hitObjectContainer.Count - 1 ? getObject(i + 1) : null;
|
||||
|
||||
if (expectedEnd == null)
|
||||
continue;
|
||||
|
||||
var points = getGroup(i).ChildrenOfType<FollowPoint>().ToArray();
|
||||
if (points.Length == 0)
|
||||
continue;
|
||||
|
||||
float expectedDirection = MathF.Atan2(expectedStart.Position.Y - expectedEnd.Position.Y, expectedStart.Position.X - expectedEnd.Position.X);
|
||||
float realDirection = MathF.Atan2(expectedStart.Position.Y - points[^1].Position.Y, expectedStart.Position.X - points[^1].Position.X);
|
||||
|
||||
if (!Precision.AlmostEquals(expectedDirection, realDirection))
|
||||
throw new AssertionException($"Expected group {i} in direction {expectedDirection}, but was {realDirection}.");
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private DrawableOsuHitObject getObject(int index) => hitObjectContainer[index];
|
||||
|
||||
private FollowPointConnection getGroup(int index) => followPointRenderer.Connections[index];
|
||||
|
108
osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs
Normal file
108
osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleArea.cs
Normal file
@ -0,0 +1,108 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestSceneHitCircleArea : ManualInputManagerTestScene
|
||||
{
|
||||
private HitCircle hitCircle;
|
||||
private DrawableHitCircle drawableHitCircle;
|
||||
private DrawableHitCircle.HitReceptor hitAreaReceptor => drawableHitCircle.HitArea;
|
||||
|
||||
[SetUp]
|
||||
public new void SetUp()
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
hitCircle = new HitCircle
|
||||
{
|
||||
Position = new Vector2(100, 100),
|
||||
StartTime = Time.Current + 500
|
||||
};
|
||||
|
||||
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
Child = new SkinProvidingContainer(new DefaultSkin())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
|
||||
{
|
||||
Size = new Vector2(100)
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCircleHitCentre()
|
||||
{
|
||||
AddStep("move mouse to centre", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.Centre));
|
||||
scheduleHit();
|
||||
|
||||
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCircleHitLeftEdge()
|
||||
{
|
||||
AddStep("move mouse to left edge", () =>
|
||||
{
|
||||
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
|
||||
var mousePosition = new Vector2(drawQuad.TopLeft.X, drawQuad.Centre.Y);
|
||||
|
||||
InputManager.MoveMouseTo(mousePosition);
|
||||
});
|
||||
scheduleHit();
|
||||
|
||||
AddAssert("hit registered", () => hitAreaReceptor.HitAction == OsuAction.LeftButton);
|
||||
}
|
||||
|
||||
[TestCase(0.95f, OsuAction.LeftButton)]
|
||||
[TestCase(1.05f, null)]
|
||||
public void TestHitsCloseToEdge(float relativeDistanceFromCentre, OsuAction? expectedAction)
|
||||
{
|
||||
AddStep("move mouse to top left circle edge", () =>
|
||||
{
|
||||
var drawQuad = hitAreaReceptor.ScreenSpaceDrawQuad;
|
||||
// sqrt(2) / 2 = sin(45deg) = cos(45deg)
|
||||
// draw width halved to get radius
|
||||
float correction = relativeDistanceFromCentre * (float)Math.Sqrt(2) / 2 * (drawQuad.Width / 2);
|
||||
var mousePosition = new Vector2(drawQuad.Centre.X - correction, drawQuad.Centre.Y - correction);
|
||||
|
||||
InputManager.MoveMouseTo(mousePosition);
|
||||
});
|
||||
scheduleHit();
|
||||
|
||||
AddAssert($"hit {(expectedAction == null ? "not " : string.Empty)}registered", () => hitAreaReceptor.HitAction == expectedAction);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCircleMissBoundingBoxCorner()
|
||||
{
|
||||
AddStep("move mouse to top left corner of bounding box", () => InputManager.MoveMouseTo(hitAreaReceptor.ScreenSpaceDrawQuad.TopLeft));
|
||||
scheduleHit();
|
||||
|
||||
AddAssert("hit not registered", () => hitAreaReceptor.HitAction == null);
|
||||
}
|
||||
|
||||
private void scheduleHit() => AddStep("schedule action", () =>
|
||||
{
|
||||
var delay = hitCircle.StartTime - hitCircle.HitWindows.WindowFor(HitResult.Great) - Time.Current;
|
||||
Scheduler.AddDelayed(() => hitAreaReceptor.OnPressed(OsuAction.LeftButton), delay);
|
||||
});
|
||||
}
|
||||
}
|
@ -3,13 +3,13 @@
|
||||
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestSceneOsuFlashlight : TestSceneOsuPlayer
|
||||
{
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = new Mod[] { new OsuModAutoplay(), new OsuModFlashlight(), };
|
||||
|
||||
|
@ -18,7 +18,6 @@ using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Game.Tests.Visual;
|
||||
@ -56,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
private void checkNextHitObject(string skin) =>
|
||||
AddUntilStep($"check skin from {skin}", () =>
|
||||
{
|
||||
var firstObject = ((TestPlayer)Player).DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
||||
var firstObject = Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.OfType<DrawableHitCircle>().FirstOrDefault();
|
||||
|
||||
if (firstObject == null)
|
||||
return false;
|
||||
@ -75,7 +74,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
[Resolved]
|
||||
private AudioManager audio { get; set; }
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new SkinProvidingPlayer(testUserSkin);
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) => new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, audio, testBeatmapSkin);
|
||||
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -44,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
base.SetUpSteps();
|
||||
|
||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)((TestPlayer)Player).DrawableRuleset.Playfield.AllHitObjects.First());
|
||||
AddStep("retrieve spinner", () => drawableSpinner = (DrawableSpinner)Player.DrawableRuleset.Playfield.AllHitObjects.First());
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -89,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
AddStep($"seek to {time}", () => track.Seek(time));
|
||||
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, ((TestPlayer)Player).DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
|
||||
|
@ -1,14 +0,0 @@
|
||||
// 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.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Judgements
|
||||
{
|
||||
public class OsuSliderTailJudgement : OsuJudgement
|
||||
{
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
protected override int NumericResultFor(HitResult result) => 0;
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
private const int spacing = 32;
|
||||
private const double preempt = 800;
|
||||
|
||||
public override bool RemoveWhenNotAlive => false;
|
||||
|
||||
/// <summary>
|
||||
/// The start time of <see cref="Start"/>.
|
||||
/// </summary>
|
||||
@ -79,27 +81,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
drawableObject.HitObject.DefaultsApplied += scheduleRefresh;
|
||||
}
|
||||
|
||||
private void scheduleRefresh() => Scheduler.AddOnce(refresh);
|
||||
private void scheduleRefresh()
|
||||
{
|
||||
Scheduler.AddOnce(refresh);
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
ClearInternal();
|
||||
|
||||
if (End == null)
|
||||
return;
|
||||
|
||||
OsuHitObject osuStart = Start.HitObject;
|
||||
OsuHitObject osuEnd = End.HitObject;
|
||||
|
||||
if (osuEnd.NewCombo)
|
||||
return;
|
||||
|
||||
if (osuStart is Spinner || osuEnd is Spinner)
|
||||
return;
|
||||
|
||||
Vector2 startPosition = osuStart.EndPosition;
|
||||
Vector2 endPosition = osuEnd.Position;
|
||||
double startTime = osuStart.GetEndTime();
|
||||
|
||||
LifetimeStart = startTime;
|
||||
|
||||
OsuHitObject osuEnd = End?.HitObject;
|
||||
|
||||
if (osuEnd == null || osuEnd.NewCombo || osuStart is Spinner || osuEnd is Spinner)
|
||||
{
|
||||
// ensure we always set a lifetime for full LifetimeManagementContainer benefits
|
||||
LifetimeEnd = LifetimeStart;
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 startPosition = osuStart.StackedEndPosition;
|
||||
Vector2 endPosition = osuEnd.StackedPosition;
|
||||
double endTime = osuEnd.StartTime;
|
||||
|
||||
Vector2 distanceVector = endPosition - startPosition;
|
||||
@ -107,6 +113,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
|
||||
double duration = endTime - startTime;
|
||||
|
||||
double? firstTransformStartTime = null;
|
||||
double finalTransformEndTime = startTime;
|
||||
|
||||
for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing)
|
||||
{
|
||||
float fraction = (float)d / distance;
|
||||
@ -125,16 +134,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
Scale = new Vector2(1.5f * osuEnd.Scale),
|
||||
});
|
||||
|
||||
if (firstTransformStartTime == null)
|
||||
firstTransformStartTime = fadeInTime;
|
||||
|
||||
using (fp.BeginAbsoluteSequence(fadeInTime))
|
||||
{
|
||||
fp.FadeIn(osuEnd.TimeFadeIn);
|
||||
fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out);
|
||||
fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out);
|
||||
fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn);
|
||||
}
|
||||
|
||||
fp.Expire(true);
|
||||
finalTransformEndTime = fadeOutTime + osuEnd.TimeFadeIn;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: use Expire() on FollowPoints and take lifetime from them when https://github.com/ppy/osu-framework/issues/3300 is fixed.
|
||||
LifetimeStart = firstTransformStartTime ?? startTime;
|
||||
LifetimeEnd = finalTransformEndTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
/// <summary>
|
||||
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
|
||||
/// </summary>
|
||||
public class FollowPointRenderer : CompositeDrawable
|
||||
public class FollowPointRenderer : LifetimeManagementContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
|
||||
@ -45,8 +45,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
|
||||
private void addConnection(FollowPointConnection connection)
|
||||
{
|
||||
AddInternal(connection);
|
||||
|
||||
// Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections
|
||||
int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value)));
|
||||
|
||||
@ -74,6 +72,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
FollowPointConnection previousConnection = connections[index - 1];
|
||||
previousConnection.End = connection.Start;
|
||||
}
|
||||
|
||||
AddInternal(connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public Drawable ProxiedLayer => ApproachCircle;
|
||||
|
||||
public class HitReceptor : Drawable, IKeyBindingHandler<OsuAction>
|
||||
public class HitReceptor : CompositeDrawable, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
// IsHovered is used
|
||||
public override bool HandlePositionalInput => true;
|
||||
@ -185,6 +185,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
CornerRadius = OsuHitObject.OBJECT_RADIUS;
|
||||
CornerExponent = 2;
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
@ -23,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
|
||||
}
|
||||
|
||||
public override Judgement CreateJudgement() => new OsuSliderTailJudgement();
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
|
||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Caching;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Batches;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
@ -14,6 +13,7 @@ using osu.Framework.Graphics.Shaders;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Framework.Timing;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -43,6 +43,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
// -1 signals that the part is unusable, and should not be drawn
|
||||
parts[i].InvalidationID = -1;
|
||||
}
|
||||
|
||||
AddLayout(partSizeCache);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -72,20 +74,12 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Cached<Vector2> partSizeCache = new Cached<Vector2>();
|
||||
private readonly LayoutValue<Vector2> partSizeCache = new LayoutValue<Vector2>(Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence);
|
||||
|
||||
private Vector2 partSize => partSizeCache.IsValid
|
||||
? partSizeCache.Value
|
||||
: (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy);
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & (Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence)) > 0)
|
||||
partSizeCache.Invalidate();
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The amount of time to fade the cursor trail pieces.
|
||||
/// </summary>
|
||||
@ -97,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Invalidate(Invalidation.DrawNode, shallPropagate: false);
|
||||
Invalidate(Invalidation.DrawNode);
|
||||
|
||||
const int fade_clock_reset_threshold = 1000000;
|
||||
|
||||
|
@ -1,24 +1,16 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TestSceneSwellJudgements : PlayerTestScene
|
||||
{
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
public TestSceneSwellJudgements()
|
||||
: base(new TaikoRuleset())
|
||||
{
|
||||
@ -28,7 +20,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
public void TestZeroTickTimeOffsets()
|
||||
{
|
||||
AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted);
|
||||
AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.Judgement is TaikoSwellTickJudgement).All(r => r.TimeOffset == 0));
|
||||
AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.HitObject is SwellTick).All(r => r.TimeOffset == 0));
|
||||
}
|
||||
|
||||
protected override bool Autoplay => true;
|
||||
@ -50,25 +42,5 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer();
|
||||
|
||||
protected class TestPlayer : Player
|
||||
{
|
||||
public readonly List<JudgementResult> Results = new List<JudgementResult>();
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public TestPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScoreProcessor.NewJudgement += r => Results.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
@ -22,10 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
return base.CreatePlayer(ruleset);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) =>
|
||||
@ -49,20 +47,10 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
AddStep("Setup judgements", () =>
|
||||
{
|
||||
judged = false;
|
||||
((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true;
|
||||
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
||||
});
|
||||
AddUntilStep("swell judged", () => judged);
|
||||
AddAssert("not failed", () => !Player.HasFailed);
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Caching;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
@ -30,13 +30,15 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
|
||||
private class TaikoFlashlight : Flashlight
|
||||
{
|
||||
private readonly Cached flashlightProperties = new Cached();
|
||||
private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize);
|
||||
private readonly TaikoPlayfield taikoPlayfield;
|
||||
|
||||
public TaikoFlashlight(TaikoPlayfield taikoPlayfield)
|
||||
{
|
||||
this.taikoPlayfield = taikoPlayfield;
|
||||
FlashlightSize = new Vector2(0, getSizeFor(0));
|
||||
|
||||
AddLayout(flashlightProperties);
|
||||
}
|
||||
|
||||
private float getSizeFor(int combo)
|
||||
@ -56,16 +58,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
|
||||
protected override string FragmentShader => "CircularFlashlight";
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
{
|
||||
flashlightProperties.Invalidate();
|
||||
}
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects
|
||||
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
public class BarLine : TaikoHitObject, IBarLine
|
||||
{
|
||||
public bool Major { get; set; }
|
||||
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
}
|
||||
}
|
||||
|
@ -54,5 +54,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
Alpha = 0.75f
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,12 @@
|
||||
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects
|
||||
{
|
||||
public class SwellTick : TaikoHitObject
|
||||
{
|
||||
public override Judgement CreateJudgement() => new TaikoSwellTickJudgement();
|
||||
public override Judgement CreateJudgement() => new IgnoreJudgement();
|
||||
|
||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||
}
|
||||
|
@ -154,6 +154,7 @@ namespace osu.Game.Tests.Gameplay
|
||||
private class JudgeableHitObject : HitObject
|
||||
{
|
||||
public override Judgement CreateJudgement() => new Judgement();
|
||||
protected override HitWindows CreateHitWindows() => new HitWindows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
@ -78,7 +78,7 @@ namespace osu.Game.Tests.Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
private class TestHitObjectWithCombo : HitObject, IHasComboInformation
|
||||
private class TestHitObjectWithCombo : ConvertHitObject, IHasComboInformation
|
||||
{
|
||||
public bool NewCombo { get; } = false;
|
||||
public int ComboOffset { get; } = 0;
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
|
||||
private DummySongSelect songSelect;
|
||||
private TestPlayerLoader playerLoader;
|
||||
private TestPlayer player;
|
||||
private LoadBlockingTestPlayer player;
|
||||
private BeatmapManager manager;
|
||||
private RulesetStore rulesets;
|
||||
|
||||
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public void PlayerLoaderSettingsHoverTest()
|
||||
{
|
||||
setupUserSettings();
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer { BlockLoad = true })));
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer { BlockLoad = true })));
|
||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader?.IsLoaded ?? false);
|
||||
AddAssert("Background retained from song select", () => songSelect.IsBackgroundCurrent());
|
||||
AddStep("Trigger background preview", () =>
|
||||
@ -268,7 +268,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
{
|
||||
setupUserSettings();
|
||||
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new TestPlayer(allowPause))));
|
||||
AddStep("Start player loader", () => songSelect.Push(playerLoader = new TestPlayerLoader(player = new LoadBlockingTestPlayer(allowPause))));
|
||||
|
||||
AddUntilStep("Wait for Player Loader to load", () => playerLoader.IsLoaded);
|
||||
AddStep("Move mouse to center of screen", () => InputManager.MoveMouseTo(playerLoader.ScreenPos));
|
||||
@ -347,7 +347,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public bool IsBlurCorrect() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(BACKGROUND_BLUR);
|
||||
}
|
||||
|
||||
private class TestPlayer : Visual.TestPlayer
|
||||
private class LoadBlockingTestPlayer : TestPlayer
|
||||
{
|
||||
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
|
||||
|
||||
@ -360,7 +360,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
public readonly Bindable<bool> ReplacesBackground = new Bindable<bool>();
|
||||
public readonly Bindable<bool> IsPaused = new Bindable<bool>();
|
||||
|
||||
public TestPlayer(bool allowPause = true)
|
||||
public LoadBlockingTestPlayer(bool allowPause = true)
|
||||
: base(allowPause)
|
||||
{
|
||||
}
|
||||
|
@ -3,53 +3,32 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
[Description("Player instantiated with an autoplay mod.")]
|
||||
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
||||
{
|
||||
private ClockBackedTestWorkingBeatmap.TrackVirtualManual track;
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return new ScoreAccessiblePlayer();
|
||||
return new TestPlayer(false, false);
|
||||
}
|
||||
|
||||
protected override void AddCheckSteps()
|
||||
{
|
||||
AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0);
|
||||
AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
||||
AddStep("rewind", () => track.Seek(-10000));
|
||||
AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
}
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||
{
|
||||
var working = base.CreateWorkingBeatmap(beatmap, storyboard);
|
||||
|
||||
track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track;
|
||||
|
||||
return working;
|
||||
}
|
||||
|
||||
private class ScoreAccessiblePlayer : TestPlayer
|
||||
{
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public ScoreAccessiblePlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0);
|
||||
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2));
|
||||
AddStep("seek to break time", () => Player.GameplayClockContainer.Seek(Player.BreakOverlay.Breaks.First().StartTime));
|
||||
AddUntilStep("wait for seek to complete", () =>
|
||||
Player.HUDOverlay.Progress.ReferenceClock.CurrentTime >= Player.BreakOverlay.Breaks.First().StartTime);
|
||||
AddAssert("test keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting);
|
||||
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
|
||||
AddUntilStep("key counter reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@ -289,7 +290,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
#region HitObject
|
||||
|
||||
private class TestHitObject : HitObject, IHasEndTime
|
||||
private class TestHitObject : ConvertHitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime { get; set; }
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -11,12 +10,8 @@ using osu.Framework.Utils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Storyboards;
|
||||
using osuTK;
|
||||
|
||||
@ -24,8 +19,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneGameplayRewinding : PlayerTestScene
|
||||
{
|
||||
private RulesetExposingPlayer player => (RulesetExposingPlayer)Player;
|
||||
|
||||
[Resolved]
|
||||
private AudioManager audioManager { get; set; }
|
||||
|
||||
@ -48,13 +41,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
AddUntilStep("wait for track to start running", () => track.IsRunning);
|
||||
addSeekStep(3000);
|
||||
AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
||||
AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
||||
AddStep("clear results", () => player.AppliedResults.Clear());
|
||||
AddAssert("all judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged));
|
||||
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7));
|
||||
AddStep("clear results", () => Player.Results.Clear());
|
||||
addSeekStep(0);
|
||||
AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
||||
AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
AddAssert("no results triggered", () => player.AppliedResults.Count == 0);
|
||||
AddAssert("none judged", () => Player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged));
|
||||
AddUntilStep("key counters reset", () => Player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0));
|
||||
AddAssert("no results triggered", () => Player.Results.Count == 0);
|
||||
}
|
||||
|
||||
private void addSeekStep(double time)
|
||||
@ -62,13 +55,13 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddStep($"seek to {time}", () => track.Seek(time));
|
||||
|
||||
// Allow a few frames of lenience
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
AddUntilStep("wait for seek to finish", () => Precision.AlmostEquals(time, Player.DrawableRuleset.FrameStableClock.CurrentTime, 100));
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray();
|
||||
return new RulesetExposingPlayer();
|
||||
return base.CreatePlayer(ruleset);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
@ -89,29 +82,5 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
private class RulesetExposingPlayer : Player
|
||||
{
|
||||
public readonly List<JudgementResult> AppliedResults = new List<JudgementResult>();
|
||||
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
|
||||
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
|
||||
|
||||
public RulesetExposingPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ScoreProcessor.NewJudgement += r => AppliedResults.Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,16 +2,17 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Catch.Scoring;
|
||||
using osu.Game.Rulesets.Mania.Scoring;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Scoring;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Scoring;
|
||||
@ -43,6 +44,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20);
|
||||
AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20);
|
||||
AddStep("New fixed judgement (50ms)", () => newJudgement(50));
|
||||
|
||||
AddStep("Judgement barrage", () =>
|
||||
{
|
||||
int runCount = 0;
|
||||
|
||||
ScheduledDelegate del = null;
|
||||
|
||||
del = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
newJudgement(runCount++ / 10f);
|
||||
|
||||
if (runCount == 500)
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
del?.Cancel();
|
||||
}, 10, true);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -47,21 +47,22 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
|
||||
|
||||
AddStep($"Press {testKey} key", () =>
|
||||
void addPressKeyStep()
|
||||
{
|
||||
InputManager.PressKey(testKey);
|
||||
InputManager.ReleaseKey(testKey);
|
||||
});
|
||||
AddStep($"Press {testKey} key", () =>
|
||||
{
|
||||
InputManager.PressKey(testKey);
|
||||
InputManager.ReleaseKey(testKey);
|
||||
});
|
||||
}
|
||||
|
||||
addPressKeyStep();
|
||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1);
|
||||
|
||||
AddStep($"Press {testKey} key", () =>
|
||||
{
|
||||
InputManager.PressKey(testKey);
|
||||
InputManager.ReleaseKey(testKey);
|
||||
});
|
||||
|
||||
addPressKeyStep();
|
||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2);
|
||||
AddStep("Disable counting", () => testCounter.IsCounting = false);
|
||||
addPressKeyStep();
|
||||
AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses == 2);
|
||||
|
||||
Add(kc);
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
@ -282,14 +281,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
protected override bool AllowFail => true;
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new PausePlayer();
|
||||
|
||||
protected class PausePlayer : TestPlayer
|
||||
{
|
||||
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
||||
|
||||
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||
|
||||
public bool FailOverlayVisible => FailOverlay.State.Value == Visibility.Visible;
|
||||
|
||||
public bool PauseOverlayVisible => PauseOverlay.State.Value == Visibility.Visible;
|
||||
|
@ -9,15 +9,12 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
[HeadlessTest] // we alter unsafe properties on the game host to test inactive window state.
|
||||
public class TestScenePauseWhenInactive : PlayerTestScene
|
||||
{
|
||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
||||
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = (Beatmap)base.CreateBeatmap(ruleset);
|
||||
@ -46,6 +43,6 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
AddAssert("time of pause is after gameplay start time", () => Player.GameplayClockContainer.GameplayClock.CurrentTime >= Player.DrawableRuleset.GameplayStartTime);
|
||||
}
|
||||
|
||||
protected override Player CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, true, true);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Utils;
|
||||
@ -307,17 +306,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
|
||||
}
|
||||
|
||||
private class TestPlayer : Visual.TestPlayer
|
||||
{
|
||||
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
||||
|
||||
public TestPlayer(bool allowPause = true, bool showResults = true)
|
||||
: base(allowPause, showResults)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected class SlowLoadPlayer : Visual.TestPlayer
|
||||
protected class SlowLoadPlayer : TestPlayer
|
||||
{
|
||||
public readonly ManualResetEventSlim AllowLoad = new ManualResetEventSlim(false);
|
||||
|
||||
|
@ -62,14 +62,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
var frameworkConfig = host.Dependencies.Get<FrameworkConfigManager>();
|
||||
frameworkConfig.GetBindable<double>(FrameworkSetting.CursorSensitivity).Disabled = false;
|
||||
|
||||
Game = new TestOsuGame(LocalStorage, API);
|
||||
Game.SetHost(host);
|
||||
|
||||
// todo: this can be removed once we can run audio tracks without a device present
|
||||
// see https://github.com/ppy/osu/issues/1302
|
||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||
|
||||
Add(Game);
|
||||
CreateGame();
|
||||
});
|
||||
|
||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||
@ -78,6 +71,18 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
ConfirmAtMainMenu();
|
||||
}
|
||||
|
||||
protected void CreateGame()
|
||||
{
|
||||
Game = new TestOsuGame(LocalStorage, API);
|
||||
Game.SetHost(host);
|
||||
|
||||
// todo: this can be removed once we can run audio tracks without a device present
|
||||
// see https://github.com/ppy/osu/issues/1302
|
||||
Game.LocalConfig.Set(OsuSetting.IntroSequence, IntroSequence.Circles);
|
||||
|
||||
Add(Game);
|
||||
}
|
||||
|
||||
protected void PushAndConfirm(Func<Screen> newScreen)
|
||||
{
|
||||
Screen screen = null;
|
||||
@ -97,12 +102,17 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
public new SettingsPanel Settings => base.Settings;
|
||||
|
||||
public new MusicController MusicController => base.MusicController;
|
||||
|
||||
public new OsuConfigManager LocalConfig => base.LocalConfig;
|
||||
|
||||
public new Bindable<WorkingBeatmap> Beatmap => base.Beatmap;
|
||||
|
||||
public new Bindable<RulesetInfo> Ruleset => base.Ruleset;
|
||||
|
||||
// if we don't do this, when running under nUnit the version that gets populated is that of nUnit.
|
||||
public override string Version => "test game";
|
||||
|
||||
protected override Loader CreateLoader() => new TestLoader();
|
||||
|
||||
public new void PerformFromScreen(Action<IScreen> action, IEnumerable<Type> validScreens = null) => base.PerformFromScreen(action, validScreens);
|
||||
|
@ -114,6 +114,22 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddAssert("Options overlay was closed", () => Game.Settings.State.Value == Visibility.Hidden);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestWaitForNextTrackInMenu()
|
||||
{
|
||||
bool trackCompleted = false;
|
||||
|
||||
AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded);
|
||||
AddStep("Seek close to end", () =>
|
||||
{
|
||||
Game.MusicController.SeekTo(Game.Beatmap.Value.Track.Length - 1000);
|
||||
Game.Beatmap.Value.Track.Completed += () => trackCompleted = true;
|
||||
});
|
||||
|
||||
AddUntilStep("Track was completed", () => trackCompleted);
|
||||
AddUntilStep("Track was restarted", () => Game.Beatmap.Value.Track.IsRunning);
|
||||
}
|
||||
|
||||
private void pushEscape() =>
|
||||
AddStep("Press escape", () => pressAndRelease(Key.Escape));
|
||||
|
||||
|
41
osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
Normal file
41
osu.Game.Tests/Visual/Navigation/TestSettingsMigration.cs
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Configuration;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Navigation
|
||||
{
|
||||
public class TestSettingsMigration : OsuGameTestScene
|
||||
{
|
||||
public override void RecycleLocalStorage()
|
||||
{
|
||||
base.RecycleLocalStorage();
|
||||
|
||||
using (var config = new OsuConfigManager(LocalStorage))
|
||||
{
|
||||
config.Set(OsuSetting.Version, "2020.101.0");
|
||||
config.Set(OsuSetting.DisplayStarsMaximum, 10.0);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDisplayStarsMigration()
|
||||
{
|
||||
AddAssert("config has migrated value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10.1));
|
||||
|
||||
AddStep("set value again", () => Game.LocalConfig.Set<double>(OsuSetting.DisplayStarsMaximum, 10));
|
||||
|
||||
AddStep("force save config", () => Game.LocalConfig.Save());
|
||||
|
||||
AddStep("remove game", () => Remove(Game));
|
||||
|
||||
AddStep("create game again", CreateGame);
|
||||
|
||||
AddUntilStep("Wait for load", () => Game.IsLoaded);
|
||||
|
||||
AddAssert("config did not migrate value", () => Precision.AlmostEquals(Game.LocalConfig.Get<double>(OsuSetting.DisplayStarsMaximum), 10));
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osuTK;
|
||||
using JetBrains.Annotations;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -30,6 +32,8 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private readonly BindableBool showDeleted = new BindableBool();
|
||||
private readonly Container content;
|
||||
|
||||
private TestCommentsPage commentsPage;
|
||||
|
||||
public TestSceneCommentsPage()
|
||||
{
|
||||
Add(new FillFlowContainer
|
||||
@ -57,15 +61,29 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AddStep("load comments", () => createPage(getCommentBundle()));
|
||||
AddStep("load empty comments", () => createPage(getEmptyCommentBundle()));
|
||||
[Test]
|
||||
public void TestAppendDuplicatedComment()
|
||||
{
|
||||
AddStep("Create page", () => createPage(getCommentBundle()));
|
||||
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
|
||||
AddStep("Append existing comment", () => commentsPage?.AppendComments(getCommentSubBundle()));
|
||||
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEmptyBundle()
|
||||
{
|
||||
AddStep("Create page", () => createPage(getEmptyCommentBundle()));
|
||||
AddAssert("Dictionary length is 0", () => commentsPage?.DictionaryLength == 0);
|
||||
}
|
||||
|
||||
private void createPage(CommentBundle commentBundle)
|
||||
{
|
||||
commentsPage = null;
|
||||
content.Clear();
|
||||
content.Add(new CommentsPage(commentBundle)
|
||||
content.Add(commentsPage = new TestCommentsPage(commentBundle)
|
||||
{
|
||||
ShowDeleted = { BindTarget = showDeleted }
|
||||
});
|
||||
@ -182,5 +200,33 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
private CommentBundle getCommentSubBundle() => new CommentBundle
|
||||
{
|
||||
Comments = new List<Comment>
|
||||
{
|
||||
new Comment
|
||||
{
|
||||
Id = 1,
|
||||
Message = "Simple test comment",
|
||||
LegacyName = "TestUser1",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 5
|
||||
},
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
};
|
||||
|
||||
private class TestCommentsPage : CommentsPage
|
||||
{
|
||||
public TestCommentsPage(CommentBundle commentBundle)
|
||||
: base(commentBundle)
|
||||
{
|
||||
}
|
||||
|
||||
public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle);
|
||||
|
||||
public int DictionaryLength => CommentDictionary.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets;
|
||||
@ -14,7 +15,8 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneDirectPanel : OsuTestScene
|
||||
[Cached(typeof(IPreviewTrackOwner))]
|
||||
public class TestSceneDirectPanel : OsuTestScene, IPreviewTrackOwner
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
|
@ -2,9 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
|
||||
@ -13,13 +15,19 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[TestFixture]
|
||||
public class TestSceneUserPanel : OsuTestScene
|
||||
{
|
||||
private readonly UserPanel peppy;
|
||||
private readonly Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||
|
||||
public TestSceneUserPanel()
|
||||
private UserPanel peppy;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesetStore { get; set; }
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
UserPanel flyte;
|
||||
|
||||
Add(new FillFlowContainer
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
@ -44,34 +52,38 @@ namespace osu.Game.Tests.Visual.Online
|
||||
SupportLevel = 3,
|
||||
}) { Width = 300 },
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
flyte.Status.Value = new UserStatusOnline();
|
||||
peppy.Status.Value = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UserStatusesTests()
|
||||
{
|
||||
AddStep("online", () => { peppy.Status.Value = new UserStatusOnline(); });
|
||||
AddStep(@"do not disturb", () => { peppy.Status.Value = new UserStatusDoNotDisturb(); });
|
||||
AddStep(@"offline", () => { peppy.Status.Value = new UserStatusOffline(); });
|
||||
AddStep(@"null status", () => { peppy.Status.Value = null; });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UserActivitiesTests()
|
||||
{
|
||||
Bindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||
|
||||
peppy.Activity.BindTo(activity);
|
||||
});
|
||||
|
||||
AddStep("idle", () => { activity.Value = null; });
|
||||
AddStep("spectating", () => { activity.Value = new UserActivity.Spectating(); });
|
||||
AddStep("solo", () => { activity.Value = new UserActivity.SoloGame(null, null); });
|
||||
AddStep("choosing", () => { activity.Value = new UserActivity.ChoosingBeatmap(); });
|
||||
AddStep("editing", () => { activity.Value = new UserActivity.Editing(null); });
|
||||
AddStep("modding", () => { activity.Value = new UserActivity.Modding(); });
|
||||
[Test]
|
||||
public void TestUserStatus()
|
||||
{
|
||||
AddStep("online", () => peppy.Status.Value = new UserStatusOnline());
|
||||
AddStep("do not disturb", () => peppy.Status.Value = new UserStatusDoNotDisturb());
|
||||
AddStep("offline", () => peppy.Status.Value = new UserStatusOffline());
|
||||
AddStep("null status", () => peppy.Status.Value = null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserActivity()
|
||||
{
|
||||
AddStep("set online status", () => peppy.Status.Value = new UserStatusOnline());
|
||||
|
||||
AddStep("idle", () => activity.Value = null);
|
||||
AddStep("spectating", () => activity.Value = new UserActivity.Spectating());
|
||||
AddStep("solo (osu!)", () => activity.Value = soloGameStatusForRuleset(0));
|
||||
AddStep("solo (osu!taiko)", () => activity.Value = soloGameStatusForRuleset(1));
|
||||
AddStep("solo (osu!catch)", () => activity.Value = soloGameStatusForRuleset(2));
|
||||
AddStep("solo (osu!mania)", () => activity.Value = soloGameStatusForRuleset(3));
|
||||
AddStep("choosing", () => activity.Value = new UserActivity.ChoosingBeatmap());
|
||||
AddStep("editing", () => activity.Value = new UserActivity.Editing(null));
|
||||
AddStep("modding", () => activity.Value = new UserActivity.Modding());
|
||||
}
|
||||
|
||||
private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.SoloGame(null, rulesetStore.GetRuleset(rulesetId));
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Overlays.Comments;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
@ -18,6 +20,9 @@ namespace osu.Game.Tests.Visual.Online
|
||||
typeof(VotePill)
|
||||
};
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||
|
||||
private VotePill votePill;
|
||||
|
||||
[Test]
|
||||
|
@ -13,6 +13,7 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
@ -194,7 +195,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
public new BufferedWedgeInfo Info => base.Info;
|
||||
}
|
||||
|
||||
private class TestHitObject : HitObject, IHasPosition
|
||||
private class TestHitObject : ConvertHitObject, IHasPosition
|
||||
{
|
||||
public float X { get; } = 0;
|
||||
public float Y { get; } = 0;
|
||||
|
@ -0,0 +1,57 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Home.Friends;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneUserListToolbar : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(UserSortTabControl),
|
||||
typeof(OverlaySortTabControl<>),
|
||||
typeof(OverlayPanelDisplayStyleControl),
|
||||
typeof(UserListToolbar),
|
||||
};
|
||||
|
||||
[Cached]
|
||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);
|
||||
|
||||
public TestSceneUserListToolbar()
|
||||
{
|
||||
UserListToolbar toolbar;
|
||||
OsuSpriteText sort;
|
||||
OsuSpriteText displayStyle;
|
||||
|
||||
Add(toolbar = new UserListToolbar
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
|
||||
Add(new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
sort = new OsuSpriteText(),
|
||||
displayStyle = new OsuSpriteText()
|
||||
}
|
||||
});
|
||||
|
||||
toolbar.SortCriteria.BindValueChanged(criteria => sort.Text = $"Criteria: {criteria.NewValue}", true);
|
||||
toolbar.DisplayStyle.BindValueChanged(style => displayStyle.Text = $"Style: {style.NewValue}", true);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Editors;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneSeedingEditorScreen : LadderTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly LadderInfo ladder = new LadderInfo();
|
||||
|
||||
public TestSceneSeedingEditorScreen()
|
||||
{
|
||||
var match = TestSceneSeedingScreen.CreateSampleSeededMatch();
|
||||
|
||||
Add(new SeedingEditorScreen(match.Team1.Value)
|
||||
{
|
||||
Width = 0.85f // create room for control panel
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
127
osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs
Normal file
127
osu.Game.Tournament.Tests/Screens/TestSceneSeedingScreen.cs
Normal file
@ -0,0 +1,127 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.TeamIntro;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tournament.Tests.Screens
|
||||
{
|
||||
public class TestSceneSeedingScreen : LadderTestScene
|
||||
{
|
||||
[Cached]
|
||||
private readonly LadderInfo ladder = new LadderInfo();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
ladder.CurrentMatch.Value = CreateSampleSeededMatch();
|
||||
|
||||
Add(new SeedingScreen
|
||||
{
|
||||
FillMode = FillMode.Fit,
|
||||
FillAspectRatio = 16 / 9f
|
||||
});
|
||||
}
|
||||
|
||||
public static TournamentMatch CreateSampleSeededMatch() => new TournamentMatch
|
||||
{
|
||||
Team1 =
|
||||
{
|
||||
Value = new TournamentTeam
|
||||
{
|
||||
FlagName = { Value = "JP" },
|
||||
FullName = { Value = "Japan" },
|
||||
LastYearPlacing = { Value = 10 },
|
||||
Seed = { Value = "Low" },
|
||||
SeedingResults =
|
||||
{
|
||||
new SeedingResult
|
||||
{
|
||||
Mod = { Value = "NM" },
|
||||
Seed = { Value = 10 },
|
||||
Beatmaps =
|
||||
{
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 12345672,
|
||||
Seed = { Value = 24 },
|
||||
},
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 1234567,
|
||||
Seed = { Value = 12 },
|
||||
},
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 1234567,
|
||||
Seed = { Value = 16 },
|
||||
}
|
||||
}
|
||||
},
|
||||
new SeedingResult
|
||||
{
|
||||
Mod = { Value = "DT" },
|
||||
Seed = { Value = 5 },
|
||||
Beatmaps =
|
||||
{
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 234567,
|
||||
Seed = { Value = 3 },
|
||||
},
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 234567,
|
||||
Seed = { Value = 6 },
|
||||
},
|
||||
new SeedingBeatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist" } },
|
||||
Score = 234567,
|
||||
Seed = { Value = 12 },
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Players =
|
||||
{
|
||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 12 } } },
|
||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 16 } } },
|
||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 20 } } },
|
||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24 } } },
|
||||
new User { Username = "Hello", Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 30 } } },
|
||||
}
|
||||
}
|
||||
},
|
||||
Team2 =
|
||||
{
|
||||
Value = new TournamentTeam
|
||||
{
|
||||
FlagName = { Value = "US" },
|
||||
FullName = { Value = "United States" },
|
||||
Players =
|
||||
{
|
||||
new User { Username = "Hello" },
|
||||
new User { Username = "Hello" },
|
||||
new User { Username = "Hello" },
|
||||
new User { Username = "Hello" },
|
||||
new User { Username = "Hello" },
|
||||
}
|
||||
}
|
||||
},
|
||||
Round =
|
||||
{
|
||||
Value = new TournamentRound { Name = { Value = "Quarterfinals" } }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ namespace osu.Game.Tournament.Tests.Screens
|
||||
match.Team1.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "USA");
|
||||
match.Team2.Value = Ladder.Teams.FirstOrDefault(t => t.Acronym.Value == "JPN");
|
||||
match.Round.Value = Ladder.Rounds.FirstOrDefault(g => g.Name.Value == "Finals");
|
||||
match.Completed.Value = true;
|
||||
ladder.CurrentMatch.Value = match;
|
||||
|
||||
Add(new TeamWinScreen
|
||||
|
@ -5,7 +5,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -35,7 +34,7 @@ namespace osu.Game.Tournament.Components
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = new Color4(54, 54, 54, 255)
|
||||
},
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Components
|
||||
@ -19,7 +18,7 @@ namespace osu.Game.Tournament.Components
|
||||
public readonly TournamentTeam Team;
|
||||
|
||||
protected readonly Sprite Flag;
|
||||
protected readonly OsuSpriteText AcronymText;
|
||||
protected readonly TournamentSpriteText AcronymText;
|
||||
|
||||
[UsedImplicitly]
|
||||
private Bindable<string> acronym;
|
||||
@ -37,9 +36,9 @@ namespace osu.Game.Tournament.Components
|
||||
FillMode = FillMode.Fit
|
||||
};
|
||||
|
||||
AcronymText = new OsuSpriteText
|
||||
AcronymText = new TournamentSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Regular),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Regular),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osuTK;
|
||||
@ -262,7 +261,7 @@ namespace osu.Game.Tournament.Components
|
||||
static void cp(SpriteText s, Color4 colour)
|
||||
{
|
||||
s.Colour = colour;
|
||||
s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15);
|
||||
s.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 15);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tuples.Length; i++)
|
||||
@ -278,9 +277,9 @@ namespace osu.Game.Tournament.Components
|
||||
});
|
||||
}
|
||||
|
||||
AddText(new OsuSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f)));
|
||||
AddText(new TournamentSpriteText { Text = heading }, s => cp(s, OsuColour.Gray(0.33f)));
|
||||
AddText(" ", s => cp(s, OsuColour.Gray(0.33f)));
|
||||
AddText(new OsuSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f)));
|
||||
AddText(new TournamentSpriteText { Text = content }, s => cp(s, OsuColour.Gray(0.5f)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -77,14 +76,14 @@ namespace osu.Game.Tournament.Components
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = new LocalisedString((
|
||||
$"{Beatmap.Metadata.ArtistUnicode ?? Beatmap.Metadata.Artist} - {Beatmap.Metadata.TitleUnicode ?? Beatmap.Metadata.Title}",
|
||||
$"{Beatmap.Metadata.Artist} - {Beatmap.Metadata.Title}")),
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, italics: true),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Bold),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
@ -95,28 +94,28 @@ namespace osu.Game.Tournament.Components
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = "mapper",
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = Beatmap.Metadata.AuthorString,
|
||||
Padding = new MarginPadding { Right = 20 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = "difficulty",
|
||||
Padding = new MarginPadding { Right = 5 },
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Regular, size: 14)
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 14)
|
||||
},
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = Beatmap.Version,
|
||||
Font = OsuFont.GetFont(italics: true, weight: FontWeight.Bold, size: 14)
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 14)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
// 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.IO;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Video;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
@ -14,13 +15,34 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public class TourneyVideo : CompositeDrawable
|
||||
{
|
||||
private readonly VideoSprite video;
|
||||
private readonly string filename;
|
||||
private readonly bool drawFallbackGradient;
|
||||
private VideoSprite video;
|
||||
|
||||
private readonly ManualClock manualClock;
|
||||
private ManualClock manualClock;
|
||||
|
||||
public TourneyVideo(Stream stream)
|
||||
public TourneyVideo(string filename, bool drawFallbackGradient = false)
|
||||
{
|
||||
if (stream == null)
|
||||
this.filename = filename;
|
||||
this.drawFallbackGradient = drawFallbackGradient;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(Storage storage)
|
||||
{
|
||||
var stream = storage.GetStream($@"videos/{filename}.m4v");
|
||||
|
||||
if (stream != null)
|
||||
{
|
||||
InternalChild = video = new VideoSprite(stream)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Clock = new FramedClock(manualClock = new ManualClock()),
|
||||
Loop = loop,
|
||||
};
|
||||
}
|
||||
else if (drawFallbackGradient)
|
||||
{
|
||||
InternalChild = new Box
|
||||
{
|
||||
@ -28,21 +50,15 @@ namespace osu.Game.Tournament.Components
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalChild = video = new VideoSprite(stream)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
Clock = new FramedClock(manualClock = new ManualClock())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private bool loop;
|
||||
|
||||
public bool Loop
|
||||
{
|
||||
set
|
||||
{
|
||||
loop = value;
|
||||
if (video != null)
|
||||
video.Loop = value;
|
||||
}
|
||||
|
23
osu.Game.Tournament/Models/SeedingBeatmap.cs
Normal file
23
osu.Game.Tournament/Models/SeedingBeatmap.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.Framework.Bindables;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
public class SeedingBeatmap
|
||||
{
|
||||
public int ID;
|
||||
|
||||
public BeatmapInfo BeatmapInfo;
|
||||
|
||||
public long Score;
|
||||
|
||||
public Bindable<int> Seed = new BindableInt
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 64
|
||||
};
|
||||
}
|
||||
}
|
21
osu.Game.Tournament/Models/SeedingResult.cs
Normal file
21
osu.Game.Tournament/Models/SeedingResult.cs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Tournament.Models
|
||||
{
|
||||
public class SeedingResult
|
||||
{
|
||||
public List<SeedingBeatmap> Beatmaps = new List<SeedingBeatmap>();
|
||||
|
||||
public Bindable<string> Mod = new Bindable<string>();
|
||||
|
||||
public Bindable<int> Seed = new BindableInt
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 64
|
||||
};
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Users;
|
||||
@ -29,6 +30,32 @@ namespace osu.Game.Tournament.Models
|
||||
/// </summary>
|
||||
public Bindable<string> Acronym = new Bindable<string>(string.Empty);
|
||||
|
||||
public BindableList<SeedingResult> SeedingResults = new BindableList<SeedingResult>();
|
||||
|
||||
public double AverageRank
|
||||
{
|
||||
get
|
||||
{
|
||||
var ranks = Players.Select(p => p.Statistics?.Ranks.Global)
|
||||
.Where(i => i.HasValue)
|
||||
.Select(i => i.Value)
|
||||
.ToArray();
|
||||
|
||||
if (ranks.Length == 0)
|
||||
return 0;
|
||||
|
||||
return ranks.Average();
|
||||
}
|
||||
}
|
||||
|
||||
public Bindable<string> Seed = new Bindable<string>(string.Empty);
|
||||
|
||||
public Bindable<int> LastYearPlacing = new BindableInt
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 64
|
||||
};
|
||||
|
||||
[JsonProperty]
|
||||
public BindableList<User> Players { get; set; } = new BindableList<User>();
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
@ -43,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
Colour = new Color4(54, 54, 54, 255)
|
||||
},
|
||||
// Group name
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
@ -51,7 +50,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
Position = new Vector2(0, 7f),
|
||||
|
||||
Text = $"GROUP {name.ToUpperInvariant()}",
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 8),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 8),
|
||||
Colour = new Color4(255, 204, 34, 255),
|
||||
},
|
||||
teams = new FillFlowContainer<GroupTeam>
|
||||
@ -134,7 +133,7 @@ namespace osu.Game.Tournament.Screens.Drawings.Components
|
||||
AcronymText.Anchor = Anchor.TopCentre;
|
||||
AcronymText.Origin = Anchor.TopCentre;
|
||||
AcronymText.Text = team.Acronym.Value.ToUpperInvariant();
|
||||
AcronymText.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 10);
|
||||
AcronymText.Font = OsuFont.Torus.With(weight: FontWeight.Bold, size: 10);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
|
@ -14,7 +14,6 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Drawings.Components;
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Tournament.Screens.Drawings
|
||||
|
||||
private ScrollingTeamContainer teamsContainer;
|
||||
private GroupContainer groupsContainer;
|
||||
private OsuSpriteText fullTeamNameText;
|
||||
private TournamentSpriteText fullTeamNameText;
|
||||
|
||||
private readonly List<TournamentTeam> allTeams = new List<TournamentTeam>();
|
||||
|
||||
@ -109,18 +108,18 @@ namespace osu.Game.Tournament.Screens.Drawings
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
// Scrolling team name
|
||||
fullTeamNameText = new OsuSpriteText
|
||||
fullTeamNameText = new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.TopCentre,
|
||||
|
||||
Position = new Vector2(0, 45f),
|
||||
|
||||
Colour = OsuColour.Gray(0.33f),
|
||||
Colour = OsuColour.Gray(0.95f),
|
||||
|
||||
Alpha = 0,
|
||||
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Light, size: 42),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Light, size: 42),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -129,8 +129,6 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
ChildrenEnumerable = round.Beatmaps.Select(p => new RoundBeatmapRow(round, p))
|
||||
};
|
||||
}
|
||||
|
286
osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs
Normal file
286
osu.Game.Tournament/Screens/Editors/SeedingEditorScreen.cs
Normal file
@ -0,0 +1,286 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Editors
|
||||
{
|
||||
public class SeedingEditorScreen : TournamentEditorScreen<SeedingEditorScreen.SeeingResultRow, SeedingResult>
|
||||
{
|
||||
private readonly TournamentTeam team;
|
||||
|
||||
protected override BindableList<SeedingResult> Storage => team.SeedingResults;
|
||||
|
||||
public SeedingEditorScreen(TournamentTeam team)
|
||||
{
|
||||
this.team = team;
|
||||
}
|
||||
|
||||
public class SeeingResultRow : CompositeDrawable, IModelBacked<SeedingResult>
|
||||
{
|
||||
public SeedingResult Model { get; }
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
public SeeingResultRow(TournamentTeam team, SeedingResult round)
|
||||
{
|
||||
Model = round;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 10;
|
||||
|
||||
SeedingBeatmapEditor beatmapEditor = new SeedingBeatmapEditor(round)
|
||||
{
|
||||
Width = 0.95f
|
||||
};
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.1f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Padding = new MarginPadding { Right = 160 },
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Full,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Mod",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.Mod
|
||||
},
|
||||
new SettingsSlider<int>
|
||||
{
|
||||
LabelText = "Seed",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.Seed
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Width = 0.2f,
|
||||
Margin = new MarginPadding(10),
|
||||
Text = "Add beatmap",
|
||||
Action = () => beatmapEditor.CreateNew()
|
||||
},
|
||||
beatmapEditor
|
||||
}
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 150,
|
||||
Text = "Delete result",
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
team.SeedingResults.Remove(Model);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
public class SeedingBeatmapEditor : CompositeDrawable
|
||||
{
|
||||
private readonly SeedingResult round;
|
||||
private readonly FillFlowContainer flow;
|
||||
|
||||
public SeedingBeatmapEditor(SeedingResult round)
|
||||
{
|
||||
this.round = round;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChild = flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
ChildrenEnumerable = round.Beatmaps.Select(p => new SeedingBeatmapRow(round, p))
|
||||
};
|
||||
}
|
||||
|
||||
public void CreateNew()
|
||||
{
|
||||
var user = new SeedingBeatmap();
|
||||
round.Beatmaps.Add(user);
|
||||
flow.Add(new SeedingBeatmapRow(round, user));
|
||||
}
|
||||
|
||||
public class SeedingBeatmapRow : CompositeDrawable
|
||||
{
|
||||
private readonly SeedingResult result;
|
||||
public SeedingBeatmap Model { get; }
|
||||
|
||||
[Resolved]
|
||||
protected IAPIProvider API { get; private set; }
|
||||
|
||||
private readonly Bindable<string> beatmapId = new Bindable<string>();
|
||||
|
||||
private readonly Bindable<string> score = new Bindable<string>();
|
||||
|
||||
private readonly Container drawableContainer;
|
||||
|
||||
public SeedingBeatmapRow(SeedingResult result, SeedingBeatmap beatmap)
|
||||
{
|
||||
this.result = result;
|
||||
Model = beatmap;
|
||||
|
||||
Margin = new MarginPadding(10);
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.2f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Margin = new MarginPadding(5),
|
||||
Padding = new MarginPadding { Right = 160 },
|
||||
Spacing = new Vector2(5),
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsNumberBox
|
||||
{
|
||||
LabelText = "Beatmap ID",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = beatmapId,
|
||||
},
|
||||
new SettingsSlider<int>
|
||||
{
|
||||
LabelText = "Seed",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = beatmap.Seed
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Score",
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 200,
|
||||
Bindable = score,
|
||||
},
|
||||
drawableContainer = new Container
|
||||
{
|
||||
Size = new Vector2(100, 70),
|
||||
},
|
||||
}
|
||||
},
|
||||
new DangerousSettingsButton
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 150,
|
||||
Text = "Delete Beatmap",
|
||||
Action = () =>
|
||||
{
|
||||
Expire();
|
||||
result.Beatmaps.Remove(beatmap);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
beatmapId.Value = Model.ID.ToString();
|
||||
beatmapId.BindValueChanged(idString =>
|
||||
{
|
||||
int parsed;
|
||||
|
||||
int.TryParse(idString.NewValue, out parsed);
|
||||
|
||||
Model.ID = parsed;
|
||||
|
||||
if (idString.NewValue != idString.OldValue)
|
||||
Model.BeatmapInfo = null;
|
||||
|
||||
if (Model.BeatmapInfo != null)
|
||||
{
|
||||
updatePanel();
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID });
|
||||
|
||||
req.Success += res =>
|
||||
{
|
||||
Model.BeatmapInfo = res.ToBeatmap(rulesets);
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
req.Failure += _ =>
|
||||
{
|
||||
Model.BeatmapInfo = null;
|
||||
updatePanel();
|
||||
};
|
||||
|
||||
API.Queue(req);
|
||||
}, true);
|
||||
|
||||
score.Value = Model.Score.ToString();
|
||||
score.BindValueChanged(str => long.TryParse(str.NewValue, out Model.Score));
|
||||
}
|
||||
|
||||
private void updatePanel()
|
||||
{
|
||||
drawableContainer.Clear();
|
||||
|
||||
if (Model.BeatmapInfo != null)
|
||||
{
|
||||
drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, result.Mod.Value)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Width = 300
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override SeeingResultRow CreateDrawable(SeedingResult model) => new SeeingResultRow(team, model);
|
||||
}
|
||||
}
|
@ -57,6 +57,9 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
|
||||
private readonly Container drawableContainer;
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private TournamentSceneManager sceneManager { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private LadderInfo ladderInfo { get; set; }
|
||||
|
||||
@ -113,6 +116,18 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
Width = 0.2f,
|
||||
Bindable = Model.FlagName
|
||||
},
|
||||
new SettingsTextBox
|
||||
{
|
||||
LabelText = "Seed",
|
||||
Width = 0.2f,
|
||||
Bindable = Model.Seed
|
||||
},
|
||||
new SettingsSlider<int>
|
||||
{
|
||||
LabelText = "Last Year Placement",
|
||||
Width = 0.33f,
|
||||
Bindable = Model.LastYearPlacing
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Width = 0.11f,
|
||||
@ -131,7 +146,17 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
ladderInfo.Teams.Remove(Model);
|
||||
},
|
||||
},
|
||||
playerEditor
|
||||
playerEditor,
|
||||
new SettingsButton
|
||||
{
|
||||
Width = 0.2f,
|
||||
Margin = new MarginPadding(10),
|
||||
Text = "Edit seeding results",
|
||||
Action = () =>
|
||||
{
|
||||
sceneManager?.SetScreen(new SeedingEditorScreen(team));
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -177,8 +202,6 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
ChildrenEnumerable = team.Players.Select(p => new PlayerRow(team, p))
|
||||
};
|
||||
}
|
||||
|
@ -48,8 +48,6 @@ namespace osu.Game.Tournament.Screens.Editors
|
||||
Direction = FillDirection.Vertical,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
Spacing = new Vector2(20)
|
||||
},
|
||||
},
|
||||
|
@ -5,9 +5,9 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
@ -30,7 +30,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
new TournamentLogo(),
|
||||
new RoundDisplay
|
||||
{
|
||||
Y = 10,
|
||||
Y = 5,
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
},
|
||||
@ -51,9 +51,6 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
{
|
||||
private readonly TeamColour teamColour;
|
||||
|
||||
private readonly Color4 red = new Color4(129, 68, 65, 255);
|
||||
private readonly Color4 blue = new Color4(41, 91, 97, 255);
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private readonly Bindable<TournamentTeam> currentTeam = new Bindable<TournamentTeam>();
|
||||
private readonly Bindable<int?> currentTeamScore = new Bindable<int?>();
|
||||
@ -106,7 +103,7 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
|
||||
private void teamChanged(TournamentTeam team)
|
||||
{
|
||||
var colour = teamColour == TeamColour.Red ? red : blue;
|
||||
var colour = teamColour == TeamColour.Red ? TournamentGame.COLOUR_RED : TournamentGame.COLOUR_BLUE;
|
||||
var flip = teamColour != TeamColour.Red;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
@ -169,13 +166,13 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Flag,
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = team?.FullName.Value.ToUpper() ?? "???",
|
||||
X = (flip ? -1 : 1) * 90,
|
||||
Y = -10,
|
||||
Colour = colour,
|
||||
Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 20),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 20),
|
||||
Origin = anchor,
|
||||
Anchor = anchor,
|
||||
},
|
||||
@ -188,10 +185,31 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
{
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
private readonly TournamentSpriteText text;
|
||||
|
||||
public RoundDisplay()
|
||||
{
|
||||
Width = 200;
|
||||
Height = 20;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 10;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = OsuColour.Gray(0.18f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
text = new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Colour = Color4.White,
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: 16),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -201,20 +219,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
currentMatch.BindTo(ladder.CurrentMatch);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Colour = Color4.White,
|
||||
Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round",
|
||||
Font = TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 18),
|
||||
},
|
||||
};
|
||||
}
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match) =>
|
||||
text.Text = match.NewValue.Round.Value?.Name.Value ?? "Unknown Round";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +123,8 @@ namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
public bool Winning
|
||||
{
|
||||
set => DisplayedCountSpriteText.Font = value
|
||||
? TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Regular, size: 60)
|
||||
: TournamentFont.GetFont(typeface: TournamentTypeface.Aquatico, weight: FontWeight.Light, size: 40);
|
||||
? OsuFont.Torus.With(weight: FontWeight.Regular, size: 60)
|
||||
: OsuFont.Torus.With(weight: FontWeight.Light, size: 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
@ -19,7 +20,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Gameplay
|
||||
{
|
||||
public class GameplayScreen : BeatmapInfoScreen
|
||||
public class GameplayScreen : BeatmapInfoScreen, IProvideVideo
|
||||
{
|
||||
private readonly BindableBool warmup = new BindableBool();
|
||||
|
||||
@ -39,12 +40,17 @@ namespace osu.Game.Tournament.Screens.Gameplay
|
||||
private TournamentMatchChatDisplay chat { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LadderInfo ladder, MatchIPCInfo ipc)
|
||||
private void load(LadderInfo ladder, MatchIPCInfo ipc, Storage storage)
|
||||
{
|
||||
this.ipc = ipc;
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new TourneyVideo("gameplay")
|
||||
{
|
||||
Loop = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new MatchHeader(),
|
||||
new Container
|
||||
{
|
||||
|
@ -11,7 +11,6 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
@ -26,7 +25,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
private readonly TournamentMatch match;
|
||||
private readonly bool losers;
|
||||
private OsuSpriteText scoreText;
|
||||
private TournamentSpriteText scoreText;
|
||||
private Box background;
|
||||
|
||||
private readonly Bindable<int?> score = new Bindable<int?>();
|
||||
@ -69,7 +68,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
|
||||
AcronymText.Anchor = AcronymText.Origin = Anchor.CentreLeft;
|
||||
AcronymText.Padding = new MarginPadding { Left = 50 };
|
||||
AcronymText.Font = OsuFont.GetFont(size: 24);
|
||||
AcronymText.Font = OsuFont.Torus.With(size: 24);
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
@ -119,11 +118,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
Alpha = 0.8f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
scoreText = new OsuSpriteText
|
||||
scoreText = new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.GetFont(size: 20),
|
||||
Font = OsuFont.Torus.With(size: 20),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -184,7 +183,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
|
||||
background.FadeColour(winner ? colourWinner : colourNormal, winner ? 500 : 0, Easing.OutQuint);
|
||||
|
||||
scoreText.Font = AcronymText.Font = OsuFont.GetFont(weight: winner ? FontWeight.Bold : FontWeight.Regular);
|
||||
scoreText.Font = AcronymText.Font = OsuFont.Torus.With(weight: winner ? FontWeight.Bold : FontWeight.Regular);
|
||||
}
|
||||
|
||||
public MenuItem[] ContextMenuItems
|
||||
|
@ -6,7 +6,6 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -22,8 +21,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
|
||||
public DrawableTournamentRound(TournamentRound round, bool losers = false)
|
||||
{
|
||||
OsuSpriteText textName;
|
||||
OsuSpriteText textDescription;
|
||||
TournamentSpriteText textName;
|
||||
TournamentSpriteText textDescription;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
InternalChild = new FillFlowContainer
|
||||
@ -32,15 +31,15 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
textDescription = new OsuSpriteText
|
||||
textDescription = new TournamentSpriteText
|
||||
{
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
},
|
||||
textName = new OsuSpriteText
|
||||
textName = new TournamentSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold),
|
||||
Font = OsuFont.Torus.With(weight: FontWeight.Bold),
|
||||
Colour = Color4.Black,
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
using osu.Game.Tournament.Components;
|
||||
@ -126,66 +125,5 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsTeamDropdown : LadderSettingsDropdown<TournamentTeam>
|
||||
{
|
||||
public SettingsTeamDropdown(BindableList<TournamentTeam> teams)
|
||||
{
|
||||
foreach (var t in teams.Prepend(new TournamentTeam()))
|
||||
add(t);
|
||||
|
||||
teams.CollectionChanged += (_, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
args.NewItems.Cast<TournamentTeam>().ForEach(add);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
args.OldItems.Cast<TournamentTeam>().ForEach(i => Control.RemoveDropdownItem(i));
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private readonly List<IUnbindable> refBindables = new List<IUnbindable>();
|
||||
|
||||
private T boundReference<T>(T obj)
|
||||
where T : IBindable
|
||||
{
|
||||
obj = (T)obj.GetBoundCopy();
|
||||
refBindables.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void add(TournamentTeam team)
|
||||
{
|
||||
Control.AddDropdownItem(team);
|
||||
boundReference(team.FullName).BindValueChanged(_ =>
|
||||
{
|
||||
Control.RemoveDropdownItem(team);
|
||||
Control.AddDropdownItem(team);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class LadderSettingsDropdown<T> : SettingsDropdown<T>
|
||||
{
|
||||
protected override OsuDropdown<T> CreateDropdown() => new DropdownControl();
|
||||
|
||||
private new class DropdownControl : SettingsDropdown<T>.DropdownControl
|
||||
{
|
||||
protected override DropdownMenu CreateMenu() => new Menu();
|
||||
|
||||
private new class Menu : OsuDropdownMenu
|
||||
{
|
||||
public Menu()
|
||||
{
|
||||
MaxHeight = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
// 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.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Settings;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class LadderSettingsDropdown<T> : SettingsDropdown<T>
|
||||
{
|
||||
protected override OsuDropdown<T> CreateDropdown() => new DropdownControl();
|
||||
|
||||
private new class DropdownControl : SettingsDropdown<T>.DropdownControl
|
||||
{
|
||||
protected override DropdownMenu CreateMenu() => new Menu();
|
||||
|
||||
private new class Menu : OsuDropdownMenu
|
||||
{
|
||||
public Menu()
|
||||
{
|
||||
MaxHeight = 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Tournament.Models;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Ladder.Components
|
||||
{
|
||||
public class SettingsTeamDropdown : LadderSettingsDropdown<TournamentTeam>
|
||||
{
|
||||
public SettingsTeamDropdown(BindableList<TournamentTeam> teams)
|
||||
{
|
||||
foreach (var t in teams.Prepend(new TournamentTeam()))
|
||||
add(t);
|
||||
|
||||
teams.CollectionChanged += (_, args) =>
|
||||
{
|
||||
switch (args.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
args.NewItems.Cast<TournamentTeam>().ForEach(add);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
args.OldItems.Cast<TournamentTeam>().ForEach(i => Control.RemoveDropdownItem(i));
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private readonly List<IUnbindable> refBindables = new List<IUnbindable>();
|
||||
|
||||
private T boundReference<T>(T obj)
|
||||
where T : IBindable
|
||||
{
|
||||
obj = (T)obj.GetBoundCopy();
|
||||
refBindables.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
private void add(TournamentTeam team)
|
||||
{
|
||||
Control.AddDropdownItem(team);
|
||||
boundReference(team.FullName).BindValueChanged(_ =>
|
||||
{
|
||||
Control.RemoveDropdownItem(team);
|
||||
Control.AddDropdownItem(team);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -42,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Ladder
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
|
||||
new TourneyVideo("ladder")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
@ -80,7 +80,7 @@ namespace osu.Game.Tournament.Screens.Ladder
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
foreach (var p in args.NewItems.Cast<TournamentMatch>())
|
||||
foreach (var p in args.OldItems.Cast<TournamentMatch>())
|
||||
{
|
||||
foreach (var d in MatchesContainer.Where(d => d.Match == p))
|
||||
d.Expire();
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.IPC;
|
||||
@ -56,7 +55,7 @@ namespace osu.Game.Tournament.Screens.MapPool
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = "Current Mode"
|
||||
},
|
||||
|
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
@ -19,7 +18,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Schedule
|
||||
{
|
||||
public class ScheduleScreen : TournamentScreen, IProvideVideo
|
||||
public class ScheduleScreen : TournamentScreen
|
||||
{
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
private Container mainContainer;
|
||||
@ -34,7 +33,7 @@ namespace osu.Game.Tournament.Screens.Schedule
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TourneyVideo(storage.GetStream(@"BG Side Logo - OWC.m4v"))
|
||||
new TourneyVideo("schedule")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
@ -107,20 +106,20 @@ namespace osu.Game.Tournament.Screens.Schedule
|
||||
Height = 0.25f,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Left = -10, Bottom = 10, Top = -5 },
|
||||
Spacing = new Vector2(10, 0),
|
||||
Text = match.NewValue.Round.Value?.Name.Value,
|
||||
Colour = Color4.Black,
|
||||
Font = OsuFont.GetFont(size: 20)
|
||||
Font = OsuFont.Torus.With(size: 20)
|
||||
},
|
||||
new ScheduleMatch(match.NewValue, false),
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = "Start Time " + match.NewValue.Date.Value.ToUniversalTime().ToString("HH:mm UTC"),
|
||||
Colour = Color4.Black,
|
||||
Font = OsuFont.GetFont(size: 20)
|
||||
Font = OsuFont.Torus.With(size: 20)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -150,7 +149,7 @@ namespace osu.Game.Tournament.Screens.Schedule
|
||||
Alpha = conditional ? 0.6f : 1,
|
||||
Margin = new MarginPadding { Horizontal = 10, Vertical = 5 },
|
||||
});
|
||||
AddInternal(new OsuSpriteText
|
||||
AddInternal(new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomLeft,
|
||||
@ -174,13 +173,13 @@ namespace osu.Game.Tournament.Screens.Schedule
|
||||
Padding = new MarginPadding { Left = 30, Top = 30 };
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
new TournamentSpriteText
|
||||
{
|
||||
X = 30,
|
||||
Text = title,
|
||||
Colour = Color4.Black,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Font = OsuFont.GetFont(size: 30)
|
||||
Font = OsuFont.Torus.With(size: 30)
|
||||
},
|
||||
content = new FillFlowContainer
|
||||
{
|
||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Online.API;
|
||||
@ -147,7 +146,7 @@ namespace osu.Game.Tournament.Screens
|
||||
|
||||
public Action Action;
|
||||
|
||||
private OsuSpriteText valueText;
|
||||
private TournamentSpriteText valueText;
|
||||
|
||||
protected override Drawable CreateComponent() => new Container
|
||||
{
|
||||
@ -155,7 +154,7 @@ namespace osu.Game.Tournament.Screens
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
valueText = new OsuSpriteText
|
||||
valueText = new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
|
@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Showcase
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(new TournamentLogo(false));
|
||||
AddInternal(new TournamentLogo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,20 +11,12 @@ namespace osu.Game.Tournament.Screens.Showcase
|
||||
{
|
||||
public class TournamentLogo : CompositeDrawable
|
||||
{
|
||||
public TournamentLogo(bool includeRoundBackground = true)
|
||||
public TournamentLogo()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Margin = new MarginPadding { Vertical = 5 };
|
||||
|
||||
if (includeRoundBackground)
|
||||
{
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
Masking = true;
|
||||
Height = 100;
|
||||
}
|
||||
Height = 100;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -32,9 +24,11 @@ namespace osu.Game.Tournament.Screens.Showcase
|
||||
{
|
||||
InternalChild = new Sprite
|
||||
{
|
||||
Texture = textures.Get("game-screen-logo"),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
FillMode = FillMode.Fit,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = textures.Get("game-screen-logo"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
316
osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
Normal file
316
osu.Game.Tournament/Screens/TeamIntro/SeedingScreen.cs
Normal file
@ -0,0 +1,316 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Tournament.Components;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osu.Game.Tournament.Screens.Ladder.Components;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.TeamIntro
|
||||
{
|
||||
public class SeedingScreen : TournamentScreen, IProvideVideo
|
||||
{
|
||||
private Container mainContainer;
|
||||
|
||||
private readonly Bindable<TournamentMatch> currentMatch = new Bindable<TournamentMatch>();
|
||||
|
||||
private readonly Bindable<TournamentTeam> currentTeam = new Bindable<TournamentTeam>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(Storage storage)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TourneyVideo("seeding")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Loop = true,
|
||||
},
|
||||
mainContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new ControlPanel
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TourneyButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Show first team",
|
||||
Action = () => currentTeam.Value = currentMatch.Value.Team1.Value,
|
||||
},
|
||||
new TourneyButton
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Show second team",
|
||||
Action = () => currentTeam.Value = currentMatch.Value.Team2.Value,
|
||||
},
|
||||
new SettingsTeamDropdown(LadderInfo.Teams)
|
||||
{
|
||||
LabelText = "Show specific team",
|
||||
Bindable = currentTeam,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
currentMatch.BindValueChanged(matchChanged);
|
||||
currentMatch.BindTo(LadderInfo.CurrentMatch);
|
||||
|
||||
currentTeam.BindValueChanged(teamChanged, true);
|
||||
}
|
||||
|
||||
private void teamChanged(ValueChangedEvent<TournamentTeam> team)
|
||||
{
|
||||
if (team.NewValue == null)
|
||||
{
|
||||
mainContainer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
showTeam(team.NewValue);
|
||||
}
|
||||
|
||||
private void matchChanged(ValueChangedEvent<TournamentMatch> match) =>
|
||||
currentTeam.Value = currentMatch.Value.Team1.Value;
|
||||
|
||||
private void showTeam(TournamentTeam team)
|
||||
{
|
||||
mainContainer.Children = new Drawable[]
|
||||
{
|
||||
new LeftInfo(team) { Position = new Vector2(55, 150), },
|
||||
new RightInfo(team) { Position = new Vector2(500, 150), },
|
||||
};
|
||||
}
|
||||
|
||||
private class RightInfo : CompositeDrawable
|
||||
{
|
||||
public RightInfo(TournamentTeam team)
|
||||
{
|
||||
FillFlowContainer fill;
|
||||
|
||||
Width = 400;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
fill = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var seeding in team.SeedingResults)
|
||||
{
|
||||
fill.Add(new ModRow(seeding.Mod.Value, seeding.Seed.Value));
|
||||
foreach (var beatmap in seeding.Beatmaps)
|
||||
fill.Add(new BeatmapScoreRow(beatmap));
|
||||
}
|
||||
}
|
||||
|
||||
private class BeatmapScoreRow : CompositeDrawable
|
||||
{
|
||||
public BeatmapScoreRow(SeedingBeatmap beatmap)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Title, Colour = Color4.Black, },
|
||||
new TournamentSpriteText { Text = "by", Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
|
||||
new TournamentSpriteText { Text = beatmap.BeatmapInfo.Metadata.Artist, Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(40),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TournamentSpriteText { Text = beatmap.Score.ToString("#,0"), Colour = Color4.Black, Width = 80 },
|
||||
new TournamentSpriteText { Text = "#" + beatmap.Seed.Value.ToString("#,0"), Colour = Color4.Black, Font = OsuFont.Torus.With(weight: FontWeight.Regular) },
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class ModRow : CompositeDrawable
|
||||
{
|
||||
private readonly string mods;
|
||||
private readonly int seeding;
|
||||
|
||||
public ModRow(string mods, int seeding)
|
||||
{
|
||||
this.mods = mods;
|
||||
this.seeding = seeding;
|
||||
|
||||
Padding = new MarginPadding { Vertical = 10 };
|
||||
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
Texture = textures.Get($"mods/{mods.ToLower()}"),
|
||||
Scale = new Vector2(0.5f)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Size = new Vector2(50, 16),
|
||||
CornerRadius = 10,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = seeding.ToString("#,0"),
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LeftInfo : CompositeDrawable
|
||||
{
|
||||
public LeftInfo(TournamentTeam team)
|
||||
{
|
||||
FillFlowContainer fill;
|
||||
|
||||
Width = 200;
|
||||
|
||||
if (team == null) return;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
fill = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TeamDisplay(team) { Margin = new MarginPadding { Bottom = 30 } },
|
||||
new RowDisplay("Average Rank:", $"#{team.AverageRank:#,0}"),
|
||||
new RowDisplay("Seed:", team.Seed.Value),
|
||||
new RowDisplay("Last year's placing:", team.LastYearPlacing.Value > 0 ? $"#{team.LastYearPlacing:#,0}" : "0"),
|
||||
new Container { Margin = new MarginPadding { Bottom = 30 } },
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
foreach (var p in team.Players)
|
||||
fill.Add(new RowDisplay(p.Username, p.Statistics?.Ranks.Global?.ToString("\\##,0") ?? "-"));
|
||||
}
|
||||
|
||||
internal class RowDisplay : CompositeDrawable
|
||||
{
|
||||
public RowDisplay(string left, string right)
|
||||
{
|
||||
AutoSizeAxes = Axes.Y;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
var colour = OsuColour.Gray(0.3f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = left,
|
||||
Colour = colour,
|
||||
Font = OsuFont.Torus.With(size: 22),
|
||||
},
|
||||
new TournamentSpriteText
|
||||
{
|
||||
Text = right,
|
||||
Colour = colour,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopLeft,
|
||||
Font = OsuFont.Torus.With(size: 22, weight: FontWeight.Regular),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TeamDisplay : DrawableTournamentTeam
|
||||
{
|
||||
public TeamDisplay(TournamentTeam team)
|
||||
: base(team)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Flag.RelativeSizeAxes = Axes.None;
|
||||
Flag.Size = new Vector2(300, 200);
|
||||
Flag.Scale = new Vector2(0.3f);
|
||||
|
||||
InternalChild = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Spacing = new Vector2(0, 5),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Flag,
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = team?.FullName.Value ?? "???",
|
||||
Font = OsuFont.Torus.With(size: 32, weight: FontWeight.SemiBold),
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user