From 870ce8868cf3955754c266cec0da8fc754a91019 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 16:07:33 +0900 Subject: [PATCH 01/53] Make scrollabletimeline use gridcontainer --- .../Visual/TestCaseEditorComposeTimeline.cs | 3 +- .../Compose/Timeline/ScrollableTimeline.cs | 135 +++++++++--------- 2 files changed, 70 insertions(+), 68 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index d15ee32d8d..0e7ba5c900 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -34,7 +34,8 @@ namespace osu.Game.Tests.Visual { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(1000, 100) + RelativeSizeAxes = Axes.X, + Size = new Vector2(0.8f, 100) } }; } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs index c308b2b9f8..9ce4830e5a 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs @@ -33,82 +33,90 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline RelativeSizeAxes = Axes.Both, Colour = OsuColour.FromHex("111") }, - new FillFlowContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new Drawable[] + Content = new[] { - new Container + new Drawable[] { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] + new Container { - new Box + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222") - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Y, - Width = 160, - Padding = new MarginPadding { Horizontal = 15 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 4), - Children = new[] + new Box { - hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hitobjects" }, - hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hitsounds" }, - waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("222") + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Y, + Width = 160, + Padding = new MarginPadding { Horizontal = 15 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 4), + Children = new[] + { + hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hitobjects" }, + hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hitsounds" }, + waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } + } } } - } - }, - new Container - { - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Children = new Drawable[] + }, + new Container { - new Box + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("333") - }, - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - Children = new[] + new Box { - new TimelineButton + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("333") + }, + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new[] { - RelativeSizeAxes = Axes.Y, - Height = 0.5f, - Icon = FontAwesome.fa_search_plus, - Action = () => timelineContainer.Zoom++ - }, - new TimelineButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Y, - Height = 0.5f, - Icon = FontAwesome.fa_search_minus, - Action = () => timelineContainer.Zoom-- - }, + new TimelineButton + { + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + Icon = FontAwesome.fa_search_plus, + // Action = () => timelineContainer.Zoom++ + }, + new TimelineButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + Icon = FontAwesome.fa_search_minus, + // Action = () => timelineContainer.Zoom-- + }, + } } } - } + }, + timelineContainer = new ScrollingTimelineContainer { RelativeSizeAxes = Axes.Both } }, - timelineContainer = new ScrollingTimelineContainer { RelativeSizeAxes = Axes.Y } + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed), } } }; @@ -120,12 +128,5 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline timelineContainer.Beatmap.BindTo(Beatmap); timelineContainer.WaveformVisible.BindTo(waveformCheckbox.Current); } - - protected override void Update() - { - base.Update(); - - timelineContainer.Size = new Vector2(DrawSize.X - timelineContainer.DrawPosition.X, 1); - } } } From e7aa1d9c38c500741ceb1da086a6aa73a5211c07 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 16:12:21 +0900 Subject: [PATCH 02/53] Temporarily remove zoom levels, simplify scrollingtimelinecontainer --- .../Timeline/ScrollingTimelineContainer.cs | 107 +----------------- 1 file changed, 3 insertions(+), 104 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index f71607a6cf..5195a85eac 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -1,12 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using OpenTK; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -14,8 +11,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { public class ScrollingTimelineContainer : ScrollContainer { - public readonly Bindable HitObjectsVisible = new Bindable(); - public readonly Bindable HitSoundsVisible = new Bindable(); public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); @@ -26,6 +21,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { Masking = true; + Content.AutoSizeAxes = Axes.None; + Content.RelativeSizeAxes = Axes.Both; + Add(waveform = new BeatmapWaveformGraph { RelativeSizeAxes = Axes.Both, @@ -33,107 +31,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline Depth = float.MaxValue }); - Content.AutoSizeAxes = Axes.None; - Content.RelativeSizeAxes = Axes.Both; - waveform.Beatmap.BindTo(Beatmap); WaveformVisible.ValueChanged += waveformVisibilityChanged; - - Zoom = 10; - } - - private float minZoom = 1; - /// - /// The minimum zoom level allowed. - /// - public float MinZoom - { - get { return minZoom; } - set - { - if (value <= 0) - throw new ArgumentOutOfRangeException(nameof(value)); - if (minZoom == value) - return; - minZoom = value; - - // Update the zoom level - Zoom = Zoom; - } - } - - private float maxZoom = 30; - /// - /// The maximum zoom level allowed. - /// - public float MaxZoom - { - get { return maxZoom; } - set - { - if (value <= 0) - throw new ArgumentOutOfRangeException(nameof(value)); - if (maxZoom == value) - return; - maxZoom = value; - - // Update the zoom level - Zoom = Zoom; - } - } - - private float zoom = 1; - /// - /// The current zoom level. - /// - public float Zoom - { - get { return zoom; } - set - { - value = MathHelper.Clamp(value, MinZoom, MaxZoom); - if (zoom == value) - return; - zoom = value; - - // Make the zoom target default to the center of the graph if it hasn't been set - if (relativeContentZoomTarget == null) - relativeContentZoomTarget = ToSpaceOfOtherDrawable(DrawSize / 2, Content).X / Content.DrawSize.X; - if (localZoomTarget == null) - localZoomTarget = DrawSize.X / 2; - - Content.ResizeWidthTo(Zoom); - - // Update the scroll position to focus on the zoom target - float scrollPos = Content.DrawSize.X * relativeContentZoomTarget.Value - localZoomTarget.Value; - ScrollTo(scrollPos, false); - - relativeContentZoomTarget = null; - localZoomTarget = null; - } - } - - /// - /// Zoom target as a relative position in the space. - /// - private float? relativeContentZoomTarget; - - /// - /// Zoom target as a position in our local space. - /// - private float? localZoomTarget; - - protected override bool OnWheel(InputState state) - { - if (!state.Keyboard.ControlPressed) - return base.OnWheel(state); - - relativeContentZoomTarget = Content.ToLocalSpace(state.Mouse.NativeState.Position).X / Content.DrawSize.X; - localZoomTarget = ToLocalSpace(state.Mouse.NativeState.Position).X; - - Zoom += state.Mouse.WheelDelta; - - return true; } private void waveformVisibilityChanged(bool visible) => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); From 9bb3e56bb3a22875f746175fee15640489713232 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 17:05:38 +0900 Subject: [PATCH 03/53] Implement half-width overflows --- .../Timeline/ScrollingTimelineContainer.cs | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 5195a85eac..e031e354db 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -14,6 +14,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); + private readonly Container waveformContainer; private readonly BeatmapWaveformGraph waveform; public ScrollingTimelineContainer() @@ -21,20 +22,31 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { Masking = true; - Content.AutoSizeAxes = Axes.None; - Content.RelativeSizeAxes = Axes.Both; - - Add(waveform = new BeatmapWaveformGraph + Child = waveformContainer = new Container { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222"), - Depth = float.MaxValue - }); + RelativeSizeAxes = Axes.Y, + Child = waveform = new BeatmapWaveformGraph + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("222"), + Depth = float.MaxValue + } + }; waveform.Beatmap.BindTo(Beatmap); WaveformVisible.ValueChanged += waveformVisibilityChanged; } + private float zoom = 10; + + protected override void Update() + { + base.Update(); + + waveformContainer.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; + waveformContainer.Width = DrawWidth * zoom; + } + private void waveformVisibilityChanged(bool visible) => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } } From e3af32ad2f0f581d56ce09c30849a632e6e830b7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 17:07:41 +0900 Subject: [PATCH 04/53] A bit of cleanup --- .../Screens/Compose/Timeline/ScrollingTimelineContainer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index e031e354db..07896d63be 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -34,7 +34,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline }; waveform.Beatmap.BindTo(Beatmap); - WaveformVisible.ValueChanged += waveformVisibilityChanged; + + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } private float zoom = 10; @@ -46,7 +47,5 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline waveformContainer.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; waveformContainer.Width = DrawWidth * zoom; } - - private void waveformVisibilityChanged(bool visible) => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } } From 074dee3a83a9d456378a91518f4daa8bb9b26e40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 18:37:51 +0900 Subject: [PATCH 05/53] Re-implement mousewheel zoom --- .../Timeline/ScrollingTimelineContainer.cs | 73 +++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 07896d63be..e4b19fc2c5 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -4,8 +4,12 @@ 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.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics; +using OpenTK; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { @@ -15,13 +19,15 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public readonly Bindable Beatmap = new Bindable(); private readonly Container waveformContainer; - private readonly BeatmapWaveformGraph waveform; + + private float currentZoom = 10; public ScrollingTimelineContainer() : base(Direction.Horizontal) { Masking = true; + BeatmapWaveformGraph waveform; Child = waveformContainer = new Container { RelativeSizeAxes = Axes.Y, @@ -34,18 +40,75 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline }; waveform.Beatmap.BindTo(Beatmap); - + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } - private float zoom = 10; - protected override void Update() { base.Update(); waveformContainer.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - waveformContainer.Width = DrawWidth * zoom; + waveformContainer.Width = DrawWidth * currentZoom; + } + + protected override bool OnWheel(InputState state) + { + if (!state.Keyboard.ControlPressed) + return base.OnWheel(state); + + setZoomTarget(zoomTarget + state.Mouse.WheelDelta, waveformContainer.ToLocalSpace(state.Mouse.NativeState.Position).X); + return true; + } + + private float zoomTarget = 10; + private void setZoomTarget(float newZoom, float focusPoint) + { + zoomTarget = MathHelper.Clamp(newZoom, 1, 60); + transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); + } + + private void transformZoomTo(float newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth, DrawWidth, Current), newZoom, duration, easing)); + + private class TransformZoom : Transform + { + private readonly float focusPoint; + private readonly float focusSize; + private readonly float sizeReference; + private readonly float scrollOffset; + + public TransformZoom(float focusPoint, float focusSize, float sizeReference, float scrollOffset) + { + this.focusPoint = focusPoint; + this.focusSize = focusSize; + this.sizeReference = sizeReference; + this.scrollOffset = scrollOffset; + } + + public override string TargetMember => nameof(currentZoom); + + private float valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + protected override void Apply(ScrollingTimelineContainer d, double time) + { + float newZoom = valueAt(time); + + float focusOffset = focusPoint - scrollOffset; + float expectedWidth = sizeReference * newZoom; + float targetOffset = expectedWidth * (focusPoint / focusSize) - focusOffset; + + d.currentZoom = newZoom; + d.ScrollTo(targetOffset, false); + } + + protected override void ReadIntoStartValue(ScrollingTimelineContainer d) => StartValue = d.currentZoom; } } } From eff5eddbe97dac18b954d81aa32542988ab1e822 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 18:41:22 +0900 Subject: [PATCH 06/53] Make zoom an int again --- .../Screens/Compose/Timeline/ScrollingTimelineContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index e4b19fc2c5..5e68b931a4 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -61,14 +61,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline return true; } - private float zoomTarget = 10; - private void setZoomTarget(float newZoom, float focusPoint) + private int zoomTarget = 10; + private void setZoomTarget(int newZoom, float focusPoint) { zoomTarget = MathHelper.Clamp(newZoom, 1, 60); transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); } - private void transformZoomTo(float newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) + private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth, DrawWidth, Current), newZoom, duration, easing)); private class TransformZoom : Transform From 35e116cb1270dce0641d3856db21d7612d34961f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:04:07 +0900 Subject: [PATCH 07/53] Reduce ctor arguments --- .../Timeline/ScrollingTimelineContainer.cs | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 5e68b931a4..a24bf7c909 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -69,21 +69,34 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline } private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth, DrawWidth, Current), newZoom, duration, easing)); + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth), newZoom, duration, easing)); private class TransformZoom : Transform { + /// + /// The focus point in the waveform, in absolute coordinates local to the waveform. + /// private readonly float focusPoint; - private readonly float focusSize; - private readonly float sizeReference; - private readonly float scrollOffset; - public TransformZoom(float focusPoint, float focusSize, float sizeReference, float scrollOffset) + /// + /// The size of the waveform. + /// + private readonly float waveformSize; + + /// + /// The scroll offset at the start time of the transform/ + /// + private float startScrollOffset; + + /// + /// Transforms to a new value. + /// + /// The focus point in the waveform, in absolute coordinates local to the waveform. + /// The size of the waveform. + public TransformZoom(float focusPoint, float waveformSize) { this.focusPoint = focusPoint; - this.focusSize = focusSize; - this.sizeReference = sizeReference; - this.scrollOffset = scrollOffset; + this.waveformSize = waveformSize; } public override string TargetMember => nameof(currentZoom); @@ -100,15 +113,19 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { float newZoom = valueAt(time); - float focusOffset = focusPoint - scrollOffset; - float expectedWidth = sizeReference * newZoom; - float targetOffset = expectedWidth * (focusPoint / focusSize) - focusOffset; + float focusOffset = focusPoint - startScrollOffset; + float expectedWidth = d.DrawWidth * newZoom; + float targetOffset = expectedWidth * (focusPoint / waveformSize) - focusOffset; d.currentZoom = newZoom; d.ScrollTo(targetOffset, false); } - protected override void ReadIntoStartValue(ScrollingTimelineContainer d) => StartValue = d.currentZoom; + protected override void ReadIntoStartValue(ScrollingTimelineContainer d) + { + startScrollOffset = d.Current; + StartValue = d.currentZoom; + } } } } From 8da3c2c52aa79ca631fcd12573bc443a61ac9d3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:05:19 +0900 Subject: [PATCH 08/53] Expose zoom publicly again, re-enable zoom buttons --- .../Edit/Screens/Compose/Timeline/ScrollableTimeline.cs | 4 ++-- .../Screens/Compose/Timeline/ScrollingTimelineContainer.cs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs index 9ce4830e5a..31466e960f 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs @@ -94,7 +94,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_plus, - // Action = () => timelineContainer.Zoom++ + Action = () => timelineContainer.Zoom++ }, new TimelineButton { @@ -103,7 +103,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_minus, - // Action = () => timelineContainer.Zoom-- + Action = () => timelineContainer.Zoom-- }, } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index a24bf7c909..2fe5d09788 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -44,6 +44,12 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } + public int Zoom + { + get => zoomTarget; + set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), waveformContainer).X); + } + protected override void Update() { base.Update(); From 0141cbebbab43ab85b11d0377aadae6259483448 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:08:10 +0900 Subject: [PATCH 09/53] waveformContainer -> zoomedContent --- .../Timeline/ScrollingTimelineContainer.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 2fe5d09788..e48b625b8b 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); - private readonly Container waveformContainer; + private readonly Container zoomedContent; private float currentZoom = 10; @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline Masking = true; BeatmapWaveformGraph waveform; - Child = waveformContainer = new Container + Child = zoomedContent = new Container { RelativeSizeAxes = Axes.Y, Child = waveform = new BeatmapWaveformGraph @@ -44,18 +44,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } + /// + /// Gets or sets the content zoom of this . + /// public int Zoom { get => zoomTarget; - set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), waveformContainer).X); + set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); } protected override void Update() { base.Update(); - waveformContainer.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - waveformContainer.Width = DrawWidth * currentZoom; + zoomedContent.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; + zoomedContent.Width = DrawWidth * currentZoom; } protected override bool OnWheel(InputState state) @@ -63,7 +66,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline if (!state.Keyboard.ControlPressed) return base.OnWheel(state); - setZoomTarget(zoomTarget + state.Mouse.WheelDelta, waveformContainer.ToLocalSpace(state.Mouse.NativeState.Position).X); + setZoomTarget(zoomTarget + state.Mouse.WheelDelta, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); return true; } @@ -75,7 +78,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline } private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, waveformContainer.DrawWidth), newZoom, duration, easing)); + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth), newZoom, duration, easing)); private class TransformZoom : Transform { From 9a9ed1d630d9aa01ecca4ae03251d3a75124c7b4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:30:54 +0900 Subject: [PATCH 10/53] Encapsulate zoom logic into a separate class --- .../Timeline/ScrollingTimelineContainer.cs | 115 ++--------------- .../Timeline/ZoomableScrollContainer.cs | 118 ++++++++++++++++++ 2 files changed, 125 insertions(+), 108 deletions(-) create mode 100644 osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index e48b625b8b..96dc54f1e9 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -3,40 +3,24 @@ 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.MathUtils; using osu.Game.Beatmaps; using osu.Game.Graphics; -using OpenTK; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { - public class ScrollingTimelineContainer : ScrollContainer + public class ScrollingTimelineContainer : ZoomableScrollContainer { public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); - private readonly Container zoomedContent; - - private float currentZoom = 10; - public ScrollingTimelineContainer() - : base(Direction.Horizontal) { - Masking = true; - BeatmapWaveformGraph waveform; - Child = zoomedContent = new Container + Child = waveform = new BeatmapWaveformGraph { - RelativeSizeAxes = Axes.Y, - Child = waveform = new BeatmapWaveformGraph - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222"), - Depth = float.MaxValue - } + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("222"), + Depth = float.MaxValue }; waveform.Beatmap.BindTo(Beatmap); @@ -44,97 +28,12 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); } - /// - /// Gets or sets the content zoom of this . - /// - public int Zoom - { - get => zoomTarget; - set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); - } - protected override void Update() { base.Update(); - zoomedContent.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - zoomedContent.Width = DrawWidth * currentZoom; - } - - protected override bool OnWheel(InputState state) - { - if (!state.Keyboard.ControlPressed) - return base.OnWheel(state); - - setZoomTarget(zoomTarget + state.Mouse.WheelDelta, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); - return true; - } - - private int zoomTarget = 10; - private void setZoomTarget(int newZoom, float focusPoint) - { - zoomTarget = MathHelper.Clamp(newZoom, 1, 60); - transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); - } - - private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth), newZoom, duration, easing)); - - private class TransformZoom : Transform - { - /// - /// The focus point in the waveform, in absolute coordinates local to the waveform. - /// - private readonly float focusPoint; - - /// - /// The size of the waveform. - /// - private readonly float waveformSize; - - /// - /// The scroll offset at the start time of the transform/ - /// - private float startScrollOffset; - - /// - /// Transforms to a new value. - /// - /// The focus point in the waveform, in absolute coordinates local to the waveform. - /// The size of the waveform. - public TransformZoom(float focusPoint, float waveformSize) - { - this.focusPoint = focusPoint; - this.waveformSize = waveformSize; - } - - public override string TargetMember => nameof(currentZoom); - - private float valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - protected override void Apply(ScrollingTimelineContainer d, double time) - { - float newZoom = valueAt(time); - - float focusOffset = focusPoint - startScrollOffset; - float expectedWidth = d.DrawWidth * newZoom; - float targetOffset = expectedWidth * (focusPoint / waveformSize) - focusOffset; - - d.currentZoom = newZoom; - d.ScrollTo(targetOffset, false); - } - - protected override void ReadIntoStartValue(ScrollingTimelineContainer d) - { - startScrollOffset = d.Current; - StartValue = d.currentZoom; - } + // We want time = 0 to be at the centre of the container when scrolled to the start + Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; } } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs new file mode 100644 index 0000000000..05a2882f31 --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -0,0 +1,118 @@ +// 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 osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using OpenTK; + +namespace osu.Game.Screens.Edit.Screens.Compose.Timeline +{ + public class ZoomableScrollContainer : ScrollContainer + { + private readonly Container zoomedContent; + protected override Container Content => zoomedContent; + + private float currentZoom = 10; + + public ZoomableScrollContainer() + : base(Direction.Horizontal) + { + base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y }); + } + + /// + /// Gets or sets the content zoom of this . + /// + public int Zoom + { + get => zoomTarget; + set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); + } + + protected override void Update() + { + base.Update(); + + zoomedContent.Width = DrawWidth * currentZoom; + } + + protected override bool OnWheel(InputState state) + { + if (!state.Keyboard.ControlPressed) + return base.OnWheel(state); + + setZoomTarget(zoomTarget + state.Mouse.WheelDelta, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); + return true; + } + + private int zoomTarget = 10; + private void setZoomTarget(int newZoom, float focusPoint) + { + zoomTarget = MathHelper.Clamp(newZoom, 1, 60); + transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); + } + + private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth), newZoom, duration, easing)); + + private class TransformZoom : Transform + { + /// + /// The focus point in the waveform, in absolute coordinates local to the waveform. + /// + private readonly float focusPoint; + + /// + /// The size of the waveform. + /// + private readonly float waveformSize; + + /// + /// The scroll offset at the start time of the transform/ + /// + private float startScrollOffset; + + /// + /// Transforms to a new value. + /// + /// The focus point in the waveform, in absolute coordinates local to the waveform. + /// The size of the waveform. + public TransformZoom(float focusPoint, float waveformSize) + { + this.focusPoint = focusPoint; + this.waveformSize = waveformSize; + } + + public override string TargetMember => nameof(currentZoom); + + private float valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + protected override void Apply(ZoomableScrollContainer d, double time) + { + float newZoom = valueAt(time); + + float focusOffset = focusPoint - startScrollOffset; + float expectedWidth = d.DrawWidth * newZoom; + float targetOffset = expectedWidth * (focusPoint / waveformSize) - focusOffset; + + d.currentZoom = newZoom; + d.ScrollTo(targetOffset, false); + } + + protected override void ReadIntoStartValue(ZoomableScrollContainer d) + { + startScrollOffset = d.Current; + StartValue = d.currentZoom; + } + } + } +} From f41d31e1db2f2a1b2d4e398662cec4bddf8cca97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:32:23 +0900 Subject: [PATCH 11/53] ScrollableTimeline -> TimelineContainer --- .../Visual/TestCaseEditorComposeTimeline.cs | 8 ++++---- osu.Game/Screens/Edit/Screens/Compose/Compose.cs | 6 +++--- ...crollableTimeline.cs => TimelineContainer.cs} | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) rename osu.Game/Screens/Edit/Screens/Compose/Timeline/{ScrollableTimeline.cs => TimelineContainer.cs} (90%) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index 0e7ba5c900..5323ac44b1 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -16,9 +16,9 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseEditorComposeTimeline : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(ScrollableTimeline), typeof(ScrollingTimelineContainer), typeof(BeatmapWaveformGraph), typeof(TimelineButton) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineContainer), typeof(Timeline), typeof(BeatmapWaveformGraph), typeof(TimelineButton) }; - private readonly ScrollableTimeline timeline; + private readonly TimelineContainer timelineContainer; public TestCaseEditorComposeTimeline() { @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopCentre, State = Visibility.Visible }, - timeline = new ScrollableTimeline + timelineContainer = new TimelineContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(OsuGameBase osuGame) { - timeline.Beatmap.BindTo(osuGame.Beatmap); + timelineContainer.Beatmap.BindTo(osuGame.Beatmap); } } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 91adc8324a..d04c4c9c0f 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose { dependencies.Cache(beatDivisor); - ScrollableTimeline timeline; + TimelineContainer timelineContainer; Children = new Drawable[] { new GridContainer @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = timeline = new ScrollableTimeline { RelativeSizeAxes = Axes.Both } + Child = timelineContainer = new TimelineContainer { RelativeSizeAxes = Axes.Both } }, new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } }, @@ -97,7 +97,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose }, }; - timeline.Beatmap.BindTo(Beatmap); + timelineContainer.Beatmap.BindTo(Beatmap); var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); if (ruleset == null) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs similarity index 90% rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs rename to osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs index 31466e960f..95a8937b9b 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs @@ -12,13 +12,13 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { - public class ScrollableTimeline : CompositeDrawable + public class TimelineContainer : CompositeDrawable { public readonly Bindable Beatmap = new Bindable(); - private readonly ScrollingTimelineContainer timelineContainer; + private readonly Timeline timeline; - public ScrollableTimeline() + public TimelineContainer() { Masking = true; CornerRadius = 5; @@ -94,7 +94,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_plus, - Action = () => timelineContainer.Zoom++ + Action = () => timeline.Zoom++ }, new TimelineButton { @@ -103,13 +103,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline RelativeSizeAxes = Axes.Y, Height = 0.5f, Icon = FontAwesome.fa_search_minus, - Action = () => timelineContainer.Zoom-- + Action = () => timeline.Zoom-- }, } } } }, - timelineContainer = new ScrollingTimelineContainer { RelativeSizeAxes = Axes.Both } + timeline = new Timeline { RelativeSizeAxes = Axes.Both } }, }, ColumnDimensions = new[] @@ -125,8 +125,8 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline hitSoundsCheckbox.Current.Value = true; waveformCheckbox.Current.Value = true; - timelineContainer.Beatmap.BindTo(Beatmap); - timelineContainer.WaveformVisible.BindTo(waveformCheckbox.Current); + timeline.Beatmap.BindTo(Beatmap); + timeline.WaveformVisible.BindTo(waveformCheckbox.Current); } } } From a84536d343be59f40e2905ad947bcdd135fc5054 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:33:47 +0900 Subject: [PATCH 12/53] ScrollingTimelineContainer -> Timeline --- .../Timeline/{ScrollingTimelineContainer.cs => Timeline.cs} | 4 ++-- .../Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Screens/Edit/Screens/Compose/Timeline/{ScrollingTimelineContainer.cs => Timeline.cs} (88%) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs similarity index 88% rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs rename to osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index 96dc54f1e9..f1086e2cf6 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -8,12 +8,12 @@ using osu.Game.Graphics; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { - public class ScrollingTimelineContainer : ZoomableScrollContainer + public class Timeline : ZoomableScrollContainer { public readonly Bindable WaveformVisible = new Bindable(); public readonly Bindable Beatmap = new Bindable(); - public ScrollingTimelineContainer() + public Timeline() { BeatmapWaveformGraph waveform; Child = waveform = new BeatmapWaveformGraph diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index 05a2882f31..592419b336 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline } /// - /// Gets or sets the content zoom of this . + /// Gets or sets the content zoom of this . /// public int Zoom { @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private float startScrollOffset; /// - /// Transforms to a new value. + /// Transforms to a new value. /// /// The focus point in the waveform, in absolute coordinates local to the waveform. /// The size of the waveform. From d9e795fb9f7a8ee7f372e84653ec3eb870b2b92d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 5 Apr 2018 19:40:03 +0900 Subject: [PATCH 13/53] TimelineContainer -> TimelineArea --- osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs | 8 ++++---- osu.Game/Screens/Edit/Screens/Compose/Compose.cs | 6 +++--- .../Timeline/{TimelineContainer.cs => TimelineArea.cs} | 4 ++-- .../Screens/Compose/Timeline/ZoomableScrollContainer.cs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) rename osu.Game/Screens/Edit/Screens/Compose/Timeline/{TimelineContainer.cs => TimelineArea.cs} (96%) diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index 5323ac44b1..8ffb54f2c7 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -16,9 +16,9 @@ namespace osu.Game.Tests.Visual [TestFixture] public class TestCaseEditorComposeTimeline : OsuTestCase { - public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineContainer), typeof(Timeline), typeof(BeatmapWaveformGraph), typeof(TimelineButton) }; + public override IReadOnlyList RequiredTypes => new[] { typeof(TimelineArea), typeof(Timeline), typeof(BeatmapWaveformGraph), typeof(TimelineButton) }; - private readonly TimelineContainer timelineContainer; + private readonly TimelineArea timelineArea; public TestCaseEditorComposeTimeline() { @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual Origin = Anchor.TopCentre, State = Visibility.Visible }, - timelineContainer = new TimelineContainer + timelineArea = new TimelineArea { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load(OsuGameBase osuGame) { - timelineContainer.Beatmap.BindTo(osuGame.Beatmap); + timelineArea.Beatmap.BindTo(osuGame.Beatmap); } } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index d04c4c9c0f..9306a3394c 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose { dependencies.Cache(beatDivisor); - TimelineContainer timelineContainer; + TimelineArea timelineArea; Children = new Drawable[] { new GridContainer @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = timelineContainer = new TimelineContainer { RelativeSizeAxes = Axes.Both } + Child = timelineArea = new TimelineArea { RelativeSizeAxes = Axes.Both } }, new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } }, @@ -97,7 +97,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose }, }; - timelineContainer.Beatmap.BindTo(Beatmap); + timelineArea.Beatmap.BindTo(Beatmap); var ruleset = Beatmap.Value.BeatmapInfo.Ruleset?.CreateInstance(); if (ruleset == null) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs similarity index 96% rename from osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs rename to osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs index 95a8937b9b..6793c30409 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs @@ -12,13 +12,13 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { - public class TimelineContainer : CompositeDrawable + public class TimelineArea : CompositeDrawable { public readonly Bindable Beatmap = new Bindable(); private readonly Timeline timeline; - public TimelineContainer() + public TimelineArea() { Masking = true; CornerRadius = 5; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index 592419b336..a5be41bb9f 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private float startScrollOffset; /// - /// Transforms to a new value. + /// Transforms to a new value. /// /// The focus point in the waveform, in absolute coordinates local to the waveform. /// The size of the waveform. From 9b060b1bdf496cb45c742c679b1681297d14d48f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Apr 2018 15:51:40 +0900 Subject: [PATCH 14/53] Fix delay in value retrieval causing offsetting when zooming --- .../Timeline/ZoomableScrollContainer.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index a5be41bb9f..194b689f10 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline } private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth), newZoom, duration, easing)); + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth, Current), newZoom, duration, easing)); private class TransformZoom : Transform { @@ -71,19 +71,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private readonly float waveformSize; /// - /// The scroll offset at the start time of the transform/ + /// The scroll offset at the start of the transform. /// - private float startScrollOffset; + private readonly float scrollOffset; /// /// Transforms to a new value. /// /// The focus point in the waveform, in absolute coordinates local to the waveform. /// The size of the waveform. - public TransformZoom(float focusPoint, float waveformSize) + /// The scroll offset at the start of the transform. + public TransformZoom(float focusPoint, float waveformSize, float scrollOffset) { this.focusPoint = focusPoint; this.waveformSize = waveformSize; + this.scrollOffset = scrollOffset; } public override string TargetMember => nameof(currentZoom); @@ -100,7 +102,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { float newZoom = valueAt(time); - float focusOffset = focusPoint - startScrollOffset; + float focusOffset = focusPoint - scrollOffset; float expectedWidth = d.DrawWidth * newZoom; float targetOffset = expectedWidth * (focusPoint / waveformSize) - focusOffset; @@ -108,11 +110,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline d.ScrollTo(targetOffset, false); } - protected override void ReadIntoStartValue(ZoomableScrollContainer d) - { - startScrollOffset = d.Current; - StartValue = d.currentZoom; - } + protected override void ReadIntoStartValue(ZoomableScrollContainer d) => StartValue = d.currentZoom; } } } From f07928446d59d1199101f522baf4838e29e3c01f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 6 Apr 2018 15:52:39 +0900 Subject: [PATCH 15/53] Remove instances of "waveform" --- .../Compose/Timeline/ZoomableScrollContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index 194b689f10..ee5d336419 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -61,14 +61,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline private class TransformZoom : Transform { /// - /// The focus point in the waveform, in absolute coordinates local to the waveform. + /// The focus point in absolute coordinates local to the content. /// private readonly float focusPoint; /// - /// The size of the waveform. + /// The size of the content. /// - private readonly float waveformSize; + private readonly float contentSize; /// /// The scroll offset at the start of the transform. @@ -78,13 +78,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline /// /// Transforms to a new value. /// - /// The focus point in the waveform, in absolute coordinates local to the waveform. - /// The size of the waveform. + /// The focus point in absolute coordinates local to the content. + /// The size of the content. /// The scroll offset at the start of the transform. - public TransformZoom(float focusPoint, float waveformSize, float scrollOffset) + public TransformZoom(float focusPoint, float contentSize, float scrollOffset) { this.focusPoint = focusPoint; - this.waveformSize = waveformSize; + this.contentSize = contentSize; this.scrollOffset = scrollOffset; } @@ -104,7 +104,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline float focusOffset = focusPoint - scrollOffset; float expectedWidth = d.DrawWidth * newZoom; - float targetOffset = expectedWidth * (focusPoint / waveformSize) - focusOffset; + float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset; d.currentZoom = newZoom; d.ScrollTo(targetOffset, false); From bc3d195aa21361f86490c7bd86f1f099c94fc00b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 May 2018 13:05:58 +0900 Subject: [PATCH 16/53] Fix line endings --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 78 +++--- .../Screens/Compose/Timeline/TimelineArea.cs | 264 +++++++++--------- .../Timeline/ZoomableScrollContainer.cs | 232 +++++++-------- 3 files changed, 287 insertions(+), 287 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index f1086e2cf6..a9de155df8 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -1,39 +1,39 @@ -// Copyright (c) 2007-2018 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.Beatmaps; -using osu.Game.Graphics; - -namespace osu.Game.Screens.Edit.Screens.Compose.Timeline -{ - public class Timeline : ZoomableScrollContainer - { - public readonly Bindable WaveformVisible = new Bindable(); - public readonly Bindable Beatmap = new Bindable(); - - public Timeline() - { - BeatmapWaveformGraph waveform; - Child = waveform = new BeatmapWaveformGraph - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222"), - Depth = float.MaxValue - }; - - waveform.Beatmap.BindTo(Beatmap); - - WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); - } - - protected override void Update() - { - base.Update(); - - // We want time = 0 to be at the centre of the container when scrolled to the start - Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; - } - } -} +// Copyright (c) 2007-2018 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.Beatmaps; +using osu.Game.Graphics; + +namespace osu.Game.Screens.Edit.Screens.Compose.Timeline +{ + public class Timeline : ZoomableScrollContainer + { + public readonly Bindable WaveformVisible = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); + + public Timeline() + { + BeatmapWaveformGraph waveform; + Child = waveform = new BeatmapWaveformGraph + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("222"), + Depth = float.MaxValue + }; + + waveform.Beatmap.BindTo(Beatmap); + + WaveformVisible.ValueChanged += visible => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint); + } + + protected override void Update() + { + base.Update(); + + // We want time = 0 to be at the centre of the container when scrolled to the start + Content.Margin = new MarginPadding { Horizontal = DrawWidth / 2 }; + } + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs index 6793c30409..9b6b0bd48d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineArea.cs @@ -1,132 +1,132 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; - -namespace osu.Game.Screens.Edit.Screens.Compose.Timeline -{ - public class TimelineArea : CompositeDrawable - { - public readonly Bindable Beatmap = new Bindable(); - - private readonly Timeline timeline; - - public TimelineArea() - { - Masking = true; - CornerRadius = 5; - - OsuCheckbox hitObjectsCheckbox; - OsuCheckbox hitSoundsCheckbox; - OsuCheckbox waveformCheckbox; - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("111") - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("222") - }, - new FillFlowContainer - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AutoSizeAxes = Axes.Y, - Width = 160, - Padding = new MarginPadding { Horizontal = 15 }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 4), - Children = new[] - { - hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hitobjects" }, - hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hitsounds" }, - waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } - } - } - } - }, - new Container - { - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex("333") - }, - new Container - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - Children = new[] - { - new TimelineButton - { - RelativeSizeAxes = Axes.Y, - Height = 0.5f, - Icon = FontAwesome.fa_search_plus, - Action = () => timeline.Zoom++ - }, - new TimelineButton - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Y, - Height = 0.5f, - Icon = FontAwesome.fa_search_minus, - Action = () => timeline.Zoom-- - }, - } - } - } - }, - timeline = new Timeline { RelativeSizeAxes = Axes.Both } - }, - }, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed), - } - } - }; - - hitObjectsCheckbox.Current.Value = true; - hitSoundsCheckbox.Current.Value = true; - waveformCheckbox.Current.Value = true; - - timeline.Beatmap.BindTo(Beatmap); - timeline.WaveformVisible.BindTo(waveformCheckbox.Current); - } - } -} +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Edit.Screens.Compose.Timeline +{ + public class TimelineArea : CompositeDrawable + { + public readonly Bindable Beatmap = new Bindable(); + + private readonly Timeline timeline; + + public TimelineArea() + { + Masking = true; + CornerRadius = 5; + + OsuCheckbox hitObjectsCheckbox; + OsuCheckbox hitSoundsCheckbox; + OsuCheckbox waveformCheckbox; + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("111") + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("222") + }, + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Y, + Width = 160, + Padding = new MarginPadding { Horizontal = 15 }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 4), + Children = new[] + { + hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hitobjects" }, + hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hitsounds" }, + waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" } + } + } + } + }, + new Container + { + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex("333") + }, + new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new[] + { + new TimelineButton + { + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + Icon = FontAwesome.fa_search_plus, + Action = () => timeline.Zoom++ + }, + new TimelineButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Y, + Height = 0.5f, + Icon = FontAwesome.fa_search_minus, + Action = () => timeline.Zoom-- + }, + } + } + } + }, + timeline = new Timeline { RelativeSizeAxes = Axes.Both } + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.Distributed), + } + } + }; + + hitObjectsCheckbox.Current.Value = true; + hitSoundsCheckbox.Current.Value = true; + waveformCheckbox.Current.Value = true; + + timeline.Beatmap.BindTo(Beatmap); + timeline.WaveformVisible.BindTo(waveformCheckbox.Current); + } + } +} diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index ee5d336419..545caf5166 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs @@ -1,116 +1,116 @@ -// 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 osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transforms; -using osu.Framework.Input; -using osu.Framework.MathUtils; -using OpenTK; - -namespace osu.Game.Screens.Edit.Screens.Compose.Timeline -{ - public class ZoomableScrollContainer : ScrollContainer - { - private readonly Container zoomedContent; - protected override Container Content => zoomedContent; - - private float currentZoom = 10; - - public ZoomableScrollContainer() - : base(Direction.Horizontal) - { - base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y }); - } - - /// - /// Gets or sets the content zoom of this . - /// - public int Zoom - { - get => zoomTarget; - set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); - } - - protected override void Update() - { - base.Update(); - - zoomedContent.Width = DrawWidth * currentZoom; - } - - protected override bool OnWheel(InputState state) - { - if (!state.Keyboard.ControlPressed) - return base.OnWheel(state); - - setZoomTarget(zoomTarget + state.Mouse.WheelDelta, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); - return true; - } - - private int zoomTarget = 10; - private void setZoomTarget(int newZoom, float focusPoint) - { - zoomTarget = MathHelper.Clamp(newZoom, 1, 60); - transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); - } - - private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) - => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth, Current), newZoom, duration, easing)); - - private class TransformZoom : Transform - { - /// - /// The focus point in absolute coordinates local to the content. - /// - private readonly float focusPoint; - - /// - /// The size of the content. - /// - private readonly float contentSize; - - /// - /// The scroll offset at the start of the transform. - /// - private readonly float scrollOffset; - - /// - /// Transforms to a new value. - /// - /// The focus point in absolute coordinates local to the content. - /// The size of the content. - /// The scroll offset at the start of the transform. - public TransformZoom(float focusPoint, float contentSize, float scrollOffset) - { - this.focusPoint = focusPoint; - this.contentSize = contentSize; - this.scrollOffset = scrollOffset; - } - - public override string TargetMember => nameof(currentZoom); - - private float valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - protected override void Apply(ZoomableScrollContainer d, double time) - { - float newZoom = valueAt(time); - - float focusOffset = focusPoint - scrollOffset; - float expectedWidth = d.DrawWidth * newZoom; - float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset; - - d.currentZoom = newZoom; - d.ScrollTo(targetOffset, false); - } - - protected override void ReadIntoStartValue(ZoomableScrollContainer d) => StartValue = d.currentZoom; - } - } -} +// 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 osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using OpenTK; + +namespace osu.Game.Screens.Edit.Screens.Compose.Timeline +{ + public class ZoomableScrollContainer : ScrollContainer + { + private readonly Container zoomedContent; + protected override Container Content => zoomedContent; + + private float currentZoom = 10; + + public ZoomableScrollContainer() + : base(Direction.Horizontal) + { + base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y }); + } + + /// + /// Gets or sets the content zoom of this . + /// + public int Zoom + { + get => zoomTarget; + set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); + } + + protected override void Update() + { + base.Update(); + + zoomedContent.Width = DrawWidth * currentZoom; + } + + protected override bool OnWheel(InputState state) + { + if (!state.Keyboard.ControlPressed) + return base.OnWheel(state); + + setZoomTarget(zoomTarget + state.Mouse.WheelDelta, zoomedContent.ToLocalSpace(state.Mouse.NativeState.Position).X); + return true; + } + + private int zoomTarget = 10; + private void setZoomTarget(int newZoom, float focusPoint) + { + zoomTarget = MathHelper.Clamp(newZoom, 1, 60); + transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); + } + + private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) + => this.TransformTo(this.PopulateTransform(new TransformZoom(focusPoint, zoomedContent.DrawWidth, Current), newZoom, duration, easing)); + + private class TransformZoom : Transform + { + /// + /// The focus point in absolute coordinates local to the content. + /// + private readonly float focusPoint; + + /// + /// The size of the content. + /// + private readonly float contentSize; + + /// + /// The scroll offset at the start of the transform. + /// + private readonly float scrollOffset; + + /// + /// Transforms to a new value. + /// + /// The focus point in absolute coordinates local to the content. + /// The size of the content. + /// The scroll offset at the start of the transform. + public TransformZoom(float focusPoint, float contentSize, float scrollOffset) + { + this.focusPoint = focusPoint; + this.contentSize = contentSize; + this.scrollOffset = scrollOffset; + } + + public override string TargetMember => nameof(currentZoom); + + private float valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + protected override void Apply(ZoomableScrollContainer d, double time) + { + float newZoom = valueAt(time); + + float focusOffset = focusPoint - scrollOffset; + float expectedWidth = d.DrawWidth * newZoom; + float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset; + + d.currentZoom = newZoom; + d.ScrollTo(targetOffset, false); + } + + protected override void ReadIntoStartValue(ZoomableScrollContainer d) => StartValue = d.currentZoom; + } + } +} From 82607b3eb302f6c1689e84c3de226adf1bd679f8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 May 2018 17:53:09 +0900 Subject: [PATCH 17/53] Expose properties to control zoom --- .../Edit/Screens/Compose/Timeline/Timeline.cs | 4 ++ .../Timeline/ZoomableScrollContainer.cs | 70 +++++++++++++++++-- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs index a9de155df8..9801ba12a1 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/Timeline.cs @@ -15,6 +15,10 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline public Timeline() { + ZoomDuration = 200; + ZoomEasing = Easing.OutQuint; + Zoom = 10; + BeatmapWaveformGraph waveform; Child = waveform = new BeatmapWaveformGraph { diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs index 545caf5166..72faf657ce 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ZoomableScrollContainer.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.Framework.Graphics.Transforms; @@ -12,10 +13,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline { public class ZoomableScrollContainer : ScrollContainer { + /// + /// The time to zoom into/out of a point. + /// All user scroll input will be overwritten during the zoom transform. + /// + public double ZoomDuration; + + /// + /// The easing with which to transform the zoom. + /// + public Easing ZoomEasing; + private readonly Container zoomedContent; protected override Container Content => zoomedContent; - private float currentZoom = 10; + private float currentZoom = 1; public ZoomableScrollContainer() : base(Direction.Horizontal) @@ -23,13 +35,59 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y }); } + private int minZoom = 1; + /// - /// Gets or sets the content zoom of this . + /// The minimum zoom level allowed. + /// + public int MinZoom + { + get => minZoom; + set + { + if (value < 1) + throw new ArgumentException($"{nameof(MinZoom)} must be >= 1.", nameof(value)); + minZoom = value; + + if (Zoom < value) + Zoom = value; + } + } + + private int maxZoom = 60; + + /// + /// The maximum zoom level allowed. + /// + public int MaxZoom + { + get => maxZoom; + set + { + if (value < 1) + throw new ArgumentException($"{nameof(MaxZoom)} must be >= 1.", nameof(value)); + maxZoom = value; + + if (Zoom > value) + Zoom = value; + } + } + + /// + /// Gets or sets the content zoom level of this . /// public int Zoom { get => zoomTarget; - set => setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); + set + { + value = MathHelper.Clamp(value, MinZoom, MaxZoom); + + if (IsLoaded) + setZoomTarget(value, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X); + else + currentZoom = zoomTarget = value; + } } protected override void Update() @@ -48,11 +106,11 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Timeline return true; } - private int zoomTarget = 10; + private int zoomTarget = 1; private void setZoomTarget(int newZoom, float focusPoint) { - zoomTarget = MathHelper.Clamp(newZoom, 1, 60); - transformZoomTo(zoomTarget, focusPoint, 200, Easing.OutQuint); + zoomTarget = MathHelper.Clamp(newZoom, MinZoom, MaxZoom); + transformZoomTo(zoomTarget, focusPoint, ZoomDuration, ZoomEasing); } private void transformZoomTo(int newZoom, float focusPoint, double duration = 0, Easing easing = Easing.None) From 757f89871819a1164e778ae544c3d6d81d7e79e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 May 2018 17:53:19 +0900 Subject: [PATCH 18/53] Add testcase for zoomable scroll container --- .../Visual/TestCaseZoomableScrollContainer.cs | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs diff --git a/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs new file mode 100644 index 0000000000..06ec9ec63c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseZoomableScrollContainer.cs @@ -0,0 +1,142 @@ +// 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.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Shapes; +using osu.Framework.MathUtils; +using osu.Game.Graphics; +using osu.Game.Graphics.Cursor; +using osu.Game.Screens.Edit.Screens.Compose.Timeline; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseZoomableScrollContainer : ManualInputManagerTestCase + { + private readonly ZoomableScrollContainer scrollContainer; + private readonly Drawable innerBox; + + public TestCaseZoomableScrollContainer() + { + Children = new Drawable[] + { + new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Height = 250, + Width = 0.75f, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(30) + }, + scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both } + } + }, + new MenuCursor() + }; + + scrollContainer.Add(innerBox = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(new Color4(0.8f, 0.6f, 0.4f, 1f), new Color4(0.4f, 0.6f, 0.8f, 1f)) + }); + } + + [Test] + public void TestZoom0() + { + reset(); + AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); + AddAssert("Box width = 1x", () => Precision.AlmostEquals(boxQuad.Size, scrollQuad.Size)); + } + + [Test] + public void TestZoom10() + { + reset(); + AddStep("Set zoom = 10", () => scrollContainer.Zoom = 10); + AddAssert("Box at 1/2", () => Precision.AlmostEquals(boxQuad.Centre, scrollQuad.Centre)); + AddAssert("Box width = 10x", () => Precision.AlmostEquals(boxQuad.Size.X, 10 * scrollQuad.Size.X)); + } + + [Test] + public void TestMouseZoomInOnceOutOnce() + { + reset(); + + // Scroll in at 0.25 + AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by 3", () => InputManager.ScrollBy(3)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); + AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X)); + + // Scroll out at 0.25 + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by -3", () => InputManager.ScrollBy(-3)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); + AddAssert("Box 1/4 at 1/4", () => Precision.AlmostEquals(boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X)); + } + + [Test] + public void TestMouseZoomInTwiceOutTwice() + { + reset(); + + // Scroll in at 0.25 + AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by 1", () => InputManager.ScrollBy(1)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + + // Scroll in at 0.6 + AddStep("Move mouse to 0.75x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.75f * scrollQuad.Size.X, scrollQuad.Centre.Y))); + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by 1", () => InputManager.ScrollBy(1)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddAssert("Box not at 0", () => !Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); + + // Very hard to determine actual position, so approximate + AddAssert("Box at correct position (1)", () => Precision.DefinitelyBigger(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, boxQuad.TopLeft.X + 0.25f * boxQuad.Size.X)); + AddAssert("Box at correct position (2)", () => Precision.DefinitelyBigger(scrollQuad.TopLeft.X + 0.6f * scrollQuad.Size.X, boxQuad.TopLeft.X + 0.3f * boxQuad.Size.X)); + AddAssert("Box at correct position (3)", () => Precision.DefinitelyBigger(boxQuad.TopLeft.X + 0.6f * boxQuad.Size.X, scrollQuad.TopLeft.X + 0.6f * scrollQuad.Size.X)); + + // Scroll out at 0.6 + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by -1", () => InputManager.ScrollBy(-1)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + + // Scroll out at 0.25 + AddStep("Move mouse to 0.25x", () => InputManager.MoveMouseTo(new Vector2(scrollQuad.TopLeft.X + 0.25f * scrollQuad.Size.X, scrollQuad.Centre.Y))); + AddStep("Press ctrl", () => InputManager.PressKey(Key.LControl)); + AddStep("Scroll by -1", () => InputManager.ScrollBy(-1)); + AddStep("Release ctrl", () => InputManager.ReleaseKey(Key.LControl)); + AddAssert("Box at 0", () => Precision.AlmostEquals(boxQuad.TopLeft, scrollQuad.TopLeft)); + } + + private void reset() + { + AddStep("Reset", () => + { + scrollContainer.Zoom = 0; + scrollContainer.ScrollTo(0, false); + }); + } + + private Quad scrollQuad => scrollContainer.ScreenSpaceDrawQuad; + private Quad boxQuad => innerBox.ScreenSpaceDrawQuad; + } +} From f50c1c78a25a719f1b1c1cf4ac072a991013d8f0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 18 May 2018 18:14:12 +0900 Subject: [PATCH 19/53] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index fac688633b..8f007de13e 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fac688633b8fcf34ae5d0514c26b03e217161eb4 +Subproject commit 8f007de13e4a1aed46cb35e5018448f809bd5e88 From a7bdaf75b0731125ddda2a5b7a3d84680279ceaf Mon Sep 17 00:00:00 2001 From: jorolf Date: Tue, 22 May 2018 13:05:15 +0200 Subject: [PATCH 20/53] Ensure badges are ordered correctly --- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index 36a9a9b01a..c97a4de464 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -113,7 +113,11 @@ namespace osu.Game.Overlays.Profile.Header { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - }, badgeFlowContainer.Add); + }, asyncBadge => + { + badgeFlowContainer.Add(asyncBadge); + badgeFlowContainer.ChangeChildDepth(asyncBadge, Array.IndexOf(badges, asyncBadge)); //Ensure the badges are ordered correctly + }); } } From 2ccffb9ac452b443c9cb09ccf44f158cd04031ee Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 28 May 2018 01:10:41 +0900 Subject: [PATCH 21/53] Add difficulty calculation mod types --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 94 ++++++++++++++++++++++++- osu.Game.Rulesets.Osu/OsuRuleset.cs | 44 +++++++++++- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 44 +++++++++++- osu.Game/Rulesets/Mods/ModType.cs | 1 + 4 files changed, 175 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 02ecb3afda..08fecacbab 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -96,6 +96,20 @@ namespace osu.Game.Rulesets.Mania yield return new ManiaModSuddenDeath(); } + private static readonly Mod[] key_mods = + { + new MultiMod(), + new ManiaModKey1(), + new ManiaModKey2(), + new ManiaModKey3(), + new ManiaModKey4(), + new ManiaModKey5(), + new ManiaModKey6(), + new ManiaModKey7(), + new ManiaModKey8(), + new ManiaModKey9(), + }; + public override IEnumerable GetModsFor(ModType type) { switch (type) @@ -114,7 +128,6 @@ namespace osu.Game.Rulesets.Mania }, }, }; - case ModType.DifficultyIncrease: return new Mod[] { @@ -145,7 +158,6 @@ namespace osu.Game.Rulesets.Mania }, new ManiaModFlashlight(), }; - case ModType.Special: return new Mod[] { @@ -176,7 +188,85 @@ namespace osu.Game.Rulesets.Mania }, }, }; + case ModType.DifficultyCalculation: + var mods = new List(); + foreach (var keyMod in key_mods) + { + mods.AddRange(new[] + { + keyMod, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModDoubleTime(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModHalfTime(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModEasy(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModHardRock(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModEasy(), + new ManiaModDoubleTime(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModEasy(), + new ManiaModHalfTime(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModHardRock(), + new ManiaModDoubleTime(), + } + }, + new MultiMod + { + Mods = new[] + { + keyMod, + new ManiaModHardRock(), + new ManiaModHalfTime(), + } + }, + }); + } + return mods.ToArray(); default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c455bb2af6..31eff5493b 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -102,7 +102,6 @@ namespace osu.Game.Rulesets.Osu }, }, }; - case ModType.DifficultyIncrease: return new Mod[] { @@ -126,7 +125,6 @@ namespace osu.Game.Rulesets.Osu new OsuModHidden(), new OsuModFlashlight(), }; - case ModType.Special: return new Mod[] { @@ -143,7 +141,47 @@ namespace osu.Game.Rulesets.Osu }, new OsuModTarget(), }; - + case ModType.DifficultyCalculation: + return new Mod[] + { + new MultiMod(), + new OsuModDoubleTime(), + new OsuModHalfTime(), + new OsuModEasy(), + new OsuModHardRock(), + new MultiMod + { + Mods = new Mod[] + { + new OsuModEasy(), + new OsuModDoubleTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new OsuModEasy(), + new OsuModHalfTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new OsuModHardRock(), + new OsuModDoubleTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new OsuModHardRock(), + new OsuModHalfTime(), + } + }, + }; default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index abaa8db597..a249646285 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -93,7 +93,6 @@ namespace osu.Game.Rulesets.Taiko }, }, }; - case ModType.DifficultyIncrease: return new Mod[] { @@ -117,7 +116,6 @@ namespace osu.Game.Rulesets.Taiko new TaikoModHidden(), new TaikoModFlashlight(), }; - case ModType.Special: return new Mod[] { @@ -133,7 +131,47 @@ namespace osu.Game.Rulesets.Taiko }, }, }; - + case ModType.DifficultyCalculation: + return new Mod[] + { + new MultiMod(), + new TaikoModDoubleTime(), + new TaikoModHalfTime(), + new TaikoModEasy(), + new TaikoModHardRock(), + new MultiMod + { + Mods = new Mod[] + { + new TaikoModEasy(), + new TaikoModDoubleTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new TaikoModEasy(), + new TaikoModHalfTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new TaikoModHardRock(), + new TaikoModDoubleTime(), + } + }, + new MultiMod + { + Mods = new Mod[] + { + new TaikoModHardRock(), + new TaikoModHalfTime(), + } + }, + }; default: return new Mod[] { }; } diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 1941724879..5619899c48 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -8,5 +8,6 @@ namespace osu.Game.Rulesets.Mods DifficultyReduction, DifficultyIncrease, Special, + DifficultyCalculation } } From 7b7236929a0e2166b94d6f66eb6bbdc0334eb588 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 06:08:39 -0300 Subject: [PATCH 22/53] Add BeatmapSetDownloadButton. --- .../UserInterface/BeatmapSetDownloadButton.cs | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs new file mode 100644 index 0000000000..091b0ddbd4 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs @@ -0,0 +1,83 @@ +// 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.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Input; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Online.API; + +namespace osu.Game.Graphics.UserInterface +{ + public abstract class BeatmapSetDownloadButton : OsuClickableContainer + { + private readonly BeatmapSetInfo set; + private readonly bool noVideo; + private readonly BindableBool downloaded = new BindableBool(); + + private Action action; + public Action Action + { + get => action; + set => action = value; + } + + protected BeatmapSetDownloadButton(BeatmapSetInfo set, bool noVideo = false) + { + this.set = set; + this.noVideo = noVideo; + + downloaded.ValueChanged += e => + { + if (e) + Disable(); + else + Enable(); + }; + } + + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps, APIAccess api) + { + beatmaps.ItemAdded += s => + { + if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + downloaded.Value = true; + }; + + beatmaps.ItemRemoved += s => + { + if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + downloaded.Value = false; + }; + + // initial downloaded value + downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; + + Action = () => + { + if (beatmaps.GetExistingDownload(set) != null) + { + AlreadyDownloading(); + return; + } + + beatmaps.Download(set, noVideo); + }; + } + + protected override bool OnClick(InputState state) + { + if (!downloaded.Value) + Action?.Invoke(); + return true; + } + + protected abstract void Enable(); + protected abstract void Disable(); + protected abstract void AlreadyDownloading(); + } +} From b332c22fe5c418438cd70fc72c1c6afe0a363062 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 06:29:35 -0300 Subject: [PATCH 23/53] Update DirectPanel to use BeatmapSetDownloadButton. --- osu.Game/Overlays/Direct/DirectGridPanel.cs | 3 +-- osu.Game/Overlays/Direct/DirectListPanel.cs | 3 +-- osu.Game/Overlays/Direct/DirectPanel.cs | 16 -------------- osu.Game/Overlays/Direct/DownloadButton.cs | 21 ++++++++++++++++--- osu.Game/Overlays/DirectOverlay.cs | 23 +-------------------- 5 files changed, 21 insertions(+), 45 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index ed4630a8e7..723e9e8b35 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -166,14 +166,13 @@ namespace osu.Game.Overlays.Direct }, }, }, - new DownloadButton + new DownloadButton(SetInfo) { Size = new Vector2(30), Margin = new MarginPadding(horizontal_padding), Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Colour = colours.Gray5, - Action = StartDownload }, }, }, diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 13398a4a32..c949e0d088 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -144,12 +144,11 @@ namespace osu.Game.Overlays.Direct }, }, }, - new DownloadButton + new DownloadButton(SetInfo) { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Size = new Vector2(height - vertical_padding * 2), - Action = StartDownload }, }, }, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index df784252ce..e767f6ec83 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -147,22 +147,6 @@ namespace osu.Game.Overlays.Direct protected void ShowInformation() => beatmapSetOverlay?.ShowBeatmapSet(SetInfo); - protected void StartDownload() - { - if (beatmaps.GetExistingDownload(SetInfo) != null) - { - // we already have an active download running. - content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine).Then(); - - return; - } - - beatmaps.Download(SetInfo); - } - private void attachDownload(DownloadBeatmapSetRequest request) { if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index f01c9dac59..a6d7a4215d 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -3,17 +3,18 @@ using osu.Framework.Graphics; using osu.Framework.Input; +using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using OpenTK; namespace osu.Game.Overlays.Direct { - public class DownloadButton : OsuClickableContainer + public class DownloadButton : BeatmapSetDownloadButton { private readonly SpriteIcon icon; - public DownloadButton() + public DownloadButton(BeatmapSetInfo set, bool noVideo = false) : base(set, noVideo) { Children = new Drawable[] { @@ -49,5 +50,19 @@ namespace osu.Game.Overlays.Direct { icon.ScaleTo(1f, 500, Easing.OutElastic); } + + protected override void Enable() + { + this.FadeIn(200); + } + + protected override void Disable() + { + this.FadeOut(200); + } + + protected override void AlreadyDownloading() + { + } } } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index f437546888..99f6de8559 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -28,7 +28,6 @@ namespace osu.Game.Overlays private APIAccess api; private RulesetStore rulesets; - private BeatmapManager beatmaps; private readonly FillFlowContainer resultCountsContainer; private readonly OsuSpriteText resultCountsText; @@ -181,20 +180,10 @@ namespace osu.Game.Overlays { this.api = api; this.rulesets = rulesets; - this.beatmaps = beatmaps; resultCountsContainer.Colour = colours.Yellow; - - beatmaps.ItemAdded += setAdded; } - private void setAdded(BeatmapSetInfo set) => Schedule(() => - { - // if a new map was imported, we should remove it from search results (download completed etc.) - panels?.FirstOrDefault(p => p.SetInfo.OnlineBeatmapSetID == set.OnlineBeatmapSetID)?.FadeOut(400).Expire(); - BeatmapSets = BeatmapSets?.Where(b => b.OnlineBeatmapSetID != set.OnlineBeatmapSetID); - }); - private void updateResultCounts() { resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, Easing.OutQuint); @@ -297,9 +286,7 @@ namespace osu.Game.Overlays { Task.Run(() => { - var onlineIds = response.Select(r => r.OnlineBeatmapSetID).ToList(); - var presentOnlineIds = beatmaps.QueryBeatmapSets(s => onlineIds.Contains(s.OnlineBeatmapSetID) && !s.DeletePending).Select(r => r.OnlineBeatmapSetID).ToList(); - var sets = response.Select(r => r.ToBeatmapSet(rulesets)).Where(b => !presentOnlineIds.Contains(b.OnlineBeatmapSetID)).ToList(); + var sets = response.Select(r => r.ToBeatmapSet(rulesets)).ToList(); // may not need scheduling; loads async internally. Schedule(() => @@ -323,14 +310,6 @@ namespace osu.Game.Overlays private int distinctCount(List list) => list.Distinct().ToArray().Length; - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - if (beatmaps != null) - beatmaps.ItemAdded -= setAdded; - } - public class ResultCounts { public readonly int Artists; From 7eeba2cf9a83934a13aade4fcaecf3b7e4206203 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 06:34:48 -0300 Subject: [PATCH 24/53] Unsubscribe from BeatmapManager events in Dispose. --- .../UserInterface/BeatmapSetDownloadButton.cs | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs index 091b0ddbd4..39bbc8216a 100644 --- a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs @@ -18,6 +18,8 @@ namespace osu.Game.Graphics.UserInterface private readonly bool noVideo; private readonly BindableBool downloaded = new BindableBool(); + private BeatmapManager beatmaps; + private Action action; public Action Action { @@ -42,17 +44,10 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(BeatmapManager beatmaps, APIAccess api) { - beatmaps.ItemAdded += s => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - downloaded.Value = true; - }; + this.beatmaps = beatmaps; - beatmaps.ItemRemoved += s => - { - if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - downloaded.Value = false; - }; + beatmaps.ItemAdded += setAdded; + beatmaps.ItemRemoved += setRemoved; // initial downloaded value downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; @@ -76,8 +71,31 @@ namespace osu.Game.Graphics.UserInterface return true; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (beatmaps != null) + { + beatmaps.ItemAdded -= setAdded; + beatmaps.ItemRemoved -= setRemoved; + } + } + protected abstract void Enable(); protected abstract void Disable(); protected abstract void AlreadyDownloading(); + + private void setAdded(BeatmapSetInfo s) + { + if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + downloaded.Value = true; + } + + private void setRemoved(BeatmapSetInfo s) + { + if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) + downloaded.Value = false; + } } } From 416384956d1ac646b7c1fe48733652439f98abba Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 06:47:39 -0300 Subject: [PATCH 25/53] Use a protected Downloaded bindable instead of abstract methods. --- .../UserInterface/BeatmapSetDownloadButton.cs | 33 +++++-------------- osu.Game/Overlays/Direct/DownloadButton.cs | 22 +++++-------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs index 39bbc8216a..d55a133d18 100644 --- a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.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; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -16,29 +15,15 @@ namespace osu.Game.Graphics.UserInterface { private readonly BeatmapSetInfo set; private readonly bool noVideo; - private readonly BindableBool downloaded = new BindableBool(); private BeatmapManager beatmaps; - private Action action; - public Action Action - { - get => action; - set => action = value; - } + protected readonly BindableBool Downloaded = new BindableBool(); protected BeatmapSetDownloadButton(BeatmapSetInfo set, bool noVideo = false) { this.set = set; this.noVideo = noVideo; - - downloaded.ValueChanged += e => - { - if (e) - Disable(); - else - Enable(); - }; } [BackgroundDependencyLoader] @@ -49,8 +34,8 @@ namespace osu.Game.Graphics.UserInterface beatmaps.ItemAdded += setAdded; beatmaps.ItemRemoved += setRemoved; - // initial downloaded value - downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; + // initial value + Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; Action = () => { @@ -66,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(InputState state) { - if (!downloaded.Value) + if (Enabled.Value && !Downloaded.Value) Action?.Invoke(); return true; } @@ -82,20 +67,20 @@ namespace osu.Game.Graphics.UserInterface } } - protected abstract void Enable(); - protected abstract void Disable(); - protected abstract void AlreadyDownloading(); + protected virtual void AlreadyDownloading() + { + } private void setAdded(BeatmapSetInfo s) { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - downloaded.Value = true; + Downloaded.Value = true; } private void setRemoved(BeatmapSetInfo s) { if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) - downloaded.Value = false; + Downloaded.Value = false; } } } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index a6d7a4215d..1b072a4101 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -26,6 +26,14 @@ namespace osu.Game.Overlays.Direct Icon = FontAwesome.fa_osu_chevron_down_o, }, }; + + Downloaded.ValueChanged += e => + { + if (e) + this.FadeOut(200); + else + this.FadeIn(200); + }; } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) @@ -50,19 +58,5 @@ namespace osu.Game.Overlays.Direct { icon.ScaleTo(1f, 500, Easing.OutElastic); } - - protected override void Enable() - { - this.FadeIn(200); - } - - protected override void Disable() - { - this.FadeOut(200); - } - - protected override void AlreadyDownloading() - { - } } } From 4bdc1fb7816c17f5362585e25f6874e4fe590323 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 07:10:33 -0300 Subject: [PATCH 26/53] Remove unused using. --- osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs index d55a133d18..3b889746ab 100644 --- a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs @@ -7,7 +7,6 @@ using osu.Framework.Configuration; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; -using osu.Game.Online.API; namespace osu.Game.Graphics.UserInterface { @@ -27,7 +26,7 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, APIAccess api) + private void load(BeatmapManager beatmaps) { this.beatmaps = beatmaps; From 698a42f1454dc088004dcdeac29468d8ba8c449a Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 20:12:43 -0300 Subject: [PATCH 27/53] BeatmapSetDownloadButton -> BeatmapSetDownloader Allows it to integrate better with existing buttons, like HeaderButton. --- ...nloadButton.cs => BeatmapSetDownloader.cs} | 42 ++++++++----------- osu.Game/Overlays/Direct/DownloadButton.cs | 11 +++-- 2 files changed, 26 insertions(+), 27 deletions(-) rename osu.Game/Graphics/UserInterface/{BeatmapSetDownloadButton.cs => BeatmapSetDownloader.cs} (67%) diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs b/osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs similarity index 67% rename from osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs rename to osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs index 3b889746ab..4fe1527283 100644 --- a/osu.Game/Graphics/UserInterface/BeatmapSetDownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs @@ -1,25 +1,27 @@ // 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.Allocation; using osu.Framework.Configuration; -using osu.Framework.Input; +using osu.Framework.Graphics; using osu.Game.Beatmaps; -using osu.Game.Graphics.Containers; namespace osu.Game.Graphics.UserInterface { - public abstract class BeatmapSetDownloadButton : OsuClickableContainer + public class BeatmapSetDownloader : Drawable { private readonly BeatmapSetInfo set; private readonly bool noVideo; private BeatmapManager beatmaps; - protected readonly BindableBool Downloaded = new BindableBool(); + public readonly BindableBool Downloaded = new BindableBool(); - protected BeatmapSetDownloadButton(BeatmapSetInfo set, bool noVideo = false) + public event Action OnAlreadyDownloading; + + public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) { this.set = set; this.noVideo = noVideo; @@ -35,24 +37,6 @@ namespace osu.Game.Graphics.UserInterface // initial value Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; - - Action = () => - { - if (beatmaps.GetExistingDownload(set) != null) - { - AlreadyDownloading(); - return; - } - - beatmaps.Download(set, noVideo); - }; - } - - protected override bool OnClick(InputState state) - { - if (Enabled.Value && !Downloaded.Value) - Action?.Invoke(); - return true; } protected override void Dispose(bool isDisposing) @@ -66,8 +50,18 @@ namespace osu.Game.Graphics.UserInterface } } - protected virtual void AlreadyDownloading() + public void Download() { + if (Downloaded.Value) + return; + + if (beatmaps.GetExistingDownload(set) != null) + { + OnAlreadyDownloading?.Invoke(); + return; + } + + beatmaps.Download(set, noVideo); } private void setAdded(BeatmapSetInfo s) diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 1b072a4101..66bca9ed17 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -5,19 +5,22 @@ using osu.Framework.Graphics; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using OpenTK; namespace osu.Game.Overlays.Direct { - public class DownloadButton : BeatmapSetDownloadButton + public class DownloadButton : OsuClickableContainer { private readonly SpriteIcon icon; - public DownloadButton(BeatmapSetInfo set, bool noVideo = false) : base(set, noVideo) + public DownloadButton(BeatmapSetInfo set, bool noVideo = false) { + BeatmapSetDownloader downloader; Children = new Drawable[] { + downloader = new BeatmapSetDownloader(set, noVideo), icon = new SpriteIcon { Anchor = Anchor.Centre, @@ -27,7 +30,9 @@ namespace osu.Game.Overlays.Direct }, }; - Downloaded.ValueChanged += e => + Action = downloader.Download; + + downloader.Downloaded.ValueChanged += e => { if (e) this.FadeOut(200); From 9377ffb784641d4d825b2472208cd03e11471a6f Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 20:27:34 -0300 Subject: [PATCH 28/53] Update BeatmapSetOverlay to use BeatmapSetDownloader. --- .../BeatmapSet/Buttons/DownloadButton.cs | 16 ++++- osu.Game/Overlays/BeatmapSet/Header.cs | 70 +++++-------------- osu.Game/Overlays/Direct/DownloadButton.cs | 4 +- 3 files changed, 36 insertions(+), 54 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index c699ae2328..2dc0892704 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -3,18 +3,21 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using OpenTK; namespace osu.Game.Overlays.BeatmapSet.Buttons { public class DownloadButton : HeaderButton { - public DownloadButton(string title, string subtitle) + public DownloadButton(string title, string subtitle, BeatmapSetInfo set, bool noVideo = false) { Width = 120; + BeatmapSetDownloader downloader; Add(new Container { Depth = -1, @@ -22,6 +25,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Padding = new MarginPadding { Horizontal = 10 }, Children = new Drawable[] { + downloader = new BeatmapSetDownloader(set, noVideo), new FillFlowContainer { Anchor = Anchor.CentreLeft, @@ -54,6 +58,16 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }, }); + + Action = downloader.Download; + + downloader.Downloaded.ValueChanged += d => + { + if (d) + this.FadeOut(200); + else + this.FadeIn(200); + }; } } } diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 89c141ef17..a1ef82c995 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -35,8 +35,6 @@ namespace osu.Game.Overlays.BeatmapSet private readonly BeatmapSetOnlineStatusPill onlineStatusPill; public Details Details; - private BeatmapManager beatmaps; - public readonly BeatmapPicker Picker; private BeatmapSetInfo beatmapSet; @@ -68,8 +66,24 @@ namespace osu.Game.Overlays.BeatmapSet downloadButtonsContainer.FadeIn(transition_duration); favouriteButton.FadeIn(transition_duration); - noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration); - videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration); + if (BeatmapSet.OnlineInfo.HasVideo) + { + videoButtons.Children = new[] + { + new DownloadButton("Download", "with Video", BeatmapSet), + new DownloadButton("Download", "without Video", BeatmapSet, true), + }; + + videoButtons.FadeIn(transition_duration); + noVideoButtons.FadeOut(transition_duration); + } + else + { + noVideoButtons.Child = new DownloadButton("Download", string.Empty, BeatmapSet); + + noVideoButtons.FadeIn(transition_duration); + videoButtons.FadeOut(transition_duration); + } } else { @@ -192,27 +206,12 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.Both, Alpha = 0f, - Child = new DownloadButton("Download", @"") - { - Action = () => download(false), - }, }, videoButtons = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Spacing = new Vector2(buttons_spacing), Alpha = 0f, - Children = new[] - { - new DownloadButton("Download", "with Video") - { - Action = () => download(false), - }, - new DownloadButton("Download", "without Video") - { - Action = () => download(true), - }, - }, }, }, }, @@ -248,41 +247,10 @@ namespace osu.Game.Overlays.BeatmapSet } [BackgroundDependencyLoader] - private void load(OsuColour colours, BeatmapManager beatmaps) + private void load(OsuColour colours) { tabsBg.Colour = colours.Gray3; - this.beatmaps = beatmaps; - - beatmaps.ItemAdded += handleBeatmapAdd; - updateDisplay(); } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - if (beatmaps != null) beatmaps.ItemAdded -= handleBeatmapAdd; - } - - private void handleBeatmapAdd(BeatmapSetInfo beatmap) => Schedule(() => - { - if (beatmap.OnlineBeatmapSetID == BeatmapSet?.OnlineBeatmapSetID) - downloadButtonsContainer.FadeOut(transition_duration); - }); - - private void download(bool noVideo) - { - if (beatmaps.GetExistingDownload(BeatmapSet) != null) - { - downloadButtonsContainer.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine).Then(); - - return; - } - - beatmaps.Download(BeatmapSet, noVideo); - } } } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 66bca9ed17..e40b7ae0cb 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -32,9 +32,9 @@ namespace osu.Game.Overlays.Direct Action = downloader.Download; - downloader.Downloaded.ValueChanged += e => + downloader.Downloaded.ValueChanged += d => { - if (e) + if (d) this.FadeOut(200); else this.FadeIn(200); From 01c5060bcf0f5cb966d397711f82b937ebfba515 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 20:30:54 -0300 Subject: [PATCH 29/53] Move BeatmapSetDownloader to osu.Game.Beatmaps.Drawables --- .../Drawables}/BeatmapSetDownloader.cs | 3 +-- osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs | 2 +- osu.Game/Overlays/Direct/DownloadButton.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) rename osu.Game/{Graphics/UserInterface => Beatmaps/Drawables}/BeatmapSetDownloader.cs (96%) diff --git a/osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs similarity index 96% rename from osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs rename to osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 4fe1527283..e800eb5115 100644 --- a/osu.Game/Graphics/UserInterface/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -6,9 +6,8 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Game.Beatmaps; -namespace osu.Game.Graphics.UserInterface +namespace osu.Game.Beatmaps.Drawables { public class BeatmapSetDownloader : Drawable { diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 2dc0892704..310bfe3372 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -4,9 +4,9 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; using OpenTK; namespace osu.Game.Overlays.BeatmapSet.Buttons diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index e40b7ae0cb..a55a6507b9 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -4,9 +4,9 @@ using osu.Framework.Graphics; using osu.Framework.Input; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.UserInterface; using OpenTK; namespace osu.Game.Overlays.Direct From c524289b246a48e347f5031ca36647e09f23686d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 21:01:15 -0300 Subject: [PATCH 30/53] Update DirectListPanel to properly handle hiding DownloadButton. --- osu.Game/Overlays/Direct/DirectListPanel.cs | 98 ++++++++++++++------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index c949e0d088..6e3483604b 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -12,28 +12,31 @@ using osu.Game.Graphics.Sprites; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Game.Beatmaps; namespace osu.Game.Overlays.Direct { public class DirectListPanel : DirectPanel { + private const float transition_duration = 120; private const float horizontal_padding = 10; private const float vertical_padding = 5; private const float height = 70; + private PlayButton playButton; + private Box progressBar; + private Container downloadContainer; + + protected override PlayButton PlayButton => playButton; + protected override Box PreviewBar => progressBar; + public DirectListPanel(BeatmapSetInfo beatmap) : base(beatmap) { RelativeSizeAxes = Axes.X; Height = height; } - private PlayButton playButton; - private Box progressBar; - - protected override PlayButton PlayButton => playButton; - protected override Box PreviewBar => progressBar; - [BackgroundDependencyLoader] private void load(LocalisationEngine localisation, OsuColour colours) { @@ -59,7 +62,7 @@ namespace osu.Game.Overlays.Direct AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, LayoutEasing = Easing.OutQuint, - LayoutDuration = 120, + LayoutDuration = transition_duration, Spacing = new Vector2(10, 0), Children = new Drawable[] { @@ -104,52 +107,69 @@ namespace osu.Game.Overlays.Direct Anchor = Anchor.TopRight, Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Margin = new MarginPadding { Right = height - vertical_padding * 2 + vertical_padding }, + Direction = FillDirection.Horizontal, + LayoutEasing = Easing.OutQuint, + LayoutDuration = transition_duration, Children = new Drawable[] { - new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) + downloadContainer = new Container { - Margin = new MarginPadding { Right = 1 }, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Alpha = 0, + Child = new DownloadButton(SetInfo) + { + Size = new Vector2(height - vertical_padding * 2), + Margin = new MarginPadding { Left = vertical_padding }, + }, }, - new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Children = new[] + Direction = FillDirection.Vertical, + Children = new Drawable[] { - new OsuSpriteText + new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) { - Text = "mapped by ", - TextSize = 14, + Margin = new MarginPadding { Right = 1 }, + }, + new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), + new FillFlowContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new OsuSpriteText + { + Text = "mapped by ", + TextSize = 14, + }, + new OsuSpriteText + { + Text = SetInfo.Metadata.Author.Username, + TextSize = 14, + Font = @"Exo2.0-SemiBoldItalic", + }, + }, }, new OsuSpriteText { - Text = SetInfo.Metadata.Author.Username, + Text = $"from {SetInfo.Metadata.Source}", + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, TextSize = 14, - Font = @"Exo2.0-SemiBoldItalic", + Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, }, }, }, - new OsuSpriteText - { - Text = $"from {SetInfo.Metadata.Source}", - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - TextSize = 14, - Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f, - }, }, }, - new DownloadButton(SetInfo) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Size = new Vector2(height - vertical_padding * 2), - }, }, }, progressBar = new Box @@ -164,5 +184,17 @@ namespace osu.Game.Overlays.Direct }, }); } + + protected override bool OnHover(InputState state) + { + downloadContainer.FadeIn(transition_duration, Easing.InOutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + downloadContainer.FadeOut(transition_duration, Easing.InOutQuint); + base.OnHoverLost(state); + } } } From 61e135841034da3b047a586bb2b3c9db4d8d67e0 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 21:07:17 -0300 Subject: [PATCH 31/53] Add OnAlreadyDownloading animations. --- osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs | 8 ++++++++ osu.Game/Overlays/Direct/DownloadButton.cs | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 310bfe3372..cf7d3cda5a 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -68,6 +68,14 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons else this.FadeIn(200); }; + + downloader.OnAlreadyDownloading += () => + { + Content.MoveToX(-5, 50, Easing.OutSine).Then() + .MoveToX(5, 100, Easing.InOutSine).Then() + .MoveToX(-5, 100, Easing.InOutSine).Then() + .MoveToX(0, 50, Easing.InSine); + }; } } } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index a55a6507b9..a621199916 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -39,6 +39,14 @@ namespace osu.Game.Overlays.Direct else this.FadeIn(200); }; + + downloader.OnAlreadyDownloading += () => + { + Content.MoveToX(-5, 50, Easing.OutSine).Then() + .MoveToX(5, 100, Easing.InOutSine).Then() + .MoveToX(-5, 100, Easing.InOutSine).Then() + .MoveToX(0, 50, Easing.InSine); + }; } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) From d8154f8cad5b243674c9c214e517021a0036596d Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 21:11:27 -0300 Subject: [PATCH 32/53] Fix BeatmapSetInfos with OnlineBeatmapSetID set to null being marked as downloaded. --- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index e800eb5115..cc4a9c6d15 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -35,7 +35,8 @@ namespace osu.Game.Beatmaps.Drawables beatmaps.ItemRemoved += setRemoved; // initial value - Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; + if (set.OnlineBeatmapSetID != null) + Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; } protected override void Dispose(bool isDisposing) From 4cf7a64636a0c354399dca8cc6fa93f81a00a3ea Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Mon, 4 Jun 2018 22:26:52 -0300 Subject: [PATCH 33/53] Remove unused parameter. --- osu.Game/Overlays/DirectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 99f6de8559..b33f271986 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -176,7 +176,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api, RulesetStore rulesets, BeatmapManager beatmaps) + private void load(OsuColour colours, APIAccess api, RulesetStore rulesets) { this.api = api; this.rulesets = rulesets; From 80951eae68f68449ce1d139f7284a5e9850f228a Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Tue, 5 Jun 2018 18:09:26 -0300 Subject: [PATCH 34/53] Inherit BeatmapSetDownloader from Component. --- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index cc4a9c6d15..779848dff6 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; namespace osu.Game.Beatmaps.Drawables { - public class BeatmapSetDownloader : Drawable + public class BeatmapSetDownloader : Component { private readonly BeatmapSetInfo set; private readonly bool noVideo; From 8274623ad6f691d62bdf4eee28808e3afb9588bb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Jun 2018 14:07:50 +0900 Subject: [PATCH 35/53] Cleanup multi mod constructions --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 36 ++----------- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 69 +++++-------------------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 36 ++----------- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 36 ++----------- osu.Game/Rulesets/Mods/MultiMod.cs | 12 ++++- 5 files changed, 37 insertions(+), 152 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 2325a8cad9..6a9f12e2f2 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -82,36 +82,15 @@ namespace osu.Game.Rulesets.Catch { new CatchModEasy(), new CatchModNoFail(), - new MultiMod - { - Mods = new Mod[] - { - new CatchModHalfTime(), - new CatchModDaycore(), - }, - }, + new MultiMod(new CatchModHalfTime(), new CatchModDaycore()) }; case ModType.DifficultyIncrease: return new Mod[] { new CatchModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new CatchModSuddenDeath(), - new CatchModPerfect(), - }, - }, - new MultiMod - { - Mods = new Mod[] - { - new CatchModDoubleTime(), - new CatchModNightcore(), - }, - }, + new MultiMod(new CatchModSuddenDeath(), new CatchModPerfect()), + new MultiMod(new CatchModDoubleTime(), new CatchModNightcore()), new CatchModHidden(), new CatchModFlashlight(), }; @@ -122,14 +101,7 @@ namespace osu.Game.Rulesets.Catch new CatchModRelax(), null, null, - new MultiMod - { - Mods = new Mod[] - { - new CatchModAutoplay(), - new ModCinema(), - }, - }, + new MultiMod(new CatchModAutoplay(), new ModCinema()), }; default: diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 08fecacbab..84cf9bc1d3 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -119,74 +119,33 @@ namespace osu.Game.Rulesets.Mania { new ManiaModEasy(), new ManiaModNoFail(), - new MultiMod - { - Mods = new Mod[] - { - new ManiaModHalfTime(), - new ManiaModDaycore(), - }, - }, + new MultiMod(new ManiaModHalfTime(), new ManiaModDaycore()), }; case ModType.DifficultyIncrease: return new Mod[] { new ManiaModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new ManiaModSuddenDeath(), - new ManiaModPerfect(), - }, - }, - new MultiMod - { - Mods = new Mod[] - { - new ManiaModDoubleTime(), - new ManiaModNightcore(), - }, - }, - new MultiMod - { - Mods = new Mod[] - { - new ManiaModFadeIn(), - new ManiaModHidden(), - } - }, + new MultiMod(new ManiaModSuddenDeath(), new ManiaModPerfect()), + new MultiMod(new ManiaModDoubleTime(), new ManiaModNightcore()), + new MultiMod(new ManiaModFadeIn(), new ManiaModHidden()), new ManiaModFlashlight(), }; case ModType.Special: return new Mod[] { - new MultiMod - { - Mods = new Mod[] - { - new ManiaModKey4(), - new ManiaModKey5(), - new ManiaModKey6(), - new ManiaModKey7(), - new ManiaModKey8(), - new ManiaModKey9(), - new ManiaModKey1(), - new ManiaModKey2(), - new ManiaModKey3(), - }, - }, + new MultiMod(new ManiaModKey4(), + new ManiaModKey5(), + new ManiaModKey6(), + new ManiaModKey7(), + new ManiaModKey8(), + new ManiaModKey9(), + new ManiaModKey1(), + new ManiaModKey2(), + new ManiaModKey3()), new ManiaModRandom(), new ManiaModDualStages(), new ManiaModMirror(), - new MultiMod - { - Mods = new Mod[] - { - new ManiaModAutoplay(), - new ModCinema(), - }, - }, + new MultiMod(new ManiaModAutoplay(), new ModCinema()), }; case ModType.DifficultyCalculation: var mods = new List(); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 31eff5493b..29cdb6cfb2 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -93,35 +93,14 @@ namespace osu.Game.Rulesets.Osu { new OsuModEasy(), new OsuModNoFail(), - new MultiMod - { - Mods = new Mod[] - { - new OsuModHalfTime(), - new OsuModDaycore(), - }, - }, + new MultiMod(new OsuModHalfTime(), new OsuModDaycore()), }; case ModType.DifficultyIncrease: return new Mod[] { new OsuModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new OsuModSuddenDeath(), - new OsuModPerfect(), - }, - }, - new MultiMod - { - Mods = new Mod[] - { - new OsuModDoubleTime(), - new OsuModNightcore(), - }, - }, + new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), + new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), new OsuModHidden(), new OsuModFlashlight(), }; @@ -131,14 +110,7 @@ namespace osu.Game.Rulesets.Osu new OsuModRelax(), new OsuModAutopilot(), new OsuModSpunOut(), - new MultiMod - { - Mods = new Mod[] - { - new OsuModAutoplay(), - new ModCinema(), - }, - }, + new MultiMod(new OsuModAutoplay(), new ModCinema()), new OsuModTarget(), }; case ModType.DifficultyCalculation: diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index a249646285..c8621066a8 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -84,35 +84,14 @@ namespace osu.Game.Rulesets.Taiko { new TaikoModEasy(), new TaikoModNoFail(), - new MultiMod - { - Mods = new Mod[] - { - new TaikoModHalfTime(), - new TaikoModDaycore(), - }, - }, + new MultiMod(new TaikoModHalfTime(), new TaikoModDaycore()), }; case ModType.DifficultyIncrease: return new Mod[] { new TaikoModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new TaikoModSuddenDeath(), - new TaikoModPerfect(), - }, - }, - new MultiMod - { - Mods = new Mod[] - { - new TaikoModDoubleTime(), - new TaikoModNightcore(), - }, - }, + new MultiMod(new TaikoModSuddenDeath(), new TaikoModPerfect()), + new MultiMod(new TaikoModDoubleTime(), new TaikoModDaycore()), new TaikoModHidden(), new TaikoModFlashlight(), }; @@ -122,14 +101,7 @@ namespace osu.Game.Rulesets.Taiko new TaikoModRelax(), null, null, - new MultiMod - { - Mods = new Mod[] - { - new TaikoModAutoplay(), - new ModCinema(), - }, - }, + new MultiMod(new TaikoModAutoplay(), new ModCinema()), }; case ModType.DifficultyCalculation: return new Mod[] diff --git a/osu.Game/Rulesets/Mods/MultiMod.cs b/osu.Game/Rulesets/Mods/MultiMod.cs index 3c90a4eedb..b65773e93f 100644 --- a/osu.Game/Rulesets/Mods/MultiMod.cs +++ b/osu.Game/Rulesets/Mods/MultiMod.cs @@ -1,6 +1,9 @@ // 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; + namespace osu.Game.Rulesets.Mods { public class MultiMod : Mod @@ -10,6 +13,13 @@ namespace osu.Game.Rulesets.Mods public override string Description => string.Empty; public override double ScoreMultiplier => 0; - public Mod[] Mods; + public Mod[] Mods { get; } + + public MultiMod(params Mod[] mods) + { + Mods = mods; + } + + public override Type[] IncompatibleMods => Mods.SelectMany(m => m.IncompatibleMods).ToArray(); } } From e19ca0c12011b86ca9cfb5093a04fe29e85172c2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Jun 2018 14:08:02 +0900 Subject: [PATCH 36/53] Add nomod mod type --- osu.Game/Rulesets/Mods/NoModMod.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 osu.Game/Rulesets/Mods/NoModMod.cs diff --git a/osu.Game/Rulesets/Mods/NoModMod.cs b/osu.Game/Rulesets/Mods/NoModMod.cs new file mode 100644 index 0000000000..dcab3538da --- /dev/null +++ b/osu.Game/Rulesets/Mods/NoModMod.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods +{ + /// + /// Indicates a type of mod that doesn't do anything. + /// + public sealed class NoModMod : Mod + { + public override string Name => "No Mod"; + public override string ShortenedName => "NM"; + public override double ScoreMultiplier => 1; + } +} From 35678237591c8ff22cb479c9f0c32130471e16cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 6 Jun 2018 14:18:38 +0900 Subject: [PATCH 37/53] Reverse order of exposed objects in HitObjectContainer Closes #2740. --- osu.Game.Rulesets.Mania/UI/Column.cs | 9 +++++++-- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 4 +--- osu.Game/Rulesets/Mods/ModHidden.cs | 3 +-- osu.Game/Rulesets/UI/HitObjectContainer.cs | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 28cd1b6b39..ff1b8e506a 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -265,8 +265,13 @@ namespace osu.Game.Rulesets.Mania.UI if (action != Action) return false; - var hitObject = HitObjects.Objects.LastOrDefault(h => h.HitObject.StartTime > Time.Current) ?? HitObjects.Objects.FirstOrDefault(); - hitObject?.PlaySamples(); + var nextObject = + HitObjects.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ?? + // fallback to non-alive objects to find next off-screen object + HitObjects.Objects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ?? + HitObjects.Objects.LastOrDefault(); + + nextObject?.PlaySamples(); return true; } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index b63f85623e..f2d5631e93 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -64,9 +64,7 @@ namespace osu.Game.Rulesets.Osu.UI public override void PostProcess() { - connectionLayer.HitObjects = HitObjects.Objects - .Select(d => d.HitObject) - .OrderBy(h => h.StartTime).OfType(); + connectionLayer.HitObjects = HitObjects.Objects.Select(d => d.HitObject).OfType(); } private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 45da628ce8..9b09f0bd6d 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -27,8 +27,7 @@ namespace osu.Game.Rulesets.Mods public virtual void ApplyToDrawableHitObjects(IEnumerable drawables) { - // todo: fix ordering of objects so we don't have to do this (#2740). - foreach (var d in drawables.Reverse().Skip(IncreaseFirstObjectVisibility ? 1 : 0)) + foreach (var d in drawables.Skip(IncreaseFirstObjectVisibility ? 1 : 0)) d.ApplyCustomUpdateState += ApplyHiddenState; } diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs index 1b6841c9bd..af18d98561 100644 --- a/osu.Game/Rulesets/UI/HitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.UI { public class HitObjectContainer : CompositeDrawable { - public virtual IEnumerable Objects => InternalChildren.Cast(); - public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + public IEnumerable Objects => InternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); + public IEnumerable AliveObjects => AliveInternalChildren.Cast().OrderBy(h => h.HitObject.StartTime); public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); From df4c855aa202f1949c769dc289e11c34d637760b Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Wed, 6 Jun 2018 03:13:37 -0300 Subject: [PATCH 38/53] Manage subtitle inside of DownloadButton. --- osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs | 9 +++++++-- osu.Game/Overlays/BeatmapSet/Header.cs | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index cf7d3cda5a..8c6c8dbaa1 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -13,10 +13,15 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public class DownloadButton : HeaderButton { - public DownloadButton(string title, string subtitle, BeatmapSetInfo set, bool noVideo = false) + public DownloadButton(BeatmapSetInfo set, bool noVideo = false) { Width = 120; + string subtitle = string.Empty; + + if (set.OnlineInfo.HasVideo) + subtitle = noVideo ? "without Video" : "with Video"; + BeatmapSetDownloader downloader; Add(new Container { @@ -36,7 +41,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { new OsuSpriteText { - Text = title, + Text = "Download", TextSize = 13, Font = @"Exo2.0-Bold", }, diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index a1ef82c995..afba99f928 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -70,8 +70,8 @@ namespace osu.Game.Overlays.BeatmapSet { videoButtons.Children = new[] { - new DownloadButton("Download", "with Video", BeatmapSet), - new DownloadButton("Download", "without Video", BeatmapSet, true), + new DownloadButton(BeatmapSet), + new DownloadButton(BeatmapSet, true), }; videoButtons.FadeIn(transition_duration); @@ -79,7 +79,7 @@ namespace osu.Game.Overlays.BeatmapSet } else { - noVideoButtons.Child = new DownloadButton("Download", string.Empty, BeatmapSet); + noVideoButtons.Child = new DownloadButton(BeatmapSet); noVideoButtons.FadeIn(transition_duration); videoButtons.FadeOut(transition_duration); From 188272e15d0d4730d14a1e9faac0fcc3db08424c Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Wed, 6 Jun 2018 03:18:42 -0300 Subject: [PATCH 39/53] Replace OnAlreadyDownloading with returning a bool from Download. --- .../Drawables/BeatmapSetDownloader.cs | 12 ++++-------- .../BeatmapSet/Buttons/DownloadButton.cs | 19 ++++++++++--------- osu.Game/Overlays/Direct/DownloadButton.cs | 19 ++++++++++--------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 779848dff6..0a322f5b72 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -18,8 +18,6 @@ namespace osu.Game.Beatmaps.Drawables public readonly BindableBool Downloaded = new BindableBool(); - public event Action OnAlreadyDownloading; - public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) { this.set = set; @@ -50,18 +48,16 @@ namespace osu.Game.Beatmaps.Drawables } } - public void Download() + public bool Download() { if (Downloaded.Value) - return; + return false; if (beatmaps.GetExistingDownload(set) != null) - { - OnAlreadyDownloading?.Invoke(); - return; - } + return false; beatmaps.Download(set, noVideo); + return true; } private void setAdded(BeatmapSetInfo s) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 8c6c8dbaa1..37fa562a73 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -64,7 +64,16 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, }); - Action = downloader.Download; + Action = () => + { + if (!downloader.Download()) + { + Content.MoveToX(-5, 50, Easing.OutSine).Then() + .MoveToX(5, 100, Easing.InOutSine).Then() + .MoveToX(-5, 100, Easing.InOutSine).Then() + .MoveToX(0, 50, Easing.InSine); + } + }; downloader.Downloaded.ValueChanged += d => { @@ -73,14 +82,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons else this.FadeIn(200); }; - - downloader.OnAlreadyDownloading += () => - { - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); - }; } } } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index a621199916..1ffa8dbd35 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -30,7 +30,16 @@ namespace osu.Game.Overlays.Direct }, }; - Action = downloader.Download; + Action = () => + { + if (!downloader.Download()) + { + Content.MoveToX(-5, 50, Easing.OutSine).Then() + .MoveToX(5, 100, Easing.InOutSine).Then() + .MoveToX(-5, 100, Easing.InOutSine).Then() + .MoveToX(0, 50, Easing.InSine); + } + }; downloader.Downloaded.ValueChanged += d => { @@ -39,14 +48,6 @@ namespace osu.Game.Overlays.Direct else this.FadeIn(200); }; - - downloader.OnAlreadyDownloading += () => - { - Content.MoveToX(-5, 50, Easing.OutSine).Then() - .MoveToX(5, 100, Easing.InOutSine).Then() - .MoveToX(-5, 100, Easing.InOutSine).Then() - .MoveToX(0, 50, Easing.InSine); - }; } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) From 7819be7957c3d78932f94dba178533760914d6f7 Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Wed, 6 Jun 2018 03:28:07 -0300 Subject: [PATCH 40/53] Remove unused using. --- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 0a322f5b72..df4847b5db 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.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; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; From 83ff47ec80ced52260d528ec0eccbf442896e704 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 6 Jun 2018 16:20:17 +0900 Subject: [PATCH 41/53] Rewrite difficulty mod combinations --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 3 - .../Difficulty/ManiaDifficultyCalculator.cs | 18 +++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 79 --------- osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs | 15 ++ .../Difficulty/OsuDifficultyCalculator.cs | 9 ++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 41 ----- .../Difficulty/TaikoDifficultyCalculator.cs | 9 ++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 41 ----- ...DifficultyAdjustmentModCombinationsTest.cs | 152 ++++++++++++++++++ .../Difficulty/DifficultyCalculator.cs | 39 +++++ osu.Game/Rulesets/Mods/ModType.cs | 3 +- 11 files changed, 243 insertions(+), 166 deletions(-) create mode 100644 osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 6a9f12e2f2..d0180f1791 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -84,7 +84,6 @@ namespace osu.Game.Rulesets.Catch new CatchModNoFail(), new MultiMod(new CatchModHalfTime(), new CatchModDaycore()) }; - case ModType.DifficultyIncrease: return new Mod[] { @@ -94,7 +93,6 @@ namespace osu.Game.Rulesets.Catch new CatchModHidden(), new CatchModFlashlight(), }; - case ModType.Special: return new Mod[] { @@ -103,7 +101,6 @@ namespace osu.Game.Rulesets.Catch null, new MultiMod(new CatchModAutoplay(), new ModCinema()), }; - default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index 2517839355..ca2002b7c9 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; @@ -141,5 +142,22 @@ namespace osu.Game.Rulesets.Mania.Difficulty return difficulty; } + + protected override Mod[] DifficultyAdjustmentMods => new Mod[] + { + new ManiaModDoubleTime(), + new ManiaModHalfTime(), + new ManiaModEasy(), + new ManiaModHardRock(), + new ManiaModKey1(), + new ManiaModKey2(), + new ManiaModKey3(), + new ManiaModKey4(), + new ManiaModKey5(), + new ManiaModKey6(), + new ManiaModKey7(), + new ManiaModKey8(), + new ManiaModKey9(), + }; } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 84cf9bc1d3..f6934484a2 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -147,85 +147,6 @@ namespace osu.Game.Rulesets.Mania new ManiaModMirror(), new MultiMod(new ManiaModAutoplay(), new ModCinema()), }; - case ModType.DifficultyCalculation: - var mods = new List(); - foreach (var keyMod in key_mods) - { - mods.AddRange(new[] - { - keyMod, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModDoubleTime(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModHalfTime(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModEasy(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModHardRock(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModEasy(), - new ManiaModDoubleTime(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModEasy(), - new ManiaModHalfTime(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModHardRock(), - new ManiaModDoubleTime(), - } - }, - new MultiMod - { - Mods = new[] - { - keyMod, - new ManiaModHardRock(), - new ManiaModHalfTime(), - } - }, - }); - } - - return mods.ToArray(); default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs index e02db68a28..6bfe295c3d 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -1,6 +1,8 @@ // 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.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mods; @@ -24,5 +26,18 @@ namespace osu.Game.Rulesets.Mania.Mods mbc.TargetColumns = KeyCount; } + + public override Type[] IncompatibleMods => new[] + { + typeof(ManiaModKey1), + typeof(ManiaModKey2), + typeof(ManiaModKey3), + typeof(ManiaModKey4), + typeof(ManiaModKey5), + typeof(ManiaModKey6), + typeof(ManiaModKey7), + typeof(ManiaModKey8), + typeof(ManiaModKey9), + }.Except(new[] { GetType() }).ToArray(); } } diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 3ed072a275..94d2afbf45 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Difficulty.Preprocessing; using osu.Game.Rulesets.Osu.Difficulty.Skills; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Difficulty @@ -71,5 +72,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty return starRating; } + + protected override Mod[] DifficultyAdjustmentMods => new Mod[] + { + new OsuModDoubleTime(), + new OsuModHalfTime(), + new OsuModEasy(), + new OsuModHardRock(), + }; } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 29cdb6cfb2..b920e889ce 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -113,47 +113,6 @@ namespace osu.Game.Rulesets.Osu new MultiMod(new OsuModAutoplay(), new ModCinema()), new OsuModTarget(), }; - case ModType.DifficultyCalculation: - return new Mod[] - { - new MultiMod(), - new OsuModDoubleTime(), - new OsuModHalfTime(), - new OsuModEasy(), - new OsuModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new OsuModEasy(), - new OsuModDoubleTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new OsuModEasy(), - new OsuModHalfTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new OsuModHardRock(), - new OsuModDoubleTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new OsuModHardRock(), - new OsuModHalfTime(), - } - }, - }; default: return new Mod[] { }; } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 57e1e65064..bb666eb528 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.Objects; namespace osu.Game.Rulesets.Taiko.Difficulty @@ -62,6 +63,14 @@ namespace osu.Game.Rulesets.Taiko.Difficulty return starRating; } + protected override Mod[] DifficultyAdjustmentMods => new Mod[] + { + new TaikoModDoubleTime(), + new TaikoModHalfTime(), + new TaikoModEasy(), + new TaikoModHardRock(), + }; + private bool calculateStrainValues() { // Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment. diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index c8621066a8..ccf28a2f12 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -103,47 +103,6 @@ namespace osu.Game.Rulesets.Taiko null, new MultiMod(new TaikoModAutoplay(), new ModCinema()), }; - case ModType.DifficultyCalculation: - return new Mod[] - { - new MultiMod(), - new TaikoModDoubleTime(), - new TaikoModHalfTime(), - new TaikoModEasy(), - new TaikoModHardRock(), - new MultiMod - { - Mods = new Mod[] - { - new TaikoModEasy(), - new TaikoModDoubleTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new TaikoModEasy(), - new TaikoModHalfTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new TaikoModHardRock(), - new TaikoModDoubleTime(), - } - }, - new MultiMod - { - Mods = new Mod[] - { - new TaikoModHardRock(), - new TaikoModHalfTime(), - } - }, - }; default: return new Mod[] { }; } diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs new file mode 100644 index 0000000000..fd697ba3d3 --- /dev/null +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -0,0 +1,152 @@ +// 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.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Tests.NonVisual +{ + [TestFixture] + public class DifficultyAdjustmentModCombinationsTest + { + [Test] + public void TestNoMods() + { + var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(1, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + } + + [Test] + public void TestSingleMod() + { + var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(2, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[1] is ModA); + } + + [Test] + public void TestDoubleMod() + { + var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(4, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[1] is ModA); + Assert.IsTrue(combinations[2] is MultiMod); + Assert.IsTrue(combinations[3] is ModB); + + Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); + Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); + } + + [Test] + public void TestIncompatibleMods() + { + var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(3, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[1] is ModA); + Assert.IsTrue(combinations[2] is ModIncompatibleWithA); + } + + [Test] + public void TestDoubleIncompatibleMods() + { + var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(8, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[1] is ModA); + Assert.IsTrue(combinations[2] is MultiMod); + Assert.IsTrue(combinations[3] is ModB); + Assert.IsTrue(combinations[4] is MultiMod); + Assert.IsTrue(combinations[5] is ModIncompatibleWithA); + Assert.IsTrue(combinations[6] is MultiMod); + Assert.IsTrue(combinations[7] is ModIncompatibleWithAAndB); + + Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); + Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); + Assert.IsTrue(((MultiMod)combinations[4]).Mods[0] is ModB); + Assert.IsTrue(((MultiMod)combinations[4]).Mods[1] is ModIncompatibleWithA); + Assert.IsTrue(((MultiMod)combinations[6]).Mods[0] is ModIncompatibleWithA); + Assert.IsTrue(((MultiMod)combinations[6]).Mods[1] is ModIncompatibleWithAAndB); + } + + [Test] + public void TestIncompatibleThroughBaseType() + { + var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); + + Assert.AreEqual(3, combinations.Length); + Assert.IsTrue(combinations[0] is NoModMod); + Assert.IsTrue(combinations[1] is ModAofA); + Assert.IsTrue(combinations[2] is ModIncompatibleWithAofA); + } + + private class ModA : Mod + { + public override string Name => nameof(ModA); + public override string ShortenedName => nameof(ModA); + public override double ScoreMultiplier => 1; + + public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) }; + } + + private class ModB : Mod + { + public override string Name => nameof(ModB); + public override string ShortenedName => nameof(ModB); + public override double ScoreMultiplier => 1; + + public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) }; + } + + private class ModIncompatibleWithA : Mod + { + public override string Name => $"Incompatible With {nameof(ModA)}"; + public override string ShortenedName => $"Incompatible With {nameof(ModA)}"; + public override double ScoreMultiplier => 1; + + public override Type[] IncompatibleMods => new[] { typeof(ModA) }; + } + + private class ModAofA : ModA + { + } + + private class ModIncompatibleWithAofA : ModIncompatibleWithA + { + // Incompatible through base type + } + + private class ModIncompatibleWithAAndB : Mod + { + public override string Name => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; + public override string ShortenedName => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; + public override double ScoreMultiplier => 1; + + public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; + } + + private class TestDifficultyCalculator : DifficultyCalculator + { + public TestDifficultyCalculator(params Mod[] mods) + : base(null) + { + DifficultyAdjustmentMods = mods; + } + + public override double Calculate(Dictionary categoryDifficulty = null) => throw new NotImplementedException(); + + protected override Mod[] DifficultyAdjustmentMods { get; } + } + } +} diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 070bc7ddb0..31cd9dc6f5 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.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.Collections.Generic; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; @@ -36,6 +37,44 @@ namespace osu.Game.Rulesets.Difficulty { } + /// + /// Creates all combinations which adjust the difficulty. + /// + public Mod[] CreateDifficultyAdjustmentModCombinations() + { + return createDifficultyAdjustmentModCombinations(Enumerable.Empty(), DifficultyAdjustmentMods).ToArray(); + + IEnumerable createDifficultyAdjustmentModCombinations(IEnumerable currentSet, Mod[] adjustmentSet, int currentSetCount = 0, int adjustmentSetStart = 0) + { + // Initial-case: Empty current set + if (currentSetCount == 0) + yield return new NoModMod(); + + if (currentSetCount == 1) + yield return currentSet.Single(); + + if (currentSetCount > 1) + yield return new MultiMod(currentSet.ToArray()); + + // Apply mods in the adjustment set recursively. Using the entire adjustment set would result in duplicate multi-mod mod + // combinations in further recursions, so a moving subset is used to eliminate this effect + for (int i = adjustmentSetStart; i < adjustmentSet.Length; i++) + { + var adjustmentMod = adjustmentSet[i]; + if (currentSet.Any(c => c.IncompatibleMods.Any(m => m.IsInstanceOfType(adjustmentMod)))) + continue; + + foreach (var combo in createDifficultyAdjustmentModCombinations(currentSet.Append(adjustmentMod), adjustmentSet, currentSetCount + 1, i + 1)) + yield return combo; + } + } + } + + /// + /// Retrieves all s which adjust the difficulty. + /// + protected virtual Mod[] DifficultyAdjustmentMods => Array.Empty(); + public abstract double Calculate(Dictionary categoryDifficulty = null); } } diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 5619899c48..913ba23701 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -7,7 +7,6 @@ namespace osu.Game.Rulesets.Mods { DifficultyReduction, DifficultyIncrease, - Special, - DifficultyCalculation + Special } } From 0b4f5af52e31c5088fa1edba366bbb931d830e8e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 03:17:12 +0900 Subject: [PATCH 42/53] Add setting to toggle standardised or exponential scoring display Also adjusts exponential scoring to be closer to stable. Log wasn't cutting it. --- osu.Game/Configuration/OsuConfigManager.cs | 6 +++++- .../Settings/Sections/Gameplay/GeneralSettings.cs | 6 ++++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 11 ++++++++--- osu.Game/Screens/Play/Player.cs | 1 + 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 597960c352..f7fe424aa9 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -5,6 +5,7 @@ using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Platform; using osu.Game.Overlays; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select; namespace osu.Game.Configuration @@ -80,6 +81,8 @@ namespace osu.Game.Configuration Set(OsuSetting.FloatingComments, false); + Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised); + Set(OsuSetting.SpeedChangeVisualisation, SpeedChangeVisualisationMethod.Sequential); Set(OsuSetting.IncreaseFirstObjectVisibility, true); @@ -147,6 +150,7 @@ namespace osu.Game.Configuration SongSelectRightMouseScroll, BeatmapSkins, BeatmapHitsounds, - IncreaseFirstObjectVisibility + IncreaseFirstObjectVisibility, + ScoreDisplayMode } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 647395cf69..9c8f5e2643 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -4,6 +4,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Configuration; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Overlays.Settings.Sections.Gameplay { @@ -38,6 +39,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Always show key overlay", Bindable = config.GetBindable(OsuSetting.KeyOverlay) }, + new SettingsEnumDropdown + { + LabelText = "Score display mode", + Bindable = config.GetBindable(OsuSetting.ScoreDisplayMode) + } }; } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 345930ed04..0568101aa7 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -65,6 +65,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableInt HighestCombo = new BindableInt(); + /// + /// The used to calculate scores. + /// + public readonly Bindable Mode = new Bindable(); + /// /// Whether all s have been processed. /// @@ -169,8 +174,6 @@ namespace osu.Game.Rulesets.Scoring private const double combo_portion = 0.7; private const double max_score = 1000000; - public readonly Bindable Mode = new Bindable(); - protected sealed override bool HasCompleted => JudgedHits == MaxHits; protected int MaxHits { get; private set; } @@ -202,6 +205,8 @@ namespace osu.Game.Rulesets.Scoring Mode.Value = ScoringMode.Exponential; Mode.Disabled = true; } + + Mode.ValueChanged += _ => updateScore(); } /// @@ -296,7 +301,7 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; break; case ScoringMode.Exponential: - TotalScore.Value = (baseScore + bonusScore) * Math.Log(HighestCombo + 1, 2); + TotalScore.Value = (baseScore + bonusScore) * Math.Max(0, HighestCombo - 1) / 25f; break; } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fe77f85a50..94d03be3c8 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -158,6 +158,7 @@ namespace osu.Game.Screens.Play userAudioOffset.TriggerChange(); ScoreProcessor = RulesetContainer.CreateScoreProcessor(); + ScoreProcessor.Mode.BindTo(config.GetBindable(OsuSetting.ScoreDisplayMode)); Children = new Drawable[] { From 0fae49ee21d28a24d9585f4e2cec830385463b4a Mon Sep 17 00:00:00 2001 From: DrabWeb Date: Thu, 7 Jun 2018 20:47:27 -0300 Subject: [PATCH 43/53] Don't add a 'with Video' subtitle. --- osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs index 37fa562a73..4fce6a49fb 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/DownloadButton.cs @@ -17,11 +17,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { Width = 120; - string subtitle = string.Empty; - - if (set.OnlineInfo.HasVideo) - subtitle = noVideo ? "without Video" : "with Video"; - BeatmapSetDownloader downloader; Add(new Container { @@ -47,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }, new OsuSpriteText { - Text = subtitle, + Text = set.OnlineInfo.HasVideo && noVideo ? "without Video" : string.Empty, TextSize = 11, Font = @"Exo2.0-Bold", }, From 4dfc328117ef886489825ea5770b1e137dfe330b Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Fri, 8 Jun 2018 17:46:38 +0900 Subject: [PATCH 44/53] Remove unused array --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index f6934484a2..5f803e3406 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -96,20 +96,6 @@ namespace osu.Game.Rulesets.Mania yield return new ManiaModSuddenDeath(); } - private static readonly Mod[] key_mods = - { - new MultiMod(), - new ManiaModKey1(), - new ManiaModKey2(), - new ManiaModKey3(), - new ManiaModKey4(), - new ManiaModKey5(), - new ManiaModKey6(), - new ManiaModKey7(), - new ManiaModKey8(), - new ManiaModKey9(), - }; - public override IEnumerable GetModsFor(ModType type) { switch (type) From 59e5a8556f91b3a47a3d8088c1041331a3c243df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 18:15:03 +0900 Subject: [PATCH 45/53] Fix volume control adjustment being extreme when precision scrolling --- osu.Game/Overlays/Volume/VolumeMeter.cs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Volume/VolumeMeter.cs b/osu.Game/Overlays/Volume/VolumeMeter.cs index 64106967f4..b2cf43704b 100644 --- a/osu.Game/Overlays/Volume/VolumeMeter.cs +++ b/osu.Game/Overlays/Volume/VolumeMeter.cs @@ -167,9 +167,25 @@ namespace osu.Game.Overlays.Volume private set => Bindable.Value = value; } - public void Increase() => Volume += 0.05f; + private const float adjust_step = 0.05f; - public void Decrease() => Volume -= 0.05f; + public void Increase() => adjust(1); + public void Decrease() => adjust(-1); + + private void adjust(int direction) + { + float amount = adjust_step * direction; + + var mouse = GetContainingInputManager().CurrentState.Mouse; + if (mouse.HasPreciseScroll) + { + float scrollDelta = mouse.ScrollDelta.Y; + if (scrollDelta != 0) + amount *= Math.Abs(scrollDelta / 10); + } + + Volume += amount; + } public bool OnPressed(GlobalAction action) { From 064e8190beebe798760b9fbb2de999fe1a8e8537 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 20:53:58 +0900 Subject: [PATCH 46/53] Add basic documentation --- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index df4847b5db..63c5c8b6e6 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -8,6 +8,9 @@ using osu.Framework.Graphics; namespace osu.Game.Beatmaps.Drawables { + /// + /// A component to allow downloading of a beatmap set. Automatically handles state syncing between other instances. + /// public class BeatmapSetDownloader : Component { private readonly BeatmapSetInfo set; @@ -15,6 +18,9 @@ namespace osu.Game.Beatmaps.Drawables private BeatmapManager beatmaps; + /// + /// Whether the associated beatmap set has been downloading (by this instance or any other instance). + /// public readonly BindableBool Downloaded = new BindableBool(); public BeatmapSetDownloader(BeatmapSetInfo set, bool noVideo = false) @@ -47,6 +53,10 @@ namespace osu.Game.Beatmaps.Drawables } } + /// + /// Begin downloading the associated beatmap set. + /// + /// True if downloading began. False if an existing download is active or completed. public bool Download() { if (Downloaded.Value) From ecc0f5e5756a6401be39c3f4ea96df270c089087 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 20:54:09 +0900 Subject: [PATCH 47/53] Use Any() instead of Count() --- osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs index 63c5c8b6e6..6acb58e165 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetDownloader.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.Drawables // initial value if (set.OnlineBeatmapSetID != null) - Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Count() != 0; + Downloaded.Value = beatmaps.QueryBeatmapSets(s => s.OnlineBeatmapSetID == set.OnlineBeatmapSetID && !s.DeletePending).Any(); } protected override void Dispose(bool isDisposing) From 9bdb3113ce0883afd6c1be0aa7f84153af381de3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 21:05:28 +0900 Subject: [PATCH 48/53] Revert "Always update children when ruleset input manager is updated" This reverts commit 4eb7a349442680ace0fb534b4f8bf5a03903c1b0. --- osu.Game/Rulesets/UI/RulesetInputManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index b35616985a..58a66a5224 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -121,6 +121,8 @@ namespace osu.Game.Rulesets.UI /// private bool validState; + protected override bool RequiresChildrenUpdate => base.RequiresChildrenUpdate && validState; + private bool isAttached => replayInputHandler != null && !UseParentState; private const int max_catch_up_updates_per_frame = 50; From a880e626d87bd3f7344b7b1b6609526e18033688 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 21:20:15 +0900 Subject: [PATCH 49/53] Use for loop and SetLayoutPosition --- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index c97a4de464..f968f94187 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -107,16 +107,19 @@ namespace osu.Game.Overlays.Profile.Header visibleBadge = 0; badgeFlowContainer.Clear(); - foreach (var badge in badges) + for (var index = 0; index < badges.Length; index++) { - LoadComponentAsync(new DrawableBadge(badge) + int displayIndex = index; + LoadComponentAsync(new DrawableBadge(badges[index]) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, }, asyncBadge => { badgeFlowContainer.Add(asyncBadge); - badgeFlowContainer.ChangeChildDepth(asyncBadge, Array.IndexOf(badges, asyncBadge)); //Ensure the badges are ordered correctly + + // load in stable order regardless of async load order. + badgeFlowContainer.SetLayoutPosition(asyncBadge, displayIndex); }); } } From fd4f61fc88da37317e060f4d810da0c2b713008b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 8 Jun 2018 21:51:43 +0900 Subject: [PATCH 50/53] Update framework and other packages --- osu.Desktop/osu.Desktop.csproj | 4 ++-- osu.Game/osu.Game.csproj | 6 +++--- osu.TestProject.props | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 0d4efc7eed..3cf95e9b3e 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -26,7 +26,7 @@ - + @@ -35,4 +35,4 @@ - + \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 363fc7d7bb..e35b6dbe1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,10 +17,10 @@ - - + + - + \ No newline at end of file diff --git a/osu.TestProject.props b/osu.TestProject.props index cf8276eee1..8f7128f8b7 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -13,7 +13,7 @@ - + From cc37a355d26836cf655c911f3953e1b30f2d614d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 10 Jun 2018 01:44:46 +0900 Subject: [PATCH 51/53] Add comment about matching stable scoring Also updated equation to be close to what is expected --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 0568101aa7..b6ec0617f2 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -301,7 +301,8 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; break; case ScoringMode.Exponential: - TotalScore.Value = (baseScore + bonusScore) * Math.Max(0, HighestCombo - 1) / 25f; + // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) + TotalScore.Value = bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); break; } } From 86fb9666b250f52e07a84b8248c98ab1c3560370 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 10 Jun 2018 01:45:05 +0900 Subject: [PATCH 52/53] Rename "Exponential" to "Classic" --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b6ec0617f2..dd4120f2fb 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -202,7 +202,7 @@ namespace osu.Game.Rulesets.Scoring if (maxBaseScore == 0 || maxHighestCombo == 0) { - Mode.Value = ScoringMode.Exponential; + Mode.Value = ScoringMode.Classic; Mode.Disabled = true; } @@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Scoring /// Simulates an autoplay of s that will be judged by this /// by adding s for each in the . /// - /// This is required for to work, otherwise will be used. + /// This is required for to work, otherwise will be used. /// /// /// The containing the s that will be judged by this . @@ -300,7 +300,7 @@ namespace osu.Game.Rulesets.Scoring case ScoringMode.Standardised: TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; break; - case ScoringMode.Exponential: + case ScoringMode.Classic: // should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1) TotalScore.Value = bonusScore + baseScore * (1 + Math.Max(0, HighestCombo - 1) / 25); break; @@ -328,6 +328,6 @@ namespace osu.Game.Rulesets.Scoring public enum ScoringMode { Standardised, - Exponential + Classic } } From b9391b3c6bb8f84426767e7233d499cb633959f3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 11 Jun 2018 18:18:24 +0900 Subject: [PATCH 53/53] Fix bindable not working under non-debug due to weak references --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 94d03be3c8..04148cd558 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Play userAudioOffset.TriggerChange(); ScoreProcessor = RulesetContainer.CreateScoreProcessor(); - ScoreProcessor.Mode.BindTo(config.GetBindable(OsuSetting.ScoreDisplayMode)); + config.BindWith(OsuSetting.ScoreDisplayMode, ScoreProcessor.Mode); Children = new Drawable[] {