From f00676e6ee8121a6344bd04f3b4814711319429b Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sun, 24 Dec 2017 20:25:23 +0100 Subject: [PATCH 001/133] initial commit to allow filtering / selecting different tabs / etc still wip tho bleh bleh --- osu.Game/Overlays/Social/FilterControl.cs | 2 +- osu.Game/Overlays/Social/Header.cs | 4 +- osu.Game/Overlays/SocialOverlay.cs | 167 +++++++++++++++------- 3 files changed, 119 insertions(+), 54 deletions(-) diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index cf4097643e..03acd9bf13 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { Rank, - //Location, + Location, //[Description("Time Zone")] //TimeZone, //[Description("World Map")] diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 2674854327..e15b16085b 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -55,8 +55,8 @@ namespace osu.Game.Overlays.Social { [Description("Online Players")] OnlinePlayers, - //[Description("Online Friends")] - //OnlineFriends, + [Description("Online Friends")] + OnlineFriends, //[Description("Online Team Members")] //OnlineTeamMembers, //[Description("Chat Channels")] diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 954a838461..84469c5e40 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -9,19 +9,23 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Graphics.Cursor; 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 osu.Framework.Configuration; +using osu.Framework.Threading; +using System.Threading.Tasks; namespace osu.Game.Overlays { - public class SocialOverlay : SearchableListOverlay, IOnlineComponent + public class SocialOverlay : SearchableListOverlay { - private readonly FillFlowContainer panelFlow; + private APIAccess api; + + private FillFlowContainer panels; protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b"); protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"672b51"); @@ -30,28 +34,19 @@ namespace osu.Game.Overlays protected override SearchableListHeader CreateHeader() => new Header(); protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - private IEnumerable users; private readonly LoadingAnimation loading; + private IEnumerable users; + public IEnumerable Users { get { return users; } set { - if (users?.Equals(value) ?? false) return; - users = value; + if (users?.Equals(value) ?? false) + return; - if (users == null) - panelFlow.Clear(); - else - { - panelFlow.ChildrenEnumerable = users.Select(u => - { - var p = new UserPanel(u) { Width = 300 }; - p.Status.BindTo(u.Status); - return p; - }); - } + users = value?.ToList(); } } @@ -62,59 +57,129 @@ namespace osu.Game.Overlays ThirdWaveColour = OsuColour.FromHex(@"9b2b6e"); FourthWaveColour = OsuColour.FromHex(@"6d214d"); - ScrollFlow.Children = new[] + Add(loading = new LoadingAnimation()); + + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; + + // TODO sort our list in some way (either locally or with API call) + //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + + Header.Tabs.Current.ValueChanged += tab => { - new OsuContextMenuContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = panelFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 20 }, - Spacing = new Vector2(10f), - } - }, + currentQuery.Value = string.Empty; + Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; + Scheduler.AddOnce(updateSearch); }; - Add(loading = new LoadingAnimation()); + currentQuery.ValueChanged += v => + { + queryChangedDebounce?.Cancel(); + + if (string.IsNullOrEmpty(v)) + Scheduler.AddOnce(updateSearch); + else + { + Users = null; + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + } + }; + + currentQuery.BindTo(Filter.Search.Current); + + Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + + Scheduler.AddOnce(updateSearch); // so it displays something once it's first opened } [BackgroundDependencyLoader] private void load(APIAccess api) { - if (Users == null) - reloadUsers(api); + this.api = api; } - private void reloadUsers(APIAccess api) + private void recreatePanels(PanelDisplayStyle displayStyle) { - Users = null; + if (Users == null) + return; - // no this is not the correct data source, but it's something. - var request = new GetUsersRequest(); - request.Success += res => + if (panels != null) { - Users = res.Select(e => e.User); - loading.Hide(); + panels.FadeOut(200); + panels.Expire(); + panels = null; + } + + var newPanels = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10f), + Margin = new MarginPadding { Top = 10 }, + ChildrenEnumerable = Users.Select(u => + { + UserPanel panel = new UserPanel(u); + switch (displayStyle) + { + case PanelDisplayStyle.Grid: + panel.Width = 300; + break; + default: + panel.RelativeSizeAxes = Axes.X; + break; + } + panel.Status.BindTo(u.Status); + return panel; + }) }; - api.Queue(request); - loading.Show(); + LoadComponentAsync(newPanels, p => + { + if (panels != null) + ScrollFlow.Remove(panels); + + ScrollFlow.Add(panels = newPanels); + }); } - public void APIStateChanged(APIAccess api, APIState state) + private GetUsersRequest getUsersRequest; + + private readonly Bindable currentQuery = new Bindable(); + + private ScheduledDelegate queryChangedDebounce; + + private void updateSearch() { - switch (state) + queryChangedDebounce?.Cancel(); + + if (!IsLoaded) + return; + + Users = null; + loading.Hide(); + getUsersRequest?.Cancel(); + + if (api == null || api.State == APIState.Offline) + return; + + getUsersRequest = new GetUsersRequest(); // TODO filter/sort values?!? + + getUsersRequest.Success += response => { - case APIState.Online: - reloadUsers(api); - break; - default: - Users = null; - break; - } + Task.Run(() => + { + var newUsers = response.Select(r => r.User); + + Schedule(() => + { + Users = newUsers; + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + loading.Hide(); + }); + }); + }; + + loading.Show(); + api.Queue(getUsersRequest); } } From e2a1b18a2c32108f386422366c737377021d4978 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 25 Dec 2017 14:17:35 +0100 Subject: [PATCH 002/133] fix selecting different tab causing filter to change by itself and minor cleanup --- osu.Game/Overlays/SocialOverlay.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 84469c5e40..39b644e469 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -64,12 +64,7 @@ namespace osu.Game.Overlays // TODO sort our list in some way (either locally or with API call) //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); - Header.Tabs.Current.ValueChanged += tab => - { - currentQuery.Value = string.Empty; - Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; - Scheduler.AddOnce(updateSearch); - }; + Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); currentQuery.ValueChanged += v => { @@ -86,7 +81,7 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); - Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); Scheduler.AddOnce(updateSearch); // so it displays something once it's first opened } @@ -99,9 +94,6 @@ namespace osu.Game.Overlays private void recreatePanels(PanelDisplayStyle displayStyle) { - if (Users == null) - return; - if (panels != null) { panels.FadeOut(200); @@ -109,6 +101,9 @@ namespace osu.Game.Overlays panels = null; } + if (Users == null) + return; + var newPanels = new FillFlowContainer { RelativeSizeAxes = Axes.X, From 0fe78bee6ec1e81c17764982ab90e5a530196395 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 25 Dec 2017 16:11:50 +0100 Subject: [PATCH 003/133] center user panels --- osu.Game/Overlays/SocialOverlay.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 39b644e469..051cf5d6d2 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -112,7 +112,11 @@ namespace osu.Game.Overlays Margin = new MarginPadding { Top = 10 }, ChildrenEnumerable = Users.Select(u => { - UserPanel panel = new UserPanel(u); + UserPanel panel = new UserPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }; switch (displayStyle) { case PanelDisplayStyle.Grid: From 66f076815f8fa82e4938e369cdb81e7118989a45 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 28 Dec 2017 19:32:06 +0100 Subject: [PATCH 004/133] query friends endpoint to fetch friendlist --- .../Online/API/Requests/GetFriendsRequest.cs | 13 +++++ osu.Game/Overlays/Social/FilterControl.cs | 2 +- osu.Game/Overlays/SocialOverlay.cs | 58 ++++++++++++------- osu.Game/osu.Game.csproj | 1 + 4 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Online/API/Requests/GetFriendsRequest.cs diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs new file mode 100644 index 0000000000..a06471fd74 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests +{ + public class GetFriendsRequest : APIRequest> + { + protected override string Target => @"friends"; + } +} diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index 03acd9bf13..cf4097643e 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { Rank, - Location, + //Location, //[Description("Time Zone")] //TimeZone, //[Description("World Map")] diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 051cf5d6d2..3d62775c84 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -64,7 +64,7 @@ namespace osu.Game.Overlays // TODO sort our list in some way (either locally or with API call) //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); - Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); currentQuery.ValueChanged += v => { @@ -81,7 +81,7 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); - Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); Scheduler.AddOnce(updateSearch); // so it displays something once it's first opened } @@ -141,6 +141,7 @@ namespace osu.Game.Overlays } private GetUsersRequest getUsersRequest; + private GetFriendsRequest getFriendsRequest; private readonly Bindable currentQuery = new Bindable(); @@ -155,33 +156,50 @@ namespace osu.Game.Overlays Users = null; loading.Hide(); - getUsersRequest?.Cancel(); + clearRequests(); if (api == null || api.State == APIState.Offline) return; - getUsersRequest = new GetUsersRequest(); // TODO filter/sort values?!? - - getUsersRequest.Success += response => + switch (Header.Tabs.Current.Value) { - Task.Run(() => - { - var newUsers = response.Select(r => r.User); - - Schedule(() => - { - Users = newUsers; - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); - loading.Hide(); - }); - }); - }; - + case SocialTab.OnlinePlayers: + getUsersRequest = new GetUsersRequest(); // TODO filter??? + getUsersRequest.Success += response => finishRequest(response.Select(r => r.User)); + queueRequest(getUsersRequest); + break; + case SocialTab.OnlineFriends: + getFriendsRequest = new GetFriendsRequest(); // TODO filter??? + getFriendsRequest.Success += finishRequest; + queueRequest(getFriendsRequest); + break; + } loading.Show(); - api.Queue(getUsersRequest); } + + private void clearRequests() + { + getUsersRequest?.Cancel(); + getFriendsRequest?.Cancel(); + } + + private void finishRequest(IEnumerable newUsers) + { + Task.Run(() => + { + Schedule(() => + { + Users = newUsers; + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + loading.Hide(); + }); + }); + } + + private void queueRequest(APIRequest request) => api.Queue(request); } + public enum SortDirection { Descending, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 94678106bf..29deea5771 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -268,6 +268,7 @@ + From 53cd47a192cfc051279c358c5f4d52864e98cc56 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 28 Dec 2017 19:34:49 +0100 Subject: [PATCH 005/133] Updated submodule osu-resources --- osu-resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-resources b/osu-resources index 4287ee8043..e01f71160f 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 4287ee8043fb1419017359bc3a5db5dc06bc643f +Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 From 7ecc693e3492296ace03aa0e37d271e3b92349ac Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 28 Dec 2017 19:35:29 +0100 Subject: [PATCH 006/133] Updated submodule osu-framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 08f85f9bf9..10cae790c6 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 08f85f9bf9a7376aec8dfcde8c7c96d267d8c295 +Subproject commit 10cae790c6f1d559c326f9438958d0b012d61dc6 From 8a02900c014be3b2117fef243aa099e0d7deff14 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 30 Dec 2017 11:33:06 +0100 Subject: [PATCH 007/133] changed titles from social tabs --- osu.Game/Overlays/Social/Header.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index e15b16085b..94368d9786 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -53,9 +53,9 @@ namespace osu.Game.Overlays.Social public enum SocialTab { - [Description("Online Players")] + [Description("Players")] OnlinePlayers, - [Description("Online Friends")] + [Description("Friends")] OnlineFriends, //[Description("Online Team Members")] //OnlineTeamMembers, From 72af5bf67242133655655777e487e3f9ae1521e1 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 30 Dec 2017 11:51:49 +0100 Subject: [PATCH 008/133] simplify socialoverlay user request structure --- osu.Game/Overlays/SocialOverlay.cs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 3d62775c84..219672b76d 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -140,8 +140,7 @@ namespace osu.Game.Overlays }); } - private GetUsersRequest getUsersRequest; - private GetFriendsRequest getFriendsRequest; + private APIRequest getUsersRequest; private readonly Bindable currentQuery = new Bindable(); @@ -156,7 +155,7 @@ namespace osu.Game.Overlays Users = null; loading.Hide(); - clearRequests(); + getUsersRequest?.Cancel(); if (api == null || api.State == APIState.Offline) return; @@ -165,24 +164,17 @@ namespace osu.Game.Overlays { case SocialTab.OnlinePlayers: getUsersRequest = new GetUsersRequest(); // TODO filter??? - getUsersRequest.Success += response => finishRequest(response.Select(r => r.User)); - queueRequest(getUsersRequest); + ((GetUsersRequest)getUsersRequest).Success += response => finishRequest(response.Select(r => r.User)); break; case SocialTab.OnlineFriends: - getFriendsRequest = new GetFriendsRequest(); // TODO filter??? - getFriendsRequest.Success += finishRequest; - queueRequest(getFriendsRequest); + getUsersRequest = new GetFriendsRequest(); // TODO filter??? + ((GetFriendsRequest)getUsersRequest).Success += finishRequest; break; } + api.Queue(getUsersRequest); loading.Show(); } - private void clearRequests() - { - getUsersRequest?.Cancel(); - getFriendsRequest?.Cancel(); - } - private void finishRequest(IEnumerable newUsers) { Task.Run(() => @@ -195,11 +187,8 @@ namespace osu.Game.Overlays }); }); } - - private void queueRequest(APIRequest request) => api.Queue(request); } - public enum SortDirection { Descending, From d37ba2c9a4b51853de432cba3f1d1992f8a7001c Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 30 Dec 2017 11:54:03 +0100 Subject: [PATCH 009/133] disable searching/filtering with textbox it doesn't do anything except from creating unnecessary requests for now --- osu.Game/Overlays/SocialOverlay.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 219672b76d..a65e2f9e77 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -66,18 +66,18 @@ namespace osu.Game.Overlays Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); - currentQuery.ValueChanged += v => - { - queryChangedDebounce?.Cancel(); + //currentQuery.ValueChanged += v => + //{ + // queryChangedDebounce?.Cancel(); - if (string.IsNullOrEmpty(v)) - Scheduler.AddOnce(updateSearch); - else - { - Users = null; - queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - } - }; + // if (string.IsNullOrEmpty(v)) + // Scheduler.AddOnce(updateSearch); + // else + // { + // Users = null; + // queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + // } + //}; currentQuery.BindTo(Filter.Search.Current); From 760d2aff4bdbd73f33ac10a9ed0858048657220f Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 30 Dec 2017 12:56:18 +0100 Subject: [PATCH 010/133] readd IOnlineComponent to be able to react to APIState changes --- osu.Game/Overlays/SocialOverlay.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index a65e2f9e77..3dafecc6df 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -21,7 +21,7 @@ using System.Threading.Tasks; namespace osu.Game.Overlays { - public class SocialOverlay : SearchableListOverlay + public class SocialOverlay : SearchableListOverlay, IOnlineComponent { private APIAccess api; @@ -90,6 +90,7 @@ namespace osu.Game.Overlays private void load(APIAccess api) { this.api = api; + api.Register(this); } private void recreatePanels(PanelDisplayStyle displayStyle) @@ -187,6 +188,20 @@ namespace osu.Game.Overlays }); }); } + + public void APIStateChanged(APIAccess api, APIState state) + { + switch (state) + { + case APIState.Online: + Scheduler.AddOnce(updateSearch); + break; + default: + Users = null; + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + break; + } + } } public enum SortDirection From f03e064c430479080fc2dc70d37e4050505584a5 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 30 Dec 2017 12:57:32 +0100 Subject: [PATCH 011/133] remove unnecessary update --- osu.Game/Overlays/SocialOverlay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 3dafecc6df..d2f56f4061 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -82,8 +82,6 @@ namespace osu.Game.Overlays currentQuery.BindTo(Filter.Search.Current); Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); - - Scheduler.AddOnce(updateSearch); // so it displays something once it's first opened } [BackgroundDependencyLoader] From 3ba5dce052224276e96ca5de1cc8c731e0f434ff Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Sun, 31 Dec 2017 11:15:14 -0500 Subject: [PATCH 012/133] new Approach to approach rate --- .../Beatmaps/OsuBeatmapProcessor.cs | 5 ++++- osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 8 +++----- .../Drawables/Connections/FollowPointRenderer.cs | 8 ++++---- .../Objects/Drawables/DrawableHitCircle.cs | 6 +++--- .../Objects/Drawables/DrawableOsuHitObject.cs | 13 ++++++------- .../Objects/Drawables/DrawableSpinner.cs | 4 ++-- .../Objects/Drawables/Pieces/SliderBody.cs | 2 +- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 10 ++++++++++ osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 15 ++++++++------- 9 files changed, 41 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 31b374f71d..e8742d24a6 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -37,7 +37,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps private void applyStacking(Beatmap beatmap) { const int stack_distance = 3; - float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; // Reset stacking for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++) @@ -58,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps continue; double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectN.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the next object. @@ -112,6 +112,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Spinner) continue; double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectI.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the previous object. @@ -165,6 +166,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; + if (objectI.StartTime - objectN.StartTime > stackThreshold) //We are no longer within stacking range of the previous object. break; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index 7b1f80f439..dd01ef9af7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -36,14 +36,12 @@ namespace osu.Game.Rulesets.Osu.Mods private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; - private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT; - public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var d in drawables.OfType()) { d.ApplyCustomUpdateState += ApplyHiddenState; - d.FadeInDuration = preEmpt * fade_in_duration_multiplier; + d.FadeInDuration = d.HitObject.TimePreempt * fade_in_duration_multiplier; } } @@ -52,8 +50,8 @@ namespace osu.Game.Rulesets.Osu.Mods if (!(drawable is DrawableOsuHitObject d)) return; - var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration; - var fadeOutDuration = preEmpt * fade_out_duration_multiplier; + var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.FadeInDuration; + var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index fca9187047..60ee10193f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -96,12 +96,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN); - fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.FadeIn(currHitObject.TimeFadein); + fp.ScaleTo(1, currHitObject.TimeFadein, Easing.Out); - fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.MoveTo(pointEndPosition, currHitObject.TimeFadein, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(DrawableOsuHitObject.TIME_FADEIN); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadein); } fp.Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 6220bbd120..bb405ea7fd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -88,8 +88,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdatePreemptState(); - ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT)); - ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT); + ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, HitObject.TimePreempt)); + ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); } protected override void UpdateCurrentState(ArmedState state) @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - this.Delay(TIME_PREEMPT).FadeOut(500); + this.Delay(HitObject.TimePreempt).FadeOut(500); Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f5f0300ae1..1a8ec68df2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -10,26 +10,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public const float TIME_PREEMPT = 600; - public const float TIME_FADEIN = 400; - /// /// The number of milliseconds used to fade in. /// - public virtual double FadeInDuration { get; set; } = TIME_FADEIN; + public virtual double FadeInDuration { get; set; } - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - TIME_PREEMPT; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { + FadeInDuration = hitObject.TimeFadein; + AccentColour = HitObject.ComboColour; Alpha = 0; } protected sealed override void UpdateState(ArmedState state) { - double transformTime = HitObject.StartTime - TIME_PREEMPT; + double transformTime = HitObject.StartTime - HitObject.TimePreempt; base.ApplyTransformsAt(transformTime, true); base.ClearTransformsAfter(transformTime, true); @@ -38,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) + using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) UpdateCurrentState(state); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 5351ad50c4..e471ad4e9b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -191,14 +191,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdatePreemptState(); circleContainer.ScaleTo(spinner.Scale * 0.3f); - circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); + circleContainer.ScaleTo(spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); Disc.RotateTo(-720); symbol.RotateTo(-720); mainContainer .ScaleTo(0) - .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, Easing.OutQuint) + .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) .Then() .ScaleTo(1, 500, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 75c2c15084..4914ec07c0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public void UpdateProgress(double progress, int repeat) { double start = 0; - double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1; + double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1; if (repeat >= slider.RepeatCount - 1) { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index a3a6527b31..0a96d6367a 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects private const double hit_window_100 = 80; private const double hit_window_300 = 30; + public float TimePreempt = 600; + public float TimeFadein = 400; + public Vector2 Position { get; set; } public float X => Position.X; public float Y => Position.Y; @@ -72,6 +75,13 @@ namespace osu.Game.Rulesets.Osu.Objects { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + if (difficulty.ApproachRate >= 5) + TimePreempt = 1200 - (difficulty.ApproachRate - 5) * 150; + else + TimePreempt = 1800 - difficulty.ApproachRate * 120; + TimeFadein = TimePreempt / 3; + + Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index ba774e887f..a4c345f96c 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using System; using System.Diagnostics; using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; @@ -133,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Replays // Do some nice easing for cursor movements if (Frames.Count > 0) { - moveToHitObject(h.StartTime, startPosition, h.Radius, easing); + moveToHitObject(h, startPosition, easing); } // Add frames to click the hitobject @@ -191,12 +192,12 @@ namespace osu.Game.Rulesets.Osu.Replays } } - private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, Easing easing) + private void moveToHitObject(OsuHitObject h, Vector2 targetPos, Easing easing) { ReplayFrame lastFrame = Frames[Frames.Count - 1]; // Wait until Auto could "see and react" to the next note. - double waitTime = targetTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime); + double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime); if (waitTime > lastFrame.Time) { lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); @@ -205,17 +206,17 @@ namespace osu.Game.Rulesets.Osu.Replays Vector2 lastPosition = lastFrame.Position; - double timeDifference = ApplyModsToTime(targetTime - lastFrame.Time); + double timeDifference = ApplyModsToTime(h.StartTime - lastFrame.Time); // Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up. if (timeDifference > 0 && // Sanity checks - ((lastPosition - targetPos).Length > hitObjectRadius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough + ((lastPosition - targetPos).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. { // Perform eased movement - for (double time = lastFrame.Time + FrameDelay; time < targetTime; time += FrameDelay) + for (double time = lastFrame.Time + FrameDelay; time < h.StartTime; time += FrameDelay) { - Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, targetTime, easing); + Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, h.StartTime, easing); AddFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); } From 064758b96d9eac2bd9be26be6ff6ea84e52594ee Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Sun, 31 Dec 2017 11:30:58 -0500 Subject: [PATCH 013/133] fixes --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 4 ++-- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 9 +-------- .../Objects/Drawables/DrawableSlider.cs | 10 ++-------- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 2 -- 8 files changed, 8 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index e8742d24a6..8ed6573d41 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Beatmaps { diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index dd01ef9af7..ba21cd8a10 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Mods foreach (var d in drawables.OfType()) { d.ApplyCustomUpdateState += ApplyHiddenState; - d.FadeInDuration = d.HitObject.TimePreempt * fade_in_duration_multiplier; + d.HitObject.TimeFadein = d.HitObject.TimePreempt * (float)fade_in_duration_multiplier; } } @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Mods if (!(drawable is DrawableOsuHitObject d)) return; - var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.FadeInDuration; + var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.HitObject.TimeFadein; var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index bb405ea7fd..6ecfd82e89 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdatePreemptState(); - ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, HitObject.TimePreempt)); + ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadein * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 1a8ec68df2..788ca43a0d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -10,18 +10,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - /// - /// The number of milliseconds used to fade in. - /// - public virtual double FadeInDuration { get; set; } - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { - FadeInDuration = hitObject.TimeFadein; - AccentColour = HitObject.ComboColour; Alpha = 0; } @@ -42,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected virtual void UpdatePreemptState() => this.FadeIn(FadeInDuration); + protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein); protected virtual void UpdateCurrentState(ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 5a8bcae277..f604ca6ccd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var tick in s.NestedHitObjects.OfType()) { var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2); + var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? HitObject.TimeFadein : HitObject.TimeFadein / 2); var fadeOutTime = repeatStartTime + repeatDuration; var drawableTick = new DrawableSliderTick(tick) @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables foreach (var repeatPoint in s.NestedHitObjects.OfType()) { var repeatStartTime = s.StartTime + repeatPoint.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2); + var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? HitObject.TimeFadein : HitObject.TimeFadein / 2); var fadeOutTime = repeatStartTime + repeatDuration; var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this) @@ -106,12 +106,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private int currentRepeat; public bool Tracking; - public override double FadeInDuration - { - get { return base.FadeInDuration; } - set { InitialCircle.FadeInDuration = base.FadeInDuration = value; } - } - protected override void Update() { base.Update(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index e471ad4e9b..1e2ec0a112 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton); if (!spmCounter.IsPresent && Disc.Tracking) - spmCounter.FadeIn(FadeInDuration); + spmCounter.FadeIn(HitObject.TimeFadein); base.Update(); } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 0a96d6367a..1c0f64322f 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = 1200 - (difficulty.ApproachRate - 5) * 150; else TimePreempt = 1800 - difficulty.ApproachRate * 120; - TimeFadein = TimePreempt / 3; + TimeFadein = TimePreempt * 0.66f; Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index a4c345f96c..29820883e9 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -5,11 +5,9 @@ using OpenTK; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; using System; using System.Diagnostics; using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; From 1502fde1b047580e83fbc3713615e5b744a9c9a7 Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Sun, 31 Dec 2017 12:04:31 -0500 Subject: [PATCH 014/133] fix slider start circles --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index f604ca6ccd..c7034bc5be 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -58,7 +58,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Scale = s.Scale, ComboColour = s.ComboColour, Samples = s.Samples, - SampleControlPoint = s.SampleControlPoint + SampleControlPoint = s.SampleControlPoint, + TimePreempt = s.TimePreempt, + TimeFadein = s.TimeFadein }) }; From 8957d82c894e38a598dc600edf96cffc013a33f9 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Mon, 1 Jan 2018 13:54:59 +0100 Subject: [PATCH 015/133] Updated submodule osu-framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 10cae790c6..6134dafccb 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 10cae790c6f1d559c326f9438958d0b012d61dc6 +Subproject commit 6134dafccb3368dac96d837537325c04b89fb8ee From 1df79c2f1b984018f4b4e7a14bdda4f85b5e45ff Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Mon, 1 Jan 2018 10:30:09 -0500 Subject: [PATCH 016/133] Move stackThreshold up where possible --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 8ed6573d41..ed19381243 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -99,6 +99,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectI = beatmap.HitObjects[i]; if (objectI.StackHeight != 0 || objectI is Spinner) continue; + float stackThreshold = objectI.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; + /* If this object is a hitcircle, then we enter this "special" case. * It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider. * Any other case is handled by the "is Slider" code below this. @@ -111,7 +113,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Spinner) continue; double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; - float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectI.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the previous object. @@ -165,8 +166,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; - float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; - if (objectI.StartTime - objectN.StartTime > stackThreshold) //We are no longer within stacking range of the previous object. break; From e0beefdfd5b81113da47d6a005156693a6e094b0 Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Mon, 1 Jan 2018 10:30:55 -0500 Subject: [PATCH 017/133] make this a float --- osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index ba21cd8a10..8bd3c5f92d 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; public override double ScoreMultiplier => 1.06; - private const double fade_in_duration_multiplier = 0.4; + private const float fade_in_duration_multiplier = 0.4f; private const double fade_out_duration_multiplier = 0.3; public void ApplyToDrawableHitObjects(IEnumerable drawables) @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Mods foreach (var d in drawables.OfType()) { d.ApplyCustomUpdateState += ApplyHiddenState; - d.HitObject.TimeFadein = d.HitObject.TimePreempt * (float)fade_in_duration_multiplier; + d.HitObject.TimeFadein = d.HitObject.TimePreempt * fade_in_duration_multiplier; } } From a00f92dcb459eb1354bd691b0f1e4c13151e5cc0 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 2 Jan 2018 17:18:49 +0100 Subject: [PATCH 018/133] change unnecessary cast --- osu.Game/Overlays/SocialOverlay.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index d2f56f4061..024e3aee73 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -162,15 +162,16 @@ namespace osu.Game.Overlays switch (Header.Tabs.Current.Value) { case SocialTab.OnlinePlayers: - getUsersRequest = new GetUsersRequest(); // TODO filter??? - ((GetUsersRequest)getUsersRequest).Success += response => finishRequest(response.Select(r => r.User)); + var userRequest = new GetUsersRequest(); // TODO filter??? + userRequest.Success += response => finishRequest(response.Select(r => r.User)); + api.Queue(getUsersRequest = userRequest); break; case SocialTab.OnlineFriends: - getUsersRequest = new GetFriendsRequest(); // TODO filter??? - ((GetFriendsRequest)getUsersRequest).Success += finishRequest; + var friendRequest = new GetFriendsRequest(); // TODO filter??? + friendRequest.Success += finishRequest; + api.Queue(getUsersRequest = friendRequest); break; } - api.Queue(getUsersRequest); loading.Show(); } From 313dfd4d46a9b05d72cbaab2679baebe6b3cc616 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 2 Jan 2018 17:22:12 +0100 Subject: [PATCH 019/133] remove unnecessary task + rename method --- osu.Game/Overlays/SocialOverlay.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 024e3aee73..b72fddc908 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -163,28 +163,25 @@ namespace osu.Game.Overlays { case SocialTab.OnlinePlayers: var userRequest = new GetUsersRequest(); // TODO filter??? - userRequest.Success += response => finishRequest(response.Select(r => r.User)); + userRequest.Success += response => updateUsers(response.Select(r => r.User)); api.Queue(getUsersRequest = userRequest); break; case SocialTab.OnlineFriends: var friendRequest = new GetFriendsRequest(); // TODO filter??? - friendRequest.Success += finishRequest; + friendRequest.Success += updateUsers; api.Queue(getUsersRequest = friendRequest); break; } loading.Show(); } - private void finishRequest(IEnumerable newUsers) + private void updateUsers(IEnumerable newUsers) { - Task.Run(() => + Schedule(() => { - Schedule(() => - { - Users = newUsers; - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); - loading.Hide(); - }); + Users = newUsers; + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + loading.Hide(); }); } From 52c2ba49cf32415b875f3b62f32ffd0258b7cbe8 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 2 Jan 2018 17:42:44 +0100 Subject: [PATCH 020/133] make loading indicator more visible by deleting panels preemptively --- osu.Game/Overlays/SocialOverlay.cs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index b72fddc908..d9cbdf37c8 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -93,12 +93,7 @@ namespace osu.Game.Overlays private void recreatePanels(PanelDisplayStyle displayStyle) { - if (panels != null) - { - panels.FadeOut(200); - panels.Expire(); - panels = null; - } + clearPanels(); if (Users == null) return; @@ -139,6 +134,15 @@ namespace osu.Game.Overlays }); } + private void clearPanels() + { + if (panels != null) + { + panels.Expire(); + panels = null; + } + } + private APIRequest getUsersRequest; private readonly Bindable currentQuery = new Bindable(); @@ -153,10 +157,11 @@ namespace osu.Game.Overlays return; Users = null; + clearPanels(); loading.Hide(); getUsersRequest?.Cancel(); - if (api == null || api.State == APIState.Offline) + if (api?.IsLoggedIn == false) return; switch (Header.Tabs.Current.Value) @@ -180,8 +185,8 @@ namespace osu.Game.Overlays Schedule(() => { Users = newUsers; - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); loading.Hide(); + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); }); } From 699902234b395294f36dea482568ff1c1ac3507e Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 2 Jan 2018 17:58:11 +0100 Subject: [PATCH 021/133] remove unused code --- osu.Game/Overlays/SocialOverlay.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index d9cbdf37c8..979ce2c851 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -15,9 +15,6 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; -using osu.Framework.Configuration; -using osu.Framework.Threading; -using System.Threading.Tasks; namespace osu.Game.Overlays { @@ -79,7 +76,7 @@ namespace osu.Game.Overlays // } //}; - currentQuery.BindTo(Filter.Search.Current); + //currentQuery.BindTo(Filter.Search.Current); Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); } @@ -145,13 +142,13 @@ namespace osu.Game.Overlays private APIRequest getUsersRequest; - private readonly Bindable currentQuery = new Bindable(); + //private readonly Bindable currentQuery = new Bindable(); - private ScheduledDelegate queryChangedDebounce; + //private ScheduledDelegate queryChangedDebounce; private void updateSearch() { - queryChangedDebounce?.Cancel(); + //queryChangedDebounce?.Cancel(); if (!IsLoaded) return; From 23f3cb646799637e4bea2fb1beaf1342baec515d Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Wed, 3 Jan 2018 10:01:28 -0500 Subject: [PATCH 022/133] address review --- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 1c0f64322f..feffb1ccf2 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -75,11 +75,8 @@ namespace osu.Game.Rulesets.Osu.Objects { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - if (difficulty.ApproachRate >= 5) - TimePreempt = 1200 - (difficulty.ApproachRate - 5) * 150; - else - TimePreempt = 1800 - difficulty.ApproachRate * 120; - TimeFadein = TimePreempt * 0.66f; + TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450); + TimeFadein = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1200, 800, 300); Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; From 94f81a178433484be6fdd5abaa4e271808e622e6 Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Wed, 3 Jan 2018 10:04:36 -0500 Subject: [PATCH 023/133] fix --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 7ed8854665..df5cb18a02 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -190,15 +190,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdatePreemptState(); - circleContainer.ScaleTo(spinner.Scale * 0.3f); - circleContainer.ScaleTo(spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); + circleContainer.ScaleTo(Spinner.Scale * 0.3f); + circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); Disc.RotateTo(-720); symbol.RotateTo(-720); mainContainer .ScaleTo(0) - .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) + .ScaleTo(Spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) .Then() .ScaleTo(1, 500, Easing.OutQuint); } From 0e361aefebba2fc1d44d56313c7fc4b258a14756 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 3 Jan 2018 17:52:11 +0100 Subject: [PATCH 024/133] added new tabs and sort criteria --- osu.Game/Overlays/Social/FilterControl.cs | 2 ++ osu.Game/Overlays/Social/Header.cs | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index cf4097643e..a4d623892d 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -21,7 +21,9 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { + Relevance, Rank, + Name, //Location, //[Description("Time Zone")] //TimeZone, diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 94368d9786..7dd8222b0b 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -18,6 +18,7 @@ namespace osu.Game.Overlays.Social protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e"); protected override float TabStripWidth => 438; + protected override SocialTab DefaultTab => SocialTab.OnlinePlayers; protected override FontAwesome Icon => FontAwesome.fa_users; @@ -53,10 +54,11 @@ namespace osu.Game.Overlays.Social public enum SocialTab { + Search, [Description("Players")] - OnlinePlayers, + OnlinePlayers = SocialSortCriteria.Rank, [Description("Friends")] - OnlineFriends, + OnlineFriends = SocialSortCriteria.Name, //[Description("Online Team Members")] //OnlineTeamMembers, //[Description("Chat Channels")] From 988f6ac90128845153b30976b84f4dd62396898a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 3 Jan 2018 17:53:50 +0100 Subject: [PATCH 025/133] fix SortDirection default to descending when retrieved data is ascending --- osu.Game.Tests/Visual/TestCaseSocial.cs | 9 +++++++++ osu.Game/Overlays/SocialOverlay.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseSocial.cs b/osu.Game.Tests/Visual/TestCaseSocial.cs index ff0707c8ab..3f418174c7 100644 --- a/osu.Game.Tests/Visual/TestCaseSocial.cs +++ b/osu.Game.Tests/Visual/TestCaseSocial.cs @@ -1,13 +1,22 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Game.Overlays; +using osu.Game.Overlays.Social; using osu.Game.Users; namespace osu.Game.Tests.Visual { public class TestCaseSocial : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(FilterControl), + typeof(SocialOverlay) + }; + public TestCaseSocial() { SocialOverlay s = new SocialOverlay diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 979ce2c851..a0c4c2b18f 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -204,7 +204,7 @@ namespace osu.Game.Overlays public enum SortDirection { - Descending, Ascending, + Descending } } From 9d29adce27c5501bc89afbf7e1dcc7c64dee1281 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 3 Jan 2018 17:54:20 +0100 Subject: [PATCH 026/133] bring social tab+filter behaviour closer to direct --- osu.Game/Overlays/SocialOverlay.cs | 65 ++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index a0c4c2b18f..c4ed14022e 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays public class SocialOverlay : SearchableListOverlay, IOnlineComponent { private APIAccess api; - + private readonly LoadingAnimation loading; private FillFlowContainer panels; protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b"); @@ -31,10 +31,7 @@ namespace osu.Game.Overlays protected override SearchableListHeader CreateHeader() => new Header(); protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); - private readonly LoadingAnimation loading; - private IEnumerable users; - public IEnumerable Users { get { return users; } @@ -56,12 +53,38 @@ namespace osu.Game.Overlays Add(loading = new LoadingAnimation()); + Filter.Search.Current.ValueChanged += text => + { + if (text != string.Empty) + { + Header.Tabs.Current.Value = SocialTab.Search; + + if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank) + Filter.Tabs.Current.Value = SocialSortCriteria.Relevance; + } + else + { + Header.Tabs.Current.Value = SocialTab.OnlinePlayers; + + if (Filter.Tabs.Current.Value == SocialSortCriteria.Relevance) + Filter.Tabs.Current.Value = SocialSortCriteria.Rank; + } + }; + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; // TODO sort our list in some way (either locally or with API call) - //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); - Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); + Header.Tabs.Current.ValueChanged += tab => + { + if (tab != SocialTab.Search) + { + //currentQuery.Value = string.Empty; + Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; + Scheduler.AddOnce(updateSearch); + } + }; //currentQuery.ValueChanged += v => //{ @@ -70,15 +93,18 @@ namespace osu.Game.Overlays // if (string.IsNullOrEmpty(v)) // Scheduler.AddOnce(updateSearch); // else - // { - // Users = null; // queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - // } //}; //currentQuery.BindTo(Filter.Search.Current); - Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + Filter.Tabs.Current.ValueChanged += sortCriteria => + { + if (Header.Tabs.Current.Value != SocialTab.Search && sortCriteria != (SocialSortCriteria)Header.Tabs.Current.Value) + Header.Tabs.Current.Value = SocialTab.Search; + + Scheduler.AddOnce(updateSearch); + }; } [BackgroundDependencyLoader] @@ -122,19 +148,14 @@ namespace osu.Game.Overlays }) }; - LoadComponentAsync(newPanels, p => - { - if (panels != null) - ScrollFlow.Remove(panels); - - ScrollFlow.Add(panels = newPanels); - }); + LoadComponentAsync(newPanels, p => ScrollFlow.Add(panels = newPanels)); } private void clearPanels() { if (panels != null) { + ScrollFlow.Remove(panels); panels.Expire(); panels = null; } @@ -163,16 +184,16 @@ namespace osu.Game.Overlays switch (Header.Tabs.Current.Value) { - case SocialTab.OnlinePlayers: - var userRequest = new GetUsersRequest(); // TODO filter??? - userRequest.Success += response => updateUsers(response.Select(r => r.User)); - api.Queue(getUsersRequest = userRequest); - break; case SocialTab.OnlineFriends: var friendRequest = new GetFriendsRequest(); // TODO filter??? friendRequest.Success += updateUsers; api.Queue(getUsersRequest = friendRequest); break; + default: + var userRequest = new GetUsersRequest(); // TODO filter??? + userRequest.Success += response => updateUsers(response.Select(r => r.User)); + api.Queue(getUsersRequest = userRequest); + break; } loading.Show(); } From 9b70578af621783aabe280495047d12a11021d65 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 3 Jan 2018 19:01:10 +0100 Subject: [PATCH 027/133] enabled Location as filter tab forgot it QQ --- osu.Game/Overlays/Social/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index a4d623892d..bb60aaac51 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Social Relevance, Rank, Name, - //Location, + Location, //[Description("Time Zone")] //TimeZone, //[Description("World Map")] From 697efba5e2175aef9f275571c7ef9c6a25a08e40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 15:55:35 +0900 Subject: [PATCH 028/133] Replace .OfType with .Cast --- osu.Game/Rulesets/UI/Playfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b4a26344d5..5c32aeac73 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.UI public class HitObjectContainer : CompositeDrawable { - public virtual IEnumerable Objects => InternalChildren.OfType(); + public virtual IEnumerable Objects => InternalChildren.Cast(); public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); } From d0c9d71ee79bdb0f5ef786de3eba25276aa7905a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 4 Jan 2018 08:15:11 +0100 Subject: [PATCH 029/133] fix covers not showing in user panels --- osu.Game/Users/User.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 5c0e5f1f95..d4bdc05337 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -39,10 +39,14 @@ namespace osu.Game.Users public string AvatarUrl; [JsonProperty(@"cover_url")] - public string CoverUrl; + public string CoverUrl + { + get { return Cover?.Url; } + set { Cover = new UserCover { Url = value }; } + } - //[JsonProperty(@"cover")] - //public UserCover Cover; + [JsonProperty(@"cover")] + public UserCover Cover; public class UserCover { From 7beb4c3507b0dc13ace923c909b0325eabd2d4ca Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:21:15 +0900 Subject: [PATCH 030/133] Initial implementation of a new scrolling hitobject container --- .../Visual/TestCaseScrollingHitObjects.cs | 104 ++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 1 + 2 files changed, 105 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs new file mode 100644 index 0000000000..2827f70ebe --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -0,0 +1,104 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseScrollingHitObjects : OsuTestCase + { + public TestCaseScrollingHitObjects() + { + AddStep("Vertically-scrolling", () => createPlayfield(Direction.Vertical)); + AddStep("Horizontally-scrolling", () => createPlayfield(Direction.Horizontal)); + + AddStep("Add hitobject", addHitObject); + } + + private TestPlayfield playfield; + private void createPlayfield(Direction scrollingDirection) + { + if (playfield != null) + Remove(playfield); + Add(playfield = new TestPlayfield(scrollingDirection)); + } + + private void addHitObject() + { + playfield.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 5000 }) + { + Anchor = playfield.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }); + } + + private class ScrollingHitObjectContainer : Playfield.HitObjectContainer + { + public double TimeRange = 5000; + + private readonly Direction scrollingDirection; + + public ScrollingHitObjectContainer(Direction scrollingDirection) + { + this.scrollingDirection = scrollingDirection; + + RelativeSizeAxes = Axes.Both; + } + + protected override void Update() + { + base.Update(); + + foreach (var obj in Objects) + { + var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (scrollingDirection) + { + case Direction.Horizontal: + obj.X = finalPosition.X; + break; + case Direction.Vertical: + obj.Y = finalPosition.Y; + break; + } + } + } + } + + private class TestPlayfield : Playfield + { + public readonly Direction ScrollingDirection; + + public TestPlayfield(Direction scrollingDirection) + { + ScrollingDirection = scrollingDirection; + + HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + } + } + + private class TestDrawableHitObject : DrawableHitObject + { + public TestDrawableHitObject(HitObject hitObject) + : base(hitObject) + { + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + Add(new Box { Size = new Vector2(75) }); + } + + protected override void UpdateState(ArmedState state) + { + } + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 8c04874e75..f47a03990a 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -141,6 +141,7 @@ + From 2b79ad879f7df53567eec7845b89aaeea46ce076 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:37:48 +0900 Subject: [PATCH 031/133] Add a way to access alive hitobjects --- osu.Game/Rulesets/UI/Playfield.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 5c32aeac73..61014b5550 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -97,6 +97,8 @@ namespace osu.Game.Rulesets.UI public class HitObjectContainer : CompositeDrawable { public virtual IEnumerable Objects => InternalChildren.Cast(); + public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); } From b968040963a5c33ced93f7d8cdd28e8a96de77e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:07 +0900 Subject: [PATCH 032/133] General improvements to testcase --- .../Visual/TestCaseScrollingHitObjects.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 2827f70ebe..7b462b5cac 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +using System; +using System.Collections.Generic; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; @@ -12,27 +14,36 @@ namespace osu.Game.Tests.Visual { public class TestCaseScrollingHitObjects : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; + + private List playfields = new List(); + public TestCaseScrollingHitObjects() { - AddStep("Vertically-scrolling", () => createPlayfield(Direction.Vertical)); - AddStep("Horizontally-scrolling", () => createPlayfield(Direction.Horizontal)); + playfields.Add(new TestPlayfield(Direction.Vertical)); + playfields.Add(new TestPlayfield(Direction.Horizontal)); - AddStep("Add hitobject", addHitObject); + AddRange(playfields); } - private TestPlayfield playfield; - private void createPlayfield(Direction scrollingDirection) + protected override void LoadComplete() { - if (playfield != null) - Remove(playfield); - Add(playfield = new TestPlayfield(scrollingDirection)); + base.LoadComplete(); + + for (int i = 0; i <= 5000; i += 1000) + addHitObject(Time.Current + i); + + Scheduler.AddDelayed(() => addHitObject(Time.Current + 5000), 1000, true); } - private void addHitObject() + private void addHitObject(double time) { - playfield.Add(new TestDrawableHitObject(new HitObject { StartTime = Time.Current + 5000 }) + playfields.ForEach(p => { - Anchor = playfield.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + p.Add(new TestDrawableHitObject(new HitObject { StartTime = time }) + { + Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }); }); } From 210fd290e53d4b0b869c1482022b8ac02e209453 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:20 +0900 Subject: [PATCH 033/133] Use the new AliveObjects --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 7b462b5cac..f5b0a964a3 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual { base.Update(); - foreach (var obj in Objects) + foreach (var obj in AliveObjects) { var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; From c067ee5fbe4b12dbd5d03502a3891f8a0fce5500 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 16:38:43 +0900 Subject: [PATCH 034/133] Move position calculation to UpdateAfterChildren Because we want this to occur after lifetimes have been evaluated. --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index f5b0a964a3..03b95042b2 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -60,9 +60,9 @@ namespace osu.Game.Tests.Visual RelativeSizeAxes = Axes.Both; } - protected override void Update() + protected override void UpdateAfterChildren() { - base.Update(); + base.UpdateAfterChildren(); foreach (var obj in AliveObjects) { From 90839e6d56f3ad6528cfb67745614b00c68e507b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 17:07:16 +0900 Subject: [PATCH 035/133] Test case improvements with TimeRange testing --- .../Visual/TestCaseScrollingHitObjects.cs | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 03b95042b2..346ded046e 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -3,12 +3,15 @@ using System; using System.Collections.Generic; +using osu.Framework.Configuration; using OpenTK; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; +using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -16,14 +19,37 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; - private List playfields = new List(); + private readonly List playfields = new List(); public TestCaseScrollingHitObjects() { playfields.Add(new TestPlayfield(Direction.Vertical)); playfields.Add(new TestPlayfield(Direction.Horizontal)); - AddRange(playfields); + Add(new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.85f), + Masking = true, + BorderColour = Color4.White, + BorderThickness = 2, + MaskingSmoothness = 1, + Children = new Drawable[] + { + new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Alpha = 0.35f, + }, + playfields[0], + playfields[1] + } + }); + + AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); } protected override void LoadComplete() @@ -49,7 +75,11 @@ namespace osu.Game.Tests.Visual private class ScrollingHitObjectContainer : Playfield.HitObjectContainer { - public double TimeRange = 5000; + public readonly BindableDouble TimeRange = new BindableDouble + { + MinValue = 0, + MaxValue = double.MaxValue + }; private readonly Direction scrollingDirection; @@ -86,13 +116,18 @@ namespace osu.Game.Tests.Visual private class TestPlayfield : Playfield { + public readonly BindableDouble TimeRange = new BindableDouble(5000); + public readonly Direction ScrollingDirection; public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + var scrollingHitObjects = new ScrollingHitObjectContainer(scrollingDirection); + scrollingHitObjects.TimeRange.BindTo(TimeRange); + + HitObjects = scrollingHitObjects; } } From 0c5ab98965558a96b80d0efcda631ae0408407dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:35:33 +0900 Subject: [PATCH 036/133] Make MultiplierControlPoint's StartTime variable --- osu.Game/Rulesets/Timing/MultiplierControlPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 4f1a85cf2d..8b8bbae9d5 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Timing /// /// The time in milliseconds at which this starts. /// - public readonly double StartTime; + public double StartTime; /// /// The multiplier which this provides. From b11f4ab8341c7cbcb3ae28b6cf88c88e98cec0b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:35:48 +0900 Subject: [PATCH 037/133] Implement control points --- .../Visual/TestCaseScrollingHitObjects.cs | 94 +++++++++++++++++-- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 346ded046e..d226203b3b 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -8,8 +8,10 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Lists; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using OpenTK.Graphics; @@ -26,6 +28,8 @@ namespace osu.Game.Tests.Visual playfields.Add(new TestPlayfield(Direction.Vertical)); playfields.Add(new TestPlayfield(Direction.Horizontal)); + playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); + Add(new Container { Anchor = Anchor.Centre, @@ -50,6 +54,7 @@ namespace osu.Game.Tests.Visual }); AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); + AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); } protected override void LoadComplete() @@ -66,13 +71,35 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.Add(new TestDrawableHitObject(new HitObject { StartTime = time }) + p.Add(new TestDrawableHitObject(time) { Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre }); }); } + private void addControlPoint(double time) + { + playfields.ForEach(p => + { + p.HitObjects.ControlPoints.AddRange(new[] + { + new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }, + new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }, + new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }, + }); + + TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) + { + Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + }; + + p.Add(createDrawablePoint(time)); + p.Add(createDrawablePoint(time + 2000)); + p.Add(createDrawablePoint(time + 3000)); + }); + } + private class ScrollingHitObjectContainer : Playfield.HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble @@ -81,6 +108,8 @@ namespace osu.Game.Tests.Visual MaxValue = double.MaxValue }; + public readonly SortedList ControlPoints = new SortedList(); + private readonly Direction scrollingDirection; public ScrollingHitObjectContainer(Direction scrollingDirection) @@ -94,9 +123,11 @@ namespace osu.Game.Tests.Visual { base.UpdateAfterChildren(); + var currentMultiplier = controlPointAt(Time.Current); + foreach (var obj in AliveObjects) { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / TimeRange; + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); // Todo: We may need to consider scale here var finalPosition = (float)relativePosition * DrawSize; @@ -112,6 +143,24 @@ namespace osu.Game.Tests.Visual } } } + + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); + + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; + + searchingPoint.StartTime = time; + + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; + + return ControlPoints[index]; + } } private class TestPlayfield : Playfield @@ -120,21 +169,52 @@ namespace osu.Game.Tests.Visual public readonly Direction ScrollingDirection; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - var scrollingHitObjects = new ScrollingHitObjectContainer(scrollingDirection); - scrollingHitObjects.TimeRange.BindTo(TimeRange); + base.HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + HitObjects.TimeRange.BindTo(TimeRange); + } + } - HitObjects = scrollingHitObjects; + private class TestDrawableControlPoint : DrawableHitObject + { + private readonly Box box; + + public TestDrawableControlPoint(double time) + : base(new HitObject { StartTime = time }) + { + Origin = Anchor.Centre; + + Add(box = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + + protected override void Update() + { + base.Update(); + + RelativeSizeAxes = (Anchor & Anchor.x2) > 0 ? Axes.Y : Axes.X; + Size = new Vector2(1); + + box.Size = DrawSize; + } + + protected override void UpdateState(ArmedState state) + { } } private class TestDrawableHitObject : DrawableHitObject { - public TestDrawableHitObject(HitObject hitObject) - : base(hitObject) + public TestDrawableHitObject(double time) + : base(new HitObject { StartTime = time }) { Origin = Anchor.Centre; AutoSizeAxes = Axes.Both; From f34131f8f444a99e4088776a5fd107b3fd6d4f51 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 18:50:17 +0900 Subject: [PATCH 038/133] Initial game-wide replacement of scrolling playfields --- .../Drawable/DrawableCatchHitObject.cs | 5 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 1 - .../Mods/IGenerateSpeedAdjustments.cs | 23 -- .../Mods/ManiaModGravity.cs | 48 ---- .../Drawables/DrawableManiaHitObject.cs | 4 +- .../Tests/TestCaseManiaPlayfield.cs | 33 +-- .../Timing/GravityScrollingContainer.cs | 60 ----- .../Timing/ManiaSpeedAdjustmentContainer.cs | 29 --- .../Timing/ScrollingAlgorithm.cs | 17 -- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- .../UI/ManiaRulesetContainer.cs | 4 - .../osu.Game.Rulesets.Mania.csproj | 5 - .../Objects/Drawables/DrawableBarLine.cs | 2 +- .../Drawables/DrawableTaikoHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- .../Visual/TestCaseScrollingHitObjects.cs | 66 +----- .../Visual/TestCaseScrollingPlayfield.cs | 219 ------------------ osu.Game.Tests/osu.Game.Tests.csproj | 1 - .../Drawables/DrawableScrollingHitObject.cs | 67 ------ .../Timing/LinearScrollingContainer.cs | 28 --- .../Rulesets/Timing/ScrollingContainer.cs | 93 -------- .../Timing/SpeedAdjustmentContainer.cs | 114 --------- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 165 ++++--------- .../Rulesets/UI/ScrollingRulesetContainer.cs | 9 +- osu.Game/osu.Game.csproj | 4 - 27 files changed, 61 insertions(+), 948 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs delete mode 100644 osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs delete mode 100644 osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs delete mode 100644 osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs delete mode 100644 osu.Game/Rulesets/Timing/LinearScrollingContainer.cs delete mode 100644 osu.Game/Rulesets/Timing/ScrollingContainer.cs delete mode 100644 osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index a617b65676..8954f9fe9e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -24,14 +24,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } - public abstract class DrawableCatchHitObject : DrawableScrollingHitObject + public abstract class DrawableCatchHitObject : DrawableHitObject { protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { - RelativePositionAxes = Axes.Both; + RelativePositionAxes = Axes.X; X = hitObject.X; - Y = (float)HitObject.StartTime; } public Func CheckPosition; diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 76dbfa77c6..322d1d91af 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,12 +23,10 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Axes.Y) + : base(Direction.Vertical) { Container explodingFruitContainer; - Reversed.Value = true; - Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 070c7b09d1..4765f25808 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -95,7 +95,6 @@ namespace osu.Game.Rulesets.Mania new ModCinema(), }, }, - new ManiaModGravity() }; default: diff --git a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs b/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs deleted file mode 100644 index 954ee3f481..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Mods -{ - /// - /// A type of mod which generates speed adjustments that scroll the hit objects and bar lines. - /// - internal interface IGenerateSpeedAdjustments - { - /// - /// Applies this mod to a hit renderer. - /// - /// The hit renderer to apply to. - /// The per-column list of speed adjustments for hit objects. - /// The list of speed adjustments for bar lines. - void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges); - } -} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs deleted file mode 100644 index 70270af6c9..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Timing; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.Mania.Objects.Drawables; - -namespace osu.Game.Rulesets.Mania.Mods -{ - public class ManiaModGravity : Mod, IGenerateSpeedAdjustments - { - public override string Name => "Gravity"; - public override string ShortenedName => "GR"; - - public override double ScoreMultiplier => 0; - - public override FontAwesome Icon => FontAwesome.fa_sort_desc; - - public void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges) - { - // We have to generate one speed adjustment per hit object for gravity - foreach (ManiaHitObject obj in rulesetContainer.Objects.OfType()) - { - MultiplierControlPoint controlPoint = rulesetContainer.CreateControlPointAt(obj.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - hitObjectTimingChanges[obj.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - - // Like with hit objects, we need to generate one speed adjustment per bar line - foreach (DrawableBarLine barLine in rulesetContainer.BarLines) - { - var controlPoint = rulesetContainer.CreateControlPointAt(barLine.HitObject.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - barlineTimingChanges.Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 6354c6ff77..385f18a4f9 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,13 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using OpenTK.Graphics; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableScrollingHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { /// @@ -20,7 +19,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { - RelativePositionAxes = Axes.Y; HitObject = hitObject; if (action != null) diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs index b5890b289f..6615b39274 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs @@ -5,16 +5,13 @@ using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -44,10 +41,10 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right)); AddStep("Reversed", () => createPlayfield(4, SpecialColumnPosition.Normal, true)); - AddStep("Notes with input", () => createPlayfieldWithNotes(false)); - AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(false, true)); - AddStep("Notes with gravity", () => createPlayfieldWithNotes(true)); - AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true, true)); + AddStep("Notes with input", () => createPlayfieldWithNotes()); + AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(true)); + AddStep("Notes with gravity", () => createPlayfieldWithNotes()); + AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true)); AddStep("Hit explosion", () => { @@ -70,11 +67,6 @@ namespace osu.Game.Rulesets.Mania.Tests maniaRuleset = rulesets.GetRuleset(3); } - private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) - { - TimingPoint = { BeatLength = 1000 } - }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); - private ManiaPlayfield createPlayfield(int cols, SpecialColumnPosition specialPos, bool inverted = false) { Clear(); @@ -95,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Tests return playfield; } - private void createPlayfieldWithNotes(bool gravity, bool inverted = false) + private void createPlayfieldWithNotes(bool inverted = false) { Clear(); @@ -114,23 +106,14 @@ namespace osu.Game.Rulesets.Mania.Tests playfield.Inverted.Value = inverted; - if (!gravity) - playfield.Columns.ForEach(c => c.Add(createTimingChange(0, false))); - for (double t = start_time; t <= start_time + duration; t += 100) { - if (gravity) - playfield.Columns.ElementAt(0).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, Column = 0 }, ManiaAction.Key1)); - if (gravity) - playfield.Columns.ElementAt(3).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, @@ -138,9 +121,6 @@ namespace osu.Game.Rulesets.Mania.Tests }, ManiaAction.Key4)); } - if (gravity) - playfield.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, @@ -148,9 +128,6 @@ namespace osu.Game.Rulesets.Mania.Tests Column = 1 }, ManiaAction.Key2)); - if (gravity) - playfield.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, diff --git a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs deleted file mode 100644 index 699acc477b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - /// - /// A that emulates a form of gravity where hit objects speed up over time. - /// - internal class GravityScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public GravityScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // The gravity-adjusted start position - float startPos = (float)computeGravityTime(controlPoint.StartTime); - // The gravity-adjusted end position - float endPos = (float)computeGravityTime(controlPoint.StartTime + RelativeChildSize.Y); - - Y = startPos; - Height = endPos - startPos; - } - - /// - /// Applies gravity to a time value based on the current time. - /// - /// The time value gravity should be applied to. - /// The time after gravity is applied to . - private double computeGravityTime(double time) - { - double relativeTime = relativeTimeAt(time); - - // The sign of the relative time, this is used to apply backwards acceleration leading into startTime - double sign = relativeTime < 0 ? -1 : 1; - - return VisibleTimeRange - acceleration * relativeTime * relativeTime * sign; - } - - /// - /// The acceleration due to "gravity" of the content of this container. - /// - private double acceleration => 1 / VisibleTimeRange; - - /// - /// Computes the current time relative to , accounting for . - /// - /// The non-offset time. - /// The current time relative to - . - private double relativeTimeAt(double time) => Time.Current - time + VisibleTimeRange; - } -} diff --git a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs deleted file mode 100644 index 321b4ee92b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - public class ManiaSpeedAdjustmentContainer : SpeedAdjustmentContainer - { - private readonly ScrollingAlgorithm scrollingAlgorithm; - - public ManiaSpeedAdjustmentContainer(MultiplierControlPoint timingSection, ScrollingAlgorithm scrollingAlgorithm) - : base(timingSection) - { - this.scrollingAlgorithm = scrollingAlgorithm; - } - - protected override ScrollingContainer CreateScrollingContainer() - { - switch (scrollingAlgorithm) - { - default: - return base.CreateScrollingContainer(); - case ScrollingAlgorithm.Gravity: - return new GravityScrollingContainer(ControlPoint); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs b/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs deleted file mode 100644 index 72e096f5aa..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mania.Timing -{ - public enum ScrollingAlgorithm - { - /// - /// Basic scrolling algorithm based on the timing section time. This is the default algorithm. - /// - Basic, - /// - /// Emulating a form of gravity where hit objects speed up over time. - /// - Gravity - } -} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 2d553f8639..048b3ef9f9 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(Axes.Y) + : base(Direction.Vertical) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 6c164a34f0..549b0f2ee6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(Axes.Y) + : base(Direction.Vertical) { this.columnCount = columnCount; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 61446a31b6..db9475b31e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -17,12 +17,10 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mania.UI @@ -121,8 +119,6 @@ namespace osu.Game.Rulesets.Mania.UI protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); - protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic); - protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay, this); } } diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 3393774a9c..4445f24cd8 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -62,7 +62,6 @@ - @@ -88,8 +87,6 @@ - - @@ -97,9 +94,7 @@ - - diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index b30b3a1aca..97fa91a94b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableScrollingHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index cc7dd2fa0f..5cda186086 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -12,7 +12,7 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableScrollingHitObject, IKeyBindingHandler + public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler where TaikoHitType : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 3fdbd056ce..5e1fa7e490 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(Axes.X) + : base(Direction.Horizontal) { AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index d226203b3b..01387791a1 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -8,7 +8,6 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Lists; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; @@ -100,68 +99,7 @@ namespace osu.Game.Tests.Visual }); } - private class ScrollingHitObjectContainer : Playfield.HitObjectContainer - { - public readonly BindableDouble TimeRange = new BindableDouble - { - MinValue = 0, - MaxValue = double.MaxValue - }; - public readonly SortedList ControlPoints = new SortedList(); - - private readonly Direction scrollingDirection; - - public ScrollingHitObjectContainer(Direction scrollingDirection) - { - this.scrollingDirection = scrollingDirection; - - RelativeSizeAxes = Axes.Both; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - var currentMultiplier = controlPointAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - - // Todo: We may need to consider scale here - var finalPosition = (float)relativePosition * DrawSize; - - switch (scrollingDirection) - { - case Direction.Horizontal: - obj.X = finalPosition.X; - break; - case Direction.Vertical: - obj.Y = finalPosition.Y; - break; - } - } - } - - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) - { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); - - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; - - searchingPoint.StartTime = time; - - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; - - return ControlPoints[index]; - } - } private class TestPlayfield : Playfield { @@ -169,13 +107,13 @@ namespace osu.Game.Tests.Visual public readonly Direction ScrollingDirection; - public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; public TestPlayfield(Direction scrollingDirection) { ScrollingDirection = scrollingDirection; - base.HitObjects = new ScrollingHitObjectContainer(scrollingDirection); + base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(scrollingDirection); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs deleted file mode 100644 index 40fb22af1e..0000000000 --- a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.UI; -using osu.Game.Tests.Beatmaps; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - /// - /// The most minimal implementation of a playfield with scrolling hit objects. - /// - [TestFixture] - public class TestCaseScrollingPlayfield : OsuTestCase - { - public TestCaseScrollingPlayfield() - { - Clock = new FramedClock(); - - var objects = new List(); - - int time = 1500; - for (int i = 0; i < 50; i++) - { - objects.Add(new TestHitObject { StartTime = time }); - - time += 500; - } - - Beatmap b = new Beatmap - { - HitObjects = objects, - BeatmapInfo = new BeatmapInfo - { - BaseDifficulty = new BeatmapDifficulty(), - Metadata = new BeatmapMetadata() - } - }; - - WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - - TestRulesetContainer horizontalRulesetContainer; - Add(horizontalRulesetContainer = new TestRulesetContainer(Axes.X, beatmap, true)); - - TestRulesetContainer verticalRulesetContainer; - Add(verticalRulesetContainer = new TestRulesetContainer(Axes.Y, beatmap, true)); - - AddStep("Reverse direction", () => - { - horizontalRulesetContainer.Playfield.Reverse(); - verticalRulesetContainer.Playfield.Reverse(); - }); - } - - [Test] - public void TestSpeedAdjustmentOrdering() - { - var hitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.X); - - var speedAdjustments = new[] - { - new SpeedAdjustmentContainer(new MultiplierControlPoint()), - new SpeedAdjustmentContainer(new MultiplierControlPoint(1000) - { - TimingPoint = new TimingControlPoint { BeatLength = 500 } - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(2000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 2} - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(3000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 1} - }), - }; - - var hitObjects = new[] - { - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = -1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject()), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 2000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 3000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 4000 }), - }; - - hitObjects.ForEach(h => hitObjectContainer.Add(h)); - speedAdjustments.ForEach(hitObjectContainer.AddSpeedAdjustment); - - // The 0th index in hitObjectContainer.SpeedAdjustments is the "default" control point - // Check multiplier of the default speed adjustment - Assert.AreEqual(1, hitObjectContainer.SpeedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[1].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[2].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier); - - // Check insertion of hit objects - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[4].Contains(hitObjects[0])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[2].Contains(hitObjects[2])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[1].Contains(hitObjects[3])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[4])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[5])); - - hitObjectContainer.RemoveSpeedAdjustment(hitObjectContainer.SpeedAdjustments[3]); - - // The hit object contained in this speed adjustment should be resorted into the one occuring before it - - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - } - - private class TestRulesetContainer : ScrollingRulesetContainer - { - private readonly Axes scrollingAxes; - - public TestRulesetContainer(Axes scrollingAxes, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(null, beatmap, isForCurrentRuleset) - { - this.scrollingAxes = scrollingAxes; - } - - public new TestPlayfield Playfield => base.Playfield; - - public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); - - public override PassThroughInputManager CreateInputManager() => new PassThroughInputManager(); - - protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); - - protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes); - - protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h); - } - - private class TestScoreProcessor : ScoreProcessor - { - protected override void OnNewJudgement(Judgement judgement) - { - } - } - - private class TestBeatmapConverter : BeatmapConverter - { - protected override IEnumerable ValidConversionTypes => new[] { typeof(HitObject) }; - - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) - { - yield return original as TestHitObject; - } - } - - private class DrawableTestHitObject : DrawableScrollingHitObject - { - public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject) - : base(hitObject) - { - Anchor = scrollingAxes == Axes.Y ? Anchor.TopCentre : Anchor.CentreLeft; - Origin = Anchor.Centre; - - AutoSizeAxes = Axes.Both; - - Add(new Circle - { - Size = new Vector2(50) - }); - } - - protected override void UpdateState(ArmedState state) - { - } - } - - private class TestPlayfield : ScrollingPlayfield - { - protected override Container Content => content; - private readonly Container content; - - public TestPlayfield(Axes scrollingAxes) - : base(scrollingAxes) - { - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f - }, - content = new Container { RelativeSizeAxes = Axes.Both } - }; - } - - public void Reverse() => Reversed.Toggle(); - } - - - private class TestHitObject : HitObject - { - } - } -} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index f47a03990a..2eb79f6b35 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -142,7 +142,6 @@ - diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs deleted file mode 100644 index 538bb826ad..0000000000 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Objects.Drawables -{ - /// - /// A basic class that overrides and implements . - /// This object does not need to have its set to be able to scroll, as this will - /// will be set by the scrolling container that contains it. - /// - public abstract class DrawableScrollingHitObject : DrawableHitObject, IScrollingHitObject - where TObject : HitObject - { - public BindableDouble LifetimeOffset { get; } = new BindableDouble(); - - Axes IScrollingHitObject.ScrollingAxes - { - set - { - RelativePositionAxes |= value; - - if ((value & Axes.X) > 0) - X = (float)HitObject.StartTime; - if ((value & Axes.Y) > 0) - Y = (float)HitObject.StartTime; - } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - protected DrawableScrollingHitObject(TObject hitObject) - : base(hitObject) - { - } - - private double? lifetimeStart; - public override double LifetimeStart - { - get { return lifetimeStart ?? HitObject.StartTime - LifetimeOffset; } - set { lifetimeStart = value; } - } - - private double? lifetimeEnd; - public override double LifetimeEnd - { - get - { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - return lifetimeEnd ?? endTime + LifetimeOffset; - } - set { lifetimeEnd = value; } - } - - protected override void AddNested(DrawableHitObject h) - { - var scrollingHitObject = h as IScrollingHitObject; - scrollingHitObject?.LifetimeOffset.BindTo(LifetimeOffset); - - base.AddNested(h); - } - } -} \ No newline at end of file diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs deleted file mode 100644 index b093cf3303..0000000000 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A which scrolls linearly relative to the start time. - /// - public class LinearScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public LinearScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void Update() - { - base.Update(); - - if ((ScrollingAxes & Axes.X) > 0) X = (float)(controlPoint.StartTime - Time.Current); - if ((ScrollingAxes & Axes.Y) > 0) Y = (float)(controlPoint.StartTime - Time.Current); - } - } -} diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs deleted file mode 100644 index eac596297a..0000000000 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Caching; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that scrolls relative to the current time. Will autosize to the total duration of all contained hit objects along the scrolling axes. - /// - public abstract class ScrollingContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// The axes through which this scrolls. This is set by the . - /// - internal Axes ScrollingAxes; - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The control point that defines the speed adjustments for this container. This is set by the . - /// - internal MultiplierControlPoint ControlPoint; - - private Cached durationBacking; - - /// - /// Creates a new . - /// - protected ScrollingContainer() - { - RelativeSizeAxes = Axes.Both; - RelativePositionAxes = Axes.Both; - } - - protected override int Compare(Drawable x, Drawable y) - { - var hX = (DrawableHitObject)x; - var hY = (DrawableHitObject)y; - - int result = hY.HitObject.StartTime.CompareTo(hX.HitObject.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } - - public override void Add(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - base.Add(drawable); - } - - public override bool Remove(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - return base.Remove(drawable); - } - - // Todo: This may underestimate the size of the hit object in some cases, but won't be too much of a problem for now - private double computeDuration() => Math.Max(0, Children.Select(c => (c.HitObject as IHasEndTime)?.EndTime ?? c.HitObject.StartTime).DefaultIfEmpty().Max() - ControlPoint.StartTime) + 1000; - - /// - /// An approximate total duration of this scrolling container. - /// - public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); - - protected override void Update() - { - base.Update(); - - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); - - // We want our size and position-space along the scrolling axes to span our duration to completely enclose all the hit objects - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)Duration : Size.X, (ScrollingAxes & Axes.Y) > 0 ? (float)Duration : Size.Y); - // And we need to make sure the hit object's position-space doesn't change due to our resizing - RelativeChildSize = Size; - } - } -} diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs deleted file mode 100644 index 81e3a5c70e..0000000000 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that provides the speed adjustments defined by s to affect the scroll speed - /// of container s. - /// - public class SpeedAdjustmentContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly Bindable VisibleTimeRange = new Bindable { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - protected override Container Content => content; - private readonly Container content; - - /// - /// The axes which the content of this container will scroll through. - /// - public Axes ScrollingAxes - { - get { return scrollingContainer.ScrollingAxes; } - set { scrollingContainer.ScrollingAxes = value; } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The that defines the speed adjustments. - /// - public readonly MultiplierControlPoint ControlPoint; - - private readonly ScrollingContainer scrollingContainer; - - /// - /// Creates a new . - /// - /// The that defines the speed adjustments. - public SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) - { - ControlPoint = controlPoint; - RelativeSizeAxes = Axes.Both; - - scrollingContainer = CreateScrollingContainer(); - scrollingContainer.ControlPoint = ControlPoint; - scrollingContainer.VisibleTimeRange.BindTo(VisibleTimeRange); - - AddInternal(content = scrollingContainer); - } - - protected override void Update() - { - float multiplier = (float)ControlPoint.Multiplier; - - // The speed adjustment happens by modifying our size by the multiplier while maintaining the visible time range as the relatve size for our children - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? multiplier : 1, (ScrollingAxes & Axes.Y) > 0 ? multiplier : 1); - - if (Reversed) - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)-VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)-VisibleTimeRange : 1); - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0); - Origin = Anchor = Anchor.BottomRight; - } - else - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); - RelativeChildOffset = Vector2.Zero; - Origin = Anchor = Anchor.TopLeft; - } - } - - public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; - public override double LifetimeEnd => ControlPoint.StartTime + scrollingContainer.Duration + VisibleTimeRange; - - public override void Add(DrawableHitObject drawable) - { - var scrollingHitObject = drawable as IScrollingHitObject; - - if (scrollingHitObject != null) - { - scrollingHitObject.LifetimeOffset.BindTo(VisibleTimeRange); - scrollingHitObject.ScrollingAxes = ScrollingAxes; - } - - base.Add(drawable); - } - - /// - /// Whether a point in time falls within this s affecting timespan. - /// - public bool CanContain(double startTime) => ControlPoint.StartTime <= startTime; - - /// - /// Creates the which contains the scrolling s of this container. - /// - /// The . - protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ControlPoint); - } -} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 395248b2fd..56959240a8 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -1,15 +1,13 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; -using System.Linq; using OpenTK.Input; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; +using osu.Framework.Lists; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; @@ -50,11 +48,6 @@ namespace osu.Game.Rulesets.UI MaxValue = time_span_max }; - /// - /// Whether to reverse the scrolling direction is reversed. Note that this does _not_ invert the hit objects. - /// - protected readonly BindableBool Reversed = new BindableBool(); - /// /// The container that contains the s and s. /// @@ -65,12 +58,11 @@ namespace osu.Game.Rulesets.UI /// /// The axes on which s in this container should scroll. /// Whether we want our internal coordinate system to be scaled to a specified width - protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) + protected ScrollingPlayfield(Direction scrollingDirection, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) { RelativeSizeAxes = Axes.Both }; - HitObjects.VisibleTimeRange.BindTo(VisibleTimeRange); - HitObjects.Reversed.BindTo(Reversed); + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingDirection) { RelativeSizeAxes = Axes.Both }; + HitObjects.TimeRange.BindTo(VisibleTimeRange); } private List nestedPlayfields; @@ -131,135 +123,66 @@ namespace osu.Game.Rulesets.UI protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; } - /// - /// A container that provides the foundation for sorting s into s. - /// public class ScrollingHitObjectContainer : HitObjectContainer { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - private readonly SortedContainer speedAdjustments; - public IReadOnlyList SpeedAdjustments => speedAdjustments; - - private readonly SpeedAdjustmentContainer defaultSpeedAdjustment; - - private readonly Axes scrollingAxes; - - /// - /// Creates a new . - /// - /// The axes upon which hit objects should appear to scroll inside this container. - public ScrollingHitObjectContainer(Axes scrollingAxes) + public readonly BindableDouble TimeRange = new BindableDouble { - this.scrollingAxes = scrollingAxes; + MinValue = 0, + MaxValue = double.MaxValue + }; - AddInternal(speedAdjustments = new SortedContainer { RelativeSizeAxes = Axes.Both }); + public readonly SortedList ControlPoints = new SortedList(); - // Default speed adjustment - AddSpeedAdjustment(defaultSpeedAdjustment = new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); + private readonly Direction scrollingDirection; + + public ScrollingHitObjectContainer(Direction scrollingDirection) + { + this.scrollingDirection = scrollingDirection; + + RelativeSizeAxes = Axes.Both; } - /// - /// Adds a to this container, re-sorting all hit objects - /// in the last that occurred (time-wise) before it. - /// - /// The . - public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + protected override void UpdateAfterChildren() { - speedAdjustment.ScrollingAxes = scrollingAxes; - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); - speedAdjustment.Reversed.BindTo(Reversed); + base.UpdateAfterChildren(); - if (speedAdjustments.Count > 0) + var currentMultiplier = controlPointAt(Time.Current); + + foreach (var obj in AliveObjects) { - // We need to re-sort all hit objects in the speed adjustment container prior to figure out if they - // should now lie within this one - var existingAdjustment = adjustmentContainerAt(speedAdjustment.ControlPoint.StartTime); - for (int i = 0; i < existingAdjustment.Count; i++) + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (scrollingDirection) { - DrawableHitObject hitObject = existingAdjustment[i]; - - if (!speedAdjustment.CanContain(hitObject.HitObject.StartTime)) - continue; - - existingAdjustment.Remove(hitObject); - speedAdjustment.Add(hitObject); - - i--; + case Direction.Horizontal: + obj.X = finalPosition.X; + break; + case Direction.Vertical: + obj.Y = finalPosition.Y; + break; } } - - speedAdjustments.Add(speedAdjustment); } - /// - /// Removes a from this container, re-sorting all hit objects - /// which it contained into new s. - /// - /// The to remove. - public void RemoveSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) { - if (speedAdjustment == defaultSpeedAdjustment) - throw new InvalidOperationException($"The default {nameof(SpeedAdjustmentContainer)} must not be removed."); + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); - if (!speedAdjustments.Remove(speedAdjustment)) - return; + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; - while (speedAdjustment.Count > 0) - { - DrawableHitObject hitObject = speedAdjustment[0]; + searchingPoint.StartTime = time; - speedAdjustment.Remove(hitObject); - Add(hitObject); - } - } + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; - public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); - - /// - /// Adds a hit object to this . The hit objects will be queued to be processed - /// new s are added to this . - /// - /// The hit object to add. - public override void Add(DrawableHitObject hitObject) - { - if (!(hitObject is IScrollingHitObject)) - throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - - adjustmentContainerAt(hitObject.HitObject.StartTime).Add(hitObject); - } - - public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); - - /// - /// Finds the which provides the speed adjustment active at a time. - /// If there is no active at the time, then the first (time-wise) speed adjustment is returned. - /// - /// The time to find the active at. - /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; - - private class SortedContainer : Container - { - protected override int Compare(Drawable x, Drawable y) - { - var sX = (SpeedAdjustmentContainer)x; - var sY = (SpeedAdjustmentContainer)y; - - int result = sY.ControlPoint.StartTime.CompareTo(sX.ControlPoint.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } + return ControlPoints[index]; } } } diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs index f1b8838fa9..9d98382a8b 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs @@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.UI private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) { - playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); + playfield.HitObjects.ControlPoints.Add(controlPoint); playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } @@ -108,12 +108,5 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - - /// - /// Creates a that facilitates the movement of hit objects. - /// - /// The that provides the speed adjustments for the hitobjects. - /// The . - protected virtual SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new SpeedAdjustmentContainer(controlPoint); } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 519e214495..2369724f6b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -614,7 +614,6 @@ - @@ -665,10 +664,7 @@ - - - From 651e24e3cc497c647f782e94fef948dbc75d35a5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:17:40 +0900 Subject: [PATCH 039/133] Implement proper scrolling directions --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- .../Visual/TestCaseScrollingHitObjects.cs | 16 ++++++------ osu.Game/Rulesets/UI/ScrollingDirection.cs | 25 +++++++++++++++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 24 +++++++++++------- osu.Game/osu.Game.csproj | 1 + 8 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Rulesets/UI/ScrollingDirection.cs diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 322d1d91af..2f7d7449c8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { Container explodingFruitContainer; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 048b3ef9f9..a0768e48a2 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 549b0f2ee6..161dd9ec22 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(Direction.Vertical) + : base(ScrollingDirection.Down) { this.columnCount = columnCount; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 5e1fa7e490..8c55fe009f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(Direction.Horizontal) + : base(ScrollingDirection.Left) { AddRangeInternal(new Drawable[] { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 01387791a1..b05efbde5c 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -24,8 +24,8 @@ namespace osu.Game.Tests.Visual public TestCaseScrollingHitObjects() { - playfields.Add(new TestPlayfield(Direction.Vertical)); - playfields.Add(new TestPlayfield(Direction.Horizontal)); + playfields.Add(new TestPlayfield(ScrollingDirection.Down)); + playfields.Add(new TestPlayfield(ScrollingDirection.Right)); playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual { p.Add(new TestDrawableHitObject(time) { - Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre }); }); } @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) { - Anchor = p.ScrollingDirection == Direction.Horizontal ? Anchor.CentreRight : Anchor.BottomCentre + Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre }; p.Add(createDrawablePoint(time)); @@ -105,15 +105,15 @@ namespace osu.Game.Tests.Visual { public readonly BindableDouble TimeRange = new BindableDouble(5000); - public readonly Direction ScrollingDirection; + public readonly ScrollingDirection Direction; public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; - public TestPlayfield(Direction scrollingDirection) + public TestPlayfield(ScrollingDirection direction) { - ScrollingDirection = scrollingDirection; + Direction = direction; - base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(scrollingDirection); + base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/ScrollingDirection.cs b/osu.Game/Rulesets/UI/ScrollingDirection.cs new file mode 100644 index 0000000000..29d63499ee --- /dev/null +++ b/osu.Game/Rulesets/UI/ScrollingDirection.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +namespace osu.Game.Rulesets.UI +{ + public enum ScrollingDirection + { + /// + /// Hitobjects will scroll vertically from the bottom of the hitobject container. + /// + Up, + /// + /// Hitobjects will scroll vertically from the top of the hitobject container. + /// + Down, + /// + /// Hitobjects will scroll horizontally from the right of the hitobject container. + /// + Left, + /// + /// Hitobjects will scroll horizontally from the left of the hitobject container. + /// + Right + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 56959240a8..f391d01ac9 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -58,10 +58,10 @@ namespace osu.Game.Rulesets.UI /// /// The axes on which s in this container should scroll. /// Whether we want our internal coordinate system to be scaled to a specified width - protected ScrollingPlayfield(Direction scrollingDirection, float? customWidth = null) + protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingDirection) { RelativeSizeAxes = Axes.Both }; + base.HitObjects = HitObjects = new ScrollingHitObjectContainer(direction) { RelativeSizeAxes = Axes.Both }; HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -133,11 +133,11 @@ namespace osu.Game.Rulesets.UI public readonly SortedList ControlPoints = new SortedList(); - private readonly Direction scrollingDirection; + private readonly ScrollingDirection direction; - public ScrollingHitObjectContainer(Direction scrollingDirection) + public ScrollingHitObjectContainer(ScrollingDirection direction) { - this.scrollingDirection = scrollingDirection; + this.direction = direction; RelativeSizeAxes = Axes.Both; } @@ -155,14 +155,20 @@ namespace osu.Game.Rulesets.UI // Todo: We may need to consider scale here var finalPosition = (float)relativePosition * DrawSize; - switch (scrollingDirection) + switch (direction) { - case Direction.Horizontal: - obj.X = finalPosition.X; + case ScrollingDirection.Up: + obj.Y = -finalPosition.Y; break; - case Direction.Vertical: + case ScrollingDirection.Down: obj.Y = finalPosition.Y; break; + case ScrollingDirection.Left: + obj.X = -finalPosition.X; + break; + case ScrollingDirection.Right: + obj.X = finalPosition.X; + break; } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2369724f6b..c5c1004663 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -314,6 +314,7 @@ + From e0c921ff5c7426c6115c9f690eb749dcb2405b15 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:20:43 +0900 Subject: [PATCH 040/133] Split out ScrollingHitObjectContainer into new file --- .../Visual/TestCaseScrollingHitObjects.cs | 4 +- .../UI/ScrollingHitObjectContainer.cs | 79 +++++++++++++++++++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 71 ----------------- osu.Game/osu.Game.csproj | 1 + 4 files changed, 82 insertions(+), 73 deletions(-) create mode 100644 osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index b05efbde5c..71c1295ebb 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -107,13 +107,13 @@ namespace osu.Game.Tests.Visual public readonly ScrollingDirection Direction; - public new ScrollingPlayfield.ScrollingHitObjectContainer HitObjects => (ScrollingPlayfield.ScrollingHitObjectContainer)base.HitObjects; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; public TestPlayfield(ScrollingDirection direction) { Direction = direction; - base.HitObjects = new ScrollingPlayfield.ScrollingHitObjectContainer(direction); + base.HitObjects = new ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..61184ac53f --- /dev/null +++ b/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Lists; +using osu.Game.Rulesets.Timing; + +namespace osu.Game.Rulesets.UI +{ + public class ScrollingHitObjectContainer : Playfield.HitObjectContainer + { + public readonly BindableDouble TimeRange = new BindableDouble + { + MinValue = 0, + MaxValue = double.MaxValue + }; + + public readonly SortedList ControlPoints = new SortedList(); + + private readonly ScrollingDirection direction; + + public ScrollingHitObjectContainer(ScrollingDirection direction) + { + this.direction = direction; + + RelativeSizeAxes = Axes.Both; + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + var currentMultiplier = controlPointAt(Time.Current); + + foreach (var obj in AliveObjects) + { + var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); + + // Todo: We may need to consider scale here + var finalPosition = (float)relativePosition * DrawSize; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = -finalPosition.Y; + break; + case ScrollingDirection.Down: + obj.Y = finalPosition.Y; + break; + case ScrollingDirection.Left: + obj.X = -finalPosition.X; + break; + case ScrollingDirection.Right: + obj.X = finalPosition.X; + break; + } + } + } + + private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (ControlPoints.Count == 0) + return new MultiplierControlPoint(double.MinValue); + + if (time < ControlPoints[0].StartTime) + return ControlPoints[0]; + + searchingPoint.StartTime = time; + + int index = ControlPoints.BinarySearch(searchingPoint); + if (index < 0) + index = ~index - 1; + + return ControlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index f391d01ac9..5492f9e272 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -7,10 +7,8 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; -using osu.Framework.Lists; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Timing; namespace osu.Game.Rulesets.UI { @@ -122,74 +120,5 @@ namespace osu.Game.Rulesets.UI protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; } - - public class ScrollingHitObjectContainer : HitObjectContainer - { - public readonly BindableDouble TimeRange = new BindableDouble - { - MinValue = 0, - MaxValue = double.MaxValue - }; - - public readonly SortedList ControlPoints = new SortedList(); - - private readonly ScrollingDirection direction; - - public ScrollingHitObjectContainer(ScrollingDirection direction) - { - this.direction = direction; - - RelativeSizeAxes = Axes.Both; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - var currentMultiplier = controlPointAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - - // Todo: We may need to consider scale here - var finalPosition = (float)relativePosition * DrawSize; - - switch (direction) - { - case ScrollingDirection.Up: - obj.Y = -finalPosition.Y; - break; - case ScrollingDirection.Down: - obj.Y = finalPosition.Y; - break; - case ScrollingDirection.Left: - obj.X = -finalPosition.X; - break; - case ScrollingDirection.Right: - obj.X = finalPosition.X; - break; - } - } - } - - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) - { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); - - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; - - searchingPoint.StartTime = time; - - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; - - return ControlPoints[index]; - } - } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index c5c1004663..9cf7d72d1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -315,6 +315,7 @@ + From a7aab21a29b5d0cc268141933b4146a8f7b7fbf5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 19:22:15 +0900 Subject: [PATCH 041/133] Re-namespace files --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs | 1 + osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 1 + osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs | 1 + osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 1 + .../Rulesets/UI/{ => Scrolling}/ScrollingDirection.cs | 2 +- .../UI/{ => Scrolling}/ScrollingHitObjectContainer.cs | 2 +- .../Rulesets/UI/{ => Scrolling}/ScrollingPlayfield.cs | 4 ++-- .../UI/{ => Scrolling}/ScrollingRulesetContainer.cs | 2 +- osu.Game/osu.Game.csproj | 8 ++++---- 13 files changed, 17 insertions(+), 13 deletions(-) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingDirection.cs (92%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingHitObjectContainer.cs (95%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingPlayfield.cs (97%) rename osu.Game/Rulesets/UI/{ => Scrolling}/ScrollingRulesetContainer.cs (97%) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 2f7d7449c8..1ea05f8ff6 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -10,6 +9,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 3ed9090098..e9f1a26e69 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index a0768e48a2..81997d3705 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -12,8 +12,8 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 161dd9ec22..cc028a85ee 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; @@ -17,6 +16,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index db9475b31e..55bae45ab2 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -22,6 +22,7 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 8c55fe009f..007c637659 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Taiko.Judgements; @@ -17,6 +16,7 @@ using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 614b446181..cef51c664f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Taiko.Replays; using OpenTK; using System.Linq; using osu.Framework.Input; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 71c1295ebb..7e332c7310 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; using OpenTK.Graphics; namespace osu.Game.Tests.Visual diff --git a/osu.Game/Rulesets/UI/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs similarity index 92% rename from osu.Game/Rulesets/UI/ScrollingDirection.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index 29d63499ee..d89795f4d3 100644 --- a/osu.Game/Rulesets/UI/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { public enum ScrollingDirection { diff --git a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs similarity index 95% rename from osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 61184ac53f..4c11c53a89 100644 --- a/osu.Game/Rulesets/UI/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Lists; using osu.Game.Rulesets.Timing; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : Playfield.HitObjectContainer { diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs similarity index 97% rename from osu.Game/Rulesets/UI/ScrollingPlayfield.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 5492f9e272..899048531f 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,15 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using OpenTK.Input; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; +using OpenTK.Input; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { /// /// A type of specialized towards scrolling s. diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs similarity index 97% rename from osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 9d98382a8b..73c3848f69 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { /// /// A type of that supports a . diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9cf7d72d1b..a1912487e9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -314,8 +314,10 @@ - - + + + + @@ -671,8 +673,6 @@ - - From bf64b8fc6966e496aadf8a747ccc47ef93d3fc29 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 4 Jan 2018 11:41:06 +0100 Subject: [PATCH 042/133] added hover effects to panels in social at least partially QQ --- osu.Game.Tests/Visual/TestCaseSocial.cs | 6 ++- osu.Game/Overlays/Social/SocialGridPanel.cs | 15 ++++++ osu.Game/Overlays/Social/SocialListPanel.cs | 16 ++++++ osu.Game/Overlays/Social/SocialPanel.cs | 60 +++++++++++++++++++++ osu.Game/Overlays/SocialOverlay.cs | 30 ++++++----- osu.Game/Users/UpdateableAvatar.cs | 2 +- osu.Game/Users/UserPanel.cs | 8 +-- osu.Game/osu.Game.csproj | 3 ++ 8 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Overlays/Social/SocialGridPanel.cs create mode 100644 osu.Game/Overlays/Social/SocialListPanel.cs create mode 100644 osu.Game/Overlays/Social/SocialPanel.cs diff --git a/osu.Game.Tests/Visual/TestCaseSocial.cs b/osu.Game.Tests/Visual/TestCaseSocial.cs index 3f418174c7..631f08254f 100644 --- a/osu.Game.Tests/Visual/TestCaseSocial.cs +++ b/osu.Game.Tests/Visual/TestCaseSocial.cs @@ -13,8 +13,12 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { + typeof(UserPanel), + typeof(SocialPanel), typeof(FilterControl), - typeof(SocialOverlay) + typeof(SocialOverlay), + typeof(SocialGridPanel), + typeof(SocialListPanel) }; public TestCaseSocial() diff --git a/osu.Game/Overlays/Social/SocialGridPanel.cs b/osu.Game/Overlays/Social/SocialGridPanel.cs new file mode 100644 index 0000000000..b2c6b75ab2 --- /dev/null +++ b/osu.Game/Overlays/Social/SocialGridPanel.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialGridPanel : SocialPanel + { + public SocialGridPanel(User user) : base(user) + { + Width = 300; + } + } +} diff --git a/osu.Game/Overlays/Social/SocialListPanel.cs b/osu.Game/Overlays/Social/SocialListPanel.cs new file mode 100644 index 0000000000..f65fbe8142 --- /dev/null +++ b/osu.Game/Overlays/Social/SocialListPanel.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialListPanel : SocialPanel + { + public SocialListPanel(User user) : base(user) + { + RelativeSizeAxes = Axes.X; + } + } +} diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs new file mode 100644 index 0000000000..234640482e --- /dev/null +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialPanel : UserPanel + { + private const double hover_transition_time = 400; + + public SocialPanel(User user) : base(user) + { + } + + private readonly EdgeEffectParameters edgeEffectNormal = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0f, 1f), + Radius = 2f, + Colour = Color4.Black.Opacity(0.25f), + }; + + private readonly EdgeEffectParameters edgeEffectHovered = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0f, 5f), + Radius = 10f, + Colour = Color4.Black.Opacity(0.3f), + }; + + protected override bool OnHover(InputState state) + { + TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); + //Content.MoveToY(-4, hover_transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); + //Content.MoveToY(0, hover_transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(200, Easing.Out); + } + } +} diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index c4ed14022e..823e264ebe 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays { private APIAccess api; private readonly LoadingAnimation loading; - private FillFlowContainer panels; + private FillFlowContainer panels; protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b"); protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"672b51"); @@ -121,7 +121,7 @@ namespace osu.Game.Overlays if (Users == null) return; - var newPanels = new FillFlowContainer + var newPanels = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -129,18 +129,18 @@ namespace osu.Game.Overlays Margin = new MarginPadding { Top = 10 }, ChildrenEnumerable = Users.Select(u => { - UserPanel panel = new UserPanel(u) - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }; + SocialPanel panel; switch (displayStyle) { case PanelDisplayStyle.Grid: - panel.Width = 300; + panel = new SocialGridPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }; break; default: - panel.RelativeSizeAxes = Axes.X; + panel = new SocialListPanel(u); break; } panel.Status.BindTo(u.Status); @@ -148,14 +148,20 @@ namespace osu.Game.Overlays }) }; - LoadComponentAsync(newPanels, p => ScrollFlow.Add(panels = newPanels)); + LoadComponentAsync(newPanels, p => + { + if(panels != null) + ScrollFlow.Remove(panels); + + ScrollFlow.Add(panels = newPanels); + }); } private void clearPanels() { if (panels != null) { - ScrollFlow.Remove(panels); + panels.FadeOut(200); panels.Expire(); panels = null; } @@ -185,7 +191,7 @@ namespace osu.Game.Overlays switch (Header.Tabs.Current.Value) { case SocialTab.OnlineFriends: - var friendRequest = new GetFriendsRequest(); // TODO filter??? + var friendRequest = new GetFriendsRequest(); friendRequest.Success += updateUsers; api.Queue(getUsersRequest = friendRequest); break; diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index d55c0caad7..455856a6d4 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -44,7 +44,7 @@ namespace osu.Game.Users new Avatar(user) { RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(200), + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), }) ); } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index e0a4e3184d..6690c38eca 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -65,8 +65,8 @@ namespace osu.Game.Users Anchor = Anchor.Centre, Origin = Anchor.Centre, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(200), - }, 0) { RelativeSizeAxes = Axes.Both }, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) + }, 300) { RelativeSizeAxes = Axes.Both }, new Box { RelativeSizeAxes = Axes.Both, @@ -76,7 +76,7 @@ namespace osu.Game.Users { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = content_padding, Left = content_padding, Right = content_padding }, + Padding = new MarginPadding { Top = content_padding, Horizontal = content_padding }, Children = new Drawable[] { new UpdateableAvatar @@ -167,11 +167,13 @@ namespace osu.Game.Users }; if (user.IsSupporter) + { infoContainer.Add(new SupporterIcon { RelativeSizeAxes = Axes.Y, Width = 20f, }); + } } [BackgroundDependencyLoader(permitNulls: true)] diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 49978693b3..dfc2120b89 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -311,6 +311,9 @@ + + + From 844c428fa7ead72a64422800feadc96fe95915ae Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Thu, 4 Jan 2018 11:49:03 +0100 Subject: [PATCH 043/133] Updated submodule osu-framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 6134dafccb..66421b8944 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 6134dafccb3368dac96d837537325c04b89fb8ee +Subproject commit 66421b894444cb9c4b792f9b93a786dcff5589dd From 585df22c88f0c8d83587f17f870afa5da8e9ac8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 20:56:18 +0900 Subject: [PATCH 044/133] Add a way to calculate length of IHasEndTime objects --- .../Scrolling/ScrollingHitObjectContainer.cs | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 4c11c53a89..36b885c84b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -4,7 +4,9 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; +using OpenTK; namespace osu.Game.Rulesets.UI.Scrolling { @@ -35,9 +37,8 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var relativePosition = (Time.Current - obj.HitObject.StartTime) / (TimeRange / currentMultiplier.Multiplier); - // Todo: We may need to consider scale here + var relativePosition = (Time.Current - obj.HitObject.StartTime) * currentMultiplier.Multiplier / TimeRange; var finalPosition = (float)relativePosition * DrawSize; switch (direction) @@ -55,6 +56,27 @@ namespace osu.Game.Rulesets.UI.Scrolling obj.X = finalPosition.X; break; } + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + // Todo: We may need to consider scale here + var relativeEndPosition = (Time.Current - endTime.EndTime) * currentMultiplier.Multiplier / TimeRange; + var finalEndPosition = (float)relativeEndPosition * DrawSize; + + float length = Vector2.Distance(finalPosition, finalEndPosition); + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = length; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = length; + break; + } } } From 4fee76ba0b8b2496f1812cebc5610de88b40ae1d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 20:56:28 +0900 Subject: [PATCH 045/133] Fix drumroll lengths --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f5bafefd0b..88184d5fcf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { - Width = (float)HitObject.Duration; + RelativeSizeAxes = Axes.Y; Container tickContainer; MainPiece.Add(tickContainer = new Container From add68ff068577a1f14ac4e9841c56316b8074336 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 21:45:29 +0900 Subject: [PATCH 046/133] Fix swells not stopping at the hit position --- osu-framework | 2 +- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 2 +- .../Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index 6134dafccb..067fdb8f5b 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 6134dafccb3368dac96d837537325c04b89fb8ee +Subproject commit 067fdb8f5b0594be1cd30e6bbd43f2ea749904ec diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 26e6585fb9..c8e5913fd2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Size = BaseSize * Parent.RelativeChildSize; // Make the swell stop at the hit target - X = (float)Math.Max(Time.Current, HitObject.StartTime); + X = Math.Max(0, X); double t = Math.Min(HitObject.StartTime, Time.Current); if (t == HitObject.StartTime && !hasStarted) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 36b885c84b..4011e7ffd1 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,9 +29,12 @@ namespace osu.Game.Rulesets.UI.Scrolling RelativeSizeAxes = Axes.Both; } - protected override void UpdateAfterChildren() + protected override void UpdateAfterChildrenLife() { - base.UpdateAfterChildren(); + base.UpdateAfterChildrenLife(); + + // We need to calculate this as soon as possible so that hitobjects + // get the final say in their positions var currentMultiplier = controlPointAt(Time.Current); From e0e84ff37011d69a5e0f521bb83f6566c478c7cf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 22:05:20 +0900 Subject: [PATCH 047/133] Fix mania playfield scrolling hitobjects in the wrong direction --- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 81997d3705..0910f9f37d 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(ScrollingDirection.Down) + : base(ScrollingDirection.Up) { Width = column_width; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index cc028a85ee..edb640a537 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI private readonly int columnCount; public ManiaPlayfield(int columnCount) - : base(ScrollingDirection.Down) + : base(ScrollingDirection.Up) { this.columnCount = columnCount; From ce94c825d18be7f32ab0ba8235bf01d7ad4b2aa2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 4 Jan 2018 22:05:38 +0900 Subject: [PATCH 048/133] Fix length of hold notes --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 41d817a746..48e1332597 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -42,8 +42,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableHoldNote(HoldNote hitObject, ManiaAction action) : base(hitObject, action) { - RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + RelativeSizeAxes = Axes.X; AddRange(new Drawable[] { From ddc9edab5423899579c1f50ff0909e1a34e7ac2f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 14:33:28 +0900 Subject: [PATCH 049/133] Make OsuSliderBar support both float and double values --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index fd75269610..4ff65dea93 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -32,11 +32,18 @@ namespace osu.Game.Graphics.UserInterface get { var bindableDouble = CurrentNumber as BindableNumber; - if (bindableDouble != null) + var bindableFloat = CurrentNumber as BindableNumber; + var floatValue = bindableDouble?.Value ?? bindableFloat?.Value ?? null; + + if (floatValue != null) { - if (bindableDouble.MaxValue == 1 && (bindableDouble.MinValue == 0 || bindableDouble.MinValue == -1)) - return bindableDouble.Value.ToString(@"P0"); - return bindableDouble.Value.ToString(@"n1"); + var floatMinValue = bindableDouble?.MinValue ?? bindableFloat?.MinValue ?? null; + var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat?.MaxValue ?? null; + + if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) + return floatValue.Value.ToString(@"P0"); + + return floatValue.Value.ToString(@"n1"); } var bindableInt = CurrentNumber as BindableNumber; From 08af3e6303e3e95064c8b5d6e6717aa1f377fd2f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 14:34:50 +0900 Subject: [PATCH 050/133] Make OsuSliderBar formatting support variable number of digits --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 4ff65dea93..bbbe710313 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Globalization; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -27,6 +28,11 @@ namespace osu.Game.Graphics.UserInterface private readonly Box leftBox; private readonly Box rightBox; + /// + /// The amount of decimal digits to display for s with floating point values. + /// + public int TooltipDecimalDigits = 1; + public virtual string TooltipText { get @@ -43,7 +49,10 @@ namespace osu.Game.Graphics.UserInterface if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) return floatValue.Value.ToString(@"P0"); - return floatValue.Value.ToString(@"n1"); + var nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); + nfi.NumberDecimalDigits = TooltipDecimalDigits; + + return string.Format(nfi, "{0:F}", floatValue.Value); } var bindableInt = CurrentNumber as BindableNumber; From eaa2a007e779e8003698a8037409a1ab90f0f64d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 16:12:15 +0900 Subject: [PATCH 051/133] Cleanup --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index bbbe710313..c282ed96d6 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -39,12 +39,12 @@ namespace osu.Game.Graphics.UserInterface { var bindableDouble = CurrentNumber as BindableNumber; var bindableFloat = CurrentNumber as BindableNumber; - var floatValue = bindableDouble?.Value ?? bindableFloat?.Value ?? null; + var floatValue = bindableDouble?.Value ?? bindableFloat?.Value; if (floatValue != null) { - var floatMinValue = bindableDouble?.MinValue ?? bindableFloat?.MinValue ?? null; - var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat?.MaxValue ?? null; + var floatMinValue = bindableDouble?.MinValue ?? bindableFloat.MinValue; + var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) return floatValue.Value.ToString(@"P0"); From b84f83cf165cc746308fbb44f94e3c53e6e436f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 16:12:48 +0900 Subject: [PATCH 052/133] Trigger a value changed event when the number of digits changes --- .../Graphics/UserInterface/OsuSliderBar.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index c282ed96d6..a5fb2de395 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -28,10 +28,26 @@ namespace osu.Game.Graphics.UserInterface private readonly Box leftBox; private readonly Box rightBox; + private int tooltipDecimalDigits = 1; /// /// The amount of decimal digits to display for s with floating point values. /// - public int TooltipDecimalDigits = 1; + public int TooltipDecimalDigits + { + get => tooltipDecimalDigits; + set + { + if (tooltipDecimalDigits == value) + return; + tooltipDecimalDigits = value; + + if (IsLoaded) + { + // Some users may want to see the updated ToolTipText + Current.TriggerChange(); + } + } + } public virtual string TooltipText { From cbf48524385b9c920f1736880ce01175b49a1c79 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 17:00:38 +0900 Subject: [PATCH 053/133] Expose a NumberFormatInfo for more extensibility --- .../Graphics/UserInterface/OsuSliderBar.cs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index a5fb2de395..701a9d4460 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -28,18 +28,15 @@ namespace osu.Game.Graphics.UserInterface private readonly Box leftBox; private readonly Box rightBox; - private int tooltipDecimalDigits = 1; - /// - /// The amount of decimal digits to display for s with floating point values. - /// - public int TooltipDecimalDigits + private NumberFormatInfo format; + public NumberFormatInfo Format { - get => tooltipDecimalDigits; + get => format ?? (format = createDefaultFormat()); set { - if (tooltipDecimalDigits == value) + if (format == value) return; - tooltipDecimalDigits = value; + format = value; if (IsLoaded) { @@ -63,17 +60,14 @@ namespace osu.Game.Graphics.UserInterface var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) - return floatValue.Value.ToString(@"P0"); + return floatValue.Value.ToString("P", Format); - var nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); - nfi.NumberDecimalDigits = TooltipDecimalDigits; - - return string.Format(nfi, "{0:F}", floatValue.Value); + return floatValue.Value.ToString("F", Format); } var bindableInt = CurrentNumber as BindableNumber; if (bindableInt != null) - return bindableInt.Value.ToString(@"n0"); + return bindableInt.Value.ToString("N0"); return Current.Value.ToString(); } @@ -137,6 +131,15 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Pink; } + private NumberFormatInfo createDefaultFormat() + { + var nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); + nfi.PercentDecimalDigits = 0; + nfi.NumberDecimalDigits = 1; + + return nfi; + } + protected override bool OnHover(InputState state) { Nub.Glowing = true; From 76f4bb1ca08d9257f1dbac24493f4a83d4d15dbf Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 17:00:51 +0900 Subject: [PATCH 054/133] Add automated test cases --- .../Visual/TestCaseSliderBarPercentage.cs | 123 +++++++++++++ .../Visual/TestCaseSliderBarPrecision.cs | 172 ++++++++++++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 2 + 3 files changed, 297 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs create mode 100644 osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs new file mode 100644 index 0000000000..5c4d545348 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs @@ -0,0 +1,123 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Configuration; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseSliderBarPercentage : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(OsuSliderBar<>) }; + + private readonly BindableFloat floatValue; + private readonly BindableDouble doubleValue; + + private readonly TestSliderBar floatSliderBar; + private readonly TestSliderBar doubleSliderBar; + + public TestCaseSliderBarPercentage() + { + floatValue = new BindableFloat + { + MinValue = -1, + MaxValue = 1, + }; + + doubleValue = new BindableDouble + { + MinValue = -1, + MaxValue = 1 + }; + + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 300, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + floatSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, + doubleSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X } + } + }; + + floatSliderBar.Current.BindTo(floatValue); + doubleSliderBar.Current.BindTo(doubleValue); + + floatValue.ValueChanged += setValue; + doubleValue.ValueChanged += setValue; + + AddStep("Digits = 0", () => setPercentageDigits(0)); + AddStep("Value = 0", () => setValue(0)); + AddAssert("Check 0%", () => checkExact(0)); + + AddStep("Value = 0.5", () => setValue(0.5)); + AddAssert("Check 50%", () => checkExact(0.5m)); + + AddStep("Value = 0.54", () => setValue(0.54)); + AddAssert("Check 54%", () => checkExact(0.54m)); + + AddStep("Value = 0.544", () => setValue(0.544)); + AddAssert("Check 54%", () => checkExact(0.54m)); + + AddStep("Value = 0.548", () => setValue(0.548)); + AddAssert("Check 55%", () => checkExact(0.55m)); + + AddStep("Digits = 1", () => setPercentageDigits(1)); + AddAssert("Check 54.8%", () => checkExact(0.548m)); + + AddSliderStep("Percentage", -1.0, 1.0, 0.0, setValue); + AddSliderStep("Digits", 0, 7, 1, setPercentageDigits); + } + + private bool checkExact(decimal percentage) + { + string expectedValue = percentage.ToString("P", floatSliderBar.Format); + return floatSliderBar.TooltipText == expectedValue && doubleSliderBar.TooltipText == expectedValue; + } + + private void setValue(T value) + { + floatValue.Value = Convert.ToSingle(value); + doubleValue.Value = Convert.ToDouble(value); + } + + private void setPercentageDigits(int digits) + { + floatSliderBar.Format.PercentDecimalDigits = digits; + doubleSliderBar.Format.PercentDecimalDigits = digits; + + // Make sure that the text referenced in TestSliderBar is updated + // This doesn't break any assertions if missing, but breaks the visual display + floatSliderBar.Current.TriggerChange(); + doubleSliderBar.Current.TriggerChange(); + } + + private class TestSliderBar : OsuSliderBar + where T : struct, IEquatable + { + public TestSliderBar() + { + SpriteText valueText; + AddInternal(valueText = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + X = 5, + Text = TooltipText + }); + + Current.ValueChanged += v => valueText.Text = TooltipText; + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs new file mode 100644 index 0000000000..928ba0d825 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs @@ -0,0 +1,172 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseSliderBarPrecision : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(OsuSliderBar<>) }; + + private readonly BindableInt intValue; + private readonly BindableFloat floatValue; + private readonly BindableDouble doubleValue; + + private readonly TestSliderBar intSliderBar; + private readonly TestSliderBar floatSliderBar; + private readonly TestSliderBar doubleSliderBar; + + public TestCaseSliderBarPrecision() + { + intValue = new BindableInt + { + MinValue = -1000, + MaxValue = 1000, + }; + + floatValue = new BindableFloat + { + MinValue = -1000, + MaxValue = 1000, + }; + + doubleValue = new BindableDouble + { + MinValue = -1000, + MaxValue = 1000 + }; + + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 300, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Children = new Drawable[] + { + intSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, + floatSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, + doubleSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X } + } + }; + + intSliderBar.Current.BindTo(intValue); + floatSliderBar.Current.BindTo(floatValue); + doubleSliderBar.Current.BindTo(doubleValue); + + intValue.ValueChanged += setValue; + floatValue.ValueChanged += setValue; + doubleValue.ValueChanged += setValue; + + AddStep("Value = 0", () => setValue(0)); + AddStep("Digits = 0", () => setDecimalDigits(0)); + AddAssert("Check all 0", () => checkExact("0")); + + AddStep("Digits = 3", () => setDecimalDigits(3)); + AddAssert("Check 0.000", () => checkExact(0.000m)); + + AddStep("Value = 0.5", () => setValue(0.5)); + AddAssert("Check 0.500", () => checkExact(0.500m)); + + AddStep("Value = 123.4567", () => setValue(123.4567)); + AddAssert("Check 123.457", () => checkExact(123.457m)); + + AddStep("Value = 765.4312", () => setValue(765.4312)); + AddAssert("Check 765.431", () => checkExact(765.431m)); + + AddStep("Value = -12.3456", () => setValue(-12.3456)); + AddAssert("Check -12.346", () => checkExact(-12.346m)); + AddStep("Digits = 1", () => setDecimalDigits(1)); + AddAssert("Check -12.3", () => checkExact(-12.3m)); + AddStep("Digits = 0", () => setDecimalDigits(0)); + AddAssert("Check -12", () => checkExact(-12m)); + + AddStep("Value = -12.8", () => setValue(-12.8)); + AddAssert("Check -13", () => checkExact(-13m)); + AddStep("Digits = 1", () => setDecimalDigits(1)); + AddAssert("Check -12.8", () => checkExact(-12.8m)); + + AddSliderStep("Digits", 0, 7, 1, setDecimalDigits); + } + + /// + /// Checks whether all sliderbar tooltips display an exact value. + /// + /// The expected value that should be displayed. + private bool checkExact(string value) + => intSliderBar.TooltipText == value + && floatSliderBar.TooltipText == value + && doubleSliderBar.TooltipText == value; + + /// + /// Checks whether all sliderbar tooltips display an exact value. + /// + /// The expected value that should be displayed. + private bool checkExact(decimal value) + { + var expectedDecimal = value.ToString(intSliderBar.Format); + + return intSliderBar.TooltipText == Convert.ToInt32(value).ToString("N0") + && floatSliderBar.TooltipText == expectedDecimal + && doubleSliderBar.TooltipText == expectedDecimal; + } + + /// + /// Checks whether all floating-point sliderbar tooltips have a certain number of decimal digits. + /// + /// The expected number of decimal digits. + private bool checkDecimalDigits(int decimals) + => checkDecimalDigits(decimals, floatSliderBar.TooltipText) + && checkDecimalDigits(decimals, doubleSliderBar.TooltipText); + + private bool checkDecimalDigits(int decimals, string value) + => value.Length - value.IndexOf(intSliderBar.Format.NumberDecimalSeparator, StringComparison.InvariantCulture) - 1 == decimals; + + private void setValue(T value) + { + intValue.Value = Convert.ToInt32(value); + floatValue.Value = Convert.ToSingle(value); + doubleValue.Value = Convert.ToDouble(value); + } + + private void setDecimalDigits(int digits) + { + intSliderBar.Format.NumberDecimalDigits = digits; + floatSliderBar.Format.NumberDecimalDigits = digits; + doubleSliderBar.Format.NumberDecimalDigits = digits; + + // Make sure that the text referenced in TestSliderBar is updated + // This doesn't break any assertions if missing, but breaks the visual display + intSliderBar.Current.TriggerChange(); + floatSliderBar.Current.TriggerChange(); + doubleSliderBar.Current.TriggerChange(); + } + + private class TestSliderBar : OsuSliderBar + where T : struct, IEquatable + { + public TestSliderBar() + { + SpriteText valueText; + AddInternal(valueText = new OsuSpriteText + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreLeft, + X = 5, + Text = TooltipText + }); + + Current.ValueChanged += v => valueText.Text = TooltipText; + } + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 8c04874e75..53d971a0b3 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -132,6 +132,8 @@ + + From b84da31174403e3790d39d2afa92a742b8686742 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Jan 2018 23:20:58 +0900 Subject: [PATCH 055/133] Change in-line with framework --- osu.Game/Overlays/OnScreenDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index ce0feeb4c6..9a35551645 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -139,7 +139,7 @@ namespace osu.Game.Overlays private readonly List references = new List(); - private void trackSetting(Bindable bindable, Bindable.BindableValueChanged action) + private void trackSetting(Bindable bindable, Action action) { // we need to keep references as we bind references.Add(bindable); From 1571c10c4255213282df82ef686b77ea34900a85 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 14:37:32 +0900 Subject: [PATCH 056/133] Fix up replay settings sliderbar formatting --- osu.Game/Overlays/Settings/SettingsSlider.cs | 13 +++++++++++-- .../Screens/Play/ReplaySettings/PlaybackSettings.cs | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 49d73f77ec..db6e5e3f2e 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -2,9 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings public class SettingsSlider : SettingsItem where T : struct, IEquatable - where U : SliderBar, new() + where U : OsuSliderBar, new() { protected override Drawable CreateControl() => new U { @@ -24,6 +24,15 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X }; + /// + /// The format that will be used for the tooltip when the sliderbar is hovered. + /// + public NumberFormatInfo Format + { + get => ((U)Control).Format; + set => ((U)Control).Format = value; + } + public float KeyboardStep; [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs index 3109552532..a7b03c3742 100644 --- a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs @@ -59,6 +59,7 @@ namespace osu.Game.Screens.Play.ReplaySettings } }; + sliderbar.Format.NumberDecimalDigits = 2; sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{rateMultiplier}x"; } From d2b135d2a81545202b25a9d7e8a625318c1d9b85 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 15:48:19 +0900 Subject: [PATCH 057/133] Give hitobjects lifetimes --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 4011e7ffd1..7382d46dec 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -29,11 +29,22 @@ namespace osu.Game.Rulesets.UI.Scrolling RelativeSizeAxes = Axes.Both; } + protected override bool UpdateChildrenLife() + { + foreach (var obj in Objects) + { + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime + TimeRange) + 1000; + } + + return base.UpdateChildrenLife(); + } + protected override void UpdateAfterChildrenLife() { base.UpdateAfterChildrenLife(); - // We need to calculate this as soon as possible so that hitobjects + // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions var currentMultiplier = controlPointAt(Time.Current); From 5d12682e83335bae9725465c46495bbe17c6457b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 20:17:02 +0900 Subject: [PATCH 058/133] Initial implementation of the new (old) mania scrolling calculations --- .../Scrolling/ScrollingHitObjectContainer.cs | 46 +++++++++---------- .../UI/Scrolling/ScrollingRulesetContainer.cs | 10 ++-- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 7382d46dec..8c3e1162e3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; @@ -33,8 +34,8 @@ namespace osu.Game.Rulesets.UI.Scrolling { foreach (var obj in Objects) { - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime + TimeRange) + 1000; + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange * 2; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange * 2; } return base.UpdateChildrenLife(); @@ -47,27 +48,25 @@ namespace osu.Game.Rulesets.UI.Scrolling // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions - var currentMultiplier = controlPointAt(Time.Current); + var timelinePosition = positionAt(Time.Current); foreach (var obj in AliveObjects) { - // Todo: We may need to consider scale here - var relativePosition = (Time.Current - obj.HitObject.StartTime) * currentMultiplier.Multiplier / TimeRange; - var finalPosition = (float)relativePosition * DrawSize; + var finalPosition = positionAt(obj.HitObject.StartTime); switch (direction) { case ScrollingDirection.Up: - obj.Y = -finalPosition.Y; + obj.Y = finalPosition.Y - timelinePosition.Y; break; case ScrollingDirection.Down: - obj.Y = finalPosition.Y; + obj.Y = -finalPosition.Y + timelinePosition.Y; break; case ScrollingDirection.Left: - obj.X = -finalPosition.X; + obj.X = finalPosition.X - timelinePosition.X; break; case ScrollingDirection.Right: - obj.X = finalPosition.X; + obj.X = -finalPosition.X + timelinePosition.X; break; } @@ -75,8 +74,7 @@ namespace osu.Game.Rulesets.UI.Scrolling continue; // Todo: We may need to consider scale here - var relativeEndPosition = (Time.Current - endTime.EndTime) * currentMultiplier.Multiplier / TimeRange; - var finalEndPosition = (float)relativeEndPosition * DrawSize; + var finalEndPosition = positionAt(endTime.EndTime); float length = Vector2.Distance(finalPosition, finalEndPosition); @@ -94,22 +92,24 @@ namespace osu.Game.Rulesets.UI.Scrolling } } - private readonly MultiplierControlPoint searchingPoint = new MultiplierControlPoint(); - private MultiplierControlPoint controlPointAt(double time) + private Vector2 positionAt(double time) { - if (ControlPoints.Count == 0) - return new MultiplierControlPoint(double.MinValue); + float length = 0; + for (int i = 0; i < ControlPoints.Count; i++) + { + var current = ControlPoints[i]; + var next = i < ControlPoints.Count - 1 ? ControlPoints[i + 1] : null; - if (time < ControlPoints[0].StartTime) - return ControlPoints[0]; + if (i > 0 && current.StartTime > time) + continue; - searchingPoint.StartTime = time; + // Duration of the current control point + var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - int index = ControlPoints.BinarySearch(searchingPoint); - if (index < 0) - index = ~index - 1; + length += (float)(Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange); + } - return ControlPoints[index]; + return length * DrawSize; } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 73c3848f69..418013bcc1 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -70,12 +70,10 @@ namespace osu.Game.Rulesets.UI.Scrolling // Perform some post processing of the timing changes timingChanges = timingChanges - // Collapse sections after the last hit object - .Where(s => s.StartTime <= lastObjectTime) - // Collapse sections with the same start time - .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime) - // Collapse sections with the same beat length - .GroupBy(s => s.TimingPoint.BeatLength * s.DifficultyPoint.SpeedMultiplier).Select(g => g.First()); + // Collapse sections after the last hit object + .Where(s => s.StartTime <= lastObjectTime) + // Collapse sections with the same start time + .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime); DefaultControlPoints.AddRange(timingChanges); From 7526225282f8aa912e51bb7b1a5fa23af8f07260 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jan 2018 20:56:21 +0900 Subject: [PATCH 059/133] Use DP for most of the code to avoid unnecessary computations --- .../Visual/TestCaseScrollingHitObjects.cs | 11 +- .../Scrolling/ScrollingHitObjectContainer.cs | 105 ++++++++++++------ .../UI/Scrolling/ScrollingRulesetContainer.cs | 2 +- 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 7e332c7310..591bf4fadd 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual playfields.Add(new TestPlayfield(ScrollingDirection.Down)); playfields.Add(new TestPlayfield(ScrollingDirection.Right)); - playfields.ForEach(p => p.HitObjects.ControlPoints.Add(new MultiplierControlPoint(double.MinValue))); + playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(double.MinValue))); Add(new Container { @@ -82,12 +82,9 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.HitObjects.ControlPoints.AddRange(new[] - { - new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }, - new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }, - new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }, - }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) { diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 8c3e1162e3..7bd5ab8f10 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -2,9 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; +using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; @@ -19,26 +22,86 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = double.MaxValue }; - public readonly SortedList ControlPoints = new SortedList(); - private readonly ScrollingDirection direction; + private Cached positionCache = new Cached(); + public ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; RelativeSizeAxes = Axes.Both; + + TimeRange.ValueChanged += v => positionCache.Invalidate(); } - protected override bool UpdateChildrenLife() + public override void Add(DrawableHitObject hitObject) { + positionCache.Invalidate(); + base.Add(hitObject); + } + + public override bool Remove(DrawableHitObject hitObject) + { + var result = base.Remove(hitObject); + if (result) + positionCache.Invalidate(); + return result; + } + + private readonly SortedList controlPoints = new SortedList(); + + public void AddControlPoint(MultiplierControlPoint controlPoint) + { + controlPoints.Add(controlPoint); + positionCache.Invalidate(); + } + + public bool RemoveControlPoint(MultiplierControlPoint controlPoint) + { + var result = controlPoints.Remove(controlPoint); + if (result) + positionCache.Invalidate(); + return result; + } + + private readonly Dictionary hitObjectPositions = new Dictionary(); + + protected override void Update() + { + base.Update(); + + if (positionCache.IsValid) + return; + foreach (var obj in Objects) { - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange * 2; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange * 2; + var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime); + + obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange + 1000; + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + var endPosition = positionAt(endTime.EndTime); + + float length = Vector2.Distance(startPosition, endPosition); + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = length; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = length; + break; + } } - return base.UpdateChildrenLife(); + positionCache.Validate(); } protected override void UpdateAfterChildrenLife() @@ -52,7 +115,7 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var finalPosition = positionAt(obj.HitObject.StartTime); + var finalPosition = hitObjectPositions[obj]; switch (direction) { @@ -69,36 +132,16 @@ namespace osu.Game.Rulesets.UI.Scrolling obj.X = -finalPosition.X + timelinePosition.X; break; } - - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - // Todo: We may need to consider scale here - var finalEndPosition = positionAt(endTime.EndTime); - - float length = Vector2.Distance(finalPosition, finalEndPosition); - - switch (direction) - { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = length; - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = length; - break; - } } } private Vector2 positionAt(double time) { - float length = 0; - for (int i = 0; i < ControlPoints.Count; i++) + double length = 0; + for (int i = 0; i < controlPoints.Count; i++) { - var current = ControlPoints[i]; - var next = i < ControlPoints.Count - 1 ? ControlPoints[i + 1] : null; + var current = controlPoints[i]; + var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; if (i > 0 && current.StartTime > time) continue; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index 418013bcc1..8990710a9d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) { - playfield.HitObjects.ControlPoints.Add(controlPoint); + playfield.HitObjects.AddControlPoint(controlPoint); playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } From c9692a44f9b044a2100d7a86b250b2aa7f9c0bfe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 5 Jan 2018 21:04:21 +0900 Subject: [PATCH 060/133] Fix framework licence headers in osu project --- osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs | 2 +- osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs index 5c4d545348..ce32dbe889 100644 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs index 928ba0d825..c4b3a63bf2 100644 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; From 57b44b8c29808fca00a10b4766ea7ebed6b1ed2a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 6 Jan 2018 10:40:18 +0100 Subject: [PATCH 061/133] fix new panels appearing too soon --- osu.Game/Overlays/SocialOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 823e264ebe..fb111a64d2 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -153,7 +153,7 @@ namespace osu.Game.Overlays if(panels != null) ScrollFlow.Remove(panels); - ScrollFlow.Add(panels = newPanels); + Scheduler.AddDelayed(() => ScrollFlow.Add(panels = newPanels), 200); }); } From 82dcb033deaaee2bacc2476b01da2812b46217e1 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 6 Jan 2018 10:47:56 +0100 Subject: [PATCH 062/133] update submodules --- osu-framework | 2 +- osu-resources | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index 66421b8944..80bcb82ef8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 66421b894444cb9c4b792f9b93a786dcff5589dd +Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 diff --git a/osu-resources b/osu-resources index e01f71160f..7724abdf1d 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 +Subproject commit 7724abdf1d7c9705ba2e3989a9c604e17ccdc871 From a61666d2a732727317f22290a3c85f02b2067440 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 6 Jan 2018 10:54:53 +0100 Subject: [PATCH 063/133] update licence headers --- osu.Game/Online/API/Requests/GetFriendsRequest.cs | 2 +- osu.Game/Overlays/Social/SocialGridPanel.cs | 2 +- osu.Game/Overlays/Social/SocialListPanel.cs | 2 +- osu.Game/Overlays/Social/SocialPanel.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs index a06471fd74..5bc3d8e39e 100644 --- a/osu.Game/Online/API/Requests/GetFriendsRequest.cs +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/Social/SocialGridPanel.cs b/osu.Game/Overlays/Social/SocialGridPanel.cs index b2c6b75ab2..f9fbce123d 100644 --- a/osu.Game/Overlays/Social/SocialGridPanel.cs +++ b/osu.Game/Overlays/Social/SocialGridPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Users; diff --git a/osu.Game/Overlays/Social/SocialListPanel.cs b/osu.Game/Overlays/Social/SocialListPanel.cs index f65fbe8142..0f102005d6 100644 --- a/osu.Game/Overlays/Social/SocialListPanel.cs +++ b/osu.Game/Overlays/Social/SocialListPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs index 234640482e..2e0b7e6df2 100644 --- a/osu.Game/Overlays/Social/SocialPanel.cs +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; From d9866a2052b5bbcc42d8537b754cc3f9e19521c6 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 6 Jan 2018 11:27:17 +0100 Subject: [PATCH 064/133] fix hover effects on social panels --- osu.Game/Overlays/Social/SocialPanel.cs | 8 +- osu.Game/Users/UserPanel.cs | 212 ++++++++++++------------ 2 files changed, 114 insertions(+), 106 deletions(-) diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs index 2e0b7e6df2..54fb88f929 100644 --- a/osu.Game/Overlays/Social/SocialPanel.cs +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -37,16 +37,16 @@ namespace osu.Game.Overlays.Social protected override bool OnHover(InputState state) { - TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); - //Content.MoveToY(-4, hover_transition_time, Easing.OutQuint); + Content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); + Content.MoveToY(-4, hover_transition_time, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); - //Content.MoveToY(0, hover_transition_time, Easing.OutQuint); + Content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); + Content.MoveToY(0, hover_transition_time, Easing.OutQuint); base.OnHoverLost(state); } diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 839c62ea40..c62ba392b8 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -28,9 +28,12 @@ namespace osu.Game.Users private const float content_padding = 10; private const float status_height = 30; - private readonly Container statusBar; - private readonly Box statusBg; - private readonly OsuSpriteText statusMessage; + private Container statusBar; + private Box statusBg; + private OsuSpriteText statusMessage; + + private Container content; + protected override Container Content => content; public readonly Bindable Status = new Bindable(); @@ -45,126 +48,138 @@ namespace osu.Game.Users this.user = user; + Height = height - status_height; + } + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(OsuColour colours, UserProfileOverlay profile) + { + if (colours == null) + throw new ArgumentNullException(nameof(colours)); + FillFlowContainer infoContainer; - Height = height - status_height; - Masking = true; - CornerRadius = 5; - EdgeEffect = new EdgeEffectParameters + AddInternal(content = new Container { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - - Children = new Drawable[] - { - new DelayedLoadWrapper(new UserCoverBackground(user) + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) - }, 300) { RelativeSizeAxes = Axes.Both }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.7f), + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, }, - new Container + + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = content_padding, Horizontal = content_padding }, - Children = new Drawable[] + new DelayedLoadWrapper(new UserCoverBackground(user) { - new UpdateableAvatar + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) + }, 300) { RelativeSizeAxes = Axes.Both }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.7f), + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Top = content_padding, Horizontal = content_padding }, + Children = new Drawable[] { - Size = new Vector2(height - status_height - content_padding * 2), - User = user, - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters + new UpdateableAvatar { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = height - status_height - content_padding }, - Children = new Drawable[] - { - new OsuSpriteText + Size = new Vector2(height - status_height - content_padding * 2), + User = user, + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters { - Text = user.Username, - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic", + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, }, - infoContainer = new FillFlowContainer + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = height - status_height - content_padding }, + Children = new Drawable[] { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.X, - Height = 20f, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - Children = new Drawable[] + new OsuSpriteText { - new DrawableFlag(user.Country) + Text = user.Username, + TextSize = 18, + Font = @"Exo2.0-SemiBoldItalic", + }, + infoContainer = new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.X, + Height = 20f, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] { - Width = 30f, - RelativeSizeAxes = Axes.Y, + new DrawableFlag(user.Country) + { + Width = 30f, + RelativeSizeAxes = Axes.Y, + }, }, }, }, }, }, }, - }, - statusBar = new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Alpha = 0f, - Children = new Drawable[] + statusBar = new Container { - statusBg = new Box + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Alpha = 0f, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0.5f, - }, - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(5f, 0f), - Children = new Drawable[] + statusBg = new Box { - new SpriteIcon + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_circle_o, - Shadow = true, - Size = new Vector2(14), - }, - statusMessage = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = @"Exo2.0-Semibold", + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_circle_o, + Shadow = true, + Size = new Vector2(14), + }, + statusMessage = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = @"Exo2.0-Semibold", + }, }, }, }, }, - }, - }; + } + }); if (user.IsSupporter) { @@ -174,13 +189,6 @@ namespace osu.Game.Users Width = 20f, }); } - } - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, UserProfileOverlay profile) - { - if (colours == null) - throw new ArgumentNullException(nameof(colours)); Status.ValueChanged += displayStatus; Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); From 98fd4f6ff2afae42c569efcb886738e193c06932 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 11:33:59 +0900 Subject: [PATCH 065/133] Fix up precision + sizing issues --- .../Scrolling/ScrollingHitObjectContainer.cs | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 7bd5ab8f10..e0df4321a8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -10,7 +10,6 @@ using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; -using OpenTK; namespace osu.Game.Rulesets.UI.Scrolling { @@ -65,7 +64,15 @@ namespace osu.Game.Rulesets.UI.Scrolling return result; } - private readonly Dictionary hitObjectPositions = new Dictionary(); + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) + positionCache.Invalidate(); + + return base.Invalidate(invalidation, source, shallPropagate); + } + + private readonly Dictionary hitObjectPositions = new Dictionary(); protected override void Update() { @@ -84,19 +91,17 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!(obj.HitObject is IHasEndTime endTime)) continue; - var endPosition = positionAt(endTime.EndTime); - - float length = Vector2.Distance(startPosition, endPosition); + var length = positionAt(endTime.EndTime) - startPosition; switch (direction) { case ScrollingDirection.Up: case ScrollingDirection.Down: - obj.Height = length; + obj.Height = (float)(length * DrawHeight); break; case ScrollingDirection.Left: case ScrollingDirection.Right: - obj.Width = length; + obj.Width = (float)(length * DrawWidth); break; } } @@ -115,27 +120,27 @@ namespace osu.Game.Rulesets.UI.Scrolling foreach (var obj in AliveObjects) { - var finalPosition = hitObjectPositions[obj]; + var finalPosition = hitObjectPositions[obj] - timelinePosition; switch (direction) { case ScrollingDirection.Up: - obj.Y = finalPosition.Y - timelinePosition.Y; + obj.Y = (float)(finalPosition * DrawHeight); break; case ScrollingDirection.Down: - obj.Y = -finalPosition.Y + timelinePosition.Y; + obj.Y = (float)(-finalPosition * DrawHeight); break; case ScrollingDirection.Left: - obj.X = finalPosition.X - timelinePosition.X; + obj.X = (float)(finalPosition * DrawWidth); break; case ScrollingDirection.Right: - obj.X = -finalPosition.X + timelinePosition.X; + obj.X = (float)(-finalPosition * DrawWidth); break; } } } - private Vector2 positionAt(double time) + private double positionAt(double time) { double length = 0; for (int i = 0; i < controlPoints.Count; i++) @@ -149,10 +154,10 @@ namespace osu.Game.Rulesets.UI.Scrolling // Duration of the current control point var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - length += (float)(Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange); + length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange; } - return length * DrawSize; + return length; } } } From 2d345b2f80e88eebdecb1847fd0ae1203c31a2f2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 11:43:31 +0900 Subject: [PATCH 066/133] Fix mania hold note tick positioning --- .../Objects/Drawables/DrawableHoldNoteTick.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 8ed5d2b924..68f6721694 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; + RelativePositionAxes = Axes.Y; Y = (float)HitObject.StartTime; RelativeSizeAxes = Axes.X; From 117ab8a26d32c5277cb1c585c73fdc726d0f1d38 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 12:47:09 +0900 Subject: [PATCH 067/133] Split out scrolling algorithm --- .../Visual/TestCaseScrollingHitObjects.cs | 6 +- osu.Game/Rulesets/UI/HitObjectContainer.cs | 19 +++ osu.Game/Rulesets/UI/Playfield.cs | 22 ++-- .../Algorithms/GlobalScrollingAlgorithm.cs | 98 +++++++++++++++ .../Algorithms/IScrollingAlgorithm.cs | 15 +++ .../GlobalScrollingHitObjectContainer.cs | 17 +++ .../Scrolling/ScrollingHitObjectContainer.cs | 115 +++++------------- .../UI/Scrolling/ScrollingPlayfield.cs | 16 ++- osu.Game/osu.Game.csproj | 4 + 9 files changed, 205 insertions(+), 107 deletions(-) create mode 100644 osu.Game/Rulesets/UI/HitObjectContainer.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 591bf4fadd..4f2e895e9d 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -99,19 +99,17 @@ namespace osu.Game.Tests.Visual - private class TestPlayfield : Playfield + private class TestPlayfield : ScrollingPlayfield { public readonly BindableDouble TimeRange = new BindableDouble(5000); public readonly ScrollingDirection Direction; - public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; - public TestPlayfield(ScrollingDirection direction) + : base(direction) { Direction = direction; - base.HitObjects = new ScrollingHitObjectContainer(direction); HitObjects.TimeRange.BindTo(TimeRange); } } diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs new file mode 100644 index 0000000000..e7843c86ca --- /dev/null +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.UI +{ + public class HitObjectContainer : CompositeDrawable + { + public virtual IEnumerable Objects => InternalChildren.Cast(); + public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); + public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + } +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 61014b5550..91ea3ade2a 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -8,8 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using osu.Game.Rulesets.Judgements; using osu.Framework.Allocation; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.UI { @@ -18,7 +16,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public HitObjectContainer HitObjects { get; protected set; } + public readonly HitObjectContainer HitObjects; public Container ScaledContent; @@ -52,10 +50,8 @@ namespace osu.Game.Rulesets.UI } }); - HitObjects = new HitObjectContainer - { - RelativeSizeAxes = Axes.Both, - }; + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] @@ -94,14 +90,10 @@ namespace osu.Game.Rulesets.UI /// The that occurred. public virtual void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { } - public class HitObjectContainer : CompositeDrawable - { - public virtual IEnumerable Objects => InternalChildren.Cast(); - public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); - - public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); - public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); - } + /// + /// Creates the container that will be used to contain the s. + /// + protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer(); private class ScaledContainer : Container { diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs new file mode 100644 index 0000000000..0a69d00377 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public class GlobalScrollingAlgorithm : IScrollingAlgorithm + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly IReadOnlyList controlPoints; + + public GlobalScrollingAlgorithm(IReadOnlyList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange + 1000; + + if (!(obj.HitObject is IHasEndTime endTime)) + continue; + + var diff = positionAt(endTime.EndTime, timeRange) - startPosition; + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = (float)(diff * length.Y); + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = (float)(diff * length.X); + break; + } + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + var timelinePosition = positionAt(currentTime, timeRange); + + foreach (var obj in hitObjects) + { + var finalPosition = hitObjectPositions[obj] - timelinePosition; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(finalPosition * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-finalPosition * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(finalPosition * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-finalPosition * length.X); + break; + } + } + } + + private double positionAt(double time, double timeRange) + { + double length = 0; + for (int i = 0; i < controlPoints.Count; i++) + { + var current = controlPoints[i]; + var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; + + if (i > 0 && current.StartTime > time) + continue; + + // Duration of the current control point + var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; + + length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / timeRange; + } + + return length; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs new file mode 100644 index 0000000000..2621ae7d6f --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public interface IScrollingAlgorithm + { + void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length); + void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length); + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..23dff01940 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling.Algorithms; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class GlobalScrollingHitObjectContainer : ScrollingHitObjectContainer + { + public GlobalScrollingHitObjectContainer(ScrollingDirection direction) + : base(direction) + { + } + + protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new GlobalScrollingAlgorithm(ControlPoints); + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e0df4321a8..e1d8fe8d59 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,19 +1,17 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI.Scrolling.Algorithms; namespace osu.Game.Rulesets.UI.Scrolling { - public class ScrollingHitObjectContainer : Playfield.HitObjectContainer + public abstract class ScrollingHitObjectContainer : HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble { @@ -21,22 +19,32 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = double.MaxValue }; + protected readonly SortedList ControlPoints = new SortedList(); + private readonly ScrollingDirection direction; - private Cached positionCache = new Cached(); + private Cached initialStateCache = new Cached(); - public ScrollingHitObjectContainer(ScrollingDirection direction) + protected ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; RelativeSizeAxes = Axes.Both; - TimeRange.ValueChanged += v => positionCache.Invalidate(); + TimeRange.ValueChanged += v => initialStateCache.Invalidate(); + } + + private IScrollingAlgorithm scrollingAlgorithm; + protected override void LoadComplete() + { + base.LoadComplete(); + + scrollingAlgorithm = CreateScrollingAlgorithm(); } public override void Add(DrawableHitObject hitObject) { - positionCache.Invalidate(); + initialStateCache.Invalidate(); base.Add(hitObject); } @@ -44,69 +52,42 @@ namespace osu.Game.Rulesets.UI.Scrolling { var result = base.Remove(hitObject); if (result) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return result; } - private readonly SortedList controlPoints = new SortedList(); - public void AddControlPoint(MultiplierControlPoint controlPoint) { - controlPoints.Add(controlPoint); - positionCache.Invalidate(); + ControlPoints.Add(controlPoint); + initialStateCache.Invalidate(); } public bool RemoveControlPoint(MultiplierControlPoint controlPoint) { - var result = controlPoints.Remove(controlPoint); + var result = ControlPoints.Remove(controlPoint); if (result) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return result; } public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) { if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) - positionCache.Invalidate(); + initialStateCache.Invalidate(); return base.Invalidate(invalidation, source, shallPropagate); } - private readonly Dictionary hitObjectPositions = new Dictionary(); - protected override void Update() { base.Update(); - if (positionCache.IsValid) + if (initialStateCache.IsValid) return; - foreach (var obj in Objects) - { - var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime); + scrollingAlgorithm.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); - obj.LifetimeStart = obj.HitObject.StartTime - TimeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + TimeRange + 1000; - - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - var length = positionAt(endTime.EndTime) - startPosition; - - switch (direction) - { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = (float)(length * DrawHeight); - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = (float)(length * DrawWidth); - break; - } - } - - positionCache.Validate(); + initialStateCache.Validate(); } protected override void UpdateAfterChildrenLife() @@ -116,48 +97,12 @@ namespace osu.Game.Rulesets.UI.Scrolling // We need to calculate this as soon as possible after lifetimes so that hitobjects // get the final say in their positions - var timelinePosition = positionAt(Time.Current); - - foreach (var obj in AliveObjects) - { - var finalPosition = hitObjectPositions[obj] - timelinePosition; - - switch (direction) - { - case ScrollingDirection.Up: - obj.Y = (float)(finalPosition * DrawHeight); - break; - case ScrollingDirection.Down: - obj.Y = (float)(-finalPosition * DrawHeight); - break; - case ScrollingDirection.Left: - obj.X = (float)(finalPosition * DrawWidth); - break; - case ScrollingDirection.Right: - obj.X = (float)(-finalPosition * DrawWidth); - break; - } - } + scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } - private double positionAt(double time) - { - double length = 0; - for (int i = 0; i < controlPoints.Count; i++) - { - var current = controlPoints[i]; - var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; - - if (i > 0 && current.StartTime > time) - continue; - - // Duration of the current control point - var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; - - length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / TimeRange; - } - - return length; - } + /// + /// Creates the algorithm that will process the positions of the s. + /// + protected abstract IScrollingAlgorithm CreateScrollingAlgorithm(); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 899048531f..f560d8eaa6 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// A type of specialized towards scrolling s. /// - public class ScrollingPlayfield : Playfield + public abstract class ScrollingPlayfield : Playfield { /// /// The default span of time visible by the length of the scrolling axes. @@ -49,7 +49,9 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// The container that contains the s and s. /// - public new readonly ScrollingHitObjectContainer HitObjects; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + + private readonly ScrollingDirection direction; /// /// Creates a new . @@ -59,7 +61,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null) : base(customWidth) { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(direction) { RelativeSizeAxes = Axes.Both }; + this.direction = direction; HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -105,6 +107,14 @@ namespace osu.Game.Rulesets.UI.Scrolling this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); } + protected sealed override HitObjectContainer CreateHitObjectContainer() => CreateScrollingHitObjectContainer(); + + /// + /// Creates the that will handle the scrolling of the s. + /// + /// + protected virtual ScrollingHitObjectContainer CreateScrollingHitObjectContainer() => new GlobalScrollingHitObjectContainer(direction); + private class TransformVisibleTimeRange : Transform { private double valueAt(double time) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6d8ce3c1b6..a33cf73934 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -315,6 +315,10 @@ + + + + From 4ab3b0d76be328d8141305930eba63d4f3384bb2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sun, 7 Jan 2018 13:24:09 +0900 Subject: [PATCH 068/133] Implement local scrolling hit object container --- .../Algorithms/LocalScrollingAlgorithm.cs | 79 +++++++++++++++++++ .../LocalScrollingHitObjectContainer.cs | 17 ++++ osu.Game/osu.Game.csproj | 2 + 3 files changed, 98 insertions(+) create mode 100644 osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs create mode 100644 osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs new file mode 100644 index 0000000000..ddd06a3725 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +{ + public class LocalScrollingAlgorithm : IScrollingAlgorithm + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly SortedList controlPoints; + + public LocalScrollingAlgorithm(SortedList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + obj.LifetimeEnd = ((obj as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + var position = (obj.HitObject.StartTime - currentTime) * controlPoint.Multiplier / timeRange; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(position * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-position * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(position * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-position * length.X); + break; + } + } + } + + private readonly MultiplierControlPoint searchPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (controlPoints.Count == 0) + return new MultiplierControlPoint(double.NegativeInfinity); + + if (time < controlPoints[0].StartTime) + return controlPoints[0]; + + searchPoint.StartTime = time; + int index = controlPoints.BinarySearch(searchPoint); + + if (index < 0) + index = ~index - 1; + + return controlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..ceef688cbc --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Game.Rulesets.UI.Scrolling.Algorithms; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class LocalScrollingHitObjectContainer : ScrollingHitObjectContainer + { + public LocalScrollingHitObjectContainer(ScrollingDirection direction) + : base(direction) + { + } + + protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new LocalScrollingAlgorithm(ControlPoints); + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a33cf73934..327b87d5de 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -318,7 +318,9 @@ + + From c4d1922c8bbf653a563f8a0854bfff3f7f1e5c78 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 8 Jan 2018 11:34:37 +0900 Subject: [PATCH 069/133] Add scrolling algorithm to global settings --- osu.Game/Configuration/OsuConfigManager.cs | 5 +++- .../Configuration/ScrollingAlgorithmType.cs | 15 +++++++++++ .../Sections/Gameplay/ScrollingSettings.cs | 26 ++++++++++++++++++ .../Settings/Sections/GameplaySection.cs | 3 ++- osu.Game/Rulesets/UI/Playfield.cs | 8 +++--- .../Algorithms/LocalScrollingAlgorithm.cs | 2 +- .../GlobalScrollingHitObjectContainer.cs | 17 ------------ .../LocalScrollingHitObjectContainer.cs | 17 ------------ .../Scrolling/ScrollingHitObjectContainer.cs | 27 +++++++++++-------- .../UI/Scrolling/ScrollingPlayfield.cs | 14 +++++----- osu.Game/osu.Game.csproj | 4 +-- 11 files changed, 77 insertions(+), 61 deletions(-) create mode 100644 osu.Game/Configuration/ScrollingAlgorithmType.cs create mode 100644 osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs delete mode 100644 osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs delete mode 100644 osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index f4c7bdb586..4ff4105b77 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -71,6 +71,8 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); + Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -114,6 +116,7 @@ namespace osu.Game.Configuration ShowFpsDisplay, ChatDisplayHeight, Version, - ShowConvertedBeatmaps + ShowConvertedBeatmaps, + ScrollingAlgorithm } } diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/ScrollingAlgorithmType.cs new file mode 100644 index 0000000000..b4a2b8a4a3 --- /dev/null +++ b/osu.Game/Configuration/ScrollingAlgorithmType.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using System.ComponentModel; + +namespace osu.Game.Configuration +{ + public enum ScrollingAlgorithmType + { + [Description("Global")] + Global, + [Description("Local")] + Local + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs new file mode 100644 index 0000000000..b2a2a25da7 --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Configuration; + +namespace osu.Game.Overlays.Settings.Sections.Gameplay +{ + public class ScrollingSettings : SettingsSubsection + { + protected override string Header => "Scrolling"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new[] + { + new SettingsEnumDropdown + { + LabelText = "Scrolling algorithm", + Bindable = config.GetBindable(OsuSetting.ScrollingAlgorithm), + } + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index 035a3c7a13..8b05bfe8de 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -21,6 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections { new GeneralSettings(), new SongSelectSettings(), + new ScrollingSettings() }; } @@ -35,4 +36,4 @@ namespace osu.Game.Overlays.Settings.Sections } } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 91ea3ade2a..0f8a650718 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public readonly HitObjectContainer HitObjects; + public HitObjectContainer HitObjects { get; private set; } public Container ScaledContent; @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); - - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; + Add(HitObjects); } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index ddd06a3725..be8612ca96 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms var controlPoint = controlPointAt(obj.HitObject.StartTime); obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; - obj.LifetimeEnd = ((obj as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; + obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs deleted file mode 100644 index 23dff01940..0000000000 --- a/osu.Game/Rulesets/UI/Scrolling/GlobalScrollingHitObjectContainer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE - -using osu.Game.Rulesets.UI.Scrolling.Algorithms; - -namespace osu.Game.Rulesets.UI.Scrolling -{ - public class GlobalScrollingHitObjectContainer : ScrollingHitObjectContainer - { - public GlobalScrollingHitObjectContainer(ScrollingDirection direction) - : base(direction) - { - } - - protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new GlobalScrollingAlgorithm(ControlPoints); - } -} diff --git a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs deleted file mode 100644 index ceef688cbc..0000000000 --- a/osu.Game/Rulesets/UI/Scrolling/LocalScrollingHitObjectContainer.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE - -using osu.Game.Rulesets.UI.Scrolling.Algorithms; - -namespace osu.Game.Rulesets.UI.Scrolling -{ - public class LocalScrollingHitObjectContainer : ScrollingHitObjectContainer - { - public LocalScrollingHitObjectContainer(ScrollingDirection direction) - : base(direction) - { - } - - protected override IScrollingAlgorithm CreateScrollingAlgorithm() => new LocalScrollingAlgorithm(ControlPoints); - } -} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e1d8fe8d59..67f2e8aee0 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,17 +1,19 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Lists; +using osu.Game.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI.Scrolling.Algorithms; namespace osu.Game.Rulesets.UI.Scrolling { - public abstract class ScrollingHitObjectContainer : HitObjectContainer + public class ScrollingHitObjectContainer : HitObjectContainer { public readonly BindableDouble TimeRange = new BindableDouble { @@ -25,7 +27,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private Cached initialStateCache = new Cached(); - protected ScrollingHitObjectContainer(ScrollingDirection direction) + public ScrollingHitObjectContainer(ScrollingDirection direction) { this.direction = direction; @@ -35,11 +37,19 @@ namespace osu.Game.Rulesets.UI.Scrolling } private IScrollingAlgorithm scrollingAlgorithm; - protected override void LoadComplete() - { - base.LoadComplete(); - scrollingAlgorithm = CreateScrollingAlgorithm(); + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + switch (config.Get(OsuSetting.ScrollingAlgorithm)) + { + case ScrollingAlgorithmType.Global: + scrollingAlgorithm = new GlobalScrollingAlgorithm(ControlPoints); + break; + case ScrollingAlgorithmType.Local: + scrollingAlgorithm = new LocalScrollingAlgorithm(ControlPoints); + break; + } } public override void Add(DrawableHitObject hitObject) @@ -99,10 +109,5 @@ namespace osu.Game.Rulesets.UI.Scrolling scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } - - /// - /// Creates the algorithm that will process the positions of the s. - /// - protected abstract IScrollingAlgorithm CreateScrollingAlgorithm(); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index f560d8eaa6..8669339294 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; @@ -62,6 +63,11 @@ namespace osu.Game.Rulesets.UI.Scrolling : base(customWidth) { this.direction = direction; + } + + [BackgroundDependencyLoader] + private void load() + { HitObjects.TimeRange.BindTo(VisibleTimeRange); } @@ -107,13 +113,7 @@ namespace osu.Game.Rulesets.UI.Scrolling this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); } - protected sealed override HitObjectContainer CreateHitObjectContainer() => CreateScrollingHitObjectContainer(); - - /// - /// Creates the that will handle the scrolling of the s. - /// - /// - protected virtual ScrollingHitObjectContainer CreateScrollingHitObjectContainer() => new GlobalScrollingHitObjectContainer(direction); + protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); private class TransformVisibleTimeRange : Transform { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 327b87d5de..45183de092 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -265,6 +265,7 @@ + @@ -310,6 +311,7 @@ + @@ -319,8 +321,6 @@ - - From 44d821172ab2d60069e95c9986d94eda5f7b1e07 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 9 Jan 2018 16:29:12 +0100 Subject: [PATCH 070/133] tidying up --- osu.Game/Overlays/Social/FilterControl.cs | 1 - osu.Game/Overlays/Social/Header.cs | 13 +++-- osu.Game/Overlays/SocialOverlay.cs | 59 ++++++++++------------- 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index c05c3eb530..382b3fd0e7 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -21,7 +21,6 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { - Relevance, Rank, Name, Location, diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 5d243ad36f..0767e0aec0 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Social protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e"); protected override float TabStripWidth => 438; - protected override SocialTab DefaultTab => SocialTab.OnlinePlayers; + protected override SocialTab DefaultTab => SocialTab.AllPlayers; protected override FontAwesome Icon => FontAwesome.fa_users; protected override Drawable CreateHeaderText() @@ -54,13 +54,12 @@ namespace osu.Game.Overlays.Social public enum SocialTab { - Search, - [Description("Players")] - OnlinePlayers = SocialSortCriteria.Rank, + [Description("All Players")] + AllPlayers = SocialSortCriteria.Rank, [Description("Friends")] - OnlineFriends = SocialSortCriteria.Name, - //[Description("Online Team Members")] - //OnlineTeamMembers, + Friends = SocialSortCriteria.Name, + //[Description("Team Members")] + //TeamMembers, //[Description("Chat Channels")] //ChatChannels, } diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 95e588942c..6fffd37456 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -55,37 +55,35 @@ namespace osu.Game.Overlays Filter.Search.Current.ValueChanged += text => { - if (text != string.Empty) + if (!string.IsNullOrEmpty(text)) { - Header.Tabs.Current.Value = SocialTab.Search; + // 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.Relevance; - } - else - { - Header.Tabs.Current.Value = SocialTab.OnlinePlayers; - - if (Filter.Tabs.Current.Value == SocialSortCriteria.Relevance) + if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank) Filter.Tabs.Current.Value = SocialSortCriteria.Rank; } }; - Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; - - // TODO sort our list in some way (either locally or with API call) - //Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); - Header.Tabs.Current.ValueChanged += tab => { - if (tab != SocialTab.Search) - { - //currentQuery.Value = string.Empty; - Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; - Scheduler.AddOnce(updateSearch); - } + //currentQuery.Value = string.Empty; + Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; + Scheduler.AddOnce(updateSearch); }; + Filter.Tabs.Current.ValueChanged += sortCriteria => + { + // force searching in players until searching for friends is supported + if (Header.Tabs.Current.Value != SocialTab.AllPlayers && sortCriteria != (SocialSortCriteria)Header.Tabs.Current.Value) + Header.Tabs.Current.Value = SocialTab.AllPlayers; + + Scheduler.AddOnce(updateSearch); + }; + + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); + //currentQuery.ValueChanged += v => //{ // queryChangedDebounce?.Cancel(); @@ -97,14 +95,6 @@ namespace osu.Game.Overlays //}; //currentQuery.BindTo(Filter.Search.Current); - - Filter.Tabs.Current.ValueChanged += sortCriteria => - { - if (Header.Tabs.Current.Value != SocialTab.Search && sortCriteria != (SocialSortCriteria)Header.Tabs.Current.Value) - Header.Tabs.Current.Value = SocialTab.Search; - - Scheduler.AddOnce(updateSearch); - }; } [BackgroundDependencyLoader] @@ -148,11 +138,12 @@ namespace osu.Game.Overlays }) }; - LoadComponentAsync(newPanels, p => + LoadComponentAsync(newPanels, f => { if(panels != null) ScrollFlow.Remove(panels); + // delay new panels so they don't get added before the old ones are gone Scheduler.AddDelayed(() => ScrollFlow.Add(panels = newPanels), 200); }); } @@ -190,13 +181,13 @@ namespace osu.Game.Overlays switch (Header.Tabs.Current.Value) { - case SocialTab.OnlineFriends: - var friendRequest = new GetFriendsRequest(); + case SocialTab.Friends: + var friendRequest = new GetFriendsRequest(); // TODO filter arguments? friendRequest.Success += updateUsers; api.Queue(getUsersRequest = friendRequest); break; default: - var userRequest = new GetUsersRequest(); // TODO filter??? + var userRequest = new GetUsersRequest(); // TODO filter arguments! userRequest.Success += response => updateUsers(response.Select(r => r.User)); api.Queue(getUsersRequest = userRequest); break; @@ -223,7 +214,7 @@ namespace osu.Game.Overlays break; default: Users = null; - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + clearPanels(); break; } } From 4ce125478a533646cb5c48c4652cae99abd729c6 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Tue, 9 Jan 2018 19:03:23 +0100 Subject: [PATCH 071/133] remove unnecessary Schedules one was bugging out when rapidly switching display styles and the other was... unnecessary --- osu.Game/Overlays/SocialOverlay.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 6fffd37456..8d91ae0c18 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -143,8 +143,7 @@ namespace osu.Game.Overlays if(panels != null) ScrollFlow.Remove(panels); - // delay new panels so they don't get added before the old ones are gone - Scheduler.AddDelayed(() => ScrollFlow.Add(panels = newPanels), 200); + ScrollFlow.Add(panels = newPanels); }); } @@ -197,12 +196,9 @@ namespace osu.Game.Overlays private void updateUsers(IEnumerable newUsers) { - Schedule(() => - { - Users = newUsers; - loading.Hide(); - recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); - }); + Users = newUsers; + loading.Hide(); + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } public void APIStateChanged(APIAccess api, APIState state) From 17e7f75aca98dc5dc826b35bd29202c9bba841dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 15:41:13 +0900 Subject: [PATCH 072/133] More osu!-side bindable fixes --- osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs | 2 +- osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs | 2 +- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 4 ++-- osu.Game/Overlays/Settings/SettingsSlider.cs | 4 ++-- osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs index ce32dbe889..8a64f7c9a4 100644 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs @@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual } private class TestSliderBar : OsuSliderBar - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { public TestSliderBar() { diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs index c4b3a63bf2..af2b9be351 100644 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs +++ b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tests.Visual } private class TestSliderBar : OsuSliderBar - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { public TestSliderBar() { diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index e3d9a89bf7..d42efe6678 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -18,7 +18,7 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Graphics.UserInterface { public class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { private SampleChannel sample; private double lastSampleTime; @@ -69,7 +69,7 @@ namespace osu.Game.Graphics.UserInterface if (bindableInt != null) return bindableInt.Value.ToString("N0"); - return Current.Value.ToString(); + return Current.Value.ToString(CultureInfo.InvariantCulture); } } diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 43f1fa6a02..56aa77a24f 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -10,12 +10,12 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { public class SettingsSlider : SettingsSlider> - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { } public class SettingsSlider : SettingsItem - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible where U : OsuSliderBar, new() { protected override Drawable CreateControl() => new U diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs b/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs index e6e909183d..724f28dadf 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs +++ b/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs @@ -11,7 +11,7 @@ using osu.Game.Overlays.Settings; namespace osu.Game.Screens.Play.ReplaySettings { public class ReplaySliderBar : SettingsSlider - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { protected override Drawable CreateControl() => new Sliderbar { From c010b48b2984e1c625505a778d904a2c3b0b79c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 17:29:16 +0900 Subject: [PATCH 073/133] Remove number format specified from OsuSliderBar, override ToolTipText Better/cleaner solution. --- .../Visual/TestCaseSliderBarPercentage.cs | 123 ------------- .../Visual/TestCaseSliderBarPrecision.cs | 172 ------------------ osu.Game.Tests/osu.Game.Tests.csproj | 2 - .../Graphics/UserInterface/OsuSliderBar.cs | 22 +-- osu.Game/Overlays/Settings/SettingsSlider.cs | 10 - .../Play/ReplaySettings/PlaybackSettings.cs | 2 +- .../Play/ReplaySettings/ReplaySliderBar.cs | 2 + 7 files changed, 5 insertions(+), 328 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs delete mode 100644 osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs deleted file mode 100644 index 8a64f7c9a4..0000000000 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPercentage.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Configuration; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseSliderBarPercentage : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] { typeof(OsuSliderBar<>) }; - - private readonly BindableFloat floatValue; - private readonly BindableDouble doubleValue; - - private readonly TestSliderBar floatSliderBar; - private readonly TestSliderBar doubleSliderBar; - - public TestCaseSliderBarPercentage() - { - floatValue = new BindableFloat - { - MinValue = -1, - MaxValue = 1, - }; - - doubleValue = new BindableDouble - { - MinValue = -1, - MaxValue = 1 - }; - - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - Width = 300, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - floatSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, - doubleSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X } - } - }; - - floatSliderBar.Current.BindTo(floatValue); - doubleSliderBar.Current.BindTo(doubleValue); - - floatValue.ValueChanged += setValue; - doubleValue.ValueChanged += setValue; - - AddStep("Digits = 0", () => setPercentageDigits(0)); - AddStep("Value = 0", () => setValue(0)); - AddAssert("Check 0%", () => checkExact(0)); - - AddStep("Value = 0.5", () => setValue(0.5)); - AddAssert("Check 50%", () => checkExact(0.5m)); - - AddStep("Value = 0.54", () => setValue(0.54)); - AddAssert("Check 54%", () => checkExact(0.54m)); - - AddStep("Value = 0.544", () => setValue(0.544)); - AddAssert("Check 54%", () => checkExact(0.54m)); - - AddStep("Value = 0.548", () => setValue(0.548)); - AddAssert("Check 55%", () => checkExact(0.55m)); - - AddStep("Digits = 1", () => setPercentageDigits(1)); - AddAssert("Check 54.8%", () => checkExact(0.548m)); - - AddSliderStep("Percentage", -1.0, 1.0, 0.0, setValue); - AddSliderStep("Digits", 0, 7, 1, setPercentageDigits); - } - - private bool checkExact(decimal percentage) - { - string expectedValue = percentage.ToString("P", floatSliderBar.Format); - return floatSliderBar.TooltipText == expectedValue && doubleSliderBar.TooltipText == expectedValue; - } - - private void setValue(T value) - { - floatValue.Value = Convert.ToSingle(value); - doubleValue.Value = Convert.ToDouble(value); - } - - private void setPercentageDigits(int digits) - { - floatSliderBar.Format.PercentDecimalDigits = digits; - doubleSliderBar.Format.PercentDecimalDigits = digits; - - // Make sure that the text referenced in TestSliderBar is updated - // This doesn't break any assertions if missing, but breaks the visual display - floatSliderBar.Current.TriggerChange(); - doubleSliderBar.Current.TriggerChange(); - } - - private class TestSliderBar : OsuSliderBar - where T : struct, IEquatable, IComparable, IConvertible - { - public TestSliderBar() - { - SpriteText valueText; - AddInternal(valueText = new OsuSpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - X = 5, - Text = TooltipText - }); - - Current.ValueChanged += v => valueText.Text = TooltipText; - } - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs b/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs deleted file mode 100644 index af2b9be351..0000000000 --- a/osu.Game.Tests/Visual/TestCaseSliderBarPrecision.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseSliderBarPrecision : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] { typeof(OsuSliderBar<>) }; - - private readonly BindableInt intValue; - private readonly BindableFloat floatValue; - private readonly BindableDouble doubleValue; - - private readonly TestSliderBar intSliderBar; - private readonly TestSliderBar floatSliderBar; - private readonly TestSliderBar doubleSliderBar; - - public TestCaseSliderBarPrecision() - { - intValue = new BindableInt - { - MinValue = -1000, - MaxValue = 1000, - }; - - floatValue = new BindableFloat - { - MinValue = -1000, - MaxValue = 1000, - }; - - doubleValue = new BindableDouble - { - MinValue = -1000, - MaxValue = 1000 - }; - - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - Width = 300, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Children = new Drawable[] - { - intSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, - floatSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X }, - doubleSliderBar = new TestSliderBar { RelativeSizeAxes = Axes.X } - } - }; - - intSliderBar.Current.BindTo(intValue); - floatSliderBar.Current.BindTo(floatValue); - doubleSliderBar.Current.BindTo(doubleValue); - - intValue.ValueChanged += setValue; - floatValue.ValueChanged += setValue; - doubleValue.ValueChanged += setValue; - - AddStep("Value = 0", () => setValue(0)); - AddStep("Digits = 0", () => setDecimalDigits(0)); - AddAssert("Check all 0", () => checkExact("0")); - - AddStep("Digits = 3", () => setDecimalDigits(3)); - AddAssert("Check 0.000", () => checkExact(0.000m)); - - AddStep("Value = 0.5", () => setValue(0.5)); - AddAssert("Check 0.500", () => checkExact(0.500m)); - - AddStep("Value = 123.4567", () => setValue(123.4567)); - AddAssert("Check 123.457", () => checkExact(123.457m)); - - AddStep("Value = 765.4312", () => setValue(765.4312)); - AddAssert("Check 765.431", () => checkExact(765.431m)); - - AddStep("Value = -12.3456", () => setValue(-12.3456)); - AddAssert("Check -12.346", () => checkExact(-12.346m)); - AddStep("Digits = 1", () => setDecimalDigits(1)); - AddAssert("Check -12.3", () => checkExact(-12.3m)); - AddStep("Digits = 0", () => setDecimalDigits(0)); - AddAssert("Check -12", () => checkExact(-12m)); - - AddStep("Value = -12.8", () => setValue(-12.8)); - AddAssert("Check -13", () => checkExact(-13m)); - AddStep("Digits = 1", () => setDecimalDigits(1)); - AddAssert("Check -12.8", () => checkExact(-12.8m)); - - AddSliderStep("Digits", 0, 7, 1, setDecimalDigits); - } - - /// - /// Checks whether all sliderbar tooltips display an exact value. - /// - /// The expected value that should be displayed. - private bool checkExact(string value) - => intSliderBar.TooltipText == value - && floatSliderBar.TooltipText == value - && doubleSliderBar.TooltipText == value; - - /// - /// Checks whether all sliderbar tooltips display an exact value. - /// - /// The expected value that should be displayed. - private bool checkExact(decimal value) - { - var expectedDecimal = value.ToString(intSliderBar.Format); - - return intSliderBar.TooltipText == Convert.ToInt32(value).ToString("N0") - && floatSliderBar.TooltipText == expectedDecimal - && doubleSliderBar.TooltipText == expectedDecimal; - } - - /// - /// Checks whether all floating-point sliderbar tooltips have a certain number of decimal digits. - /// - /// The expected number of decimal digits. - private bool checkDecimalDigits(int decimals) - => checkDecimalDigits(decimals, floatSliderBar.TooltipText) - && checkDecimalDigits(decimals, doubleSliderBar.TooltipText); - - private bool checkDecimalDigits(int decimals, string value) - => value.Length - value.IndexOf(intSliderBar.Format.NumberDecimalSeparator, StringComparison.InvariantCulture) - 1 == decimals; - - private void setValue(T value) - { - intValue.Value = Convert.ToInt32(value); - floatValue.Value = Convert.ToSingle(value); - doubleValue.Value = Convert.ToDouble(value); - } - - private void setDecimalDigits(int digits) - { - intSliderBar.Format.NumberDecimalDigits = digits; - floatSliderBar.Format.NumberDecimalDigits = digits; - doubleSliderBar.Format.NumberDecimalDigits = digits; - - // Make sure that the text referenced in TestSliderBar is updated - // This doesn't break any assertions if missing, but breaks the visual display - intSliderBar.Current.TriggerChange(); - floatSliderBar.Current.TriggerChange(); - doubleSliderBar.Current.TriggerChange(); - } - - private class TestSliderBar : OsuSliderBar - where T : struct, IEquatable, IComparable, IConvertible - { - public TestSliderBar() - { - SpriteText valueText; - AddInternal(valueText = new OsuSpriteText - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreLeft, - X = 5, - Text = TooltipText - }); - - Current.ValueChanged += v => valueText.Text = TooltipText; - } - } - } -} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 53d971a0b3..8c04874e75 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -132,8 +132,6 @@ - - diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index d42efe6678..f574ac13f7 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -28,24 +28,6 @@ namespace osu.Game.Graphics.UserInterface private readonly Box leftBox; private readonly Box rightBox; - private NumberFormatInfo format; - public NumberFormatInfo Format - { - get => format ?? (format = createDefaultFormat()); - set - { - if (format == value) - return; - format = value; - - if (IsLoaded) - { - // Some users may want to see the updated ToolTipText - Current.TriggerChange(); - } - } - } - public virtual string TooltipText { get @@ -60,9 +42,9 @@ namespace osu.Game.Graphics.UserInterface var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) - return floatValue.Value.ToString("P", Format); + return floatValue.Value.ToString("P0"); - return floatValue.Value.ToString("F", Format); + return floatValue.Value.ToString("N1"); } var bindableInt = CurrentNumber as BindableNumber; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 56aa77a24f..708d9437a5 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Globalization; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; @@ -24,15 +23,6 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X }; - /// - /// The format that will be used for the tooltip when the sliderbar is hovered. - /// - public NumberFormatInfo Format - { - get => ((U)Control).Format; - set => ((U)Control).Format = value; - } - public float KeyboardStep; [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs index 65d83480a0..a63a3415e3 100644 --- a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs @@ -59,7 +59,6 @@ namespace osu.Game.Screens.Play.ReplaySettings } }; - sliderbar.Format.NumberDecimalDigits = 2; sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{rateMultiplier}x"; } @@ -73,5 +72,6 @@ namespace osu.Game.Screens.Play.ReplaySettings var clockRate = AdjustableClock.Rate; sliderbar.Bindable.ValueChanged += rateMultiplier => AdjustableClock.Rate = clockRate * rateMultiplier; } + } } diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs b/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs index 724f28dadf..e755e6bfd9 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs +++ b/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs @@ -21,6 +21,8 @@ namespace osu.Game.Screens.Play.ReplaySettings private class Sliderbar : OsuSliderBar { + public override string TooltipText => $"{CurrentNumber.Value}"; + [BackgroundDependencyLoader] private void load(OsuColour colours) { From d1476833619261ed5ff136d6faf33069cf9ad2dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 17:39:15 +0900 Subject: [PATCH 074/133] Cleanup --- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 9 --------- osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs | 1 - 2 files changed, 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index f574ac13f7..3c3939586e 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -113,15 +113,6 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Pink; } - private NumberFormatInfo createDefaultFormat() - { - var nfi = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone(); - nfi.PercentDecimalDigits = 0; - nfi.NumberDecimalDigits = 1; - - return nfi; - } - protected override bool OnHover(InputState state) { Nub.Glowing = true; diff --git a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs index a63a3415e3..f8ac653f69 100644 --- a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs @@ -72,6 +72,5 @@ namespace osu.Game.Screens.Play.ReplaySettings var clockRate = AdjustableClock.Rate; sliderbar.Bindable.ValueChanged += rateMultiplier => AdjustableClock.Rate = clockRate * rateMultiplier; } - } } From 1c412e233ae48e65bf17f1a0fce1b8181dd93db9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:04:12 +0900 Subject: [PATCH 075/133] Update submodules --- osu-framework | 2 +- osu-resources | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index 067fdb8f5b..80bcb82ef8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 067fdb8f5b0594be1cd30e6bbd43f2ea749904ec +Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 diff --git a/osu-resources b/osu-resources index e01f71160f..7724abdf1d 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 +Subproject commit 7724abdf1d7c9705ba2e3989a9c604e17ccdc871 From f71d086a41e25704ad801fc05c4e04bd6e90a114 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:05:19 +0900 Subject: [PATCH 076/133] Fix post-merge issues --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +--- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index dd99229cca..7fdabd46c2 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; @@ -24,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Axes.Y, BASE_WIDTH) + : base(ScrollingDirection.Down, BASE_WIDTH) { Container explodingFruitContainer; diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index eab39ff002..39f8333413 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -64,7 +64,6 @@ - @@ -120,7 +119,7 @@ - + From 9036ea92ebc3146124348af74b3c490e6b6d51ac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 18:29:46 +0900 Subject: [PATCH 077/133] Run child updates for nested hitobjects when parent hitobjects are masked --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 34c34e1d33..e461cb96c5 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -36,6 +36,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveCompletedTransforms => false; public override bool RemoveWhenNotAlive => false; + protected override bool RequiresChildrenUpdate => true; protected DrawableHitObject(HitObject hitObject) { From 6255aaab687335b73e941fedb89ea72bbe6725f7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 10 Jan 2018 19:17:43 +0900 Subject: [PATCH 078/133] Per-hitobject lifetime management --- .../Objects/Drawables/DrawableHoldNote.cs | 4 ++++ .../Objects/Drawables/DrawableHoldNoteTick.cs | 4 ---- .../Objects/Drawables/DrawableManiaHitObject.cs | 4 ++++ osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 7 +++++++ .../Objects/Drawables/DrawableDrumRoll.cs | 7 +++++++ .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 1 - .../UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 3 --- 8 files changed, 23 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 8e3159d531..1ed7cc594a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -251,6 +251,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } + protected override void UpdateState(ArmedState state) + { + } + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down public override bool OnReleased(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index cfe82a2b59..0685c7bb2d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -38,10 +38,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables RelativeSizeAxes = Axes.X; Size = new Vector2(1); - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - Children = new[] { glowContainer = new CircularContainer diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 5b98d84e68..0a1624b464 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; using OpenTK.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -19,6 +20,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + HitObject = hitObject; if (action != null) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 1696de2880..101db0205c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -78,6 +78,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 564e496af5..0f16f85b63 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -100,6 +100,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 96485fbc9e..3408a830ed 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - Content.ScaleTo(0, 100, Easing.OutQuint); + Content.ScaleTo(0, 100, Easing.OutQuint).Expire(); break; } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index 0a69d00377..a8e41a951b 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -28,7 +28,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange); obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange + 1000; if (!(obj.HitObject is IHasEndTime endTime)) continue; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index be8612ca96..c956766474 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Framework.Lists; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; @@ -26,9 +25,7 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms foreach (var obj in hitObjects) { var controlPoint = controlPointAt(obj.HitObject.StartTime); - obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; - obj.LifetimeEnd = ((obj.HitObject as IHasEndTime)?.EndTime ?? obj.HitObject.StartTime) + timeRange / controlPoint.Multiplier; } } From 312f52072bd4762e5cbd998e1fd905f736c13126 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Wed, 10 Jan 2018 16:46:55 +0100 Subject: [PATCH 079/133] enable query change Avatar animation too add forgotten usings --- osu.Game/Overlays/Social/Header.cs | 4 +-- osu.Game/Overlays/SocialOverlay.cs | 42 ++++++++++++------------------ osu.Game/Users/UpdateableAvatar.cs | 2 +- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 0767e0aec0..7bb4b4dde9 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -55,9 +55,9 @@ namespace osu.Game.Overlays.Social public enum SocialTab { [Description("All Players")] - AllPlayers = SocialSortCriteria.Rank, + AllPlayers, [Description("Friends")] - Friends = SocialSortCriteria.Name, + Friends, //[Description("Team Members")] //TeamMembers, //[Description("Chat Channels")] diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 8d91ae0c18..161ff70dc9 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -15,6 +15,8 @@ using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; +using osu.Framework.Configuration; +using osu.Framework.Threading; namespace osu.Game.Overlays { @@ -65,36 +67,24 @@ namespace osu.Game.Overlays } }; - Header.Tabs.Current.ValueChanged += tab => - { - //currentQuery.Value = string.Empty; - Filter.Tabs.Current.Value = (SocialSortCriteria)Header.Tabs.Current.Value; - Scheduler.AddOnce(updateSearch); - }; + Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); - Filter.Tabs.Current.ValueChanged += sortCriteria => - { - // force searching in players until searching for friends is supported - if (Header.Tabs.Current.Value != SocialTab.AllPlayers && sortCriteria != (SocialSortCriteria)Header.Tabs.Current.Value) - Header.Tabs.Current.Value = SocialTab.AllPlayers; - - Scheduler.AddOnce(updateSearch); - }; + Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); - //currentQuery.ValueChanged += v => - //{ - // queryChangedDebounce?.Cancel(); + currentQuery.ValueChanged += query => + { + queryChangedDebounce?.Cancel(); - // if (string.IsNullOrEmpty(v)) - // Scheduler.AddOnce(updateSearch); - // else - // queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); - //}; + if (string.IsNullOrEmpty(query)) + Scheduler.AddOnce(updateSearch); + else + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + }; - //currentQuery.BindTo(Filter.Search.Current); + currentQuery.BindTo(Filter.Search.Current); } [BackgroundDependencyLoader] @@ -159,13 +149,13 @@ namespace osu.Game.Overlays private APIRequest getUsersRequest; - //private readonly Bindable currentQuery = new Bindable(); + private readonly Bindable currentQuery = new Bindable(); - //private ScheduledDelegate queryChangedDebounce; + private ScheduledDelegate queryChangedDebounce; private void updateSearch() { - //queryChangedDebounce?.Cancel(); + queryChangedDebounce?.Cancel(); if (!IsLoaded) return; diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index e58647c7f6..2edd7cbf55 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -44,7 +44,7 @@ namespace osu.Game.Users new Avatar(user) { RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), + OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), }) ); } From 6a5a3b01b265878c5fccca36cc80307769c5cfe5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 12:39:06 +0900 Subject: [PATCH 080/133] Fix license headers --- osu.Game/Configuration/ScrollingAlgorithmType.cs | 2 +- .../Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs | 2 +- osu.Game/Rulesets/UI/HitObjectContainer.cs | 2 +- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs | 2 +- .../Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs | 2 +- osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/ScrollingAlgorithmType.cs index b4a2b8a4a3..8b9d292634 100644 --- a/osu.Game/Configuration/ScrollingAlgorithmType.cs +++ b/osu.Game/Configuration/ScrollingAlgorithmType.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs index b2a2a25da7..3243f4c23a 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index e7843c86ca..c26a6cdff0 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index a8e41a951b..55a0a7c2f3 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs index 2621ae7d6f..f9863bd299 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index c956766474..b2d4289a9a 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using osu.Framework.Lists; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs index d89795f4d3..372bdb1030 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.UI.Scrolling { diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 67f2e8aee0..dfa6a40db4 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; From 3a869edf36312657761727a26917a3bafb5e7029 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 12:44:17 +0900 Subject: [PATCH 081/133] Add a flag to disable user scroll speed adjustments --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 1 + osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index b8e4ede120..3c5093d82f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -37,6 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// private const float left_area_size = 240; + protected override bool UserScrollSpeedAdjustment => false; private readonly Container hitExplosionContainer; private readonly Container kiaiExplosionContainer; diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 5be1c8bed7..11185015b8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -47,6 +47,11 @@ namespace osu.Game.Rulesets.UI.Scrolling MaxValue = time_span_max }; + /// + /// Whether the player can change . + /// + protected virtual bool UserScrollSpeedAdjustment => true; + /// /// The container that contains the s and s. /// @@ -92,6 +97,9 @@ namespace osu.Game.Rulesets.UI.Scrolling protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { + if (!UserScrollSpeedAdjustment) + return false; + if (state.Keyboard.ControlPressed) { switch (args.Key) From a6d8b28221910993005d6adbbcc5b0447b5a1511 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 13:40:46 +0900 Subject: [PATCH 082/133] Add OSD + config value for scroll speed --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 5 ++++- osu.Game/Configuration/OsuConfigManager.cs | 4 +++- osu.Game/Overlays/OnScreenDisplay.cs | 6 +++++- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 7 +++++-- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 919518dbe8..532be2759f 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -15,6 +15,7 @@ using osu.Framework.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; +using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.UI.Scrolling; @@ -161,8 +162,10 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, OsuConfigManager config) { + config.BindWith(OsuSetting.UserScrollSpeed, VisibleTimeRange); + normalColumnColours = new List { colours.RedDark, diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 13213a54a1..26879782fc 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -73,6 +73,7 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + Set(OsuSetting.UserScrollSpeed, 1500.0, 50.0, 10000.0); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -119,6 +120,7 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm + ScrollingAlgorithm, + UserScrollSpeed } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 6a1bd8e182..4f3f03c749 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Configuration; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays @@ -115,7 +116,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig) + private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager osuConfig) { trackSetting(frameworkConfig.GetBindable(FrameworkSetting.FrameSync), v => display(v, "Frame Limiter", v.GetDescription(), "Ctrl+F7")); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.AudioDevice), v => display(v, "Audio Device", string.IsNullOrEmpty(v) ? "Default" : v, v)); @@ -135,6 +136,9 @@ namespace osu.Game.Overlays }); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter")); + + // Todo: This should be part of the ruleset-specific OSD + trackSetting(osuConfig.GetBindable(OsuSetting.UserScrollSpeed), v => display(v, "Scroll Speed", $"{v:N0}ms", "Ctrl+(+/-) to change")); } private readonly List references = new List(); diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 11185015b8..fa04b7f137 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -102,13 +103,15 @@ namespace osu.Game.Rulesets.UI.Scrolling if (state.Keyboard.ControlPressed) { + var lastValue = Transforms.OfType().LastOrDefault()?.EndValue ?? VisibleTimeRange.Value; + switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(lastValue + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(lastValue - time_span_step, 200, Easing.OutQuint); break; } } From 9d00e5bb7dfc103003f11a73bda6d435b345686c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:08:30 +0900 Subject: [PATCH 083/133] Make ScrollingHitObjectContainer handle nested hitobjects --- .../Objects/Drawable/DrawableJuiceStream.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 24 +---------- .../Objects/Drawables/DrawableHoldNoteTick.cs | 3 -- .../Objects/Drawables/DrawableDrumRoll.cs | 7 +--- .../Objects/Drawables/DrawableDrumRollTick.cs | 12 ------ .../Objects/Drawables/DrawableHitObject.cs | 41 +++++++++++++------ .../Algorithms/GlobalScrollingAlgorithm.cs | 34 ++++++++------- .../Algorithms/LocalScrollingAlgorithm.cs | 6 +++ 8 files changed, 59 insertions(+), 70 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 031b70924d..dcb7fdb823 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; dropletContainer.Add(h); diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 1ed7cc594a..6748bc22e6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -7,7 +7,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Extensions.IEnumerableExtensions; @@ -59,12 +58,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, }, - tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, @@ -72,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, tail = new DrawableTailNote(this, action) { - Anchor = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre } }); @@ -174,13 +168,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } @@ -213,13 +200,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 0685c7bb2d..f9c0b96d37 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -32,9 +32,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - RelativePositionAxes = Axes.Y; - Y = (float)HitObject.StartTime; - RelativeSizeAxes = Axes.X; Size = new Vector2(1); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 0f16f85b63..2fa6c8ed95 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -37,12 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Y; Container tickContainer; - MainPiece.Add(tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2((float)HitObject.StartTime, 0), - RelativeChildSize = new Vector2((float)HitObject.Duration, 1) - }); + MainPiece.Add(tickContainer = new Container { RelativeSizeAxes = Axes.Both }); foreach (var tick in drumRoll.NestedHitObjects.OfType()) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 3408a830ed..bc5abce245 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -15,23 +15,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { - // Because ticks aren't added by the ScrollingPlayfield, we need to set the following properties ourselves - RelativePositionAxes = Axes.X; - X = (float)tick.StartTime; - FillMode = FillMode.Fit; } public override bool DisplayJudgement => false; - protected override void LoadComplete() - { - base.LoadComplete(); - - // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize - Width *= Parent.RelativeChildSize.X; - } - protected override TaikoPiece CreateMainPiece() => new TickPiece { Filled = HitObject.FirstTick diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e461cb96c5..13329a1470 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -38,11 +38,30 @@ namespace osu.Game.Rulesets.Objects.Drawables public override bool RemoveWhenNotAlive => false; protected override bool RequiresChildrenUpdate => true; + public virtual bool AllJudged => false; + protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; } + /// + /// Processes this , checking if any judgements have occurred. + /// + /// Whether the user triggered this process. + /// Whether a judgement has occurred from this or any nested s. + protected internal virtual bool UpdateJudgement(bool userTriggered) => false; + + private List nestedHitObjects; + public IReadOnlyList NestedHitObjects => nestedHitObjects; + + protected virtual void AddNested(DrawableHitObject h) + { + if (nestedHitObjects == null) + nestedHitObjects = new List(); + nestedHitObjects.Add(h); + } + /// /// The screen-space point that causes this to be selected in the Editor. /// @@ -145,7 +164,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been judged. /// - public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); + public sealed override bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); /// /// Notifies that a new judgement has occurred for this . @@ -181,7 +200,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether the user triggered this process. /// Whether a judgement has occurred from this or any nested s. - protected bool UpdateJudgement(bool userTriggered) + protected internal sealed override bool UpdateJudgement(bool userTriggered) { judgementOccurred = false; @@ -238,18 +257,16 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateJudgement(false); } - private List> nestedHitObjects; - protected IEnumerable> NestedHitObjects => nestedHitObjects; - - protected virtual void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject h) { - if (nestedHitObjects == null) - nestedHitObjects = new List>(); + base.AddNested(h); - h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); - h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); - h.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); - nestedHitObjects.Add(h); + if (!(h is DrawableHitObject hWithJudgement)) + return; + + hWithJudgement.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); + hWithJudgement.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); + hWithJudgement.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); } /// diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index 55a0a7c2f3..c1347ad122 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -29,22 +29,25 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; - if (!(obj.HitObject is IHasEndTime endTime)) - continue; - - var diff = positionAt(endTime.EndTime, timeRange) - startPosition; - - switch (direction) + if (obj.HitObject is IHasEndTime endTime) { - case ScrollingDirection.Up: - case ScrollingDirection.Down: - obj.Height = (float)(diff * length.Y); - break; - case ScrollingDirection.Left: - case ScrollingDirection.Right: - obj.Width = (float)(diff * length.X); - break; + var diff = positionAt(endTime.EndTime, timeRange) - startPosition; + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = (float)(diff * length.Y); + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = (float)(diff * length.X); + break; + } } + + if (obj.NestedHitObjects != null) + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); } } @@ -71,6 +74,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-finalPosition * length.X); break; } + + if (obj.NestedHitObjects != null) + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index b2d4289a9a..ecb7aaff95 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -26,6 +26,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { var controlPoint = controlPointAt(obj.HitObject.StartTime); obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + + if (obj.NestedHitObjects != null) + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); } } @@ -52,6 +55,9 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-position * length.X); break; } + + if (obj.NestedHitObjects != null) + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } From 428f8b6670b2a7b55861de4dc63d53389514a320 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:08:46 +0900 Subject: [PATCH 084/133] Fix up license header --- osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index 4f2e895e9d..b8e0934928 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -1,5 +1,5 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; From 9ae67b519b6bb8f81dab49efa465c6004e5a5981 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:25:15 +0900 Subject: [PATCH 085/133] Optimise nested hitobject position computations --- .../UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs | 6 +++--- .../UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs index c1347ad122..ed156ecfd5 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs @@ -47,7 +47,10 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms } if (obj.NestedHitObjects != null) + { ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } } } @@ -74,9 +77,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-finalPosition * length.X); break; } - - if (obj.NestedHitObjects != null) - ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs index ecb7aaff95..96a85c5f9f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs @@ -28,7 +28,10 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; if (obj.NestedHitObjects != null) + { ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } } } @@ -55,9 +58,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms obj.X = (float)(-position * length.X); break; } - - if (obj.NestedHitObjects != null) - ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); } } From d998936e9eaa57a276c3d371496c6dc3e95f0338 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 15:50:44 +0900 Subject: [PATCH 086/133] Fix testcase errors --- osu.Game/Rulesets/UI/Playfield.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 25a7adb5a7..a1d07d9a03 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); + + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; - Add(HitObjects); } From ab762045d608655c6495298544ed62c5545f6b36 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 16:51:46 +0900 Subject: [PATCH 087/133] Move back to using load(), fix testcase --- .../Visual/TestCaseEditorSelectionLayer.cs | 39 +++--- .../Visual/TestCaseScrollingHitObjects.cs | 114 ++++++++++-------- osu.Game/Rulesets/UI/Playfield.cs | 6 +- 3 files changed, 90 insertions(+), 69 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index b318d4afd3..f236182939 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Allocation; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,26 +19,10 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(SelectionLayer) }; - public TestCaseEditorSelectionLayer() + [BackgroundDependencyLoader] + private void load() { - var playfield = new OsuEditPlayfield - { - new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }), - new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f }), - new DrawableSlider(new Slider - { - ControlPoints = new List - { - new Vector2(128, 256), - new Vector2(344, 256), - }, - Distance = 400, - Position = new Vector2(128, 256), - Velocity = 1, - TickDistance = 100, - Scale = 0.5f - }) - }; + var playfield = new OsuEditPlayfield(); Children = new Drawable[] { @@ -49,6 +34,22 @@ namespace osu.Game.Tests.Visual }, new SelectionLayer(playfield) }; + + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f })); + playfield.Add(new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f })); + playfield.Add(new DrawableSlider(new Slider + { + ControlPoints = new List + { + new Vector2(128, 256), + new Vector2(344, 256), + }, + Distance = 400, + Position = new Vector2(128, 256), + Velocity = 1, + TickDistance = 100, + Scale = 0.5f + })); } } } diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs index b8e0934928..21d967c3e3 100644 --- a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +13,6 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; -using OpenTK.Graphics; namespace osu.Game.Tests.Visual { @@ -21,39 +20,29 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; - private readonly List playfields = new List(); + private readonly TestPlayfield[] playfields = new TestPlayfield[4]; public TestCaseScrollingHitObjects() { - playfields.Add(new TestPlayfield(ScrollingDirection.Down)); - playfields.Add(new TestPlayfield(ScrollingDirection.Right)); - - playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(double.MinValue))); - - Add(new Container + Add(new GridContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.85f), - Masking = true, - BorderColour = Color4.White, - BorderThickness = 2, - MaskingSmoothness = 1, - Children = new Drawable[] + Content = new[] { - new Box + new Drawable[] { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Alpha = 0.35f, + playfields[0] = new TestPlayfield(ScrollingDirection.Up), + playfields[1] = new TestPlayfield(ScrollingDirection.Down) }, - playfields[0], - playfields[1] + new Drawable[] + { + playfields[2] = new TestPlayfield(ScrollingDirection.Left), + playfields[3] = new TestPlayfield(ScrollingDirection.Right) + } } }); - AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.TimeRange.Value = v)); + AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.VisibleTimeRange.Value = v)); AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); } @@ -61,6 +50,8 @@ namespace osu.Game.Tests.Visual { base.LoadComplete(); + playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(0))); + for (int i = 0; i <= 5000; i += 1000) addHitObject(Time.Current + i); @@ -71,10 +62,10 @@ namespace osu.Game.Tests.Visual { playfields.ForEach(p => { - p.Add(new TestDrawableHitObject(time) - { - Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre - }); + var hitObject = new TestDrawableHitObject(time); + setAnchor(hitObject, p); + + p.Add(hitObject); }); } @@ -86,10 +77,12 @@ namespace osu.Game.Tests.Visual p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); - TestDrawableControlPoint createDrawablePoint(double t) => new TestDrawableControlPoint(t) + TestDrawableControlPoint createDrawablePoint(double t) { - Anchor = p.Direction == ScrollingDirection.Right ? Anchor.CentreRight : Anchor.BottomCentre - }; + var obj = new TestDrawableControlPoint(p.Direction, t); + setAnchor(obj, p); + return obj; + } p.Add(createDrawablePoint(time)); p.Add(createDrawablePoint(time + 2000)); @@ -97,12 +90,28 @@ namespace osu.Game.Tests.Visual }); } + private void setAnchor(DrawableHitObject obj, TestPlayfield playfield) + { + switch (playfield.Direction) + { + case ScrollingDirection.Up: + obj.Anchor = Anchor.TopCentre; + break; + case ScrollingDirection.Down: + obj.Anchor = Anchor.BottomCentre; + break; + case ScrollingDirection.Left: + obj.Anchor = Anchor.CentreLeft; + break; + case ScrollingDirection.Right: + obj.Anchor = Anchor.CentreRight; + break; + } + } private class TestPlayfield : ScrollingPlayfield { - public readonly BindableDouble TimeRange = new BindableDouble(5000); - public readonly ScrollingDirection Direction; public TestPlayfield(ScrollingDirection direction) @@ -110,34 +119,45 @@ namespace osu.Game.Tests.Visual { Direction = direction; - HitObjects.TimeRange.BindTo(TimeRange); + Padding = new MarginPadding(2); + ScaledContent.Masking = true; + + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + Depth = float.MaxValue + }); } } private class TestDrawableControlPoint : DrawableHitObject { - private readonly Box box; - - public TestDrawableControlPoint(double time) + public TestDrawableControlPoint(ScrollingDirection direction, double time) : base(new HitObject { StartTime = time }) { Origin = Anchor.Centre; - Add(box = new Box + Add(new Box { Anchor = Anchor.Centre, Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both }); - } - protected override void Update() - { - base.Update(); - - RelativeSizeAxes = (Anchor & Anchor.x2) > 0 ? Axes.Y : Axes.X; - Size = new Vector2(1); - - box.Size = DrawSize; + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + RelativeSizeAxes = Axes.X; + Height = 2; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + RelativeSizeAxes = Axes.Y; + Width = 2; + break; + } } protected override void UpdateState(ArmedState state) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index a1d07d9a03..25a7adb5a7 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.UI } } }); - - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] private void load() { + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; + Add(HitObjects); } From 5b190d3cd2e311cf28d1fcdf93ebf08c521ab288 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 12:47:04 +0900 Subject: [PATCH 088/133] Use correct container type when removing fruit (cherry picked from commit a2be7f7) --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index e02849d0f5..c70cb15b40 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; @@ -48,7 +49,7 @@ namespace osu.Game.Rulesets.Catch.UI var screenSpacePosition = fruit.ScreenSpaceDrawQuad.Centre; // todo: make this less ugly, somehow. - (fruit.Parent as Container)?.Remove(fruit); + (fruit.Parent as HitObjectContainer)?.Remove(fruit); (fruit.Parent as Container)?.Remove(fruit); fruit.RelativePositionAxes = Axes.None; From 66ebe2ee6679866d46b497a6b1318d8bc5cab5e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 20:55:43 +0900 Subject: [PATCH 089/133] Change anchors in line with new ScrollingPlayfield implementation (cherry picked from commit 079827d) --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 41313b9197..d9a16ad248 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable HitObject = hitObject; Scale = new Vector2(HitObject.Scale); + + Anchor = Anchor.BottomLeft; } } From 0609fc40de1ba8ba08e5126bc22c1351b027d268 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 20:56:09 +0900 Subject: [PATCH 090/133] Fix up DrawableJuiceStream/BananaShower (cherry picked from commit 0bfb3b6) --- .../Objects/Drawable/DrawableJuiceStream.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index dcb7fdb823..036c5bd879 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -16,15 +16,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public DrawableJuiceStream(JuiceStream s) : base(s) { RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + Origin = Anchor.BottomLeft; X = 0; - Child = dropletContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }; + Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; foreach (CatchHitObject tick in s.NestedHitObjects.OfType()) { From 61062164cb3944efb45066132015a3a67b4d9bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 21:12:27 +0900 Subject: [PATCH 091/133] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 80bcb82ef8..6594729122 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 +Subproject commit 65947291229541de3eb1aff0e703f6968b07f976 From e5f17e3ddbd6ec793f5e618fb57f2067b376f1ad Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 21:49:20 +0900 Subject: [PATCH 092/133] Remove scale from all but palpable fruit --- .../Objects/Drawable/DrawableCatchHitObject.cs | 14 +++++++++++--- .../Objects/Drawable/DrawableDroplet.cs | 2 +- .../Objects/Drawable/DrawableFruit.cs | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index d9a16ad248..554fb1323e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -10,6 +10,17 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable { + public abstract class PalpableCatchHitObject : DrawableCatchHitObject + where TObject : CatchHitObject + { + protected PalpableCatchHitObject(TObject hitObject) + : base(hitObject) + { + Scale = new Vector2(HitObject.Scale); + } + } + + public abstract class DrawableCatchHitObject : DrawableCatchHitObject where TObject : CatchHitObject { @@ -19,9 +30,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable : base(hitObject) { HitObject = hitObject; - - Scale = new Vector2(HitObject.Scale); - Anchor = Anchor.BottomLeft; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 289323c1b5..c2b0552ab3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -8,7 +8,7 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableDroplet : DrawableCatchHitObject + public class DrawableDroplet : PalpableCatchHitObject { public DrawableDroplet(Droplet h) : base(h) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index c2c59468e9..ae20abf0d9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -14,7 +14,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableFruit : DrawableCatchHitObject + public class DrawableFruit : PalpableCatchHitObject { private Circle border; From 712d586d4159e1271d7b57129c4a6564637cb965 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 11 Jan 2018 13:40:46 +0900 Subject: [PATCH 093/133] Revert "Add OSD + config value for scroll speed" This reverts commit a6d8b28221910993005d6adbbcc5b0447b5a1511. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 5 +---- osu.Game/Configuration/OsuConfigManager.cs | 4 +--- osu.Game/Overlays/OnScreenDisplay.cs | 6 +----- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 7 ++----- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 532be2759f..919518dbe8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -15,7 +15,6 @@ using osu.Framework.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; -using osu.Game.Configuration; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.UI.Scrolling; @@ -162,10 +161,8 @@ namespace osu.Game.Rulesets.Mania.UI } [BackgroundDependencyLoader] - private void load(OsuColour colours, OsuConfigManager config) + private void load(OsuColour colours) { - config.BindWith(OsuSetting.UserScrollSpeed, VisibleTimeRange); - normalColumnColours = new List { colours.RedDark, diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 26879782fc..13213a54a1 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -73,7 +73,6 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); - Set(OsuSetting.UserScrollSpeed, 1500.0, 50.0, 10000.0); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -120,7 +119,6 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm, - UserScrollSpeed + ScrollingAlgorithm } } diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 4f3f03c749..6a1bd8e182 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -14,7 +14,6 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Configuration; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays @@ -116,7 +115,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(FrameworkConfigManager frameworkConfig, OsuConfigManager osuConfig) + private void load(FrameworkConfigManager frameworkConfig) { trackSetting(frameworkConfig.GetBindable(FrameworkSetting.FrameSync), v => display(v, "Frame Limiter", v.GetDescription(), "Ctrl+F7")); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.AudioDevice), v => display(v, "Audio Device", string.IsNullOrEmpty(v) ? "Default" : v, v)); @@ -136,9 +135,6 @@ namespace osu.Game.Overlays }); trackSetting(frameworkConfig.GetBindable(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter")); - - // Todo: This should be part of the ruleset-specific OSD - trackSetting(osuConfig.GetBindable(OsuSetting.UserScrollSpeed), v => display(v, "Scroll Speed", $"{v:N0}ms", "Ctrl+(+/-) to change")); } private readonly List references = new List(); diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index fa04b7f137..11185015b8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -103,15 +102,13 @@ namespace osu.Game.Rulesets.UI.Scrolling if (state.Keyboard.ControlPressed) { - var lastValue = Transforms.OfType().LastOrDefault()?.EndValue ?? VisibleTimeRange.Value; - switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(lastValue + time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(lastValue - time_span_step, 200, Easing.OutQuint); + transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); break; } } From 4b2d971b005bf6e82d84d4969b248bbf55ef32b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 13:03:47 +0900 Subject: [PATCH 094/133] Add some comments --- .../Algorithms/IScrollingAlgorithm.cs | 18 ++++++++++++++++++ .../Scrolling/ScrollingHitObjectContainer.cs | 10 +++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs index f9863bd299..d9e4ab228f 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs @@ -9,7 +9,25 @@ namespace osu.Game.Rulesets.UI.Scrolling.Algorithms { public interface IScrollingAlgorithm { + /// + /// Computes the states of s that are constant, such as lifetime and spatial length. + /// This is invoked once whenever or changes. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length); + + /// + /// Computes the states of s that change depending on , such as position. + /// This is invoked once per frame. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The current time. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index dfa6a40db4..960fd94762 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -15,12 +15,18 @@ namespace osu.Game.Rulesets.UI.Scrolling { public class ScrollingHitObjectContainer : HitObjectContainer { + /// + /// The duration required to scroll through one length of the before any control point adjustments. + /// public readonly BindableDouble TimeRange = new BindableDouble { MinValue = 0, MaxValue = double.MaxValue }; + /// + /// The control points that adjust the scrolling speed. + /// protected readonly SortedList ControlPoints = new SortedList(); private readonly ScrollingDirection direction; @@ -104,9 +110,7 @@ namespace osu.Game.Rulesets.UI.Scrolling { base.UpdateAfterChildrenLife(); - // We need to calculate this as soon as possible after lifetimes so that hitobjects - // get the final say in their positions - + // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } } From 1985e5bdb23a887d7a1cc8d392f1380971843061 Mon Sep 17 00:00:00 2001 From: james58899 Date: Fri, 12 Jan 2018 12:21:37 +0800 Subject: [PATCH 095/133] fix background dim --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- osu.Game/Screens/Play/Player.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 1ce84289b2..032950db4a 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; } - public TransformSequence BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) + public void BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) => background?.BlurTo(blurTarget = sigma, duration, easing); public override bool Equals(BackgroundScreen other) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c24b5e0d2a..fc8b0f2c88 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -394,9 +394,8 @@ namespace osu.Game.Screens.Play .FadeColour(OsuColour.Gray(opacity), duration, Easing.OutQuint) .FadeTo(storyboardVisible && opacity > 0 ? 1 : 0, duration, Easing.OutQuint); - (Background as BackgroundScreenBeatmap)? - .BlurTo(new Vector2((float)blurLevel.Value * 25), duration, Easing.OutQuint)? - .FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, duration, Easing.OutQuint); + (Background as BackgroundScreenBeatmap)?.BlurTo(new Vector2((float)blurLevel.Value * 25), duration, Easing.OutQuint); + Background?.FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, duration, Easing.OutQuint); } private void fadeOut() From 61c8fd4ab94a24ea6fda301aeb92e9a18eaa7e90 Mon Sep 17 00:00:00 2001 From: james58899 Date: Fri, 12 Jan 2018 12:39:32 +0800 Subject: [PATCH 096/133] useless using --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 032950db4a..f7042991ac 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Transforms; using OpenTK; using osu.Game.Beatmaps; using osu.Game.Graphics.Backgrounds; From 057efa24c729f570b7205cacda1f72f974b53f48 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 14:26:09 +0900 Subject: [PATCH 097/133] Move a few interfaces to base classes --- osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs | 2 +- osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index e6711923ff..aafebb61ec 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Mods { - public abstract class ManiaKeyMod : Mod, IApplicableMod, IApplicableToBeatmapConverter + public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter { public override string ShortenedName => Name; public abstract int KeyCount { get; } diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs index 6b02a902e0..d89d6f20d8 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Mods /// Interface for a that applies changes to a . /// /// The type of converted . - public interface IApplicableToBeatmapConverter + public interface IApplicableToBeatmapConverter : IApplicableMod where TObject : HitObject { /// From 9a77005d2e443aff2b5c3edf2b94841f6bc713b6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 14:26:23 +0900 Subject: [PATCH 098/133] Make sure unimplemented auto mods aren't consumable --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 3 ++- osu.Game/Rulesets/Mods/ModAutoplay.cs | 17 +++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 37525470c2..0d52046485 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -10,6 +10,7 @@ using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch { @@ -80,7 +81,7 @@ namespace osu.Game.Rulesets.Catch { Mods = new Mod[] { - new ModAutoplay(), + new ModAutoplay(), new ModCinema(), }, }, diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index e8f5bb4740..a0752acb1a 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -5,23 +5,25 @@ using System; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods { - public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer + public class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer, IApplicableFailOverride where T : HitObject { - protected abstract Score CreateReplayScore(Beatmap beatmap); + protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; - public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) - { - rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); - } + public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; + + public bool AllowFail => false; + + public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) => rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); } - public class ModAutoplay : Mod, IApplicableFailOverride + public abstract class ModAutoplay : Mod { public override string Name => "Autoplay"; public override string ShortenedName => "AT"; @@ -29,6 +31,5 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Watch a perfect automated play through the song"; public override double ScoreMultiplier => 0; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; - public bool AllowFail => false; } } From f83c84a0a6139e8789b32d4c65767b94f4d9680f Mon Sep 17 00:00:00 2001 From: james58899 Date: Fri, 12 Jan 2018 14:24:42 +0800 Subject: [PATCH 099/133] keep BlurTo --- osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index f7042991ac..1ce84289b2 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Transforms; using OpenTK; using osu.Game.Beatmaps; using osu.Game.Graphics.Backgrounds; @@ -53,7 +54,7 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; } - public void BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) + public TransformSequence BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) => background?.BlurTo(blurTarget = sigma, duration, easing); public override bool Equals(BackgroundScreen other) From 03824eccc8f658a50551e1f592520a45aa77447c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:09:21 +0900 Subject: [PATCH 100/133] Block fadeout on holdnote heads --- .../Objects/Drawables/DrawableHoldNote.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 6748bc22e6..76fc0dcf77 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -186,6 +186,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } + + protected override void UpdateState(ArmedState state) + { + // The holdnote keeps scrolling through for now, so having the head disappear looks weird + } } /// From cae93a1d1f7a6d31ebc181c97766e341d3023322 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:09:34 +0900 Subject: [PATCH 101/133] Add comment to fade override of holdnote tail --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 76fc0dcf77..58f024870d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -238,6 +238,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void UpdateState(ArmedState state) { + // The holdnote keeps scrolling through, so having the tail disappear looks weird } public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down From 441e8aced51376ac99d153423a20de42b1a6e55e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:18:34 +0900 Subject: [PATCH 102/133] Better namings for the speed change "algorithms" --- osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- ...pe.cs => SpeedChangeVisualisationMethod.cs} | 10 +++++----- .../Sections/Gameplay/ScrollingSettings.cs | 6 +++--- .../Scrolling/ScrollingHitObjectContainer.cs | 18 +++++++++--------- .../ISpeedChangeVisualiser.cs} | 4 ++-- .../OverlappingSpeedChangeVisualiser.cs} | 6 +++--- .../SequentialSpeedChangeVisualiser.cs} | 6 +++--- osu.Game/osu.Game.csproj | 8 ++++---- 8 files changed, 31 insertions(+), 31 deletions(-) rename osu.Game/Configuration/{ScrollingAlgorithmType.cs => SpeedChangeVisualisationMethod.cs} (57%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/IScrollingAlgorithm.cs => Visualisers/ISpeedChangeVisualiser.cs} (93%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/LocalScrollingAlgorithm.cs => Visualisers/OverlappingSpeedChangeVisualiser.cs} (90%) rename osu.Game/Rulesets/UI/Scrolling/{Algorithms/GlobalScrollingAlgorithm.cs => Visualisers/SequentialSpeedChangeVisualiser.cs} (92%) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 13213a54a1..23f7fd6ac1 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -72,7 +72,7 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); - Set(OsuSetting.ScrollingAlgorithm, ScrollingAlgorithmType.Global); + Set(OsuSetting.SpeedChangeVisualisation, SpeedChangeVisualisationMethod.Sequential); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -119,6 +119,6 @@ namespace osu.Game.Configuration ChatDisplayHeight, Version, ShowConvertedBeatmaps, - ScrollingAlgorithm + SpeedChangeVisualisation } } diff --git a/osu.Game/Configuration/ScrollingAlgorithmType.cs b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs similarity index 57% rename from osu.Game/Configuration/ScrollingAlgorithmType.cs rename to osu.Game/Configuration/SpeedChangeVisualisationMethod.cs index 8b9d292634..644ae0a727 100644 --- a/osu.Game/Configuration/ScrollingAlgorithmType.cs +++ b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs @@ -5,11 +5,11 @@ using System.ComponentModel; namespace osu.Game.Configuration { - public enum ScrollingAlgorithmType + public enum SpeedChangeVisualisationMethod { - [Description("Global")] - Global, - [Description("Local")] - Local + [Description("Sequential")] + Sequential, + [Description("Overlapping")] + Overlapping } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs index 3243f4c23a..4e8706137c 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -15,10 +15,10 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay { Children = new[] { - new SettingsEnumDropdown + new SettingsEnumDropdown { - LabelText = "Scrolling algorithm", - Bindable = config.GetBindable(OsuSetting.ScrollingAlgorithm), + LabelText = "Visualise speed changes as", + Bindable = config.GetBindable(OsuSetting.SpeedChangeVisualisation), } }; } diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 960fd94762..e69abec45e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -9,7 +9,7 @@ using osu.Framework.Lists; using osu.Game.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.UI.Scrolling.Algorithms; +using osu.Game.Rulesets.UI.Scrolling.Visualisers; namespace osu.Game.Rulesets.UI.Scrolling { @@ -42,18 +42,18 @@ namespace osu.Game.Rulesets.UI.Scrolling TimeRange.ValueChanged += v => initialStateCache.Invalidate(); } - private IScrollingAlgorithm scrollingAlgorithm; + private ISpeedChangeVisualiser speedChangeVisualiser; [BackgroundDependencyLoader] private void load(OsuConfigManager config) { - switch (config.Get(OsuSetting.ScrollingAlgorithm)) + switch (config.Get(OsuSetting.SpeedChangeVisualisation)) { - case ScrollingAlgorithmType.Global: - scrollingAlgorithm = new GlobalScrollingAlgorithm(ControlPoints); + case SpeedChangeVisualisationMethod.Sequential: + speedChangeVisualiser = new SequentialSpeedChangeVisualiser(ControlPoints); break; - case ScrollingAlgorithmType.Local: - scrollingAlgorithm = new LocalScrollingAlgorithm(ControlPoints); + case SpeedChangeVisualisationMethod.Overlapping: + speedChangeVisualiser = new OverlappingSpeedChangeVisualiser(ControlPoints); break; } } @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (initialStateCache.IsValid) return; - scrollingAlgorithm.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); initialStateCache.Validate(); } @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.UI.Scrolling base.UpdateAfterChildrenLife(); // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions - scrollingAlgorithm.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); + speedChangeVisualiser.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); } } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs similarity index 93% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs index d9e4ab228f..46d71e1602 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/IScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public interface IScrollingAlgorithm + public interface ISpeedChangeVisualiser { /// /// Computes the states of s that are constant, such as lifetime and spatial length. diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs similarity index 90% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs index 96a85c5f9f..24f69c627d 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/LocalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs @@ -7,15 +7,15 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Timing; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public class LocalScrollingAlgorithm : IScrollingAlgorithm + public class OverlappingSpeedChangeVisualiser : ISpeedChangeVisualiser { private readonly Dictionary hitObjectPositions = new Dictionary(); private readonly SortedList controlPoints; - public LocalScrollingAlgorithm(SortedList controlPoints) + public OverlappingSpeedChangeVisualiser(SortedList controlPoints) { this.controlPoints = controlPoints; } diff --git a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs similarity index 92% rename from osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs rename to osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs index ed156ecfd5..94705426f8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Algorithms/GlobalScrollingAlgorithm.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs @@ -8,15 +8,15 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; using OpenTK; -namespace osu.Game.Rulesets.UI.Scrolling.Algorithms +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { - public class GlobalScrollingAlgorithm : IScrollingAlgorithm + public class SequentialSpeedChangeVisualiser : ISpeedChangeVisualiser { private readonly Dictionary hitObjectPositions = new Dictionary(); private readonly IReadOnlyList controlPoints; - public GlobalScrollingAlgorithm(IReadOnlyList controlPoints) + public SequentialSpeedChangeVisualiser(IReadOnlyList controlPoints) { this.controlPoints = controlPoints; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 45183de092..01052a7898 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -265,7 +265,7 @@ - + @@ -318,9 +318,9 @@ - - - + + + From 8a04c954a90198a6c2e4b3369160a9fcd84c8dea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 17:19:59 +0900 Subject: [PATCH 103/133] Cleanup --- .../UI/Scrolling/ScrollingHitObjectContainer.cs | 11 +++++------ .../Visualisers/OverlappingSpeedChangeVisualiser.cs | 2 -- osu.Game/osu.Game.csproj | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e69abec45e..530ed653aa 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -98,12 +98,11 @@ namespace osu.Game.Rulesets.UI.Scrolling { base.Update(); - if (initialStateCache.IsValid) - return; - - speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); - - initialStateCache.Validate(); + if (!initialStateCache.IsValid) + { + speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + initialStateCache.Validate(); + } } protected override void UpdateAfterChildrenLife() diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs index 24f69c627d..4cce90ee94 100644 --- a/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.UI.Scrolling.Visualisers { public class OverlappingSpeedChangeVisualiser : ISpeedChangeVisualiser { - private readonly Dictionary hitObjectPositions = new Dictionary(); - private readonly SortedList controlPoints; public OverlappingSpeedChangeVisualiser(SortedList controlPoints) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 01052a7898..967f3fc1d7 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -318,9 +318,9 @@ - - - + + + From 0a06f8069f5d6515bd7209645bff54cf85374bf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 17:22:51 +0900 Subject: [PATCH 104/133] Remove panel fade out for now Should be implemented at one level above using a dedicated container. --- osu.Game/Overlays/SocialOverlay.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 161ff70dc9..e61153d290 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -137,16 +137,6 @@ namespace osu.Game.Overlays }); } - private void clearPanels() - { - if (panels != null) - { - panels.FadeOut(200); - panels.Expire(); - panels = null; - } - } - private APIRequest getUsersRequest; private readonly Bindable currentQuery = new Bindable(); @@ -191,6 +181,15 @@ namespace osu.Game.Overlays recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } + private void clearPanels() + { + if (panels != null) + { + panels.Expire(); + panels = null; + } + } + public void APIStateChanged(APIAccess api, APIState state) { switch (state) From 7f189080b91a0d8d7a082b28b023eb939c86b023 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 17:43:56 +0900 Subject: [PATCH 105/133] Move fail override back to abstract implementation --- osu.Game/Rulesets/Mods/ModAutoplay.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index a0752acb1a..3356a56c33 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -11,25 +11,24 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods { - public class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer, IApplicableFailOverride + public class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer where T : HitObject { protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; - public bool AllowFail => false; - public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) => rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); } - public abstract class ModAutoplay : Mod + public abstract class ModAutoplay : Mod, IApplicableFailOverride { public override string Name => "Autoplay"; public override string ShortenedName => "AT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override string Description => "Watch a perfect automated play through the song"; public override double ScoreMultiplier => 0; + public bool AllowFail => false; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; } } From b55adf655f9334ad292363465b33e49d2737e144 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 17:46:24 +0900 Subject: [PATCH 106/133] Yeah, cinema mod isn't going to work --- osu.Game/Rulesets/Mods/ModCinema.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 576d29fdfb..c0480b0647 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => "Cinema"; public override string ShortenedName => "CN"; + public override bool HasImplementation => false; public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; } } From e5056e11f416fcaabdbc60d5e6bd3463c861794c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:07:40 +0900 Subject: [PATCH 107/133] Remove extra newline --- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 0a1a6c7960..2d1331d30a 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -78,7 +78,6 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450); TimeFadein = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1200, 800, 300); - Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; } } From 2bf2cc15d41863014a81d46109425e0fcce23efd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:09:37 +0900 Subject: [PATCH 108/133] Fix unnecessary osu-resources rollback --- osu-resources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-resources b/osu-resources index e01f71160f..7724abdf1d 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 +Subproject commit 7724abdf1d7c9705ba2e3989a9c604e17ccdc871 From 8ed24e1bca2e750b16cdb0acfeffe9b7eddccbc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:15:53 +0900 Subject: [PATCH 109/133] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 6594729122..a6090d3f6f 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 65947291229541de3eb1aff0e703f6968b07f976 +Subproject commit a6090d3f6f03eaf9a3f643cf1ef3db96384c62ff From ff725f0e32f8acd3c5ac9100d8e21d8d6a5c9082 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:17:32 +0900 Subject: [PATCH 110/133] Fix incorrect online conditional check in social browser logic --- osu.Game/Overlays/SocialOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index e61153d290..ddcb933e5d 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -155,7 +155,7 @@ namespace osu.Game.Overlays loading.Hide(); getUsersRequest?.Cancel(); - if (api?.IsLoggedIn == false) + if (api?.IsLoggedIn != true) return; switch (Header.Tabs.Current.Value) From 1c3c90bac6886e2757bba11b1c458d2b4aad92f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Jan 2018 18:32:16 +0900 Subject: [PATCH 111/133] Add banana design (cherry picked from commit 6961ca2) --- .../Objects/Drawable/DrawableFruit.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index ae20abf0d9..93a1483f6f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -243,6 +243,27 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }, } }; + case FruitVisualRepresentation.Banana: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + Y = -0.15f + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3), + }, + } + }; } } From a36cfd426532ed148cbcd0088f8babf89d6ea49e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jan 2018 14:52:22 +0900 Subject: [PATCH 112/133] Add BananaShower models and representations (cherry picked from commit e12e095) --- .../Objects/BananaShower.cs | 61 +++++++++++++++++++ .../Objects/Drawable/DrawableBananaShower.cs | 40 ++++++++++++ .../Tests/TestCaseBananaShower.cs | 38 ++++++++++++ .../UI/CatchRulesetContainer.cs | 16 ++--- .../osu.Game.Rulesets.Catch.csproj | 3 + 5 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/BananaShower.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs create mode 100644 osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs new file mode 100644 index 0000000000..cb0f4eab96 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Objects.Types; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects +{ + public class BananaShower : CatchHitObject, IHasEndTime + { + public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + + protected override void CreateNestedHitObjects() + { + base.CreateNestedHitObjects(); + createBananas(); + } + + private void createBananas() + { + double spacing = Duration; + while (spacing > 100) + spacing /= 2; + + if (spacing <= 0) + return; + + for (double i = StartTime; i <= EndTime; i += spacing) + AddNested(new Banana + { + Samples = Samples, + ComboColour = getNextComboColour(), + StartTime = i, + X = RNG.NextSingle() + }); + } + + private Color4 getNextComboColour() + { + switch (RNG.Next(0, 3)) + { + default: + return new Color4(255, 240, 0, 255); + case 1: + return new Color4(255, 192, 0, 255); + case 2: + return new Color4(214, 221, 28, 255); + } + } + + public double EndTime => StartTime + Duration; + + public double Duration { get; set; } + + public class Banana : Fruit + { + public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs new file mode 100644 index 0000000000..ff787d80e9 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using OpenTK; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Catch.Objects.Drawable +{ + public class DrawableBananaShower : DrawableCatchHitObject + { + private readonly Container dropletContainer; + + public DrawableBananaShower(BananaShower s) : base(s) + { + RelativeSizeAxes = Axes.Both; + Height = (float)HitObject.Duration; + X = 0; + + Child = dropletContainer = new Container + { + RelativeSizeAxes = Axes.Both, + RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), + RelativeChildSize = new Vector2(1, (float)HitObject.Duration) + }; + + foreach (var b in s.NestedHitObjects.OfType()) + AddNested(new DrawableFruit(b)); + } + + protected override void AddNested(DrawableHitObject h) + { + ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + dropletContainer.Add(h); + base.AddNested(h); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs new file mode 100644 index 0000000000..4499905560 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + [Ignore("getting CI working")] + public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer + { + public TestCaseBananaShower() + : base(typeof(CatchRuleset)) + { + } + + protected override Beatmap CreateBeatmap() + { + var beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 6, + } + } + }; + + for (int i = 0; i < 10; i++) + beatmap.HitObjects.Add(new BananaShower { StartTime = i * 1200, Duration = 1000, NewCombo = i % 2 == 0 }); + + return beatmap; + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index a146014ca4..076487a5e2 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -33,13 +33,15 @@ namespace osu.Game.Rulesets.Catch.UI protected override DrawableHitObject GetVisualRepresentation(CatchHitObject h) { - var fruit = h as Fruit; - if (fruit != null) - return new DrawableFruit(fruit); - - var stream = h as JuiceStream; - if (stream != null) - return new DrawableJuiceStream(stream); + switch (h) + { + case Fruit fruit: + return new DrawableFruit(fruit); + case JuiceStream stream: + return new DrawableJuiceStream(stream); + case BananaShower banana: + return new DrawableBananaShower(banana); + } return null; } diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 566ec385fc..50fbc8b6a2 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -60,6 +60,8 @@ + + @@ -73,6 +75,7 @@ + From 5c79bdc41c613ac3c9db32004abfe092f4e8e655 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jan 2018 15:37:55 +0900 Subject: [PATCH 113/133] Use switch pattern matching in more places Also switch access to many classes to public. (cherry picked from commit 86cc3b7) --- .../Beatmaps/CatchBeatmapProcessor.cs | 2 +- .../Objects/Drawable/DrawableJuiceStream.cs | 28 ++++++++--------- .../Scoring/CatchScoreProcessor.cs | 30 ++++++++++--------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index f601ce624d..d3012b1981 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -12,7 +12,7 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Beatmaps { - internal class CatchBeatmapProcessor : BeatmapProcessor + public class CatchBeatmapProcessor : BeatmapProcessor { public override void PostProcess(Beatmap beatmap) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 036c5bd879..2955b51044 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; @@ -13,7 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private readonly Container dropletContainer; - public DrawableJuiceStream(JuiceStream s) : base(s) + public DrawableJuiceStream(JuiceStream s) + : base(s) { RelativeSizeAxes = Axes.Both; Origin = Anchor.BottomLeft; @@ -21,22 +21,20 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; - foreach (CatchHitObject tick in s.NestedHitObjects.OfType()) + foreach (var tick in s.NestedHitObjects) { - TinyDroplet tiny = tick as TinyDroplet; - if (tiny != null) + switch (tick) { - AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }); - continue; + case TinyDroplet tiny: + AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }); + break; + case Droplet droplet: + AddNested(new DrawableDroplet(droplet)); + break; + case Fruit fruit: + AddNested(new DrawableFruit(fruit)); + break; } - - Droplet droplet = tick as Droplet; - if (droplet != null) - AddNested(new DrawableDroplet(droplet)); - - Fruit fruit = tick as Fruit; - if (fruit != null) - AddNested(new DrawableFruit(fruit)); } } diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index a6dc1350be..6df9498881 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.Scoring { - internal class CatchScoreProcessor : ScoreProcessor + public class CatchScoreProcessor : ScoreProcessor { public CatchScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) @@ -21,23 +21,25 @@ namespace osu.Game.Rulesets.Catch.Scoring { foreach (var obj in beatmap.HitObjects) { - var stream = obj as JuiceStream; - - if (stream != null) + switch (obj) { - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - - foreach (var unused in stream.NestedHitObjects.OfType()) + case JuiceStream stream: + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - continue; + foreach (var _ in stream.NestedHitObjects.Cast()) + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + break; + case BananaShower shower: + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + + foreach (var _ in shower.NestedHitObjects.Cast()) + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + break; + case Fruit _: + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + break; } - - var fruit = obj as Fruit; - - if (fruit != null) - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); } base.SimulateAutoplay(beatmap); From 5b150730107888fd4e39f881a3a05d7fe3c1fb24 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jan 2018 15:38:12 +0900 Subject: [PATCH 114/133] Add actual banana conversion/reading (cherry picked from commit d353158) --- .../Beatmaps/CatchBeatmapConverter.cs | 16 +++++++++++++++- .../Objects/Drawable/DrawableBananaShower.cs | 8 ++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index dadb852654..01aa7abb9f 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Beatmaps { - internal class CatchBeatmapConverter : BeatmapConverter + public class CatchBeatmapConverter : BeatmapConverter { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps var curveData = obj as IHasCurve; var positionData = obj as IHasXPosition; var comboData = obj as IHasCombo; + var endTime = obj as IHasEndTime; if (positionData == null) yield break; @@ -42,6 +43,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps yield break; } + if (endTime != null) + { + yield return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false + }; + + yield break; + } + yield return new Fruit { StartTime = obj.StartTime, diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index ff787d80e9..0bbf12bfcc 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableBananaShower : DrawableCatchHitObject { - private readonly Container dropletContainer; + private readonly Container bananaContainer; public DrawableBananaShower(BananaShower s) : base(s) { @@ -19,21 +19,21 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Height = (float)HitObject.Duration; X = 0; - Child = dropletContainer = new Container + Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both, RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), RelativeChildSize = new Vector2(1, (float)HitObject.Duration) }; - foreach (var b in s.NestedHitObjects.OfType()) + foreach (var b in s.NestedHitObjects.Cast()) AddNested(new DrawableFruit(b)); } protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; - dropletContainer.Add(h); + bananaContainer.Add(h); base.AddNested(h); } } From 26fedd7e61cac1145b92e3e32c6016c30b8f5d23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jan 2018 16:58:20 +0900 Subject: [PATCH 115/133] Update in line with upstream changes (cherry picked from commit 2b6d991) --- .../Objects/Drawable/DrawableBananaShower.cs | 7 ++++--- .../Tests/TestCaseBananaShower.cs | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 0bbf12bfcc..b38880a8c3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -13,13 +13,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private readonly Container bananaContainer; - public DrawableBananaShower(BananaShower s) : base(s) + public DrawableBananaShower(BananaShower s) + : base(s) { RelativeSizeAxes = Axes.Both; Height = (float)HitObject.Duration; X = 0; - Child = bananaContainer = new Container + Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both, RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), @@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable }; foreach (var b in s.NestedHitObjects.Cast()) - AddNested(new DrawableFruit(b)); + AddNested(new DrawableFruit(b)); } protected override void AddNested(DrawableHitObject h) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs index 4499905560..aae36beb57 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -1,9 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.UI; namespace osu.Game.Rulesets.Catch.Tests { @@ -11,8 +15,17 @@ namespace osu.Game.Rulesets.Catch.Tests [Ignore("getting CI working")] public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BananaShower), + typeof(DrawableBananaShower), + + typeof(CatchRuleset), + typeof(CatchRulesetContainer), + }; + public TestCaseBananaShower() - : base(typeof(CatchRuleset)) + : base(new CatchRuleset()) { } From 3b929ffd21035432d09ea8dc029150bc4194e54e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 10 Jan 2018 19:18:03 +0900 Subject: [PATCH 116/133] Make test more useful (cherry picked from commit 5985115) --- osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs index aae36beb57..4f183c3ebc 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -42,8 +42,7 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - for (int i = 0; i < 10; i++) - beatmap.HitObjects.Add(new BananaShower { StartTime = i * 1200, Duration = 1000, NewCombo = i % 2 == 0 }); + beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 10000, NewCombo = true }); return beatmap; } From 9e3091bfe9c78c466b3044316c408340596f0537 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 11 Jan 2018 13:41:50 +0900 Subject: [PATCH 117/133] Change anchors in line with new ScrollingPlayfield implementation (cherry picked from commit 079827d) --- .../Objects/Drawable/DrawableBananaShower.cs | 14 ++++---------- .../Tests/TestCaseBananaShower.cs | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index b38880a8c3..b5d9163a50 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -4,7 +4,6 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using OpenTK; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable @@ -16,22 +15,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public DrawableBananaShower(BananaShower s) : base(s) { - RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + RelativeSizeAxes = Axes.X; + Origin = Anchor.BottomLeft; X = 0; - Child = bananaContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }; + Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; foreach (var b in s.NestedHitObjects.Cast()) AddNested(new DrawableFruit(b)); } - protected override void AddNested(DrawableHitObject h) + protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; bananaContainer.Add(h); diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs index 4f183c3ebc..6bf5b6beca 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 10000, NewCombo = true }); + beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 500, NewCombo = true }); return beatmap; } From 33fdc2c1d6210898150726457adfe62e48509937 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:35:28 +0900 Subject: [PATCH 118/133] Add very basic replay handling --- osu.Game.Rulesets.Catch/CatchInputManager.cs | 3 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 2 +- .../Mods/CatchModAutoplay.cs | 24 +++++++++ .../Replays/CatchAutoGenerator.cs | 54 +++++++++++++++++++ .../Replays/CatchFramedReplayInputHandler.cs | 32 +++++++++++ .../Replays/CatchReplayFrame.cs | 17 ++++++ .../UI/CatchRulesetContainer.cs | 4 ++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 17 +++++- .../osu.Game.Rulesets.Catch.csproj | 4 ++ 9 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs create mode 100644 osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs create mode 100644 osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs create mode 100644 osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index d1851d31bf..f57952f95e 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Catch [Description("Move right")] MoveRight, [Description("Engage dash")] - Dash + Dash, + PositionUpdate } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 0d52046485..08bc94863b 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Catch { Mods = new Mod[] { - new ModAutoplay(), + new CatchModAutoplay(), new ModCinema(), }, }, diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs new file mode 100644 index 0000000000..8ff08ab825 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModAutoplay : ModAutoplay + { + protected override Score CreateReplayScore(Beatmap beatmap) + { + return new Score + { + User = new User { Username = "osu!salad!" }, + Replay = new CatchAutoGenerator(beatmap).Generate(), + }; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs new file mode 100644 index 0000000000..bc53e6e869 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Replays; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Catch.Replays +{ + internal class CatchAutoGenerator : AutoGenerator + { + public const double RELEASE_DELAY = 20; + + public CatchAutoGenerator(Beatmap beatmap) + : base(beatmap) + { + Replay = new Replay { User = new User { Username = @"Autoplay" } }; + } + + protected Replay Replay; + + public override Replay Generate() + { + // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled + Replay.Frames.Add(new CatchReplayFrame(-100000, 0)); + + foreach (var obj in Beatmap.HitObjects) + { + switch (obj) + { + case Fruit _: + Replay.Frames.Add(new CatchReplayFrame(obj.StartTime, obj.X)); + break; + } + + foreach (var nestedObj in obj.NestedHitObjects.Cast()) + { + switch (nestedObj) + { + case BananaShower.Banana _: + case TinyDroplet _: + case Droplet _: + Replay.Frames.Add(new CatchReplayFrame(nestedObj.StartTime, nestedObj.X)); + break; + } + } + } + + return Replay; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs new file mode 100644 index 0000000000..146e31fa69 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Input; +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Catch.Replays +{ + public class CatchFramedReplayInputHandler : FramedReplayInputHandler + { + public CatchFramedReplayInputHandler(Replay replay) + : base(replay) + { + } + + public override List GetPendingStates() => new List + { + new CatchReplayState + { + PressedActions = new List { CatchAction.PositionUpdate }, + CatcherX = ((CatchReplayFrame)CurrentFrame).MouseX + }, + new CatchReplayState { PressedActions = new List() }, + }; + + public class CatchReplayState : ReplayState + { + public float? CatcherX { get; set; } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs new file mode 100644 index 0000000000..c47f60ec3c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Catch.Replays +{ + public class CatchReplayFrame : ReplayFrame + { + public override bool IsImportant => MouseX > 0; + + public CatchReplayFrame(double time, float? x = null) + : base(time, x ?? -1, null, ReplayButtonState.None) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index a146014ca4..08808a445e 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -6,8 +6,10 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -23,6 +25,8 @@ namespace osu.Game.Rulesets.Catch.UI public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); + protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); + protected override BeatmapProcessor CreateBeatmapProcessor() => new CatchBeatmapProcessor(); protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index c70cb15b40..1837086d9c 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -13,6 +13,7 @@ using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; @@ -21,7 +22,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.UI { - public class CatcherArea : Container + public class CatcherArea : Container, IKeyBindingHandler { public const float CATCHER_SIZE = 172; @@ -72,6 +73,20 @@ namespace osu.Game.Rulesets.Catch.UI } } + public bool OnPressed(CatchAction action) + { + if (action != CatchAction.PositionUpdate) return false; + + CatchFramedReplayInputHandler.CatchReplayState state = (CatchFramedReplayInputHandler.CatchReplayState)GetContainingInputManager().CurrentState; + + if (state.CatcherX.HasValue) + MovableCatcher.X = state.CatcherX.Value; + + return true; + } + + public bool OnReleased(CatchAction action) => false; + public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj); public class Catcher : Container, IKeyBindingHandler diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 566ec385fc..4d17fa6570 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -60,11 +60,15 @@ + + + + From 98894f010fada7224403248726d90825ccf64844 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 18:57:53 +0900 Subject: [PATCH 119/133] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 80bcb82ef8..49b563e2cf 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 80bcb82ef8d2e1af1ce077f4a037b6d279ad9e74 +Subproject commit 49b563e2cf170eb19006b98dd5b69c2398362d9e From 7bdedf802c8881071a42c9083ae6396ea9a532a0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 19:18:49 +0900 Subject: [PATCH 120/133] Fix juice streams not propagating accent colours to nested objects --- .../Objects/Drawable/DrawableJuiceStream.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 036c5bd879..1c59b65663 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -42,7 +42,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void AddNested(DrawableHitObject h) { - ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + var catchObject = (DrawableCatchHitObject)h; + + catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + catchObject.AccentColour = HitObject.ComboColour; + dropletContainer.Add(h); base.AddNested(h); } From 90bcec42d7ef99a48676b0d171f41203b5b30857 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 12 Jan 2018 20:48:58 +0900 Subject: [PATCH 121/133] Remove unused using --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 08bc94863b..5e70239c7c 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Catch.Objects; namespace osu.Game.Rulesets.Catch { From 93c4d58b69d29c3a13b7bee1ab4737eb03b4ae3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 21:46:50 +0900 Subject: [PATCH 122/133] Make catch plate fruit again --- .../Objects/Drawable/DrawableBananaShower.cs | 5 ++-- .../Drawable/DrawableCatchHitObject.cs | 26 ++++++++++++---- .../Objects/Drawable/DrawableJuiceStream.cs | 22 ++++---------- .../Objects/JuiceStream.cs | 2 -- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 ++- .../UI/CatchRulesetContainer.cs | 11 +++++-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 30 ++++++++++--------- 7 files changed, 55 insertions(+), 45 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index b5d9163a50..72aeddee56 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private readonly Container bananaContainer; - public DrawableBananaShower(BananaShower s) + public DrawableBananaShower(BananaShower s, Func> getVisualRepresentation = null) : base(s) { RelativeSizeAxes = Axes.X; @@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; foreach (var b in s.NestedHitObjects.Cast()) - AddNested(new DrawableFruit(b)); + AddNested(getVisualRepresentation?.Invoke(b)); } protected override void AddNested(DrawableHitObject h) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 554fb1323e..8871e26101 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using OpenTK; using osu.Game.Rulesets.Scoring; @@ -13,6 +14,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public abstract class PalpableCatchHitObject : DrawableCatchHitObject where TObject : CatchHitObject { + public override bool CanBePlated => true; + protected PalpableCatchHitObject(TObject hitObject) : base(hitObject) { @@ -36,6 +39,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public abstract class DrawableCatchHitObject : DrawableHitObject { + public virtual bool CanBePlated => false; + protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { @@ -47,8 +52,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void CheckForJudgements(bool userTriggered, double timeOffset) { + if (CheckPosition == null) return; + if (timeOffset > 0) - AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss }); + AddJudgement(new Judgement { Result = (bool)CheckPosition?.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss }); } private const float preempt = 1000; @@ -61,12 +68,19 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable this.FadeIn(200); } - switch (state) + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + + using (BeginAbsoluteSequence(endTime, true)) { - case ArmedState.Miss: - using (BeginAbsoluteSequence(HitObject.StartTime, true)) - this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); - break; + switch (state) + { + case ArmedState.Miss: + this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire(); + break; + case ArmedState.Hit: + this.FadeOut().Expire(); + break; + } } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index e66999229c..c8b15aec61 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -1,9 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using OpenTK; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable @@ -12,7 +13,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private readonly Container dropletContainer; - public DrawableJuiceStream(JuiceStream s) + public DrawableJuiceStream(JuiceStream s, Func> getVisualRepresentation = null) : base(s) { RelativeSizeAxes = Axes.Both; @@ -21,21 +22,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; - foreach (var tick in s.NestedHitObjects) - { - switch (tick) - { - case TinyDroplet tiny: - AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }); - break; - case Droplet droplet: - AddNested(new DrawableDroplet(droplet)); - break; - case Fruit fruit: - AddNested(new DrawableFruit(fruit)); - break; - } - } + foreach (var o in s.NestedHitObjects.Cast()) + AddNested(getVisualRepresentation?.Invoke(o)); } protected override void AddNested(DrawableHitObject h) diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index b1c83f5964..188af58e6a 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -125,10 +125,8 @@ namespace osu.Game.Rulesets.Catch.Objects X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH }); } - } - public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity; public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH; diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 7fdabd46c2..8ea30a2899 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; @@ -21,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; - public CatchPlayfield(BeatmapDifficulty difficulty) + public CatchPlayfield(BeatmapDifficulty difficulty, Func> getVisualRepresentation) : base(ScrollingDirection.Down, BASE_WIDTH) { Container explodingFruitContainer; @@ -44,6 +45,7 @@ namespace osu.Game.Rulesets.Catch.UI }, catcherArea = new CatcherArea(difficulty) { + GetVisualRepresentation = getVisualRepresentation, ExplodingFruitTarget = explodingFruitContainer, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index ae0fe8189e..956a524121 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; namespace osu.Game.Rulesets.Catch.UI { @@ -31,7 +32,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); - protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty); + protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); @@ -42,9 +43,13 @@ namespace osu.Game.Rulesets.Catch.UI case Fruit fruit: return new DrawableFruit(fruit); case JuiceStream stream: - return new DrawableJuiceStream(stream); + return new DrawableJuiceStream(stream, GetVisualRepresentation); case BananaShower banana: - return new DrawableBananaShower(banana); + return new DrawableBananaShower(banana, GetVisualRepresentation); + case TinyDroplet tiny: + return new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }; + case Droplet droplet: + return new DrawableDroplet(droplet); } return null; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 1837086d9c..6d0c3589e8 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -16,7 +16,6 @@ using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; @@ -28,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.UI protected readonly Catcher MovableCatcher; + public Func> GetVisualRepresentation; + public Container ExplodingFruitTarget { set { MovableCatcher.ExplodingFruitTarget = value; } @@ -45,23 +46,24 @@ namespace osu.Game.Rulesets.Catch.UI public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement) { - if (judgement.IsHit) + if (judgement.IsHit && fruit.CanBePlated) { - var screenSpacePosition = fruit.ScreenSpaceDrawQuad.Centre; + var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); - // todo: make this less ugly, somehow. - (fruit.Parent as HitObjectContainer)?.Remove(fruit); - (fruit.Parent as Container)?.Remove(fruit); + if (caughtFruit != null) + { + caughtFruit.State.Value = ArmedState.Idle; + caughtFruit.AccentColour = fruit.AccentColour; + caughtFruit.RelativePositionAxes = Axes.None; + caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); - fruit.RelativePositionAxes = Axes.None; - fruit.Position = new Vector2(MovableCatcher.ToLocalSpace(screenSpacePosition).X - MovableCatcher.DrawSize.X / 2, 0); + caughtFruit.Anchor = Anchor.TopCentre; + caughtFruit.Origin = Anchor.Centre; + caughtFruit.Scale *= 0.7f; + caughtFruit.LifetimeEnd = double.MaxValue; + } - fruit.Anchor = Anchor.TopCentre; - fruit.Origin = Anchor.Centre; - fruit.Scale *= 0.7f; - fruit.LifetimeEnd = double.MaxValue; - - MovableCatcher.Add(fruit); + MovableCatcher.Add(caughtFruit); } if (fruit.HitObject.LastInCombo) From 20c6f84efab1fa9f851b5b31466844e9492d5c0b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 21:46:57 +0900 Subject: [PATCH 123/133] Fix banana test regression --- osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs index 6bf5b6beca..e23e7633ca 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.Tests } }; - beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 500, NewCombo = true }); + beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true }); return beatmap; } From f03b8206da2c2a3e7eaa045b8631c882c352785f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 21:47:52 +0900 Subject: [PATCH 124/133] Make banana showers always last in combo (explodey) --- osu.Game.Rulesets.Catch/Objects/BananaShower.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index cb0f4eab96..89bd73f8fb 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Catch.Objects { public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + public override bool LastInCombo => true; + protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); From 7b19353ed8653356a7db2b0f2de42f6a3e488c17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 22:07:21 +0900 Subject: [PATCH 125/133] Fix weird fruit not fading out --- .../Drawable/DrawableCatchHitObject.cs | 3 -- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 44 +++++++++++-------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 8871e26101..d3b714fc9b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -63,10 +63,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void UpdateState(ArmedState state) { using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) - { - // animation this.FadeIn(200); - } var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 6d0c3589e8..23b0ceeac1 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -44,35 +44,43 @@ namespace osu.Game.Rulesets.Catch.UI }; } + private DrawableCatchHitObject lastPlateableFruit; + public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement) { if (judgement.IsHit && fruit.CanBePlated) { var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); - if (caughtFruit != null) - { - caughtFruit.State.Value = ArmedState.Idle; - caughtFruit.AccentColour = fruit.AccentColour; - caughtFruit.RelativePositionAxes = Axes.None; - caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); + if (caughtFruit == null) return; - caughtFruit.Anchor = Anchor.TopCentre; - caughtFruit.Origin = Anchor.Centre; - caughtFruit.Scale *= 0.7f; - caughtFruit.LifetimeEnd = double.MaxValue; - } + caughtFruit.State.Value = ArmedState.Idle; + caughtFruit.AccentColour = fruit.AccentColour; + caughtFruit.RelativePositionAxes = Axes.None; + caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); + + caughtFruit.Anchor = Anchor.TopCentre; + caughtFruit.Origin = Anchor.Centre; + caughtFruit.Scale *= 0.7f; + caughtFruit.LifetimeEnd = double.MaxValue; MovableCatcher.Add(caughtFruit); + + lastPlateableFruit = caughtFruit; } - if (fruit.HitObject.LastInCombo) + // this is required to make this run after the last caught fruit runs UpdateState at least once. + // TODO: find a better alternative + lastPlateableFruit.OnLoadComplete = _ => { - if (judgement.IsHit) - MovableCatcher.Explode(); - else - MovableCatcher.Drop(); - } + if (fruit.HitObject.LastInCombo) + { + if (judgement.IsHit) + MovableCatcher.Explode(); + else + MovableCatcher.Drop(); + } + }; } public bool OnPressed(CatchAction action) @@ -211,7 +219,7 @@ namespace osu.Game.Rulesets.Catch.UI while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && - Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2))) + Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2))) { float diff = (ourRadius + theirRadius) / allowance; fruit.X += (RNG.NextSingle() - 0.5f) * 2 * diff; From 9e108548400353781971f24e8c4445e4a9539729 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 12 Jan 2018 22:30:21 +0900 Subject: [PATCH 126/133] Fix banannanananana showers not exploding enough --- .../Objects/Drawable/DrawableBananaShower.cs | 8 ++++++++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 16 +++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index 72aeddee56..7b0370ef88 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -5,7 +5,9 @@ using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -26,6 +28,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddNested(getVisualRepresentation?.Invoke(b)); } + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (timeOffset >= 0) + AddJudgement(new Judgement { Result = NestedHitObjects.Cast().Any(n => n.Judgements.Any(j => j.IsHit)) ? HitResult.Perfect : HitResult.Miss }); + } + protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 23b0ceeac1..2df43bdcd4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -69,18 +69,20 @@ namespace osu.Game.Rulesets.Catch.UI lastPlateableFruit = caughtFruit; } - // this is required to make this run after the last caught fruit runs UpdateState at least once. - // TODO: find a better alternative - lastPlateableFruit.OnLoadComplete = _ => + if (fruit.HitObject.LastInCombo) { - if (fruit.HitObject.LastInCombo) + if (judgement.IsHit) { - if (judgement.IsHit) + // this is required to make this run after the last caught fruit runs UpdateState at least once. + // TODO: find a better alternative + if (lastPlateableFruit.IsLoaded) MovableCatcher.Explode(); else - MovableCatcher.Drop(); + lastPlateableFruit.OnLoadComplete = _ => { MovableCatcher.Explode(); }; } - }; + else + MovableCatcher.Drop(); + } } public bool OnPressed(CatchAction action) From b4b15b7dd0893b9e4ecbcece91c26a1a0d2f1c59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 13 Jan 2018 00:51:20 +0900 Subject: [PATCH 127/133] Apply review fixes --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index d3b714fc9b..fce43137d1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable if (CheckPosition == null) return; if (timeOffset > 0) - AddJudgement(new Judgement { Result = (bool)CheckPosition?.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss }); + AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss }); } private const float preempt = 1000; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2df43bdcd4..17c78f3aa0 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -54,7 +54,6 @@ namespace osu.Game.Rulesets.Catch.UI if (caughtFruit == null) return; - caughtFruit.State.Value = ArmedState.Idle; caughtFruit.AccentColour = fruit.AccentColour; caughtFruit.RelativePositionAxes = Axes.None; caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); From 1c5b3d009cedc0e2de237b9531195a5accccf0da Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Fri, 12 Jan 2018 17:09:57 +0100 Subject: [PATCH 128/133] remove volume reduction on preview it doubles with global reduction --- osu.Game/Overlays/Direct/PlayButton.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index e939047f1a..9ecddb01ba 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -174,10 +174,7 @@ namespace osu.Game.Overlays.Direct private void load(AudioManager audio) { if (!string.IsNullOrEmpty(preview)) - { Preview = audio.Track.Get(preview); - Preview.Volume.Value = 0.5; - } } } } From ae1adfd2f247509f9f36ce0ec0b43f1dfb1eed53 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Fri, 12 Jan 2018 19:30:34 +0100 Subject: [PATCH 129/133] remove unnecessary empty lines codefactor.io \(o.o)/ also one unnecessary semicolon --- osu.Desktop/Program.cs | 1 - .../Objects/Drawable/DrawableCatchHitObject.cs | 1 - osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 1 - osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 1 - osu.Game/Beatmaps/BeatmapManager.cs | 3 --- osu.Game/Beatmaps/DifficultyCalculator.cs | 1 - osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Graphics/UserInterface/OsuTabControl.cs | 1 - osu.Game/Online/API/OAuthToken.cs | 1 - osu.Game/Overlays/Chat/ChatLine.cs | 1 - osu.Game/Overlays/Direct/DirectPanel.cs | 1 - osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 2 -- osu.Game/Overlays/Music/PlaylistItem.cs | 1 - osu.Game/Overlays/Music/PlaylistList.cs | 1 - osu.Game/Overlays/Notifications/NotificationSection.cs | 1 - .../Overlays/Notifications/ProgressCompletionNotification.cs | 1 - osu.Game/Overlays/Notifications/ProgressNotification.cs | 1 - osu.Game/Rulesets/Objects/Types/IHasXPosition.cs | 1 - osu.Game/Rulesets/Objects/Types/IHasYPosition.cs | 1 - osu.Game/Rulesets/Replays/ReplayFrame.cs | 1 - osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs | 1 - osu.Game/Screens/Menu/ButtonSystem.cs | 1 - osu.Game/Screens/Multiplayer/DrawableRoom.cs | 1 - 23 files changed, 1 insertion(+), 26 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 6927568cc4..9760538197 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -43,7 +43,6 @@ namespace osu.Desktop host.Run(new OsuGameDesktop(args)); break; } - } return 0; } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index fce43137d1..05ef947e4b 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -23,7 +23,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable } } - public abstract class DrawableCatchHitObject : DrawableCatchHitObject where TObject : CatchHitObject { diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 8b0b59593c..557ce5eb1b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -58,7 +58,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override Beatmap ConvertBeatmap(Beatmap original) { - BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 881ce9199d..728c79b9cf 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -93,7 +93,6 @@ namespace osu.Game.Rulesets.Mania.Objects Column = Column }); } - } /// diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index d342e495e2..634b5bcd20 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -566,7 +566,6 @@ namespace osu.Game.Beatmaps using (var stream = new StreamReader(reader.GetStream(mapName))) metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata; - // check if a set already exists with the same online id. if (metadata.OnlineBeatmapSetID != null) beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID); @@ -581,7 +580,6 @@ namespace osu.Game.Beatmaps Metadata = metadata }; - var mapNames = reader.Filenames.Where(f => f.EndsWith(".osu")); foreach (var name in mapNames) @@ -693,7 +691,6 @@ namespace osu.Game.Beatmaps { try { - using (var beatmap = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) { Decoder decoder = Decoder.GetDecoder(beatmap); diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index 55aa876a1b..798268d05f 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -27,7 +27,6 @@ namespace osu.Game.Beatmaps Beatmap = CreateBeatmapConverter(beatmap).Convert(beatmap); Mods = mods ?? new Mod[0]; - ApplyMods(Mods); PreprocessHitObjects(); diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index c4c91e3e09..e0fc439924 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -137,7 +137,7 @@ namespace osu.Game.Beatmaps.Formats CentreRight, BottomLeft, BottomRight - }; + } internal enum StoryLayer { diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 032420b61e..7ad9bc73a8 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -180,7 +180,6 @@ namespace osu.Game.Graphics.UserInterface } } - protected class OsuTabDropdownHeader : OsuDropdownHeader { public override Color4 AccentColour diff --git a/osu.Game/Online/API/OAuthToken.cs b/osu.Game/Online/API/OAuthToken.cs index 7d644a2628..d2b9703a93 100644 --- a/osu.Game/Online/API/OAuthToken.cs +++ b/osu.Game/Online/API/OAuthToken.cs @@ -56,7 +56,6 @@ namespace osu.Game.Online.API } catch { - } return null; } diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 19dede56a0..4895c3a37c 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -219,7 +219,6 @@ namespace osu.Game.Overlays.Chat } else contentFlow.Text = message.Content; - } private class MessageSender : OsuClickableContainer, IHasContextMenu diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index ede9f2c412..7dd6be8dc6 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -65,7 +65,6 @@ namespace osu.Game.Overlays.Direct Colour = Color4.Black.Opacity(0.3f), }; - [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index e1a780406b..8edfdf9d95 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -183,8 +183,6 @@ namespace osu.Game.Overlays.MedalSplash description.FadeInFromZero(duration * 2); break; } - - } } diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 9eab8f797d..34dcc36699 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -148,7 +148,6 @@ namespace osu.Game.Overlays.Music private class PlaylistItemHandle : SpriteIcon { - public PlaylistItemHandle() { Anchor = Anchor.TopLeft; diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 17687a9623..31b7d0f9aa 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -230,7 +230,6 @@ namespace osu.Game.Overlays.Music items.ChangeChildDepth(draggedItem, dstIndex); } - private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { public IEnumerable FilterTerms => new string[] { }; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index d51cdb8bcc..13a69fbe3a 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -168,5 +168,4 @@ namespace osu.Game.Overlays.Notifications // the layout portion of this is being tracked as a framework issue (https://github.com/ppy/osu-framework/issues/1297). protected override bool RequiresChildrenUpdate => true; } - } diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index 4cd48edcf3..df2be95b40 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Framework.Graphics.Colour; - namespace osu.Game.Overlays.Notifications { public class ProgressCompletionNotification : SimpleNotification diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 4106a40867..b36ac6eebc 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -217,7 +217,6 @@ namespace osu.Game.Overlays.Notifications }; } - [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs index 2dec9e6ef1..f73f338778 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs index 8a38bde0f9..fc2d21481f 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index 92defad62e..4f8ed5163e 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -52,7 +52,6 @@ namespace osu.Game.Rulesets.Replays protected ReplayFrame() { - } public ReplayFrame(double time, float? mouseX, float? mouseY, ReplayButtonState buttonState) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs index c64ae23d46..758032a711 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs @@ -5,6 +5,5 @@ namespace osu.Game.Screens.Backgrounds { public class BackgroundScreenEmpty : BackgroundScreen { - } } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 72fe4368f0..529565312e 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -157,7 +157,6 @@ namespace osu.Game.Screens.Menu return true; } - return false; } diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index 7fcd364fe0..cc2828fb91 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -229,7 +229,6 @@ namespace osu.Game.Screens.Multiplayer { coverContainer.FadeIn(transition_duration); - LoadComponentAsync(new BeatmapSetCover(value.BeatmapSet) { Anchor = Anchor.Centre, From 70fc09f81e697925955da38755691e4d6f1686f5 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 13 Jan 2018 12:42:42 +0100 Subject: [PATCH 130/133] move judgement + state logic up to DrawableHitObject --- .../Objects/Drawables/DrawableHitObject.cs | 298 +++++++++--------- 1 file changed, 142 insertions(+), 156 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 13329a1470..a29ea4cbbb 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -29,37 +29,167 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual Color4 AccentColour { get; set; } = Color4.Gray; + private List nestedHitObjects; + public IReadOnlyList NestedHitObjects => nestedHitObjects; + + public event Action OnJudgement; + public event Action OnJudgementRemoved; + + public IReadOnlyList Judgements => judgements; + private readonly List judgements = new List(); + /// /// Whether a visible judgement should be displayed when this representation is hit. /// public virtual bool DisplayJudgement => true; - public override bool RemoveCompletedTransforms => false; + /// + /// Whether this and all of its nested s have been judged. + /// + public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); + + /// + /// Whether this can be judged. + /// + protected virtual bool ProvidesJudgement => true; + + private bool judgementOccurred; + private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; + + public bool Interactive = true; + public override bool HandleInput => Interactive; + public override bool RemoveWhenNotAlive => false; + public override bool RemoveCompletedTransforms => false; protected override bool RequiresChildrenUpdate => true; - public virtual bool AllJudged => false; + public readonly Bindable State = new Bindable(); protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; } + protected override void LoadComplete() + { + base.LoadComplete(); + + State.ValueChanged += state => + { + UpdateState(state); + + // apply any custom state overrides + ApplyCustomUpdateState?.Invoke(this, state); + }; + + State.TriggerChange(); + } + + protected abstract void UpdateState(ArmedState state); + + /// + /// Bind to apply a custom state which can override the default implementation. + /// + public event Action ApplyCustomUpdateState; + + protected override void Update() + { + base.Update(); + + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + + while (judgements.Count > 0) + { + var lastJudgement = judgements[judgements.Count - 1]; + if (lastJudgement.TimeOffset + endTime <= Time.Current) + break; + + judgements.RemoveAt(judgements.Count - 1); + State.Value = ArmedState.Idle; + + OnJudgementRemoved?.Invoke(this, lastJudgement); + } + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + UpdateJudgement(false); + } + + protected virtual void AddNested(DrawableHitObject h) + { + if (nestedHitObjects == null) + nestedHitObjects = new List(); + nestedHitObjects.Add(h); + } + + /// + /// Notifies that a new judgement has occurred for this . + /// + /// The . + protected void AddJudgement(Judgement judgement) + { + judgementOccurred = true; + + // Ensure that the judgement is given a valid time offset, because this may not get set by the caller + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + judgement.TimeOffset = Time.Current - endTime; + + judgements.Add(judgement); + + switch (judgement.Result) + { + case HitResult.None: + break; + case HitResult.Miss: + State.Value = ArmedState.Miss; + break; + default: + State.Value = ArmedState.Hit; + break; + } + + OnJudgement?.Invoke(this, judgement); + } + /// /// Processes this , checking if any judgements have occurred. /// /// Whether the user triggered this process. /// Whether a judgement has occurred from this or any nested s. - protected internal virtual bool UpdateJudgement(bool userTriggered) => false; - - private List nestedHitObjects; - public IReadOnlyList NestedHitObjects => nestedHitObjects; - - protected virtual void AddNested(DrawableHitObject h) + protected internal bool UpdateJudgement(bool userTriggered) + { + judgementOccurred = false; + + if (AllJudged) + return false; + + if (NestedHitObjects != null) + { + foreach (var d in NestedHitObjects) + judgementOccurred |= d.UpdateJudgement(userTriggered); + } + + if (!ProvidesJudgement || judgementFinalized || judgementOccurred) + return judgementOccurred; + + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + CheckForJudgements(userTriggered, Time.Current - endTime); + + return judgementOccurred; + } + + /// + /// Checks if any judgements have occurred for this . This method must construct + /// all s and notify of them through . + /// + /// Whether the user triggered this check. + /// The offset from the end time at which this check occurred. A > 0 + /// implies that this check occurred after the end time of . + protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { - if (nestedHitObjects == null) - nestedHitObjects = new List(); - nestedHitObjects.Add(h); } /// @@ -76,30 +206,14 @@ namespace osu.Game.Rulesets.Objects.Drawables public abstract class DrawableHitObject : DrawableHitObject where TObject : HitObject { - public event Action OnJudgement; - public event Action OnJudgementRemoved; - public new readonly TObject HitObject; - public override bool HandleInput => Interactive; - public bool Interactive = true; - - /// - /// Whether this can be judged. - /// - protected virtual bool ProvidesJudgement => true; - - private readonly List judgements = new List(); - public IReadOnlyList Judgements => judgements; - protected List Samples = new List(); protected virtual IEnumerable GetSamples() => HitObject.Samples; // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first protected virtual string SampleNamespace => null; - public readonly Bindable State = new Bindable(); - protected DrawableHitObject(TObject hitObject) : base(hitObject) { @@ -141,139 +255,11 @@ namespace osu.Game.Rulesets.Objects.Drawables State.ValueChanged += state => { - UpdateState(state); - - // apply any custom state overrides - ApplyCustomUpdateState?.Invoke(this, state); - if (State == ArmedState.Hit) PlaySamples(); }; - - State.TriggerChange(); } - protected void PlaySamples() - { - Samples.ForEach(s => s?.Play()); - } - - private bool judgementOccurred; - private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; - - /// - /// Whether this and all of its nested s have been judged. - /// - public sealed override bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); - - /// - /// Notifies that a new judgement has occurred for this . - /// - /// The . - protected void AddJudgement(Judgement judgement) - { - judgementOccurred = true; - - // Ensure that the judgement is given a valid time offset, because this may not get set by the caller - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - judgement.TimeOffset = Time.Current - endTime; - - judgements.Add(judgement); - - switch (judgement.Result) - { - case HitResult.None: - break; - case HitResult.Miss: - State.Value = ArmedState.Miss; - break; - default: - State.Value = ArmedState.Hit; - break; - } - - OnJudgement?.Invoke(this, judgement); - } - - /// - /// Processes this , checking if any judgements have occurred. - /// - /// Whether the user triggered this process. - /// Whether a judgement has occurred from this or any nested s. - protected internal sealed override bool UpdateJudgement(bool userTriggered) - { - judgementOccurred = false; - - if (AllJudged) - return false; - - if (NestedHitObjects != null) - { - foreach (var d in NestedHitObjects) - judgementOccurred |= d.UpdateJudgement(userTriggered); - } - - if (!ProvidesJudgement || judgementFinalized || judgementOccurred) - return judgementOccurred; - - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - CheckForJudgements(userTriggered, Time.Current - endTime); - - return judgementOccurred; - } - - /// - /// Checks if any judgements have occurred for this . This method must construct - /// all s and notify of them through . - /// - /// Whether the user triggered this check. - /// The offset from the end time at which this check occurred. A > 0 - /// implies that this check occurred after the end time of . - protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { } - - protected override void Update() - { - base.Update(); - - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - - while (judgements.Count > 0) - { - var lastJudgement = judgements[judgements.Count - 1]; - if (lastJudgement.TimeOffset + endTime <= Time.Current) - break; - - judgements.RemoveAt(judgements.Count - 1); - State.Value = ArmedState.Idle; - - OnJudgementRemoved?.Invoke(this, lastJudgement); - } - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - UpdateJudgement(false); - } - - protected override void AddNested(DrawableHitObject h) - { - base.AddNested(h); - - if (!(h is DrawableHitObject hWithJudgement)) - return; - - hWithJudgement.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); - hWithJudgement.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); - hWithJudgement.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); - } - - /// - /// Bind to apply a custom state which can override the default implementation. - /// - public event Action ApplyCustomUpdateState; - - protected abstract void UpdateState(ArmedState state); + protected void PlaySamples() => Samples.ForEach(s => s?.Play()); } } From 356bb5da1e5e63243174c84cfcdb7b2dbefc5839 Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 13 Jan 2018 12:55:52 +0100 Subject: [PATCH 131/133] move sample logic up too --- .../Objects/Drawables/DrawableHitObject.cs | 88 +++++++++---------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a29ea4cbbb..68766789e0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -29,6 +29,12 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual Color4 AccentColour { get; set; } = Color4.Gray; + // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first + protected virtual string SampleNamespace => null; + + protected List Samples = new List(); + protected virtual IEnumerable GetSamples() => HitObject.Samples; + private List nestedHitObjects; public IReadOnlyList NestedHitObjects => nestedHitObjects; @@ -70,6 +76,35 @@ namespace osu.Game.Rulesets.Objects.Drawables HitObject = hitObject; } + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + var samples = GetSamples(); + if (samples.Any()) + { + if (HitObject.SampleControlPoint == null) + throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); + + foreach (SampleInfo s in samples) + { + SampleInfo localSampleInfo = new SampleInfo + { + Bank = s.Bank ?? HitObject.SampleControlPoint.SampleBank, + Name = s.Name, + Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume + }; + + SampleChannel channel = localSampleInfo.GetChannel(audio.Sample, SampleNamespace); + + if (channel == null) + continue; + + Samples.Add(channel); + } + } + } + protected override void LoadComplete() { base.LoadComplete(); @@ -80,6 +115,9 @@ namespace osu.Game.Rulesets.Objects.Drawables // apply any custom state overrides ApplyCustomUpdateState?.Invoke(this, state); + + if (State == ArmedState.Hit) + PlaySamples(); }; State.TriggerChange(); @@ -92,6 +130,8 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public event Action ApplyCustomUpdateState; + protected void PlaySamples() => Samples.ForEach(s => s?.Play()); + protected override void Update() { base.Update(); @@ -208,58 +248,10 @@ namespace osu.Game.Rulesets.Objects.Drawables { public new readonly TObject HitObject; - protected List Samples = new List(); - protected virtual IEnumerable GetSamples() => HitObject.Samples; - - // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first - protected virtual string SampleNamespace => null; - protected DrawableHitObject(TObject hitObject) : base(hitObject) { HitObject = hitObject; } - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - var samples = GetSamples(); - if (samples.Any()) - { - if (HitObject.SampleControlPoint == null) - throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." - + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); - - foreach (SampleInfo s in samples) - { - SampleInfo localSampleInfo = new SampleInfo - { - Bank = s.Bank ?? HitObject.SampleControlPoint.SampleBank, - Name = s.Name, - Volume = s.Volume > 0 ? s.Volume : HitObject.SampleControlPoint.SampleVolume - }; - - SampleChannel channel = localSampleInfo.GetChannel(audio.Sample, SampleNamespace); - - if (channel == null) - continue; - - Samples.Add(channel); - } - } - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - State.ValueChanged += state => - { - if (State == ArmedState.Hit) - PlaySamples(); - }; - } - - protected void PlaySamples() => Samples.ForEach(s => s?.Play()); } } From 7875f0cb01d44738480b071fd0e7625b41bfe51a Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 13 Jan 2018 16:15:41 +0100 Subject: [PATCH 132/133] remove unnecessary internal --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 68766789e0..e43ef1cc60 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -199,7 +199,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether the user triggered this process. /// Whether a judgement has occurred from this or any nested s. - protected internal bool UpdateJudgement(bool userTriggered) + protected bool UpdateJudgement(bool userTriggered) { judgementOccurred = false; From 8ac6818639c93751a3b7212d05a987ead1bc4adc Mon Sep 17 00:00:00 2001 From: Aergwyn Date: Sat, 13 Jan 2018 13:05:23 +0100 Subject: [PATCH 133/133] expose IsHit --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e43ef1cc60..af14c43a3f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -49,6 +49,11 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual bool DisplayJudgement => true; + /// + /// Whether this and all of its nested s have been hit. + /// + public bool IsHit => Judgements.Any(j => j.Final && j.IsHit) && (NestedHitObjects?.All(n => n.IsHit) ?? true); + /// /// Whether this and all of its nested s have been judged. ///