mirror of
https://github.com/SK-la/Ez2Lazer.git
synced 2026-03-13 11:20:28 +00:00
Merge remote-tracking branch 'ppy-osu/master' into locmain
# Conflicts: # osu.Game.Rulesets.Mania/ManiaRuleset.cs # osu.Game/osu.Game.csproj
This commit is contained in:
@@ -185,15 +185,20 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.LargeTickMiss,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.SmallTickMiss,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.LAsEzExtensions.Background;
|
||||
using osu.Game.LAsEzExtensions.Statistics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
@@ -436,7 +435,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v);
|
||||
}
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
@@ -445,13 +444,11 @@ namespace osu.Game.Rulesets.Mania
|
||||
HitResult.Good,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
HitResult.ComboBreak,
|
||||
HitResult.Miss,
|
||||
HitResult.Poor,
|
||||
|
||||
// HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as
|
||||
// it would be a bit redundant to show this to the user.
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.ComboBreak,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -286,19 +286,24 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override IRulesetConfigManager CreateConfig(SettingsStore? settings) => new OsuRulesetConfigManager(settings, RulesetInfo);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
HitResult.Meh,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.LargeTickHit,
|
||||
HitResult.LargeTickMiss,
|
||||
HitResult.SmallTickHit,
|
||||
HitResult.SmallTickMiss,
|
||||
HitResult.SliderTailHit,
|
||||
HitResult.SmallBonus,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -231,15 +231,18 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
public override RulesetSettingsSubsection CreateSettings() => new TaikoSettingsSubsection(this);
|
||||
|
||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
||||
public override IEnumerable<HitResult> GetValidHitResults()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
HitResult.Great,
|
||||
HitResult.Ok,
|
||||
HitResult.Miss,
|
||||
|
||||
HitResult.SmallBonus,
|
||||
HitResult.LargeBonus,
|
||||
HitResult.IgnoreHit,
|
||||
HitResult.IgnoreMiss,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
@@ -116,6 +117,69 @@ namespace osu.Game.Tests.Database
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestFakedRulesetIdIsDetected()
|
||||
{
|
||||
RunTestWithRealm((realm, storage) =>
|
||||
{
|
||||
LoadTestRuleset.HasImplementations = true;
|
||||
LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION;
|
||||
|
||||
var ruleset = new LoadTestRuleset();
|
||||
string rulesetShortName = ruleset.RulesetInfo.ShortName;
|
||||
|
||||
realm.Write(r => r.Add(new RulesetInfo(rulesetShortName, ruleset.RulesetInfo.Name, ruleset.RulesetInfo.InstantiationInfo, 0)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(rulesetShortName)!.Available), Is.True);
|
||||
|
||||
// Availability is updated on construction of a RealmRulesetStore
|
||||
using var _ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(rulesetShortName)!.Available), Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleRulesetWithSameOnlineIdsAreDetected()
|
||||
{
|
||||
RunTestWithRealm((realm, storage) =>
|
||||
{
|
||||
LoadTestRuleset.HasImplementations = true;
|
||||
LoadTestRuleset.Version = Ruleset.CURRENT_RULESET_API_VERSION;
|
||||
LoadTestRuleset.OnlineID = 2;
|
||||
|
||||
var first = new LoadTestRuleset();
|
||||
var second = new CatchRuleset();
|
||||
|
||||
realm.Write(r => r.Add(new RulesetInfo(first.ShortName, first.RulesetInfo.Name, first.RulesetInfo.InstantiationInfo, first.RulesetInfo.OnlineID)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
realm.Write(r => r.Add(new RulesetInfo(second.ShortName, second.RulesetInfo.Name, second.RulesetInfo.InstantiationInfo, second.RulesetInfo.OnlineID)
|
||||
{
|
||||
Available = true,
|
||||
}));
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(first.ShortName)!.Available), Is.True);
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.True);
|
||||
|
||||
// Availability is updated on construction of a RealmRulesetStore
|
||||
using var _ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(first.ShortName)!.Available), Is.False);
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.False);
|
||||
|
||||
realm.Write(r => r.Remove(r.Find<RulesetInfo>(first.ShortName)!));
|
||||
|
||||
using var __ = new RealmRulesetStore(realm, storage);
|
||||
|
||||
Assert.That(realm.Run(r => r.Find<RulesetInfo>(second.ShortName)!.Available), Is.True);
|
||||
});
|
||||
}
|
||||
|
||||
private class LoadTestRuleset : Ruleset
|
||||
{
|
||||
public override string RulesetAPIVersionSupported => Version;
|
||||
@@ -124,6 +188,13 @@ namespace osu.Game.Tests.Database
|
||||
|
||||
public static string Version { get; set; } = CURRENT_RULESET_API_VERSION;
|
||||
|
||||
public static int OnlineID { get; set; } = -1;
|
||||
|
||||
public LoadTestRuleset()
|
||||
{
|
||||
RulesetInfo.OnlineID = OnlineID;
|
||||
}
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
if (!HasImplementations)
|
||||
|
||||
@@ -526,7 +526,7 @@ namespace osu.Game.Tests.Rulesets.Scoring
|
||||
// ReSharper disable once MemberHidesStaticFromOuterClass
|
||||
private class TestRuleset : Ruleset
|
||||
{
|
||||
protected override IEnumerable<HitResult> GetValidHitResults() => new[] { HitResult.Great };
|
||||
public override IEnumerable<HitResult> GetValidHitResults() => new[] { HitResult.Great };
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => throw new NotImplementedException();
|
||||
|
||||
|
||||
61
osu.Game.Tests/Visual/Online/TestSceneClickableTeamFlag.cs
Normal file
61
osu.Game.Tests/Visual/Online/TestSceneClickableTeamFlag.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Users.Drawables;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public partial class TestSceneClickableTeamFlag : OsuManualInputManagerTestScene
|
||||
{
|
||||
[SetUpSteps]
|
||||
public void SetUp()
|
||||
{
|
||||
AddStep("create flags", () =>
|
||||
{
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Spacing = new Vector2(10f),
|
||||
Children = new[]
|
||||
{
|
||||
new ClickableTeamFlag(
|
||||
new APITeam
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Collective Wangs",
|
||||
ShortName = "WANG",
|
||||
}, showTooltipOnHover: false) { Width = 300, Height = 150 },
|
||||
new ClickableTeamFlag(
|
||||
new APITeam
|
||||
{
|
||||
Id = 2,
|
||||
Name = "mom?",
|
||||
ShortName = "MOM",
|
||||
FlagUrl = "https://assets.ppy.sh/teams/flag/1/b46fb10dbfd8a35dc50e6c00296c0dc6172dffc3ed3d3a4b379277ba498399fe.png",
|
||||
}, showTooltipOnHover: true) { Width = 300, Height = 150 },
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHover()
|
||||
{
|
||||
AddStep("hover flag with no tooltip", () => InputManager.MoveMouseTo(this.ChildrenOfType<ClickableTeamFlag>().ElementAt(0)));
|
||||
AddWaitStep("wait", 3);
|
||||
AddAssert("tooltip is not visible", () => this.ChildrenOfType<OsuTooltipContainer.OsuTooltip>().FirstOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Hidden));
|
||||
AddStep("hover flag with tooltip", () => InputManager.MoveMouseTo(this.ChildrenOfType<ClickableTeamFlag>().ElementAt(1)));
|
||||
AddUntilStep("wait for tooltip to show", () => this.ChildrenOfType<OsuTooltipContainer.OsuTooltip>().FirstOrDefault()?.State.Value, () => Is.EqualTo(Visibility.Visible));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
osu.Game.Tests/Visual/Online/TestSceneUpdateableTeamFlag.cs
Normal file
43
osu.Game.Tests/Visual/Online/TestSceneUpdateableTeamFlag.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Users.Drawables;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
[TestFixture]
|
||||
public partial class TestSceneUpdateableTeamFlag : OsuTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestHideOnNull()
|
||||
{
|
||||
UpdateableTeamFlag flag = null!;
|
||||
|
||||
AddStep("create flag with team", () => Child = flag = new UpdateableTeamFlag(createTeam(), hideOnNull: true) { Width = 300, Height = 150 });
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
AddStep("set team to null", () => flag.Team = null);
|
||||
AddAssert("flag is not present", () => flag.IsPresent, () => Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DontHideOnNull()
|
||||
{
|
||||
UpdateableTeamFlag flag = null!;
|
||||
|
||||
AddStep("create flag with team", () => Child = flag = new UpdateableTeamFlag(createTeam(), hideOnNull: false) { Width = 300, Height = 150 });
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
AddStep("set team to null", () => flag.Team = null);
|
||||
AddAssert("flag is present", () => flag.IsPresent, () => Is.True);
|
||||
}
|
||||
|
||||
private static APITeam createTeam() => new APITeam
|
||||
{
|
||||
Id = 2,
|
||||
Name = "mom?",
|
||||
ShortName = "MOM",
|
||||
FlagUrl = @"https://assets.ppy.sh/teams/flag/1/b46fb10dbfd8a35dc50e6c00296c0dc6172dffc3ed3d3a4b379277ba498399fe.png",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace osu.Game.Database
|
||||
|
||||
var beatmap = new Beatmap();
|
||||
|
||||
HitResult maxRulesetJudgement = ruleset.GetHitResults().First().result;
|
||||
HitResult maxRulesetJudgement = ruleset.GetHitResultsForDisplay().First().result;
|
||||
|
||||
// This is a list of all results, ordered from best to worst.
|
||||
// We are constructing a "best possible" score from the statistics provided because it's the best we can do.
|
||||
|
||||
@@ -18,6 +18,6 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
public string ShortName { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty(@"flag_url")]
|
||||
public string FlagUrl = string.Empty;
|
||||
public string? FlagUrl = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
|
||||
var ruleset = scores.First().Ruleset.CreateInstance();
|
||||
|
||||
foreach (var resultGroup in ruleset.GetHitResults().GroupBy(r => r.displayName))
|
||||
foreach (var resultGroup in ruleset.GetHitResultsForDisplay().GroupBy(r => r.displayName))
|
||||
{
|
||||
if (!resultGroup.Any(r => allScoreStatistics.Contains(r.result)))
|
||||
continue;
|
||||
|
||||
@@ -93,6 +93,12 @@ namespace osu.Game.Rulesets
|
||||
$"Ruleset API version is too old (was {instance.RulesetAPIVersionSupported}, expected {Ruleset.CURRENT_RULESET_API_VERSION})");
|
||||
}
|
||||
|
||||
if (r.OnlineID != instanceInfo.OnlineID)
|
||||
throw new InvalidOperationException($@"Online ID mismatch for ruleset {r.ShortName}: database has {r.OnlineID}, constructed instance has {instanceInfo.OnlineID}");
|
||||
|
||||
if (r.OnlineID > 0 && rulesets.Any(otherRuleset => otherRuleset.ShortName != r.ShortName && otherRuleset.OnlineID == r.OnlineID))
|
||||
throw new InvalidOperationException($@"Ruleset {r.ShortName} shares online ID {r.OnlineID} with another ruleset");
|
||||
|
||||
// If a ruleset isn't up-to-date with the API, it could cause a crash at an arbitrary point of execution.
|
||||
// To eagerly handle cases of missing implementations, enumerate all types here and mark as non-available on throw.
|
||||
resolvedType.Assembly.GetTypes();
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
@@ -343,13 +344,17 @@ namespace osu.Game.Rulesets
|
||||
public virtual StatisticItem[] CreateStatisticsForScore(ScoreInfo score, IBeatmap playableBeatmap) => Array.Empty<StatisticItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Get all valid <see cref="HitResult"/>s for this ruleset.
|
||||
/// Generally used for results display purposes, where it can't be determined if zero-count means the user has not achieved any or the type is not used by this ruleset.
|
||||
/// Get all <see cref="HitResult"/>s for this ruleset which are important enough to displayed to the end user.
|
||||
/// Used for results display purposes, where it can't be determined if zero-count means the user has not achieved any or the type is not used by this ruleset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="HitResult.Miss"/> is implicitly included. Special types like <see cref="HitResult.IgnoreHit"/> are not returned by this method.
|
||||
/// Values are returned as ordered by <see cref="OrderAttribute"/>.
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// All valid <see cref="HitResult"/>s along with a display-friendly name.
|
||||
/// All relevant <see cref="HitResult"/>s along with a display-friendly name.
|
||||
/// </returns>
|
||||
public IEnumerable<(HitResult result, LocalisableString displayName)> GetHitResults()
|
||||
public IEnumerable<(HitResult result, LocalisableString displayName)> GetHitResultsForDisplay()
|
||||
{
|
||||
var validResults = GetValidHitResults();
|
||||
|
||||
@@ -362,6 +367,7 @@ namespace osu.Game.Rulesets
|
||||
case HitResult.None:
|
||||
case HitResult.IgnoreHit:
|
||||
case HitResult.IgnoreMiss:
|
||||
case HitResult.ComboBreak:
|
||||
// display is handled as a completion count with corresponding "hit" type.
|
||||
case HitResult.LargeTickMiss:
|
||||
case HitResult.SmallTickMiss:
|
||||
@@ -375,12 +381,10 @@ namespace osu.Game.Rulesets
|
||||
|
||||
/// <summary>
|
||||
/// Get all valid <see cref="HitResult"/>s for this ruleset.
|
||||
/// Generally used for results display purposes, where it can't be determined if zero-count means the user has not achieved any or the type is not used by this ruleset.
|
||||
/// Used for strict validation purposes. The ruleset should return ALL applicable <see cref="HitResult"/> types here
|
||||
/// (except <see cref="HitResult.None"/> and obsolete types).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <see cref="HitResult.Miss"/> is implicitly included. Special types like <see cref="HitResult.IgnoreHit"/> are ignored even when specified.
|
||||
/// </remarks>
|
||||
protected virtual IEnumerable<HitResult> GetValidHitResults() => EnumExtensions.GetValuesInOrder<HitResult>();
|
||||
public virtual IEnumerable<HitResult> GetValidHitResults() => EnumExtensions.GetValuesInOrder<HitResult>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a display friendly name for the specified result type.
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace osu.Game.Scoring.Legacy
|
||||
var scoreProcessor = rulesetInstance.CreateScoreProcessor();
|
||||
|
||||
// Populate the maximum statistics.
|
||||
HitResult maxBasicResult = rulesetInstance.GetHitResults()
|
||||
HitResult maxBasicResult = rulesetInstance.GetHitResultsForDisplay()
|
||||
.Select(h => h.result)
|
||||
.Where(h => h.IsBasic()).MaxBy(scoreProcessor.GetBaseScoreForResult);
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace osu.Game.Scoring
|
||||
|
||||
public IEnumerable<HitResultDisplayStatistic> GetStatisticsForDisplay()
|
||||
{
|
||||
foreach (var r in Ruleset.CreateInstance().GetHitResults())
|
||||
foreach (var r in Ruleset.CreateInstance().GetHitResultsForDisplay())
|
||||
{
|
||||
int value = Statistics.GetValueOrDefault(r.result);
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
|
||||
userFlag.CountryCode = user?.CountryCode ?? default;
|
||||
teamFlagContainer.Child = new UpdateableTeamFlag(user?.Team)
|
||||
{
|
||||
Size = new Vector2(40, 20)
|
||||
Size = new Vector2(40, 20),
|
||||
};
|
||||
username.Text = user?.Username ?? string.Empty;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play.HUD.JudgementCounter
|
||||
{
|
||||
// Due to weirdness in judgements, some results have the same name and should be aggregated for display purposes.
|
||||
// There's only one case of this right now ("slider end").
|
||||
foreach (var group in ruleset.Value.CreateInstance().GetHitResults().GroupBy(r => r.displayName))
|
||||
foreach (var group in ruleset.Value.CreateInstance().GetHitResultsForDisplay().GroupBy(r => r.displayName))
|
||||
{
|
||||
var judgementCount = new JudgementCount
|
||||
{
|
||||
|
||||
52
osu.Game/Users/Drawables/ClickableTeamFlag.cs
Normal file
52
osu.Game/Users/Drawables/ClickableTeamFlag.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Users.Drawables
|
||||
{
|
||||
public partial class ClickableTeamFlag : OsuClickableContainer
|
||||
{
|
||||
private readonly APITeam? team;
|
||||
|
||||
[Resolved]
|
||||
private OsuGame? game { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// A clickable flag component for the specified team, with UI sounds and a tooltip.
|
||||
/// </summary>
|
||||
/// <param name="team">The team. A null value will show a placeholder background.</param>
|
||||
/// <param name="showTooltipOnHover">If set to true, the team's name is displayed in the tooltip.</param>
|
||||
public ClickableTeamFlag(APITeam? team, bool showTooltipOnHover = true)
|
||||
{
|
||||
this.team = team;
|
||||
|
||||
if (team == null)
|
||||
return;
|
||||
|
||||
Action = openProfile;
|
||||
|
||||
if (showTooltipOnHover)
|
||||
TooltipText = team.Name;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
LoadComponentAsync(new DrawableTeamFlag(team) { RelativeSizeAxes = Axes.Both }, Add);
|
||||
}
|
||||
|
||||
private void openProfile()
|
||||
{
|
||||
if (team != null)
|
||||
game?.OpenUrlExternally($@"{api.Endpoints.WebsiteUrl}/teams/{team.Id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
53
osu.Game/Users/Drawables/DrawableTeamFlag.cs
Normal file
53
osu.Game/Users/Drawables/DrawableTeamFlag.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Users.Drawables
|
||||
{
|
||||
[LongRunningLoad]
|
||||
public partial class DrawableTeamFlag : CompositeDrawable
|
||||
{
|
||||
private readonly APITeam? team;
|
||||
|
||||
private readonly Sprite sprite;
|
||||
|
||||
/// <summary>
|
||||
/// A simple, non-interactable flag sprite for the specified user.
|
||||
/// </summary>
|
||||
/// <param name="team">The team. A null value will show a placeholder background.</param>
|
||||
public DrawableTeamFlag(APITeam? team)
|
||||
{
|
||||
this.team = team;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Colour4.FromHex("333"),
|
||||
},
|
||||
sprite = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
FillMode = FillMode.Fit,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LargeTextureStore textures)
|
||||
{
|
||||
if (team != null)
|
||||
sprite.Texture = textures.Get(team.FlagUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
|
||||
namespace osu.Game.Users.Drawables
|
||||
@@ -31,10 +23,52 @@ namespace osu.Game.Users.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public new bool Masking
|
||||
{
|
||||
get => base.Masking;
|
||||
set => base.Masking = value;
|
||||
}
|
||||
|
||||
private bool useDefaultRadius = true;
|
||||
|
||||
public new float CornerRadius
|
||||
{
|
||||
get => base.CornerRadius;
|
||||
set
|
||||
{
|
||||
useDefaultRadius = false;
|
||||
base.CornerRadius = value;
|
||||
}
|
||||
}
|
||||
|
||||
public new EdgeEffectParameters EdgeEffect
|
||||
{
|
||||
get => base.EdgeEffect;
|
||||
set => base.EdgeEffect = value;
|
||||
}
|
||||
|
||||
protected override double LoadDelay => 200;
|
||||
|
||||
public UpdateableTeamFlag(APITeam? team = null)
|
||||
private readonly bool isInteractive;
|
||||
private readonly bool hideOnNull;
|
||||
private readonly bool showTooltipOnHover;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new UpdateableTeamFlag.
|
||||
/// </summary>
|
||||
/// <param name="team">The initial team to display.</param>
|
||||
/// <param name="isInteractive">If set to true, hover/click sounds will play and clicking the flag will open the team's profile.</param>
|
||||
/// <param name="showTooltipOnHover">
|
||||
/// If set to true, the team's name is displayed in the tooltip.
|
||||
/// Only has an effect if <see cref="isInteractive"/> is true.
|
||||
/// </param>
|
||||
/// <param name="hideOnNull">Whether to hide the flag when the provided team is null.</param>
|
||||
public UpdateableTeamFlag(APITeam? team = null, bool isInteractive = true, bool hideOnNull = true, bool showTooltipOnHover = true)
|
||||
{
|
||||
this.isInteractive = isInteractive;
|
||||
this.hideOnNull = hideOnNull;
|
||||
this.showTooltipOnHover = showTooltipOnHover;
|
||||
|
||||
Team = team;
|
||||
|
||||
Masking = true;
|
||||
@@ -42,69 +76,33 @@ namespace osu.Game.Users.Drawables
|
||||
|
||||
protected override Drawable? CreateDrawable(APITeam? team)
|
||||
{
|
||||
if (team == null)
|
||||
if (team == null && hideOnNull)
|
||||
return Empty();
|
||||
|
||||
return new TeamFlag(team) { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
if (isInteractive)
|
||||
{
|
||||
return new ClickableTeamFlag(team, showTooltipOnHover)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
}
|
||||
|
||||
// Generally we just want team flags to disappear if the user doesn't have one.
|
||||
// This also handles fill flow cases and avoids spacing being added for non-displaying flags.
|
||||
public override bool IsPresent => base.IsPresent && Team != null;
|
||||
return new DrawableTeamFlag(team)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
CornerRadius = DrawHeight / 8;
|
||||
if (useDefaultRadius)
|
||||
base.CornerRadius = DrawHeight / 8;
|
||||
}
|
||||
|
||||
[LongRunningLoad]
|
||||
public partial class TeamFlag : CompositeDrawable, IHasTooltip
|
||||
{
|
||||
private readonly APITeam team;
|
||||
|
||||
public LocalisableString TooltipText { get; }
|
||||
|
||||
[Resolved]
|
||||
private OsuGame? game { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
public TeamFlag(APITeam team)
|
||||
{
|
||||
this.team = team;
|
||||
TooltipText = team.Name;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LargeTextureStore textures)
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new HoverClickSounds(),
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Colour4.FromHex("333"),
|
||||
},
|
||||
new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = textures.Get(team.FlagUrl),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
FillMode = FillMode.Fit,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
game?.OpenUrlExternally($"{api.Endpoints.WebsiteUrl}/teams/{team.Id}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Generally we just want team flags to disappear if the user doesn't have one.
|
||||
// This also handles fill flow cases and avoids spacing being added for non-displaying flags.
|
||||
public override bool IsPresent => base.IsPresent && (Team != null || !hideOnNull);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="20.1.0" />
|
||||
<!-- <PackageReference Include="ppy.osu.Framework" Version="2026.209.0" />-->
|
||||
<!-- <PackageReference Include="ppy.osu.Game.Resources" Version="2026.123.0" />-->
|
||||
<PackageReference Include="Sentry" Version="5.1.1" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
<PackageReference Include="SharpCompress" Version="0.39.0" />
|
||||
|
||||
Reference in New Issue
Block a user