From 8147e67f5337b9bfe6d29cbfc7a6c8bcb0015f7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 Jul 2020 11:53:04 +0900 Subject: [PATCH 01/37] Use static instances in all fallback ControlPoint lookups to reduce allocations --- .../ControlPoints/ControlPointInfo.cs | 16 ++++++------- .../ControlPoints/DifficultyControlPoint.cs | 5 ++++ .../ControlPoints/EffectControlPoint.cs | 6 +++++ .../ControlPoints/TimingControlPoint.cs | 12 ++++++++++ .../Containers/BeatSyncedContainer.cs | 23 ++----------------- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index af6ca24165..49f1052248 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -64,14 +64,14 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time to find the difficulty control point at. /// The difficulty control point. - public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time); + public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time, DifficultyControlPoint.DEFAULT); /// /// Finds the effect control point that is active at . /// /// The time to find the effect control point at. /// The effect control point. - public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time); + public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time, EffectControlPoint.DEFAULT); /// /// Finds the sound control point that is active at . @@ -92,21 +92,21 @@ namespace osu.Game.Beatmaps.ControlPoints /// [JsonIgnore] public double BPMMaximum => - 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength; /// /// Finds the minimum BPM represented by any timing control point. /// [JsonIgnore] public double BPMMinimum => - 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength; /// /// Finds the mode BPM (most common BPM) represented by the control points. /// [JsonIgnore] public double BPMMode => - 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength; + 60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength; /// /// Remove all s and return to a pristine state. @@ -170,12 +170,12 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The list to search. /// The time to find the control point at. - /// The control point to use when is before any control points. If null, a new control point will be constructed. + /// The control point to use when is before any control points. /// The active control point at , or a fallback if none found. - private T binarySearchWithFallback(IReadOnlyList list, double time, T prePoint = null) + private T binarySearchWithFallback(IReadOnlyList list, double time, T fallback) where T : ControlPoint, new() { - return binarySearch(list, time) ?? prePoint ?? new T(); + return binarySearch(list, time) ?? fallback; } /// diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 2448b2b25c..1d38790f87 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -7,6 +7,11 @@ namespace osu.Game.Beatmaps.ControlPoints { public class DifficultyControlPoint : ControlPoint { + public static readonly DifficultyControlPoint DEFAULT = new DifficultyControlPoint + { + SpeedMultiplierBindable = { Disabled = true }, + }; + /// /// The speed multiplier at this control point. /// diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 9b69147468..9e8e3978be 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -7,6 +7,12 @@ namespace osu.Game.Beatmaps.ControlPoints { public class EffectControlPoint : ControlPoint { + public static readonly EffectControlPoint DEFAULT = new EffectControlPoint + { + KiaiModeBindable = { Disabled = true }, + OmitFirstBarLineBindable = { Disabled = true } + }; + /// /// Whether the first bar line of this control point is ignored. /// diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 1927dd6575..c3a32c4410 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -13,6 +13,18 @@ namespace osu.Game.Beatmaps.ControlPoints /// public readonly Bindable TimeSignatureBindable = new Bindable(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple }; + /// + /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing. + /// + private const double default_beat_length = 60000.0 / 60.0; + + public static readonly TimingControlPoint DEFAULT = new TimingControlPoint + { + BeatLength = default_beat_length, + BeatLengthBindable = { Disabled = true }, + TimeSignatureBindable = { Disabled = true } + }; + /// /// The time signature at this control point. /// diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index dd5c41285a..df063f57d5 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -43,14 +43,6 @@ namespace osu.Game.Graphics.Containers /// public double MinimumBeatLength { get; set; } - /// - /// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing. - /// - private const double default_beat_length = 60000.0 / 60.0; - - private TimingControlPoint defaultTiming; - private EffectControlPoint defaultEffect; - protected bool IsBeatSyncedWithTrack { get; private set; } protected override void Update() @@ -81,8 +73,8 @@ namespace osu.Game.Graphics.Containers if (timingPoint == null || !IsBeatSyncedWithTrack) { currentTrackTime = Clock.CurrentTime; - timingPoint = defaultTiming; - effectPoint = defaultEffect; + timingPoint = TimingControlPoint.DEFAULT; + effectPoint = EffectControlPoint.DEFAULT; } double beatLength = timingPoint.BeatLength / Divisor; @@ -116,17 +108,6 @@ namespace osu.Game.Graphics.Containers private void load(IBindable beatmap) { Beatmap.BindTo(beatmap); - - defaultTiming = new TimingControlPoint - { - BeatLength = default_beat_length, - }; - - defaultEffect = new EffectControlPoint - { - KiaiMode = false, - OmitFirstBarLine = false - }; } protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) From 2f16b448ea8619ea6ea8d34231ff94f040702e53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 Jul 2020 12:03:49 +0900 Subject: [PATCH 02/37] Set beatLength inline --- osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index c3a32c4410..9345299c3a 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -20,8 +20,11 @@ namespace osu.Game.Beatmaps.ControlPoints public static readonly TimingControlPoint DEFAULT = new TimingControlPoint { - BeatLength = default_beat_length, - BeatLengthBindable = { Disabled = true }, + BeatLengthBindable = + { + Value = default_beat_length, + Disabled = true + }, TimeSignatureBindable = { Disabled = true } }; From 7250bc351d3068ed767d73cf67a663135119da65 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 Jul 2020 12:06:41 +0900 Subject: [PATCH 03/37] Remove unnecessary new() specification --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 49f1052248..55a04e5ee8 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -173,7 +173,7 @@ namespace osu.Game.Beatmaps.ControlPoints /// The control point to use when is before any control points. /// The active control point at , or a fallback if none found. private T binarySearchWithFallback(IReadOnlyList list, double time, T fallback) - where T : ControlPoint, new() + where T : ControlPoint { return binarySearch(list, time) ?? fallback; } From 81d95f8584b21f8b656ab522107a130acbe29941 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 18 Jul 2020 20:24:38 +0300 Subject: [PATCH 04/37] Implement UserBrickPanel component --- .../Visual/Online/TestSceneSocialOverlay.cs | 84 ------ .../Visual/Online/TestSceneUserPanel.cs | 13 + .../Dashboard/Friends/FriendDisplay.cs | 3 + .../OverlayPanelDisplayStyleControl.cs | 7 +- .../Sections/General/LoginSettings.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 242 ------------------ osu.Game/Users/ExtendedUserPanel.cs | 148 +++++++++++ osu.Game/Users/UserBrickPanel.cs | 65 +++++ osu.Game/Users/UserGridPanel.cs | 2 +- osu.Game/Users/UserListPanel.cs | 2 +- osu.Game/Users/UserPanel.cs | 130 +--------- 11 files changed, 241 insertions(+), 457 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs delete mode 100644 osu.Game/Overlays/SocialOverlay.cs create mode 100644 osu.Game/Users/ExtendedUserPanel.cs create mode 100644 osu.Game/Users/UserBrickPanel.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs deleted file mode 100644 index 77e77d90c1..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using NUnit.Framework; -using osu.Game.Overlays; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Online -{ - [TestFixture] - public class TestSceneSocialOverlay : OsuTestScene - { - protected override bool UseOnlineAPI => true; - - public TestSceneSocialOverlay() - { - SocialOverlay s = new SocialOverlay - { - Users = new[] - { - new User - { - Username = @"flyte", - Id = 3103765, - Country = new Country { FlagName = @"JP" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", - }, - new User - { - Username = @"Cookiezi", - Id = 124493, - Country = new Country { FlagName = @"KR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", - }, - new User - { - Username = @"Angelsim", - Id = 1777162, - Country = new Country { FlagName = @"KR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", - }, - new User - { - Username = @"Rafis", - Id = 2558286, - Country = new Country { FlagName = @"PL" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg", - }, - new User - { - Username = @"hvick225", - Id = 50265, - Country = new Country { FlagName = @"TW" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c5.jpg", - }, - new User - { - Username = @"peppy", - Id = 2, - Country = new Country { FlagName = @"AU" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" - }, - new User - { - Username = @"filsdelama", - Id = 2831793, - Country = new Country { FlagName = @"FR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c7.jpg" - }, - new User - { - Username = @"_index", - Id = 652457, - Country = new Country { FlagName = @"RU" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c8.jpg" - }, - }, - }; - Add(s); - - AddStep(@"toggle", s.ToggleVisibility); - } - } -} diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index f763e50067..c2e9945c99 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -42,6 +42,19 @@ namespace osu.Game.Tests.Visual.Online Spacing = new Vector2(10f), Children = new Drawable[] { + new UserBrickPanel(new User + { + Username = @"flyte", + Id = 3103765, + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" + }), + new UserBrickPanel(new User + { + Username = @"peppy", + Id = 2, + Colour = "99EB47", + CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", + }), flyte = new UserGridPanel(new User { Username = @"flyte", diff --git a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs index 79fda99c73..41b25ee1a5 100644 --- a/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs +++ b/osu.Game/Overlays/Dashboard/Friends/FriendDisplay.cs @@ -225,6 +225,9 @@ namespace osu.Game.Overlays.Dashboard.Friends case OverlayPanelDisplayStyle.List: return new UserListPanel(user); + + case OverlayPanelDisplayStyle.Brick: + return new UserBrickPanel(user); } } diff --git a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs index 7269007b41..87b9d89d4d 100644 --- a/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs +++ b/osu.Game/Overlays/OverlayPanelDisplayStyleControl.cs @@ -34,6 +34,10 @@ namespace osu.Game.Overlays { Icon = FontAwesome.Solid.Bars }); + AddTabItem(new PanelDisplayTabItem(OverlayPanelDisplayStyle.Brick) + { + Icon = FontAwesome.Solid.Th + }); } protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer @@ -96,6 +100,7 @@ namespace osu.Game.Overlays public enum OverlayPanelDisplayStyle { Card, - List + List, + Brick } } diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 52b712a40e..34e5da4ef4 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General [Resolved] private OsuColour colours { get; set; } - private UserPanel panel; + private UserGridPanel panel; private UserDropdown dropdown; /// diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs deleted file mode 100644 index 1b05142192..0000000000 --- a/osu.Game/Overlays/SocialOverlay.cs +++ /dev/null @@ -1,242 +0,0 @@ -// 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 System.Linq; -using osu.Framework.Bindables; -using osuTK; -using osuTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Overlays.SearchableList; -using osu.Game.Overlays.Social; -using osu.Game.Users; -using System.Threading; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Threading; - -namespace osu.Game.Overlays -{ - public class SocialOverlay : SearchableListOverlay - { - private readonly LoadingSpinner loading; - private FillFlowContainer panels; - - protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"60284b"); - protected override Color4 TrianglesColourLight => Color4Extensions.FromHex(@"672b51"); - protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"5c2648"); - - protected override SearchableListHeader CreateHeader() => new Header(); - protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - - private User[] users = Array.Empty(); - - public User[] Users - { - get => users; - set - { - if (users == value) - return; - - users = value ?? Array.Empty(); - - if (LoadState >= LoadState.Ready) - recreatePanels(); - } - } - - public SocialOverlay() - : base(OverlayColourScheme.Pink) - { - Add(loading = new LoadingSpinner()); - - Filter.Search.Current.ValueChanged += text => - { - if (!string.IsNullOrEmpty(text.NewValue)) - { - // force searching in players until searching for friends is supported - Header.Tabs.Current.Value = SocialTab.AllPlayers; - - if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank) - Filter.Tabs.Current.Value = SocialSortCriteria.Rank; - } - }; - - Header.Tabs.Current.ValueChanged += _ => queueUpdate(); - Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate(); - - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels(); - Filter.Dropdown.Current.ValueChanged += _ => recreatePanels(); - - currentQuery.BindTo(Filter.Search.Current); - currentQuery.ValueChanged += query => - { - queryChangedDebounce?.Cancel(); - - if (string.IsNullOrEmpty(query.NewValue)) - queueUpdate(); - else - queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - }; - } - - [BackgroundDependencyLoader] - private void load() - { - recreatePanels(); - } - - private APIRequest getUsersRequest; - - private readonly Bindable currentQuery = new Bindable(); - - private ScheduledDelegate queryChangedDebounce; - - private void queueUpdate() => Scheduler.AddOnce(updateSearch); - - private CancellationTokenSource loadCancellation; - - private void updateSearch() - { - queryChangedDebounce?.Cancel(); - - if (!IsLoaded) - return; - - Users = null; - clearPanels(); - getUsersRequest?.Cancel(); - - if (API?.IsLoggedIn != true) - return; - - switch (Header.Tabs.Current.Value) - { - case SocialTab.Friends: - var friendRequest = new GetFriendsRequest(); // TODO filter arguments? - friendRequest.Success += users => Users = users.ToArray(); - API.Queue(getUsersRequest = friendRequest); - break; - - default: - var userRequest = new GetUsersRequest(); // TODO filter arguments! - userRequest.Success += res => Users = res.Users.Select(r => r.User).ToArray(); - API.Queue(getUsersRequest = userRequest); - break; - } - } - - private void recreatePanels() - { - clearPanels(); - - if (Users == null) - { - loading.Hide(); - return; - } - - IEnumerable sortedUsers = Users; - - switch (Filter.Tabs.Current.Value) - { - case SocialSortCriteria.Location: - sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName); - break; - - case SocialSortCriteria.Name: - sortedUsers = sortedUsers.OrderBy(u => u.Username); - break; - } - - if (Filter.Dropdown.Current.Value == SortDirection.Descending) - sortedUsers = sortedUsers.Reverse(); - - var newPanels = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(10f), - Margin = new MarginPadding { Top = 10 }, - ChildrenEnumerable = sortedUsers.Select(u => - { - UserPanel panel; - - switch (Filter.DisplayStyleControl.DisplayStyle.Value) - { - case PanelDisplayStyle.Grid: - panel = new UserGridPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 290, - }; - break; - - default: - panel = new UserListPanel(u); - break; - } - - panel.Status.BindTo(u.Status); - panel.Activity.BindTo(u.Activity); - return panel; - }) - }; - - LoadComponentAsync(newPanels, f => - { - if (panels != null) - ScrollFlow.Remove(panels); - - loading.Hide(); - ScrollFlow.Add(panels = newPanels); - }, (loadCancellation = new CancellationTokenSource()).Token); - } - - private void onFilterUpdate() - { - if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank) - { - queueUpdate(); - return; - } - - recreatePanels(); - } - - private void clearPanels() - { - loading.Show(); - - loadCancellation?.Cancel(); - - if (panels != null) - { - panels.Expire(); - panels = null; - } - } - - public override void APIStateChanged(IAPIProvider api, APIState state) - { - switch (state) - { - case APIState.Online: - queueUpdate(); - break; - - default: - Users = null; - clearPanels(); - break; - } - } - } -} diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs new file mode 100644 index 0000000000..5bd98b3fb7 --- /dev/null +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -0,0 +1,148 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osuTK; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osu.Framework.Input.Events; + +namespace osu.Game.Users +{ + public abstract class ExtendedUserPanel : UserPanel + { + public readonly Bindable Status = new Bindable(); + + public readonly IBindable Activity = new Bindable(); + + protected TextFlowContainer LastVisitMessage { get; private set; } + + private SpriteIcon statusIcon; + private OsuSpriteText statusMessage; + + public ExtendedUserPanel(User user) + : base(user) + { + } + + [BackgroundDependencyLoader] + private void load() + { + BorderColour = ColourProvider?.Light1 ?? Colours.GreyVioletLighter; + + Status.ValueChanged += status => displayStatus(status.NewValue, Activity.Value); + Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Status.TriggerChange(); + + // Colour should be applied immediately on first load. + statusIcon.FinishTransforms(); + } + + protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar + { + User = User, + OpenOnClick = { Value = false } + }; + + protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country) + { + Size = new Vector2(39, 26) + }; + + protected SpriteIcon CreateStatusIcon() => statusIcon = new SpriteIcon + { + Icon = FontAwesome.Regular.Circle, + Size = new Vector2(25) + }; + + protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren) + { + var statusContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical + }; + + var alignment = rightAlignedChildren ? Anchor.CentreRight : Anchor.CentreLeft; + + statusContainer.Add(LastVisitMessage = new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)).With(text => + { + text.Anchor = alignment; + text.Origin = alignment; + text.AutoSizeAxes = Axes.Both; + text.Alpha = 0; + + if (User.LastVisit.HasValue) + { + text.AddText(@"Last seen "); + text.AddText(new DrawableDate(User.LastVisit.Value, italic: false) + { + Shadow = false + }); + } + })); + + statusContainer.Add(statusMessage = new OsuSpriteText + { + Anchor = alignment, + Origin = alignment, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold) + }); + + return statusContainer; + } + + private void displayStatus(UserStatus status, UserActivity activity = null) + { + if (status != null) + { + LastVisitMessage.FadeTo(status is UserStatusOffline && User.LastVisit.HasValue ? 1 : 0); + + // Set status message based on activity (if we have one) and status is not offline + if (activity != null && !(status is UserStatusOffline)) + { + statusMessage.Text = activity.Status; + statusIcon.FadeColour(activity.GetAppropriateColour(Colours), 500, Easing.OutQuint); + return; + } + + // Otherwise use only status + statusMessage.Text = status.Message; + statusIcon.FadeColour(status.GetAppropriateColour(Colours), 500, Easing.OutQuint); + + return; + } + + // Fallback to web status if local one is null + if (User.IsOnline) + { + Status.Value = new UserStatusOnline(); + return; + } + + Status.Value = new UserStatusOffline(); + } + + protected override bool OnHover(HoverEvent e) + { + BorderThickness = 2; + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + BorderThickness = 0; + base.OnHoverLost(e); + } + } +} diff --git a/osu.Game/Users/UserBrickPanel.cs b/osu.Game/Users/UserBrickPanel.cs new file mode 100644 index 0000000000..f6eabc3b75 --- /dev/null +++ b/osu.Game/Users/UserBrickPanel.cs @@ -0,0 +1,65 @@ +// 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.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osuTK; + +namespace osu.Game.Users +{ + public class UserBrickPanel : UserPanel + { + public UserBrickPanel(User user) + : base(user) + { + AutoSizeAxes = Axes.X; + Height = 23; + CornerRadius = 6; + } + + [BackgroundDependencyLoader] + private void load() + { + Background.FadeTo(0.3f); + } + + protected override Drawable CreateLayout() => new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Margin = new MarginPadding + { + Horizontal = 5 + }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new CircularContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Masking = true, + Width = 4, + Height = 13, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = string.IsNullOrEmpty(User.Colour) ? Color4Extensions.FromHex("0087ca") : Color4Extensions.FromHex(User.Colour) + } + }, + CreateUsername().With(u => + { + u.Anchor = Anchor.CentreLeft; + u.Origin = Anchor.CentreLeft; + u.Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold); + }) + } + }; + } +} diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index e62a834d6d..44dcbc305d 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -9,7 +9,7 @@ using osuTK; namespace osu.Game.Users { - public class UserGridPanel : UserPanel + public class UserGridPanel : ExtendedUserPanel { private const int margin = 10; diff --git a/osu.Game/Users/UserListPanel.cs b/osu.Game/Users/UserListPanel.cs index 1c3ae20577..9c95eff739 100644 --- a/osu.Game/Users/UserListPanel.cs +++ b/osu.Game/Users/UserListPanel.cs @@ -12,7 +12,7 @@ using osu.Game.Overlays.Profile.Header.Components; namespace osu.Game.Users { - public class UserListPanel : UserPanel + public class UserListPanel : ExtendedUserPanel { public UserListPanel(User user) : base(user) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 6f59f9e443..94c0c31cfc 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; -using osuTK; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -14,11 +12,8 @@ using osu.Game.Overlays; using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Containers; -using osu.Game.Users.Drawables; using JetBrains.Annotations; -using osu.Framework.Input.Events; namespace osu.Game.Users { @@ -26,21 +21,12 @@ namespace osu.Game.Users { public readonly User User; - public readonly Bindable Status = new Bindable(); - - public readonly IBindable Activity = new Bindable(); - public new Action Action; protected Action ViewProfile { get; private set; } protected DelayedLoadUnloadWrapper Background { get; private set; } - protected TextFlowContainer LastVisitMessage { get; private set; } - - private SpriteIcon statusIcon; - private OsuSpriteText statusMessage; - protected UserPanel(User user) { if (user == null) @@ -53,23 +39,22 @@ namespace osu.Game.Users private UserProfileOverlay profileOverlay { get; set; } [Resolved(canBeNull: true)] - private OverlayColourProvider colourProvider { get; set; } + protected OverlayColourProvider ColourProvider { get; private set; } [Resolved] - private OsuColour colours { get; set; } + protected OsuColour Colours { get; private set; } [BackgroundDependencyLoader] private void load() { Masking = true; - BorderColour = colourProvider?.Light1 ?? colours.GreyVioletLighter; AddRange(new[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider?.Background5 ?? colours.Gray1 + Colour = ColourProvider?.Background5 ?? Colours.Gray1 }, Background = new DelayedLoadUnloadWrapper(() => new UserCoverBackground { @@ -86,9 +71,6 @@ namespace osu.Game.Users CreateLayout() }); - Status.ValueChanged += status => displayStatus(status.NewValue, Activity.Value); - Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue); - base.Action = ViewProfile = () => { Action?.Invoke(); @@ -96,41 +78,9 @@ namespace osu.Game.Users }; } - protected override void LoadComplete() - { - base.LoadComplete(); - Status.TriggerChange(); - - // Colour should be applied immediately on first load. - statusIcon.FinishTransforms(); - } - - protected override bool OnHover(HoverEvent e) - { - BorderThickness = 2; - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - BorderThickness = 0; - base.OnHoverLost(e); - } - [NotNull] protected abstract Drawable CreateLayout(); - protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar - { - User = User, - OpenOnClick = { Value = false } - }; - - protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country) - { - Size = new Vector2(39, 26) - }; - protected OsuSpriteText CreateUsername() => new OsuSpriteText { Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), @@ -138,80 +88,6 @@ namespace osu.Game.Users Text = User.Username, }; - protected SpriteIcon CreateStatusIcon() => statusIcon = new SpriteIcon - { - Icon = FontAwesome.Regular.Circle, - Size = new Vector2(25) - }; - - protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren) - { - var statusContainer = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical - }; - - var alignment = rightAlignedChildren ? Anchor.CentreRight : Anchor.CentreLeft; - - statusContainer.Add(LastVisitMessage = new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)).With(text => - { - text.Anchor = alignment; - text.Origin = alignment; - text.AutoSizeAxes = Axes.Both; - text.Alpha = 0; - - if (User.LastVisit.HasValue) - { - text.AddText(@"Last seen "); - text.AddText(new DrawableDate(User.LastVisit.Value, italic: false) - { - Shadow = false - }); - } - })); - - statusContainer.Add(statusMessage = new OsuSpriteText - { - Anchor = alignment, - Origin = alignment, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold) - }); - - return statusContainer; - } - - private void displayStatus(UserStatus status, UserActivity activity = null) - { - if (status != null) - { - LastVisitMessage.FadeTo(status is UserStatusOffline && User.LastVisit.HasValue ? 1 : 0); - - // Set status message based on activity (if we have one) and status is not offline - if (activity != null && !(status is UserStatusOffline)) - { - statusMessage.Text = activity.Status; - statusIcon.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint); - return; - } - - // Otherwise use only status - statusMessage.Text = status.Message; - statusIcon.FadeColour(status.GetAppropriateColour(colours), 500, Easing.OutQuint); - - return; - } - - // Fallback to web status if local one is null - if (User.IsOnline) - { - Status.Value = new UserStatusOnline(); - return; - } - - Status.Value = new UserStatusOffline(); - } - public MenuItem[] ContextMenuItems => new MenuItem[] { new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile), From 753b1f3401757cb6cd71b1cece3b2499a59f1328 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 18 Jul 2020 20:26:15 +0300 Subject: [PATCH 05/37] Make ctor protected --- osu.Game/Users/ExtendedUserPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index 5bd98b3fb7..2604815751 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -25,7 +25,7 @@ namespace osu.Game.Users private SpriteIcon statusIcon; private OsuSpriteText statusMessage; - public ExtendedUserPanel(User user) + protected ExtendedUserPanel(User user) : base(user) { } From 3e773fde27d165bd43558ba48d5685c3568d5a26 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 18 Jul 2020 23:15:22 +0300 Subject: [PATCH 06/37] Remove SocialOverlay component as never being used --- .../Visual/Online/TestSceneSocialOverlay.cs | 84 ------ osu.Game/Overlays/SocialOverlay.cs | 242 ------------------ 2 files changed, 326 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs delete mode 100644 osu.Game/Overlays/SocialOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs deleted file mode 100644 index 77e77d90c1..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using NUnit.Framework; -using osu.Game.Overlays; -using osu.Game.Users; - -namespace osu.Game.Tests.Visual.Online -{ - [TestFixture] - public class TestSceneSocialOverlay : OsuTestScene - { - protected override bool UseOnlineAPI => true; - - public TestSceneSocialOverlay() - { - SocialOverlay s = new SocialOverlay - { - Users = new[] - { - new User - { - Username = @"flyte", - Id = 3103765, - Country = new Country { FlagName = @"JP" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg", - }, - new User - { - Username = @"Cookiezi", - Id = 124493, - Country = new Country { FlagName = @"KR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg", - }, - new User - { - Username = @"Angelsim", - Id = 1777162, - Country = new Country { FlagName = @"KR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", - }, - new User - { - Username = @"Rafis", - Id = 2558286, - Country = new Country { FlagName = @"PL" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg", - }, - new User - { - Username = @"hvick225", - Id = 50265, - Country = new Country { FlagName = @"TW" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c5.jpg", - }, - new User - { - Username = @"peppy", - Id = 2, - Country = new Country { FlagName = @"AU" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg" - }, - new User - { - Username = @"filsdelama", - Id = 2831793, - Country = new Country { FlagName = @"FR" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c7.jpg" - }, - new User - { - Username = @"_index", - Id = 652457, - Country = new Country { FlagName = @"RU" }, - CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c8.jpg" - }, - }, - }; - Add(s); - - AddStep(@"toggle", s.ToggleVisibility); - } - } -} diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs deleted file mode 100644 index 1b05142192..0000000000 --- a/osu.Game/Overlays/SocialOverlay.cs +++ /dev/null @@ -1,242 +0,0 @@ -// 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 System.Linq; -using osu.Framework.Bindables; -using osuTK; -using osuTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests; -using osu.Game.Overlays.SearchableList; -using osu.Game.Overlays.Social; -using osu.Game.Users; -using System.Threading; -using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Threading; - -namespace osu.Game.Overlays -{ - public class SocialOverlay : SearchableListOverlay - { - private readonly LoadingSpinner loading; - private FillFlowContainer panels; - - protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"60284b"); - protected override Color4 TrianglesColourLight => Color4Extensions.FromHex(@"672b51"); - protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"5c2648"); - - protected override SearchableListHeader CreateHeader() => new Header(); - protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - - private User[] users = Array.Empty(); - - public User[] Users - { - get => users; - set - { - if (users == value) - return; - - users = value ?? Array.Empty(); - - if (LoadState >= LoadState.Ready) - recreatePanels(); - } - } - - public SocialOverlay() - : base(OverlayColourScheme.Pink) - { - Add(loading = new LoadingSpinner()); - - Filter.Search.Current.ValueChanged += text => - { - if (!string.IsNullOrEmpty(text.NewValue)) - { - // force searching in players until searching for friends is supported - Header.Tabs.Current.Value = SocialTab.AllPlayers; - - if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank) - Filter.Tabs.Current.Value = SocialSortCriteria.Rank; - } - }; - - Header.Tabs.Current.ValueChanged += _ => queueUpdate(); - Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate(); - - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels(); - Filter.Dropdown.Current.ValueChanged += _ => recreatePanels(); - - currentQuery.BindTo(Filter.Search.Current); - currentQuery.ValueChanged += query => - { - queryChangedDebounce?.Cancel(); - - if (string.IsNullOrEmpty(query.NewValue)) - queueUpdate(); - else - queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - }; - } - - [BackgroundDependencyLoader] - private void load() - { - recreatePanels(); - } - - private APIRequest getUsersRequest; - - private readonly Bindable currentQuery = new Bindable(); - - private ScheduledDelegate queryChangedDebounce; - - private void queueUpdate() => Scheduler.AddOnce(updateSearch); - - private CancellationTokenSource loadCancellation; - - private void updateSearch() - { - queryChangedDebounce?.Cancel(); - - if (!IsLoaded) - return; - - Users = null; - clearPanels(); - getUsersRequest?.Cancel(); - - if (API?.IsLoggedIn != true) - return; - - switch (Header.Tabs.Current.Value) - { - case SocialTab.Friends: - var friendRequest = new GetFriendsRequest(); // TODO filter arguments? - friendRequest.Success += users => Users = users.ToArray(); - API.Queue(getUsersRequest = friendRequest); - break; - - default: - var userRequest = new GetUsersRequest(); // TODO filter arguments! - userRequest.Success += res => Users = res.Users.Select(r => r.User).ToArray(); - API.Queue(getUsersRequest = userRequest); - break; - } - } - - private void recreatePanels() - { - clearPanels(); - - if (Users == null) - { - loading.Hide(); - return; - } - - IEnumerable sortedUsers = Users; - - switch (Filter.Tabs.Current.Value) - { - case SocialSortCriteria.Location: - sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName); - break; - - case SocialSortCriteria.Name: - sortedUsers = sortedUsers.OrderBy(u => u.Username); - break; - } - - if (Filter.Dropdown.Current.Value == SortDirection.Descending) - sortedUsers = sortedUsers.Reverse(); - - var newPanels = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(10f), - Margin = new MarginPadding { Top = 10 }, - ChildrenEnumerable = sortedUsers.Select(u => - { - UserPanel panel; - - switch (Filter.DisplayStyleControl.DisplayStyle.Value) - { - case PanelDisplayStyle.Grid: - panel = new UserGridPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Width = 290, - }; - break; - - default: - panel = new UserListPanel(u); - break; - } - - panel.Status.BindTo(u.Status); - panel.Activity.BindTo(u.Activity); - return panel; - }) - }; - - LoadComponentAsync(newPanels, f => - { - if (panels != null) - ScrollFlow.Remove(panels); - - loading.Hide(); - ScrollFlow.Add(panels = newPanels); - }, (loadCancellation = new CancellationTokenSource()).Token); - } - - private void onFilterUpdate() - { - if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank) - { - queueUpdate(); - return; - } - - recreatePanels(); - } - - private void clearPanels() - { - loading.Show(); - - loadCancellation?.Cancel(); - - if (panels != null) - { - panels.Expire(); - panels = null; - } - } - - public override void APIStateChanged(IAPIProvider api, APIState state) - { - switch (state) - { - case APIState.Online: - queueUpdate(); - break; - - default: - Users = null; - clearPanels(); - break; - } - } - } -} From a6562be3eb33d35ac6b47a2d19cdaee3f6cc52dd Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 18 Jul 2020 23:27:33 +0300 Subject: [PATCH 07/37] Remove unused classes from social namespace --- osu.Game/Overlays/Social/FilterControl.cs | 33 ----------- osu.Game/Overlays/Social/Header.cs | 67 ----------------------- 2 files changed, 100 deletions(-) delete mode 100644 osu.Game/Overlays/Social/FilterControl.cs delete mode 100644 osu.Game/Overlays/Social/Header.cs diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs deleted file mode 100644 index 93fcc3c401..0000000000 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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.Extensions.Color4Extensions; -using osuTK.Graphics; -using osu.Framework.Graphics; -using osu.Game.Overlays.SearchableList; - -namespace osu.Game.Overlays.Social -{ - public class FilterControl : SearchableListFilterControl - { - protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"47253a"); - protected override SocialSortCriteria DefaultTab => SocialSortCriteria.Rank; - protected override SortDirection DefaultCategory => SortDirection.Ascending; - - public FilterControl() - { - Tabs.Margin = new MarginPadding { Top = 10 }; - } - } - - public enum SocialSortCriteria - { - Rank, - Name, - Location, - //[Description("Time Zone")] - //TimeZone, - //[Description("World Map")] - //WorldMap, - } -} diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs deleted file mode 100644 index 22e0fdcd56..0000000000 --- a/osu.Game/Overlays/Social/Header.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Overlays.SearchableList; -using osuTK.Graphics; -using osu.Framework.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Framework.Graphics.Containers; -using osu.Game.Graphics; -using osu.Framework.Allocation; -using System.ComponentModel; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics.Sprites; - -namespace osu.Game.Overlays.Social -{ - public class Header : SearchableListHeader - { - private OsuSpriteText browser; - - protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"38202e"); - - protected override SocialTab DefaultTab => SocialTab.AllPlayers; - protected override IconUsage Icon => FontAwesome.Solid.Users; - - protected override Drawable CreateHeaderText() - { - return new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] - { - new OsuSpriteText - { - Text = "social ", - Font = OsuFont.GetFont(size: 25), - }, - browser = new OsuSpriteText - { - Text = "browser", - Font = OsuFont.GetFont(size: 25, weight: FontWeight.Light), - }, - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - browser.Colour = colours.Pink; - } - } - - public enum SocialTab - { - [Description("All Players")] - AllPlayers, - - [Description("Friends")] - Friends, - //[Description("Team Members")] - //TeamMembers, - //[Description("Chat Channels")] - //ChatChannels, - } -} From 2025e5418c841a386ba5599164c3c9d017c7814c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 19 Jul 2020 04:10:35 +0300 Subject: [PATCH 08/37] Minor visual adjustments --- osu.Game/Users/UserBrickPanel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Users/UserBrickPanel.cs b/osu.Game/Users/UserBrickPanel.cs index f6eabc3b75..9ca7768187 100644 --- a/osu.Game/Users/UserBrickPanel.cs +++ b/osu.Game/Users/UserBrickPanel.cs @@ -16,15 +16,14 @@ namespace osu.Game.Users public UserBrickPanel(User user) : base(user) { - AutoSizeAxes = Axes.X; - Height = 23; + AutoSizeAxes = Axes.Both; CornerRadius = 6; } [BackgroundDependencyLoader] private void load() { - Background.FadeTo(0.3f); + Background.FadeTo(0.2f); } protected override Drawable CreateLayout() => new FillFlowContainer @@ -34,7 +33,8 @@ namespace osu.Game.Users Spacing = new Vector2(5, 0), Margin = new MarginPadding { - Horizontal = 5 + Horizontal = 10, + Vertical = 3, }, Anchor = Anchor.Centre, Origin = Anchor.Centre, From 648e414c14ac0ade2821b91b7101f225a3b8a65f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Jul 2020 11:04:33 +0900 Subject: [PATCH 09/37] Update InputHandlers in line with framework changes --- .../Replays/CatchFramedReplayInputHandler.cs | 15 ++++++--------- .../Replays/ManiaFramedReplayInputHandler.cs | 5 ++++- .../Replays/OsuFramedReplayInputHandler.cs | 12 ++++++------ .../Replays/TaikoFramedReplayInputHandler.cs | 5 ++++- .../Visual/Gameplay/TestSceneReplayRecorder.cs | 15 +++------------ .../Visual/Gameplay/TestSceneReplayRecording.cs | 15 +++------------ .../Rulesets/Replays/FramedReplayInputHandler.cs | 3 --- 7 files changed, 26 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index f122588a2b..24c21fbc84 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -35,18 +35,15 @@ namespace osu.Game.Rulesets.Catch.Replays } } - public override List GetPendingInputs() + public override void GetPendingInputs(List input) { - if (!Position.HasValue) return new List(); + if (!Position.HasValue) return; - return new List + input.Add(new CatchReplayState { - new CatchReplayState - { - PressedActions = CurrentFrame?.Actions ?? new List(), - CatcherX = Position.Value - }, - }; + PressedActions = CurrentFrame?.Actions ?? new List(), + CatcherX = Position.Value + }); } public class CatchReplayState : ReplayState diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index 899718b77e..26c4ccf289 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Mania.Replays protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any(); - public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() } }; + public override void GetPendingInputs(List input) + { + input.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); + } } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index b42e9ac187..5c803539c2 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -36,19 +36,19 @@ namespace osu.Game.Rulesets.Osu.Replays } } - public override List GetPendingInputs() + public override void GetPendingInputs(List input) { - return new List - { + input.Add( new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(Position ?? Vector2.Zero) - }, + }); + input.Add( new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() - } - }; + }); + ; } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index 97337acc45..7361d4efa8 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Replays protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any(); - public override List GetPendingInputs() => new List { new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() } }; + public override void GetPendingInputs(List input) + { + input.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); + } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index c7455583e4..e473f49826 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -173,19 +173,10 @@ namespace osu.Game.Tests.Visual.Gameplay { } - public override List GetPendingInputs() + public override void GetPendingInputs(List inputs) { - return new List - { - new MousePositionAbsoluteInput - { - Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) - }, - new ReplayState - { - PressedActions = CurrentFrame?.Actions ?? new List() - } - }; + inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) }); + inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index 7822f07957..e891ed617a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -113,19 +113,10 @@ namespace osu.Game.Tests.Visual.Gameplay { } - public override List GetPendingInputs() + public override void GetPendingInputs(List inputs) { - return new List - { - new MousePositionAbsoluteInput - { - Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) - }, - new ReplayState - { - PressedActions = CurrentFrame?.Actions ?? new List() - } - }; + inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) }); + inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); } } diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 55d82c4083..cf5c88b8fd 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; -using osu.Framework.Input.StateChanges; using osu.Game.Input.Handlers; using osu.Game.Replays; @@ -69,8 +68,6 @@ namespace osu.Game.Rulesets.Replays return true; } - public override List GetPendingInputs() => new List(); - private const double sixty_frame_time = 1000.0 / 60; protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2; From a7fcce0bf719a68fda8d5cb4abad429d72828699 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Jul 2020 11:37:38 +0900 Subject: [PATCH 10/37] Fix hard crash on notifications firing before NotificationOverlay is ready --- osu.Game/OsuGame.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 618049e72c..f4bb10340e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -63,7 +63,8 @@ namespace osu.Game private ChannelManager channelManager; - private NotificationOverlay notifications; + [NotNull] + private readonly NotificationOverlay notifications = new NotificationOverlay(); private NowPlayingOverlay nowPlaying; @@ -82,7 +83,7 @@ namespace osu.Game public virtual Storage GetStorageForStableInstall() => null; - public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight; + public float ToolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0); private IdleTracker idleTracker; @@ -250,7 +251,7 @@ namespace osu.Game case LinkAction.OpenEditorTimestamp: case LinkAction.JoinMultiplayerMatch: case LinkAction.Spectate: - waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification + waitForReady(() => notifications, _ => notifications.Post(new SimpleNotification { Text = @"This link type is not yet supported!", Icon = FontAwesome.Solid.LifeRing, @@ -536,14 +537,14 @@ namespace osu.Game MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false; // todo: all archive managers should be able to be looped here. - SkinManager.PostNotification = n => notifications?.Post(n); + SkinManager.PostNotification = n => notifications.Post(n); SkinManager.GetStableStorage = GetStorageForStableInstall; - BeatmapManager.PostNotification = n => notifications?.Post(n); + BeatmapManager.PostNotification = n => notifications.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; BeatmapManager.PresentImport = items => PresentBeatmap(items.First()); - ScoreManager.PostNotification = n => notifications?.Post(n); + ScoreManager.PostNotification = n => notifications.Post(n); ScoreManager.GetStableStorage = GetStorageForStableInstall; ScoreManager.PresentImport = items => PresentScore(items.First()); @@ -615,12 +616,12 @@ namespace osu.Game loadComponentSingleFile(MusicController = new MusicController(), Add, true); - loadComponentSingleFile(notifications = new NotificationOverlay + loadComponentSingleFile(notifications.With(d => { - GetToolbarHeight = () => ToolbarOffset, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }, rightFloatingOverlayContent.Add, true); + d.GetToolbarHeight = () => ToolbarOffset; + d.Anchor = Anchor.TopRight; + d.Origin = Anchor.TopRight; + }), rightFloatingOverlayContent.Add, true); loadComponentSingleFile(screenshotManager, Add); From 3823bd8343d7ae3a8e8281ce154cdd6a05031e09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 Jul 2020 14:11:21 +0900 Subject: [PATCH 11/37] Add back missing default implementations for lookup functions --- osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 55a04e5ee8..e7788b75f3 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -78,14 +78,14 @@ namespace osu.Game.Beatmaps.ControlPoints /// /// The time to find the sound control point at. /// The sound control point. - public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : null); + public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : SampleControlPoint.DEFAULT); /// /// Finds the timing control point that is active at . /// /// The time to find the timing control point at. /// The timing control point. - public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null); + public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : TimingControlPoint.DEFAULT); /// /// Finds the maximum BPM represented by any timing control point. diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 61851a00d7..c052c04ea0 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -10,6 +10,12 @@ namespace osu.Game.Beatmaps.ControlPoints { public const string DEFAULT_BANK = "normal"; + public static readonly SampleControlPoint DEFAULT = new SampleControlPoint + { + SampleBankBindable = { Disabled = true }, + SampleVolumeBindable = { Disabled = true } + }; + /// /// The default sample bank at this control point. /// From 55d921ef85629cd0b04687497793336abfda88aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Jul 2020 15:19:17 +0900 Subject: [PATCH 12/37] Improve feel of animation --- .../TestSceneSpinner.cs | 2 +- .../Objects/Drawables/DrawableSpinner.cs | 32 ++++++++++++------- .../Drawables/Pieces/SpinnerBackground.cs | 10 +++--- .../Objects/Drawables/Pieces/SpinnerTicks.cs | 8 ++--- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs index 8cb7f3f4b6..67afc45e32 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinner.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Tests private void testSingle(float circleSize, bool auto = false) { - var spinner = new Spinner { StartTime = Time.Current + 1000, EndTime = Time.Current + 4000 }; + var spinner = new Spinner { StartTime = Time.Current + 2000, EndTime = Time.Current + 5000 }; spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize }); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index be6766509c..3dd98be6fb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Background = new SpinnerBackground { - Alpha = 0.6f, + Alpha = 1f, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -128,7 +128,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Background.AccentColour = normalColour; - completeColour = colours.YellowLight.Opacity(0.75f); + completeColour = colours.YellowLight; Disc.AccentColour = fillColour; circle.Colour = colours.BlueDark; @@ -152,8 +152,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Disc.FadeAccent(completeColour, duration); - Background.FadeAccent(completeColour, duration); - Background.FadeOut(duration); + Background.FadeAccent(completeColour.Darken(1), duration); circle.FadeColour(completeColour, duration); glow.FadeColour(completeColour, duration); @@ -204,14 +203,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateInitialTransforms(); - circleContainer.ScaleTo(Spinner.Scale * 0.3f); - circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); + circleContainer.ScaleTo(0); + mainContainer.ScaleTo(0); - mainContainer - .ScaleTo(0) - .ScaleTo(Spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) - .Then() - .ScaleTo(1, 500, Easing.OutQuint); + using (BeginDelayedSequence(HitObject.TimePreempt / 2, true)) + { + float phaseOneScale = Spinner.Scale * 0.8f; + + circleContainer.ScaleTo(phaseOneScale, HitObject.TimePreempt / 2f, Easing.OutQuint); + + mainContainer + .ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt / 2, Easing.OutElasticHalf) + .RotateTo(25, HitObject.TimePreempt + Spinner.Duration); + + using (BeginDelayedSequence(HitObject.TimePreempt / 2, true)) + { + circleContainer.ScaleTo(Spinner.Scale * 1.4f, 400, Easing.OutQuint); + mainContainer.ScaleTo(Spinner.Scale, 400, Easing.OutQuint); + } + } } protected override void UpdateStateTransforms(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index 77228e28af..bfb9a9e763 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -1,25 +1,25 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SpinnerBackground : CircularContainer, IHasAccentColour { - protected Box Disc; + private readonly Box disc; public Color4 AccentColour { - get => Disc.Colour; + get => disc.Colour; set { - Disc.Colour = value; + disc.Colour = value; EdgeEffect = new EdgeEffectParameters { @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Children = new Drawable[] { - Disc = new Box + disc = new Box { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index 676cefb236..0e7dafdbea 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -20,24 +20,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre; RelativeSizeAxes = Axes.Both; - const float count = 18; + const float count = 8; for (float i = 0; i < count; i++) { Add(new Container { Colour = Color4.Black, - Alpha = 0.4f, + Alpha = 0.2f, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Radius = 10, + Radius = 20, Colour = Color4.Gray.Opacity(0.2f), }, RelativePositionAxes = Axes.Both, Masking = true, CornerRadius = 5, - Size = new Vector2(60, 10), + Size = new Vector2(65, 10), Origin = Anchor.Centre, Position = new Vector2( 0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.86f, From 33e58bb7db992e24562ecf38774b09297b6b55cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Jul 2020 17:22:17 +0900 Subject: [PATCH 13/37] Fix sizing and colour not correct on hit --- .../Objects/Drawables/DrawableSpinner.cs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 3dd98be6fb..b8a290a978 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -147,15 +147,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (Progress >= 1 && !Disc.Complete) { Disc.Complete = true; - - const float duration = 200; - - Disc.FadeAccent(completeColour, duration); - - Background.FadeAccent(completeColour.Darken(1), duration); - - circle.FadeColour(completeColour, duration); - glow.FadeColour(completeColour, duration); + transformFillColour(completeColour, 200); } if (userTriggered || Time.Current < Spinner.EndTime) @@ -208,18 +200,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables using (BeginDelayedSequence(HitObject.TimePreempt / 2, true)) { - float phaseOneScale = Spinner.Scale * 0.8f; + float phaseOneScale = Spinner.Scale * 0.7f; - circleContainer.ScaleTo(phaseOneScale, HitObject.TimePreempt / 2f, Easing.OutQuint); + circleContainer.ScaleTo(phaseOneScale, HitObject.TimePreempt / 4, Easing.OutQuint); mainContainer - .ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt / 2, Easing.OutElasticHalf) - .RotateTo(25, HitObject.TimePreempt + Spinner.Duration); + .ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.5f, HitObject.TimePreempt / 4, Easing.OutQuint) + .RotateTo((float)(25 * Spinner.Duration / 2000), HitObject.TimePreempt + Spinner.Duration); using (BeginDelayedSequence(HitObject.TimePreempt / 2, true)) { - circleContainer.ScaleTo(Spinner.Scale * 1.4f, 400, Easing.OutQuint); - mainContainer.ScaleTo(Spinner.Scale, 400, Easing.OutQuint); + circleContainer.ScaleTo(Spinner.Scale, 400, Easing.OutQuint); + mainContainer.ScaleTo(1, 400, Easing.OutQuint); } } } @@ -228,18 +220,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateStateTransforms(state); - var sequence = this.Delay(Spinner.Duration).FadeOut(160); - - switch (state) + using (BeginDelayedSequence(Spinner.Duration, true)) { - case ArmedState.Hit: - sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); - break; + this.FadeOut(160); - case ArmedState.Miss: - sequence.ScaleTo(Scale * 0.8f, 320, Easing.In); - break; + switch (state) + { + case ArmedState.Hit: + transformFillColour(completeColour, 0); + this.ScaleTo(Scale * 1.2f, 320, Easing.Out); + mainContainer.RotateTo(mainContainer.Rotation + 180, 320); + break; + + case ArmedState.Miss: + this.ScaleTo(Scale * 0.8f, 320, Easing.In); + break; + } } } + + private void transformFillColour(Colour4 colour, double duration) + { + Disc.FadeAccent(colour, duration); + + Background.FadeAccent(colour.Darken(1), duration); + + circle.FadeColour(colour, duration); + glow.FadeColour(colour, duration); + } } } From 4cbc176cb66c3c9616ccc613252c7eee20d9a97f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Jul 2020 17:48:35 +0900 Subject: [PATCH 14/37] Add less fill and more transparency --- .../Objects/Drawables/DrawableSpinner.cs | 10 ++++-- .../Drawables/Pieces/SpinnerBackground.cs | 8 ++--- .../Objects/Drawables/Pieces/SpinnerTicks.cs | 34 ++++++++++++++----- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index b8a290a978..fafb3ab69d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -93,7 +93,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Background = new SpinnerBackground { - Alpha = 1f, + Disc = + { + Alpha = 0f, + }, Anchor = Anchor.Centre, Origin = Anchor.Centre, }, @@ -125,10 +128,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private void load(OsuColour colours) { normalColour = baseColour; + completeColour = colours.YellowLight; Background.AccentColour = normalColour; - - completeColour = colours.YellowLight; + Ticks.AccentColour = normalColour; Disc.AccentColour = fillColour; circle.Colour = colours.BlueDark; @@ -244,6 +247,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Disc.FadeAccent(colour, duration); Background.FadeAccent(colour.Darken(1), duration); + Ticks.FadeAccent(colour, duration); circle.FadeColour(colour, duration); glow.FadeColour(colour, duration); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index bfb9a9e763..944354abca 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -12,14 +12,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SpinnerBackground : CircularContainer, IHasAccentColour { - private readonly Box disc; + public readonly Box Disc; public Color4 AccentColour { - get => disc.Colour; + get => Disc.Colour; set { - disc.Colour = value; + Disc.Colour = value; EdgeEffect = new EdgeEffectParameters { @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Children = new Drawable[] { - disc = new Box + Disc = new Box { Origin = Anchor.Centre, Anchor = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index 0e7dafdbea..95bccbf2fc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,10 +10,11 @@ using osu.Framework.Graphics.Effects; using osuTK; using osuTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { - public class SpinnerTicks : Container + public class SpinnerTicks : Container, IHasAccentColour { public SpinnerTicks() { @@ -26,14 +28,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Add(new Container { - Colour = Color4.Black, - Alpha = 0.2f, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Radius = 20, - Colour = Color4.Gray.Opacity(0.2f), - }, + Alpha = 0.4f, + Blending = BlendingParameters.Additive, RelativePositionAxes = Axes.Both, Masking = true, CornerRadius = 5, @@ -54,5 +50,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }); } } + + public Color4 AccentColour + { + get => Colour; + set + { + Colour = value; + + foreach (var c in Children.OfType()) + { + c.EdgeEffect = + new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Radius = 20, + Colour = value.Opacity(0.8f), + }; + } + } + } } } From e06d3c5812e87037b94a756b1bba98cdcaf09d87 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Jul 2020 17:52:59 +0900 Subject: [PATCH 15/37] Minor adjustments to tick clearance --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 2 +- .../Objects/Drawables/Pieces/SpinnerTicks.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index fafb3ab69d..9c4608cbb1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circleContainer.ScaleTo(phaseOneScale, HitObject.TimePreempt / 4, Easing.OutQuint); mainContainer - .ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.5f, HitObject.TimePreempt / 4, Easing.OutQuint) + .ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.6f, HitObject.TimePreempt / 4, Easing.OutQuint) .RotateTo((float)(25 * Spinner.Duration / 2000), HitObject.TimePreempt + Spinner.Duration); using (BeginDelayedSequence(HitObject.TimePreempt / 2, true)) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index 95bccbf2fc..ba7e8eae6f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -33,11 +33,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces RelativePositionAxes = Axes.Both, Masking = true, CornerRadius = 5, - Size = new Vector2(65, 10), + Size = new Vector2(60, 10), Origin = Anchor.Centre, Position = new Vector2( - 0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.86f, - 0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.86f + 0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.83f, + 0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.83f ), Rotation = -i / count * 360 + 90, Children = new[] From f044c06d089319841abc78a59c68096fd0a5a330 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 20 Jul 2020 22:26:58 +0900 Subject: [PATCH 16/37] Fix hold notes accepting presses during release lenience --- .../TestSceneHoldNoteInput.cs | 65 +++++++++++++++++-- .../Objects/Drawables/DrawableHoldNote.cs | 6 ++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 0d13b85901..95072cf4f8 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -10,6 +11,8 @@ using osu.Game.Replays; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -236,6 +239,53 @@ namespace osu.Game.Rulesets.Mania.Tests assertTailJudgement(HitResult.Meh); } + [Test] + public void TestMissReleaseAndHitSecondRelease() + { + var windows = new ManiaHitWindows(); + windows.SetDifficulty(10); + + var beatmap = new Beatmap + { + HitObjects = + { + new HoldNote + { + StartTime = 1000, + Duration = 500, + Column = 0, + }, + new HoldNote + { + StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10, + Duration = 500, + Column = 0, + }, + }, + BeatmapInfo = + { + BaseDifficulty = new BeatmapDifficulty + { + SliderTickRate = 4, + OverallDifficulty = 10, + }, + Ruleset = new ManiaRuleset().RulesetInfo + }, + }; + + performTest(new List + { + new ManiaReplayFrame(beatmap.HitObjects[1].StartTime, ManiaAction.Key1), + new ManiaReplayFrame(beatmap.HitObjects[1].GetEndTime()), + }, beatmap); + + AddAssert("first hold note missed", () => judgementResults.Where(j => beatmap.HitObjects[0].NestedHitObjects.Contains(j.HitObject)) + .All(j => j.Type == HitResult.Miss)); + + AddAssert("second hold note missed", () => judgementResults.Where(j => beatmap.HitObjects[1].NestedHitObjects.Contains(j.HitObject)) + .All(j => j.Type == HitResult.Perfect)); + } + private void assertHeadJudgement(HitResult result) => AddAssert($"head judged as {result}", () => judgementResults[0].Type == result); @@ -250,11 +300,11 @@ namespace osu.Game.Rulesets.Mania.Tests private ScoreAccessibleReplayPlayer currentPlayer; - private void performTest(List frames) + private void performTest(List frames, Beatmap beatmap = null) { - AddStep("load player", () => + if (beatmap == null) { - Beatmap.Value = CreateWorkingBeatmap(new Beatmap + beatmap = new Beatmap { HitObjects = { @@ -270,9 +320,14 @@ namespace osu.Game.Rulesets.Mania.Tests BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 }, Ruleset = new ManiaRuleset().RulesetInfo }, - }); + }; - Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f }); + } + + AddStep("load player", () => + { + Beatmap.Value = CreateWorkingBeatmap(beatmap); var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } }); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 2262bd2b7d..0c5289efe1 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -167,6 +167,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (action != Action.Value) return false; + // The tail has a lenience applied to it which is factored into the miss window (i.e. the miss judgement will be delayed). + // But the hold cannot ever be started within the late-lenience window, so we should skip trying to begin the hold during that time. + // Note: Unlike below, we use the tail's start time to determine the time offset. + if (Time.Current > Tail.HitObject.StartTime && !Tail.HitObject.HitWindows.CanBeHit(Time.Current - Tail.HitObject.StartTime)) + return false; + beginHoldAt(Time.Current - Head.HitObject.StartTime); Head.UpdateResult(); From 72722d4c721c304a8119e56a496a0d05173cfa20 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2020 17:18:26 +0000 Subject: [PATCH 17/37] Bump Microsoft.Build.Traversal from 2.0.50 to 2.0.52 Bumps [Microsoft.Build.Traversal](https://github.com/Microsoft/MSBuildSdks) from 2.0.50 to 2.0.52. - [Release notes](https://github.com/Microsoft/MSBuildSdks/releases) - [Changelog](https://github.com/microsoft/MSBuildSdks/blob/master/RELEASE.md) - [Commits](https://github.com/Microsoft/MSBuildSdks/compare/Microsoft.Build.Traversal.2.0.50...Microsoft.Build.Traversal.2.0.52) Signed-off-by: dependabot-preview[bot] --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 9aa5b6192b..233a040d18 100644 --- a/global.json +++ b/global.json @@ -5,6 +5,6 @@ "version": "3.1.100" }, "msbuild-sdks": { - "Microsoft.Build.Traversal": "2.0.50" + "Microsoft.Build.Traversal": "2.0.52" } } \ No newline at end of file From f71ed47e6693f59c0bba83433d83d0f43c876833 Mon Sep 17 00:00:00 2001 From: Joehu Date: Mon, 20 Jul 2020 11:52:02 -0700 Subject: [PATCH 18/37] Fix focused textbox absorbing input when unfocused --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 8977f014b6..f77a3109c9 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -67,6 +67,8 @@ namespace osu.Game.Graphics.UserInterface public bool OnPressed(GlobalAction action) { + if (!HasFocus) return false; + if (action == GlobalAction.Back) { if (Text.Length > 0) From c1442568b95548316e748e470c00c70a45bd5f9a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Jul 2020 17:04:29 +0900 Subject: [PATCH 19/37] Make perfect mod ignore all non-combo-affecting hitobjects --- .../Mods/TestSceneCatchModPerfect.cs | 2 +- osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs | 6 ------ .../Skinning/TestSceneDrawableTaikoMascot.cs | 2 +- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs | 4 ++-- .../Judgements/TaikoDrumRollJudgement.cs | 2 -- osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs | 2 -- osu.Game/Rulesets/Mods/ModPerfect.cs | 1 + 7 files changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs index 3e06e78dba..c1b7214d72 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModPerfect.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss); // We only care about testing misses, hits are tested via JuiceStream - [TestCase(true)] + [TestCase(false)] public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs index e3391c47f1..fb92399102 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs @@ -1,17 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Rulesets.Catch.Judgements; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Mods { public class CatchModPerfect : ModPerfect { - protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) - => !(result.Judgement is CatchBananaJudgement) - && base.FailCondition(healthProcessor, result); } } diff --git a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs index d200c44a02..cb6a0decde 100644 --- a/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs +++ b/osu.Game.Rulesets.Taiko.Tests/Skinning/TestSceneDrawableTaikoMascot.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle); assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Miss }, TaikoMascotAnimationState.Fail); - assertStateAfterResult(new JudgementResult(new DrumRoll(), new TaikoDrumRollJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Fail); + assertStateAfterResult(new JudgementResult(new DrumRoll(), new TaikoDrumRollJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle); assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Good }, TaikoMascotAnimationState.Idle); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index aaa634648a..0be005e1c4 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Tests }; [Test] - public void TestSpinnerDoesNotFail() + public void TestSpinnerDoesFail() { bool judged = false; AddStep("Setup judgements", () => @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Taiko.Tests Player.ScoreProcessor.NewJudgement += b => judged = true; }); AddUntilStep("swell judged", () => judged); - AddAssert("not failed", () => !Player.HasFailed); + AddAssert("failed", () => Player.HasFailed); } } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs index 604daa929f..0d91002f4b 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollJudgement.cs @@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoDrumRollJudgement : TaikoJudgement { - public override bool AffectsCombo => false; - protected override double HealthIncreaseFor(HitResult result) { // Drum rolls can be ignored with no health penalty diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs index 29be5e0eac..4d61efd3ee 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellJudgement.cs @@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoSwellJudgement : TaikoJudgement { - public override bool AffectsCombo => false; - protected override double HealthIncreaseFor(HitResult result) { switch (result) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 7fe606d584..65f1a972ed 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Mods protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result) => !(result.Judgement is IgnoreJudgement) + && result.Judgement.AffectsCombo && result.Type != result.Judgement.MaxResult; } } From e96f8f1cb652e4d312758b20414f74c01d144ca0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 21 Jul 2020 20:02:22 +0300 Subject: [PATCH 20/37] Make content side padding adjustable for OverlayHeader --- .../UserInterface/TestSceneOverlayHeader.cs | 20 +++++++++++--- osu.Game/Overlays/OverlayHeader.cs | 27 ++++++++++++++----- osu.Game/Overlays/TabControlOverlayHeader.cs | 24 ++++++++++++++--- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index 60af5b37ef..01c13dbc97 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface } }); - addHeader("Orange OverlayHeader (no background)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange); - addHeader("Blue OverlayHeader", new TestNoControlHeader(), OverlayColourScheme.Blue); + addHeader("Orange OverlayHeader (no background, 100 padding)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange); + addHeader("Blue OverlayHeader (default 70 padding)", new TestNoControlHeader(), OverlayColourScheme.Blue); addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green); - addHeader("Pink TabControlOverlayHeader (enum)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink); - addHeader("Red BreadcrumbControlOverlayHeader (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); + addHeader("Pink TabControlOverlayHeader (enum, 30 padding)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink); + addHeader("Red BreadcrumbControlOverlayHeader (no background, 10 padding)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); } private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme) @@ -86,6 +86,11 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestNoBackgroundHeader : OverlayHeader { protected override OverlayTitle CreateTitle() => new TestTitle(); + + public TestNoBackgroundHeader() + { + ContentSidePadding = 100; + } } private class TestNoControlHeader : OverlayHeader @@ -112,6 +117,11 @@ namespace osu.Game.Tests.Visual.UserInterface private class TestEnumTabControlHeader : TabControlOverlayHeader { + public TestEnumTabControlHeader() + { + ContentSidePadding = 30; + } + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings"); protected override OverlayTitle CreateTitle() => new TestTitle(); @@ -130,6 +140,8 @@ namespace osu.Game.Tests.Visual.UserInterface public TestBreadcrumbControlHeader() { + ContentSidePadding = 10; + TabControl.AddItem("tab1"); TabControl.AddItem("tab2"); TabControl.Current.Value = "tab2"; diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index dbc934bde9..c9b9e3b836 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -12,9 +12,26 @@ namespace osu.Game.Overlays { public abstract class OverlayHeader : Container { - public const int CONTENT_X_MARGIN = 50; + private float contentSidePadding; + + /// + /// Horizontal padding of the header content. + /// + protected float ContentSidePadding + { + get => contentSidePadding; + set + { + contentSidePadding = value; + content.Padding = new MarginPadding + { + Horizontal = value + }; + } + } private readonly Box titleBackground; + private readonly Container content; protected readonly FillFlowContainer HeaderInfo; @@ -50,14 +67,10 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Both, Colour = Color4.Gray, }, - new Container + content = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding - { - Horizontal = CONTENT_X_MARGIN, - }, Children = new[] { CreateTitle().With(title => @@ -79,6 +92,8 @@ namespace osu.Game.Overlays CreateContent() } }); + + ContentSidePadding = 70; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/TabControlOverlayHeader.cs b/osu.Game/Overlays/TabControlOverlayHeader.cs index e8e000f441..61605d9e9e 100644 --- a/osu.Game/Overlays/TabControlOverlayHeader.cs +++ b/osu.Game/Overlays/TabControlOverlayHeader.cs @@ -22,6 +22,7 @@ namespace osu.Game.Overlays protected OsuTabControl TabControl; private readonly Box controlBackground; + private readonly Container tabControlContainer; private readonly BindableWithCurrent current = new BindableWithCurrent(); public Bindable Current @@ -30,6 +31,16 @@ namespace osu.Game.Overlays set => current.Current = value; } + protected new float ContentSidePadding + { + get => base.ContentSidePadding; + set + { + base.ContentSidePadding = value; + tabControlContainer.Padding = new MarginPadding { Horizontal = value }; + } + } + protected TabControlOverlayHeader() { HeaderInfo.Add(new Container @@ -42,11 +53,16 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both, }, - TabControl = CreateTabControl().With(control => + tabControlContainer = new Container { - control.Margin = new MarginPadding { Left = CONTENT_X_MARGIN }; - control.Current = Current; - }) + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = ContentSidePadding }, + Child = TabControl = CreateTabControl().With(control => + { + control.Current = Current; + }) + } } }); } From 0145ca09e5d8ebd98a85857c6fab121d7c112143 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 21 Jul 2020 20:11:10 +0300 Subject: [PATCH 21/37] Apply changes to overlays --- osu.Game/Overlays/OverlayHeader.cs | 2 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index c9b9e3b836..cc7f798c4a 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -93,7 +93,7 @@ namespace osu.Game.Overlays } }); - ContentSidePadding = 70; + ContentSidePadding = 50; } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 0161d91daa..2895fa0726 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -23,6 +23,8 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { + ContentSidePadding = 70; + User.ValueChanged += e => updateDisplay(e.NewValue); TabControl.AddItem("info"); From 0a71194ea69e07e516be8db5c9180d612459aec8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 21 Jul 2020 22:46:08 +0300 Subject: [PATCH 22/37] Fix SpotlightSelector is a VisibilityContainer without a reason --- .../TestSceneRankingsSpotlightSelector.cs | 6 - .../Overlays/Rankings/SpotlightSelector.cs | 104 ++++++++---------- .../Overlays/Rankings/SpotlightsLayout.cs | 2 - 3 files changed, 45 insertions(+), 67 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs index 997db827f3..d60222fa0b 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -30,12 +30,6 @@ namespace osu.Game.Tests.Visual.Online Add(selector = new SpotlightSelector()); } - [Test] - public void TestVisibility() - { - AddStep("Toggle Visibility", selector.ToggleVisibility); - } - [Test] public void TestLocalSpotlights() { diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs index f112c1ec43..422373d099 100644 --- a/osu.Game/Overlays/Rankings/SpotlightSelector.cs +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -18,10 +18,8 @@ using osu.Game.Online.API.Requests; namespace osu.Game.Overlays.Rankings { - public class SpotlightSelector : VisibilityContainer, IHasCurrentValue + public class SpotlightSelector : CompositeDrawable, IHasCurrentValue { - private const int duration = 300; - private readonly BindableWithCurrent current = new BindableWithCurrent(); public readonly Bindable Sort = new Bindable(); @@ -37,10 +35,7 @@ namespace osu.Game.Overlays.Rankings set => dropdown.Items = value; } - protected override bool StartHidden => true; - private readonly Box background; - private readonly Container content; private readonly SpotlightsDropdown dropdown; private readonly InfoColumn startDateColumn; private readonly InfoColumn endDateColumn; @@ -51,73 +46,68 @@ namespace osu.Game.Overlays.Rankings { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Add(content = new Container + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + background = new Box { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - new Container + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN }, + Child = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN }, - Child = new FillFlowContainer + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new Container { - new Container - { - Margin = new MarginPadding { Vertical = 20 }, - RelativeSizeAxes = Axes.X, - Height = 40, - Depth = -float.MaxValue, - Child = dropdown = new SpotlightsDropdown - { - RelativeSizeAxes = Axes.X, - Current = Current - } - }, - new Container + Margin = new MarginPadding { Vertical = 20 }, + RelativeSizeAxes = Axes.X, + Height = 40, + Depth = -float.MaxValue, + Child = dropdown = new SpotlightsDropdown { RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + Current = Current + } + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Margin = new MarginPadding { Bottom = 5 }, + Children = new Drawable[] { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Margin = new MarginPadding { Bottom = 5 }, - Children = new Drawable[] - { - startDateColumn = new InfoColumn(@"Start Date"), - endDateColumn = new InfoColumn(@"End Date"), - mapCountColumn = new InfoColumn(@"Map Count"), - participantsColumn = new InfoColumn(@"Participants") - } - }, - new RankingsSortTabControl - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - Current = Sort + startDateColumn = new InfoColumn(@"Start Date"), + endDateColumn = new InfoColumn(@"End Date"), + mapCountColumn = new InfoColumn(@"Map Count"), + participantsColumn = new InfoColumn(@"Participants") } + }, + new RankingsSortTabControl + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + Current = Sort } } } } } } - }); + }; } [BackgroundDependencyLoader] @@ -134,10 +124,6 @@ namespace osu.Game.Overlays.Rankings participantsColumn.Value = response.Spotlight.Participants?.ToString("N0"); } - protected override void PopIn() => content.FadeIn(duration, Easing.OutQuint); - - protected override void PopOut() => content.FadeOut(duration, Easing.OutQuint); - private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); private class InfoColumn : FillFlowContainer diff --git a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs index 0f9b07bf89..61339df76f 100644 --- a/osu.Game/Overlays/Rankings/SpotlightsLayout.cs +++ b/osu.Game/Overlays/Rankings/SpotlightsLayout.cs @@ -81,8 +81,6 @@ namespace osu.Game.Overlays.Rankings { base.LoadComplete(); - selector.Show(); - selectedSpotlight.BindValueChanged(_ => onSpotlightChanged()); sort.BindValueChanged(_ => onSpotlightChanged()); Ruleset.BindValueChanged(onRulesetChanged); From ad9492804a645ea851f815b23878e4ab98211f6c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 21 Jul 2020 22:56:44 +0300 Subject: [PATCH 23/37] Apply suggestions --- osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs | 2 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs index 01c13dbc97..2a76b8e265 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneOverlayHeader.cs @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); addHeader("Orange OverlayHeader (no background, 100 padding)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange); - addHeader("Blue OverlayHeader (default 70 padding)", new TestNoControlHeader(), OverlayColourScheme.Blue); + addHeader("Blue OverlayHeader (default 50 padding)", new TestNoControlHeader(), OverlayColourScheme.Blue); addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green); addHeader("Pink TabControlOverlayHeader (enum, 30 padding)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink); addHeader("Red BreadcrumbControlOverlayHeader (no background, 10 padding)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red); diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 2895fa0726..2e5f1071f2 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Profile public ProfileHeader() { - ContentSidePadding = 70; + ContentSidePadding = UserProfileOverlay.CONTENT_X_MARGIN; User.ValueChanged += e => updateDisplay(e.NewValue); From cccb47e6e04e956dc4cfe73dfdff8c2bdc993526 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 11:29:23 +0900 Subject: [PATCH 24/37] Add user cover background to expanded version of score panel --- osu.Game/Screens/Ranking/ScorePanel.cs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Ranking/ScorePanel.cs b/osu.Game/Screens/Ranking/ScorePanel.cs index 9633f5c533..5da432d5b2 100644 --- a/osu.Game/Screens/Ranking/ScorePanel.cs +++ b/osu.Game/Screens/Ranking/ScorePanel.cs @@ -13,6 +13,7 @@ using osu.Framework.Input.Events; using osu.Game.Scoring; using osu.Game.Screens.Ranking.Contracted; using osu.Game.Screens.Ranking.Expanded; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -142,7 +143,16 @@ namespace osu.Game.Screens.Ranking CornerRadius = 20, CornerExponent = 2.5f, Masking = true, - Child = middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both } + Children = new[] + { + middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both }, + new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + User = Score.User, + Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.5f), Color4Extensions.FromHex("#444").Opacity(0)) + }, + } }, middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both } } @@ -155,18 +165,10 @@ namespace osu.Game.Screens.Ranking { base.LoadComplete(); - if (state == PanelState.Expanded) - { - topLayerBackground.FadeColour(expanded_top_layer_colour); - middleLayerBackground.FadeColour(expanded_middle_layer_colour); - } - else - { - topLayerBackground.FadeColour(contracted_top_layer_colour); - middleLayerBackground.FadeColour(contracted_middle_layer_colour); - } - updateState(); + + topLayerBackground.FinishTransforms(false, nameof(Colour)); + middleLayerBackground.FinishTransforms(false, nameof(Colour)); } private PanelState state = PanelState.Contracted; From ac602846df9d6a6be5b70672b537fe126cd0274e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 16:37:24 +0900 Subject: [PATCH 25/37] Expose balance and sample loading methods in DrawableHitObject --- .../Objects/Drawables/DrawableHitObject.cs | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index b633cb0860..f275153ce3 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); - loadSamples(); + LoadSamples(); } protected override void LoadComplete() @@ -145,14 +145,14 @@ namespace osu.Game.Rulesets.Objects.Drawables } samplesBindable = HitObject.SamplesBindable.GetBoundCopy(); - samplesBindable.CollectionChanged += (_, __) => loadSamples(); + samplesBindable.CollectionChanged += (_, __) => LoadSamples(); apply(HitObject); updateState(ArmedState.Idle, true); } - private void loadSamples() + protected virtual void LoadSamples() { if (Samples != null) { @@ -353,17 +353,32 @@ namespace osu.Game.Rulesets.Objects.Drawables [Resolved(canBeNull: true)] private GameplayClock gameplayClock { get; set; } + /// + /// Calculate the position to be used for sample playback at a specified X position (0..1). + /// + /// The lookup X position. Generally should be . + /// + protected double CalculateSamplePlaybackBalance(double position) + { + const float balance_adjust_amount = 0.4f; + + return balance_adjust_amount * (userPositionalHitSounds.Value ? position - 0.5f : 0); + } + + /// + /// Whether samples should currently be playing. Will be false during seek operations. + /// + protected bool ShouldPlaySamples => gameplayClock?.IsSeeking != true; + /// /// Plays all the hit sounds for this . /// This is invoked automatically when this is hit. /// public virtual void PlaySamples() { - const float balance_adjust_amount = 0.4f; - - if (Samples != null && gameplayClock?.IsSeeking != true) + if (Samples != null && ShouldPlaySamples) { - Samples.Balance.Value = balance_adjust_amount * (userPositionalHitSounds.Value ? SamplePlaybackPosition - 0.5f : 0); + Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition); Samples.Play(); } } From 3ed40d3a6b1fd14413920fc70208a71e4beebf99 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 16:37:53 +0900 Subject: [PATCH 26/37] Fix SkinnableSounds not continuing playback on skin change --- osu.Game/Skinning/SkinnableSound.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs index 24d6648273..49f9f01cff 100644 --- a/osu.Game/Skinning/SkinnableSound.cs +++ b/osu.Game/Skinning/SkinnableSound.cs @@ -98,6 +98,8 @@ namespace osu.Game.Skinning protected override void SkinChanged(ISkinSource skin, bool allowFallback) { + bool wasPlaying = samplesContainer.Any(s => s.Playing); + var channels = hitSamples.Select(s => { var ch = skin.GetSample(s); @@ -121,6 +123,9 @@ namespace osu.Game.Skinning }).Where(c => c != null); samplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c)); + + if (wasPlaying) + Play(); } } } From 2126f6bffc9d613706e12c4ef153c1fb7cb567ab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 16:37:38 +0900 Subject: [PATCH 27/37] Add slider "sliding" sample support --- .../Objects/Drawables/DrawableSlider.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 72502c02cd..5059ec1231 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using osuTK; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -11,6 +12,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Scoring; using osuTK.Graphics; using osu.Game.Skinning; @@ -81,6 +83,41 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var drawableHitObject in NestedHitObjects) drawableHitObject.AccentColour.Value = colour.NewValue; }, true); + + Tracking.BindValueChanged(updateSlidingSample); + } + + private SkinnableSound slidingSample; + + protected override void LoadSamples() + { + base.LoadSamples(); + + slidingSample?.Expire(); + + var firstSample = HitObject.Samples.FirstOrDefault(); + + if (firstSample != null) + { + var clone = HitObject.SampleControlPoint.ApplyTo(firstSample); + clone.Name = "sliderslide"; + + AddInternal(slidingSample = new SkinnableSound(clone) + { + Looping = true + }); + } + } + + private void updateSlidingSample(ValueChangedEvent tracking) + { + // note that samples will not start playing if exiting a seek operation in the middle of a slider. + // may be something we want to address at a later point, but not so easy to make happen right now + // (SkinnableSound would need to expose whether the sample is already playing and this logic would need to run in Update). + if (tracking.NewValue && ShouldPlaySamples) + slidingSample?.Play(); + else + slidingSample?.Stop(); } protected override void AddNestedHitObject(DrawableHitObject hitObject) @@ -156,6 +193,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Tracking.Value = Ball.Tracking; + if (Tracking.Value && slidingSample != null) + // keep the sliding sample playing at the current tracking position + slidingSample.Balance.Value = CalculateSamplePlaybackBalance(Ball.X / OsuPlayfield.BASE_SIZE.X); + double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); Ball.UpdateProgress(completionProgress); From 0957c5f74ce0bdf1e3fc6524d18d0021780abb86 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Jul 2020 18:29:50 +0900 Subject: [PATCH 28/37] Re-namespace multiplayer requests/responses --- .../Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs | 1 - .../Requests/Responses => Multiplayer}/APICreatedRoom.cs | 3 +-- osu.Game/Online/{API => Multiplayer}/APIPlaylistBeatmap.cs | 2 +- .../{API/Requests/Responses => Multiplayer}/APIScoreToken.cs | 2 +- .../{API/Requests => Multiplayer}/CreateRoomRequest.cs | 5 ++--- .../{API/Requests => Multiplayer}/CreateRoomScoreRequest.cs | 4 ++-- .../Requests => Multiplayer}/GetRoomPlaylistScoresRequest.cs | 3 ++- .../Online/{API/Requests => Multiplayer}/GetRoomRequest.cs | 4 ++-- .../{API/Requests => Multiplayer}/GetRoomScoresRequest.cs | 3 ++- .../Online/{API/Requests => Multiplayer}/GetRoomsRequest.cs | 4 ++-- .../Online/{API/Requests => Multiplayer}/JoinRoomRequest.cs | 4 ++-- .../Online/{API/Requests => Multiplayer}/PartRoomRequest.cs | 4 ++-- osu.Game/Online/{API => Multiplayer}/RoomScore.cs | 4 ++-- .../{API/Requests => Multiplayer}/SubmitRoomScoreRequest.cs | 3 ++- osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs | 1 - osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs | 1 - osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs | 1 - osu.Game/Screens/Multi/RoomManager.cs | 1 - 18 files changed, 23 insertions(+), 27 deletions(-) rename osu.Game/Online/{API/Requests/Responses => Multiplayer}/APICreatedRoom.cs (78%) rename osu.Game/Online/{API => Multiplayer}/APIPlaylistBeatmap.cs (94%) rename osu.Game/Online/{API/Requests/Responses => Multiplayer}/APIScoreToken.cs (85%) rename osu.Game/Online/{API/Requests => Multiplayer}/CreateRoomRequest.cs (86%) rename osu.Game/Online/{API/Requests => Multiplayer}/CreateRoomScoreRequest.cs (90%) rename osu.Game/Online/{API/Requests => Multiplayer}/GetRoomPlaylistScoresRequest.cs (92%) rename osu.Game/Online/{API/Requests => Multiplayer}/GetRoomRequest.cs (84%) rename osu.Game/Online/{API/Requests => Multiplayer}/GetRoomScoresRequest.cs (89%) rename osu.Game/Online/{API/Requests => Multiplayer}/GetRoomsRequest.cs (94%) rename osu.Game/Online/{API/Requests => Multiplayer}/JoinRoomRequest.cs (90%) rename osu.Game/Online/{API/Requests => Multiplayer}/PartRoomRequest.cs (90%) rename osu.Game/Online/{API => Multiplayer}/RoomScore.cs (97%) rename osu.Game/Online/{API/Requests => Multiplayer}/SubmitRoomScoreRequest.cs (95%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs index 9fc7c336cb..0da1e11fee 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using NUnit.Framework; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs b/osu.Game/Online/Multiplayer/APICreatedRoom.cs similarity index 78% rename from osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs rename to osu.Game/Online/Multiplayer/APICreatedRoom.cs index a554101bc7..2a3bb39647 100644 --- a/osu.Game/Online/API/Requests/Responses/APICreatedRoom.cs +++ b/osu.Game/Online/Multiplayer/APICreatedRoom.cs @@ -2,9 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using Newtonsoft.Json; -using osu.Game.Online.Multiplayer; -namespace osu.Game.Online.API.Requests.Responses +namespace osu.Game.Online.Multiplayer { public class APICreatedRoom : Room { diff --git a/osu.Game/Online/API/APIPlaylistBeatmap.cs b/osu.Game/Online/Multiplayer/APIPlaylistBeatmap.cs similarity index 94% rename from osu.Game/Online/API/APIPlaylistBeatmap.cs rename to osu.Game/Online/Multiplayer/APIPlaylistBeatmap.cs index 4f7786e880..98972ef36d 100644 --- a/osu.Game/Online/API/APIPlaylistBeatmap.cs +++ b/osu.Game/Online/Multiplayer/APIPlaylistBeatmap.cs @@ -6,7 +6,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; -namespace osu.Game.Online.API +namespace osu.Game.Online.Multiplayer { public class APIPlaylistBeatmap : APIBeatmap { diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs b/osu.Game/Online/Multiplayer/APIScoreToken.cs similarity index 85% rename from osu.Game/Online/API/Requests/Responses/APIScoreToken.cs rename to osu.Game/Online/Multiplayer/APIScoreToken.cs index 1d2465bedf..1f0063d94e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreToken.cs +++ b/osu.Game/Online/Multiplayer/APIScoreToken.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; -namespace osu.Game.Online.API.Requests.Responses +namespace osu.Game.Online.Multiplayer { public class APIScoreToken { diff --git a/osu.Game/Online/API/Requests/CreateRoomRequest.cs b/osu.Game/Online/Multiplayer/CreateRoomRequest.cs similarity index 86% rename from osu.Game/Online/API/Requests/CreateRoomRequest.cs rename to osu.Game/Online/Multiplayer/CreateRoomRequest.cs index c848c55cc6..dcb4ed51ea 100644 --- a/osu.Game/Online/API/Requests/CreateRoomRequest.cs +++ b/osu.Game/Online/Multiplayer/CreateRoomRequest.cs @@ -4,10 +4,9 @@ using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Multiplayer; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class CreateRoomRequest : APIRequest { diff --git a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs b/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs similarity index 90% rename from osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs rename to osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs index e6246b4f1f..f973f96b37 100644 --- a/osu.Game/Online/API/Requests/CreateRoomScoreRequest.cs +++ b/osu.Game/Online/Multiplayer/CreateRoomScoreRequest.cs @@ -3,9 +3,9 @@ using System.Net.Http; using osu.Framework.IO.Network; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class CreateRoomScoreRequest : APIRequest { diff --git a/osu.Game/Online/API/Requests/GetRoomPlaylistScoresRequest.cs b/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs similarity index 92% rename from osu.Game/Online/API/Requests/GetRoomPlaylistScoresRequest.cs rename to osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs index 38f852870b..833a761f42 100644 --- a/osu.Game/Online/API/Requests/GetRoomPlaylistScoresRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs @@ -3,8 +3,9 @@ using System.Collections.Generic; using Newtonsoft.Json; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class GetRoomPlaylistScoresRequest : APIRequest { diff --git a/osu.Game/Online/API/Requests/GetRoomRequest.cs b/osu.Game/Online/Multiplayer/GetRoomRequest.cs similarity index 84% rename from osu.Game/Online/API/Requests/GetRoomRequest.cs rename to osu.Game/Online/Multiplayer/GetRoomRequest.cs index 531e1857de..2907b49f1d 100644 --- a/osu.Game/Online/API/Requests/GetRoomRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomRequest.cs @@ -1,9 +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 osu.Game.Online.Multiplayer; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class GetRoomRequest : APIRequest { diff --git a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs b/osu.Game/Online/Multiplayer/GetRoomScoresRequest.cs similarity index 89% rename from osu.Game/Online/API/Requests/GetRoomScoresRequest.cs rename to osu.Game/Online/Multiplayer/GetRoomScoresRequest.cs index eb53369d18..bc913030dd 100644 --- a/osu.Game/Online/API/Requests/GetRoomScoresRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomScoresRequest.cs @@ -2,9 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class GetRoomScoresRequest : APIRequest> { diff --git a/osu.Game/Online/API/Requests/GetRoomsRequest.cs b/osu.Game/Online/Multiplayer/GetRoomsRequest.cs similarity index 94% rename from osu.Game/Online/API/Requests/GetRoomsRequest.cs rename to osu.Game/Online/Multiplayer/GetRoomsRequest.cs index c47ed20909..64e0386f77 100644 --- a/osu.Game/Online/API/Requests/GetRoomsRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomsRequest.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using Humanizer; using osu.Framework.IO.Network; -using osu.Game.Online.Multiplayer; +using osu.Game.Online.API; using osu.Game.Screens.Multi.Lounge.Components; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class GetRoomsRequest : APIRequest> { diff --git a/osu.Game/Online/API/Requests/JoinRoomRequest.cs b/osu.Game/Online/Multiplayer/JoinRoomRequest.cs similarity index 90% rename from osu.Game/Online/API/Requests/JoinRoomRequest.cs rename to osu.Game/Online/Multiplayer/JoinRoomRequest.cs index b0808afa45..74375af856 100644 --- a/osu.Game/Online/API/Requests/JoinRoomRequest.cs +++ b/osu.Game/Online/Multiplayer/JoinRoomRequest.cs @@ -3,9 +3,9 @@ using System.Net.Http; using osu.Framework.IO.Network; -using osu.Game.Online.Multiplayer; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class JoinRoomRequest : APIRequest { diff --git a/osu.Game/Online/API/Requests/PartRoomRequest.cs b/osu.Game/Online/Multiplayer/PartRoomRequest.cs similarity index 90% rename from osu.Game/Online/API/Requests/PartRoomRequest.cs rename to osu.Game/Online/Multiplayer/PartRoomRequest.cs index c988cd5c9e..54bb005d96 100644 --- a/osu.Game/Online/API/Requests/PartRoomRequest.cs +++ b/osu.Game/Online/Multiplayer/PartRoomRequest.cs @@ -3,9 +3,9 @@ using System.Net.Http; using osu.Framework.IO.Network; -using osu.Game.Online.Multiplayer; +using osu.Game.Online.API; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class PartRoomRequest : APIRequest { diff --git a/osu.Game/Online/API/RoomScore.cs b/osu.Game/Online/Multiplayer/RoomScore.cs similarity index 97% rename from osu.Game/Online/API/RoomScore.cs rename to osu.Game/Online/Multiplayer/RoomScore.cs index 3c7f8c9833..97f378856f 100644 --- a/osu.Game/Online/API/RoomScore.cs +++ b/osu.Game/Online/Multiplayer/RoomScore.cs @@ -6,13 +6,13 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using osu.Game.Online.Multiplayer; +using osu.Game.Online.API; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Users; -namespace osu.Game.Online.API +namespace osu.Game.Online.Multiplayer { public class RoomScore { diff --git a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs b/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs similarity index 95% rename from osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs rename to osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs index 8eb2952159..f725ea5dc9 100644 --- a/osu.Game/Online/API/Requests/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs @@ -4,9 +4,10 @@ using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; +using osu.Game.Online.API; using osu.Game.Scoring; -namespace osu.Game.Online.API.Requests +namespace osu.Game.Online.Multiplayer { public class SubmitRoomScoreRequest : APIRequest { diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs index 571bbde716..1afbf5c32a 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Online.Multiplayer; diff --git a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs index cf0197d26b..c2381fe219 100644 --- a/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs +++ b/osu.Game/Screens/Multi/Play/TimeshiftPlayer.cs @@ -10,7 +10,6 @@ using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Framework.Screens; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Scoring; diff --git a/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs b/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs index 5cafc974f1..f367d44347 100644 --- a/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs +++ b/osu.Game/Screens/Multi/Ranking/TimeshiftResultsScreen.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Scoring; using osu.Game.Screens.Ranking; diff --git a/osu.Game/Screens/Multi/RoomManager.cs b/osu.Game/Screens/Multi/RoomManager.cs index 491be2e946..2a96fa536d 100644 --- a/osu.Game/Screens/Multi/RoomManager.cs +++ b/osu.Game/Screens/Multi/RoomManager.cs @@ -14,7 +14,6 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API; -using osu.Game.Online.API.Requests; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets; using osu.Game.Screens.Multi.Lounge.Components; From e423630b7cbec15c0457089513ff0af85822591b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Jul 2020 18:37:00 +0900 Subject: [PATCH 29/37] Rename RoomScore -> MultiplayerScore --- .../Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs | 4 ++-- osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs | 2 +- .../Online/Multiplayer/{RoomScore.cs => MultiplayerScore.cs} | 2 +- osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game/Online/Multiplayer/{RoomScore.cs => MultiplayerScore.cs} (98%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs index 0da1e11fee..0023866124 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTimeshiftResultsScreen.cs @@ -64,11 +64,11 @@ namespace osu.Game.Tests.Visual.Multiplayer private void bindHandler(double delay = 0) { - var roomScores = new List(); + var roomScores = new List(); for (int i = 0; i < 10; i++) { - roomScores.Add(new RoomScore + roomScores.Add(new MultiplayerScore { ID = i, Accuracy = 0.9 - 0.01 * i, diff --git a/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs b/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs index 833a761f42..3d3bd20ff3 100644 --- a/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs +++ b/osu.Game/Online/Multiplayer/GetRoomPlaylistScoresRequest.cs @@ -24,6 +24,6 @@ namespace osu.Game.Online.Multiplayer public class RoomPlaylistScores { [JsonProperty("scores")] - public List Scores { get; set; } + public List Scores { get; set; } } } diff --git a/osu.Game/Online/Multiplayer/RoomScore.cs b/osu.Game/Online/Multiplayer/MultiplayerScore.cs similarity index 98% rename from osu.Game/Online/Multiplayer/RoomScore.cs rename to osu.Game/Online/Multiplayer/MultiplayerScore.cs index 97f378856f..3bbf19b11f 100644 --- a/osu.Game/Online/Multiplayer/RoomScore.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerScore.cs @@ -14,7 +14,7 @@ using osu.Game.Users; namespace osu.Game.Online.Multiplayer { - public class RoomScore + public class MultiplayerScore { [JsonProperty("id")] public int ID { get; set; } diff --git a/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs b/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs index f725ea5dc9..d31aef2ea5 100644 --- a/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/Multiplayer/SubmitRoomScoreRequest.cs @@ -9,7 +9,7 @@ using osu.Game.Scoring; namespace osu.Game.Online.Multiplayer { - public class SubmitRoomScoreRequest : APIRequest + public class SubmitRoomScoreRequest : APIRequest { private readonly int scoreId; private readonly int roomId; From 53a9ac3c1aa160bd1ccd8a23aa3833bd5f014e9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 19:06:39 +0900 Subject: [PATCH 30/37] Fix slider ball rotation being applied to follow circle and specular layer --- .../Objects/Drawables/Pieces/SliderBall.cs | 18 ++++-------- .../Skinning/LegacySliderBall.cs | 28 +++++++++++++++++-- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 395c76a233..b87e112d10 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private readonly Slider slider; private readonly Drawable followCircle; private readonly DrawableSlider drawableSlider; - private readonly CircularContainer ball; + private readonly Drawable ball; public SliderBall(Slider slider, DrawableSlider drawableSlider = null) { @@ -54,19 +54,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Alpha = 0, Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()), }, - ball = new CircularContainer + ball = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()) { - Masking = true, - RelativeSizeAxes = Axes.Both, - Origin = Anchor.Centre, Anchor = Anchor.Centre, - Alpha = 1, - Child = new Container - { - RelativeSizeAxes = Axes.Both, - Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()), - } - } + Origin = Anchor.Centre, + }, }; } @@ -187,7 +179,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return; Position = newPos; - Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); + ball.Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI); lastPosition = newPos; } diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs index b4ed75d97c..0f586034d5 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacySliderBall.cs @@ -15,6 +15,9 @@ namespace osu.Game.Rulesets.Osu.Skinning { private readonly Drawable animationContent; + private Sprite layerNd; + private Sprite layerSpec; + public LegacySliderBall(Drawable animationContent) { this.animationContent = animationContent; @@ -29,18 +32,37 @@ namespace osu.Game.Rulesets.Osu.Skinning InternalChildren = new[] { - new Sprite + layerNd = new Sprite { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Texture = skin.GetTexture("sliderb-nd"), Colour = new Color4(5, 5, 5, 255), }, - animationContent, - new Sprite + animationContent.With(d => { + d.Anchor = Anchor.Centre; + d.Origin = Anchor.Centre; + }), + layerSpec = new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Texture = skin.GetTexture("sliderb-spec"), Blending = BlendingParameters.Additive, }, }; } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + //undo rotation on layers which should not be rotated. + float appliedRotation = Parent.Rotation; + + layerNd.Rotation = -appliedRotation; + layerSpec.Rotation = -appliedRotation; + } } } From bd6a51f545a5121d98e57f3e8894094d3cb1e738 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 19:30:10 +0900 Subject: [PATCH 31/37] Hide slider repeat judgements temporarily --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs index 720ffcd51c..d79ecb7b4e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderRepeat.cs @@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly Drawable scaleContainer; + public override bool DisplayResult => false; + public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider) : base(sliderRepeat) { From 798bf0503818856b48f150b4598c2e01f340fdaf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 19:43:48 +0900 Subject: [PATCH 32/37] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 71d4e5aacf..c0c75b8d71 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2f3d08c528..e8c333b6b1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 2bb3914c25..8d1b837995 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - + From 2c62b23d859d46b1e4f3c21ea18e8c52a910b9c0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 19:53:45 +0900 Subject: [PATCH 33/37] Update naming --- .../Replays/CatchFramedReplayInputHandler.cs | 4 ++-- .../Replays/ManiaFramedReplayInputHandler.cs | 4 ++-- .../Replays/OsuFramedReplayInputHandler.cs | 15 +++------------ .../Replays/TaikoFramedReplayInputHandler.cs | 4 ++-- .../Visual/Gameplay/TestSceneReplayRecorder.cs | 2 +- .../Visual/Gameplay/TestSceneReplayRecording.cs | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 24c21fbc84..99d899db80 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -35,11 +35,11 @@ namespace osu.Game.Rulesets.Catch.Replays } } - public override void GetPendingInputs(List input) + public override void CollectPendingInputs(List inputs) { if (!Position.HasValue) return; - input.Add(new CatchReplayState + inputs.Add(new CatchReplayState { PressedActions = CurrentFrame?.Actions ?? new List(), CatcherX = Position.Value diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index 26c4ccf289..aa0c148caf 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -18,9 +18,9 @@ namespace osu.Game.Rulesets.Mania.Replays protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any(); - public override void GetPendingInputs(List input) + public override void CollectPendingInputs(List inputs) { - input.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); + inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); } } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs index 5c803539c2..cf48dc053f 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuFramedReplayInputHandler.cs @@ -36,19 +36,10 @@ namespace osu.Game.Rulesets.Osu.Replays } } - public override void GetPendingInputs(List input) + public override void CollectPendingInputs(List inputs) { - input.Add( - new MousePositionAbsoluteInput - { - Position = GamefieldToScreenSpace(Position ?? Vector2.Zero) - }); - input.Add( - new ReplayState - { - PressedActions = CurrentFrame?.Actions ?? new List() - }); - ; + inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(Position ?? Vector2.Zero) }); + inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index 7361d4efa8..138e8f9785 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -18,9 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Replays protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any(); - public override void GetPendingInputs(List input) + public override void CollectPendingInputs(List inputs) { - input.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); + inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); } } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs index e473f49826..bc1c10e59d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecorder.cs @@ -173,7 +173,7 @@ namespace osu.Game.Tests.Visual.Gameplay { } - public override void GetPendingInputs(List inputs) + public override void CollectPendingInputs(List inputs) { inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) }); inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs index e891ed617a..c0f99db85d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayRecording.cs @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Gameplay { } - public override void GetPendingInputs(List inputs) + public override void CollectPendingInputs(List inputs) { inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) }); inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); From 113fac84ddf195b10d1ae3a9b1cd1e437c94d0ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Jul 2020 21:14:04 +0900 Subject: [PATCH 34/37] Fix circle container type --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index b87e112d10..07dc6021c9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces lastPosition = newPos; } - private class FollowCircleContainer : Container + private class FollowCircleContainer : CircularContainer { public override bool HandlePositionalInput => true; } From acff270e969cde58d12893fc891351d3d06afdbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Jul 2020 19:14:18 +0900 Subject: [PATCH 35/37] Fix failing test by moving slider closer --- osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index c3b4d2625e..854626d362 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Osu.Tests const double time_slider = 1500; const double time_circle = 1510; Vector2 positionCircle = Vector2.Zero; - Vector2 positionSlider = new Vector2(80); + Vector2 positionSlider = new Vector2(30); var hitObjects = new List { From f883cb85d72ff2f98ec87a1f207e239b805e2c8b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 Jul 2020 21:24:31 +0900 Subject: [PATCH 36/37] Null out the sample too --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 5059ec1231..07f40f763b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -94,6 +94,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.LoadSamples(); slidingSample?.Expire(); + slidingSample = null; var firstSample = HitObject.Samples.FirstOrDefault(); From d0b35d7b32895ff3f988c0f6e85fa86eaacaad0f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Jul 2020 22:13:37 +0900 Subject: [PATCH 37/37] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index c0c75b8d71..e5b0245dd0 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e8c333b6b1..5af28ae11a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 8d1b837995..4a94ec33d8 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -80,7 +80,7 @@ - +