1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 16:32:54 +08:00

Merge pull request #5042 from iiSaLMaN/use-modelbackeddrawable

Use ModelBackedDrawables for Flags, Ranks and Avatars
This commit is contained in:
Dan Balasescu 2019-06-21 14:38:00 +09:00 committed by GitHub
commit 554b451e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 232 additions and 201 deletions

View File

@ -3,72 +3,44 @@
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Scoring;
using System;
namespace osu.Game.Online.Leaderboards
{
public class DrawableRank : Container
public class DrawableRank : Sprite
{
private readonly Sprite rankSprite;
private TextureStore textures;
public ScoreRank Rank { get; private set; }
private readonly ScoreRank rank;
public DrawableRank(ScoreRank rank)
{
Rank = rank;
Children = new Drawable[]
{
rankSprite = new Sprite
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fit
},
};
this.rank = rank;
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
[BackgroundDependencyLoader(true)]
private void load(TextureStore ts)
{
this.textures = textures;
updateTexture();
if (ts == null)
throw new ArgumentNullException(nameof(ts));
Texture = ts.Get($@"Grades/{getTextureName()}");
}
private void updateTexture()
private string getTextureName()
{
string textureName;
switch (Rank)
switch (rank)
{
default:
textureName = Rank.GetDescription();
break;
return rank.GetDescription();
case ScoreRank.SH:
textureName = "SPlus";
break;
return "SPlus";
case ScoreRank.XH:
textureName = "SSPlus";
break;
return "SSPlus";
}
rankSprite.Texture = textures.Get($@"Grades/{textureName}");
}
public void UpdateRank(ScoreRank newRank)
{
Rank = newRank;
if (LoadState >= LoadState.Ready)
updateTexture();
}
}
}

View File

@ -17,7 +17,7 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;
@ -65,7 +65,7 @@ namespace osu.Game.Online.Leaderboards
statisticsLabels = GetStatistics(score).Select(s => new ScoreComponentLabel(s)).ToList();
Avatar innerAvatar;
DrawableAvatar innerAvatar;
Children = new Drawable[]
{
@ -112,7 +112,7 @@ namespace osu.Game.Online.Leaderboards
Children = new[]
{
avatar = new DelayedLoadWrapper(
innerAvatar = new Avatar(user)
innerAvatar = new DrawableAvatar(user)
{
RelativeSizeAxes = Axes.Both,
CornerRadius = corner_radius,
@ -157,7 +157,7 @@ namespace osu.Game.Online.Leaderboards
Masking = true,
Children = new Drawable[]
{
new DrawableFlag(user.Country)
new UpdateableFlag(user.Country)
{
Width = 30,
RelativeSizeAxes = Axes.Y,
@ -193,7 +193,7 @@ namespace osu.Game.Online.Leaderboards
Size = new Vector2(40f, 20f),
Children = new[]
{
scoreRank = new DrawableRank(score.Rank)
scoreRank = new UpdateableRank(score.Rank)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,

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;
using osu.Framework.Graphics.Containers;
using osu.Game.Scoring;
namespace osu.Game.Online.Leaderboards
{
public class UpdateableRank : ModelBackedDrawable<ScoreRank>
{
public ScoreRank Rank
{
get => Model;
set => Model = value;
}
public UpdateableRank(ScoreRank rank)
{
Rank = rank;
}
protected override Drawable CreateDrawable(ScoreRank rank) => new DrawableRank(rank)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fit,
};
}
}

View File

@ -6,7 +6,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;
using osu.Framework.Graphics.Effects;

View File

@ -13,7 +13,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Online.Leaderboards;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;
@ -103,7 +103,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Text = $"#{index + 1}",
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold)
},
new DrawableRank(score.Rank)
new UpdateableRank(score.Rank)
{
Size = new Vector2(30, 20)
},
@ -135,7 +135,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Spacing = new Vector2(5, 0),
Children = new Drawable[]
{
new DrawableFlag(score.User.Country) { Size = new Vector2(20, 13) },
new UpdateableFlag(score.User.Country)
{
Size = new Vector2(20, 13),
ShowPlaceholderOnNull = false,
},
username
}
},

View File

@ -13,7 +13,7 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Leaderboards;
using osu.Game.Scoring;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;
@ -22,11 +22,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
public class TopScoreUserSection : CompositeDrawable
{
private readonly SpriteText rankText;
private readonly DrawableRank rank;
private readonly UpdateableRank rank;
private readonly UpdateableAvatar avatar;
private readonly LinkFlowContainer usernameText;
private readonly SpriteText date;
private readonly DrawableFlag flag;
private readonly UpdateableFlag flag;
public TopScoreUserSection()
{
@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Text = "#1",
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true)
},
rank = new DrawableRank(ScoreRank.D)
rank = new UpdateableRank(ScoreRank.D)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -67,6 +67,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Offset = new Vector2(0, 2),
Radius = 1,
},
ShowGuestOnNull = false,
},
new FillFlowContainer
{
@ -89,11 +90,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold)
},
flag = new DrawableFlag
flag = new UpdateableFlag
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Size = new Vector2(20, 13),
ShowPlaceholderOnNull = false,
},
}
}
@ -121,7 +123,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
usernameText.Clear();
usernameText.AddUserLink(value.User);
rank.UpdateRank(value.Rank);
rank.Rank = value.Rank;
}
}
}

View File

@ -10,7 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
using osu.Game.Online.Chat;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
namespace osu.Game.Overlays.Chat.Tabs
@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Chat.Tabs
if (value.Type != ChannelType.PM)
throw new ArgumentException("Argument value needs to have the targettype user!");
Avatar avatar;
DrawableAvatar avatar;
AddRange(new Drawable[]
{
@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Chat.Tabs
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Masking = true,
Child = new DelayedLoadWrapper(avatar = new Avatar(value.Users.First())
Child = new DelayedLoadWrapper(avatar = new DrawableAvatar(value.Users.First())
{
RelativeSizeAxes = Axes.Both,
OpenOnClick = { Value = false },

View File

@ -200,7 +200,7 @@ namespace osu.Game.Overlays.Profile.Header
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
new DrawableRank(rank)
new UpdateableRank(rank)
{
RelativeSizeAxes = Axes.X,
Height = 30,

View File

@ -12,6 +12,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
namespace osu.Game.Overlays.Profile.Header
@ -27,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Header
private OsuSpriteText usernameText;
private ExternalLinkButton openUserExternally;
private OsuSpriteText titleText;
private DrawableFlag userFlag;
private UpdateableFlag userFlag;
private OsuSpriteText userCountryText;
private FillFlowContainer userStats;
@ -51,7 +52,7 @@ namespace osu.Game.Overlays.Profile.Header
AutoSizeAxes = Axes.X,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Children = new[]
Children = new Drawable[]
{
avatar = new UpdateableAvatar
{
@ -59,6 +60,7 @@ namespace osu.Game.Overlays.Profile.Header
Masking = true,
CornerRadius = avatar_size * 0.25f,
OpenOnClick = { Value = false },
ShowGuestOnNull = false,
},
new Container
{
@ -115,9 +117,10 @@ namespace osu.Game.Overlays.Profile.Header
Margin = new MarginPadding { Top = 5 },
Children = new Drawable[]
{
userFlag = new DrawableFlag
userFlag = new UpdateableFlag
{
Size = new Vector2(30, 20)
Size = new Vector2(30, 20),
ShowPlaceholderOnNull = false,
},
userCountryText = new OsuSpriteText
{

View File

@ -59,7 +59,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
modsContainer.Add(new ModIcon(mod) { Scale = new Vector2(0.5f) });
}
protected override Drawable CreateLeftVisual() => new DrawableRank(Score.Rank)
protected override Drawable CreateLeftVisual() => new UpdateableRank(Score.Rank)
{
RelativeSizeAxes = Axes.Y,
Width = 60,

View File

@ -58,7 +58,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
switch (activity.Type)
{
case RecentActivityType.Rank:
return new DrawableRank(activity.ScoreRank)
return new UpdateableRank(activity.ScoreRank)
{
RelativeSizeAxes = Axes.Y,
Width = 60,

View File

@ -8,6 +8,7 @@ using osu.Framework.Graphics.Effects;
using osu.Game.Graphics;
using osu.Game.Online.API;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;

View File

@ -8,7 +8,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
namespace osu.Game.Screens.Multi.Lounge.Components
@ -79,7 +79,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components
hostText.AddText("hosted by ");
hostText.AddUserLink(host.NewValue, s => s.Font = s.Font.With(Typeface.Exo, weight: FontWeight.Bold, italics: true));
flagContainer.Child = new DrawableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both };
flagContainer.Child = new UpdateableFlag(host.NewValue.Country) { RelativeSizeAxes = Axes.Both };
}
}, true);

View File

@ -19,6 +19,7 @@ using osu.Game.Online.API.Requests;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Multi.Components;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
using osuTK.Graphics;

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Users;
using osu.Game.Users.Drawables;
using osuTK;
namespace osu.Game.Screens.Multi.Match.Components

View File

@ -74,7 +74,7 @@ namespace osu.Game.Screens.Ranking.Pages
RelativeSizeAxes = Axes.X,
Height = user_header_height,
},
new DrawableRank(Score.Rank)
new UpdateableRank(Score.Rank)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,

View File

@ -1,14 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using Newtonsoft.Json;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Users
{
@ -26,54 +19,4 @@ namespace osu.Game.Users
[JsonProperty(@"code")]
public string FlagName;
}
public class DrawableFlag : Container, IHasTooltip
{
private readonly Sprite sprite;
private TextureStore textures;
private Country country;
public Country Country
{
get => country;
set
{
if (value == country)
return;
country = value;
if (LoadState >= LoadState.Ready)
sprite.Texture = getFlagTexture();
}
}
public string TooltipText => country?.FullName;
public DrawableFlag(Country country = null)
{
this.country = country;
Children = new Drawable[]
{
sprite = new Sprite
{
RelativeSizeAxes = Axes.Both,
},
};
}
[BackgroundDependencyLoader]
private void load(TextureStore ts)
{
if (ts == null)
throw new ArgumentNullException(nameof(ts));
textures = ts;
sprite.Texture = getFlagTexture();
}
private Texture getFlagTexture() => textures.Get($@"Flags/{country?.FlagName ?? @"__"}");
}
}

View File

@ -11,9 +11,9 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Events;
using osu.Game.Graphics.Containers;
namespace osu.Game.Users
namespace osu.Game.Users.Drawables
{
public class Avatar : Container
public class DrawableAvatar : Container
{
/// <summary>
/// Whether to open the user's profile when clicked.
@ -29,7 +29,7 @@ namespace osu.Game.Users
/// An avatar for specified user.
/// </summary>
/// <param name="user">The user. A null value will get a placeholder avatar.</param>
public Avatar(User user = null)
public DrawableAvatar(User user = null)
{
this.user = user;
}

View File

@ -0,0 +1,32 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Users.Drawables
{
public class DrawableFlag : Sprite, IHasTooltip
{
private readonly Country country;
public string TooltipText => country?.FullName;
public DrawableFlag(Country country)
{
this.country = country;
}
[BackgroundDependencyLoader]
private void load(TextureStore ts)
{
if (ts == null)
throw new ArgumentNullException(nameof(ts));
Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}");
}
}
}

View File

@ -0,0 +1,71 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
namespace osu.Game.Users.Drawables
{
/// <summary>
/// An avatar which can update to a new user when needed.
/// </summary>
public class UpdateableAvatar : ModelBackedDrawable<User>
{
public User User
{
get => Model;
set => Model = value;
}
public new bool Masking
{
get => base.Masking;
set => base.Masking = value;
}
public new float CornerRadius
{
get => base.CornerRadius;
set => base.CornerRadius = value;
}
public new EdgeEffectParameters EdgeEffect
{
get => base.EdgeEffect;
set => base.EdgeEffect = value;
}
/// <summary>
/// Whether to show a default guest representation on null user (as opposed to nothing).
/// </summary>
public bool ShowGuestOnNull = true;
/// <summary>
/// Whether to open the user's profile when clicked.
/// </summary>
public readonly BindableBool OpenOnClick = new BindableBool(true);
public UpdateableAvatar(User user = null)
{
User = user;
}
protected override Drawable CreateDrawable(User user)
{
if (user == null && !ShowGuestOnNull)
return null;
var avatar = new DrawableAvatar(user)
{
RelativeSizeAxes = Axes.Both,
};
avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint);
avatar.OpenOnClick.BindTo(OpenOnClick);
return avatar;
}
}
}

View File

@ -0,0 +1,38 @@
// 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;
namespace osu.Game.Users.Drawables
{
public class UpdateableFlag : ModelBackedDrawable<Country>
{
public Country Country
{
get => Model;
set => Model = value;
}
/// <summary>
/// Whether to show a place holder on null country.
/// </summary>
public bool ShowPlaceholderOnNull = true;
public UpdateableFlag(Country country = null)
{
Country = country;
}
protected override Drawable CreateDrawable(Country country)
{
if (country == null && !ShowPlaceholderOnNull)
return null;
return new DrawableFlag(country)
{
RelativeSizeAxes = Axes.Both,
};
}
}
}

View File

@ -1,69 +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.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Users
{
/// <summary>
/// An avatar which can update to a new user when needed.
/// </summary>
public class UpdateableAvatar : Container
{
private Drawable displayedAvatar;
private User user;
/// <summary>
/// Whether to show a default guest representation on null user (as opposed to nothing).
/// </summary>
public bool ShowGuestOnNull = true;
public User User
{
get => user;
set
{
if (user?.Id == value?.Id)
return;
user = value;
if (IsLoaded)
updateAvatar();
}
}
/// <summary>
/// Whether to open the user's profile when clicked.
/// </summary>
public readonly BindableBool OpenOnClick = new BindableBool(true);
protected override void LoadComplete()
{
base.LoadComplete();
updateAvatar();
}
private void updateAvatar()
{
displayedAvatar?.FadeOut(300);
displayedAvatar?.Expire();
if (user != null || ShowGuestOnNull)
{
var avatar = new Avatar(user)
{
RelativeSizeAxes = Axes.Both,
};
avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint);
avatar.OpenOnClick.BindTo(OpenOnClick);
Add(displayedAvatar = new DelayedLoadWrapper(avatar));
}
}
}
}

View File

@ -20,6 +20,7 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics.Containers;
using osu.Game.Overlays.Profile.Header.Components;
using osu.Game.Users.Drawables;
namespace osu.Game.Users
{
@ -137,7 +138,7 @@ namespace osu.Game.Users
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
new DrawableFlag(user.Country)
new UpdateableFlag(user.Country)
{
Width = 30f,
RelativeSizeAxes = Axes.Y,