1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-11 15:27:20 +08:00

Merge branch 'master' into fix-muted-dim-factor

This commit is contained in:
Dan Balasescu 2021-08-04 12:00:49 +09:00 committed by GitHub
commit 472925180a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 654 additions and 912 deletions

View File

@ -190,3 +190,5 @@ dotnet_diagnostic.CA2225.severity = none
# Banned APIs # Banned APIs
dotnet_diagnostic.RS0030.severity = error dotnet_diagnostic.RS0030.severity = error
dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text.

View File

@ -51,8 +51,8 @@
<Reference Include="Java.Interop" /> <Reference Include="Java.Interop" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.728.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2021.803.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Transitive Dependencies"> <ItemGroup Label="Transitive Dependencies">
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. --> <!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->

View File

@ -109,15 +109,23 @@ namespace osu.Game.Rulesets.Catch.UI
comboDisplay.X = Catcher.X; comboDisplay.X = Catcher.X;
if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) if (Time.Elapsed <= 0)
catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); {
// This is probably a wrong value, but currently the true value is not recorded.
// Setting `true` will prevent generation of false-positive after-images (with more false-negatives).
lastHyperDashState = true;
return;
}
if (!lastHyperDashState && Catcher.HyperDashing)
displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterImage);
if (Catcher.Dashing || Catcher.HyperDashing) if (Catcher.Dashing || Catcher.HyperDashing)
{ {
double generationInterval = Catcher.HyperDashing ? 25 : 50; double generationInterval = Catcher.HyperDashing ? 25 : 50;
if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval) if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval)
catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); displayCatcherTrail(Catcher.HyperDashing ? CatcherTrailAnimation.HyperDashing : CatcherTrailAnimation.Dashing);
} }
lastHyperDashState = Catcher.HyperDashing; lastHyperDashState = Catcher.HyperDashing;
@ -173,5 +181,7 @@ namespace osu.Game.Rulesets.Catch.UI
break; break;
} }
} }
private void displayCatcherTrail(CatcherTrailAnimation animation) => catcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation));
} }
} }

View File

@ -2,8 +2,8 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Pooling;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Rulesets.Objects.Pooling;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
@ -12,13 +12,8 @@ namespace osu.Game.Rulesets.Catch.UI
/// A trail of the catcher. /// A trail of the catcher.
/// It also represents a hyper dash afterimage. /// It also represents a hyper dash afterimage.
/// </summary> /// </summary>
public class CatcherTrail : PoolableDrawable public class CatcherTrail : PoolableDrawableWithLifetime<CatcherTrailEntry>
{ {
public CatcherAnimationState AnimationState
{
set => body.AnimationState.Value = value;
}
private readonly SkinnableCatcher body; private readonly SkinnableCatcher body;
public CatcherTrail() public CatcherTrail()
@ -34,11 +29,40 @@ namespace osu.Game.Rulesets.Catch.UI
}; };
} }
protected override void FreeAfterUse() protected override void OnApply(CatcherTrailEntry entry)
{ {
Position = new Vector2(entry.Position, 0);
Scale = entry.Scale;
body.AnimationState.Value = entry.CatcherState;
using (BeginAbsoluteSequence(entry.LifetimeStart, false))
applyTransforms(entry.Animation);
}
protected override void OnFree(CatcherTrailEntry entry)
{
ApplyTransformsAt(double.MinValue);
ClearTransforms(); ClearTransforms();
Alpha = 1; }
base.FreeAfterUse();
private void applyTransforms(CatcherTrailAnimation animation)
{
switch (animation)
{
case CatcherTrailAnimation.Dashing:
case CatcherTrailAnimation.HyperDashing:
this.FadeTo(0.4f).FadeOut(800, Easing.OutQuint);
break;
case CatcherTrailAnimation.HyperDashAfterImage:
this.MoveToOffset(new Vector2(0, -10), 1200, Easing.In);
this.ScaleTo(Scale * 0.95f).ScaleTo(Scale * 1.2f, 1200, Easing.In);
this.FadeOut(1200);
break;
}
Expire();
} }
} }
} }

View File

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

View File

@ -2,12 +2,13 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Pooling; using osu.Framework.Graphics.Pooling;
using osu.Game.Rulesets.Catch.Skinning; using osu.Game.Rulesets.Catch.Skinning;
using osu.Game.Rulesets.Objects.Pooling;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.UI
/// Represents a component responsible for displaying /// Represents a component responsible for displaying
/// the appropriate catcher trails when requested to. /// the appropriate catcher trails when requested to.
/// </summary> /// </summary>
public class CatcherTrailDisplay : SkinReloadableDrawable public class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer<CatcherTrailEntry, CatcherTrail>
{ {
/// <summary> /// <summary>
/// The most recent time a dash trail was added to this container. /// The most recent time a dash trail was added to this container.
@ -29,12 +30,17 @@ namespace osu.Game.Rulesets.Catch.UI
public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour; public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour;
protected override bool RemoveRewoundEntry => true;
private readonly DrawablePool<CatcherTrail> trailPool; private readonly DrawablePool<CatcherTrail> trailPool;
private readonly Container<CatcherTrail> dashTrails; private readonly Container<CatcherTrail> dashTrails;
private readonly Container<CatcherTrail> hyperDashTrails; private readonly Container<CatcherTrail> hyperDashTrails;
private readonly Container<CatcherTrail> hyperDashAfterImages; private readonly Container<CatcherTrail> hyperDashAfterImages;
[Resolved]
private ISkinSource skin { get; set; }
public CatcherTrailDisplay() public CatcherTrailDisplay()
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
@ -48,50 +54,60 @@ namespace osu.Game.Rulesets.Catch.UI
}; };
} }
protected override void SkinChanged(ISkinSource skin) protected override void LoadComplete()
{ {
base.SkinChanged(skin); base.LoadComplete();
skin.SourceChanged += skinSourceChanged;
skinSourceChanged();
}
private void skinSourceChanged()
{
hyperDashTrails.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; hyperDashTrails.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR;
hyperDashAfterImages.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; hyperDashAfterImages.Colour = skin.GetConfig<CatchSkinColour, Color4>(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour;
} }
/// <summary> protected override void AddDrawable(CatcherTrailEntry entry, CatcherTrail drawable)
/// Displays a hyper-dash after-image of the catcher.
/// </summary>
public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale)
{ {
var trail = createTrail(animationState, x, scale); switch (entry.Animation)
{
case CatcherTrailAnimation.Dashing:
dashTrails.Add(drawable);
break;
hyperDashAfterImages.Add(trail); case CatcherTrailAnimation.HyperDashing:
hyperDashTrails.Add(drawable);
break;
trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); case CatcherTrailAnimation.HyperDashAfterImage:
trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In); hyperDashAfterImages.Add(drawable);
trail.FadeOut(1200); break;
trail.Expire(true); }
} }
public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) protected override void RemoveDrawable(CatcherTrailEntry entry, CatcherTrail drawable)
{ {
var trail = createTrail(animationState, x, scale); switch (entry.Animation)
{
case CatcherTrailAnimation.Dashing:
dashTrails.Remove(drawable);
break;
if (hyperDashing) case CatcherTrailAnimation.HyperDashing:
hyperDashTrails.Add(trail); hyperDashTrails.Remove(drawable);
else break;
dashTrails.Add(trail);
trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); case CatcherTrailAnimation.HyperDashAfterImage:
trail.Expire(true); hyperDashAfterImages.Remove(drawable);
break;
}
} }
private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale) protected override CatcherTrail GetDrawable(CatcherTrailEntry entry)
{ {
CatcherTrail trail = trailPool.Get(); CatcherTrail trail = trailPool.Get();
trail.Apply(entry);
trail.AnimationState = animationState;
trail.Scale = scale;
trail.Position = new Vector2(x, 0);
return trail; return trail;
} }
@ -107,5 +123,13 @@ namespace osu.Game.Rulesets.Catch.UI
return maxTime; return maxTime;
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (skin != null)
skin.SourceChanged -= skinSourceChanged;
}
} }
} }

View File

@ -0,0 +1,31 @@
// 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.Graphics.Performance;
using osuTK;
namespace osu.Game.Rulesets.Catch.UI
{
public class CatcherTrailEntry : LifetimeEntry
{
public readonly CatcherAnimationState CatcherState;
public readonly float Position;
/// <summary>
/// The scaling of the catcher body. It also represents a flipped catcher (negative x component).
/// </summary>
public readonly Vector2 Scale;
public readonly CatcherTrailAnimation Animation;
public CatcherTrailEntry(double startTime, CatcherAnimationState catcherState, float position, Vector2 scale, CatcherTrailAnimation animation)
{
LifetimeStart = startTime;
CatcherState = catcherState;
Position = position;
Scale = scale;
Animation = animation;
}
}
}

View File

@ -2,10 +2,30 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.UI;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Taiko.Mods namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModClassic : ModClassic public class TaikoModClassic : ModClassic, IApplicableToDrawableRuleset<TaikoHitObject>, IUpdatableByPlayfield
{ {
private DrawableTaikoRuleset drawableTaikoRuleset;
public void ApplyToDrawableRuleset(DrawableRuleset<TaikoHitObject> drawableRuleset)
{
drawableTaikoRuleset = (DrawableTaikoRuleset)drawableRuleset;
}
public void Update(Playfield playfield)
{
// Classic taiko scrolls at a constant 100px per 1000ms. More notes become visible as the playfield is lengthened.
const float scroll_rate = 10;
// Since the time range will depend on a positional value, it is referenced to the x480 pixel space.
float ratio = drawableTaikoRuleset.DrawHeight / 480;
drawableTaikoRuleset.TimeRange.Value = (playfield.HitObjectContainer.DrawWidth / ratio) * scroll_rate;
}
} }
} }

View File

@ -12,23 +12,11 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Mods namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModHidden : ModHidden, IApplicableToDifficulty public class TaikoModHidden : ModHidden
{ {
public override string Description => @"Beats fade out before you hit them!"; public override string Description => @"Beats fade out before you hit them!";
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
/// <summary>
/// In osu-stable, the hit position is 160, so the active playfield is essentially 160 pixels shorter
/// than the actual screen width. The normalized playfield height is 480, so on a 4:3 screen the
/// playfield ratio of the active area up to the hit position will actually be (640 - 160) / 480 = 1.
/// For custom resolutions/aspect ratios (x:y), the screen width given the normalized height becomes 480 * x / y instead,
/// and the playfield ratio becomes (480 * x / y - 160) / 480 = x / y - 1/3.
/// This constant is equal to the playfield ratio on 4:3 screens divided by the playfield ratio on 16:9 screens.
/// </summary>
private const double hd_sv_scale = (4.0 / 3.0 - 1.0 / 3.0) / (16.0 / 9.0 - 1.0 / 3.0);
private double originalSliderMultiplier;
private ControlPointInfo controlPointInfo; private ControlPointInfo controlPointInfo;
protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state) protected override void ApplyIncreasedVisibilityState(DrawableHitObject hitObject, ArmedState state)
@ -41,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
double beatLength = controlPointInfo.TimingPointAt(position).BeatLength; double beatLength = controlPointInfo.TimingPointAt(position).BeatLength;
double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier; double speedMultiplier = controlPointInfo.DifficultyPointAt(position).SpeedMultiplier;
return originalSliderMultiplier * speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength; return speedMultiplier * TimingControlPoint.DEFAULT_BEAT_LENGTH / beatLength;
} }
protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state) protected override void ApplyNormalVisibilityState(DrawableHitObject hitObject, ArmedState state)
@ -69,22 +57,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
} }
} }
public void ReadFromDifficulty(BeatmapDifficulty difficulty)
{
}
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
{
// needs to be read after all processing has been run (TaikoBeatmapConverter applies an adjustment which would otherwise be omitted).
originalSliderMultiplier = difficulty.SliderMultiplier;
// osu-stable has an added playfield cover that essentially forces a 4:3 playfield ratio, by cutting off all objects past that size.
// This is not yet implemented; instead a playfield adjustment container is present which maintains a 16:9 ratio.
// For now, increase the slider multiplier proportionally so that the notes stay on the screen for the same amount of time as on stable.
// Note that this means that the notes will scroll faster as they have a longer distance to travel on the screen in that same amount of time.
difficulty.SliderMultiplier /= hd_sv_scale;
}
public override void ApplyToBeatmap(IBeatmap beatmap) public override void ApplyToBeatmap(IBeatmap beatmap)
{ {
controlPointInfo = beatmap.ControlPointInfo; controlPointInfo = beatmap.ControlPointInfo;

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -24,12 +25,14 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
public class DrawableTaikoRuleset : DrawableScrollingRuleset<TaikoHitObject> public class DrawableTaikoRuleset : DrawableScrollingRuleset<TaikoHitObject>
{ {
private SkinnableDrawable scroller; public new BindableDouble TimeRange => base.TimeRange;
protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping; protected override ScrollVisualisationMethod VisualisationMethod => ScrollVisualisationMethod.Overlapping;
protected override bool UserScrollSpeedAdjustment => false; protected override bool UserScrollSpeedAdjustment => false;
private SkinnableDrawable scroller;
public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null) public DrawableTaikoRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
: base(ruleset, beatmap, mods) : base(ruleset, beatmap, mods)
{ {

View File

@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.UI
/// <summary> /// <summary>
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="DrawableTaikoRuleset"/>. /// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="DrawableTaikoRuleset"/>.
/// </summary> /// </summary>
public const float DEFAULT_HEIGHT = 178; public const float DEFAULT_HEIGHT = 212;
private Container<HitExplosion> hitExplosionContainer; private Container<HitExplosion> hitExplosionContainer;
private Container<KiaiHitExplosion> kiaiExplosionContainer; private Container<KiaiHitExplosion> kiaiExplosionContainer;

View File

@ -13,6 +13,7 @@ using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Screens;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Beatmaps.IO;
using osu.Game.Tests.Visual.Multiplayer; using osu.Game.Tests.Visual.Multiplayer;
@ -25,41 +26,43 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
private readonly User streamingUser = new User { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Test user" }; private readonly User streamingUser = new User { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Test user" };
[Cached(typeof(SpectatorClient))]
private TestSpectatorClient testSpectatorClient = new TestSpectatorClient();
[Cached(typeof(UserLookupCache))] [Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache(); private UserLookupCache lookupCache = new TestUserLookupCache();
// used just to show beatmap card for the time being. // used just to show beatmap card for the time being.
protected override bool UseOnlineAPI => true; protected override bool UseOnlineAPI => true;
private SoloSpectator spectatorScreen;
[Resolved] [Resolved]
private OsuGameBase game { get; set; } private OsuGameBase game { get; set; }
private BeatmapSetInfo importedBeatmap; private TestSpectatorClient spectatorClient;
private SoloSpectator spectatorScreen;
private BeatmapSetInfo importedBeatmap;
private int importedBeatmapId; private int importedBeatmapId;
public override void SetUpSteps() [SetUpSteps]
public void SetupSteps()
{ {
base.SetUpSteps(); DependenciesScreen dependenciesScreen = null;
AddStep("load dependencies", () =>
{
spectatorClient = new TestSpectatorClient();
// The screen gets suspended so it stops receiving updates.
Child = spectatorClient;
LoadScreen(dependenciesScreen = new DependenciesScreen(spectatorClient));
});
AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded);
AddStep("import beatmap", () => AddStep("import beatmap", () =>
{ {
importedBeatmap = ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Result; importedBeatmap = ImportBeatmapTest.LoadOszIntoOsu(game, virtualTrack: true).Result;
importedBeatmapId = importedBeatmap.Beatmaps.First(b => b.RulesetID == 0).OnlineBeatmapID ?? -1; importedBeatmapId = importedBeatmap.Beatmaps.First(b => b.RulesetID == 0).OnlineBeatmapID ?? -1;
}); });
AddStep("add streaming client", () =>
{
Remove(testSpectatorClient);
Add(testSpectatorClient);
});
finish();
} }
[Test] [Test]
@ -206,22 +209,36 @@ namespace osu.Game.Tests.Visual.Gameplay
private void waitForPlayer() => AddUntilStep("wait for player", () => (Stack.CurrentScreen as Player)?.IsLoaded == true); private void waitForPlayer() => AddUntilStep("wait for player", () => (Stack.CurrentScreen as Player)?.IsLoaded == true);
private void start(int? beatmapId = null) => AddStep("start play", () => testSpectatorClient.StartPlay(streamingUser.Id, beatmapId ?? importedBeatmapId)); private void start(int? beatmapId = null) => AddStep("start play", () => spectatorClient.StartPlay(streamingUser.Id, beatmapId ?? importedBeatmapId));
private void finish() => AddStep("end play", () => testSpectatorClient.EndPlay(streamingUser.Id)); private void finish() => AddStep("end play", () => spectatorClient.EndPlay(streamingUser.Id));
private void checkPaused(bool state) => private void checkPaused(bool state) =>
AddUntilStep($"game is {(state ? "paused" : "playing")}", () => player.ChildrenOfType<DrawableRuleset>().First().IsPaused.Value == state); AddUntilStep($"game is {(state ? "paused" : "playing")}", () => player.ChildrenOfType<DrawableRuleset>().First().IsPaused.Value == state);
private void sendFrames(int count = 10) private void sendFrames(int count = 10)
{ {
AddStep("send frames", () => testSpectatorClient.SendFrames(streamingUser.Id, count)); AddStep("send frames", () => spectatorClient.SendFrames(streamingUser.Id, count));
} }
private void loadSpectatingScreen() private void loadSpectatingScreen()
{ {
AddStep("load screen", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser))); AddStep("load spectator", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser)));
AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded); AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded);
} }
/// <summary>
/// Used for the sole purpose of adding <see cref="TestSpectatorClient"/> as a resolvable dependency.
/// </summary>
private class DependenciesScreen : OsuScreen
{
[Cached(typeof(SpectatorClient))]
public readonly TestSpectatorClient Client;
public DependenciesScreen(TestSpectatorClient client)
{
Client = client;
}
}
} }
} }

View File

@ -1,13 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Online.Spectator; using osu.Game.Online.Spectator;
@ -21,51 +20,44 @@ namespace osu.Game.Tests.Visual.Online
{ {
private readonly User streamingUser = new User { Id = 2, Username = "Test user" }; private readonly User streamingUser = new User { Id = 2, Username = "Test user" };
[Cached(typeof(SpectatorClient))] private TestSpectatorClient spectatorClient;
private TestSpectatorClient testSpectatorClient = new TestSpectatorClient();
private CurrentlyPlayingDisplay currentlyPlaying; private CurrentlyPlayingDisplay currentlyPlaying;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
private Container nestedContainer;
[SetUpSteps] [SetUpSteps]
public void SetUpSteps() public void SetUpSteps()
{ {
AddStep("add streaming client", () => AddStep("add streaming client", () =>
{ {
nestedContainer?.Remove(testSpectatorClient); spectatorClient = new TestSpectatorClient();
Remove(lookupCache); var lookupCache = new TestUserLookupCache();
Children = new Drawable[] Children = new Drawable[]
{ {
lookupCache, lookupCache,
nestedContainer = new Container spectatorClient,
new DependencyProvidingContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Children = new Drawable[] CachedDependencies = new (Type, object)[]
{ {
testSpectatorClient, (typeof(SpectatorClient), spectatorClient),
currentlyPlaying = new CurrentlyPlayingDisplay (typeof(UserLookupCache), lookupCache)
},
Child = currentlyPlaying = new CurrentlyPlayingDisplay
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} }
}
}, },
}; };
}); });
AddStep("Reset players", () => testSpectatorClient.EndPlay(streamingUser.Id));
} }
[Test] [Test]
public void TestBasicDisplay() public void TestBasicDisplay()
{ {
AddStep("Add playing user", () => testSpectatorClient.StartPlay(streamingUser.Id, 0)); AddStep("Add playing user", () => spectatorClient.StartPlay(streamingUser.Id, 0));
AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType<UserGridPanel>()?.FirstOrDefault()?.User.Id == 2); AddUntilStep("Panel loaded", () => currentlyPlaying.ChildrenOfType<UserGridPanel>()?.FirstOrDefault()?.User.Id == 2);
AddStep("Remove playing user", () => testSpectatorClient.EndPlay(streamingUser.Id)); AddStep("Remove playing user", () => spectatorClient.EndPlay(streamingUser.Id));
AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType<UserGridPanel>().Any()); AddUntilStep("Panel no longer present", () => !currentlyPlaying.ChildrenOfType<UserGridPanel>().Any());
} }

View File

@ -29,7 +29,7 @@ namespace osu.Game.Tests.Visual.Online
[Test] [Test]
public void TestControl() public void TestControl()
{ {
AddAssert("Front page selected", () => header.Current.Value == "frontpage"); AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
AddAssert("1 tab total", () => header.TabCount == 1); AddAssert("1 tab total", () => header.TabCount == 1);
AddStep("Set article 1", () => header.SetArticle("1")); AddStep("Set article 1", () => header.SetArticle("1"));
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("2 tabs total", () => header.TabCount == 2); AddAssert("2 tabs total", () => header.TabCount == 2);
AddStep("Set front page", () => header.SetFrontPage()); AddStep("Set front page", () => header.SetFrontPage());
AddAssert("Front page selected", () => header.Current.Value == "frontpage"); AddAssert("Front page selected", () => header.Current.Value == NewsHeader.FrontPageString);
AddAssert("1 tab total", () => header.TabCount == 1); AddAssert("1 tab total", () => header.TabCount == 1);
} }

View File

@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online
[Test] [Test]
public void TestWikiHeader() public void TestWikiHeader()
{ {
AddAssert("Current is index", () => checkCurrent("index")); AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
{ {
@ -54,8 +54,8 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Current is welcome", () => checkCurrent("Welcome")); AddAssert("Current is welcome", () => checkCurrent("Welcome"));
AddAssert("Check breadcrumb", checkBreadcrumb); AddAssert("Check breadcrumb", checkBreadcrumb);
AddStep("Change current to index", () => header.Current.Value = "index"); AddStep("Change current to index", () => header.Current.Value = WikiHeader.IndexPageString);
AddAssert("Current is index", () => checkCurrent("index")); AddAssert("Current is index", () => checkCurrent(WikiHeader.IndexPageString));
AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage
{ {
@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online
AddAssert("Check breadcrumb", checkBreadcrumb); AddAssert("Check breadcrumb", checkBreadcrumb);
} }
private bool checkCurrent(string expectedCurrent) => header.Current.Value == expectedCurrent; private bool checkCurrent(LocalisableString expectedCurrent) => header.Current.Value == expectedCurrent;
private bool checkBreadcrumb() private bool checkBreadcrumb()
{ {

View File

@ -1,2 +1,3 @@
[*.cs] [*.cs]
dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation dotnet_diagnostic.OLOC001.prefix_namespace = osu.Game.Resources.Localisation
dotnet_diagnostic.OLOC001.license_header = // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\n// See the LICENCE file in the repository root for full licence text.

View File

@ -1,22 +1,34 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
[LocalisableEnum(typeof(BeatmapSetOnlineStatusEnumLocalisationMapper))]
public enum BeatmapSetOnlineStatus public enum BeatmapSetOnlineStatus
{ {
None = -3, None = -3,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusGraveyard))]
Graveyard = -2, Graveyard = -2,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusWip))]
WIP = -1, WIP = -1,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusPending))]
Pending = 0, Pending = 0,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusRanked))]
Ranked = 1, Ranked = 1,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusApproved))]
Approved = 2, Approved = 2,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusQualified))]
Qualified = 3, Qualified = 3,
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusLoved))]
Loved = 4, Loved = 4,
} }
@ -25,40 +37,4 @@ namespace osu.Game.Beatmaps
public static bool GrantsPerformancePoints(this BeatmapSetOnlineStatus status) public static bool GrantsPerformancePoints(this BeatmapSetOnlineStatus status)
=> status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved; => status == BeatmapSetOnlineStatus.Ranked || status == BeatmapSetOnlineStatus.Approved;
} }
public class BeatmapSetOnlineStatusEnumLocalisationMapper : EnumLocalisationMapper<BeatmapSetOnlineStatus>
{
public override LocalisableString Map(BeatmapSetOnlineStatus value)
{
switch (value)
{
case BeatmapSetOnlineStatus.None:
return string.Empty;
case BeatmapSetOnlineStatus.Graveyard:
return BeatmapsetsStrings.ShowStatusGraveyard;
case BeatmapSetOnlineStatus.WIP:
return BeatmapsetsStrings.ShowStatusWip;
case BeatmapSetOnlineStatus.Pending:
return BeatmapsetsStrings.ShowStatusPending;
case BeatmapSetOnlineStatus.Ranked:
return BeatmapsetsStrings.ShowStatusRanked;
case BeatmapSetOnlineStatus.Approved:
return BeatmapsetsStrings.ShowStatusApproved;
case BeatmapSetOnlineStatus.Qualified:
return BeatmapsetsStrings.ShowStatusQualified;
case BeatmapSetOnlineStatus.Loved:
return BeatmapsetsStrings.ShowStatusLoved;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -48,7 +48,7 @@ namespace osu.Game.Graphics.Containers.Markdown
public override SpriteText CreateSpriteText() => new OsuSpriteText public override SpriteText CreateSpriteText() => new OsuSpriteText
{ {
Font = OsuFont.GetFont(size: 14), Font = OsuFont.GetFont(Typeface.Inter, size: 14, weight: FontWeight.Regular),
}; };
public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer(); public override MarkdownTextFlowContainer CreateTextFlow() => new OsuMarkdownTextFlowContainer();

View File

@ -70,7 +70,7 @@ namespace osu.Game.Graphics.Containers.Markdown
public FontWeight FontWeight; public FontWeight FontWeight;
protected override SpriteText CreateSpriteText() protected override SpriteText CreateSpriteText()
=> base.CreateSpriteText().With(t => t.Font = t.Font.With(size: FontSize, weight: FontWeight)); => base.CreateSpriteText().With(t => t.Font = t.Font.With(Typeface.Torus, size: FontSize, weight: FontWeight));
} }
} }
} }

View File

@ -21,6 +21,8 @@ namespace osu.Game.Graphics
public static FontUsage Torus => GetFont(Typeface.Torus, weight: FontWeight.Regular); public static FontUsage Torus => GetFont(Typeface.Torus, weight: FontWeight.Regular);
public static FontUsage Inter => GetFont(Typeface.Inter, weight: FontWeight.Regular);
/// <summary> /// <summary>
/// Retrieves a <see cref="FontUsage"/>. /// Retrieves a <see cref="FontUsage"/>.
/// </summary> /// </summary>
@ -54,6 +56,9 @@ namespace osu.Game.Graphics
case Typeface.Torus: case Typeface.Torus:
return "Torus"; return "Torus";
case Typeface.Inter:
return "Inter";
} }
return null; return null;
@ -107,7 +112,8 @@ namespace osu.Game.Graphics
public enum Typeface public enum Typeface
{ {
Venera, Venera,
Torus Torus,
Inter,
} }
public enum FontWeight public enum FontWeight

View File

@ -0,0 +1,44 @@
// 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.Localisation;
namespace osu.Game.Localisation
{
public static class NamedOverlayComponentStrings
{
private const string prefix = @"osu.Game.Resources.Localisation.NamedOverlayComponent";
/// <summary>
/// "browse for new beatmaps"
/// </summary>
public static LocalisableString BeatmapListingDescription => new TranslatableString(getKey(@"beatmap_listing_description"), @"browse for new beatmaps");
/// <summary>
/// "track recent dev updates in the osu! ecosystem"
/// </summary>
public static LocalisableString ChangelogDescription => new TranslatableString(getKey(@"changelog_description"), @"track recent dev updates in the osu! ecosystem");
/// <summary>
/// "view your friends and other information"
/// </summary>
public static LocalisableString DashboardDescription => new TranslatableString(getKey(@"dashboard_description"), @"view your friends and other information");
/// <summary>
/// "find out who's the best right now"
/// </summary>
public static LocalisableString RankingsDescription => new TranslatableString(getKey(@"rankings_description"), @"find out who's the best right now");
/// <summary>
/// "get up-to-date on community happenings"
/// </summary>
public static LocalisableString NewsDescription => new TranslatableString(getKey(@"news_description"), @"get up-to-date on community happenings");
/// <summary>
/// "knowledge base"
/// </summary>
public static LocalisableString WikiDescription => new TranslatableString(getKey(@"wiki_description"), @"knowledge base");
private static string getKey(string key) => $"{prefix}:{key}";
}
}

View File

@ -1,18 +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.Framework.Graphics;
using osu.Game.Graphics;
namespace osu.Game.Online.Rooms
{
public abstract class GameType
{
public abstract string Name { get; }
public abstract Drawable GetIcon(OsuColour colours, float size);
public override int GetHashCode() => GetType().GetHashCode();
public override bool Equals(object obj) => GetType() == obj?.GetType();
}
}

View File

@ -1,25 +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.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Online.Rooms.GameTypes
{
public class GameTypePlaylists : GameType
{
public override string Name => "Playlists";
public override Drawable GetIcon(OsuColour colours, float size) => new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Icon = FontAwesome.Regular.Clock,
Size = new Vector2(size),
Colour = colours.Blue,
Shadow = false
};
}
}

View File

@ -1,28 +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.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Online.Rooms.GameTypes
{
public class GameTypeTag : GameType
{
public override string Name => "Tag";
public override Drawable GetIcon(OsuColour colours, float size)
{
return new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Icon = FontAwesome.Solid.Sync,
Size = new Vector2(size),
Colour = colours.Blue,
Shadow = false,
};
}
}
}

View File

@ -1,45 +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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Online.Rooms.GameTypes
{
public class GameTypeTagTeam : GameType
{
public override string Name => "Tag Team";
public override Drawable GetIcon(OsuColour colours, float size)
{
return new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(2f),
Children = new[]
{
new SpriteIcon
{
Icon = FontAwesome.Solid.Sync,
Size = new Vector2(size * 0.75f),
Colour = colours.Blue,
Shadow = false,
},
new SpriteIcon
{
Icon = FontAwesome.Solid.Sync,
Size = new Vector2(size * 0.75f),
Colour = colours.Pink,
Shadow = false,
},
},
};
}
}
}

View File

@ -1,32 +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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osuTK;
namespace osu.Game.Online.Rooms.GameTypes
{
public class GameTypeTeamVersus : GameType
{
public override string Name => "Team Versus";
public override Drawable GetIcon(OsuColour colours, float size)
{
return new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(2f),
Children = new[]
{
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
},
};
}
}
}

View File

@ -1,22 +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.Framework.Graphics;
using osu.Game.Graphics;
namespace osu.Game.Online.Rooms.GameTypes
{
public class GameTypeVersus : GameType
{
public override string Name => "Versus";
public override Drawable GetIcon(OsuColour colours, float size)
{
return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
};
}
}
}

View File

@ -1,55 +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.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Online.Rooms.GameTypes
{
public class VersusRow : FillFlowContainer
{
public VersusRow(Color4 first, Color4 second, float size)
{
var triangleSize = new Vector2(size);
AutoSizeAxes = Axes.Both;
Spacing = new Vector2(2f, 0f);
Children = new[]
{
new Container
{
Size = triangleSize,
Colour = first,
Children = new[]
{
new EquilateralTriangle
{
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Rotation = 90,
EdgeSmoothness = new Vector2(1f),
},
},
},
new Container
{
Size = triangleSize,
Colour = second,
Children = new[]
{
new EquilateralTriangle
{
Anchor = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Rotation = -90,
EdgeSmoothness = new Vector2(1f),
},
},
},
};
}
}
}

View File

@ -0,0 +1,18 @@
// 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.ComponentModel;
namespace osu.Game.Online.Rooms
{
public enum MatchType
{
Playlists,
[Description("Head to head")]
HeadToHead,
[Description("Team VS")]
TeamVersus,
}
}

View File

@ -7,7 +7,6 @@ using Newtonsoft.Json;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.IO.Serialization.Converters; using osu.Game.IO.Serialization.Converters;
using osu.Game.Online.Rooms.GameTypes;
using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Online.Rooms.RoomStatuses;
using osu.Game.Users; using osu.Game.Users;
using osu.Game.Utils; using osu.Game.Utils;
@ -63,7 +62,7 @@ namespace osu.Game.Online.Rooms
[Cached] [Cached]
[JsonIgnore] [JsonIgnore]
public readonly Bindable<GameType> Type = new Bindable<GameType>(new GameTypePlaylists()); public readonly Bindable<MatchType> Type = new Bindable<MatchType>();
[Cached] [Cached]
[JsonIgnore] [JsonIgnore]

View File

@ -1,6 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
public class BeatmapListingHeader : OverlayHeader public class BeatmapListingHeader : OverlayHeader
@ -11,8 +14,8 @@ namespace osu.Game.Overlays.BeatmapListing
{ {
public BeatmapListingTitle() public BeatmapListingTitle()
{ {
Title = "beatmap listing"; Title = PageTitleStrings.MainBeatmapsetsControllerIndex;
Description = "browse for new beatmaps"; Description = NamedOverlayComponentStrings.BeatmapListingDescription;
IconTexture = "Icons/Hexacons/beatmap"; IconTexture = "Icons/Hexacons/beatmap";
} }
} }

View File

@ -1,69 +1,42 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchCategoryEnumLocalisationMapper))]
public enum SearchCategory public enum SearchCategory
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusAny))]
Any, Any,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusLeaderboard))]
[Description("Has Leaderboard")] [Description("Has Leaderboard")]
Leaderboard, Leaderboard,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusRanked))]
Ranked, Ranked,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusQualified))]
Qualified, Qualified,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusLoved))]
Loved, Loved,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusFavourites))]
Favourites, Favourites,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusPending))]
[Description("Pending & WIP")] [Description("Pending & WIP")]
Pending, Pending,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusGraveyard))]
Graveyard, Graveyard,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.StatusMine))]
[Description("My Maps")] [Description("My Maps")]
Mine, Mine,
} }
public class SearchCategoryEnumLocalisationMapper : EnumLocalisationMapper<SearchCategory>
{
public override LocalisableString Map(SearchCategory value)
{
switch (value)
{
case SearchCategory.Any:
return BeatmapsStrings.StatusAny;
case SearchCategory.Leaderboard:
return BeatmapsStrings.StatusLeaderboard;
case SearchCategory.Ranked:
return BeatmapsStrings.StatusRanked;
case SearchCategory.Qualified:
return BeatmapsStrings.StatusQualified;
case SearchCategory.Loved:
return BeatmapsStrings.StatusLoved;
case SearchCategory.Favourites:
return BeatmapsStrings.StatusFavourites;
case SearchCategory.Pending:
return BeatmapsStrings.StatusPending;
case SearchCategory.Graveyard:
return BeatmapsStrings.StatusGraveyard;
case SearchCategory.Mine:
return BeatmapsStrings.StatusMine;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,34 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchExplicitEnumLocalisationMapper))]
public enum SearchExplicit public enum SearchExplicit
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.NsfwExclude))]
Hide, Hide,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.NsfwInclude))]
Show Show
} }
public class SearchExplicitEnumLocalisationMapper : EnumLocalisationMapper<SearchExplicit>
{
public override LocalisableString Map(SearchExplicit value)
{
switch (value)
{
case SearchExplicit.Hide:
return BeatmapsStrings.NsfwExclude;
case SearchExplicit.Show:
return BeatmapsStrings.NsfwInclude;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,38 +1,20 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchExtraEnumLocalisationMapper))]
public enum SearchExtra public enum SearchExtra
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ExtraVideo))]
[Description("Has Video")] [Description("Has Video")]
Video, Video,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ExtraStoryboard))]
[Description("Has Storyboard")] [Description("Has Storyboard")]
Storyboard Storyboard
} }
public class SearchExtraEnumLocalisationMapper : EnumLocalisationMapper<SearchExtra>
{
public override LocalisableString Map(SearchExtra value)
{
switch (value)
{
case SearchExtra.Video:
return BeatmapsStrings.ExtraVideo;
case SearchExtra.Storyboard:
return BeatmapsStrings.ExtraStoryboard;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,44 +1,24 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchGeneralEnumLocalisationMapper))]
public enum SearchGeneral public enum SearchGeneral
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralRecommended))]
[Description("Recommended difficulty")] [Description("Recommended difficulty")]
Recommended, Recommended,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralConverts))]
[Description("Include converted beatmaps")] [Description("Include converted beatmaps")]
Converts, Converts,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GeneralFollows))]
[Description("Subscribed mappers")] [Description("Subscribed mappers")]
Follows Follows
} }
public class SearchGeneralEnumLocalisationMapper : EnumLocalisationMapper<SearchGeneral>
{
public override LocalisableString Map(SearchGeneral value)
{
switch (value)
{
case SearchGeneral.Recommended:
return BeatmapsStrings.GeneralRecommended;
case SearchGeneral.Converts:
return BeatmapsStrings.GeneralConverts;
case SearchGeneral.Follows:
return BeatmapsStrings.GeneralFollows;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,87 +1,56 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchGenreEnumLocalisationMapper))]
public enum SearchGenre public enum SearchGenre
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreAny))]
Any = 0, Any = 0,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreUnspecified))]
Unspecified = 1, Unspecified = 1,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreVideoGame))]
[Description("Video Game")] [Description("Video Game")]
VideoGame = 2, VideoGame = 2,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreAnime))]
Anime = 3, Anime = 3,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreRock))]
Rock = 4, Rock = 4,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenrePop))]
Pop = 5, Pop = 5,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreOther))]
Other = 6, Other = 6,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreNovelty))]
Novelty = 7, Novelty = 7,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreHipHop))]
[Description("Hip Hop")] [Description("Hip Hop")]
HipHop = 9, HipHop = 9,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreElectronic))]
Electronic = 10, Electronic = 10,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreMetal))]
Metal = 11, Metal = 11,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreClassical))]
Classical = 12, Classical = 12,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreFolk))]
Folk = 13, Folk = 13,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.GenreJazz))]
Jazz = 14 Jazz = 14
} }
public class SearchGenreEnumLocalisationMapper : EnumLocalisationMapper<SearchGenre>
{
public override LocalisableString Map(SearchGenre value)
{
switch (value)
{
case SearchGenre.Any:
return BeatmapsStrings.GenreAny;
case SearchGenre.Unspecified:
return BeatmapsStrings.GenreUnspecified;
case SearchGenre.VideoGame:
return BeatmapsStrings.GenreVideoGame;
case SearchGenre.Anime:
return BeatmapsStrings.GenreAnime;
case SearchGenre.Rock:
return BeatmapsStrings.GenreRock;
case SearchGenre.Pop:
return BeatmapsStrings.GenrePop;
case SearchGenre.Other:
return BeatmapsStrings.GenreOther;
case SearchGenre.Novelty:
return BeatmapsStrings.GenreNovelty;
case SearchGenre.HipHop:
return BeatmapsStrings.GenreHipHop;
case SearchGenre.Electronic:
return BeatmapsStrings.GenreElectronic;
case SearchGenre.Metal:
return BeatmapsStrings.GenreMetal;
case SearchGenre.Classical:
return BeatmapsStrings.GenreClassical;
case SearchGenre.Folk:
return BeatmapsStrings.GenreFolk;
case SearchGenre.Jazz:
return BeatmapsStrings.GenreJazz;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,117 +1,73 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchLanguageEnumLocalisationMapper))]
[HasOrderedElements] [HasOrderedElements]
public enum SearchLanguage public enum SearchLanguage
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageAny))]
[Order(0)] [Order(0)]
Any, Any,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageUnspecified))]
[Order(14)] [Order(14)]
Unspecified, Unspecified,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageEnglish))]
[Order(1)] [Order(1)]
English, English,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageJapanese))]
[Order(6)] [Order(6)]
Japanese, Japanese,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageChinese))]
[Order(2)] [Order(2)]
Chinese, Chinese,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageInstrumental))]
[Order(12)] [Order(12)]
Instrumental, Instrumental,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageKorean))]
[Order(7)] [Order(7)]
Korean, Korean,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageFrench))]
[Order(3)] [Order(3)]
French, French,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageGerman))]
[Order(4)] [Order(4)]
German, German,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageSwedish))]
[Order(9)] [Order(9)]
Swedish, Swedish,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageSpanish))]
[Order(8)] [Order(8)]
Spanish, Spanish,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageItalian))]
[Order(5)] [Order(5)]
Italian, Italian,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageRussian))]
[Order(10)] [Order(10)]
Russian, Russian,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguagePolish))]
[Order(11)] [Order(11)]
Polish, Polish,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.LanguageOther))]
[Order(13)] [Order(13)]
Other Other
} }
public class SearchLanguageEnumLocalisationMapper : EnumLocalisationMapper<SearchLanguage>
{
public override LocalisableString Map(SearchLanguage value)
{
switch (value)
{
case SearchLanguage.Any:
return BeatmapsStrings.LanguageAny;
case SearchLanguage.Unspecified:
return BeatmapsStrings.LanguageUnspecified;
case SearchLanguage.English:
return BeatmapsStrings.LanguageEnglish;
case SearchLanguage.Japanese:
return BeatmapsStrings.LanguageJapanese;
case SearchLanguage.Chinese:
return BeatmapsStrings.LanguageChinese;
case SearchLanguage.Instrumental:
return BeatmapsStrings.LanguageInstrumental;
case SearchLanguage.Korean:
return BeatmapsStrings.LanguageKorean;
case SearchLanguage.French:
return BeatmapsStrings.LanguageFrench;
case SearchLanguage.German:
return BeatmapsStrings.LanguageGerman;
case SearchLanguage.Swedish:
return BeatmapsStrings.LanguageSwedish;
case SearchLanguage.Spanish:
return BeatmapsStrings.LanguageSpanish;
case SearchLanguage.Italian:
return BeatmapsStrings.LanguageItalian;
case SearchLanguage.Russian:
return BeatmapsStrings.LanguageRussian;
case SearchLanguage.Polish:
return BeatmapsStrings.LanguagePolish;
case SearchLanguage.Other:
return BeatmapsStrings.LanguageOther;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,38 +1,20 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SearchPlayedEnumLocalisationMapper))]
public enum SearchPlayed public enum SearchPlayed
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedAny))]
Any, Any,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedPlayed))]
Played, Played,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.PlayedUnplayed))]
Unplayed Unplayed
} }
public class SearchPlayedEnumLocalisationMapper : EnumLocalisationMapper<SearchPlayed>
{
public override LocalisableString Map(SearchPlayed value)
{
switch (value)
{
case SearchPlayed.Any:
return BeatmapsStrings.PlayedAny;
case SearchPlayed.Played:
return BeatmapsStrings.PlayedPlayed;
case SearchPlayed.Unplayed:
return BeatmapsStrings.PlayedUnplayed;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,58 +1,35 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.BeatmapListing namespace osu.Game.Overlays.BeatmapListing
{ {
[LocalisableEnum(typeof(SortCriteriaLocalisationMapper))]
public enum SortCriteria public enum SortCriteria
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingTitle))]
Title, Title,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingArtist))]
Artist, Artist,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingDifficulty))]
Difficulty, Difficulty,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRanked))]
Ranked, Ranked,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRating))]
Rating, Rating,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingPlays))]
Plays, Plays,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingFavourites))]
Favourites, Favourites,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.ListingSearchSortingRelevance))]
Relevance Relevance
} }
public class SortCriteriaLocalisationMapper : EnumLocalisationMapper<SortCriteria>
{
public override LocalisableString Map(SortCriteria value)
{
switch (value)
{
case SortCriteria.Title:
return BeatmapsStrings.ListingSearchSortingTitle;
case SortCriteria.Artist:
return BeatmapsStrings.ListingSearchSortingArtist;
case SortCriteria.Difficulty:
return BeatmapsStrings.ListingSearchSortingDifficulty;
case SortCriteria.Ranked:
return BeatmapsStrings.ListingSearchSortingRanked;
case SortCriteria.Rating:
return BeatmapsStrings.ListingSearchSortingRating;
case SortCriteria.Plays:
return BeatmapsStrings.ListingSearchSortingPlays;
case SortCriteria.Favourites:
return BeatmapsStrings.ListingSearchSortingFavourites;
case SortCriteria.Relevance:
return BeatmapsStrings.ListingSearchSortingRelevance;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -7,6 +7,7 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osuTK; using osuTK;
using osuTK.Graphics; using osuTK.Graphics;
@ -54,7 +55,7 @@ namespace osu.Game.Overlays.BeatmapSet
{ {
public BeatmapHeaderTitle() public BeatmapHeaderTitle()
{ {
Title = "beatmap info"; Title = PageTitleStrings.MainBeatmapsetsControllerShow;
IconTexture = "Icons/Hexacons/beatmap"; IconTexture = "Icons/Hexacons/beatmap";
} }
} }

View File

@ -9,7 +9,10 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Changelog namespace osu.Game.Overlays.Changelog
{ {
@ -21,16 +24,16 @@ namespace osu.Game.Overlays.Changelog
public ChangelogUpdateStreamControl Streams; public ChangelogUpdateStreamControl Streams;
private const string listing_string = "listing"; public static LocalisableString ListingString => LayoutStrings.HeaderChangelogIndex;
private Box streamsBackground; private Box streamsBackground;
public ChangelogHeader() public ChangelogHeader()
{ {
TabControl.AddItem(listing_string); TabControl.AddItem(ListingString);
Current.ValueChanged += e => Current.ValueChanged += e =>
{ {
if (e.NewValue == listing_string) if (e.NewValue == ListingString)
ListingSelected?.Invoke(); ListingSelected?.Invoke();
}; };
@ -63,7 +66,7 @@ namespace osu.Game.Overlays.Changelog
} }
else else
{ {
Current.Value = listing_string; Current.Value = ListingString;
Streams.Current.Value = null; Streams.Current.Value = null;
} }
} }
@ -114,8 +117,8 @@ namespace osu.Game.Overlays.Changelog
{ {
public ChangelogHeaderTitle() public ChangelogHeaderTitle()
{ {
Title = "changelog"; Title = PageTitleStrings.MainChangelogControllerDefault;
Description = "track recent dev updates in the osu! ecosystem"; Description = NamedOverlayComponentStrings.ChangelogDescription;
IconTexture = "Icons/Hexacons/devtools"; IconTexture = "Icons/Hexacons/devtools";
} }
} }

View File

@ -1,9 +1,9 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Dashboard namespace osu.Game.Overlays.Dashboard
@ -16,37 +16,19 @@ namespace osu.Game.Overlays.Dashboard
{ {
public DashboardTitle() public DashboardTitle()
{ {
Title = HomeStrings.UserTitle; Title = PageTitleStrings.MainHomeControllerIndex;
Description = "view your friends and other information"; Description = NamedOverlayComponentStrings.DashboardDescription;
IconTexture = "Icons/Hexacons/social"; IconTexture = "Icons/Hexacons/social";
} }
} }
} }
[LocalisableEnum(typeof(DashboardOverlayTabsEnumLocalisationMapper))]
public enum DashboardOverlayTabs public enum DashboardOverlayTabs
{ {
[LocalisableDescription(typeof(FriendsStrings), nameof(FriendsStrings.TitleCompact))]
Friends, Friends,
[Description("Currently Playing")] [Description("Currently Playing")]
CurrentlyPlaying CurrentlyPlaying
} }
public class DashboardOverlayTabsEnumLocalisationMapper : EnumLocalisationMapper<DashboardOverlayTabs>
{
public override LocalisableString Map(DashboardOverlayTabs value)
{
switch (value)
{
case DashboardOverlayTabs.Friends:
return FriendsStrings.TitleCompact;
case DashboardOverlayTabs.CurrentlyPlaying:
return @"Currently Playing";
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,38 +1,20 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Dashboard.Friends namespace osu.Game.Overlays.Dashboard.Friends
{ {
[LocalisableEnum(typeof(OnlineStatusEnumLocalisationMapper))]
public enum OnlineStatus public enum OnlineStatus
{ {
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusAll))]
All, All,
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOnline))]
Online, Online,
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.StatusOffline))]
Offline Offline
} }
public class OnlineStatusEnumLocalisationMapper : EnumLocalisationMapper<OnlineStatus>
{
public override LocalisableString Map(OnlineStatus value)
{
switch (value)
{
case OnlineStatus.All:
return SortStrings.All;
case OnlineStatus.Online:
return UsersStrings.StatusOnline;
case OnlineStatus.Offline:
return UsersStrings.StatusOffline;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
@ -12,33 +11,16 @@ namespace osu.Game.Overlays.Dashboard.Friends
{ {
} }
[LocalisableEnum(typeof(UserSortCriteriaEnumLocalisationMappper))]
public enum UserSortCriteria public enum UserSortCriteria
{ {
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.LastVisit))]
[Description(@"Recently Active")] [Description(@"Recently Active")]
LastVisit, LastVisit,
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Rank))]
Rank, Rank,
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Username))]
Username Username
} }
public class UserSortCriteriaEnumLocalisationMappper : EnumLocalisationMapper<UserSortCriteria>
{
public override LocalisableString Map(UserSortCriteria value)
{
switch (value)
{
case UserSortCriteria.LastVisit:
return SortStrings.LastVisit;
case UserSortCriteria.Rank:
return SortStrings.Rank;
case UserSortCriteria.Username:
return SortStrings.Username;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -4,12 +4,15 @@
using System; using System;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.News namespace osu.Game.Overlays.News
{ {
public class NewsHeader : BreadcrumbControlOverlayHeader public class NewsHeader : BreadcrumbControlOverlayHeader
{ {
private const string front_page_string = "frontpage"; public static LocalisableString FrontPageString => NewsStrings.IndexTitleInfo;
public Action ShowFrontPage; public Action ShowFrontPage;
@ -17,7 +20,7 @@ namespace osu.Game.Overlays.News
public NewsHeader() public NewsHeader()
{ {
TabControl.AddItem(front_page_string); TabControl.AddItem(FrontPageString);
article.BindValueChanged(onArticleChanged, true); article.BindValueChanged(onArticleChanged, true);
} }
@ -28,7 +31,7 @@ namespace osu.Game.Overlays.News
Current.BindValueChanged(e => Current.BindValueChanged(e =>
{ {
if (e.NewValue == front_page_string) if (e.NewValue == FrontPageString)
ShowFrontPage?.Invoke(); ShowFrontPage?.Invoke();
}); });
} }
@ -49,7 +52,7 @@ namespace osu.Game.Overlays.News
} }
else else
{ {
Current.Value = front_page_string; Current.Value = FrontPageString;
} }
} }
@ -61,8 +64,8 @@ namespace osu.Game.Overlays.News
{ {
public NewsHeaderTitle() public NewsHeaderTitle()
{ {
Title = "news"; Title = PageTitleStrings.MainNewsControllerDefault;
Description = "get up-to-date on community happenings"; Description = NamedOverlayComponentStrings.NewsDescription;
IconTexture = "Icons/Hexacons/news"; IconTexture = "Icons/Hexacons/news";
} }
} }

View File

@ -12,7 +12,6 @@ using osu.Framework.Allocation;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using System;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
using osu.Framework.Extensions; using osu.Framework.Extensions;
@ -101,32 +100,15 @@ namespace osu.Game.Overlays
} }
} }
[LocalisableEnum(typeof(OverlayPanelDisplayStyleEnumLocalisationMapper))]
public enum OverlayPanelDisplayStyle public enum OverlayPanelDisplayStyle
{ {
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeCard))]
Card, Card,
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeList))]
List, List,
[LocalisableDescription(typeof(UsersStrings), nameof(UsersStrings.ViewModeBrick))]
Brick Brick
} }
public class OverlayPanelDisplayStyleEnumLocalisationMapper : EnumLocalisationMapper<OverlayPanelDisplayStyle>
{
public override LocalisableString Map(OverlayPanelDisplayStyle value)
{
switch (value)
{
case OverlayPanelDisplayStyle.Card:
return UsersStrings.ViewModeCard;
case OverlayPanelDisplayStyle.List:
return UsersStrings.ViewModeList;
case OverlayPanelDisplayStyle.Brick:
return UsersStrings.ViewModeBrick;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -1,13 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Localisation;
using osu.Game.Resources.Localisation.Web;
using osu.Framework.Graphics;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Users; using osu.Game.Users;
using osu.Game.Resources.Localisation.Web;
using osu.Framework.Localisation;
using System;
namespace osu.Game.Overlays.Rankings namespace osu.Game.Overlays.Rankings
{ {
@ -33,42 +32,9 @@ namespace osu.Game.Overlays.Rankings
public RankingsTitle() public RankingsTitle()
{ {
Title = PageTitleStrings.MainRankingControllerDefault; Title = PageTitleStrings.MainRankingControllerDefault;
Description = "find out who's the best right now"; Description = NamedOverlayComponentStrings.RankingsDescription;
IconTexture = "Icons/Hexacons/rankings"; IconTexture = "Icons/Hexacons/rankings";
} }
} }
} }
[LocalisableEnum(typeof(RankingsScopeEnumLocalisationMapper))]
public enum RankingsScope
{
Performance,
Spotlights,
Score,
Country
}
public class RankingsScopeEnumLocalisationMapper : EnumLocalisationMapper<RankingsScope>
{
public override LocalisableString Map(RankingsScope value)
{
switch (value)
{
case RankingsScope.Performance:
return RankingsStrings.TypePerformance;
case RankingsScope.Spotlights:
return RankingsStrings.TypeCharts;
case RankingsScope.Score:
return RankingsStrings.TypeScore;
case RankingsScope.Country:
return RankingsStrings.TypeCountry;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View 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.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Rankings
{
public enum RankingsScope
{
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypePerformance))]
Performance,
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCharts))]
Spotlights,
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeScore))]
Score,
[LocalisableDescription(typeof(RankingsStrings), nameof(RankingsStrings.TypeCountry))]
Country
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
@ -16,28 +15,12 @@ namespace osu.Game.Overlays.Rankings
} }
} }
[LocalisableEnum(typeof(RankingsSortCriteriaEnumLocalisationMapper))]
public enum RankingsSortCriteria public enum RankingsSortCriteria
{ {
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.All))]
All, All,
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.Friends))]
Friends Friends
} }
public class RankingsSortCriteriaEnumLocalisationMapper : EnumLocalisationMapper<RankingsSortCriteria>
{
public override LocalisableString Map(RankingsSortCriteria value)
{
switch (value)
{
case RankingsSortCriteria.All:
return SortStrings.All;
case RankingsSortCriteria.Friends:
return SortStrings.Friends;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -6,15 +6,18 @@ using System.Linq;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Localisation;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Overlays.Wiki namespace osu.Game.Overlays.Wiki
{ {
public class WikiHeader : BreadcrumbControlOverlayHeader public class WikiHeader : BreadcrumbControlOverlayHeader
{ {
private const string index_page_string = "index";
private const string index_path = "Main_Page"; private const string index_path = "Main_Page";
public static LocalisableString IndexPageString => LayoutStrings.HeaderHelpIndex;
public readonly Bindable<APIWikiPage> WikiPageData = new Bindable<APIWikiPage>(); public readonly Bindable<APIWikiPage> WikiPageData = new Bindable<APIWikiPage>();
public Action ShowIndexPage; public Action ShowIndexPage;
@ -22,8 +25,8 @@ namespace osu.Game.Overlays.Wiki
public WikiHeader() public WikiHeader()
{ {
TabControl.AddItem(index_page_string); TabControl.AddItem(IndexPageString);
Current.Value = index_page_string; Current.Value = IndexPageString;
WikiPageData.BindValueChanged(onWikiPageChange); WikiPageData.BindValueChanged(onWikiPageChange);
Current.BindValueChanged(onCurrentChange); Current.BindValueChanged(onCurrentChange);
@ -37,11 +40,11 @@ namespace osu.Game.Overlays.Wiki
TabControl.Clear(); TabControl.Clear();
Current.Value = null; Current.Value = null;
TabControl.AddItem(index_page_string); TabControl.AddItem(IndexPageString);
if (e.NewValue.Path == index_path) if (e.NewValue.Path == index_path)
{ {
Current.Value = index_page_string; Current.Value = IndexPageString;
return; return;
} }
@ -57,7 +60,7 @@ namespace osu.Game.Overlays.Wiki
if (e.NewValue == TabControl.Items.LastOrDefault()) if (e.NewValue == TabControl.Items.LastOrDefault())
return; return;
if (e.NewValue == index_page_string) if (e.NewValue == IndexPageString)
{ {
ShowIndexPage?.Invoke(); ShowIndexPage?.Invoke();
return; return;
@ -74,8 +77,8 @@ namespace osu.Game.Overlays.Wiki
{ {
public WikiHeaderTitle() public WikiHeaderTitle()
{ {
Title = "wiki"; Title = PageTitleStrings.MainWikiControllerDefault;
Description = "knowledge base"; Description = NamedOverlayComponentStrings.WikiDescription;
IconTexture = "Icons/Hexacons/wiki"; IconTexture = "Icons/Hexacons/wiki";
} }
} }

View File

@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Wiki
Child = new OsuSpriteText Child = new OsuSpriteText
{ {
Text = blurbNode.InnerText, Text = blurbNode.InnerText,
Font = OsuFont.GetFont(size: 12), Font = OsuFont.GetFont(Typeface.Inter, size: 12, weight: FontWeight.Light),
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,
} }

View File

@ -89,7 +89,7 @@ namespace osu.Game.Overlays.Wiki
DocumentMargin = new MarginPadding(0); DocumentMargin = new MarginPadding(0);
} }
public override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(weight: FontWeight.Bold)); public override SpriteText CreateSpriteText() => base.CreateSpriteText().With(t => t.Font = t.Font.With(Typeface.Torus, weight: FontWeight.Bold));
public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(f => f.TextAnchor = Anchor.TopCentre); public override MarkdownTextFlowContainer CreateTextFlow() => base.CreateTextFlow().With(f => f.TextAnchor = Anchor.TopCentre);

View File

@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
/// <summary> /// <summary>
/// The maximum span of time that may be visible by the length of the scrolling axes. /// The maximum span of time that may be visible by the length of the scrolling axes.
/// </summary> /// </summary>
private const double time_span_max = 10000; private const double time_span_max = 20000;
/// <summary> /// <summary>
/// The step increase/decrease of the span of time visible by the length of the scrolling axes. /// The step increase/decrease of the span of time visible by the length of the scrolling axes.

View File

@ -1,74 +1,44 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Scoring namespace osu.Game.Scoring
{ {
[LocalisableEnum(typeof(ScoreRankEnumLocalisationMapper))]
public enum ScoreRank public enum ScoreRank
{ {
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankD))]
[Description(@"D")] [Description(@"D")]
D, D,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankC))]
[Description(@"C")] [Description(@"C")]
C, C,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankB))]
[Description(@"B")] [Description(@"B")]
B, B,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankA))]
[Description(@"A")] [Description(@"A")]
A, A,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankS))]
[Description(@"S")] [Description(@"S")]
S, S,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankSH))]
[Description(@"S+")] [Description(@"S+")]
SH, SH,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankX))]
[Description(@"SS")] [Description(@"SS")]
X, X,
[LocalisableDescription(typeof(BeatmapsStrings), nameof(BeatmapsStrings.RankXH))]
[Description(@"SS+")] [Description(@"SS+")]
XH, XH,
} }
public class ScoreRankEnumLocalisationMapper : EnumLocalisationMapper<ScoreRank>
{
public override LocalisableString Map(ScoreRank value)
{
switch (value)
{
case ScoreRank.XH:
return BeatmapsStrings.RankXH;
case ScoreRank.X:
return BeatmapsStrings.RankX;
case ScoreRank.SH:
return BeatmapsStrings.RankSH;
case ScoreRank.S:
return BeatmapsStrings.RankS;
case ScoreRank.A:
return BeatmapsStrings.RankA;
case ScoreRank.B:
return BeatmapsStrings.RankB;
case ScoreRank.C:
return BeatmapsStrings.RankC;
case ScoreRank.D:
return BeatmapsStrings.RankD;
default:
throw new ArgumentOutOfRangeException(nameof(value), value, null);
}
}
}
} }

View File

@ -2,24 +2,28 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.OnlinePlay.Components namespace osu.Game.Screens.OnlinePlay.Components
{ {
public class DrawableGameType : CircularContainer, IHasTooltip public class DrawableGameType : CircularContainer, IHasTooltip
{ {
private readonly GameType type; private readonly MatchType type;
public LocalisableString TooltipText => type.Name; public LocalisableString TooltipText => type.GetLocalisableDescription();
public DrawableGameType(GameType type) public DrawableGameType(MatchType type)
{ {
this.type = type; this.type = type;
Masking = true; Masking = true;
@ -34,10 +38,138 @@ namespace osu.Game.Screens.OnlinePlay.Components
}; };
} }
[Resolved]
private OsuColour colours { get; set; }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load()
{ {
Add(type.GetIcon(colours, Height / 2)); Add(getIconFor(type));
}
private Drawable getIconFor(MatchType matchType)
{
float size = Height / 2;
switch (matchType)
{
default:
case MatchType.Playlists:
return new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(size),
Icon = FontAwesome.Regular.Clock,
Colour = colours.Blue,
Shadow = false
};
case MatchType.HeadToHead:
return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
};
case MatchType.TeamVersus:
return new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(2f),
Children = new[]
{
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
},
};
// case MatchType.TagCoop:
// return new SpriteIcon
// {
// Anchor = Anchor.Centre,
// Origin = Anchor.Centre,
// Size = new Vector2(size),
// Icon = FontAwesome.Solid.Sync,
// Colour = colours.Blue,
//
// Shadow = false
// };
// case MatchType.TagTeamCoop:
// return new FillFlowContainer
// {
// Anchor = Anchor.Centre,
// Origin = Anchor.Centre,
// AutoSizeAxes = Axes.Both,
// Direction = FillDirection.Horizontal,
// Spacing = new Vector2(2f),
// Children = new[]
// {
// new SpriteIcon
// {
// Icon = FontAwesome.Solid.Sync,
// Size = new Vector2(size * 0.75f),
// Colour = colours.Blue,
// Shadow = false,
// },
// new SpriteIcon
// {
// Icon = FontAwesome.Solid.Sync,
// Size = new Vector2(size * 0.75f),
// Colour = colours.Pink,
// Shadow = false,
// },
// },
// };
}
}
private class VersusRow : FillFlowContainer
{
public VersusRow(Color4 first, Color4 second, float size)
{
var triangleSize = new Vector2(size);
AutoSizeAxes = Axes.Both;
Spacing = new Vector2(2f, 0f);
Children = new[]
{
new Container
{
Size = triangleSize,
Colour = first,
Children = new[]
{
new EquilateralTriangle
{
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Rotation = 90,
EdgeSmoothness = new Vector2(1f),
},
},
},
new Container
{
Size = triangleSize,
Colour = second,
Children = new[]
{
new EquilateralTriangle
{
Anchor = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Rotation = -90,
EdgeSmoothness = new Vector2(1f),
},
},
},
};
}
} }
} }
} }

View File

@ -9,31 +9,29 @@ using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Online.Rooms; using osu.Game.Online.Rooms;
using osu.Game.Online.Rooms.GameTypes;
using osu.Game.Screens.OnlinePlay.Components; using osu.Game.Screens.OnlinePlay.Components;
using osuTK; using osuTK;
namespace osu.Game.Screens.OnlinePlay.Match.Components namespace osu.Game.Screens.OnlinePlay.Match.Components
{ {
public class GameTypePicker : DisableableTabControl<GameType> public class MatchTypePicker : DisableableTabControl<MatchType>
{ {
private const float height = 40; private const float height = 40;
private const float selection_width = 3; private const float selection_width = 3;
protected override TabItem<GameType> CreateTabItem(GameType value) => new GameTypePickerItem(value); protected override TabItem<MatchType> CreateTabItem(MatchType value) => new GameTypePickerItem(value);
protected override Dropdown<GameType> CreateDropdown() => null; protected override Dropdown<MatchType> CreateDropdown() => null;
public GameTypePicker() public MatchTypePicker()
{ {
Height = height + selection_width * 2; Height = height + selection_width * 2;
TabContainer.Spacing = new Vector2(10 - selection_width * 2); TabContainer.Spacing = new Vector2(10 - selection_width * 2);
AddItem(new GameTypeTag()); AddItem(MatchType.HeadToHead);
AddItem(new GameTypeVersus()); AddItem(MatchType.TeamVersus);
AddItem(new GameTypeTagTeam()); // TODO: remove after osu-web is updated to set the correct default type.
AddItem(new GameTypeTeamVersus()); AddItem(MatchType.Playlists);
AddItem(new GameTypePlaylists());
} }
private class GameTypePickerItem : DisableableTabItem private class GameTypePickerItem : DisableableTabItem
@ -42,7 +40,7 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
private readonly CircularContainer hover, selection; private readonly CircularContainer hover, selection;
public GameTypePickerItem(GameType value) public GameTypePickerItem(MatchType value)
: base(value) : base(value)
{ {
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Extensions.ExceptionExtensions; using osu.Framework.Extensions.ExceptionExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -43,7 +44,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
public OsuTextBox NameField, MaxParticipantsField; public OsuTextBox NameField, MaxParticipantsField;
public RoomAvailabilityPicker AvailabilityPicker; public RoomAvailabilityPicker AvailabilityPicker;
public GameTypePicker TypePicker; public MatchTypePicker TypePicker;
public OsuTextBox PasswordTextBox; public OsuTextBox PasswordTextBox;
public TriangleButton ApplyButton; public TriangleButton ApplyButton;
@ -157,7 +158,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
Spacing = new Vector2(7), Spacing = new Vector2(7),
Children = new Drawable[] Children = new Drawable[]
{ {
TypePicker = new GameTypePicker TypePicker = new MatchTypePicker
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Enabled = { Value = false } Enabled = { Value = false }
@ -265,7 +266,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
loadingLayer = new LoadingLayer(true) loadingLayer = new LoadingLayer(true)
}; };
TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue.GetLocalisableDescription(), true);
RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true); RoomName.BindValueChanged(name => NameField.Text = name.NewValue, true);
Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true); Availability.BindValueChanged(availability => AvailabilityPicker.Current.Value = availability.NewValue, true);
Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true); Type.BindValueChanged(type => TypePicker.Current.Value = type.NewValue, true);

View File

@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay
protected Bindable<RoomStatus> Status { get; private set; } protected Bindable<RoomStatus> Status { get; private set; }
[Resolved(typeof(Room))] [Resolved(typeof(Room))]
protected Bindable<GameType> Type { get; private set; } protected Bindable<MatchType> Type { get; private set; }
[Resolved(typeof(Room))] [Resolved(typeof(Room))]
protected BindableList<PlaylistItem> Playlist { get; private set; } protected BindableList<PlaylistItem> Playlist { get; private set; }

View File

@ -36,8 +36,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="10.3.0" /> <PackageReference Include="Realm" Version="10.3.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.728.0" /> <PackageReference Include="ppy.osu.Framework" Version="2021.803.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
<PackageReference Include="Sentry" Version="3.8.3" /> <PackageReference Include="Sentry" Version="3.8.3" />
<PackageReference Include="SharpCompress" Version="0.28.3" /> <PackageReference Include="SharpCompress" Version="0.28.3" />
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2" />

View File

@ -70,8 +70,8 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.728.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.803.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.730.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
</ItemGroup> </ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) --> <!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
<PropertyGroup> <PropertyGroup>
@ -93,7 +93,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2021.728.0" /> <PackageReference Include="ppy.osu.Framework" Version="2021.803.0" />
<PackageReference Include="SharpCompress" Version="0.28.3" /> <PackageReference Include="SharpCompress" Version="0.28.3" />
<PackageReference Include="NUnit" Version="3.13.2" /> <PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />