diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 3e4995482d..fd6a9c7b7b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -174,8 +174,8 @@ namespace osu.Game.Rulesets.Catch.Tests private void addToPlayfield(DrawableCatchHitObject drawable) { - foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToDrawableHitObjects(new[] { drawable }); + foreach (var mod in SelectedMods.Value.OfType()) + mod.ApplyToDrawableHitObject(drawable); drawableRuleset.Playfield.Add(drawable); } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs index cf8b510ab6..f6e8a771ed 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs @@ -92,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Tests var drawable = CreateDrawableHitCircle(circle, auto, hitOffset); - foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToDrawableHitObjects(new[] { drawable }); + foreach (var mod in SelectedMods.Value.OfType()) + mod.ApplyToDrawableHitObject(drawable); return drawable; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs index fc5fcf2358..81902c25af 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSlider.cs @@ -335,8 +335,8 @@ namespace osu.Game.Rulesets.Osu.Tests var drawable = CreateDrawableSlider(slider); - foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToDrawableHitObjects(new[] { drawable }); + foreach (var mod in SelectedMods.Value.OfType()) + mod.ApplyToDrawableHitObject(drawable); drawable.OnNewResult += onNewResult; diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index b21b7a6f4a..2dea9837f3 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -85,8 +85,8 @@ namespace osu.Game.Rulesets.Osu.Tests Scale = new Vector2(0.75f) }; - foreach (var mod in SelectedMods.Value.OfType()) - mod.ApplyToDrawableHitObjects(new[] { drawableSpinner }); + foreach (var mod in SelectedMods.Value.OfType()) + mod.ApplyToDrawableHitObject(drawableSpinner); return drawableSpinner; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs index 3e638c4833..074fb7dbed 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs @@ -1,9 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Bindables; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; @@ -13,7 +11,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObjects + public class OsuModApproachDifferent : Mod, IApplicableToDrawableHitObject { public override string Name => "Approach Different"; public override string Acronym => "AD"; @@ -32,22 +30,19 @@ namespace osu.Game.Rulesets.Osu.Mods [SettingSource("Style", "Change the animation style of the approach circles.", 1)] public Bindable Style { get; } = new Bindable(); - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - drawables.ForEach(drawable => + drawable.ApplyCustomUpdateState += (drawableObject, state) => { - drawable.ApplyCustomUpdateState += (drawableObject, state) => - { - if (!(drawableObject is DrawableHitCircle drawableHitCircle)) return; + if (!(drawableObject is DrawableHitCircle drawableHitCircle)) return; - var hitCircle = drawableHitCircle.HitObject; + var hitCircle = drawableHitCircle.HitObject; - drawableHitCircle.ApproachCircle.ClearTransforms(targetMember: nameof(Scale)); + drawableHitCircle.ApproachCircle.ClearTransforms(targetMember: nameof(Scale)); - using (drawableHitCircle.BeginAbsoluteSequence(hitCircle.StartTime - hitCircle.TimePreempt)) - drawableHitCircle.ApproachCircle.ScaleTo(Scale.Value).ScaleTo(1f, hitCircle.TimePreempt, getEasing(Style.Value)); - }; - }); + using (drawableHitCircle.BeginAbsoluteSequence(hitCircle.StartTime - hitCircle.TimePreempt)) + drawableHitCircle.ApproachCircle.ScaleTo(Scale.Value).ScaleTo(1f, hitCircle.TimePreempt, getEasing(Style.Value)); + }; } private Easing getEasing(AnimationStyle style) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs index 9ae9653e9b..9e71f657ce 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModBarrelRoll.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; @@ -9,22 +8,19 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModBarrelRoll : ModBarrelRoll, IApplicableToDrawableHitObjects + public class OsuModBarrelRoll : ModBarrelRoll, IApplicableToDrawableHitObject { - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ApplyToDrawableHitObject(DrawableHitObject d) { - foreach (var d in drawables) + d.OnUpdate += _ => { - d.OnUpdate += _ => + switch (d) { - switch (d) - { - case DrawableHitCircle circle: - circle.CirclePiece.Rotation = -CurrentRotation; - break; - } - }; - } + case DrawableHitCircle circle: + circle.CirclePiece.Rotation = -CurrentRotation; + break; + } + }; } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs index 77dea5b0dc..e04a30d06c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModClassic.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; using osu.Game.Configuration; @@ -15,7 +14,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModClassic : ModClassic, IApplicableToHitObject, IApplicableToDrawableHitObjects, IApplicableToDrawableRuleset + public class OsuModClassic : ModClassic, IApplicableToHitObject, IApplicableToDrawableHitObject, IApplicableToDrawableRuleset { [SettingSource("No slider head accuracy requirement", "Scores sliders proportionally to the number of ticks hit.")] public Bindable NoSliderHeadAccuracy { get; } = new BindableBool(true); @@ -54,24 +53,21 @@ namespace osu.Game.Rulesets.Osu.Mods osuRuleset.Playfield.HitPolicy = new ObjectOrderedHitPolicy(); } - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ApplyToDrawableHitObject(DrawableHitObject obj) { - foreach (var obj in drawables) + switch (obj) { - switch (obj) - { - case DrawableSlider slider: - slider.Ball.InputTracksVisualSize = !FixedFollowCircleHitArea.Value; - break; + case DrawableSlider slider: + slider.Ball.InputTracksVisualSize = !FixedFollowCircleHitArea.Value; + break; - case DrawableSliderHead head: - head.TrackFollowCircle = !NoSliderHeadMovement.Value; - break; + case DrawableSliderHead head: + head.TrackFollowCircle = !NoSliderHeadMovement.Value; + break; - case DrawableSliderTail tail: - tail.SamplePlaysOnlyOnHit = !AlwaysPlayTailSample.Value; - break; - } + case DrawableSliderTail tail: + tail.SamplePlaysOnlyOnHit = !AlwaysPlayTailSample.Value; + break; } } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs index 683b35f282..300a9d48aa 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -2,8 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; -using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input; @@ -19,7 +17,7 @@ using osuTK; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObjects + public class OsuModFlashlight : ModFlashlight, IApplicableToDrawableHitObject { public override double ScoreMultiplier => 1.12; @@ -31,12 +29,10 @@ namespace osu.Game.Rulesets.Osu.Mods public override Flashlight CreateFlashlight() => flashlight = new OsuFlashlight(); - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ApplyToDrawableHitObject(DrawableHitObject drawable) { - foreach (var s in drawables.OfType()) - { + if (drawable is DrawableSlider s) s.Tracking.ValueChanged += flashlight.OnSliderTrackingChange; - } } public override void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs index b12d735474..c7f4811701 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Utils; @@ -13,7 +12,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModSpunOut : Mod, IApplicableToDrawableHitObjects + public class OsuModSpunOut : Mod, IApplicableToDrawableHitObject { public override string Name => "Spun Out"; public override string Acronym => "SO"; @@ -23,15 +22,12 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 0.9; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) }; - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ApplyToDrawableHitObject(DrawableHitObject hitObject) { - foreach (var hitObject in drawables) + if (hitObject is DrawableSpinner spinner) { - if (hitObject is DrawableSpinner spinner) - { - spinner.HandleUserInput = false; - spinner.OnUpdate += onSpinnerUpdate; - } + spinner.HandleUserInput = false; + spinner.OnUpdate += onSpinnerUpdate; } } diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 971b34fcc4..265d9bf125 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -53,9 +53,8 @@ namespace osu.Game.Overlays.BeatmapSet AutoSizeAxes = Axes.Both, CornerRadius = 4, Masking = true, - Child = avatar = new UpdateableAvatar + Child = avatar = new UpdateableAvatar(showGuestOnNull: false) { - ShowGuestOnNull = false, Size = new Vector2(height), }, EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 9111a0cfc7..736366fb5c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -61,7 +61,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, } }, - avatar = new UpdateableAvatar + avatar = new UpdateableAvatar(showGuestOnNull: false) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -75,7 +75,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Offset = new Vector2(0, 2), Radius = 1, }, - ShowGuestOnNull = false, }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs index 00f46b0035..7c82420e08 100644 --- a/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs +++ b/osu.Game/Overlays/Chat/Tabs/PrivateChannelTabItem.cs @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Chat.Tabs Child = new DelayedLoadWrapper(avatar = new ClickableAvatar(value.Users.First()) { RelativeSizeAxes = Axes.Both, - OpenOnClick = { Value = false }, + OpenOnClick = false, }) { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index e0642d650c..d751424367 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -58,13 +58,11 @@ namespace osu.Game.Overlays.Profile.Header Origin = Anchor.CentreLeft, Children = new Drawable[] { - avatar = new UpdateableAvatar + avatar = new UpdateableAvatar(openOnClick: false, showGuestOnNull: false) { Size = new Vector2(avatar_size), Masking = true, CornerRadius = avatar_size * 0.25f, - OpenOnClick = { Value = false }, - ShowGuestOnNull = false, }, new Container { diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index db4e491d9a..165c095514 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -32,14 +32,13 @@ namespace osu.Game.Overlays.Toolbar Add(new OpaqueBackground { Depth = 1 }); - Flow.Add(avatar = new UpdateableAvatar + Flow.Add(avatar = new UpdateableAvatar(openOnClick: false) { Masking = true, Size = new Vector2(32), Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, CornerRadius = 4, - OpenOnClick = { Value = false }, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs index 5630315770..93055e733d 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs @@ -1,7 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mods @@ -9,13 +11,20 @@ namespace osu.Game.Rulesets.Mods /// /// An interface for s that can be applied to s. /// - public interface IApplicableToDrawableHitObjects : IApplicableMod + public interface IApplicableToDrawableHitObject : IApplicableMod { /// - /// Applies this to a list of s. + /// Applies this to a . /// This will only be invoked with top-level s. Access if adjusting nested objects is necessary. /// - /// The list of s to apply to. + void ApplyToDrawableHitObject(DrawableHitObject drawable); + } + + [Obsolete(@"Use the singular version IApplicableToDrawableHitObject instead.")] // Can be removed 20211216 + public interface IApplicableToDrawableHitObjects : IApplicableToDrawableHitObject + { void ApplyToDrawableHitObjects(IEnumerable drawables); + + void IApplicableToDrawableHitObject.ApplyToDrawableHitObject(DrawableHitObject drawable) => ApplyToDrawableHitObjects(drawable.Yield()); } } diff --git a/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs b/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs index 5b119b5e46..b58ee5ff36 100644 --- a/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs +++ b/osu.Game/Rulesets/Mods/ModWithVisibilityAdjustment.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods /// A which applies visibility adjustments to s /// with an optional increased visibility adjustment depending on the user's "increase first object visibility" setting. /// - public abstract class ModWithVisibilityAdjustment : Mod, IReadFromConfig, IApplicableToBeatmap, IApplicableToDrawableHitObjects + public abstract class ModWithVisibilityAdjustment : Mod, IReadFromConfig, IApplicableToBeatmap, IApplicableToDrawableHitObject { /// /// The first adjustable object. @@ -73,19 +73,16 @@ namespace osu.Game.Rulesets.Mods } } - public virtual void ApplyToDrawableHitObjects(IEnumerable drawables) + public virtual void ApplyToDrawableHitObject(DrawableHitObject dho) { - foreach (var dho in drawables) + dho.ApplyCustomUpdateState += (o, state) => { - dho.ApplyCustomUpdateState += (o, state) => - { - // Increased visibility is applied to the entire first object, including all of its nested hitobjects. - if (IncreaseFirstObjectVisibility.Value && isObjectEqualToOrNestedIn(o.HitObject, FirstObject)) - ApplyIncreasedVisibilityState(o, state); - else - ApplyNormalVisibilityState(o, state); - }; - } + // Increased visibility is applied to the entire first object, including all of its nested hitobjects. + if (IncreaseFirstObjectVisibility.Value && isObjectEqualToOrNestedIn(o.HitObject, FirstObject)) + ApplyIncreasedVisibilityState(o, state); + else + ApplyNormalVisibilityState(o, state); + }; } /// diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index 0ab8b94e3f..8dcc1ca164 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -199,8 +199,11 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); - foreach (var mod in Mods.OfType()) - mod.ApplyToDrawableHitObjects(Playfield.AllHitObjects); + foreach (var mod in Mods.OfType()) + { + foreach (var drawableHitObject in Playfield.AllHitObjects) + mod.ApplyToDrawableHitObject(drawableHitObject); + } } public override void RequestResume(Action continueResume) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b154288dba..52aecb27de 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -356,8 +356,8 @@ namespace osu.Game.Rulesets.UI // This is done before Apply() so that the state is updated once when the hitobject is applied. if (mods != null) { - foreach (var m in mods.OfType()) - m.ApplyToDrawableHitObjects(dho.Yield()); + foreach (var m in mods.OfType()) + m.ApplyToDrawableHitObject(dho); } } diff --git a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs index 9aceb39a27..e531ddb0ec 100644 --- a/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Components/ParticipantsList.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Threading; using osu.Game.Users; @@ -91,7 +90,7 @@ namespace osu.Game.Screens.OnlinePlay.Components }); } - private class UserTile : CompositeDrawable, IHasTooltip + private class UserTile : CompositeDrawable { public User User { @@ -99,8 +98,6 @@ namespace osu.Game.Screens.OnlinePlay.Components set => avatar.User = value; } - public string TooltipText => User?.Username ?? string.Empty; - private readonly UpdateableAvatar avatar; public UserTile() @@ -116,7 +113,7 @@ namespace osu.Game.Screens.OnlinePlay.Components RelativeSizeAxes = Axes.Both, Colour = Color4Extensions.FromHex(@"27252d"), }, - avatar = new UpdateableAvatar { RelativeSizeAxes = Axes.Both }, + avatar = new UpdateableAvatar(showUsernameTooltip: true) { RelativeSizeAxes = Axes.Both }, }; } } diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 0fca9c7c9b..c3bf740108 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; @@ -13,16 +12,32 @@ namespace osu.Game.Users.Drawables { public class ClickableAvatar : Container { + private const string default_tooltip_text = "view profile"; + /// /// Whether to open the user's profile when clicked. /// - public readonly BindableBool OpenOnClick = new BindableBool(true); + public bool OpenOnClick + { + set => clickableArea.Enabled.Value = value; + } + + /// + /// By default, the tooltip will show "view profile" as avatars are usually displayed next to a username. + /// Setting this to true exposes the username via tooltip for special cases where this is not true. + /// + public bool ShowUsernameTooltip + { + set => clickableArea.TooltipText = value ? (user?.Username ?? string.Empty) : default_tooltip_text; + } private readonly User user; [Resolved(CanBeNull = true)] private OsuGame game { get; set; } + private readonly ClickableArea clickableArea; + /// /// A clickable avatar for the specified user, with UI sounds included. /// If is true, clicking will open the user's profile. @@ -31,35 +46,35 @@ namespace osu.Game.Users.Drawables public ClickableAvatar(User user = null) { this.user = user; - } - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) - { - ClickableArea clickableArea; Add(clickableArea = new ClickableArea { RelativeSizeAxes = Axes.Both, Action = openProfile }); + } + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) + { LoadComponentAsync(new DrawableAvatar(user), clickableArea.Add); - - clickableArea.Enabled.BindTo(OpenOnClick); } private void openProfile() { - if (!OpenOnClick.Value) - return; - if (user?.Id > 1) game?.ShowUser(user.Id); } private class ClickableArea : OsuClickableContainer { - public override string TooltipText => Enabled.Value ? @"view profile" : null; + private string tooltip = default_tooltip_text; + + public override string TooltipText + { + get => Enabled.Value ? tooltip : null; + set => tooltip = value; + } protected override bool OnClick(ClickEvent e) { diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs index 927e48cb56..df724404e9 100644 --- a/osu.Game/Users/Drawables/UpdateableAvatar.cs +++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . 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; @@ -45,33 +44,38 @@ namespace osu.Game.Users.Drawables protected override double LoadDelay => 200; - /// - /// Whether to show a default guest representation on null user (as opposed to nothing). - /// - public bool ShowGuestOnNull = true; + private readonly bool openOnClick; + private readonly bool showUsernameTooltip; + private readonly bool showGuestOnNull; /// - /// Whether to open the user's profile when clicked. + /// Construct a new UpdateableAvatar. /// - public readonly BindableBool OpenOnClick = new BindableBool(true); - - public UpdateableAvatar(User user = null) + /// The initial user to display. + /// Whether to open the user's profile when clicked. + /// Whether to show the username rather than "view profile" on the tooltip. + /// Whether to show a default guest representation on null user (as opposed to nothing). + public UpdateableAvatar(User user = null, bool openOnClick = true, bool showUsernameTooltip = false, bool showGuestOnNull = true) { + this.openOnClick = openOnClick; + this.showUsernameTooltip = showUsernameTooltip; + this.showGuestOnNull = showGuestOnNull; + User = user; } protected override Drawable CreateDrawable(User user) { - if (user == null && !ShowGuestOnNull) + if (user == null && !showGuestOnNull) return null; var avatar = new ClickableAvatar(user) { + OpenOnClick = openOnClick, + ShowUsernameTooltip = showUsernameTooltip, RelativeSizeAxes = Axes.Both, }; - avatar.OpenOnClick.BindTo(OpenOnClick); - return avatar; } } diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index 2604815751..24317e6069 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -48,11 +48,7 @@ namespace osu.Game.Users statusIcon.FinishTransforms(); } - protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar - { - User = User, - OpenOnClick = { Value = false } - }; + protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar(User, false); protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country) {