From a95ee7494f54b36929dbc7574b893adc199b47a8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 8 Aug 2017 16:01:18 +0900 Subject: [PATCH 001/180] Initial conversion of taiko to use ScrollingPlayfield. --- .../Visual/TestCaseTaikoPlayfield.cs | 12 ++----- .../Objects/Drawables/DrawableBarLine.cs | 29 +++++---------- .../Objects/Drawables/DrawableDrumRoll.cs | 36 ++++++++----------- .../Objects/Drawables/DrawableDrumRollTick.cs | 5 --- .../Objects/Drawables/DrawableSwell.cs | 13 +++---- .../Drawables/DrawableTaikoHitObject.cs | 18 +--------- .../Drawables/Pieces/ElongatedCirclePiece.cs | 12 +------ osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 1 - .../Objects/TaikoHitObject.cs | 14 -------- .../UI/TaikoHitRenderer.cs | 4 +-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 20 ++++------- 11 files changed, 41 insertions(+), 123 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs index 45be9e800d..f6ee2a5bf3 100644 --- a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs @@ -151,13 +151,9 @@ namespace osu.Desktop.Tests.Visual private void addBarLine(bool major, double delay = scroll_time) { - BarLine bl = new BarLine - { - StartTime = playfield.Time.Current + delay, - ScrollTime = scroll_time - }; + BarLine bl = new BarLine { StartTime = playfield.Time.Current + delay }; - playfield.AddBarLine(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); + playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); } private void addSwell(double duration = default_duration) @@ -166,7 +162,6 @@ namespace osu.Desktop.Tests.Visual { StartTime = playfield.Time.Current + scroll_time, Duration = duration, - ScrollTime = scroll_time })); } @@ -180,7 +175,6 @@ namespace osu.Desktop.Tests.Visual StartTime = playfield.Time.Current + scroll_time, IsStrong = strong, Duration = duration, - ScrollTime = scroll_time, }; playfield.Add(new DrawableDrumRoll(d)); @@ -191,7 +185,6 @@ namespace osu.Desktop.Tests.Visual Hit h = new Hit { StartTime = playfield.Time.Current + scroll_time, - ScrollTime = scroll_time, IsStrong = strong }; @@ -206,7 +199,6 @@ namespace osu.Desktop.Tests.Visual Hit h = new Hit { StartTime = playfield.Time.Current + scroll_time, - ScrollTime = scroll_time, IsStrong = strong }; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 7507ee600e..f6959fb426 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -5,13 +5,16 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using OpenTK; +using osu.Game.Rulesets.Objects.Drawables; +using System; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : Container + public class DrawableBarLine : DrawableTaikoHitObject { /// /// The width of the line tracker. @@ -34,15 +37,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected readonly BarLine BarLine; public DrawableBarLine(BarLine barLine) + : base(barLine) { BarLine = barLine; - Anchor = Anchor.CentreLeft; - Origin = Anchor.Centre; - - RelativePositionAxes = Axes.X; RelativeSizeAxes = Axes.Y; - Width = tracker_width; Children = new[] @@ -56,24 +55,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Alpha = 0.75f } }; - - LifetimeStart = BarLine.StartTime - BarLine.ScrollTime * 2; - LifetimeEnd = BarLine.StartTime + BarLine.ScrollTime; } - protected override void LoadComplete() + protected override TaikoPiece CreateMainPiece() => new TaikoPiece(); + + protected override void UpdateState(ArmedState state) { - base.LoadComplete(); - this.Delay(BarLine.StartTime - Time.Current).FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000); - } - - private void updateScrollPosition(double time) => this.MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime)); - - protected override void Update() - { - base.Update(); - - updateScrollPosition(Time.Current); } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 74f0f2326d..e9c50dacf8 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -11,6 +11,7 @@ using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -34,27 +35,29 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; + Width = (float)HitObject.Duration; + + Container tickContainer; + MainPiece.Add(tickContainer = new Container + { + RelativeSizeAxes = Axes.Both, + RelativeChildOffset = new Vector2((float)HitObject.StartTime, 0), + RelativeChildSize = new Vector2((float)HitObject.Duration, 1) + }); + foreach (var tick in drumRoll.Ticks) { - var newTick = new DrawableDrumRollTick(tick) - { - X = (float)((tick.StartTime - HitObject.StartTime) / HitObject.Duration) - }; - + var newTick = new DrawableDrumRollTick(tick) { X = (float)tick.StartTime }; newTick.OnJudgement += onTickJudgement; AddNested(newTick); - MainPiece.Add(newTick); + tickContainer.Add(newTick); } } protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong }; - protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece - { - Length = (float)(HitObject.Duration / HitObject.ScrollTime), - PlayfieldLengthReference = () => Parent.DrawSize.X - }; + protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); [BackgroundDependencyLoader] private void load(OsuColour colours) @@ -63,17 +66,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables accentDarkColour = colours.YellowDarker; } - protected override void LoadComplete() - { - base.LoadComplete(); - - // This is naive, however it's based on the reasoning that the hit target - // is further than mid point of the play field, so the time taken to scroll in should always - // be greater than the time taken to scroll out to the left of the screen. - // Thus, using PreEmpt here is enough for the drum roll to completely scroll out. - LifetimeEnd = HitObject.EndTime + HitObject.ScrollTime; - } - private void onTickJudgement(DrawableHitObject obj) { if (obj.Judgement.Result == HitResult.Hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 0e1cd05de3..ad065395b9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -47,11 +47,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override void UpdateScrollPosition(double time) - { - // Ticks don't move - } - protected override bool HandleKeyPress(Key key) { return Judgement.Result == HitResult.None && UpdateJudgement(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index e861af03cf..f704879f1a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -118,7 +118,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables }); MainPiece.Add(symbol = new SwellSymbolPiece()); - } [BackgroundDependencyLoader] @@ -189,20 +188,22 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Expire(); } - protected override void UpdateScrollPosition(double time) + protected override void Update() { - // Make the swell stop at the hit target - double t = Math.Min(HitObject.StartTime, time); + base.Update(); + // Make the swell stop at the hit target + X = (float)Math.Max(Time.Current, HitObject.StartTime); + + double t = Math.Min(HitObject.StartTime, Time.Current); if (t == HitObject.StartTime && !hasStarted) { OnStart?.Invoke(); hasStarted = true; } - - base.UpdateScrollPosition(t); } + protected override bool HandleKeyPress(Key key) { if (Judgement.Result != HitResult.None) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 510994ed70..caae70fe05 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -12,7 +12,7 @@ using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableHitObject + public abstract class DrawableTaikoHitObject : DrawableScrollingHitObject where TaikoHitType : TaikoHitObject { /// @@ -38,30 +38,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables RelativeSizeAxes = Axes.Both; Size = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); - RelativePositionAxes = Axes.X; - Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; - - LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2; } protected override TaikoJudgement CreateJudgement() => new TaikoJudgement(); protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); - /// - /// Sets the scroll position of the DrawableHitObject relative to the offset between - /// a time value and the HitObject's StartTime. - /// - /// - protected virtual void UpdateScrollPosition(double time) => X = (float)((HitObject.StartTime - time) / HitObject.ScrollTime); - - protected override void Update() - { - UpdateScrollPosition(Time.Current); - } - protected virtual bool HandleKeyPress(Key key) => false; protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs index 2f5b4eefd6..d3786a4324 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -8,16 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class ElongatedCirclePiece : CirclePiece { - /// - /// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing playfield container. - /// - public Func PlayfieldLengthReference; - - /// - /// The length of this piece as a multiple of the value returned by - /// - public float Length; - public ElongatedCirclePiece() { RelativeSizeAxes = Axes.Y; @@ -35,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces Right = padding, }; - Width = (PlayfieldLengthReference?.Invoke() ?? 0) * Length + DrawHeight; + Width = Parent.DrawSize.X + DrawHeight; } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index fd9daa269c..526d23f51a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -80,7 +80,6 @@ namespace osu.Game.Rulesets.Taiko.Objects ret.Add(new DrumRollTick { FirstTick = first, - ScrollTime = ScrollTime, TickSpacing = tickSpacing, StartTime = t, IsStrong = IsStrong, diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 7e7dc3662f..f1c0afc675 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -24,16 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public const float DEFAULT_STRONG_SIZE = DEFAULT_SIZE * STRONG_SCALE; - /// - /// The time taken from the initial (off-screen) spawn position to the centre of the hit target for a of 1000ms. - /// - private const double scroll_time = 6000; - - /// - /// Our adjusted taking into consideration local and other speed multipliers. - /// - public double ScrollTime; - /// /// Whether this HitObject is a "strong" type. /// Strong hit objects give more points for hitting the hit object with both keys. @@ -49,12 +39,8 @@ namespace osu.Game.Rulesets.Taiko.Objects { base.ApplyDefaults(controlPointInfo, difficulty); - TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); - DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime); - ScrollTime = scroll_time * (timingPoint.BeatLength * difficultyPoint.SpeedMultiplier / 1000) / difficulty.SliderMultiplier; - Kiai |= effectPoint.KiaiMode; } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs index 570b4be488..9c9c71ab46 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs @@ -21,7 +21,7 @@ using System.Linq; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoHitRenderer : HitRenderer + public class TaikoHitRenderer : ScrollingHitRenderer { public TaikoHitRenderer(WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(beatmap, isForCurrentRuleset) @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Taiko.UI barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty); bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; - taikoPlayfield.AddBarLine(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); + taikoPlayfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); double bl = currentPoint.BeatLength; if (bl < 800) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index dca339f734..d94b69f141 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -18,7 +18,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.UI { - public class TaikoPlayfield : Playfield + public class TaikoPlayfield : ScrollingPlayfield { /// /// Default height of a when inside a . @@ -35,14 +35,14 @@ namespace osu.Game.Rulesets.Taiko.UI /// private const float left_area_size = 240; - protected override Container Content => hitObjectContainer; private readonly Container hitExplosionContainer; private readonly Container kiaiExplosionContainer; - private readonly Container barLineContainer; private readonly Container judgementContainer; - private readonly Container hitObjectContainer; + protected override Container Content => content; + private readonly Container content; + private readonly Container topLevelHitContainer; private readonly Container overlayBackgroundContainer; @@ -52,6 +52,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield() + : base(Axes.X) { AddRangeInternal(new Drawable[] { @@ -96,10 +97,6 @@ namespace osu.Game.Rulesets.Taiko.UI FillMode = FillMode.Fit, BlendingMode = BlendingMode.Additive, }, - barLineContainer = new Container - { - RelativeSizeAxes = Axes.Both, - }, new HitTarget { Anchor = Anchor.CentreLeft, @@ -107,7 +104,7 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit }, - hitObjectContainer = new Container + content = new Container { RelativeSizeAxes = Axes.Both, }, @@ -205,11 +202,6 @@ namespace osu.Game.Rulesets.Taiko.UI swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); } - public void AddBarLine(DrawableBarLine barLine) - { - barLineContainer.Add(barLine); - } - public override void OnJudgement(DrawableHitObject judgedObject) { bool wasHit = judgedObject.Judgement.Result == HitResult.Hit; From 3d4db427ff36912220337fbc90bb440d4215b2d5 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Tue, 8 Aug 2017 17:17:53 +0200 Subject: [PATCH 002/180] Pass RuleSet to ScoreStore, compute and store MD5 for legacy replays compatibility --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 ++ osu.Game/Beatmaps/BeatmapManager.cs | 1 + osu.Game/OsuGameBase.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreStore.cs | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index ec90cabf02..578b37ea17 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -52,6 +52,8 @@ namespace osu.Game.Beatmaps [JsonProperty("file_md5")] public string Hash { get; set; } + public string MD5Hash { get; set; } + // General public int AudioLeadIn { get; set; } public bool Countdown { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index bbb6c975d0..51c1b698ce 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -367,6 +367,7 @@ namespace osu.Game.Beatmaps beatmap.BeatmapInfo.Path = name; beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); + beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0dec4228de..2855c75ef1 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -103,7 +103,7 @@ namespace osu.Game dependencies.Cache(RulesetStore = new RulesetStore(connection)); dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); - dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager)); + dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager, RulesetStore)); dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index e69fec4b54..c6421522b4 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Scoring var version = sr.ReadInt32(); /* score.FileChecksum = */ var beatmapHash = sr.ReadString(); - score.Beatmap = beatmaps.QueryBeatmap(b => b.Hash == beatmapHash); + score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); /* score.PlayerName = */ sr.ReadString(); /* var localScoreChecksum = */ From 27e63eb7c4d2947e8acec044b189349102593bd4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 10:54:00 +0900 Subject: [PATCH 003/180] Fix up sizing issues. --- osu-framework | 2 +- .../Objects/Drawables/DrawableBarLine.cs | 8 ++++++-- .../Objects/Drawables/DrawableDrumRoll.cs | 3 --- .../Objects/Drawables/DrawableDrumRollTick.cs | 8 ++++++++ osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 8 ++++++++ .../Objects/Drawables/DrawableSwell.cs | 8 ++++++++ 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/osu-framework b/osu-framework index dd0daafcfc..3b858d078c 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit dd0daafcfc0d625bb588c8e12d7db58bc00c255e +Subproject commit 3b858d078cf54465d9af8e2bb9e1a144bcfcdbf4 diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index f6959fb426..28f0af4aba 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -8,13 +8,14 @@ using OpenTK; using osu.Game.Rulesets.Objects.Drawables; using System; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableTaikoHitObject + public class DrawableBarLine : DrawableScrollingHitObject { /// /// The width of the line tracker. @@ -41,6 +42,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { BarLine = barLine; + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Y; Width = tracker_width; @@ -57,7 +61,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables }; } - protected override TaikoPiece CreateMainPiece() => new TaikoPiece(); + protected override TaikoJudgement CreateJudgement() => new TaikoJudgement(); protected override void UpdateState(ArmedState state) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index e9c50dacf8..425f87752f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -32,9 +32,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { - RelativeSizeAxes = Axes.Y; - AutoSizeAxes = Axes.X; - Width = (float)HitObject.Duration; Container tickContainer; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index ad065395b9..5a6abd24b1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -18,6 +18,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables FillMode = FillMode.Fit; } + protected override void LoadComplete() + { + base.LoadComplete(); + + // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize + Width *= Parent.RelativeChildSize.X; + } + protected override TaikoPiece CreateMainPiece() => new TickPiece { Filled = HitObject.FirstTick diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 5a17355cdb..0666d75083 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -29,6 +29,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables FillMode = FillMode.Fit; } + protected override void LoadComplete() + { + base.LoadComplete(); + + // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize + Width *= Parent.RelativeChildSize.X; + } + protected override void CheckJudgement(bool userTriggered) { if (!userTriggered) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index f704879f1a..2b1ed07da7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -128,6 +128,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables targetRing.BorderColour = colours.YellowDark.Opacity(0.25f); } + protected override void LoadComplete() + { + base.LoadComplete(); + + // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize + Width *= Parent.RelativeChildSize.X; + } + protected override void CheckJudgement(bool userTriggered) { if (userTriggered) From a751c19cf73d8915fb551ceb9d6fbb90ff9721a3 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Wed, 9 Aug 2017 08:36:15 +0200 Subject: [PATCH 004/180] Moved JsonProperty file_md5 and added file_sha2 --- osu.Game/Beatmaps/BeatmapInfo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 578b37ea17..432da57a5c 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -49,9 +49,10 @@ namespace osu.Game.Beatmaps public string Path { get; set; } - [JsonProperty("file_md5")] + [JsonProperty("file_sha2")] public string Hash { get; set; } + [JsonProperty("file_md5")] public string MD5Hash { get; set; } // General From d83c218e08155add50e570246f09e84ebdf0d6a5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:19:09 +0900 Subject: [PATCH 005/180] Remove various scrolling container optimisations (removing when not alive). --- .../Drawables/DrawableScrollingHitObject.cs | 2 ++ osu.Game/Rulesets/Timing/ScrollingContainer.cs | 2 ++ .../Rulesets/Timing/SpeedAdjustmentContainer.cs | 2 ++ osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 17 +++++++++-------- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index f67dd4dfea..a7c4dd0333 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Objects.Drawables } } + public override bool RemoveWhenNotAlive => false; + protected DrawableScrollingHitObject(TObject hitObject) : base(hitObject) { diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index 843f307d0d..9bb32ead77 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Timing /// internal Axes ScrollingAxes; + public override bool RemoveWhenNotAlive => false; + /// /// The control point that defines the speed adjustments for this container. This is set by the . /// diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 9d5f49e155..5d6c03b9de 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Timing /// public Axes ScrollingAxes { get; internal set; } + public override bool RemoveWhenNotAlive => false; + /// /// The that defines the speed adjustments. /// diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 66ca2dd7c4..f8e090d613 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -7,6 +7,7 @@ using System.Linq; using OpenTK.Input; using osu.Framework.Configuration; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Framework.MathUtils; @@ -154,7 +155,7 @@ namespace osu.Game.Rulesets.UI /// Hit objects that are to be re-processed on the next update. /// private readonly List queuedHitObjects = new List(); - private readonly List speedAdjustments = new List(); + private readonly Container speedAdjustments; private readonly Axes scrollingAxes; @@ -165,6 +166,8 @@ namespace osu.Game.Rulesets.UI public ScrollingHitObjectContainer(Axes scrollingAxes) { this.scrollingAxes = scrollingAxes; + + AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); } /// @@ -176,9 +179,7 @@ namespace osu.Game.Rulesets.UI speedAdjustment.ScrollingAxes = scrollingAxes; speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.Reversed.BindTo(Reversed); - speedAdjustments.Add(speedAdjustment); - AddInternal(speedAdjustment); } public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); @@ -210,11 +211,11 @@ namespace osu.Game.Rulesets.UI var hitObject = queuedHitObjects[i]; var target = adjustmentContainerFor(hitObject); - if (target != null) - { - target.Add(hitObject); - queuedHitObjects.RemoveAt(i); - } + if (target == null) + continue; + + target.Add(hitObject); + queuedHitObjects.RemoveAt(i); } } From 88cefa77bd69ec637afbfaf6dddf1614e9fd9e8d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:19:20 +0900 Subject: [PATCH 006/180] Make TestCaseTaikoPlayfield work again. --- .../Visual/TestCaseTaikoPlayfield.cs | 64 +++++++++++++------ 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs index f6ee2a5bf3..1589ca8f9b 100644 --- a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs @@ -14,6 +14,9 @@ using osu.Game.Rulesets.Taiko.UI; using OpenTK; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps; +using osu.Desktop.Tests.Beatmaps; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects; namespace osu.Desktop.Tests.Visual { @@ -27,7 +30,7 @@ namespace osu.Desktop.Tests.Visual protected override double TimePerAction => default_duration * 2; private readonly Random rng = new Random(1337); - private readonly TaikoPlayfield playfield; + private readonly TaikoRulesetContainer rulesetContainer; private readonly Container playfieldContainer; public TestCaseTaikoPlayfield() @@ -51,7 +54,29 @@ namespace osu.Desktop.Tests.Visual AddStep("Height test 5", () => changePlayfieldSize(5)); AddStep("Reset height", () => changePlayfieldSize(6)); - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; + var controlPointInfo = new ControlPointInfo(); + controlPointInfo.TimingPoints.Add(new TimingControlPoint + { + BeatLength = 200 + }); + + WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap + { + HitObjects = new List { new CentreHit() }, + BeatmapInfo = new BeatmapInfo + { + Difficulty = new BeatmapDifficulty(), + Metadata = new BeatmapMetadata + { + Artist = @"Unknown", + Title = @"Sample Beatmap", + Author = @"peppy", + }, + }, + ControlPointInfo = controlPointInfo + }); + + var rateAdjustClock = new StopwatchClock(true) { Rate = 0.1 }; Add(playfieldContainer = new Container { @@ -60,10 +85,7 @@ namespace osu.Desktop.Tests.Visual RelativeSizeAxes = Axes.X, Height = TaikoPlayfield.DEFAULT_HEIGHT, Clock = new FramedClock(rateAdjustClock), - Children = new[] - { - playfield = new TaikoPlayfield() - } + Children = new[] { rulesetContainer = new TaikoRulesetContainer(null, beatmap, true) } }); } @@ -128,18 +150,18 @@ namespace osu.Desktop.Tests.Visual } }; - playfield.OnJudgement(h); + rulesetContainer.Playfield.OnJudgement(h); if (RNG.Next(10) == 0) { h.Judgement.SecondHit = true; - playfield.OnJudgement(h); + rulesetContainer.Playfield.OnJudgement(h); } } private void addMissJudgement() { - playfield.OnJudgement(new DrawableTestHit(new Hit()) + rulesetContainer.Playfield.OnJudgement(new DrawableTestHit(new Hit()) { Judgement = new TaikoJudgement { @@ -151,16 +173,16 @@ namespace osu.Desktop.Tests.Visual private void addBarLine(bool major, double delay = scroll_time) { - BarLine bl = new BarLine { StartTime = playfield.Time.Current + delay }; + BarLine bl = new BarLine { StartTime = rulesetContainer.Playfield.Time.Current + delay }; - playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); + rulesetContainer.Playfield.Add(major ? new DrawableBarLineMajor(bl) : new DrawableBarLine(bl)); } private void addSwell(double duration = default_duration) { - playfield.Add(new DrawableSwell(new Swell + rulesetContainer.Playfield.Add(new DrawableSwell(new Swell { - StartTime = playfield.Time.Current + scroll_time, + StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, Duration = duration, })); } @@ -172,40 +194,40 @@ namespace osu.Desktop.Tests.Visual var d = new DrumRoll { - StartTime = playfield.Time.Current + scroll_time, + StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, IsStrong = strong, Duration = duration, }; - playfield.Add(new DrawableDrumRoll(d)); + rulesetContainer.Playfield.Add(new DrawableDrumRoll(d)); } private void addCentreHit(bool strong) { Hit h = new Hit { - StartTime = playfield.Time.Current + scroll_time, + StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, IsStrong = strong }; if (strong) - playfield.Add(new DrawableCentreHitStrong(h)); + rulesetContainer.Playfield.Add(new DrawableCentreHitStrong(h)); else - playfield.Add(new DrawableCentreHit(h)); + rulesetContainer.Playfield.Add(new DrawableCentreHit(h)); } private void addRimHit(bool strong) { Hit h = new Hit { - StartTime = playfield.Time.Current + scroll_time, + StartTime = rulesetContainer.Playfield.Time.Current + scroll_time, IsStrong = strong }; if (strong) - playfield.Add(new DrawableRimHitStrong(h)); + rulesetContainer.Playfield.Add(new DrawableRimHitStrong(h)); else - playfield.Add(new DrawableRimHit(h)); + rulesetContainer.Playfield.Add(new DrawableRimHit(h)); } private class DrawableTestHit : DrawableHitObject From 8b4f28318f5e45a365f27efaad51e79ff39bc438 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:19:31 +0900 Subject: [PATCH 007/180] Fix drum roll ticks. --- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs | 2 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 425f87752f..8f81368a2c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables foreach (var tick in drumRoll.Ticks) { - var newTick = new DrawableDrumRollTick(tick) { X = (float)tick.StartTime }; + var newTick = new DrawableDrumRollTick(tick); newTick.OnJudgement += onTickJudgement; AddNested(newTick); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 5a6abd24b1..6e916aa9d5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -15,6 +15,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { + // Because ticks aren't added by the ScrollingPlayfield, we need to set the following properties ourselves + RelativePositionAxes = Axes.X; + X = (float)tick.StartTime; + FillMode = FillMode.Fit; } From 7237f834c4e1144bef0c38627cc6b2d02dc49922 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:39:19 +0900 Subject: [PATCH 008/180] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 67d89a3601..9bad670471 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 67d89a36016f98c0ede576b859a2ccafe114fce8 +Subproject commit 9bad670471a03e299760315fd9d3fa9a726f6233 From 2334c109e5262514970e54ab34a626d94d0aff52 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:46:08 +0900 Subject: [PATCH 009/180] Set better TaikoPlayfield default VisibleTimeRange. --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index e2823ccdfe..da86c31123 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -178,6 +178,8 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, } }); + + VisibleTimeRange.Value = 6000; } [BackgroundDependencyLoader] From 0c1b68d7111a2e5da1d4bb073db1f3ccf374b2ff Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 16:46:22 +0900 Subject: [PATCH 010/180] Fix up TestCaseTaikoPlayfield. --- osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs index 1589ca8f9b..43148da512 100644 --- a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs @@ -55,10 +55,7 @@ namespace osu.Desktop.Tests.Visual AddStep("Reset height", () => changePlayfieldSize(6)); var controlPointInfo = new ControlPointInfo(); - controlPointInfo.TimingPoints.Add(new TimingControlPoint - { - BeatLength = 200 - }); + controlPointInfo.TimingPoints.Add(new TimingControlPoint()); WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap { @@ -76,14 +73,14 @@ namespace osu.Desktop.Tests.Visual ControlPointInfo = controlPointInfo }); - var rateAdjustClock = new StopwatchClock(true) { Rate = 0.1 }; + var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; Add(playfieldContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, - Height = TaikoPlayfield.DEFAULT_HEIGHT, + Height = 768, Clock = new FramedClock(rateAdjustClock), Children = new[] { rulesetContainer = new TaikoRulesetContainer(null, beatmap, true) } }); From e9a98358b3d47ad6708e39a9ad9f0ea71adf7030 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 17:26:59 +0900 Subject: [PATCH 011/180] Don't move completed drum rolls above the playfield. --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index da86c31123..eb9e41f771 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.Taiko.UI if (!secondHit) { - if (judgedObject.X >= -0.05f && !(judgedObject is DrawableSwell)) + if (judgedObject.X >= -0.05f && judgedObject is DrawableHit) { // If we're far enough away from the left stage, we should bring outselves in front of it topLevelHitContainer.Add(judgedObject.CreateProxy()); From bb8c5338022cd6d1313ec64750930917cccb523e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 9 Aug 2017 17:34:09 +0900 Subject: [PATCH 012/180] Fix CI issues. --- .../Objects/Drawables/DrawableBarLine.cs | 3 --- .../Objects/Drawables/Pieces/ElongatedCirclePiece.cs | 1 - osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs | 7 +------ 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 28f0af4aba..06702e8141 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -2,12 +2,9 @@ // 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.Shapes; using OpenTK; using osu.Game.Rulesets.Objects.Drawables; -using System; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs index d3786a4324..4642e318c4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Graphics; namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 36ee0c2a1d..723af3e4e9 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -36,11 +36,6 @@ namespace osu.Game.Rulesets.Taiko.UI private void loadBarLines() { - var taikoPlayfield = Playfield as TaikoPlayfield; - - if (taikoPlayfield == null) - return; - TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; double lastHitTime = 1 + (lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime; @@ -72,7 +67,7 @@ namespace osu.Game.Rulesets.Taiko.UI barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty); bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; - taikoPlayfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); + Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); double bl = currentPoint.BeatLength; if (bl < 800) From c0642ad6d3b438761412e28649fa5437ea8d2bb5 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Wed, 9 Aug 2017 10:54:03 +0200 Subject: [PATCH 013/180] Added database migration --- osu-framework | 2 +- osu-resources | 2 +- osu.Game/Beatmaps/BeatmapStore.cs | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu-framework b/osu-framework index 107c551767..9bad670471 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 107c5517670ca88dbe8c83a97e37e99ac5742ee6 +Subproject commit 9bad670471a03e299760315fd9d3fa9a726f6233 diff --git a/osu-resources b/osu-resources index 76656c51f2..f6042e1cb3 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 76656c51f281e7934159e9ed4414378fef24d130 +Subproject commit f6042e1cb37cfad6c879d0e1245f7880c7fcd5f5 diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 2ec9a7d759..d717a46a24 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -20,7 +20,7 @@ namespace osu.Game.Beatmaps /// The current version of this store. Used for migrations (see ). /// The initial version is 1. /// - protected override int StoreVersion => 2; + protected override int StoreVersion => 3; public BeatmapStore(SQLiteConnection connection) : base(connection) @@ -77,6 +77,10 @@ namespace osu.Game.Beatmaps // cannot migrate; breaking underlying changes. Reset(); break; + case 3: + // Added MD5Hash column to BeatmapInfo + Connection.CreateCommand("ALTER TABLE BeatmapInfo ADD COLUMN MD5Hash varchar").ExecuteNonQuery(); + break; } } } From 8dd4f513e717ebf638ca46b3c6139643f0557f36 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Wed, 9 Aug 2017 11:55:36 +0200 Subject: [PATCH 014/180] Symplified migration using MigrateTable<> instead of commands --- osu.Game/Beatmaps/BeatmapStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index d717a46a24..8212712bf9 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -79,7 +79,7 @@ namespace osu.Game.Beatmaps break; case 3: // Added MD5Hash column to BeatmapInfo - Connection.CreateCommand("ALTER TABLE BeatmapInfo ADD COLUMN MD5Hash varchar").ExecuteNonQuery(); + Connection.MigrateTable(); break; } } From e48c5898bd8f59f98e95b92f28cd9a699ce56370 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 11 Aug 2017 17:26:30 +0930 Subject: [PATCH 015/180] Ensure the Track for the selected beatmap is added to the TrackManager. Fixes the problem where a beatmap would be stuck at 100% if it is replayed. --- osu.Game/Screens/Select/SongSelect.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8f545240c8..f8423a90ed 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -372,6 +372,7 @@ namespace osu.Game.Screens.Select if (!track.IsRunning) { + Game.Audio.Track.AddItemToList(track); if (preview) track.Seek(Beatmap.Value.Metadata.PreviewTime); track.Start(); } From 096e5744012fad381b3fbfa3d7b1fc9e64317765 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 12 Aug 2017 19:52:09 +0930 Subject: [PATCH 016/180] Selecting a beatmap set no longer updates the ruleset to the first map of that set (since it causes the carousel to refilter) --- osu.Game/Screens/Select/SongSelect.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8f545240c8..6414365853 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -253,8 +253,6 @@ namespace osu.Game.Screens.Select } else { - Ruleset.Value = beatmap.Ruleset; - if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID) sampleChangeDifficulty.Play(); else From d19c8f56be69c913c95b72334b6cea5e9e7e71bf Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sun, 13 Aug 2017 15:03:01 +0930 Subject: [PATCH 017/180] Make RulesetInfo implement IEquatable since EqualityComparer was sometimes giving false negatives and causing Bindable observers to fire --- osu.Game/Rulesets/RulesetInfo.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index bc23649ede..059f93645f 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -6,7 +6,7 @@ using SQLite.Net.Attributes; namespace osu.Game.Rulesets { - public class RulesetInfo + public class RulesetInfo : IEquatable { [PrimaryKey, AutoIncrement] public int? ID { get; set; } @@ -21,5 +21,10 @@ namespace osu.Game.Rulesets public bool Available { get; set; } public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); + + public bool Equals(RulesetInfo other) + { + return this.ID == other.ID && this.Available == other.Available && this.Name == other.Name && this.InstantiationInfo == other.InstantiationInfo; + } } } \ No newline at end of file From 66fa84a451e0b3afdbfd95fc0e1d87448cefe6be Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Aug 2017 22:21:22 +0900 Subject: [PATCH 018/180] Make settings more modular --- .../Visual/TestCaseKeyConfiguration.cs | 44 +++++++++++++++++++ osu.Desktop.Tests/Visual/TestCaseSettings.cs | 2 +- osu.Desktop.Tests/osu.Desktop.Tests.csproj | 1 + osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/MainSettings.cs | 29 ++++++++++++ osu.Game/Overlays/Settings/SettingsHeader.cs | 13 +++++- osu.Game/Overlays/SettingsOverlay.cs | 30 ++++++------- osu.Game/osu.Game.csproj | 1 + 8 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs create mode 100644 osu.Game/Overlays/MainSettings.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs new file mode 100644 index 0000000000..10a15d0a96 --- /dev/null +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Overlays; +using osu.Game.Overlays.Settings; +using System.Collections.Generic; +using osu.Game.Graphics; + +namespace osu.Desktop.Tests.Visual +{ + public class TestCaseKeyConfiguration : OsuTestCase + { + private readonly KeyConfiguration configuration; + + public override string Description => @"Key configuration"; + + public TestCaseKeyConfiguration() + { + Child = configuration = new KeyConfiguration(); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + configuration.Show(); + } + } + + public class KeyConfiguration : SettingsOverlay + { + protected override IEnumerable CreateSections() => new[] + { + new BindingsSection(), + new BindingsSection() + }; + } + + public class BindingsSection : SettingsSection + { + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => "Header"; + } +} diff --git a/osu.Desktop.Tests/Visual/TestCaseSettings.cs b/osu.Desktop.Tests/Visual/TestCaseSettings.cs index 7b35009aef..1f4b88e9e3 100644 --- a/osu.Desktop.Tests/Visual/TestCaseSettings.cs +++ b/osu.Desktop.Tests/Visual/TestCaseSettings.cs @@ -13,7 +13,7 @@ namespace osu.Desktop.Tests.Visual public TestCaseSettings() { - Children = new[] { settings = new SettingsOverlay() }; + Children = new[] { settings = new MainSettings() }; } protected override void LoadComplete() diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 3111088ff6..24d112a45c 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -81,6 +81,7 @@ + diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f54fba4a0b..0d1e8396e4 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -182,7 +182,7 @@ namespace osu.Game LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(social = new SocialOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(settings = new SettingsOverlay { Depth = -1 }, overlayContent.Add); + LoadComponentAsync(settings = new MainSettings { Depth = -1 }, overlayContent.Add); LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); LoadComponentAsync(musicController = new MusicController { diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs new file mode 100644 index 0000000000..86a1262a11 --- /dev/null +++ b/osu.Game/Overlays/MainSettings.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Game.Overlays.Settings; +using osu.Game.Overlays.Settings.Sections; + +namespace osu.Game.Overlays +{ + public class MainSettings : SettingsOverlay + { + protected override IEnumerable CreateSections() => new SettingsSection[] + { + new GeneralSection(), + new GraphicsSection(), + new GameplaySection(), + new AudioSection(), + new SkinSection(), + new InputSection(), + new OnlineSection(), + new MaintenanceSection(), + new DebugSection(), + }; + + protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); + protected override Drawable CreateFooter() => new SettingsFooter(); + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index c554b54a87..80d60b6e5d 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -11,6 +11,15 @@ namespace osu.Game.Overlays.Settings { public class SettingsHeader : Container { + private readonly string heading; + private readonly string subheading; + + public SettingsHeader(string heading, string subheading) + { + this.heading = heading; + this.subheading = subheading; + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -28,7 +37,7 @@ namespace osu.Game.Overlays.Settings { new OsuSpriteText { - Text = "settings", + Text = heading, TextSize = 40, Margin = new MarginPadding { @@ -39,7 +48,7 @@ namespace osu.Game.Overlays.Settings new OsuSpriteText { Colour = colours.Pink, - Text = "Change the way osu! behaves", + Text = subheading, TextSize = 18, Margin = new MarginPadding { diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 1dcabbfa15..c4971fd4ac 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -12,11 +13,10 @@ using osu.Framework.Input; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; -using osu.Game.Overlays.Settings.Sections; namespace osu.Game.Overlays { - public class SettingsOverlay : OsuFocusedOverlayContainer + public abstract class SettingsOverlay : OsuFocusedOverlayContainer { internal const float CONTENT_MARGINS = 10; @@ -38,27 +38,19 @@ namespace osu.Game.Overlays private Func getToolbarHeight; - public SettingsOverlay() + protected SettingsOverlay() { RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; } + protected abstract IEnumerable CreateSections(); + [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuGame game) { - var sections = new SettingsSection[] - { - new GeneralSection(), - new GraphicsSection(), - new GameplaySection(), - new AudioSection(), - new SkinSection(), - new InputSection(), - new OnlineSection(), - new MaintenanceSection(), - new DebugSection(), - }; + var sections = CreateSections().ToList(); + Children = new Drawable[] { new Box @@ -72,7 +64,7 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Width = width, Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - ExpandableHeader = new SettingsHeader(), + ExpandableHeader = CreateHeader(), FixedHeader = searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X, @@ -87,7 +79,7 @@ namespace osu.Game.Overlays Exit = Hide, }, Children = sections, - Footer = new SettingsFooter() + Footer = CreateFooter() }, sidebar = new Sidebar { @@ -121,6 +113,10 @@ namespace osu.Game.Overlays getToolbarHeight = () => game?.ToolbarOffset ?? 0; } + protected virtual Drawable CreateHeader() => new Container(); + + protected virtual Drawable CreateFooter() => new Container(); + protected override void PopIn() { base.PopIn(); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7690a56378..13c4938850 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -102,6 +102,7 @@ + From dccefe1c0e1c926bdf424a8b2eef5ebe62813250 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Aug 2017 14:40:48 +0900 Subject: [PATCH 019/180] Make the settings sidebar optional Also removes an unnecessary secondary list of SidebarButtons by using generic containers. --- osu.Game/Overlays/MainSettings.cs | 4 + osu.Game/Overlays/Settings/SettingsSection.cs | 52 ++++++------ osu.Game/Overlays/Settings/Sidebar.cs | 8 +- osu.Game/Overlays/SettingsOverlay.cs | 79 +++++++++++-------- 4 files changed, 81 insertions(+), 62 deletions(-) diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 86a1262a11..44c4d4ccdb 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -25,5 +25,9 @@ namespace osu.Game.Overlays protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); protected override Drawable CreateFooter() => new SettingsFooter(); + + public MainSettings() : base(true) + { + } } } \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 68ebde6b28..f091192d27 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using System.Collections.Generic; @@ -25,25 +24,38 @@ namespace osu.Game.Overlays.Settings public IEnumerable FilterableChildren => Children.OfType(); public string[] FilterTerms => new[] { Header }; + + private const int header_size = 26; + private const int header_margin = 25; + private const int border_size = 2; + public bool MatchingFilter { - set - { - this.FadeTo(value ? 1 : 0); - } + set { this.FadeTo(value ? 1 : 0); } } - private readonly SpriteText headerLabel; - protected SettingsSection() { Margin = new MarginPadding { Top = 20 }; AutoSizeAxes = Axes.Y; RelativeSizeAxes = Axes.X; - const int header_size = 26; - const int header_margin = 25; - const int border_size = 2; + FlowContent = new FillFlowContainer + { + Margin = new MarginPadding + { + Top = header_size + header_margin + }, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 30), + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { AddRangeInternal(new Drawable[] { new Box @@ -65,28 +77,16 @@ namespace osu.Game.Overlays.Settings AutoSizeAxes = Axes.Y, Children = new[] { - headerLabel = new OsuSpriteText + new OsuSpriteText { TextSize = header_size, Text = Header, + Colour = colours.Yellow }, - FlowContent = new FillFlowContainer - { - Margin = new MarginPadding { Top = header_size + header_margin }, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 30), - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - }, + FlowContent } }, }); } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - headerLabel.Colour = colours.Yellow; - } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 6eafc65d12..706e7ecc25 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -14,12 +14,12 @@ using osu.Game.Overlays.Toolbar; namespace osu.Game.Overlays.Settings { - public class Sidebar : Container, IStateful + public class Sidebar : Container, IStateful { - private readonly FillFlowContainer content; + private readonly FillFlowContainer content; internal const float DEFAULT_WIDTH = ToolbarButton.WIDTH; internal const int EXPANDED_WIDTH = 200; - protected override Container Content => content; + protected override Container Content => content; public Sidebar() { @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Settings { Children = new[] { - content = new FillFlowContainer + content = new FillFlowContainer { Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index c4971fd4ac..dfbcedd479 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -29,7 +30,6 @@ namespace osu.Game.Overlays private const float sidebar_padding = 10; private Sidebar sidebar; - private SidebarButton[] sidebarButtons; private SidebarButton selectedSidebarButton; private SettingsSectionsContainer sectionsContainer; @@ -38,19 +38,20 @@ namespace osu.Game.Overlays private Func getToolbarHeight; - protected SettingsOverlay() + private readonly bool showSidebar; + + protected SettingsOverlay(bool showSidebar) { + this.showSidebar = showSidebar; RelativeSizeAxes = Axes.Y; AutoSizeAxes = Axes.X; } - protected abstract IEnumerable CreateSections(); + protected virtual IEnumerable CreateSections() => null; [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuGame game) { - var sections = CreateSections().ToList(); - Children = new Drawable[] { new Box @@ -78,39 +79,53 @@ namespace osu.Game.Overlays }, Exit = Hide, }, - Children = sections, Footer = CreateFooter() - }, - sidebar = new Sidebar - { - Width = SIDEBAR_WIDTH, - Children = sidebarButtons = sections.Select(section => - new SidebarButton - { - Section = section, - Action = s => - { - sectionsContainer.ScrollTo(s); - sidebar.State = ExpandedState.Contracted; - }, - } - ).ToArray() } }; - selectedSidebarButton = sidebarButtons[0]; - selectedSidebarButton.Selected = true; - - sectionsContainer.SelectedSection.ValueChanged += section => + if (showSidebar) { - selectedSidebarButton.Selected = false; - selectedSidebarButton = sidebarButtons.Single(b => b.Section == section); - selectedSidebarButton.Selected = true; - }; + Add(sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); + + sectionsContainer.SelectedSection.ValueChanged += section => + { + selectedSidebarButton.Selected = false; + selectedSidebarButton = sidebar.Children.Single(b => b.Section == section); + selectedSidebarButton.Selected = true; + }; + } searchTextBox.Current.ValueChanged += newValue => sectionsContainer.SearchContainer.SearchTerm = newValue; getToolbarHeight = () => game?.ToolbarOffset ?? 0; + + CreateSections()?.ForEach(AddSection); + } + + protected void AddSection(SettingsSection section) + { + sectionsContainer.Add(section); + + if (sidebar != null) + { + var button = new SidebarButton + { + Section = section, + Action = s => + { + sectionsContainer.ScrollTo(s); + sidebar.State = ExpandedState.Contracted; + }, + }; + + sidebar.Add(button); + + if (selectedSidebarButton == null) + { + selectedSidebarButton = sidebar.Children.First(); + selectedSidebarButton.Selected = true; + } + } } protected virtual Drawable CreateHeader() => new Container(); @@ -122,7 +137,7 @@ namespace osu.Game.Overlays base.PopIn(); sectionsContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); - sidebar.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH / 2); searchTextBox.HoldFocus = true; @@ -133,7 +148,7 @@ namespace osu.Game.Overlays base.PopOut(); sectionsContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); - sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); + sidebar?.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(0, TRANSITION_LENGTH / 2); searchTextBox.HoldFocus = false; @@ -155,7 +170,7 @@ namespace osu.Game.Overlays { base.UpdateAfterChildren(); - sectionsContainer.Margin = new MarginPadding { Left = sidebar.DrawWidth }; + sectionsContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; sectionsContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; } From 7c9d6c9c83a4f070d205527cc5d0bb852a030862 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Aug 2017 20:19:25 +0900 Subject: [PATCH 020/180] Initial refactoring of key binding logic --- osu.Game.Rulesets.Catch/CatchInputManager.cs | 12 ---------- osu.Game.Rulesets.Catch/CatchRuleset.cs | 11 ++++++++++ .../UI/CatchRulesetContainer.cs | 2 +- osu.Game.Rulesets.Osu/OsuInputManager.cs | 12 +++------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 11 +++++++++- .../UI/OsuRulesetContainer.cs | 2 +- .../Input/Bindings/DatabasedKeyBinding.cs | 2 +- .../DatabasedKeyBindingInputManager.cs | 22 +++++++------------ .../Bindings/GlobalBindingInputManager.cs | 2 +- .../{BindingStore.cs => KeyBindingStore.cs} | 19 +++++++++++++--- osu.Game/OsuGameBase.cs | 10 ++++++--- osu.Game/Rulesets/Ruleset.cs | 13 +++++++++++ osu.Game/Rulesets/UI/RulesetContainer.cs | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 14 files changed, 75 insertions(+), 49 deletions(-) rename osu.Game/Input/{BindingStore.cs => KeyBindingStore.cs} (61%) diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 446f9b2787..683724b7b8 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -1,11 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using System.ComponentModel; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; -using OpenTK.Input; namespace osu.Game.Rulesets.Catch { @@ -15,16 +13,6 @@ namespace osu.Game.Rulesets.Catch : base(ruleset, simultaneousMode: SimultaneousBindingMode.Unique) { } - - protected override IEnumerable CreateDefaultMappings() => new[] - { - new KeyBinding(Key.Z, CatchAction.MoveLeft), - new KeyBinding(Key.Left, CatchAction.MoveLeft), - new KeyBinding(Key.X, CatchAction.MoveRight), - new KeyBinding(Key.Right, CatchAction.MoveRight), - new KeyBinding(Key.LShift, CatchAction.Dash), - new KeyBinding(Key.RShift, CatchAction.Dash), - }; } public enum CatchAction diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 8d45ea8fa2..b486566b7d 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Scoring; +using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Catch { @@ -20,6 +21,16 @@ namespace osu.Game.Rulesets.Catch { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] + { + new KeyBinding(Key.Z, CatchAction.MoveLeft), + new KeyBinding(Key.Left, CatchAction.MoveLeft), + new KeyBinding(Key.X, CatchAction.MoveRight), + new KeyBinding(Key.Right, CatchAction.MoveRight), + new KeyBinding(Key.LShift, CatchAction.Dash), + new KeyBinding(Key.RShift, CatchAction.Dash), + }; + public override IEnumerable GetModsFor(ModType type) { switch (type) diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 8469be24dd..1d037deaef 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override PassThroughInputManager CreateActionMappingInputManager() => new CatchInputManager(Ruleset?.RulesetInfo); + public override PassThroughInputManager CreateKeyBindingInputManager() => new CatchInputManager(Ruleset?.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) { diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index c1ee19d8c5..06836994d2 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using osu.Framework.Input; using osu.Framework.Input.Bindings; @@ -33,19 +33,13 @@ namespace osu.Game.Rulesets.Osu keyboard.Keys = keyboard.Keys.Concat(new[] { Key.LastKey + 2 }); } } - - protected override IEnumerable CreateDefaultMappings() => new[] - { - new KeyBinding(Key.Z, OsuAction.LeftButton), - new KeyBinding(Key.X, OsuAction.RightButton), - new KeyBinding(Key.LastKey + 1, OsuAction.LeftButton), - new KeyBinding(Key.LastKey + 2, OsuAction.RightButton), - }; } public enum OsuAction { + [Description("Left Button")] LeftButton, + [Description("Right Button")] RightButton } } diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 212c634aaf..75b7be01a4 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -17,6 +17,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Settings; +using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Osu { @@ -24,8 +25,16 @@ namespace osu.Game.Rulesets.Osu { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset); - public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { + new KeyBinding(Key.Z, OsuAction.LeftButton), + new KeyBinding(Key.X, OsuAction.RightButton), + new KeyBinding(Key.LastKey + 1, OsuAction.LeftButton), + new KeyBinding(Key.LastKey + 2, OsuAction.RightButton), + }; + + public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] + { new BeatmapStatistic { Name = @"Circle count", diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 538b94603c..917322de44 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - protected override PassThroughInputManager CreateActionMappingInputManager() => new OsuInputManager(Ruleset?.RulesetInfo); + public override PassThroughInputManager CreateKeyBindingInputManager() => new OsuInputManager(Ruleset?.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index 278033899c..3870cc5b04 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -27,7 +27,7 @@ namespace osu.Game.Input.Bindings [Column("Action")] public new int Action { - get { return base.Action; } + get { return (int)base.Action; } private set { base.Action = value; } } } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index 5c62f1ddc8..52e5af152c 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; using osu.Game.Rulesets; @@ -18,7 +19,9 @@ namespace osu.Game.Input.Bindings private readonly int? variant; - private BindingStore store; + private KeyBindingStore store; + + public override IEnumerable DefaultMappings => ruleset.CreateInstance().GetDefaultKeyBindings(); /// /// Create a new instance. @@ -34,24 +37,15 @@ namespace osu.Game.Input.Bindings } [BackgroundDependencyLoader] - private void load(BindingStore bindings) + private void load(KeyBindingStore keyBindings) { - store = bindings; + store = keyBindings; } protected override void ReloadMappings() { - // load defaults - base.ReloadMappings(); - - var rulesetId = ruleset?.ID; - - // load from database if present. - if (store != null) - { - foreach (var b in store.Query(b => b.RulesetID == rulesetId && b.Variant == variant)) - KeyBindings.Add(b); - } + KeyBindings.Clear(); + KeyBindings.AddRange(store.GetProcessedList(DefaultMappings, ruleset?.ID, variant)); } } } \ No newline at end of file diff --git a/osu.Game/Input/Bindings/GlobalBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalBindingInputManager.cs index 60a4faa8cd..d00ed588ae 100644 --- a/osu.Game/Input/Bindings/GlobalBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalBindingInputManager.cs @@ -21,7 +21,7 @@ namespace osu.Game.Input.Bindings handler = game; } - protected override IEnumerable CreateDefaultMappings() => new[] + public override IEnumerable DefaultMappings => new[] { new KeyBinding(Key.F8, GlobalAction.ToggleChat), new KeyBinding(Key.F9, GlobalAction.ToggleSocial), diff --git a/osu.Game/Input/BindingStore.cs b/osu.Game/Input/KeyBindingStore.cs similarity index 61% rename from osu.Game/Input/BindingStore.cs rename to osu.Game/Input/KeyBindingStore.cs index 25a997e29d..e26942a06c 100644 --- a/osu.Game/Input/BindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -2,6 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; +using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Input.Bindings; @@ -9,9 +11,9 @@ using SQLite.Net; namespace osu.Game.Input { - public class BindingStore : DatabaseBackedStore + public class KeyBindingStore : DatabaseBackedStore { - public BindingStore(SQLiteConnection connection, Storage storage = null) + public KeyBindingStore(SQLiteConnection connection, Storage storage = null) : base(connection, storage) { } @@ -44,5 +46,16 @@ namespace osu.Game.Input typeof(DatabasedKeyBinding) }; + public List GetProcessedList(IEnumerable defaults, int? rulesetId, int? variant) + { + //todo: cache and share reference + List bindings = new List(defaults); + + // load from database if present. + foreach (var b in Query(b => b.RulesetID == rulesetId && b.Variant == variant)) + bindings.Add(b); + + return bindings; + } } -} \ No newline at end of file +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 344b23cca4..d72716b5d6 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -39,7 +39,7 @@ namespace osu.Game protected ScoreStore ScoreStore; - protected BindingStore BindingStore; + protected KeyBindingStore KeyBindingStore; protected override string MainResourceFile => @"osu.Game.Resources.dll"; @@ -108,7 +108,7 @@ namespace osu.Game dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager)); - dependencies.Cache(BindingStore = new BindingStore(connection)); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(connection)); dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. @@ -183,12 +183,14 @@ namespace osu.Game { base.LoadComplete(); + GlobalBindingInputManager globalBinding; + base.Content.Add(new RatioAdjust { Children = new Drawable[] { Cursor = new MenuCursor(), - new GlobalBindingInputManager(this) + globalBinding = new GlobalBindingInputManager(this) { RelativeSizeAxes = Axes.Both, Child = new OsuTooltipContainer(Cursor) @@ -200,6 +202,8 @@ namespace osu.Game } }); + dependencies.Cache(globalBinding); + // TODO: This is temporary until we reimplement the local FPS display. // It's just to allow end-users to access the framework FPS display without knowing the shortcut key. fpsDisplayVisible = LocalConfig.GetBindable(OsuSetting.ShowFpsDisplay); diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index ba040403ba..e5fa7117f3 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Settings; @@ -53,5 +54,17 @@ namespace osu.Game.Rulesets /// Do not override this unless you are a legacy mode. /// public virtual int LegacyID => -1; + + /// + /// A list of available variant ids. + /// + public virtual IEnumerable AvailableVariants => new[] { 0 }; + + /// + /// Get a list of default keys for the specified variant. + /// + /// A variant. + /// A list of valid s. + public virtual IEnumerable GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { }; } } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 387fa15191..8512d4b5e1 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.UI internal RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; - KeyConversionInputManager = CreateActionMappingInputManager(); + KeyConversionInputManager = CreateKeyBindingInputManager(); KeyConversionInputManager.RelativeSizeAxes = Axes.Both; } @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.UI /// Creates a key conversion input manager. /// /// The input manager. - protected virtual PassThroughInputManager CreateActionMappingInputManager() => new PassThroughInputManager(); + public virtual PassThroughInputManager CreateKeyBindingInputManager() => new PassThroughInputManager(); protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 13c4938850..b324fb9f92 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -94,7 +94,7 @@ - + From 46bfa4db29da2bb501a98a97c4cd39ba74d1c355 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Aug 2017 22:31:23 +0900 Subject: [PATCH 021/180] Load defaults, pass around live IEnumerable, add PK for updating --- .../Input/Bindings/DatabasedKeyBinding.cs | 5 +- .../DatabasedKeyBindingInputManager.cs | 3 +- osu.Game/Input/KeyBindingStore.cs | 50 +++++++++++++++---- osu.Game/OsuGameBase.cs | 2 +- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index 3870cc5b04..73896b5ffe 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -11,6 +11,9 @@ namespace osu.Game.Input.Bindings [Table("KeyBinding")] public class DatabasedKeyBinding : KeyBinding { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + [ForeignKey(typeof(RulesetInfo))] public int? RulesetID { get; set; } @@ -28,7 +31,7 @@ namespace osu.Game.Input.Bindings public new int Action { get { return (int)base.Action; } - private set { base.Action = value; } + set { base.Action = value; } } } } \ No newline at end of file diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index 52e5af152c..a02dd00a77 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -44,8 +44,7 @@ namespace osu.Game.Input.Bindings protected override void ReloadMappings() { - KeyBindings.Clear(); - KeyBindings.AddRange(store.GetProcessedList(DefaultMappings, ruleset?.ID, variant)); + KeyBindings = store.GetProcessedList(DefaultMappings, ruleset?.ID, variant); } } } \ No newline at end of file diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index e26942a06c..0cd556289f 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -3,22 +3,35 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.Input.Bindings; +using osu.Game.Rulesets; using SQLite.Net; namespace osu.Game.Input { public class KeyBindingStore : DatabaseBackedStore { - public KeyBindingStore(SQLiteConnection connection, Storage storage = null) + public KeyBindingStore(SQLiteConnection connection, RulesetStore rulesets, Storage storage = null) : base(connection, storage) { + foreach (var info in rulesets.Query()) + { + var ruleset = info.CreateInstance(); + foreach (var variant in ruleset.AvailableVariants) + GetProcessedList(ruleset.GetDefaultKeyBindings(), info.ID, variant); + } } - protected override int StoreVersion => 2; + public void Register(KeyBindingInputManager manager) + { + GetProcessedList(manager.DefaultMappings); + } + + protected override int StoreVersion => 3; protected override void PerformMigration(int currentVersion, int targetVersion) { @@ -29,6 +42,8 @@ namespace osu.Game.Input switch (currentVersion) { case 1: + case 2: + case 3: // cannot migrate; breaking underlying changes. Reset(); break; @@ -38,6 +53,11 @@ namespace osu.Game.Input protected override void Prepare(bool reset = false) { + if (reset) + { + Connection.DropTable(); + } + Connection.CreateTable(); } @@ -46,16 +66,28 @@ namespace osu.Game.Input typeof(DatabasedKeyBinding) }; - public List GetProcessedList(IEnumerable defaults, int? rulesetId, int? variant) + public IEnumerable GetProcessedList(IEnumerable defaults, int? rulesetId = null, int? variant = null) { - //todo: cache and share reference - List bindings = new List(defaults); + var databaseEntries = Query(b => b.RulesetID == rulesetId && b.Variant == variant); - // load from database if present. - foreach (var b in Query(b => b.RulesetID == rulesetId && b.Variant == variant)) - bindings.Add(b); + if (!databaseEntries.Any()) + { + // if there are no entries for this category in the database, we should populate our defaults. + Connection.InsertAll(defaults.Select(k => new DatabasedKeyBinding + { + KeyCombination = k.KeyCombination, + Action = (int)k.Action, + RulesetID = rulesetId, + Variant = variant + })); + } - return bindings; + return databaseEntries; + } + + public void Update(KeyBinding keyBinding) + { + Connection.Update(keyBinding); } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index d72716b5d6..54b091d7d9 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -108,7 +108,7 @@ namespace osu.Game dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager)); - dependencies.Cache(KeyBindingStore = new KeyBindingStore(connection)); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(connection, RulesetStore)); dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. From 4da76cd98e8164155a21f7a0ab88954e8a1ffaaa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Aug 2017 22:31:35 +0900 Subject: [PATCH 022/180] Initial key configuration UI implementation --- .../Visual/TestCaseKeyConfiguration.cs | 355 +++++++++++++++++- 1 file changed, 348 insertions(+), 7 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 10a15d0a96..077417577a 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,10 +1,27 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using System.Linq; using osu.Game.Overlays; using osu.Game.Overlays.Settings; -using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Input; +using osu.Game.Rulesets; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Input; +using OpenTK.Input; namespace osu.Desktop.Tests.Visual { @@ -29,16 +46,340 @@ namespace osu.Desktop.Tests.Visual public class KeyConfiguration : SettingsOverlay { - protected override IEnumerable CreateSections() => new[] + protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(RulesetStore rulesets, GlobalBindingInputManager global) { - new BindingsSection(), - new BindingsSection() - }; + AddSection(new GlobalBindingsSection(global, "Global")); + + foreach (var ruleset in rulesets.Query()) + AddSection(new RulesetBindingsSection(ruleset)); + } + + public KeyConfiguration() + : base(false) + { + } } - public class BindingsSection : SettingsSection + public class GlobalBindingsSection : KeyBindingsSection + { + private readonly string name; + + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => name; + + public GlobalBindingsSection(KeyBindingInputManager manager, string name) + { + this.name = name; + + Defaults = manager.DefaultMappings; + } + } + + public class RulesetBindingsSection : KeyBindingsSection { public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => "Header"; + public override string Header => Ruleset.Name; + + public RulesetBindingsSection(RulesetInfo ruleset) + { + Ruleset = ruleset; + + Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); + } + } + + public abstract class KeyBindingsSection : SettingsSection + { + protected IEnumerable Defaults; + + protected RulesetInfo Ruleset; + + protected KeyBindingsSection() + { + FlowContent.Spacing = new Vector2(0, 1); + } + + [BackgroundDependencyLoader] + private void load(KeyBindingStore store) + { + var firstDefault = Defaults?.FirstOrDefault(); + + if (firstDefault == null) return; + + var actionType = firstDefault.Action.GetType(); + + var bindings = store.GetProcessedList(Defaults, Ruleset?.ID); + + foreach (Enum v in Enum.GetValues(actionType)) + { + Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); + } + } + } + + internal class KeyBindingRow : Container, IFilterable + { + private readonly Enum action; + private readonly IEnumerable bindings; + + private const float transition_time = 150; + + private const float height = 20; + + private const float padding = 5; + + private bool matchingFilter; + + public bool MatchingFilter + { + get { return matchingFilter; } + set + { + matchingFilter = value; + this.FadeTo(!matchingFilter ? 0 : 1); + } + } + + private OsuSpriteText text; + private OsuSpriteText pressAKey; + + private FillFlowContainer buttons; + + public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); + + public KeyBindingRow(Enum action, IEnumerable bindings) + { + this.action = action; + this.bindings = bindings; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Masking = true; + CornerRadius = padding; + } + + private KeyBindingStore store; + + [BackgroundDependencyLoader] + private void load(OsuColour colours, KeyBindingStore store) + { + this.store = store; + + EdgeEffect = new EdgeEffectParameters + { + Radius = 2, + Colour = colours.YellowDark.Opacity(0), + Type = EdgeEffectType.Shadow, + Hollow = true, + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + text = new OsuSpriteText + { + Text = action.GetDescription(), + Margin = new MarginPadding(padding), + }, + buttons = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + pressAKey = new OsuSpriteText + { + Text = "Press a key to change the binding, or ESC to cancel.", + Y = height, + Margin = new MarginPadding(padding), + Alpha = 0, + Colour = colours.YellowDark + } + }; + + reloadBindings(); + } + + private void reloadBindings() + { + buttons.Clear(); + foreach (var b in bindings) + buttons.Add(new KeyButton(b)); + } + + protected override bool OnHover(InputState state) + { + this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + this.FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + + public override bool AcceptsFocus => true; + + private KeyButton bindTarget; + + protected override void OnFocus(InputState state) + { + AutoSizeDuration = 500; + AutoSizeEasing = Easing.OutQuint; + + pressAKey.FadeIn(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding(); + + base.OnFocus(state); + } + + private bool isModifier(Key k) => k < Key.F1; + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (HasFocus) + { + if (!isModifier(args.Key)) + { + bindTarget.KeyBinding.KeyCombination = new KeyCombination(state.Keyboard.Keys); + store.Update(bindTarget.KeyBinding); + GetContainingInputManager().ChangeFocus(null); + } + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override void OnFocusLost(InputState state) + { + bindTarget.IsBinding = false; + bindTarget = null; + reloadBindings(); + + pressAKey.FadeOut(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + base.OnFocusLost(state); + } + + protected override bool OnClick(InputState state) + { + bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); + if (bindTarget != null) bindTarget.IsBinding = true; + + return bindTarget != null; + } + + private class KeyButton : Container + { + public readonly KeyBinding KeyBinding; + + private readonly Box box; + public readonly OsuSpriteText Text; + + private Color4 hoverColour; + + private bool isBinding; + + public bool IsBinding + { + get { return isBinding; } + set + { + isBinding = value; + + if (value) + { + box.FadeColour(Color4.White, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + } + else + { + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + } + } + } + + public KeyButton(KeyBinding keyBinding) + { + KeyBinding = keyBinding; + + Margin = new MarginPadding(padding); + + var isDefault = keyBinding.Action is Enum; + + Masking = true; + CornerRadius = padding; + + Height = height; + AutoSizeAxes = Axes.X; + + Children = new Drawable[] + { + new Container + { + AlwaysPresent = true, + Width = 80, + Height = height, + }, + box = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + Text = new OsuSpriteText + { + Font = "Venera", + TextSize = 10, + Margin = new MarginPadding(5), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = keyBinding.KeyCombination.ReadableString(), + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.YellowDark; + } + + protected override bool OnHover(InputState state) + { + if (isBinding) + return false; + + box.FadeColour(hoverColour, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (isBinding) + return; + + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + } } } From 70f148f0b4ab7cc2eb7fc9a78cd4bb33fce082ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 09:30:46 +0900 Subject: [PATCH 023/180] Fix icons on skip button --- osu.Game/Screens/Play/SkipButton.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/SkipButton.cs b/osu.Game/Screens/Play/SkipButton.cs index a67cf4e5ea..3cf371f1e1 100644 --- a/osu.Game/Screens/Play/SkipButton.cs +++ b/osu.Game/Screens/Play/SkipButton.cs @@ -227,9 +227,9 @@ namespace osu.Game.Screens.Play Direction = FillDirection.Horizontal, Children = new[] { - new SpriteIcon { Icon = FontAwesome.fa_chevron_right }, - new SpriteIcon { Icon = FontAwesome.fa_chevron_right }, - new SpriteIcon { Icon = FontAwesome.fa_chevron_right }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_right }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_right }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_right }, } }, new OsuSpriteText From 97ac8e1a64b2bacf8697423ad124965ede65dbc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Aug 2017 11:03:03 +0900 Subject: [PATCH 024/180] Update usages of IsAlive/IsLoaded in line with framework changes --- osu.Desktop.Tests/Visual/TestCaseNotificationOverlay.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs | 2 +- osu.Game/Screens/BackgroundScreen.cs | 2 +- osu.Game/Screens/Play/KeyCounterCollection.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Desktop.Tests/Visual/TestCaseNotificationOverlay.cs index b9e492593f..1e46fbda35 100644 --- a/osu.Desktop.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Desktop.Tests/Visual/TestCaseNotificationOverlay.cs @@ -68,7 +68,7 @@ namespace osu.Desktop.Tests.Visual while (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3) { - var p = progressingNotifications.FirstOrDefault(n => n.IsLoaded && n.State == ProgressNotificationState.Queued); + var p = progressingNotifications.FirstOrDefault(n => n.IsAlive && n.State == ProgressNotificationState.Queued); if (p == null) break; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 8b9441ea65..680f987274 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return; accentColour = value; - if (LoadState == LoadState.Loaded) + if (LoadState == LoadState.Ready) Schedule(reloadTexture); } } diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index c5bbf04075..5b07ca6020 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens } // Make sure the in-progress loading is complete before pushing the screen. - while (screen.LoadState < LoadState.Loaded) + while (screen.LoadState < LoadState.Ready) Thread.Sleep(1); base.Push(screen); diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 01e20fdbd7..63c29a8f78 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -108,7 +108,7 @@ namespace osu.Game.Screens.Play } } - public override bool HandleInput => receptor?.IsAlive != true; + public override bool HandleInput => receptor == null; private Receptor receptor; From a74ebdfe568bfd94a20756ac880981279e2a159e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 14:30:25 +0900 Subject: [PATCH 025/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 2a56eb0619..4a213a02aa 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 2a56eb0619adf654ed4927af1a4b227596c87494 +Subproject commit 4a213a02aa09b0fd8bd119eb391549ca1fa00f95 From 6ded194c5317cc6bdae056c377433bb394c8f05e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 14:30:50 +0900 Subject: [PATCH 026/180] Remove all usage of DI to retrieve InputManager Uses GetContainingInputManager instead, as per framework changes. --- osu.Game/Graphics/Containers/ParallaxContainer.cs | 9 +++++++-- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 10 +--------- osu.Game/Overlays/Music/PlaylistOverlay.cs | 6 ++---- .../Settings/Sections/General/LoginSettings.cs | 15 +++++---------- osu.Game/Screens/Select/FilterControl.cs | 8 ++------ osu.Game/Screens/Select/SongSelect.cs | 8 ++++---- 6 files changed, 21 insertions(+), 35 deletions(-) diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index ec9d30f244..3e0ed4b059 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -34,9 +34,8 @@ namespace osu.Game.Graphics.Containers protected override Container Content => content; [BackgroundDependencyLoader] - private void load(UserInputManager input, OsuConfigManager config) + private void load(OsuConfigManager config) { - this.input = input; parallaxEnabled = config.GetBindable(OsuSetting.MenuParallax); parallaxEnabled.ValueChanged += delegate { @@ -48,6 +47,12 @@ namespace osu.Game.Graphics.Containers }; } + protected override void LoadComplete() + { + base.LoadComplete(); + input = GetContainingInputManager(); + } + private bool firstUpdate = true; protected override void Update() diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 447daca75e..4817212f7a 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -28,18 +28,10 @@ namespace osu.Game.Graphics.UserInterface { focus = value; if (!focus && HasFocus) - inputManager.ChangeFocus(null); + GetContainingInputManager().ChangeFocus(null); } } - private InputManager inputManager; - - [BackgroundDependencyLoader] - private void load(UserInputManager inputManager) - { - this.inputManager = inputManager; - } - protected override void OnFocus(InputState state) { base.OnFocus(state); diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 942633b35e..2681c8bbb8 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -31,12 +31,10 @@ namespace osu.Game.Overlays.Music private readonly Bindable beatmapBacking = new Bindable(); public IEnumerable BeatmapSets; - private InputManager inputManager; [BackgroundDependencyLoader] - private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours, UserInputManager inputManager) + private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours) { - this.inputManager = inputManager; this.beatmaps = beatmaps; Children = new Drawable[] @@ -102,7 +100,7 @@ namespace osu.Game.Overlays.Music protected override void PopIn() { filter.Search.HoldFocus = true; - Schedule(() => inputManager.ChangeFocus(filter.Search)); + Schedule(() => GetContainingInputManager().ChangeFocus(filter.Search)); this.ResizeTo(new Vector2(1, playlist_height), transition_duration, Easing.OutQuint); this.FadeIn(transition_duration, Easing.OutQuint); diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index d07f156673..3f8b6186c4 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -57,12 +57,9 @@ namespace osu.Game.Overlays.Settings.Sections.General Spacing = new Vector2(0f, 5f); } - private InputManager inputManager; - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, APIAccess api, UserInputManager inputManager) + private void load(OsuColour colours, APIAccess api) { - this.inputManager = inputManager; this.colours = colours; api?.Register(this); @@ -174,7 +171,7 @@ namespace osu.Game.Overlays.Settings.Sections.General break; } - if (form != null) inputManager.ChangeFocus(form); + if (form != null) GetContainingInputManager().ChangeFocus(form); } public override bool AcceptsFocus => true; @@ -183,7 +180,7 @@ namespace osu.Game.Overlays.Settings.Sections.General protected override void OnFocus(InputState state) { - if (form != null) inputManager.ChangeFocus(form); + if (form != null) GetContainingInputManager().ChangeFocus(form); base.OnFocus(state); } @@ -192,7 +189,6 @@ namespace osu.Game.Overlays.Settings.Sections.General private TextBox username; private TextBox password; private APIAccess api; - private InputManager inputManager; private void performLogin() { @@ -201,9 +197,8 @@ namespace osu.Game.Overlays.Settings.Sections.General } [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, OsuConfigManager config, UserInputManager inputManager) + private void load(APIAccess api, OsuConfigManager config) { - this.inputManager = inputManager; this.api = api; Direction = FillDirection.Vertical; Spacing = new Vector2(0, 5); @@ -256,7 +251,7 @@ namespace osu.Game.Overlays.Settings.Sections.General protected override void OnFocus(InputState state) { - Schedule(() => { inputManager.ChangeFocus(string.IsNullOrEmpty(username.Text) ? username : password); }); + Schedule(() => { GetContainingInputManager().ChangeFocus(string.IsNullOrEmpty(username.Text) ? username : password); }); } } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 838e6f7123..e83613125b 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -153,7 +153,7 @@ namespace osu.Game.Screens.Select { searchTextBox.HoldFocus = false; if (searchTextBox.HasFocus) - inputManager.ChangeFocus(searchTextBox); + GetContainingInputManager().ChangeFocus(searchTextBox); } public void Activate() @@ -163,13 +163,9 @@ namespace osu.Game.Screens.Select private readonly Bindable ruleset = new Bindable(); - private InputManager inputManager; - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame osu, UserInputManager inputManager) + private void load(OsuColour colours, OsuGame osu) { - this.inputManager = inputManager; - sortTabs.AccentColour = colours.GreenLight; if (osu != null) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 8f545240c8..afab9e8746 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -156,11 +156,11 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours, UserInputManager input) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours) { if (Footer != null) { - Footer.AddButton(@"random", colours.Green, () => triggerRandom(input), Key.F2); + Footer.AddButton(@"random", colours.Green, triggerRandom, Key.F2); Footer.AddButton(@"options", colours.Blue, BeatmapOptions.ToggleVisibility, Key.F3); BeatmapOptions.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, colours.Pink, promptDelete, Key.Number4, float.MaxValue); @@ -267,9 +267,9 @@ namespace osu.Game.Screens.Select } } - private void triggerRandom(UserInputManager input) + private void triggerRandom() { - if (input.CurrentState.Keyboard.ShiftPressed) + if (GetContainingInputManager().CurrentState.Keyboard.ShiftPressed) carousel.SelectPreviousRandom(); else carousel.SelectNextRandom(); From 9e5deb63d1bc7d8a409012d1c93f362e39caca09 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Tue, 15 Aug 2017 16:42:26 +0930 Subject: [PATCH 027/180] Fix spinner not handling left/right action bindings --- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index cd808abe9d..99c287f6fb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -5,13 +5,14 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { - public class SpinnerDisc : CircularContainer, IHasAccentColour + public class SpinnerDisc : CircularContainer, IHasAccentColour, IKeyBindingHandler { private readonly Spinner spinner; @@ -66,26 +67,53 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } + private void updateTracking() + { + Tracking = mouseHasMainButtonPressed || actionLeftButtonPressed || actionRightButtonPressed; + } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - Tracking |= state.Mouse.HasMainButtonPressed; + mouseHasMainButtonPressed |= state.Mouse.HasMainButtonPressed; + updateTracking(); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - Tracking &= state.Mouse.HasMainButtonPressed; + mouseHasMainButtonPressed &= state.Mouse.HasMainButtonPressed; + updateTracking(); return base.OnMouseUp(state, args); } protected override bool OnMouseMove(InputState state) { - Tracking |= state.Mouse.HasMainButtonPressed; + mouseHasMainButtonPressed |= state.Mouse.HasMainButtonPressed; mousePosition = Parent.ToLocalSpace(state.Mouse.NativeState.Position); + updateTracking(); return base.OnMouseMove(state); } + public bool OnPressed(OsuAction action) + { + actionLeftButtonPressed |= action == OsuAction.LeftButton; + actionRightButtonPressed |= action == OsuAction.RightButton; + updateTracking(); + return false; + } + + public bool OnReleased(OsuAction action) + { + actionLeftButtonPressed &= action == OsuAction.LeftButton; + actionRightButtonPressed &= action == OsuAction.RightButton; + updateTracking(); + return false; + } + private Vector2 mousePosition; + private bool mouseHasMainButtonPressed; + private bool actionLeftButtonPressed; + private bool actionRightButtonPressed; private float lastAngle; private float currentRotation; From 143ff695efd03e163c558f5bebbbeb70cb0d81b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 17:44:04 +0900 Subject: [PATCH 028/180] Remove unused using statements --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 1 - osu.Game/Overlays/Music/PlaylistOverlay.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 4817212f7a..dbbb069f7c 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -3,7 +3,6 @@ using OpenTK.Graphics; using OpenTK.Input; -using osu.Framework.Allocation; using osu.Framework.Input; using System; using System.Linq; diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 2681c8bbb8..83e92c5554 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Input; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; From 3bee36f6a2faf447cb863984b562013e93436a01 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 23:59:06 +0900 Subject: [PATCH 029/180] Add index to Action column Is used for default assignment --- osu.Game/Input/Bindings/DatabasedKeyBinding.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index 73896b5ffe..c0197ce3dc 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -27,6 +27,7 @@ namespace osu.Game.Input.Bindings private set { KeyCombination = value; } } + [Indexed] [Column("Action")] public new int Action { From 2bd098173818718c533166d7da9805f86e4625b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Aug 2017 23:59:58 +0900 Subject: [PATCH 030/180] Improve default key binding logic Defaults will be added to the database as long as the database has unbalanced counts for any actions. --- .../DatabasedKeyBindingInputManager.cs | 2 +- osu.Game/Input/KeyBindingStore.cs | 51 ++++++++++--------- osu.Game/OsuGameBase.cs | 1 + 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index a02dd00a77..e565c13b31 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -44,7 +44,7 @@ namespace osu.Game.Input.Bindings protected override void ReloadMappings() { - KeyBindings = store.GetProcessedList(DefaultMappings, ruleset?.ID, variant); + KeyBindings = store.Query(ruleset?.ID, variant); } } } \ No newline at end of file diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 0cd556289f..057fa4d4e7 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -22,14 +22,11 @@ namespace osu.Game.Input { var ruleset = info.CreateInstance(); foreach (var variant in ruleset.AvailableVariants) - GetProcessedList(ruleset.GetDefaultKeyBindings(), info.ID, variant); + insertDefaults(ruleset.GetDefaultKeyBindings(), info.ID, variant); } } - public void Register(KeyBindingInputManager manager) - { - GetProcessedList(manager.DefaultMappings); - } + public void Register(KeyBindingInputManager manager) => insertDefaults(manager.DefaultMappings); protected override int StoreVersion => 3; @@ -61,29 +58,37 @@ namespace osu.Game.Input Connection.CreateTable(); } + private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) + { + var query = Query(rulesetId, variant); + + // compare counts in database vs defaults + foreach (var group in defaults.GroupBy(k => k.Action)) + { + int count; + while (group.Count() > (count = query.Count(k => (int)k.Action == (int)group.Key))) + { + var insertable = group.Skip(count).First(); + + // insert any defaults which are missing. + Connection.Insert(new DatabasedKeyBinding + { + KeyCombination = insertable.KeyCombination, + Action = (int)insertable.Action, + RulesetID = rulesetId, + Variant = variant + }); + } + } + } + protected override Type[] ValidTypes => new[] { typeof(DatabasedKeyBinding) }; - public IEnumerable GetProcessedList(IEnumerable defaults, int? rulesetId = null, int? variant = null) - { - var databaseEntries = Query(b => b.RulesetID == rulesetId && b.Variant == variant); - - if (!databaseEntries.Any()) - { - // if there are no entries for this category in the database, we should populate our defaults. - Connection.InsertAll(defaults.Select(k => new DatabasedKeyBinding - { - KeyCombination = k.KeyCombination, - Action = (int)k.Action, - RulesetID = rulesetId, - Variant = variant - })); - } - - return databaseEntries; - } + public IEnumerable Query(int? rulesetId = null, int? variant = null) => + Query(b => b.RulesetID == rulesetId && b.Variant == variant); public void Update(KeyBinding keyBinding) { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 54b091d7d9..571c75022e 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -202,6 +202,7 @@ namespace osu.Game } }); + KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); // TODO: This is temporary until we reimplement the local FPS display. From 9c75df884fe67c41b0d77b21bbe480119f88746b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 00:08:59 +0900 Subject: [PATCH 031/180] Add initial implementation of KeyConfiguration overlay --- .../Visual/TestCaseKeyConfiguration.cs | 362 +----------------- .../KeyConfiguration/GlobalBindingsSection.cs | 23 ++ .../KeyConfiguration/KeyBindingRow.cs | 284 ++++++++++++++ .../KeyConfiguration/KeyBindingsSection.cs | 51 +++ .../KeyConfiguration/KeyConfiguration.cs | 30 ++ .../RulesetBindingsSection.cs | 21 + osu.Game/osu.Game.csproj | 5 + 7 files changed, 415 insertions(+), 361 deletions(-) create mode 100644 osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs create mode 100644 osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs create mode 100644 osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs create mode 100644 osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs create mode 100644 osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 077417577a..69489c51a1 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,27 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Overlays; -using osu.Game.Overlays.Settings; -using osu.Framework.Allocation; -using osu.Framework.Extensions; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Input; -using osu.Game.Rulesets; -using osu.Framework.Input.Bindings; -using osu.Game.Input.Bindings; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Input; -using OpenTK.Input; +using osu.Game.Overlays.KeyConfiguration; namespace osu.Desktop.Tests.Visual { @@ -39,347 +19,7 @@ namespace osu.Desktop.Tests.Visual protected override void LoadComplete() { base.LoadComplete(); - configuration.Show(); } } - - public class KeyConfiguration : SettingsOverlay - { - protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); - - [BackgroundDependencyLoader(permitNulls: true)] - private void load(RulesetStore rulesets, GlobalBindingInputManager global) - { - AddSection(new GlobalBindingsSection(global, "Global")); - - foreach (var ruleset in rulesets.Query()) - AddSection(new RulesetBindingsSection(ruleset)); - } - - public KeyConfiguration() - : base(false) - { - } - } - - public class GlobalBindingsSection : KeyBindingsSection - { - private readonly string name; - - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => name; - - public GlobalBindingsSection(KeyBindingInputManager manager, string name) - { - this.name = name; - - Defaults = manager.DefaultMappings; - } - } - - public class RulesetBindingsSection : KeyBindingsSection - { - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => Ruleset.Name; - - public RulesetBindingsSection(RulesetInfo ruleset) - { - Ruleset = ruleset; - - Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); - } - } - - public abstract class KeyBindingsSection : SettingsSection - { - protected IEnumerable Defaults; - - protected RulesetInfo Ruleset; - - protected KeyBindingsSection() - { - FlowContent.Spacing = new Vector2(0, 1); - } - - [BackgroundDependencyLoader] - private void load(KeyBindingStore store) - { - var firstDefault = Defaults?.FirstOrDefault(); - - if (firstDefault == null) return; - - var actionType = firstDefault.Action.GetType(); - - var bindings = store.GetProcessedList(Defaults, Ruleset?.ID); - - foreach (Enum v in Enum.GetValues(actionType)) - { - Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); - } - } - } - - internal class KeyBindingRow : Container, IFilterable - { - private readonly Enum action; - private readonly IEnumerable bindings; - - private const float transition_time = 150; - - private const float height = 20; - - private const float padding = 5; - - private bool matchingFilter; - - public bool MatchingFilter - { - get { return matchingFilter; } - set - { - matchingFilter = value; - this.FadeTo(!matchingFilter ? 0 : 1); - } - } - - private OsuSpriteText text; - private OsuSpriteText pressAKey; - - private FillFlowContainer buttons; - - public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); - - public KeyBindingRow(Enum action, IEnumerable bindings) - { - this.action = action; - this.bindings = bindings; - - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Masking = true; - CornerRadius = padding; - } - - private KeyBindingStore store; - - [BackgroundDependencyLoader] - private void load(OsuColour colours, KeyBindingStore store) - { - this.store = store; - - EdgeEffect = new EdgeEffectParameters - { - Radius = 2, - Colour = colours.YellowDark.Opacity(0), - Type = EdgeEffectType.Shadow, - Hollow = true, - }; - - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - text = new OsuSpriteText - { - Text = action.GetDescription(), - Margin = new MarginPadding(padding), - }, - buttons = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight - }, - pressAKey = new OsuSpriteText - { - Text = "Press a key to change the binding, or ESC to cancel.", - Y = height, - Margin = new MarginPadding(padding), - Alpha = 0, - Colour = colours.YellowDark - } - }; - - reloadBindings(); - } - - private void reloadBindings() - { - buttons.Clear(); - foreach (var b in bindings) - buttons.Add(new KeyButton(b)); - } - - protected override bool OnHover(InputState state) - { - this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); - - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - this.FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); - - base.OnHoverLost(state); - } - - public override bool AcceptsFocus => true; - - private KeyButton bindTarget; - - protected override void OnFocus(InputState state) - { - AutoSizeDuration = 500; - AutoSizeEasing = Easing.OutQuint; - - pressAKey.FadeIn(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding(); - - base.OnFocus(state); - } - - private bool isModifier(Key k) => k < Key.F1; - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (HasFocus) - { - if (!isModifier(args.Key)) - { - bindTarget.KeyBinding.KeyCombination = new KeyCombination(state.Keyboard.Keys); - store.Update(bindTarget.KeyBinding); - GetContainingInputManager().ChangeFocus(null); - } - return true; - } - - return base.OnKeyDown(state, args); - } - - protected override void OnFocusLost(InputState state) - { - bindTarget.IsBinding = false; - bindTarget = null; - reloadBindings(); - - pressAKey.FadeOut(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; - base.OnFocusLost(state); - } - - protected override bool OnClick(InputState state) - { - bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); - if (bindTarget != null) bindTarget.IsBinding = true; - - return bindTarget != null; - } - - private class KeyButton : Container - { - public readonly KeyBinding KeyBinding; - - private readonly Box box; - public readonly OsuSpriteText Text; - - private Color4 hoverColour; - - private bool isBinding; - - public bool IsBinding - { - get { return isBinding; } - set - { - isBinding = value; - - if (value) - { - box.FadeColour(Color4.White, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - - } - else - { - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - } - } - } - - public KeyButton(KeyBinding keyBinding) - { - KeyBinding = keyBinding; - - Margin = new MarginPadding(padding); - - var isDefault = keyBinding.Action is Enum; - - Masking = true; - CornerRadius = padding; - - Height = height; - AutoSizeAxes = Axes.X; - - Children = new Drawable[] - { - new Container - { - AlwaysPresent = true, - Width = 80, - Height = height, - }, - box = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - Text = new OsuSpriteText - { - Font = "Venera", - TextSize = 10, - Margin = new MarginPadding(5), - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = keyBinding.KeyCombination.ReadableString(), - }, - }; - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - hoverColour = colours.YellowDark; - } - - protected override bool OnHover(InputState state) - { - if (isBinding) - return false; - - box.FadeColour(hoverColour, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - if (isBinding) - return; - - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - - base.OnHoverLost(state); - } - } - } } diff --git a/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs new file mode 100644 index 0000000000..9d68b41045 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class GlobalBindingsSection : KeyBindingsSection + { + private readonly string name; + + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => name; + + public GlobalBindingsSection(KeyBindingInputManager manager, string name) + { + this.name = name; + + Defaults = manager.DefaultMappings; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs new file mode 100644 index 0000000000..a9ef10eae6 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs @@ -0,0 +1,284 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Extensions; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.Input.Bindings; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Input; +using OpenTK.Graphics; +using OpenTK.Input; + +namespace osu.Game.Overlays.KeyConfiguration +{ + internal class KeyBindingRow : Container, IFilterable + { + private readonly Enum action; + private readonly IEnumerable bindings; + + private const float transition_time = 150; + + private const float height = 20; + + private const float padding = 5; + + private bool matchingFilter; + + public bool MatchingFilter + { + get { return matchingFilter; } + set + { + matchingFilter = value; + this.FadeTo(!matchingFilter ? 0 : 1); + } + } + + private OsuSpriteText text; + private OsuSpriteText pressAKey; + + private FillFlowContainer buttons; + + public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); + + public KeyBindingRow(Enum action, IEnumerable bindings) + { + this.action = action; + this.bindings = bindings; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Masking = true; + CornerRadius = padding; + } + + private KeyBindingStore store; + + [BackgroundDependencyLoader] + private void load(OsuColour colours, KeyBindingStore store) + { + this.store = store; + + EdgeEffect = new EdgeEffectParameters + { + Radius = 2, + Colour = colours.YellowDark.Opacity(0), + Type = EdgeEffectType.Shadow, + Hollow = true, + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, + }, + text = new OsuSpriteText + { + Text = action.GetDescription(), + Margin = new MarginPadding(padding), + }, + buttons = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight + }, + pressAKey = new OsuSpriteText + { + Text = "Press a key to change binding, DEL to delete, ESC to cancel.", + Y = height, + Margin = new MarginPadding(padding), + Alpha = 0, + Colour = colours.YellowDark + } + }; + + reloadBindings(); + } + + private void reloadBindings() + { + buttons.Clear(); + foreach (var b in bindings) + buttons.Add(new KeyButton(b)); + } + + protected override bool OnHover(InputState state) + { + this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + this.FadeEdgeEffectTo(0, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + + public override bool AcceptsFocus => true; + + private KeyButton bindTarget; + + protected override void OnFocus(InputState state) + { + AutoSizeDuration = 500; + AutoSizeEasing = Easing.OutQuint; + + pressAKey.FadeIn(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding(); + + base.OnFocus(state); + } + + private bool isModifier(Key k) => k < Key.F1; + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (HasFocus && !isModifier(args.Key)) + { + bindTarget.KeyBinding.KeyCombination = args.Key == Key.Delete ? Key.Unknown : new KeyCombination(state.Keyboard.Keys); + + store.Update(bindTarget.KeyBinding); + GetContainingInputManager().ChangeFocus(null); + return true; + } + + return base.OnKeyDown(state, args); + } + + protected override void OnFocusLost(InputState state) + { + bindTarget.IsBinding = false; + bindTarget = null; + reloadBindings(); + + pressAKey.FadeOut(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + base.OnFocusLost(state); + } + + protected override bool OnClick(InputState state) + { + if (bindTarget != null) bindTarget.IsBinding = false; + bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); + if (bindTarget != null) bindTarget.IsBinding = true; + + return bindTarget != null; + } + + private class KeyButton : Container + { + public readonly KeyBinding KeyBinding; + + private readonly Box box; + public readonly OsuSpriteText Text; + + private Color4 hoverColour; + + private bool isBinding; + + public bool IsBinding + { + get { return isBinding; } + set + { + isBinding = value; + + if (value) + { + box.FadeColour(Color4.White, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + } + else + { + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + } + } + } + + public KeyButton(KeyBinding keyBinding) + { + KeyBinding = keyBinding; + + Margin = new MarginPadding(padding); + + //var isDefault = keyBinding.Action is Enum; + + Masking = true; + CornerRadius = padding; + + Height = height; + AutoSizeAxes = Axes.X; + + Children = new Drawable[] + { + new Container + { + AlwaysPresent = true, + Width = 80, + Height = height, + }, + box = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + Text = new OsuSpriteText + { + Font = "Venera", + TextSize = 10, + Margin = new MarginPadding(5), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = keyBinding.KeyCombination.ReadableString(), + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.YellowDark; + } + + protected override bool OnHover(InputState state) + { + if (isBinding) + return false; + + box.FadeColour(hoverColour, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + if (isBinding) + return; + + box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs new file mode 100644 index 0000000000..1e574d5e55 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Input.Bindings; +using osu.Game.Input; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets; +using OpenTK; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public abstract class KeyBindingsSection : SettingsSection + { + protected IEnumerable Defaults; + + protected RulesetInfo Ruleset; + + protected KeyBindingsSection() + { + FlowContent.Spacing = new Vector2(0, 1); + } + + [BackgroundDependencyLoader] + private void load(KeyBindingStore store) + { + var firstDefault = Defaults?.FirstOrDefault(); + + if (firstDefault == null) return; + + var actionType = firstDefault.Action.GetType(); + + int? variant = null; + + // for now let's just assume a variant of zero. + // this will need to be implemented in a better way in the future. + if (Ruleset != null) + variant = 0; + + var bindings = store.Query(Ruleset?.ID, variant); + + foreach (Enum v in Enum.GetValues(actionType)) + { + Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs b/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs new file mode 100644 index 0000000000..416f828495 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs @@ -0,0 +1,30 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Input.Bindings; +using osu.Game.Overlays.Settings; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class KeyConfiguration : SettingsOverlay + { + protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); + + [BackgroundDependencyLoader(permitNulls: true)] + private void load(RulesetStore rulesets, GlobalBindingInputManager global) + { + AddSection(new GlobalBindingsSection(global, "Global")); + + foreach (var ruleset in rulesets.Query()) + AddSection(new RulesetBindingsSection(ruleset)); + } + + public KeyConfiguration() + : base(false) + { + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs new file mode 100644 index 0000000000..038df5e122 --- /dev/null +++ b/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyConfiguration +{ + public class RulesetBindingsSection : KeyBindingsSection + { + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Header => Ruleset.Name; + + public RulesetBindingsSection(RulesetInfo ruleset) + { + Ruleset = ruleset; + + Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); + } + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b324fb9f92..6eb0ece6ed 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -102,6 +102,11 @@ + + + + + From 72eb082f916b849ad58041ecf27fa89e6da2251b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 01:14:37 +0900 Subject: [PATCH 032/180] Use .Equals --- osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs index 1e574d5e55..b7b07ab2f8 100644 --- a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs @@ -44,7 +44,7 @@ namespace osu.Game.Overlays.KeyConfiguration foreach (Enum v in Enum.GetValues(actionType)) { - Add(new KeyBindingRow(v, bindings.Where(b => (int)b.Action == (int)(object)v))); + Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v)))); } } } From c221472d6ee7e01c59bde8a085371c760a216ca2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 01:19:21 +0900 Subject: [PATCH 033/180] Code tidy-ups --- .../KeyConfiguration/KeyBindingsSection.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs index b7b07ab2f8..fe72c64edb 100644 --- a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs @@ -27,25 +27,21 @@ namespace osu.Game.Overlays.KeyConfiguration [BackgroundDependencyLoader] private void load(KeyBindingStore store) { - var firstDefault = Defaults?.FirstOrDefault(); + var enumType = Defaults?.FirstOrDefault()?.Action?.GetType(); - if (firstDefault == null) return; - - var actionType = firstDefault.Action.GetType(); - - int? variant = null; + if (enumType == null) return; // for now let's just assume a variant of zero. // this will need to be implemented in a better way in the future. + int? variant = null; if (Ruleset != null) variant = 0; var bindings = store.Query(Ruleset?.ID, variant); - foreach (Enum v in Enum.GetValues(actionType)) - { + foreach (Enum v in Enum.GetValues(enumType)) + // one row per valid action. Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v)))); - } } } } \ No newline at end of file From 6ee4716ec53e378da4e91a394dd7d1b0878cd61c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 12:39:18 +0900 Subject: [PATCH 034/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 2a56eb0619..e5b0f1c9d0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 2a56eb0619adf654ed4927af1a4b227596c87494 +Subproject commit e5b0f1c9d0c98ee89563042071e516d5304a6d06 From a5007fc64fa3c661f29b5f7b4978af932252db9b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 13:07:18 +0900 Subject: [PATCH 035/180] Fix some remaining usage of local InputManager instances --- osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs | 2 +- osu.Game/Overlays/ChatOverlay.cs | 2 +- osu.Game/Overlays/LoginOverlay.cs | 2 +- osu.Game/Overlays/SearchableList/SearchableListOverlay.cs | 2 +- osu.Game/Overlays/SettingsOverlay.cs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs index 368d3cc5ef..4362b3f787 100644 --- a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs @@ -152,7 +152,7 @@ namespace osu.Game.Overlays.Chat protected override void OnFocus(InputState state) { - InputManager.ChangeFocus(search); + GetContainingInputManager().ChangeFocus(search); base.OnFocus(state); } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 29b7548ada..e7a4c1c0ab 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -243,7 +243,7 @@ namespace osu.Game.Overlays protected override void OnFocus(InputState state) { //this is necessary as inputTextBox is masked away and therefore can't get focus :( - InputManager.ChangeFocus(inputTextBox); + GetContainingInputManager().ChangeFocus(inputTextBox); base.OnFocus(state); } diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index 95e0fef9aa..1bce31c789 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -69,7 +69,7 @@ namespace osu.Game.Overlays settingsSection.Bounding = true; this.FadeIn(transition_time, Easing.OutQuint); - InputManager.ChangeFocus(settingsSection); + GetContainingInputManager().ChangeFocus(settingsSection); } protected override void PopOut() diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index c5b8b0cf85..d1d40388e1 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -103,7 +103,7 @@ namespace osu.Game.Overlays.SearchableList protected override void OnFocus(InputState state) { - InputManager.ChangeFocus(Filter.Search); + GetContainingInputManager().ChangeFocus(Filter.Search); } protected override void PopIn() diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index dfbcedd479..bd2212785a 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -153,7 +153,7 @@ namespace osu.Game.Overlays searchTextBox.HoldFocus = false; if (searchTextBox.HasFocus) - InputManager.ChangeFocus(null); + GetContainingInputManager().ChangeFocus(null); } public override bool AcceptsFocus => true; @@ -162,7 +162,7 @@ namespace osu.Game.Overlays protected override void OnFocus(InputState state) { - InputManager.ChangeFocus(searchTextBox); + GetContainingInputManager().ChangeFocus(searchTextBox); base.OnFocus(state); } From 7d00365154592294e2bb3be3ec6953e63df5bed3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 12:12:25 +0900 Subject: [PATCH 036/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 4a213a02aa..fc13a4c2f1 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 4a213a02aa09b0fd8bd119eb391549ca1fa00f95 +Subproject commit fc13a4c2f1eff443ffe7d5ff3ca5caa17b98ffbf From 9448e2f192bfee608ad6b620c495fcef2c22e09b Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 16 Aug 2017 17:25:48 +0930 Subject: [PATCH 037/180] Remove unnecessary OnMouseDown/Up from SpinnerDisc --- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 99c287f6fb..eda6334b7a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -67,30 +67,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - private void updateTracking() - { - Tracking = mouseHasMainButtonPressed || actionLeftButtonPressed || actionRightButtonPressed; - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - mouseHasMainButtonPressed |= state.Mouse.HasMainButtonPressed; - updateTracking(); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - mouseHasMainButtonPressed &= state.Mouse.HasMainButtonPressed; - updateTracking(); - return base.OnMouseUp(state, args); - } - protected override bool OnMouseMove(InputState state) { - mouseHasMainButtonPressed |= state.Mouse.HasMainButtonPressed; mousePosition = Parent.ToLocalSpace(state.Mouse.NativeState.Position); - updateTracking(); return base.OnMouseMove(state); } @@ -98,7 +77,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { actionLeftButtonPressed |= action == OsuAction.LeftButton; actionRightButtonPressed |= action == OsuAction.RightButton; - updateTracking(); + Tracking = actionLeftButtonPressed || actionRightButtonPressed; return false; } @@ -106,12 +85,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { actionLeftButtonPressed &= action == OsuAction.LeftButton; actionRightButtonPressed &= action == OsuAction.RightButton; - updateTracking(); + Tracking = actionLeftButtonPressed || actionRightButtonPressed; return false; } private Vector2 mousePosition; - private bool mouseHasMainButtonPressed; private bool actionLeftButtonPressed; private bool actionRightButtonPressed; From 25a3835c3c25ab89baed02a88a9bf104b5696920 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 16:59:16 +0900 Subject: [PATCH 038/180] Cancel pending sidebar expansion when a button is clicked --- osu.Game/Overlays/Settings/Sidebar.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 6eafc65d12..bfb3b96cb7 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -87,6 +87,8 @@ namespace osu.Game.Overlays.Settings get { return state; } set { + expandEvent?.Cancel(); + if (state == value) return; state = value; From b1abf83fee82bfb3bdb6ab1d0a538d67b5f242ca Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Wed, 16 Aug 2017 17:50:24 +0930 Subject: [PATCH 039/180] Change spinner action checks to switches --- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index eda6334b7a..1e56a2559a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -75,16 +75,30 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public bool OnPressed(OsuAction action) { - actionLeftButtonPressed |= action == OsuAction.LeftButton; - actionRightButtonPressed |= action == OsuAction.RightButton; + switch (action) + { + case OsuAction.LeftButton: + actionLeftButtonPressed = true; + break; + case OsuAction.RightButton: + actionRightButtonPressed = true; + break; + } Tracking = actionLeftButtonPressed || actionRightButtonPressed; return false; } public bool OnReleased(OsuAction action) { - actionLeftButtonPressed &= action == OsuAction.LeftButton; - actionRightButtonPressed &= action == OsuAction.RightButton; + switch (action) + { + case OsuAction.LeftButton: + actionLeftButtonPressed = false; + break; + case OsuAction.RightButton: + actionRightButtonPressed = false; + break; + } Tracking = actionLeftButtonPressed || actionRightButtonPressed; return false; } From dc82a88bb8ee6fa2983512bb1e532dd7e1965a26 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 17:19:27 +0900 Subject: [PATCH 040/180] Improve namespaces of key bindings --- .../Visual/TestCaseKeyConfiguration.cs | 6 ++--- .../GlobalBindingsSection.cs | 2 +- .../KeyBindingRow.cs | 10 ++++---- .../KeyBindingsSection.cs | 5 ++-- .../RulesetBindingsSection.cs | 2 +- ...yConfiguration.cs => KeyBindingOverlay.cs} | 7 +++--- osu.Game/Overlays/SettingsOverlay.cs | 24 +++++++++---------- osu.Game/osu.Game.csproj | 10 ++++---- 8 files changed, 32 insertions(+), 34 deletions(-) rename osu.Game/Overlays/{KeyConfiguration => KeyBinding}/GlobalBindingsSection.cs (90%) rename osu.Game/Overlays/{KeyConfiguration => KeyBinding}/KeyBindingRow.cs (92%) rename osu.Game/Overlays/{KeyConfiguration => KeyBinding}/KeyBindingsSection.cs (87%) rename osu.Game/Overlays/{KeyConfiguration => KeyBinding}/RulesetBindingsSection.cs (89%) rename osu.Game/Overlays/{KeyConfiguration/KeyConfiguration.cs => KeyBindingOverlay.cs} (81%) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 69489c51a1..77db6e7b91 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,19 +1,17 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Overlays.KeyConfiguration; - namespace osu.Desktop.Tests.Visual { public class TestCaseKeyConfiguration : OsuTestCase { - private readonly KeyConfiguration configuration; + private readonly KeyConfigurationOverlay configuration; public override string Description => @"Key configuration"; public TestCaseKeyConfiguration() { - Child = configuration = new KeyConfiguration(); + Child = configuration = new KeyConfigurationOverlay(); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs similarity index 90% rename from osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs index 9d68b41045..943fc4a416 100644 --- a/osu.Game/Overlays/KeyConfiguration/GlobalBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs @@ -4,7 +4,7 @@ using osu.Framework.Input.Bindings; using osu.Game.Graphics; -namespace osu.Game.Overlays.KeyConfiguration +namespace osu.Game.Overlays.KeyBinding { public class GlobalBindingsSection : KeyBindingsSection { diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs similarity index 92% rename from osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs rename to osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index a9ef10eae6..4cc179aaf1 100644 --- a/osu.Game/Overlays/KeyConfiguration/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -18,12 +18,12 @@ using osu.Game.Input; using OpenTK.Graphics; using OpenTK.Input; -namespace osu.Game.Overlays.KeyConfiguration +namespace osu.Game.Overlays.KeyBinding { internal class KeyBindingRow : Container, IFilterable { private readonly Enum action; - private readonly IEnumerable bindings; + private readonly IEnumerable bindings; private const float transition_time = 150; @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.KeyConfiguration public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); - public KeyBindingRow(Enum action, IEnumerable bindings) + public KeyBindingRow(Enum action, IEnumerable bindings) { this.action = action; this.bindings = bindings; @@ -183,7 +183,7 @@ namespace osu.Game.Overlays.KeyConfiguration private class KeyButton : Container { - public readonly KeyBinding KeyBinding; + public readonly Framework.Input.Bindings.KeyBinding KeyBinding; private readonly Box box; public readonly OsuSpriteText Text; @@ -213,7 +213,7 @@ namespace osu.Game.Overlays.KeyConfiguration } } - public KeyButton(KeyBinding keyBinding) + public KeyButton(Framework.Input.Bindings.KeyBinding keyBinding) { KeyBinding = keyBinding; diff --git a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs similarity index 87% rename from osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs index fe72c64edb..19baeca771 100644 --- a/osu.Game/Overlays/KeyConfiguration/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs @@ -5,17 +5,16 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Input.Bindings; using osu.Game.Input; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using OpenTK; -namespace osu.Game.Overlays.KeyConfiguration +namespace osu.Game.Overlays.KeyBinding { public abstract class KeyBindingsSection : SettingsSection { - protected IEnumerable Defaults; + protected IEnumerable Defaults; protected RulesetInfo Ruleset; diff --git a/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs similarity index 89% rename from osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs index 038df5e122..20941115e3 100644 --- a/osu.Game/Overlays/KeyConfiguration/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs @@ -4,7 +4,7 @@ using osu.Game.Graphics; using osu.Game.Rulesets; -namespace osu.Game.Overlays.KeyConfiguration +namespace osu.Game.Overlays.KeyBinding { public class RulesetBindingsSection : KeyBindingsSection { diff --git a/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs b/osu.Game/Overlays/KeyBindingOverlay.cs similarity index 81% rename from osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs rename to osu.Game/Overlays/KeyBindingOverlay.cs index 416f828495..e5061def77 100644 --- a/osu.Game/Overlays/KeyConfiguration/KeyConfiguration.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -4,12 +4,13 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Input.Bindings; +using osu.Game.Overlays.KeyBinding; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; -namespace osu.Game.Overlays.KeyConfiguration +namespace osu.Game.Overlays { - public class KeyConfiguration : SettingsOverlay + public class KeyConfigurationOverlay : SettingsOverlay { protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.KeyConfiguration AddSection(new RulesetBindingsSection(ruleset)); } - public KeyConfiguration() + public KeyConfigurationOverlay() : base(false) { } diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index bd2212785a..76f9ef3326 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays private Sidebar sidebar; private SidebarButton selectedSidebarButton; - private SettingsSectionsContainer sectionsContainer; + protected SettingsSectionsContainer SectionsContainer; private SearchTextBox searchTextBox; @@ -60,7 +60,7 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.6f, }, - sectionsContainer = new SettingsSectionsContainer + SectionsContainer = new SettingsSectionsContainer { RelativeSizeAxes = Axes.Y, Width = width, @@ -80,14 +80,14 @@ namespace osu.Game.Overlays Exit = Hide, }, Footer = CreateFooter() - } + }, }; if (showSidebar) { Add(sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); - sectionsContainer.SelectedSection.ValueChanged += section => + SectionsContainer.SelectedSection.ValueChanged += section => { selectedSidebarButton.Selected = false; selectedSidebarButton = sidebar.Children.Single(b => b.Section == section); @@ -95,7 +95,7 @@ namespace osu.Game.Overlays }; } - searchTextBox.Current.ValueChanged += newValue => sectionsContainer.SearchContainer.SearchTerm = newValue; + searchTextBox.Current.ValueChanged += newValue => SectionsContainer.SearchContainer.SearchTerm = newValue; getToolbarHeight = () => game?.ToolbarOffset ?? 0; @@ -104,7 +104,7 @@ namespace osu.Game.Overlays protected void AddSection(SettingsSection section) { - sectionsContainer.Add(section); + SectionsContainer.Add(section); if (sidebar != null) { @@ -113,7 +113,7 @@ namespace osu.Game.Overlays Section = section, Action = s => { - sectionsContainer.ScrollTo(s); + SectionsContainer.ScrollTo(s); sidebar.State = ExpandedState.Contracted; }, }; @@ -136,7 +136,7 @@ namespace osu.Game.Overlays { base.PopIn(); - sectionsContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + SectionsContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH / 2); @@ -147,7 +147,7 @@ namespace osu.Game.Overlays { base.PopOut(); - sectionsContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); + SectionsContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); sidebar?.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(0, TRANSITION_LENGTH / 2); @@ -170,11 +170,11 @@ namespace osu.Game.Overlays { base.UpdateAfterChildren(); - sectionsContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; - sectionsContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; + SectionsContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; + SectionsContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; } - private class SettingsSectionsContainer : SectionsContainer + protected class SettingsSectionsContainer : SectionsContainer { public SearchContainer SearchContainer; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6eb0ece6ed..f21ce528ca 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -102,11 +102,11 @@ - - - - - + + + + + From 54698f2d8ff37071ec706d919add0010cf4b3845 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 17:27:09 +0900 Subject: [PATCH 041/180] Use IntAction instead of new --- osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs | 2 ++ osu.Game/Input/Bindings/DatabasedKeyBinding.cs | 6 +++--- osu.Game/Input/KeyBindingStore.cs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 77db6e7b91..41e0c25507 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Overlays; + namespace osu.Desktop.Tests.Visual { public class TestCaseKeyConfiguration : OsuTestCase diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index c0197ce3dc..cbf74d6984 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -29,10 +29,10 @@ namespace osu.Game.Input.Bindings [Indexed] [Column("Action")] - public new int Action + public int IntAction { - get { return (int)base.Action; } - set { base.Action = value; } + get { return (int)Action; } + set { Action = value; } } } } \ No newline at end of file diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 057fa4d4e7..95fdaba339 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -74,7 +74,7 @@ namespace osu.Game.Input Connection.Insert(new DatabasedKeyBinding { KeyCombination = insertable.KeyCombination, - Action = (int)insertable.Action, + Action = insertable.Action, RulesetID = rulesetId, Variant = variant }); From 3df51540e19a39b0c8010d00153058ecf4ee0625 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 17:34:49 +0900 Subject: [PATCH 042/180] Code review fixes --- osu-framework | 2 +- .../Input/Bindings/DatabasedKeyBindingInputManager.cs | 2 +- ...ngInputManager.cs => GlobalKeyBindingInputManager.cs} | 6 +++--- osu.Game/Input/KeyBindingStore.cs | 9 ++------- osu.Game/OsuGameBase.cs | 4 ++-- ...balBindingsSection.cs => GlobalKeyBindingsSection.cs} | 6 +++--- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 3 ++- osu.Game/Overlays/KeyBindingOverlay.cs | 4 ++-- osu.Game/osu.Game.csproj | 4 ++-- 9 files changed, 18 insertions(+), 22 deletions(-) rename osu.Game/Input/Bindings/{GlobalBindingInputManager.cs => GlobalKeyBindingInputManager.cs} (88%) rename osu.Game/Overlays/KeyBinding/{GlobalBindingsSection.cs => GlobalKeyBindingsSection.cs} (68%) diff --git a/osu-framework b/osu-framework index fc13a4c2f1..acb9bfb084 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit fc13a4c2f1eff443ffe7d5ff3ca5caa17b98ffbf +Subproject commit acb9bfb084b5607ff31c6269cb7942fa02624b75 diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index e565c13b31..89aee7ca4d 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -21,7 +21,7 @@ namespace osu.Game.Input.Bindings private KeyBindingStore store; - public override IEnumerable DefaultMappings => ruleset.CreateInstance().GetDefaultKeyBindings(); + public override IEnumerable DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(); /// /// Create a new instance. diff --git a/osu.Game/Input/Bindings/GlobalBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs similarity index 88% rename from osu.Game/Input/Bindings/GlobalBindingInputManager.cs rename to osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs index d00ed588ae..4dff25d509 100644 --- a/osu.Game/Input/Bindings/GlobalBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs @@ -11,17 +11,17 @@ using osu.Framework.Input.Bindings; namespace osu.Game.Input.Bindings { - public class GlobalBindingInputManager : DatabasedKeyBindingInputManager + public class GlobalKeyBindingInputManager : DatabasedKeyBindingInputManager { private readonly Drawable handler; - public GlobalBindingInputManager(OsuGameBase game) + public GlobalKeyBindingInputManager(OsuGameBase game) { if (game is IKeyBindingHandler) handler = game; } - public override IEnumerable DefaultMappings => new[] + public override IEnumerable DefaultKeyBindings => new[] { new KeyBinding(Key.F8, GlobalAction.ToggleChat), new KeyBinding(Key.F9, GlobalAction.ToggleSocial), diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 95fdaba339..f50acb4802 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -26,7 +26,7 @@ namespace osu.Game.Input } } - public void Register(KeyBindingInputManager manager) => insertDefaults(manager.DefaultMappings); + public void Register(KeyBindingInputManager manager) => insertDefaults(manager.DefaultKeyBindings); protected override int StoreVersion => 3; @@ -51,9 +51,7 @@ namespace osu.Game.Input protected override void Prepare(bool reset = false) { if (reset) - { Connection.DropTable(); - } Connection.CreateTable(); } @@ -90,9 +88,6 @@ namespace osu.Game.Input public IEnumerable Query(int? rulesetId = null, int? variant = null) => Query(b => b.RulesetID == rulesetId && b.Variant == variant); - public void Update(KeyBinding keyBinding) - { - Connection.Update(keyBinding); - } + public void Update(KeyBinding keyBinding) => Connection.Update(keyBinding); } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 571c75022e..a5600d1ef7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -183,14 +183,14 @@ namespace osu.Game { base.LoadComplete(); - GlobalBindingInputManager globalBinding; + GlobalKeyBindingInputManager globalBinding; base.Content.Add(new RatioAdjust { Children = new Drawable[] { Cursor = new MenuCursor(), - globalBinding = new GlobalBindingInputManager(this) + globalBinding = new GlobalKeyBindingInputManager(this) { RelativeSizeAxes = Axes.Both, Child = new OsuTooltipContainer(Cursor) diff --git a/osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs similarity index 68% rename from osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 943fc4a416..7dd9919e5d 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -6,18 +6,18 @@ using osu.Game.Graphics; namespace osu.Game.Overlays.KeyBinding { - public class GlobalBindingsSection : KeyBindingsSection + public class GlobalKeyBindingsSection : KeyBindingsSection { private readonly string name; public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; public override string Header => name; - public GlobalBindingsSection(KeyBindingInputManager manager, string name) + public GlobalKeyBindingsSection(KeyBindingInputManager manager, string name) { this.name = name; - Defaults = manager.DefaultMappings; + Defaults = manager.DefaultKeyBindings; } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 4cc179aaf1..082e1c0eec 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -219,7 +219,8 @@ namespace osu.Game.Overlays.KeyBinding Margin = new MarginPadding(padding); - //var isDefault = keyBinding.Action is Enum; + // todo: use this in a meaningful way + // var isDefault = keyBinding.Action is Enum; Masking = true; CornerRadius = padding; diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index e5061def77..ba45b3c812 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -15,9 +15,9 @@ namespace osu.Game.Overlays protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); [BackgroundDependencyLoader(permitNulls: true)] - private void load(RulesetStore rulesets, GlobalBindingInputManager global) + private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global) { - AddSection(new GlobalBindingsSection(global, "Global")); + AddSection(new GlobalKeyBindingsSection(global, "Global")); foreach (var ruleset in rulesets.Query()) AddSection(new RulesetBindingsSection(ruleset)); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f21ce528ca..07ab58bffc 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -95,14 +95,14 @@ - + - + From 7e1fc47b76d0fc6252549f0c65d51555b7d400ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 17:43:01 +0900 Subject: [PATCH 043/180] Fix forgotten rename --- osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs | 6 +++--- osu.Game/Overlays/KeyBindingOverlay.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs index 41e0c25507..cab285c72e 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyConfiguration.cs @@ -7,19 +7,19 @@ namespace osu.Desktop.Tests.Visual { public class TestCaseKeyConfiguration : OsuTestCase { - private readonly KeyConfigurationOverlay configuration; + private readonly KeyBindingOverlay overlay; public override string Description => @"Key configuration"; public TestCaseKeyConfiguration() { - Child = configuration = new KeyConfigurationOverlay(); + Child = overlay = new KeyBindingOverlay(); } protected override void LoadComplete() { base.LoadComplete(); - configuration.Show(); + overlay.Show(); } } } diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index ba45b3c812..7d6ef7ffa6 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets; namespace osu.Game.Overlays { - public class KeyConfigurationOverlay : SettingsOverlay + public class KeyBindingOverlay : SettingsOverlay { protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); @@ -23,7 +23,7 @@ namespace osu.Game.Overlays AddSection(new RulesetBindingsSection(ruleset)); } - public KeyConfigurationOverlay() + public KeyBindingOverlay() : base(false) { } From 7e21ddb5eb5ab0fbdc466fe1209bad805fe999b9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 19:17:29 +0900 Subject: [PATCH 044/180] Remove usage of HideOnEscape --- osu.Desktop/Overlays/VersionManager.cs | 2 -- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 9 +++++---- osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs | 2 -- osu.Game/Overlays/Toolbar/Toolbar.cs | 2 -- osu.Game/Screens/Play/MenuOverlay.cs | 5 ++--- osu.Game/Screens/Play/SongProgress.cs | 2 -- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 -- 7 files changed, 7 insertions(+), 17 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 18fa43ab5c..b445340f50 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -27,8 +27,6 @@ namespace osu.Desktop.Overlays private UpdateManager updateManager; private NotificationOverlay notificationOverlay; - protected override bool HideOnEscape => false; - public override bool HandleInput => false; [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index dbbb069f7c..fe060f70f0 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -5,7 +5,6 @@ using OpenTK.Graphics; using OpenTK.Input; using osu.Framework.Input; using System; -using System.Linq; namespace osu.Game.Graphics.UserInterface { @@ -37,16 +36,18 @@ namespace osu.Game.Graphics.UserInterface BorderThickness = 0; } - protected override void OnFocusLost(InputState state) + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (state.Keyboard.Keys.Any(key => key == Key.Escape)) + if (args.Key == Key.Escape) { if (Text.Length > 0) Text = string.Empty; else Exit?.Invoke(); + return true; } - base.OnFocusLost(state); + + return base.OnKeyDown(state, args); } public override bool RequestsFocus => HoldFocus; diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index fa192b0825..cd77fb9f5b 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -15,8 +15,6 @@ namespace osu.Game.Graphics.UserInterface.Volume { private readonly VolumeMeter volumeMeterMaster; - protected override bool HideOnEscape => false; - private void volumeChanged(double newVolume) { Show(); diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 1ecfe90aa1..f9821782a7 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -22,8 +22,6 @@ namespace osu.Game.Overlays.Toolbar private readonly ToolbarUserArea userArea; - protected override bool HideOnEscape => false; - protected override bool BlockPassThroughMouse => false; private const double transition_time = 500; diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index a0f867d248..0a8e172e57 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -22,8 +22,6 @@ namespace osu.Game.Screens.Play private const int button_height = 70; private const float background_alpha = 0.75f; - protected override bool HideOnEscape => false; - protected override bool BlockPassThroughKeyboard => true; public Action OnRetry; @@ -95,7 +93,8 @@ namespace osu.Game.Screens.Play Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, Height = button_height, - Action = delegate { + Action = delegate + { action?.Invoke(); Hide(); } diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index c513daf3d9..68f0cb3661 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -18,8 +18,6 @@ namespace osu.Game.Screens.Play { private const int bottom_bar_height = 5; - protected override bool HideOnEscape => false; - private static readonly Vector2 handle_size = new Vector2(14, 25); private const float transition_duration = 200; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 1fb9c707f0..872f7483b6 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -50,8 +50,6 @@ namespace osu.Game.Screens.Select AlwaysPresent = true; } - protected override bool HideOnEscape => false; - protected override bool BlockPassThroughMouse => false; protected override void PopIn() From 5ebec53970a8e6a3b24ec401a65a9028ba928eab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 19:17:42 +0900 Subject: [PATCH 045/180] Integrate key binding config with main settings --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 75 ++++++++++++------- osu.Game/Overlays/MainSettings.cs | 51 ++++++++++++- .../Sections/Input/KeyboardSettings.cs | 5 +- .../Settings/Sections/InputSection.cs | 4 +- osu.Game/Overlays/SettingsOverlay.cs | 69 +++++++++-------- 5 files changed, 139 insertions(+), 65 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 082e1c0eec..3415c22972 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; -using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Input; @@ -106,12 +105,6 @@ namespace osu.Game.Overlays.KeyBinding } }; - reloadBindings(); - } - - private void reloadBindings() - { - buttons.Clear(); foreach (var b in bindings) buttons.Add(new KeyButton(b)); } @@ -149,23 +142,46 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (HasFocus && !isModifier(args.Key)) + if (args.Key == Key.Delete) { - bindTarget.KeyBinding.KeyCombination = args.Key == Key.Delete ? Key.Unknown : new KeyCombination(state.Keyboard.Keys); - + bindTarget.UpdateKeyCombination(Key.Unknown); store.Update(bindTarget.KeyBinding); GetContainingInputManager().ChangeFocus(null); return true; } + if (HasFocus) + { + bindTarget.UpdateKeyCombination(state.Keyboard.Keys.ToArray()); + if (!isModifier(args.Key)) + finalise(); + return true; + } + return base.OnKeyDown(state, args); } + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + { + if (HasFocus) + { + finalise(); + return true; + } + + return base.OnKeyUp(state, args); + } + + private void finalise() + { + store.Update(bindTarget.KeyBinding); + GetContainingInputManager().ChangeFocus(null); + } + protected override void OnFocusLost(InputState state) { bindTarget.IsBinding = false; bindTarget = null; - reloadBindings(); pressAKey.FadeOut(300, Easing.OutQuint); pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; @@ -197,19 +213,16 @@ namespace osu.Game.Overlays.KeyBinding get { return isBinding; } set { + if (value == isBinding) return; isBinding = value; - if (value) + if (isBinding) { box.FadeColour(Color4.White, transition_time, Easing.OutQuint); Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - } else - { - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - } + updateHoverState(); } } @@ -261,25 +274,29 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnHover(InputState state) { - if (isBinding) - return false; - - box.FadeColour(hoverColour, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - + if (!isBinding) + updateHoverState(); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - if (isBinding) - return; - - box.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.White, transition_time, Easing.OutQuint); - + if (!isBinding) + updateHoverState(); base.OnHoverLost(state); } + + private void updateHoverState() + { + box.FadeColour(IsHovered ? hoverColour : Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(IsHovered ? Color4.Black : Color4.White, transition_time, Easing.OutQuint); + } + + public void UpdateKeyCombination(params Key[] newCombination) + { + KeyBinding.KeyCombination = newCombination; + Text.Text = KeyBinding.KeyCombination.ReadableString(); + } } } } \ No newline at end of file diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 44c4d4ccdb..b040f5043b 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -2,7 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; @@ -10,6 +12,8 @@ namespace osu.Game.Overlays { public class MainSettings : SettingsOverlay { + private readonly KeyBindingOverlay keyBindingOverlay; + protected override IEnumerable CreateSections() => new SettingsSection[] { new GeneralSection(), @@ -17,7 +21,7 @@ namespace osu.Game.Overlays new GameplaySection(), new AudioSection(), new SkinSection(), - new InputSection(), + new InputSection(keyBindingOverlay), new OnlineSection(), new MaintenanceSection(), new DebugSection(), @@ -26,8 +30,51 @@ namespace osu.Game.Overlays protected override Drawable CreateHeader() => new SettingsHeader("settings", "Change the way osu! behaves"); protected override Drawable CreateFooter() => new SettingsFooter(); - public MainSettings() : base(true) + public MainSettings() + : base(true) { + keyBindingOverlay = new KeyBindingOverlay { Depth = 1 }; + keyBindingOverlay.StateChanged += keyBindingOverlay_StateChanged; + } + + public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible; + + private void keyBindingOverlay_StateChanged(VisibilityContainer container, Visibility visibility) + { + const float hidden_width = 120; + + switch (visibility) + { + case Visibility.Visible: + Background.FadeTo(0.9f, 500, Easing.OutQuint); + SectionsContainer.FadeOut(100); + ContentContainer.MoveToX(hidden_width - ContentContainer.DrawWidth, 500, Easing.OutQuint); + break; + case Visibility.Hidden: + Background.FadeTo(0.6f, 500, Easing.OutQuint); + SectionsContainer.FadeIn(500, Easing.OutQuint); + ContentContainer.MoveToX(0, 500, Easing.OutQuint); + break; + } + } + + protected override void PopOut() + { + base.PopOut(); + keyBindingOverlay.State = Visibility.Hidden; + } + + [BackgroundDependencyLoader] + private void load() + { + AddInternal(keyBindingOverlay); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + keyBindingOverlay.Margin = new MarginPadding { Left = ContentContainer.Margin.Left + ContentContainer.DrawWidth + ContentContainer.X }; } } } \ No newline at end of file diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 9ead4ca7a4..01e73d0168 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -10,14 +10,15 @@ namespace osu.Game.Overlays.Settings.Sections.Input { protected override string Header => "Keyboard"; - public KeyboardSettings() + public KeyboardSettings(KeyBindingOverlay keyConfig) { Children = new Drawable[] { new OsuButton { RelativeSizeAxes = Axes.X, - Text = "Key Configuration" + Text = "Key Configuration", + Action = () => keyConfig.ToggleVisibility() }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 65df3746b3..5ece8aad77 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -12,12 +12,12 @@ namespace osu.Game.Overlays.Settings.Sections public override string Header => "Input"; public override FontAwesome Icon => FontAwesome.fa_keyboard_o; - public InputSection() + public InputSection(KeyBindingOverlay keyConfig) { Children = new Drawable[] { new MouseSettings(), - new KeyboardSettings(), + new KeyboardSettings(keyConfig), }; } } diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 76f9ef3326..f62087ee71 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -29,6 +29,10 @@ namespace osu.Game.Overlays private const float sidebar_padding = 10; + protected Container ContentContainer; + + protected override Container Content => ContentContainer; + private Sidebar sidebar; private SidebarButton selectedSidebarButton; @@ -40,6 +44,8 @@ namespace osu.Game.Overlays private readonly bool showSidebar; + protected Box Background; + protected SettingsOverlay(bool showSidebar) { this.showSidebar = showSidebar; @@ -52,40 +58,43 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuGame game) { - Children = new Drawable[] + InternalChild = ContentContainer = new Container { - new Box + Width = width, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.6f, - }, - SectionsContainer = new SettingsSectionsContainer - { - RelativeSizeAxes = Axes.Y, - Width = width, - Margin = new MarginPadding { Left = SIDEBAR_WIDTH }, - ExpandableHeader = CreateHeader(), - FixedHeader = searchTextBox = new SearchTextBox + Background = new Box { - RelativeSizeAxes = Axes.X, - Origin = Anchor.TopCentre, - Anchor = Anchor.TopCentre, - Width = 0.95f, - Margin = new MarginPadding - { - Top = 20, - Bottom = 20 - }, - Exit = Hide, + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + Alpha = 0.6f, }, - Footer = CreateFooter() - }, + SectionsContainer = new SettingsSectionsContainer + { + RelativeSizeAxes = Axes.Both, + ExpandableHeader = CreateHeader(), + FixedHeader = searchTextBox = new SearchTextBox + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.TopCentre, + Anchor = Anchor.TopCentre, + Width = 0.95f, + Margin = new MarginPadding + { + Top = 20, + Bottom = 20 + }, + Exit = Hide, + }, + Footer = CreateFooter() + }, + } }; if (showSidebar) { - Add(sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); + AddInternal(sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); SectionsContainer.SelectedSection.ValueChanged += section => { @@ -136,7 +145,7 @@ namespace osu.Game.Overlays { base.PopIn(); - SectionsContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + ContentContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(1, TRANSITION_LENGTH / 2); @@ -147,7 +156,7 @@ namespace osu.Game.Overlays { base.PopOut(); - SectionsContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); + ContentContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); sidebar?.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); this.FadeTo(0, TRANSITION_LENGTH / 2); @@ -170,8 +179,8 @@ namespace osu.Game.Overlays { base.UpdateAfterChildren(); - SectionsContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; - SectionsContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; + ContentContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; + ContentContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; } protected class SettingsSectionsContainer : SectionsContainer From 71f83dbdfa606541b163d9cc17130bffb884560e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 20:16:40 +0900 Subject: [PATCH 046/180] Add null check for safety --- .../Settings/Sections/Audio/AudioDevicesSettings.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index 47f7abf571..9b1c5e5e49 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -26,8 +26,11 @@ namespace osu.Game.Overlays.Settings.Sections.Audio { base.Dispose(isDisposing); - audio.OnNewDevice -= onDeviceChanged; - audio.OnLostDevice -= onDeviceChanged; + if (audio != null) + { + audio.OnNewDevice -= onDeviceChanged; + audio.OnLostDevice -= onDeviceChanged; + } } private void updateItems() From c41ba7b7042eee8ac1d66839bbb5c6f0c6393451 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 22:55:13 +0900 Subject: [PATCH 047/180] Update with latest framework changes --- .../Bindings/GlobalKeyBindingInputManager.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs index 4dff25d509..e9eab49c32 100644 --- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; using osu.Framework.Graphics; -using osu.Framework.Input; using osu.Framework.Input.Bindings; namespace osu.Game.Input.Bindings @@ -31,23 +30,7 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { Key.LControl, Key.D }, GlobalAction.ToggleDirect), }; - protected override bool PropagateKeyDown(IEnumerable drawables, InputState state, KeyDownEventArgs args) - { - if (handler != null) - drawables = new[] { handler }.Concat(drawables); - - // always handle ourselves before all children. - return base.PropagateKeyDown(drawables, state, args); - } - - protected override bool PropagateKeyUp(IEnumerable drawables, InputState state, KeyUpEventArgs args) - { - if (handler != null) - drawables = new[] { handler }.Concat(drawables); - - // always handle ourselves before all children. - return base.PropagateKeyUp(drawables, state, args); - } + protected override IEnumerable GetKeyboardInputQueue() => new[] { handler }.Concat(base.GetKeyboardInputQueue()); } public enum GlobalAction From e64f455ff74d14fcf31f417d8406cc0f86e24241 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 23:01:10 +0900 Subject: [PATCH 048/180] Escape to cancel, again --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 3415c22972..274619991c 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -142,12 +142,16 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { - if (args.Key == Key.Delete) + switch (args.Key) { - bindTarget.UpdateKeyCombination(Key.Unknown); - store.Update(bindTarget.KeyBinding); - GetContainingInputManager().ChangeFocus(null); - return true; + case Key.Escape: + GetContainingInputManager().ChangeFocus(null); + return true; + case Key.Delete: + bindTarget.UpdateKeyCombination(Key.Unknown); + store.Update(bindTarget.KeyBinding); + GetContainingInputManager().ChangeFocus(null); + return true; } if (HasFocus) From 09089a31260122e1385aa58acbdcbc6bb781731d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 23:20:08 +0900 Subject: [PATCH 049/180] Fix potential nullref --- osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs index e9eab49c32..31be2e6adc 100644 --- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs @@ -30,7 +30,8 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { Key.LControl, Key.D }, GlobalAction.ToggleDirect), }; - protected override IEnumerable GetKeyboardInputQueue() => new[] { handler }.Concat(base.GetKeyboardInputQueue()); + protected override IEnumerable GetKeyboardInputQueue() => + handler == null ? base.GetKeyboardInputQueue() : new[] { handler }.Concat(base.GetKeyboardInputQueue()); } public enum GlobalAction From 0c19202b9aff2371e5daef1f7d3d3e6236902b8f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 23:20:18 +0900 Subject: [PATCH 050/180] Add basic back button --- osu.Game/Overlays/MainSettings.cs | 94 +++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index b040f5043b..6302c56018 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -5,14 +5,21 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; +using osu.Game.Screens.Ranking; +using OpenTK; namespace osu.Game.Overlays { public class MainSettings : SettingsOverlay { private readonly KeyBindingOverlay keyBindingOverlay; + private BackButton backButton; protected override IEnumerable CreateSections() => new SettingsSection[] { @@ -49,11 +56,15 @@ namespace osu.Game.Overlays Background.FadeTo(0.9f, 500, Easing.OutQuint); SectionsContainer.FadeOut(100); ContentContainer.MoveToX(hidden_width - ContentContainer.DrawWidth, 500, Easing.OutQuint); + + backButton.Delay(100).FadeIn(100); break; case Visibility.Hidden: Background.FadeTo(0.6f, 500, Easing.OutQuint); SectionsContainer.FadeIn(500, Easing.OutQuint); ContentContainer.MoveToX(0, 500, Easing.OutQuint); + + backButton.FadeOut(100); break; } } @@ -68,6 +79,14 @@ namespace osu.Game.Overlays private void load() { AddInternal(keyBindingOverlay); + AddInternal(backButton = new BackButton + { + Alpha = 0, + Height = 150, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Action = () => keyBindingOverlay.Hide() + }); } protected override void UpdateAfterChildren() @@ -75,6 +94,81 @@ namespace osu.Game.Overlays base.UpdateAfterChildren(); keyBindingOverlay.Margin = new MarginPadding { Left = ContentContainer.Margin.Left + ContentContainer.DrawWidth + ContentContainer.X }; + + backButton.Margin = new MarginPadding { Left = ContentContainer.Margin.Left }; + backButton.Width = ContentContainer.DrawWidth + ContentContainer.X; + } + + private class BackButton : OsuClickableContainer + { + private FillFlowContainer flow; + private AspectContainer aspect; + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + aspect = new AspectContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Children = new Drawable[] + { + flow = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + RelativePositionAxes = Axes.Y, + Y = 0.4f, + AutoSizeAxes = Axes.Both, + Origin = Anchor.Centre, + Direction = FillDirection.Horizontal, + Children = new[] + { + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, + new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, + } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + RelativePositionAxes = Axes.Y, + Y = 0.7f, + TextSize = 12, + Font = @"Exo2.0-Bold", + Origin = Anchor.Centre, + Text = @"back", + }, + } + } + }; + } + + protected override bool OnHover(InputState state) + { + flow.TransformSpacingTo(new Vector2(5), 500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + flow.TransformSpacingTo(new Vector2(0), 500, Easing.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + aspect.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(state, args); + } } } } \ No newline at end of file From c6c9c5431fe19c4638d24877bb3c7cbced88b7c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Aug 2017 23:22:12 +0900 Subject: [PATCH 051/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index acb9bfb084..68e461df82 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit acb9bfb084b5607ff31c6269cb7942fa02624b75 +Subproject commit 68e461df82a608d5748e758101f99f9d3081f8b6 From 94d664a626c5e368d1e00b67e676f2dcf854cafd Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Wed, 16 Aug 2017 17:00:30 +0200 Subject: [PATCH 052/180] Swap the order of the social and chat toolbar buttons --- osu.Game/Overlays/Toolbar/Toolbar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 1ecfe90aa1..aca1051c7c 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -60,8 +60,8 @@ namespace osu.Game.Overlays.Toolbar AutoSizeAxes = Axes.X, Children = new Drawable[] { - new ToolbarSocialButton(), new ToolbarChatButton(), + new ToolbarSocialButton(), new ToolbarMusicButton(), new ToolbarButton { From 8c05a40fbfd5decac27b45ecea116d6ce4c23dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 16 Aug 2017 01:10:09 +0900 Subject: [PATCH 053/180] Use SliderStep instead of TestCaseSliderBar This greatly simplifies TestCaseKeyCounter and TestCaseHitObject and allows more future automation. --- .../Visual/TestCaseHitObjects.cs | 27 ++----------------- .../Visual/TestCaseKeyCounter.cs | 27 +++---------------- 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs index df5f9f65b8..8dfaa7ea3d 100644 --- a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs @@ -27,35 +27,13 @@ namespace osu.Desktop.Tests.Visual { var rateAdjustClock = new StopwatchClock(true); framedClock = new FramedClock(rateAdjustClock); - playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; }; - - playbackSpeed.TriggerChange(); AddStep(@"circles", () => loadHitobjects(HitObjectType.Circle)); AddStep(@"slider", () => loadHitobjects(HitObjectType.Slider)); AddStep(@"spinner", () => loadHitobjects(HitObjectType.Spinner)); - AddToggleStep(@"auto", state => { auto = state; loadHitobjects(mode); }); - - BasicSliderBar sliderBar; - Add(new Container - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new SpriteText { Text = "Playback Speed" }, - sliderBar = new BasicSliderBar - { - Width = 150, - Height = 10, - SelectionColor = Color4.Orange, - } - } - }); - - sliderBar.Current.BindTo(playbackSpeed); + AddToggleStep("Auto", state => { auto = state; loadHitobjects(mode); }); + AddSliderStep("Playback speed", 0.0, 2.0, 0.5, v => rateAdjustClock.Rate = v); framedClock.ProcessFrame(); @@ -75,7 +53,6 @@ namespace osu.Desktop.Tests.Visual private HitObjectType mode = HitObjectType.Slider; - private readonly BindableNumber playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 }; private readonly Container playfieldContainer; private readonly Container approachContainer; diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs index efb662d3b9..f0c77659eb 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs @@ -34,34 +34,13 @@ namespace osu.Desktop.Tests.Visual new KeyCounterMouse(MouseButton.Right), }, }; - BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 }; - bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; }; - AddStep("Add Random", () => + + AddStep("Add random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); kc.Add(new KeyCounterKeyboard(key)); }); - - TestSliderBar sliderBar; - - Add(new Container - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new SpriteText { Text = "FadeTime" }, - sliderBar = new TestSliderBar - { - Width = 150, - Height = 10, - SelectionColor = Color4.Orange, - } - } - }); - - sliderBar.Current.BindTo(bindable); + AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v); Add(kc); } From 55b159b976208e72c422d5353639ae8f7fb3628a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 16 Aug 2017 13:02:11 +0900 Subject: [PATCH 054/180] Remove unnecessary usings --- osu.Desktop.Tests/Visual/TestCaseHitObjects.cs | 4 ---- osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs | 3 --- 2 files changed, 7 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs index 8dfaa7ea3d..75e1a656de 100644 --- a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs @@ -2,18 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; using osu.Framework.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using OpenTK; -using OpenTK.Graphics; namespace osu.Desktop.Tests.Visual { diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs index f0c77659eb..1861a77a3a 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs @@ -1,11 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.MathUtils; using osu.Game.Screens.Play; From 118d0f09704483c7d8ba03735d1085891d1c3e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 17 Aug 2017 07:28:07 +0900 Subject: [PATCH 055/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index acb9bfb084..5c22092e59 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit acb9bfb084b5607ff31c6269cb7942fa02624b75 +Subproject commit 5c22092e590d589927962b8d0173dae5f9b1405c From 4ef1be308037af1d4775b9c0d8a491d5ab2aae00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 17 Aug 2017 08:43:45 +0900 Subject: [PATCH 056/180] More localised key binding hover colour logic --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 274619991c..44aee0e666 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -220,13 +220,7 @@ namespace osu.Game.Overlays.KeyBinding if (value == isBinding) return; isBinding = value; - if (isBinding) - { - box.FadeColour(Color4.White, transition_time, Easing.OutQuint); - Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); - } - else - updateHoverState(); + updateHoverState(); } } @@ -278,22 +272,28 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnHover(InputState state) { - if (!isBinding) - updateHoverState(); + updateHoverState(); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - if (!isBinding) - updateHoverState(); + updateHoverState(); base.OnHoverLost(state); } private void updateHoverState() { - box.FadeColour(IsHovered ? hoverColour : Color4.Black, transition_time, Easing.OutQuint); - Text.FadeColour(IsHovered ? Color4.Black : Color4.White, transition_time, Easing.OutQuint); + if (isBinding) + { + box.FadeColour(Color4.White, transition_time, Easing.OutQuint); + Text.FadeColour(Color4.Black, transition_time, Easing.OutQuint); + } + else + { + box.FadeColour(IsHovered ? hoverColour : Color4.Black, transition_time, Easing.OutQuint); + Text.FadeColour(IsHovered ? Color4.Black : Color4.White, transition_time, Easing.OutQuint); + } } public void UpdateKeyCombination(params Key[] newCombination) From cceeb864d505cb492284726d98a763bac2190d0c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 17 Aug 2017 12:16:33 +0900 Subject: [PATCH 057/180] Fix hitobjects in TestCaseHitObjects not receiving actions. --- osu.Desktop.Tests/Visual/TestCaseHitObjects.cs | 14 +++++++++----- .../Bindings/DatabasedKeyBindingInputManager.cs | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs index 75e1a656de..13e05d6477 100644 --- a/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseHitObjects.cs @@ -10,16 +10,20 @@ using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using OpenTK; +using osu.Game.Rulesets.Osu; +using osu.Framework.Allocation; +using osu.Game.Rulesets; namespace osu.Desktop.Tests.Visual { internal class TestCaseHitObjects : OsuTestCase { - private readonly FramedClock framedClock; + private FramedClock framedClock; private bool auto; - public TestCaseHitObjects() + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { var rateAdjustClock = new StopwatchClock(true); framedClock = new FramedClock(rateAdjustClock); @@ -39,7 +43,7 @@ namespace osu.Desktop.Tests.Visual Clock = framedClock, Children = new[] { - playfieldContainer = new Container { RelativeSizeAxes = Axes.Both }, + playfieldContainer = new OsuInputManager(rulesets.GetRuleset(0)) { RelativeSizeAxes = Axes.Both }, approachContainer = new Container { RelativeSizeAxes = Axes.Both } } }; @@ -49,8 +53,8 @@ namespace osu.Desktop.Tests.Visual private HitObjectType mode = HitObjectType.Slider; - private readonly Container playfieldContainer; - private readonly Container approachContainer; + private Container playfieldContainer; + private Container approachContainer; private void loadHitobjects(HitObjectType mode) { diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index 89aee7ca4d..f739ba2a59 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -17,7 +17,7 @@ namespace osu.Game.Input.Bindings { private readonly RulesetInfo ruleset; - private readonly int? variant; + private readonly int variant; private KeyBindingStore store; @@ -29,7 +29,7 @@ namespace osu.Game.Input.Bindings /// A reference to identify the current . Used to lookup mappings. Null for global mappings. /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. /// Specify how to deal with multiple matches of s and s. - protected DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) + protected DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int variant = 0, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) : base(simultaneousMode) { this.ruleset = ruleset; From a19fc28cffffa12cf8b44a2e42b73b62f7e1d29b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Aug 2017 17:31:14 +0900 Subject: [PATCH 058/180] Visually improve settings transitions and back button --- osu.Game/OsuGame.cs | 6 +- osu.Game/Overlays/MainSettings.cs | 88 ++++++++++------------------ osu.Game/Overlays/SettingsOverlay.cs | 49 +++++++++------- 3 files changed, 66 insertions(+), 77 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 0d1e8396e4..e3525e423c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -182,7 +182,11 @@ namespace osu.Game LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(social = new SocialOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(settings = new MainSettings { Depth = -1 }, overlayContent.Add); + LoadComponentAsync(settings = new MainSettings + { + GetToolbarHeight = () => ToolbarOffset, + Depth = -1 + }, overlayContent.Add); LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); LoadComponentAsync(musicController = new MusicController { diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 6302c56018..f2011ae88e 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -13,6 +13,7 @@ using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings.Sections; using osu.Game.Screens.Ranking; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays { @@ -40,27 +41,34 @@ namespace osu.Game.Overlays public MainSettings() : base(true) { - keyBindingOverlay = new KeyBindingOverlay { Depth = 1 }; + keyBindingOverlay = new KeyBindingOverlay { + Depth = 1, + Anchor = Anchor.TopRight, + }; keyBindingOverlay.StateChanged += keyBindingOverlay_StateChanged; } public override bool AcceptsFocus => keyBindingOverlay.State != Visibility.Visible; + private const float hidden_width = 120; + private void keyBindingOverlay_StateChanged(VisibilityContainer container, Visibility visibility) { - const float hidden_width = 120; - switch (visibility) { case Visibility.Visible: - Background.FadeTo(0.9f, 500, Easing.OutQuint); - SectionsContainer.FadeOut(100); - ContentContainer.MoveToX(hidden_width - ContentContainer.DrawWidth, 500, Easing.OutQuint); + Background.FadeTo(0.9f, 300, Easing.OutQuint); + Sidebar?.FadeColour(Color4.DarkGray, 300, Easing.OutQuint); + + SectionsContainer.FadeOut(300, Easing.OutQuint); + ContentContainer.MoveToX(hidden_width - WIDTH, 500, Easing.OutQuint); backButton.Delay(100).FadeIn(100); break; case Visibility.Hidden: Background.FadeTo(0.6f, 500, Easing.OutQuint); + Sidebar?.FadeColour(Color4.White, 300, Easing.OutQuint); + SectionsContainer.FadeIn(500, Easing.OutQuint); ContentContainer.MoveToX(0, 500, Easing.OutQuint); @@ -69,39 +77,26 @@ namespace osu.Game.Overlays } } - protected override void PopOut() - { - base.PopOut(); - keyBindingOverlay.State = Visibility.Hidden; - } + protected override float ExpandedPosition => keyBindingOverlay.State == Visibility.Visible ? hidden_width - WIDTH : base.ExpandedPosition; [BackgroundDependencyLoader] private void load() { - AddInternal(keyBindingOverlay); - AddInternal(backButton = new BackButton + ContentContainer.Add(keyBindingOverlay); + + ContentContainer.Add(backButton = new BackButton { Alpha = 0, - Height = 150, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, + Width = hidden_width, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, Action = () => keyBindingOverlay.Hide() }); } - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - keyBindingOverlay.Margin = new MarginPadding { Left = ContentContainer.Margin.Left + ContentContainer.DrawWidth + ContentContainer.X }; - - backButton.Margin = new MarginPadding { Left = ContentContainer.Margin.Left }; - backButton.Width = ContentContainer.DrawWidth + ContentContainer.X; - } - private class BackButton : OsuClickableContainer { - private FillFlowContainer flow; private AspectContainer aspect; [BackgroundDependencyLoader] @@ -116,29 +111,22 @@ namespace osu.Game.Overlays RelativeSizeAxes = Axes.Y, Children = new Drawable[] { - flow = new FillFlowContainer + new SpriteIcon { - Anchor = Anchor.TopCentre, - RelativePositionAxes = Axes.Y, - Y = 0.4f, - AutoSizeAxes = Axes.Both, + Anchor = Anchor.Centre, Origin = Anchor.Centre, - Direction = FillDirection.Horizontal, - Children = new[] - { - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, - new SpriteIcon { Size = new Vector2(15), Shadow = true, Icon = FontAwesome.fa_chevron_left }, - } + Y = -15, + Size = new Vector2(15), + Shadow = true, + Icon = FontAwesome.fa_chevron_left }, new OsuSpriteText { - Anchor = Anchor.TopCentre, - RelativePositionAxes = Axes.Y, - Y = 0.7f, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 15, TextSize = 12, Font = @"Exo2.0-Bold", - Origin = Anchor.Centre, Text = @"back", }, } @@ -146,18 +134,6 @@ namespace osu.Game.Overlays }; } - protected override bool OnHover(InputState state) - { - flow.TransformSpacingTo(new Vector2(5), 500, Easing.OutQuint); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - flow.TransformSpacingTo(new Vector2(0), 500, Easing.OutQuint); - base.OnHoverLost(state); - } - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); @@ -171,4 +147,4 @@ namespace osu.Game.Overlays } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index f62087ee71..43720e12b2 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; @@ -25,7 +26,7 @@ namespace osu.Game.Overlays public const float SIDEBAR_WIDTH = Sidebar.DEFAULT_WIDTH; - private const float width = 400; + protected const float WIDTH = 400; private const float sidebar_padding = 10; @@ -33,14 +34,17 @@ namespace osu.Game.Overlays protected override Container Content => ContentContainer; - private Sidebar sidebar; + protected Sidebar Sidebar; private SidebarButton selectedSidebarButton; protected SettingsSectionsContainer SectionsContainer; private SearchTextBox searchTextBox; - private Func getToolbarHeight; + /// + /// Provide a source for the toolbar height. + /// + public Func GetToolbarHeight; private readonly bool showSidebar; @@ -60,12 +64,15 @@ namespace osu.Game.Overlays { InternalChild = ContentContainer = new Container { - Width = width, + Width = WIDTH, RelativeSizeAxes = Axes.Y, Children = new Drawable[] { Background = new Box { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Scale = new Vector2(2, 1), // over-extend to the left for transitions RelativeSizeAxes = Axes.Both, Colour = Color4.Black, Alpha = 0.6f, @@ -94,20 +101,18 @@ namespace osu.Game.Overlays if (showSidebar) { - AddInternal(sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); + AddInternal(Sidebar = new Sidebar { Width = SIDEBAR_WIDTH }); SectionsContainer.SelectedSection.ValueChanged += section => { selectedSidebarButton.Selected = false; - selectedSidebarButton = sidebar.Children.Single(b => b.Section == section); + selectedSidebarButton = Sidebar.Children.Single(b => b.Section == section); selectedSidebarButton.Selected = true; }; } searchTextBox.Current.ValueChanged += newValue => SectionsContainer.SearchContainer.SearchTerm = newValue; - getToolbarHeight = () => game?.ToolbarOffset ?? 0; - CreateSections()?.ForEach(AddSection); } @@ -115,7 +120,7 @@ namespace osu.Game.Overlays { SectionsContainer.Add(section); - if (sidebar != null) + if (Sidebar != null) { var button = new SidebarButton { @@ -123,15 +128,15 @@ namespace osu.Game.Overlays Action = s => { SectionsContainer.ScrollTo(s); - sidebar.State = ExpandedState.Contracted; + Sidebar.State = ExpandedState.Contracted; }, }; - sidebar.Add(button); + Sidebar.Add(button); if (selectedSidebarButton == null) { - selectedSidebarButton = sidebar.Children.First(); + selectedSidebarButton = Sidebar.Children.First(); selectedSidebarButton.Selected = true; } } @@ -145,20 +150,24 @@ namespace osu.Game.Overlays { base.PopIn(); - ContentContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); - sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); - this.FadeTo(1, TRANSITION_LENGTH / 2); + ContentContainer.MoveToX(ExpandedPosition, TRANSITION_LENGTH, Easing.OutQuint); + + Sidebar?.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(1, TRANSITION_LENGTH, Easing.OutQuint); searchTextBox.HoldFocus = true; } + protected virtual float ExpandedPosition => 0; + protected override void PopOut() { base.PopOut(); - ContentContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); - sidebar?.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); - this.FadeTo(0, TRANSITION_LENGTH / 2); + ContentContainer.MoveToX(-WIDTH, TRANSITION_LENGTH, Easing.OutQuint); + + Sidebar?.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint); searchTextBox.HoldFocus = false; if (searchTextBox.HasFocus) @@ -179,8 +188,8 @@ namespace osu.Game.Overlays { base.UpdateAfterChildren(); - ContentContainer.Margin = new MarginPadding { Left = sidebar?.DrawWidth ?? 0 }; - ContentContainer.Padding = new MarginPadding { Top = getToolbarHeight() }; + ContentContainer.Margin = new MarginPadding { Left = Sidebar?.DrawWidth ?? 0 }; + ContentContainer.Padding = new MarginPadding { Top = GetToolbarHeight?.Invoke() ?? 0 }; } protected class SettingsSectionsContainer : SectionsContainer From a44ff5a2c2ed1ac3396e488df6812030a44bb1f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Aug 2017 17:47:44 +0900 Subject: [PATCH 059/180] Fix regression causing global hotkeys to no longer work --- osu.Game.Rulesets.Catch/CatchInputManager.cs | 2 +- osu.Game.Rulesets.Osu/OsuInputManager.cs | 2 +- .../Input/Bindings/DatabasedKeyBindingInputManager.cs | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 683724b7b8..2a913a77d3 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Catch public class CatchInputManager : DatabasedKeyBindingInputManager { public CatchInputManager(RulesetInfo ruleset) - : base(ruleset, simultaneousMode: SimultaneousBindingMode.Unique) + : base(ruleset, 0, SimultaneousBindingMode.Unique) { } } diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 06836994d2..a29b128e07 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu { public class OsuInputManager : DatabasedKeyBindingInputManager { - public OsuInputManager(RulesetInfo ruleset) : base(ruleset, simultaneousMode: SimultaneousBindingMode.Unique) + public OsuInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) { } diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs index f739ba2a59..0a4fcf4389 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Input.Bindings; @@ -17,7 +18,7 @@ namespace osu.Game.Input.Bindings { private readonly RulesetInfo ruleset; - private readonly int variant; + private readonly int? variant; private KeyBindingStore store; @@ -29,11 +30,14 @@ namespace osu.Game.Input.Bindings /// A reference to identify the current . Used to lookup mappings. Null for global mappings. /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. /// Specify how to deal with multiple matches of s and s. - protected DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int variant = 0, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) + protected DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) : base(simultaneousMode) { this.ruleset = ruleset; this.variant = variant; + + if (ruleset != null && variant == null) + throw new InvalidOperationException($"{nameof(variant)} can not be null when a non-null {nameof(ruleset)} is provided."); } [BackgroundDependencyLoader] From 58b1e9c95459b0ee7375db822ead8c74cb70b484 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Aug 2017 17:47:55 +0900 Subject: [PATCH 060/180] Remove unused DI retrieval --- osu.Game/Overlays/SettingsOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 43720e12b2..f9ec2f68b5 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -59,8 +59,8 @@ namespace osu.Game.Overlays protected virtual IEnumerable CreateSections() => null; - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuGame game) + [BackgroundDependencyLoader] + private void load() { InternalChild = ContentContainer = new Container { From f459794665564d4b29d028dfd390a9daafee573e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Aug 2017 18:11:15 +0900 Subject: [PATCH 061/180] Update MainSettings.cs --- osu.Game/Overlays/MainSettings.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index f2011ae88e..b4d9cac045 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -41,7 +41,8 @@ namespace osu.Game.Overlays public MainSettings() : base(true) { - keyBindingOverlay = new KeyBindingOverlay { + keyBindingOverlay = new KeyBindingOverlay + { Depth = 1, Anchor = Anchor.TopRight, }; From df683d911480b987660233c11f322afd4d6b3832 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Thu, 17 Aug 2017 23:28:26 +0930 Subject: [PATCH 062/180] Fix multiple difficulty control points sharing the same time and thus confusing slider velocity calculations --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 46cbad2487..82f48d4361 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Linq; using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Legacy; @@ -331,6 +332,7 @@ namespace osu.Game.Beatmaps.Formats if (speedMultiplier != difficultyPoint.SpeedMultiplier) { + beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == time); beatmap.ControlPointInfo.DifficultyPoints.Add(new DifficultyControlPoint { Time = time, From 61182092004e43ac597ef1492e29a7bc0acaf63a Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Thu, 17 Aug 2017 18:46:16 +0200 Subject: [PATCH 063/180] Fix unlit initial state of the OnScreenDisplay --- osu.Game/Overlays/OnScreenDisplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 746b6dd50f..dcab942522 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -258,7 +258,10 @@ namespace osu.Game.Overlays Type = EdgeEffectType.Glow, Radius = 8, }; + } + protected override void LoadComplete() + { updateGlow(); FinishTransforms(true); } From cc39aad7f8d05fc8f678d1763b998cb1abcab41c Mon Sep 17 00:00:00 2001 From: PoULkY Date: Fri, 18 Aug 2017 01:23:44 +0700 Subject: [PATCH 064/180] Fix OsuButton doesn't implement IFilterable --- osu.Game/Graphics/UserInterface/OsuButton.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 3c454f2af2..5650fc6f48 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -16,7 +17,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { - public class OsuButton : Button + public class OsuButton : Button, IFilterable { private Box hover; @@ -108,5 +109,15 @@ namespace osu.Game.Graphics.UserInterface Content.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(state, args); } + + public string[] FilterTerms => new[] { Text }; + + public bool MatchingFilter + { + set + { + this.FadeTo(value ? 1 : 0); + } + } } } \ No newline at end of file From e4b832e8a6be6ba801cec5d8e2d6228e86e7f9ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Aug 2017 10:48:35 +0900 Subject: [PATCH 065/180] Fix a possible nullref when login fails --- osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 3f8b6186c4..7ae45159d9 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -171,7 +171,7 @@ namespace osu.Game.Overlays.Settings.Sections.General break; } - if (form != null) GetContainingInputManager().ChangeFocus(form); + if (form != null) GetContainingInputManager()?.ChangeFocus(form); } public override bool AcceptsFocus => true; From 243a6ca7745f59e256b531ca5034059ca55e644c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 18 Aug 2017 13:27:16 +0900 Subject: [PATCH 066/180] Update OsuLegacyDecoder.cs --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 82f48d4361..093f607e0d 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Legacy; From a47b6526a2b7810d51adb2cc2f6d035b8e6d5cad Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 18 Aug 2017 14:40:36 +0900 Subject: [PATCH 067/180] Fix CI issues. --- osu.Game/Rulesets/RulesetInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 059f93645f..8d19b28a81 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets public bool Equals(RulesetInfo other) { - return this.ID == other.ID && this.Available == other.Available && this.Name == other.Name && this.InstantiationInfo == other.InstantiationInfo; + return ID == other?.ID && Available == other?.Available && Name == other?.Name && InstantiationInfo == other?.InstantiationInfo; } } -} \ No newline at end of file +} From 90885a31ae8f172fa89fa50279e2cde01ed3f9e7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 18 Aug 2017 15:09:54 +0900 Subject: [PATCH 068/180] Round 2 of CI fixes. --- osu.Game/Rulesets/RulesetInfo.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 8d19b28a81..740369b1b6 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -22,9 +22,6 @@ namespace osu.Game.Rulesets public virtual Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo), this); - public bool Equals(RulesetInfo other) - { - return ID == other?.ID && Available == other?.Available && Name == other?.Name && InstantiationInfo == other?.InstantiationInfo; - } + public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; } } From 306c00e593089589c98ddeea266ffc87d4871037 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 16:26:48 +0930 Subject: [PATCH 069/180] Update framework to include PR #977 --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 5c22092e59..03b7608f21 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 5c22092e590d589927962b8d0173dae5f9b1405c +Subproject commit 03b7608f210b35dbcd3a811bda002e7a9334d081 From 9c6ca2d15928742fb2dbae1b56333d3656a2a7a9 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 16:34:01 +0930 Subject: [PATCH 070/180] Add lazy weak property to DrawableOsuHitObject to find and cache the containing OsuInputManager, if it exists --- .../Objects/Drawables/DrawableOsuHitObject.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index ca1b44e1c7..c5d75f076b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.ComponentModel; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; @@ -51,6 +52,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void UpdateCurrentState(ArmedState state) { } + + private WeakReference osuActionInputManager = new WeakReference(null); + internal OsuInputManager OsuActionInputManager + { + get + { + OsuInputManager target = null; + if (osuActionInputManager.TryGetTarget(out target)) return target; + target = GetContainingInputManager() as OsuInputManager; + osuActionInputManager.SetTarget(target); + return target; + } + } } public enum ComboResult From 9628c0b6d656a2a63a62b46f649344a80399a08b Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 16:46:00 +0930 Subject: [PATCH 071/180] Change spinner to check currently pressed actions rather than implementing IKeyBindingHandler --- .../Objects/Drawables/DrawableSpinner.cs | 8 +++++ .../Objects/Drawables/Pieces/SpinnerDisc.cs | 34 +------------------ 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 4a0b8422f1..307ef5d636 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; @@ -165,6 +166,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables glow.Colour = colours.BlueDark; } + protected override void Update() + { + disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton); + + base.Update(); + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 1e56a2559a..80d4391718 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -12,7 +12,7 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { - public class SpinnerDisc : CircularContainer, IHasAccentColour, IKeyBindingHandler + public class SpinnerDisc : CircularContainer, IHasAccentColour { private readonly Spinner spinner; @@ -73,39 +73,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(state); } - public bool OnPressed(OsuAction action) - { - switch (action) - { - case OsuAction.LeftButton: - actionLeftButtonPressed = true; - break; - case OsuAction.RightButton: - actionRightButtonPressed = true; - break; - } - Tracking = actionLeftButtonPressed || actionRightButtonPressed; - return false; - } - - public bool OnReleased(OsuAction action) - { - switch (action) - { - case OsuAction.LeftButton: - actionLeftButtonPressed = false; - break; - case OsuAction.RightButton: - actionRightButtonPressed = false; - break; - } - Tracking = actionLeftButtonPressed || actionRightButtonPressed; - return false; - } - private Vector2 mousePosition; - private bool actionLeftButtonPressed; - private bool actionRightButtonPressed; private float lastAngle; private float currentRotation; From 90dacd9861809f715151bbcae699afc758914a3b Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 16:49:10 +0930 Subject: [PATCH 072/180] Trim whitespace --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 307ef5d636..8473cc2453 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void Update() { disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton); - + base.Update(); } From 529732ea473093a5a7bbd4fcd27f94b09872fb83 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 16:58:01 +0930 Subject: [PATCH 073/180] More CI fixes --- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 ++-- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index c5d75f076b..cca91925f0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -53,12 +53,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } - private WeakReference osuActionInputManager = new WeakReference(null); + private readonly WeakReference osuActionInputManager = new WeakReference(null); internal OsuInputManager OsuActionInputManager { get { - OsuInputManager target = null; + OsuInputManager target; if (osuActionInputManager.TryGetTarget(out target)) return target; target = GetContainingInputManager() as OsuInputManager; osuActionInputManager.SetTarget(target); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 80d4391718..6577c7fd50 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; -using osu.Framework.Input.Bindings; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; From 4901ac9e35f7c0cd4f23b15c30461e2593ea43df Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 18:01:18 +0930 Subject: [PATCH 074/180] Add some comments explaining why the Track is being forcefully added to the TrackManager --- osu.Game/Screens/Select/SongSelect.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index e20ddf1c09..aa554152f9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -370,6 +370,8 @@ namespace osu.Game.Screens.Select if (!track.IsRunning) { + // Ensure the track is added to the TrackManager, since it is removed after the player finishes the map. + // Using AddItemToList rather than AddItem so that it doesn't attempt to register adjustment dependencies more than once. Game.Audio.Track.AddItemToList(track); if (preview) track.Seek(Beatmap.Value.Metadata.PreviewTime); track.Start(); From 44feef78f14f4d13c7cd173cef22af6980e34bb9 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 19:32:08 +0930 Subject: [PATCH 075/180] Simplify OsuActionInputManager property --- .../Objects/Drawables/DrawableOsuHitObject.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index cca91925f0..409244998e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -53,18 +53,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { } - private readonly WeakReference osuActionInputManager = new WeakReference(null); - internal OsuInputManager OsuActionInputManager - { - get - { - OsuInputManager target; - if (osuActionInputManager.TryGetTarget(out target)) return target; - target = GetContainingInputManager() as OsuInputManager; - osuActionInputManager.SetTarget(target); - return target; - } - } + private OsuInputManager osuActionInputManager; + internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); } public enum ComboResult From 9558d2a16185c5e1b3b2dd8e96f779970df100a9 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 19:39:28 +0930 Subject: [PATCH 076/180] Remove unnecessary using --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 409244998e..b3043d18f6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.ComponentModel; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; From 7e0fe6cbcbafbe0fce0bd6ebaf1d814b5423f9e6 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Fri, 18 Aug 2017 20:19:23 +0930 Subject: [PATCH 077/180] Fix slider tracking to use pressed actions rather than directly querying the mouse buttons --- osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index dbfd9b291b..bdf67a48cc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -118,7 +119,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces base.Update(); if (Time.Current < slider.EndTime) - Tracking = canCurrentlyTrack && lastState != null && ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed; + Tracking = canCurrentlyTrack && lastState != null && ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); } public void UpdateProgress(double progress, int repeat) From d6249e7a633a4df5d504728c7af5404fd8d284d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 18 Aug 2017 18:22:00 +0900 Subject: [PATCH 078/180] Add support for binding mouse buttons to actions --- osu-framework | 2 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 12 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 8 +- .../Bindings/GlobalKeyBindingInputManager.cs | 17 ++- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 126 ++++++++++++------ .../Overlays/KeyBinding/KeyBindingsSection.cs | 5 +- 6 files changed, 111 insertions(+), 59 deletions(-) diff --git a/osu-framework b/osu-framework index 03b7608f21..825505e788 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 03b7608f210b35dbcd3a811bda002e7a9334d081 +Subproject commit 825505e788c4f093b269c61b485d38d50cd68096 diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index b486566b7d..f7662030fc 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -23,12 +23,12 @@ namespace osu.Game.Rulesets.Catch public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { - new KeyBinding(Key.Z, CatchAction.MoveLeft), - new KeyBinding(Key.Left, CatchAction.MoveLeft), - new KeyBinding(Key.X, CatchAction.MoveRight), - new KeyBinding(Key.Right, CatchAction.MoveRight), - new KeyBinding(Key.LShift, CatchAction.Dash), - new KeyBinding(Key.RShift, CatchAction.Dash), + new KeyBinding(InputKey.Z, CatchAction.MoveLeft), + new KeyBinding(InputKey.Left, CatchAction.MoveLeft), + new KeyBinding(InputKey.X, CatchAction.MoveRight), + new KeyBinding(InputKey.Right, CatchAction.MoveRight), + new KeyBinding(InputKey.Shift, CatchAction.Dash), + new KeyBinding(InputKey.Shift, CatchAction.Dash), }; public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 75b7be01a4..aaa1dff820 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -27,10 +27,10 @@ namespace osu.Game.Rulesets.Osu public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] { - new KeyBinding(Key.Z, OsuAction.LeftButton), - new KeyBinding(Key.X, OsuAction.RightButton), - new KeyBinding(Key.LastKey + 1, OsuAction.LeftButton), - new KeyBinding(Key.LastKey + 2, OsuAction.RightButton), + new KeyBinding(InputKey.Z, OsuAction.LeftButton), + new KeyBinding(InputKey.X, OsuAction.RightButton), + new KeyBinding(InputKey.LastKey + 1, OsuAction.LeftButton), + new KeyBinding(InputKey.LastKey + 2, OsuAction.RightButton), }; public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs index 31be2e6adc..5ea66fa600 100644 --- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -22,16 +21,16 @@ namespace osu.Game.Input.Bindings public override IEnumerable DefaultKeyBindings => new[] { - new KeyBinding(Key.F8, GlobalAction.ToggleChat), - new KeyBinding(Key.F9, GlobalAction.ToggleSocial), - new KeyBinding(new[] { Key.LControl, Key.LAlt, Key.R }, GlobalAction.ResetInputSettings), - new KeyBinding(new[] { Key.LControl, Key.T }, GlobalAction.ToggleToolbar), - new KeyBinding(new[] { Key.LControl, Key.O }, GlobalAction.ToggleSettings), - new KeyBinding(new[] { Key.LControl, Key.D }, GlobalAction.ToggleDirect), + new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), + new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), + new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), + new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), + new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), + new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleDirect), }; - protected override IEnumerable GetKeyboardInputQueue() => - handler == null ? base.GetKeyboardInputQueue() : new[] { handler }.Concat(base.GetKeyboardInputQueue()); + protected override IEnumerable KeyBindingInputQueue => + handler == null ? base.KeyBindingInputQueue : new[] { handler }.Concat(base.KeyBindingInputQueue); } public enum GlobalAction diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 44aee0e666..a3361743a1 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Input; @@ -123,46 +124,74 @@ namespace osu.Game.Overlays.KeyBinding base.OnHoverLost(state); } - public override bool AcceptsFocus => true; + public override bool AcceptsFocus => bindTarget == null; private KeyButton bindTarget; - protected override void OnFocus(InputState state) - { - AutoSizeDuration = 500; - AutoSizeEasing = Easing.OutQuint; - - pressAKey.FadeIn(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding(); - - base.OnFocus(state); - } + public bool AllowMainMouseButtons; private bool isModifier(Key k) => k < Key.F1; - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - switch (args.Key) - { - case Key.Escape: - GetContainingInputManager().ChangeFocus(null); - return true; - case Key.Delete: - bindTarget.UpdateKeyCombination(Key.Unknown); - store.Update(bindTarget.KeyBinding); - GetContainingInputManager().ChangeFocus(null); - return true; - } + protected override bool OnClick(InputState state) => true; + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { if (HasFocus) { - bindTarget.UpdateKeyCombination(state.Keyboard.Keys.ToArray()); - if (!isModifier(args.Key)) + if (bindTarget.IsHovered) + { + if (!AllowMainMouseButtons) + { + switch (args.Button) + { + case MouseButton.Left: + case MouseButton.Right: + return true; + } + } + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + return true; + } + } + + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + if (HasFocus && !state.Mouse.Buttons.Any()) + { + if (bindTarget.IsHovered) finalise(); + else + updateBindTarget(); return true; } - return base.OnKeyDown(state, args); + return base.OnMouseUp(state, args); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (!HasFocus) + return false; + + switch (args.Key) + { + case Key.Escape: + finalise(); + return true; + case Key.Delete: + bindTarget.UpdateKeyCombination(InputKey.None); + finalise(); + return true; + } + + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + if (!isModifier(args.Key)) finalise(); + + return true; } protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) @@ -178,27 +207,48 @@ namespace osu.Game.Overlays.KeyBinding private void finalise() { - store.Update(bindTarget.KeyBinding); - GetContainingInputManager().ChangeFocus(null); + if (bindTarget != null) + { + store.Update(bindTarget.KeyBinding); + + bindTarget.IsBinding = false; + Schedule(() => + { + // schedule to ensure we don't instantly get focus back on next OnMouseClick (see AcceptFocus impl.) + bindTarget = null; + }); + } + + if (HasFocus) + GetContainingInputManager().ChangeFocus(null); + + pressAKey.FadeOut(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + } + + protected override void OnFocus(InputState state) + { + AutoSizeDuration = 500; + AutoSizeEasing = Easing.OutQuint; + + pressAKey.FadeIn(300, Easing.OutQuint); + pressAKey.Padding = new MarginPadding(); + + updateBindTarget(); + base.OnFocus(state); } protected override void OnFocusLost(InputState state) { - bindTarget.IsBinding = false; - bindTarget = null; - - pressAKey.FadeOut(300, Easing.OutQuint); - pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight }; + finalise(); base.OnFocusLost(state); } - protected override bool OnClick(InputState state) + private void updateBindTarget() { if (bindTarget != null) bindTarget.IsBinding = false; bindTarget = buttons.FirstOrDefault(b => b.IsHovered) ?? buttons.FirstOrDefault(); if (bindTarget != null) bindTarget.IsBinding = true; - - return bindTarget != null; } private class KeyButton : Container @@ -296,7 +346,7 @@ namespace osu.Game.Overlays.KeyBinding } } - public void UpdateKeyCombination(params Key[] newCombination) + public void UpdateKeyCombination(KeyCombination newCombination) { KeyBinding.KeyCombination = newCombination; Text.Text = KeyBinding.KeyCombination.ReadableString(); diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs index 19baeca771..44c28ee9c8 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs @@ -40,7 +40,10 @@ namespace osu.Game.Overlays.KeyBinding foreach (Enum v in Enum.GetValues(enumType)) // one row per valid action. - Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v)))); + Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v))) + { + AllowMainMouseButtons = Ruleset != null + }); } } } \ No newline at end of file From f829caf197c7565bf8d4995073d1eae17c183579 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 19 Aug 2017 07:21:20 +0900 Subject: [PATCH 079/180] Fix custom logic still existing in OsuInputManager --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index a29b128e07..0c4384c006 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -2,13 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; -using System.Linq; -using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; -using OpenTK.Input; -using KeyboardState = osu.Framework.Input.KeyboardState; -using MouseState = osu.Framework.Input.MouseState; namespace osu.Game.Rulesets.Osu { @@ -16,22 +11,6 @@ namespace osu.Game.Rulesets.Osu { public OsuInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) { - - } - protected override void TransformState(InputState state) - { - base.TransformState(state); - - var mouse = state.Mouse as MouseState; - var keyboard = state.Keyboard as KeyboardState; - - if (mouse != null && keyboard != null) - { - if (mouse.IsPressed(MouseButton.Left)) - keyboard.Keys = keyboard.Keys.Concat(new[] { Key.LastKey + 1 }); - if (mouse.IsPressed(MouseButton.Right)) - keyboard.Keys = keyboard.Keys.Concat(new[] { Key.LastKey + 2 }); - } } } From 51af233d66f5cf54449d1252e0d6c5de260bc099 Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sat, 19 Aug 2017 12:19:37 +0930 Subject: [PATCH 080/180] Fix sliders not checking the correct cursor position once it moves out of the follow circle --- .../Objects/Drawables/Pieces/SliderBall.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index bdf67a48cc..9b5862e739 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces @@ -97,6 +98,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(state); } + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) + { + // If the current time is between the start and end of the slider, we should track mouse input regardless of the cursor position. + return canCurrentlyTrack || base.ReceiveMouseInputAt(screenSpacePos); + } + private bool tracking; public bool Tracking { @@ -118,8 +125,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { base.Update(); + // Make sure to use the base version of ReceiveMouseInputAt so that we correctly check the position. if (Time.Current < slider.EndTime) - Tracking = canCurrentlyTrack && lastState != null && ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + Tracking = canCurrentlyTrack && lastState != null && base.ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); } public void UpdateProgress(double progress, int repeat) From 1e6d99a4ef1e0787b9863cc72545e69286db332f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 19 Aug 2017 07:31:03 +0900 Subject: [PATCH 081/180] Update paths --- osu.Desktop.Deploy/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index 37776b329f..644987ce5a 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -17,8 +17,8 @@ namespace osu.Desktop.Deploy { internal static class Program { - private const string nuget_path = @"packages\NuGet.CommandLine.3.5.0\tools\NuGet.exe"; - private const string squirrel_path = @"packages\squirrel.windows.1.5.2\tools\Squirrel.exe"; + private const string nuget_path = @"packages\NuGet.CommandLine.4.1.0\tools\NuGet.exe"; + private const string squirrel_path = @"packages\squirrel.windows.1.7.5\tools\Squirrel.exe"; private const string msbuild_path = @"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"; public static string StagingFolder = ConfigurationManager.AppSettings["StagingFolder"]; From 3ea7be1ccfef8643fcc94597d9b542dbb43d0909 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 19 Aug 2017 12:26:54 +0900 Subject: [PATCH 082/180] Fix selecting unranked beatmaps in song select crashing the game. Fixes #1134. --- osu.Game/Graphics/UserInterface/BarGraph.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 87b4ab9e40..1a980e6bd5 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -44,19 +44,31 @@ namespace osu.Game.Graphics.UserInterface { List bars = Children.ToList(); foreach (var bar in value.Select((length, index) => new { Value = length, Bar = bars.Count > index ? bars[index] : null })) + { + float length = MaxValue ?? value.Max(); + if (length != 0) + length = bar.Value / length; + + float size = value.Count(); + if (size != 0) + size = 1.0f / size; + if (bar.Bar != null) { - bar.Bar.Length = bar.Value / (MaxValue ?? value.Max()); - bar.Bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / value.Count()) : new Vector2(1.0f / value.Count(), 1); + bar.Bar.Length = length; + bar.Bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1); } else + { Add(new Bar { RelativeSizeAxes = Axes.Both, - Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / value.Count()) : new Vector2(1.0f / value.Count(), 1), - Length = bar.Value / (MaxValue ?? value.Max()), + Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, size) : new Vector2(size, 1), + Length = length, Direction = Direction, }); + } + } //I'm using ToList() here because Where() returns an Enumerable which can change it's elements afterwards RemoveRange(Children.Where((bar, index) => index >= value.Count()).ToList()); } From 9bebb9f5b0ec5c087801504fce2eaee06850dc4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 19 Aug 2017 16:09:32 +0200 Subject: [PATCH 083/180] Remove now unused SliderBar class --- .../Visual/TestCaseKeyCounter.cs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs index 1861a77a3a..e8b6e6378e 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs @@ -41,38 +41,5 @@ namespace osu.Desktop.Tests.Visual Add(kc); } - private class TestSliderBar : SliderBar where T : struct - { - public Color4 Color - { - get { return Box.Colour; } - set { Box.Colour = value; } - } - - public Color4 SelectionColor - { - get { return SelectionBox.Colour; } - set { SelectionBox.Colour = value; } - } - - protected readonly Box SelectionBox; - protected readonly Box Box; - - public TestSliderBar() - { - Children = new Drawable[] - { - Box = new Box { RelativeSizeAxes = Axes.Both }, - SelectionBox = new Box { RelativeSizeAxes = Axes.Both } - }; - } - - protected override void UpdateValue(float value) - { - SelectionBox.ScaleTo( - new Vector2(value, 1), - 300, Easing.OutQuint); - } - } } } From bae1340b5063a9bb72fe2c31f31cf88048c0e782 Mon Sep 17 00:00:00 2001 From: Jorolf Date: Sat, 19 Aug 2017 17:00:01 +0200 Subject: [PATCH 084/180] mask the settings overlay --- osu.Game/Overlays/SettingsOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index f9ec2f68b5..ddef5d1001 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -79,6 +79,7 @@ namespace osu.Game.Overlays }, SectionsContainer = new SettingsSectionsContainer { + Masking = true, RelativeSizeAxes = Axes.Both, ExpandableHeader = CreateHeader(), FixedHeader = searchTextBox = new SearchTextBox From 7e1df7907febed0cab5d5d423a0f917e7ddc6df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Sat, 19 Aug 2017 17:43:02 +0200 Subject: [PATCH 085/180] Remove now unnecessary usings --- osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs index e8b6e6378e..ffe37c83a6 100644 --- a/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Desktop.Tests/Visual/TestCaseKeyCounter.cs @@ -2,12 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.UserInterface; using osu.Framework.MathUtils; using osu.Game.Screens.Play; -using OpenTK; -using OpenTK.Graphics; using OpenTK.Input; namespace osu.Desktop.Tests.Visual From 9b20da94e7cc0d1c27819b8bbb6d7bd4fc546302 Mon Sep 17 00:00:00 2001 From: Jorolf Date: Sat, 19 Aug 2017 22:07:03 +0200 Subject: [PATCH 086/180] change Query to AllRulesets --- osu.Game/Input/KeyBindingStore.cs | 2 +- osu.Game/Overlays/KeyBindingOverlay.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index f50acb4802..56302acafe 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -18,7 +18,7 @@ namespace osu.Game.Input public KeyBindingStore(SQLiteConnection connection, RulesetStore rulesets, Storage storage = null) : base(connection, storage) { - foreach (var info in rulesets.Query()) + foreach (var info in rulesets.AllRulesets) { var ruleset = info.CreateInstance(); foreach (var variant in ruleset.AvailableVariants) diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 7d6ef7ffa6..827d361099 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays { AddSection(new GlobalKeyBindingsSection(global, "Global")); - foreach (var ruleset in rulesets.Query()) + foreach (var ruleset in rulesets.AllRulesets) AddSection(new RulesetBindingsSection(ruleset)); } From 71ddbd22a1b74c28ed7dc182396939d942fb6cfa Mon Sep 17 00:00:00 2001 From: Shane Woolcock Date: Sun, 20 Aug 2017 14:00:53 +0930 Subject: [PATCH 087/180] Convert ReceiveMouseInputAt override to lambda syntax, and make Tracking property private set --- .../Objects/Drawables/Pieces/SliderBall.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 9b5862e739..0bcb8a4986 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -98,17 +98,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(state); } - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) - { - // If the current time is between the start and end of the slider, we should track mouse input regardless of the cursor position. - return canCurrentlyTrack || base.ReceiveMouseInputAt(screenSpacePos); - } + // If the current time is between the start and end of the slider, we should track mouse input regardless of the cursor position. + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => canCurrentlyTrack || base.ReceiveMouseInputAt(screenSpacePos); private bool tracking; public bool Tracking { get { return tracking; } - set + private set { if (value == tracking) return; From ff84eb219bfdbf954da4046dadbd5d48f7a6eb7b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 21:18:21 +0900 Subject: [PATCH 088/180] Add action support to taiko --- .../Objects/Drawables/DrawableCentreHit.cs | 3 +- .../Drawables/DrawableCentreHitStrong.cs | 3 +- .../Objects/Drawables/DrawableDrumRoll.cs | 2 + .../Objects/Drawables/DrawableDrumRollTick.cs | 3 +- .../Objects/Drawables/DrawableHit.cs | 7 ++-- .../Objects/Drawables/DrawableHitStrong.cs | 30 +++++++------- .../Objects/Drawables/DrawableRimHit.cs | 3 +- .../Objects/Drawables/DrawableRimHitStrong.cs | 3 +- .../Objects/Drawables/DrawableSwell.cs | 16 ++++---- .../Drawables/DrawableTaikoHitObject.cs | 41 ++++++++----------- 10 files changed, 50 insertions(+), 61 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs index 8bb78669ca..26aa20f1af 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -4,13 +4,12 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableCentreHit : DrawableHit { - protected override Key[] HitKeys { get; } = { Key.F, Key.J }; + protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; public DrawableCentreHit(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs index 434fb9377f..1dbab408de 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs @@ -4,13 +4,12 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableCentreHitStrong : DrawableHitStrong { - protected override Key[] HitKeys { get; } = { Key.F, Key.J }; + protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; public DrawableCentreHitStrong(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 8f81368a2c..5d6ea8f51e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -56,6 +56,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); + public override bool OnPressed(TaikoAction action) => false; + [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 6e916aa9d5..e94886df16 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; -using OpenTK.Input; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -59,7 +58,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override bool HandleKeyPress(Key key) + public override bool OnPressed(TaikoAction action) { return Judgement.Result == HitResult.None && UpdateJudgement(true); } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 0666d75083..5fcae7d0f4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -16,7 +15,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A list of keys which can result in hits for this HitObject. /// - protected abstract Key[] HitKeys { get; } + protected abstract TaikoAction[] HitActions { get; } /// /// Whether the last key pressed is a valid hit key. @@ -62,12 +61,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Judgement.Result = HitResult.Miss; } - protected override bool HandleKeyPress(Key key) + public override bool OnPressed(TaikoAction action) { if (Judgement.Result != HitResult.None) return false; - validKeyPressed = HitKeys.Contains(key); + validKeyPressed = HitActions.Contains(action); return UpdateJudgement(true); } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index 57e7eea470..f419bacfa1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework.Input; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private double firstHitTime; private bool firstKeyHeld; - private Key firstHitKey; + private TaikoAction firstHitAction; protected DrawableHitStrong(Hit hit) : base(hit) @@ -46,18 +45,26 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Judgement.SecondHit = true; } - protected override bool HandleKeyPress(Key key) + public override bool OnReleased(TaikoAction action) + { + if (action == firstHitAction) + firstKeyHeld = false; + return base.OnReleased(action); + } + + public override bool OnPressed(TaikoAction action) { // Check if we've handled the first key if (Judgement.Result == HitResult.None) { // First key hasn't been handled yet, attempt to handle it - bool handled = base.HandleKeyPress(key); + bool handled = base.OnPressed(action); if (handled) { firstHitTime = Time.Current; - firstHitKey = key; + firstHitAction = action; + firstKeyHeld = true; } return handled; @@ -68,22 +75,15 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; // Don't handle represses of the first key - if (firstHitKey == key) + if (firstHitAction == action) return false; - // Don't handle invalid hit key presses - if (!HitKeys.Contains(key)) + // Don't handle invalid hit action presses + if (!HitActions.Contains(action)) return false; // Assume the intention was to hit the strong hit with both keys only if the first key is still being held down return firstKeyHeld && UpdateJudgement(true); } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - firstKeyHeld = state.Keyboard.Keys.Contains(firstHitKey); - - return base.OnKeyDown(state, args); - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs index 20e8d36105..9f0cd3e061 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -4,13 +4,12 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableRimHit : DrawableHit { - protected override Key[] HitKeys { get; } = { Key.D, Key.K }; + protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftRim, TaikoAction.RightRim }; public DrawableRimHit(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs index 4b1bb62bab..294198f3ee 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs @@ -4,13 +4,12 @@ using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableRimHitStrong : DrawableHitStrong { - protected override Key[] HitKeys { get; } = { Key.D, Key.K }; + protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftRim, TaikoAction.RightRim }; public DrawableRimHitStrong(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 2b1ed07da7..fc3bc82520 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -13,7 +13,6 @@ using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; using osu.Framework.Graphics.Shapes; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -35,9 +34,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; - private readonly Key[] rimKeys = { Key.D, Key.K }; - private readonly Key[] centreKeys = { Key.F, Key.J }; - private Key[] lastKeySet; + private readonly TaikoAction[] rimActions = { TaikoAction.LeftRim, TaikoAction.RightRim }; + private readonly TaikoAction[] centreActions = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; + private TaikoAction[] lastAction; /// /// The amount of times the user has hit this swell. @@ -211,8 +210,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - - protected override bool HandleKeyPress(Key key) + public override bool OnPressed(TaikoAction action) { if (Judgement.Result != HitResult.None) return false; @@ -222,12 +220,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; // Find the keyset which this key corresponds to - var keySet = rimKeys.Contains(key) ? rimKeys : centreKeys; + var keySet = rimActions.Contains(action) ? rimActions : centreActions; // Ensure alternating keysets - if (keySet == lastKeySet) + if (keySet == lastAction) return false; - lastKeySet = keySet; + lastAction = keySet; UpdateJudgement(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index caae70fe05..44b371f710 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,26 +1,21 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; +using System.ComponentModel; using osu.Framework.Graphics; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; -using OpenTK.Input; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableScrollingHitObject + public abstract class DrawableTaikoHitObject : + DrawableScrollingHitObject, + IKeyBindingHandler where TaikoHitType : TaikoHitObject { - /// - /// A list of keys which this hit object will accept. These are the standard Taiko keys for now. - /// These should be moved to bindings later. - /// - private readonly List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K }); - public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); protected readonly TaikoPiece MainPiece; @@ -46,20 +41,20 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); - protected virtual bool HandleKeyPress(Key key) => false; + public abstract bool OnPressed(TaikoAction action); - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - // Make sure we don't handle held-down keys - if (args.Repeat) - return false; + public virtual bool OnReleased(TaikoAction action) => false; + } - // Check if we've pressed a valid taiko key - if (!validKeys.Contains(args.Key)) - return false; - - // Handle it! - return HandleKeyPress(args.Key); - } + public enum TaikoAction + { + [Description("Left (Rim)")] + LeftRim, + [Description("Left (Centre)")] + LeftCentre, + [Description("Right (Centre)")] + RightCentre, + [Description("Right (Rim)")] + RightRim } } From 59fc6cbed7b2c207ecfff3353f253ca97785cacb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 21:51:56 +0900 Subject: [PATCH 089/180] Add action support to InputDrum --- .../Objects/Drawables/DrawableHitStrong.cs | 1 - osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 29 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index f419bacfa1..256c50d33a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using osu.Framework.Input; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 0255171284..9cabf2cd2b 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -3,14 +3,14 @@ using System; using OpenTK; -using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.UI { @@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.X, X = -middle_split / 2, - RimKey = Key.D, - CentreKey = Key.F + RimAction = TaikoAction.LeftRim, + CentreAction = TaikoAction.LeftCentre }, new TaikoHalfDrum(true) { @@ -47,8 +47,8 @@ namespace osu.Game.Rulesets.Taiko.UI RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.X, X = middle_split / 2, - RimKey = Key.K, - CentreKey = Key.J + RimAction = TaikoAction.RightRim, + CentreAction = TaikoAction.RightCentre } }; } @@ -56,17 +56,17 @@ namespace osu.Game.Rulesets.Taiko.UI /// /// A half-drum. Contains one centre and one rim hit. /// - private class TaikoHalfDrum : Container + private class TaikoHalfDrum : Container, IKeyBindingHandler { /// /// The key to be used for the rim of the half-drum. /// - public Key RimKey; + public TaikoAction RimAction; /// /// The key to be used for the centre of the half-drum. /// - public Key CentreKey; + public TaikoAction CentreAction; private readonly Sprite rim; private readonly Sprite rimHit; @@ -124,20 +124,17 @@ namespace osu.Game.Rulesets.Taiko.UI centreHit.Colour = colours.Pink; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(TaikoAction action) { - if (args.Repeat) - return false; - Drawable target = null; Drawable back = null; - if (args.Key == CentreKey) + if (action == CentreAction) { target = centreHit; back = centre; } - else if (args.Key == RimKey) + else if (action == RimAction) { target = rimHit; back = rim; @@ -166,6 +163,8 @@ namespace osu.Game.Rulesets.Taiko.UI return false; } + + public bool OnReleased(TaikoAction action) => false; } } } From 09b5eef26e8ae1852cfc6a5e1e14f0464e482bb2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 21:56:28 +0900 Subject: [PATCH 090/180] Fix incorrect osu! defaults --- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index aaa1dff820..49848cb67c 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -29,8 +29,8 @@ namespace osu.Game.Rulesets.Osu { new KeyBinding(InputKey.Z, OsuAction.LeftButton), new KeyBinding(InputKey.X, OsuAction.RightButton), - new KeyBinding(InputKey.LastKey + 1, OsuAction.LeftButton), - new KeyBinding(InputKey.LastKey + 2, OsuAction.RightButton), + new KeyBinding(InputKey.MouseLeft, OsuAction.LeftButton), + new KeyBinding(InputKey.MouseRight, OsuAction.RightButton), }; public override IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] From ec08b2940d8fe1a028b208e4d6d6fd0db3275105 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 21:56:37 +0900 Subject: [PATCH 091/180] Add taiko default keys --- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 4d4bbb7bc5..892c8a1705 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -13,6 +13,8 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Scoring; +using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko { @@ -20,6 +22,14 @@ namespace osu.Game.Rulesets.Taiko { public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset); + public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[] + { + new KeyBinding(InputKey.D, TaikoAction.LeftRim), + new KeyBinding(InputKey.F, TaikoAction.LeftCentre), + new KeyBinding(InputKey.J, TaikoAction.RightCentre), + new KeyBinding(InputKey.K, TaikoAction.RightRim), + }; + public override IEnumerable GetModsFor(ModType type) { switch (type) From a18b2bd5f05106b25e0ce2f832e8da892ced0ae5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 22:21:16 +0900 Subject: [PATCH 092/180] Hook everything up --- .../Visual/TestCaseTaikoPlayfield.cs | 11 ++++--- .../Drawables/DrawableTaikoHitObject.cs | 13 --------- osu.Game.Rulesets.Taiko/TaikoInputManager.cs | 29 +++++++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 1 - osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 1 - .../UI/TaikoRulesetContainer.cs | 3 ++ .../osu.Game.Rulesets.Taiko.csproj | 1 + 7 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/TaikoInputManager.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs index 43148da512..681805ced0 100644 --- a/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseTaikoPlayfield.cs @@ -16,6 +16,8 @@ using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps; using osu.Desktop.Tests.Beatmaps; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; namespace osu.Desktop.Tests.Visual @@ -30,10 +32,11 @@ namespace osu.Desktop.Tests.Visual protected override double TimePerAction => default_duration * 2; private readonly Random rng = new Random(1337); - private readonly TaikoRulesetContainer rulesetContainer; - private readonly Container playfieldContainer; + private TaikoRulesetContainer rulesetContainer; + private Container playfieldContainer; - public TestCaseTaikoPlayfield() + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { AddStep("Hit!", () => addHitJudgement(false)); AddStep("Kiai hit", () => addHitJudgement(true)); @@ -82,7 +85,7 @@ namespace osu.Desktop.Tests.Visual RelativeSizeAxes = Axes.X, Height = 768, Clock = new FramedClock(rateAdjustClock), - Children = new[] { rulesetContainer = new TaikoRulesetContainer(null, beatmap, true) } + Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap, true) } }); } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 44b371f710..8d7a14b683 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.ComponentModel; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Objects.Drawables; @@ -45,16 +44,4 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public virtual bool OnReleased(TaikoAction action) => false; } - - public enum TaikoAction - { - [Description("Left (Rim)")] - LeftRim, - [Description("Left (Centre)")] - LeftCentre, - [Description("Right (Centre)")] - RightCentre, - [Description("Right (Rim)")] - RightRim - } } diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs new file mode 100644 index 0000000000..ad3b25d088 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; + +namespace osu.Game.Rulesets.Taiko +{ + public class TaikoInputManager : DatabasedKeyBindingInputManager + { + public TaikoInputManager(RulesetInfo ruleset) + : base(ruleset, 0, SimultaneousBindingMode.Unique) + { + } + } + + public enum TaikoAction + { + [Description("Left (Rim)")] + LeftRim, + [Description("Left (Centre)")] + LeftCentre, + [Description("Right (Centre)")] + RightCentre, + [Description("Right (Rim)")] + RightRim + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 892c8a1705..3a85df43fe 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Scoring; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko { diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 9cabf2cd2b..659f421ebe 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Game.Graphics; -using osu.Game.Rulesets.Taiko.Objects.Drawables; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 723af3e4e9..4b1c3d7f16 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Taiko.Replays; using OpenTK; using osu.Game.Rulesets.Beatmaps; using System.Linq; +using osu.Framework.Input; namespace osu.Game.Rulesets.Taiko.UI { @@ -92,6 +93,8 @@ namespace osu.Game.Rulesets.Taiko.UI protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + public override PassThroughInputManager CreateKeyBindingInputManager() => new TaikoInputManager(Ruleset?.RulesetInfo); + protected override Playfield CreatePlayfield() => new TaikoPlayfield { Anchor = Anchor.CentreLeft, diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 59c6f4db0a..33748a267f 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -86,6 +86,7 @@ + From 325eaa8671f53adc2c2d47cb72a65d5329a81232 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 22:26:33 +0900 Subject: [PATCH 093/180] Add mouse buttons defaults for taiko --- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 3a85df43fe..41b8ff78a9 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -27,6 +27,10 @@ namespace osu.Game.Rulesets.Taiko new KeyBinding(InputKey.F, TaikoAction.LeftCentre), new KeyBinding(InputKey.J, TaikoAction.RightCentre), new KeyBinding(InputKey.K, TaikoAction.RightRim), + new KeyBinding(InputKey.MouseLeft, TaikoAction.LeftCentre), + new KeyBinding(InputKey.MouseLeft, TaikoAction.RightCentre), + new KeyBinding(InputKey.MouseRight, TaikoAction.LeftRim), + new KeyBinding(InputKey.MouseRight, TaikoAction.RightRim), }; public override IEnumerable GetModsFor(ModType type) From 83643396176e4e085ef5f1cf10f4aac2aad6d213 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 20 Aug 2017 23:47:07 +0900 Subject: [PATCH 094/180] Adjust with proposed formatting --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 8d7a14b683..765002fb34 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -10,10 +10,9 @@ using OpenTK; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : - DrawableScrollingHitObject, - IKeyBindingHandler - where TaikoHitType : TaikoHitObject + public abstract class DrawableTaikoHitObject + : DrawableScrollingHitObject, IKeyBindingHandler + where TaikoHitType : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); From 6a7b410bc3f9616d8d9fb2e952e1f2f9f49cfb52 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 11:45:57 +0900 Subject: [PATCH 095/180] Make DifficultyControlPoint.SpeedMultiplier actually increase with an increasing speed. Fixes #1147 --- .../Patterns/Legacy/DistanceObjectPatternGenerator.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 4 ++-- osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs | 2 +- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- osu.Game/Rulesets/Timing/MultiplierControlPoint.cs | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 7e9615a703..c03a8438ae 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // The true distance, accounting for any repeats double distance = (distanceData?.Distance ?? 0) * repeatCount; // The velocity of the osu! hit object - calculated as the velocity of a slider - double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier / (timingPoint.BeatLength * difficultyPoint.SpeedMultiplier); + double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier / timingPoint.BeatLength; // The duration of the osu! hit object double osuDuration = distance / osuVelocity; diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 4d8c030ede..056bde4005 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier / difficultyPoint.SpeedMultiplier; + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; Velocity = scoringDistance / timingPoint.BeatLength; TickDistance = scoringDistance / difficulty.SliderTickRate; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 44f61e2074..b6d87c745f 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); double speedAdjustment = difficultyPoint.SpeedMultiplier; - double speedAdjustedBeatLength = timingPoint.BeatLength * speedAdjustment; + double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; // The true distance, accounting for any repeats. This ends up being the drum roll distance later double distance = distanceData.Distance * repeats * legacy_velocity_multiplier; @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps // For some reason, old osu! always uses speedAdjustment to determine the taiko velocity, but // only uses it to determine osu! velocity if beatmap version < 8. Let's account for that here. if (beatmap.BeatmapInfo.BeatmapVersion >= 8) - speedAdjustedBeatLength /= speedAdjustment; + speedAdjustedBeatLength *= speedAdjustment; // The velocity of the osu! hit object - calculated as the velocity of a slider double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.Difficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength; diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 30c7884334..c622d5310c 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -10,4 +10,4 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double SpeedMultiplier = 1; } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 093f607e0d..b51ea607dd 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -280,7 +280,7 @@ namespace osu.Game.Beatmaps.Formats double time = double.Parse(split[0].Trim(), NumberFormatInfo.InvariantInfo); double beatLength = double.Parse(split[1].Trim(), NumberFormatInfo.InvariantInfo); - double speedMultiplier = beatLength < 0 ? -beatLength / 100.0 : 1; + double speedMultiplier = beatLength < 0 ? 100.0 / -beatLength : 1; TimeSignatures timeSignature = TimeSignatures.SimpleQuadruple; if (split.Length >= 3) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index ffe40e4f2e..479cacc52b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Objects.Legacy TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime); - double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier / difficultyPoint.SpeedMultiplier; + double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier; Velocity = scoringDistance / timingPoint.BeatLength; } diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index 3b9b8d2d57..4f1a85cf2d 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Timing /// /// The multiplier which this provides. /// - public double Multiplier => 1000 / TimingPoint.BeatLength / DifficultyPoint.SpeedMultiplier; + public double Multiplier => 1000 / TimingPoint.BeatLength * DifficultyPoint.SpeedMultiplier; /// /// The that provides the timing information for this . @@ -62,4 +62,4 @@ namespace osu.Game.Rulesets.Timing public int CompareTo(MultiplierControlPoint other) => StartTime.CompareTo(other?.StartTime); } -} \ No newline at end of file +} From 0970439e34d6c33c0747f83049835dd47f6edf0e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 12:04:58 +0900 Subject: [PATCH 096/180] Fix TaikoBeatmapConverter attempting to convert taiko-specific drum rolls to hits. Fixes #1149 --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 44f61e2074..a72ba1fa55 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -39,10 +39,14 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps /// private const float taiko_base_distance = 100; + private bool isForCurrentRuleset; + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; protected override Beatmap ConvertBeatmap(Beatmap original, bool isForCurrentRuleset) { + this.isForCurrentRuleset = isForCurrentRuleset; + // Rewrite the beatmap info to add the slider velocity multiplier BeatmapInfo info = original.BeatmapInfo.DeepClone(); info.Difficulty.SliderMultiplier *= legacy_velocity_multiplier; @@ -104,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.Difficulty.SliderTickRate, taikoDuration / repeats); - if (tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) + if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { List allSamples = curveData != null ? curveData.RepeatSamples : new List(new[] { samples }); From 16e96888abc044955288fdfedf5a33fc968c672b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 12:31:21 +0900 Subject: [PATCH 097/180] Update KeyCounterCollection to support action-based buttons --- .../Visual/TestCaseScrollingPlayfield.cs | 3 ++ osu.Game.Rulesets.Catch/CatchInputManager.cs | 4 +- osu.Game.Rulesets.Catch/CatchRuleset.cs | 9 ---- .../UI/CatchRulesetContainer.cs | 2 +- osu.Game.Rulesets.Mania/ManiaInputManager.cs | 21 +++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 3 -- .../UI/ManiaRulesetContainer.cs | 3 ++ .../osu.Game.Rulesets.Mania.csproj | 1 + osu.Game.Rulesets.Osu/OsuInputManager.cs | 4 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 10 ----- .../UI/OsuRulesetContainer.cs | 2 +- osu.Game.Rulesets.Taiko/TaikoInputManager.cs | 4 +- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 10 ----- .../UI/TaikoRulesetContainer.cs | 2 +- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 3 -- osu.Game/Rulesets/Ruleset.cs | 3 -- osu.Game/Rulesets/UI/RulesetContainer.cs | 16 ++++--- osu.Game/Rulesets/UI/RulesetInputManager.cs | 44 +++++++++++++++++++ osu.Game/Screens/Play/HUDOverlay.cs | 2 +- osu.Game/Screens/Play/KeyCounterAction.cs | 30 +++++++++++++ osu.Game/Screens/Play/KeyCounterCollection.cs | 22 +++++++--- osu.Game/Screens/Play/Player.cs | 5 +-- osu.Game/osu.Game.csproj | 2 + 23 files changed, 140 insertions(+), 65 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/ManiaInputManager.cs create mode 100644 osu.Game/Rulesets/UI/RulesetInputManager.cs create mode 100644 osu.Game/Screens/Play/KeyCounterAction.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 43bd921cfc..e9c29d36c2 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -8,6 +8,7 @@ using osu.Desktop.Tests.Beatmaps; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; @@ -77,6 +78,8 @@ namespace osu.Desktop.Tests.Visual public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); + public override PassThroughInputManager CreateInputManager() => new PassThroughInputManager(); + protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes); diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 2a913a77d3..47e9b9905a 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -3,11 +3,11 @@ using System.ComponentModel; using osu.Framework.Input.Bindings; -using osu.Game.Input.Bindings; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch { - public class CatchInputManager : DatabasedKeyBindingInputManager + public class CatchInputManager : RulesetInputManager { public CatchInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index f7662030fc..96f8a8df9b 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,14 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Catch.Mods; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Scoring; @@ -101,13 +99,6 @@ namespace osu.Game.Rulesets.Catch public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; - public override IEnumerable CreateGameplayKeys() => new KeyCounter[] - { - new KeyCounterKeyboard(Key.ShiftLeft), - new KeyCounterMouse(MouseButton.Left), - new KeyCounterMouse(MouseButton.Right) - }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 1d037deaef..f8f74af6c9 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.UI protected override Playfield CreatePlayfield() => new CatchPlayfield(); - public override PassThroughInputManager CreateKeyBindingInputManager() => new CatchInputManager(Ruleset?.RulesetInfo); + public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) { diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs new file mode 100644 index 0000000000..b608e4d8d6 --- /dev/null +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Input.Bindings; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mania +{ + public class ManiaInputManager : RulesetInputManager + { + public ManiaInputManager(RulesetInfo ruleset) + : base(ruleset, 0, SimultaneousBindingMode.Unique) + { + } + } + + public enum ManiaAction + { + // placeholder + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 50ad6960ae..c7809f83ed 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Graphics; @@ -111,8 +110,6 @@ namespace osu.Game.Rulesets.Mania public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; - public override IEnumerable CreateGameplayKeys() => new KeyCounter[] { /* Todo: Should be keymod specific */ }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 7f6b19f3bd..9584dc34b8 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -10,6 +10,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Framework.Lists; using osu.Framework.MathUtils; using osu.Game.Beatmaps; @@ -92,6 +93,8 @@ namespace osu.Game.Rulesets.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); + public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo); + protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index fb0b2d907f..890c9116cf 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -79,6 +79,7 @@ + diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 0c4384c006..a65d28cec0 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -3,11 +3,11 @@ using System.ComponentModel; using osu.Framework.Input.Bindings; -using osu.Game.Input.Bindings; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu { - public class OsuInputManager : DatabasedKeyBindingInputManager + public class OsuInputManager : RulesetInputManager { public OsuInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) { diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 49848cb67c..00413331e0 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; @@ -10,7 +9,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.OsuDifficulty; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; @@ -122,14 +120,6 @@ namespace osu.Game.Rulesets.Osu public override string Description => "osu!"; - public override IEnumerable CreateGameplayKeys() => new KeyCounter[] - { - new KeyCounterKeyboard(Key.Z), - new KeyCounterKeyboard(Key.X), - new KeyCounterMouse(MouseButton.Left), - new KeyCounterMouse(MouseButton.Right) - }; - public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); public override SettingsSubsection CreateSettings() => new OsuSettings(); diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index 917322de44..083f11945c 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override Playfield CreatePlayfield() => new OsuPlayfield(); - public override PassThroughInputManager CreateKeyBindingInputManager() => new OsuInputManager(Ruleset?.RulesetInfo); + public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index ad3b25d088..1e3c0fbcf2 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -3,11 +3,11 @@ using System.ComponentModel; using osu.Framework.Input.Bindings; -using osu.Game.Input.Bindings; +using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Taiko { - public class TaikoInputManager : DatabasedKeyBindingInputManager + public class TaikoInputManager : RulesetInputManager { public TaikoInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 41b8ff78a9..f457732085 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,14 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Mods; using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; @@ -103,14 +101,6 @@ namespace osu.Game.Rulesets.Taiko public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; - public override IEnumerable CreateGameplayKeys() => new KeyCounter[] - { - new KeyCounterKeyboard(Key.D), - new KeyCounterKeyboard(Key.F), - new KeyCounterKeyboard(Key.J), - new KeyCounterKeyboard(Key.K) - }; - public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 4b1c3d7f16..1ecd699a8e 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); - public override PassThroughInputManager CreateKeyBindingInputManager() => new TaikoInputManager(Ruleset?.RulesetInfo); + public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); protected override Playfield CreatePlayfield() => new TaikoPlayfield { diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 2fb9a568f8..479f274efb 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; namespace osu.Game.Beatmaps { @@ -76,8 +75,6 @@ namespace osu.Game.Beatmaps public override string Description => "dummy"; - public override IEnumerable CreateGameplayKeys() => new List(); - public DummyRuleset(RulesetInfo rulesetInfo) : base(rulesetInfo) { diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index e5fa7117f3..32d958b462 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -5,7 +5,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Play; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; @@ -46,8 +45,6 @@ namespace osu.Game.Rulesets public abstract string Description { get; } - public abstract IEnumerable CreateGameplayKeys(); - public virtual SettingsSubsection CreateSettings() => null; /// diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 8512d4b5e1..1e294827ab 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI /// /// The key conversion input manager for this RulesetContainer. /// - protected readonly PassThroughInputManager KeyConversionInputManager; + public readonly PassThroughInputManager KeyBindingInputManager; /// /// Whether we are currently providing the local user a gameplay cursor. @@ -76,8 +76,10 @@ namespace osu.Game.Rulesets.UI internal RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; - KeyConversionInputManager = CreateKeyBindingInputManager(); - KeyConversionInputManager.RelativeSizeAxes = Axes.Both; + KeyBindingInputManager = CreateInputManager(); + if (!(KeyBindingInputManager is ICanAttachKeyCounter)) + throw new InvalidOperationException($"Rulesets should create input managers of type {nameof(ICanAttachKeyCounter)}"); + KeyBindingInputManager.RelativeSizeAxes = Axes.Both; } /// @@ -92,10 +94,10 @@ namespace osu.Game.Rulesets.UI public abstract ScoreProcessor CreateScoreProcessor(); /// - /// Creates a key conversion input manager. + /// Creates a key conversion input manager. An exception will be thrown if a valid is not returned. /// /// The input manager. - public virtual PassThroughInputManager CreateKeyBindingInputManager() => new PassThroughInputManager(); + public abstract PassThroughInputManager CreateInputManager(); protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); @@ -253,7 +255,7 @@ namespace osu.Game.Rulesets.UI InputManager.Add(content = new Container { RelativeSizeAxes = Axes.Both, - Children = new[] { KeyConversionInputManager } + Children = new[] { KeyBindingInputManager } }); AddInternal(InputManager); @@ -262,7 +264,7 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load() { - KeyConversionInputManager.Add(Playfield = CreatePlayfield()); + KeyBindingInputManager.Add(Playfield = CreatePlayfield()); loadObjects(); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs new file mode 100644 index 0000000000..6d22b2e91e --- /dev/null +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; +using osu.Game.Screens.Play; + +namespace osu.Game.Rulesets.UI +{ + public abstract class RulesetInputManager : DatabasedKeyBindingInputManager, ICanAttachKeyCounter + where T : struct + { + protected RulesetInputManager(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) : base(ruleset, variant, unique) + { + } + + public void Attach(KeyCounterCollection keyCounter) + { + var receptor = new ActionReceptor(keyCounter); + Add(receptor); + keyCounter.SetReceptor(receptor); + + keyCounter.AddRange(DefaultKeyBindings.Select(b => b.GetAction()).Distinct().Select(b => new KeyCounterAction(b))); + } + + public class ActionReceptor : KeyCounterCollection.Receptor, IKeyBindingHandler + { + public ActionReceptor(KeyCounterCollection target) + : base(target) + { + } + + public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action)); + + public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action)); + } + } + + public interface ICanAttachKeyCounter + { + void Attach(KeyCounterCollection keyCounter); + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index cf6bc03c60..ddcf031bd4 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play public virtual void BindRulesetContainer(RulesetContainer rulesetContainer) { - rulesetContainer.InputManager.Add(KeyCounter.GetReceptor()); + (rulesetContainer.KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(KeyCounter); replayLoaded = rulesetContainer.HasReplayLoaded; diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs new file mode 100644 index 0000000000..a6baeeafb6 --- /dev/null +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -0,0 +1,30 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Input.Bindings; + +namespace osu.Game.Screens.Play +{ + public class KeyCounterAction : KeyCounter, IKeyBindingHandler + where T : struct + { + public T Action { get; } + + public KeyCounterAction(T action) : base($"B{(int)(object)action + 1}") + { + Action = action; + } + + public bool OnPressed(T action) + { + if (action.Equals(Action)) IsLit = true; + return false; + } + + public bool OnReleased(T action) + { + if (action.Equals(Action)) IsLit = false; + return false; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 63c29a8f78..0f6c5984c4 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -117,27 +118,36 @@ namespace osu.Game.Screens.Play return receptor ?? (receptor = new Receptor(this)); } + public void SetReceptor(Receptor receptor) + { + if (this.receptor != null) + throw new InvalidOperationException("Cannot set a new receptor when one is already active"); + + this.receptor = receptor; + } + public class Receptor : Drawable { - private readonly KeyCounterCollection target; + protected readonly KeyCounterCollection Target; public Receptor(KeyCounterCollection target) { RelativeSizeAxes = Axes.Both; - this.target = target; + Depth = float.MinValue; + Target = target; } public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; public override bool HandleInput => true; - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => target.Children.Any(c => c.TriggerOnKeyDown(state, args)); + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyDown(state, args)); - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => target.Children.Any(c => c.TriggerOnKeyUp(state, args)); + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyUp(state, args)); - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => target.Children.Any(c => c.TriggerOnMouseDown(state, args)); + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseDown(state, args)); - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => target.Children.Any(c => c.TriggerOnMouseUp(state, args)); + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseUp(state, args)); } } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 00f1bd1b6b..3f399d69e6 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -76,8 +76,6 @@ namespace osu.Game.Screens.Play sampleRestart = audio.Sample.Get(@"Gameplay/restart"); - Ruleset rulesetInstance; - WorkingBeatmap working = Beatmap.Value; Beatmap beatmap; @@ -89,7 +87,7 @@ namespace osu.Game.Screens.Play throw new InvalidOperationException("Beatmap was not loaded"); ruleset = osu?.Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; - rulesetInstance = ruleset.CreateInstance(); + var rulesetInstance = ruleset.CreateInstance(); try { @@ -192,7 +190,6 @@ namespace osu.Game.Screens.Play scoreProcessor = RulesetContainer.CreateScoreProcessor(); - hudOverlay.KeyCounter.AddRange(rulesetInstance.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindRulesetContainer(RulesetContainer); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 07ab58bffc..e35bc44c43 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -128,6 +128,8 @@ + + From a63923a4971f133635a1a50d56c48705e1d5e05b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 12:50:48 +0900 Subject: [PATCH 098/180] Remove type check for now --- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 1e294827ab..50fcaa128c 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -77,8 +77,6 @@ namespace osu.Game.Rulesets.UI { Ruleset = ruleset; KeyBindingInputManager = CreateInputManager(); - if (!(KeyBindingInputManager is ICanAttachKeyCounter)) - throw new InvalidOperationException($"Rulesets should create input managers of type {nameof(ICanAttachKeyCounter)}"); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; } From e7c9aec1b18891f02fccd7437b07fca6b5eb92b8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 13:05:06 +0900 Subject: [PATCH 099/180] Ensure the sqlite connection is correctly closed before the game ends Hopefully fixes CI race conditions between consecutive tests. --- osu.Game/OsuGameBase.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a5600d1ef7..022b3e9fc3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -94,13 +94,15 @@ namespace osu.Game protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + private SQLiteConnection connection; + [BackgroundDependencyLoader] private void load() { dependencies.Cache(this); dependencies.Cache(LocalConfig); - SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); + connection = Host.Storage.GetDatabase(@"client"); connection.CreateTable(); @@ -237,6 +239,8 @@ namespace osu.Game LocalConfig.Save(); } + connection.Dispose(); + base.Dispose(isDisposing); } } From 7a5708ce9279c94116a4bee0f98fe60d9dc5392c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 15:35:16 +0900 Subject: [PATCH 100/180] Further support for null judgements. --- osu-framework | 2 +- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs | 4 ++-- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu-framework b/osu-framework index 825505e788..aba135ff83 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 825505e788c4f093b269c61b485d38d50cd68096 +Subproject commit aba135ff83feabd9ca2e8e8075b811b64a9006ad diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 06702e8141..9df1b41a8b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -58,10 +58,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables }; } - protected override TaikoJudgement CreateJudgement() => new TaikoJudgement(); + protected override TaikoJudgement CreateJudgement() => null; protected override void UpdateState(ArmedState state) { } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 8cfedc9599..3fba168216 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -106,6 +106,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether a hit was processed. protected bool UpdateJudgement(bool userTriggered) { + if (Judgement == null) + return false; + var partial = Judgement as IPartialJudgement; // Never re-process non-partial hits From 6a7e868a2e1f55cbf1ff4f7211d71d1f04289c40 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 15:36:01 +0900 Subject: [PATCH 101/180] Make taiko major bar line triangles show up again. Fixes #1081 --- .../Objects/Drawables/DrawableBarLineMajor.cs | 14 ++++++++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 28 ++++++++++++++----- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index c07be915d5..7a4cf1f1f7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -20,10 +20,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const float triangle_size = 20f; + private readonly Container triangleContainer; + public DrawableBarLineMajor(BarLine barLine) : base(barLine) { - Add(new Container + Add(triangleContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -53,5 +55,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Tracker.Alpha = 1f; } + + protected override void LoadComplete() + { + base.LoadComplete(); + + using (triangleContainer.BeginAbsoluteSequence(HitObject.StartTime)) + triangleContainer.FadeOut(150); + } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index eb9e41f771..678de7f713 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -45,6 +45,8 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Container topLevelHitContainer; + private readonly Container barlineContainer; + private readonly Container overlayBackgroundContainer; private readonly Container backgroundContainer; @@ -85,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.UI { new Container { - Name = "Masked elements", + Name = "Masked elements before hit objects", RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, Masking = true, @@ -103,13 +105,21 @@ namespace osu.Game.Rulesets.Taiko.UI Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit - }, - content = new Container - { - RelativeSizeAxes = Axes.Both, - }, + } } }, + barlineContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = HIT_TARGET_OFFSET } + }, + content = new Container + { + Name = "Hit objects", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = HIT_TARGET_OFFSET }, + Masking = true + }, kiaiExplosionContainer = new Container { Name = "Kiai hit explosions", @@ -198,6 +208,10 @@ namespace osu.Game.Rulesets.Taiko.UI base.Add(h); + var barline = h as DrawableBarLine; + if (barline != null) + barlineContainer.Add(barline.CreateProxy()); + // Swells should be moved at the very top of the playfield when they reach the hit target var swell = h as DrawableSwell; if (swell != null) @@ -239,4 +253,4 @@ namespace osu.Game.Rulesets.Taiko.UI hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit(); } } -} \ No newline at end of file +} From 5d13efa76d6f4bb566b6c6c4d01d077059ae10bf Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 16:14:44 +0900 Subject: [PATCH 102/180] Remove the concept of "queued hit objects", add a default speed adjustment. --- osu-framework | 2 +- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 52 +++++++++++----------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/osu-framework b/osu-framework index aba135ff83..92e1dc21c0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit aba135ff83feabd9ca2e8e8075b811b64a9006ad +Subproject commit 92e1dc21c069a6b65ee71060f2f37f3f4180fd20 diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index f8e090d613..b89f5e15c6 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -151,10 +151,6 @@ namespace osu.Game.Rulesets.UI /// public readonly BindableBool Reversed = new BindableBool(); - /// - /// Hit objects that are to be re-processed on the next update. - /// - private readonly List queuedHitObjects = new List(); private readonly Container speedAdjustments; private readonly Axes scrollingAxes; @@ -168,6 +164,9 @@ namespace osu.Game.Rulesets.UI this.scrollingAxes = scrollingAxes; AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); + + // Default speed adjustment + AddSpeedAdjustment(new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); } /// @@ -180,6 +179,21 @@ namespace osu.Game.Rulesets.UI speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.Reversed.BindTo(Reversed); speedAdjustments.Add(speedAdjustment); + + // We now need to re-sort the hit objects in the last speed adjustment prior to this one, to see if they need a new parent + var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s.ControlPoint.StartTime < speedAdjustment.ControlPoint.StartTime); + if (previousSpeedAdjustment == null) + return; + + foreach (DrawableHitObject h in previousSpeedAdjustment.Children) + { + var newSpeedAdjustment = adjustmentContainerFor(h); + if (newSpeedAdjustment == previousSpeedAdjustment) + continue; + + previousSpeedAdjustment.Remove(h); + newSpeedAdjustment.Add(h); + } } public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); @@ -194,30 +208,14 @@ namespace osu.Game.Rulesets.UI if (!(hitObject is IScrollingHitObject)) throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - queuedHitObjects.Add(hitObject); + var target = adjustmentContainerFor(hitObject); + if (target == null) + throw new InvalidOperationException($"A {nameof(SpeedAdjustmentContainer)} to container {hitObject.ToString()} could not be found."); + + target.Add(hitObject); } - public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)) || queuedHitObjects.Remove(hitObject); - - protected override void Update() - { - base.Update(); - - // Todo: At the moment this is going to re-process every single Update, however this will only be a null-op - // when there are no SpeedAdjustmentContainers available. This should probably error or something, but it's okay for now. - - for (int i = queuedHitObjects.Count - 1; i >= 0; i--) - { - var hitObject = queuedHitObjects[i]; - - var target = adjustmentContainerFor(hitObject); - if (target == null) - continue; - - target.Add(hitObject); - queuedHitObjects.RemoveAt(i); - } - } + public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); /// /// Finds the which provides the speed adjustment active at the start time @@ -237,4 +235,4 @@ namespace osu.Game.Rulesets.UI private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? speedAdjustments.LastOrDefault(); } } -} \ No newline at end of file +} From 9369c18d7772a0820fc0721d83444d105dd58860 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 16:18:04 +0900 Subject: [PATCH 103/180] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 92e1dc21c0..bce1e26732 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 92e1dc21c069a6b65ee71060f2f37f3f4180fd20 +Subproject commit bce1e26732360caf4acb716fde439de48805014e From 6e0d2182cbd2e196fc2fafe917eaf29252f62e38 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Mon, 21 Aug 2017 16:24:16 +0900 Subject: [PATCH 104/180] CI. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index b89f5e15c6..0a8469c928 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -210,7 +210,7 @@ namespace osu.Game.Rulesets.UI var target = adjustmentContainerFor(hitObject); if (target == null) - throw new InvalidOperationException($"A {nameof(SpeedAdjustmentContainer)} to container {hitObject.ToString()} could not be found."); + throw new InvalidOperationException($"A {nameof(SpeedAdjustmentContainer)} to container {hitObject} could not be found."); target.Add(hitObject); } From 877c69d5fea29641a81093972c74a873b92d568f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 17:43:26 +0900 Subject: [PATCH 105/180] Add local chat echo support --- osu.Game/Online/Chat/Channel.cs | 49 +++++++++- osu.Game/Online/Chat/LocalEchoMessage.cs | 12 +++ osu.Game/Online/Chat/Message.cs | 17 +++- osu.Game/Overlays/Chat/ChatLine.cs | 114 ++++++++++++++-------- osu.Game/Overlays/Chat/DrawableChannel.cs | 60 +++++++++--- osu.Game/Overlays/ChatOverlay.cs | 69 ++++++------- osu.Game/osu.Game.csproj | 1 + 7 files changed, 223 insertions(+), 99 deletions(-) create mode 100644 osu.Game/Online/Chat/LocalEchoMessage.cs diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 01685cc7dc..0c10ddde97 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; @@ -26,6 +27,8 @@ namespace osu.Game.Online.Chat public readonly SortedList Messages = new SortedList(Comparer.Default); + private readonly List pendingMessages = new List(); + public Bindable Joined = new Bindable(); public bool ReadOnly => Name != "#lazer"; @@ -38,12 +41,23 @@ namespace osu.Game.Online.Chat } public event Action> NewMessagesArrived; + public event Action PendingMessageResolved; + public event Action MessageRemoved; + + public void AddLocalEcho(LocalEchoMessage message) + { + pendingMessages.Add(message); + Messages.Add(message); + + NewMessagesArrived?.Invoke(new[] { message }); + } public void AddNewMessages(params Message[] messages) { messages = messages.Except(Messages).ToArray(); - Messages.AddRange(messages); + foreach (Message message in messages) + Messages.Add(message); purgeOldMessages(); @@ -52,11 +66,42 @@ namespace osu.Game.Online.Chat private void purgeOldMessages() { - int messageCount = Messages.Count; + // never purge local echos + int messageCount = Messages.Count - pendingMessages.Count; if (messageCount > MAX_HISTORY) Messages.RemoveRange(0, messageCount - MAX_HISTORY); } + /// + /// Replace or remove a message from the channel. + /// + /// The local echo message (client-side). + /// The response message, or null if the message became invalid. + public void ReplaceMessage(LocalEchoMessage echo, Message final) + { + if (!pendingMessages.Remove(echo)) + Trace.Fail("Attempted to remove echo that wasn't present"); + + Messages.Remove(echo); + + if (final == null) + { + MessageRemoved?.Invoke(echo); + return; + } + + if (Messages.Contains(final)) + { + // message already inserted, so let's throw away this update. + // we may want to handle this better in the future, but for the time being api requests are single-threaded so order is assumed. + MessageRemoved?.Invoke(echo); + return; + } + + Messages.Add(final); + PendingMessageResolved?.Invoke(echo, final); + } + public override string ToString() => Name; } } diff --git a/osu.Game/Online/Chat/LocalEchoMessage.cs b/osu.Game/Online/Chat/LocalEchoMessage.cs new file mode 100644 index 0000000000..079ec58686 --- /dev/null +++ b/osu.Game/Online/Chat/LocalEchoMessage.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Online.Chat +{ + public class LocalEchoMessage : Message + { + public LocalEchoMessage() : base(null) + { + } + } +} diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 4c7e099647..fc61b9f37a 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.Chat public class Message : IComparable, IEquatable { [JsonProperty(@"message_id")] - public readonly long Id; + public readonly long? Id; //todo: this should be inside sender. [JsonProperty(@"sender_id")] @@ -37,14 +37,23 @@ namespace osu.Game.Online.Chat { } - public Message(long id) + public Message(long? id) { Id = id; } - public int CompareTo(Message other) => Id.CompareTo(other.Id); + public int CompareTo(Message other) + { - public bool Equals(Message other) => Id == other?.Id; + if (!Id.HasValue) + return other.Id.HasValue ? 1 : Timestamp.CompareTo(other.Timestamp); + if (!other.Id.HasValue) + return -1; + + return Id.Value.CompareTo(other.Id.Value); + } + + public virtual bool Equals(Message other) => Id == other?.Id; public override int GetHashCode() => Id.GetHashCode(); } diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index fcebca6fe3..afc6589f57 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -2,26 +2,24 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; -using OpenTK; -using OpenTK.Graphics; -using osu.Framework.Graphics.Effects; -using osu.Framework.Extensions.Color4Extensions; -using osu.Framework.Allocation; using osu.Game.Users; -using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Chat { public class ChatLine : Container { - public readonly Message Message; - - private static readonly Color4[] username_colours = { + private static readonly Color4[] username_colours = + { OsuColour.FromHex("588c7e"), OsuColour.FromHex("b2a367"), OsuColour.FromHex("c98f65"), @@ -69,6 +67,8 @@ namespace osu.Game.Overlays.Chat private Color4 customUsernameColour; + private OsuSpriteText timestamp; + public ChatLine(Message message) { Message = message; @@ -79,6 +79,26 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = padding, Right = padding }; } + private Message message; + private OsuSpriteText username; + private OsuTextFlowContainer contentFlow; + + public Message Message + { + get { return message; } + set + { + if (message == value) return; + + message = value; + + if (!IsLoaded) + return; + + updateMessageContent(); + } + } + [BackgroundDependencyLoader(true)] private void load(OsuColour colours, UserProfileOverlay profile) { @@ -86,49 +106,54 @@ namespace osu.Game.Overlays.Chat loadProfile = u => profile?.ShowUser(u); } + private bool senderHasBackground => !string.IsNullOrEmpty(message.Sender.Colour); + protected override void LoadComplete() { base.LoadComplete(); - bool hasBackground = !string.IsNullOrEmpty(Message.Sender.Colour); - Drawable username = new OsuSpriteText + bool hasBackground = senderHasBackground; + + Drawable effectedUsername = username = new OsuSpriteText { Font = @"Exo2.0-BoldItalic", - Text = $@"{Message.Sender.Username}" + (hasBackground ? "" : ":"), - Colour = hasBackground ? customUsernameColour : username_colours[Message.UserId % username_colours.Length], + Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], TextSize = text_size, }; if (hasBackground) { // Background effect - username = username.WithEffect(new EdgeEffect + effectedUsername = new Container { + AutoSizeAxes = Axes.Both, + Masking = true, CornerRadius = 4, - Parameters = new EdgeEffectParameters - { - Radius = 1, - Colour = OsuColour.FromHex(Message.Sender.Colour), - Type = EdgeEffectType.Shadow, - } - }, d => - { - d.Padding = new MarginPadding { Left = 3, Right = 3, Bottom = 1, Top = -3 }; - d.Y = 3; - }) - // Drop shadow effect - .WithEffect(new EdgeEffect - { - CornerRadius = 4, - Parameters = new EdgeEffectParameters + EdgeEffect = new EdgeEffectParameters { Roundness = 1, Offset = new Vector2(0, 3), Radius = 3, Colour = Color4.Black.Opacity(0.3f), Type = EdgeEffectType.Shadow, + }, + // Drop shadow effect + Child = new Container + { + AutoSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 4, + EdgeEffect = new EdgeEffectParameters + { + Radius = 1, + Colour = OsuColour.FromHex(message.Sender.Colour), + Type = EdgeEffectType.Shadow, + }, + Padding = new MarginPadding { Left = 3, Right = 3, Bottom = 1, Top = -3 }, + Y = 3, + Child = username, } - }); + }; } Children = new Drawable[] @@ -138,23 +163,21 @@ namespace osu.Game.Overlays.Chat Size = new Vector2(message_padding, text_size), Children = new Drawable[] { - new OsuSpriteText + timestamp = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = @"Exo2.0-SemiBold", - Text = $@"{Message.Timestamp.LocalDateTime:HH:mm:ss}", FixedWidth = true, TextSize = text_size * 0.75f, - Alpha = 0.4f, }, new ClickableContainer { AutoSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, - Child = username, - Action = () => loadProfile(Message.Sender), + Child = effectedUsername, + Action = () => loadProfile(message.Sender), }, } }, @@ -165,18 +188,27 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = message_padding + padding }, Children = new Drawable[] { - new OsuTextFlowContainer(t => + contentFlow = new OsuTextFlowContainer(t => { t.TextSize = text_size; }) { - t.TextSize = text_size; - }) - { - Text = Message.Content, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, } } } }; + + updateMessageContent(); + FinishTransforms(true); + } + + private void updateMessageContent() + { + this.FadeTo(message is LocalEchoMessage ? 0.4f : 1.0f, 500, Easing.OutQuint); + timestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint); + + timestamp.Text = $@"{message.Timestamp.LocalDateTime:HH:mm:ss}"; + username.Text = $@"{message.Sender.Username}" + (senderHasBackground ? "" : ":"); + contentFlow.Text = message.Content; } } } diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 8a2fa95ed1..38a736993e 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,8 +16,19 @@ namespace osu.Game.Overlays.Chat { public class DrawableChannel : Container { + private class ChatLineContainer : FillFlowContainer + { + protected override int Compare(Drawable x, Drawable y) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; + + return xC.Message.CompareTo(yC.Message); + } + } + public readonly Channel Channel; - private readonly FillFlowContainer flow; + private readonly ChatLineContainer flow; private readonly ScrollContainer scroll; public DrawableChannel(Channel channel) @@ -32,20 +45,19 @@ namespace osu.Game.Overlays.Chat // Some chat lines have effects that slightly protrude to the bottom, // which we do not want to mask away, hence the padding. Padding = new MarginPadding { Bottom = 5 }, - Children = new Drawable[] + Child = flow = new ChatLineContainer { - flow = new FillFlowContainer - { - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = 20, Right = 20 } - } - } + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }, } }; - channel.NewMessagesArrived += newMessagesArrived; + Channel.NewMessagesArrived += newMessagesArrived; + Channel.MessageRemoved += messageRemoved; + Channel.PendingMessageResolved += pendingMessageResolved; } [BackgroundDependencyLoader] @@ -63,15 +75,19 @@ namespace osu.Game.Overlays.Chat protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); + Channel.NewMessagesArrived -= newMessagesArrived; + Channel.MessageRemoved -= messageRemoved; + Channel.PendingMessageResolved -= pendingMessageResolved; } private void newMessagesArrived(IEnumerable newMessages) { + // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY)); - //up to last Channel.MAX_HISTORY messages - flow.AddRange(displayMessages.Select(m => new ChatLine(m))); + foreach (Message m in displayMessages) + flow.Add(new ChatLine(m)); if (!IsLoaded) return; @@ -90,6 +106,24 @@ namespace osu.Game.Overlays.Chat } } + private void pendingMessageResolved(Message existing, Message updated) + { + var found = flow.Children.LastOrDefault(c => c.Message == existing); + if (found != null) + { + Trace.Assert(updated.Id.HasValue, "An updated message was returned with no ID."); + + flow.Remove(found); + found.Message = updated; + flow.Add(found); + } + } + + private void messageRemoved(Message removed) + { + flow.Children.FirstOrDefault(c => c.Message == removed)?.FadeColour(Color4.Red, 400).FadeOut(600).Expire(); + } + private void scrollToEnd() => ScheduleAfterChildren(() => scroll.ScrollToEnd()); } } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index e7a4c1c0ab..705772aec3 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -6,23 +6,23 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using OpenTK; +using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input; using osu.Framework.Threading; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Chat; -using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.UserInterface; -using OpenTK.Graphics; -using osu.Framework.Input; -using osu.Game.Configuration; -using osu.Game.Graphics; using osu.Game.Overlays.Chat; -using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { @@ -37,7 +37,7 @@ namespace osu.Game.Overlays private readonly LoadingAnimation loading; - private readonly FocusedTextBox inputTextBox; + private readonly FocusedTextBox textbox; private APIAccess api; @@ -130,7 +130,7 @@ namespace osu.Game.Overlays }, Children = new Drawable[] { - inputTextBox = new FocusedTextBox + textbox = new FocusedTextBox { RelativeSizeAxes = Axes.Both, Height = 1, @@ -175,7 +175,7 @@ namespace osu.Game.Overlays if (state == Visibility.Visible) { - inputTextBox.HoldFocus = false; + textbox.HoldFocus = false; if (1f - chatHeight.Value < channel_selection_min_height) { chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); @@ -186,7 +186,7 @@ namespace osu.Game.Overlays } else { - inputTextBox.HoldFocus = true; + textbox.HoldFocus = true; } }; } @@ -242,8 +242,8 @@ namespace osu.Game.Overlays protected override void OnFocus(InputState state) { - //this is necessary as inputTextBox is masked away and therefore can't get focus :( - GetContainingInputManager().ChangeFocus(inputTextBox); + //this is necessary as textbox is masked away and therefore can't get focus :( + GetContainingInputManager().ChangeFocus(textbox); base.OnFocus(state); } @@ -252,7 +252,7 @@ namespace osu.Game.Overlays this.MoveToY(0, transition_length, Easing.OutQuint); this.FadeIn(transition_length, Easing.OutQuint); - inputTextBox.HoldFocus = true; + textbox.HoldFocus = true; base.PopIn(); } @@ -261,7 +261,7 @@ namespace osu.Game.Overlays this.MoveToY(Height, transition_length, Easing.InSine); this.FadeOut(transition_length, Easing.InSine); - inputTextBox.HoldFocus = false; + textbox.HoldFocus = false; base.PopOut(); } @@ -336,7 +336,7 @@ namespace osu.Game.Overlays currentChannel = value; - inputTextBox.Current.Disabled = currentChannel.ReadOnly; + textbox.Current.Disabled = currentChannel.ReadOnly; channelTabs.Current.Value = value; var loaded = loadedChannels.Find(d => d.Channel == value); @@ -437,51 +437,42 @@ namespace osu.Game.Overlays { var postText = textbox.Text; + textbox.Text = string.Empty; + if (string.IsNullOrEmpty(postText)) return; + var target = currentChannel; + + if (target == null) return; + if (!api.IsLoggedIn) { - currentChannel?.AddNewMessages(new ErrorMessage("Please login to participate in chat!")); - textbox.Text = string.Empty; + target.AddNewMessages(new ErrorMessage("Please login to participate in chat!")); return; } - if (currentChannel == null) return; - if (postText[0] == '/') { // TODO: handle commands - currentChannel.AddNewMessages(new ErrorMessage("Chat commands are not supported yet!")); - textbox.Text = string.Empty; + target.AddNewMessages(new ErrorMessage("Chat commands are not supported yet!")); return; } - var message = new Message + var message = new LocalEchoMessage { Sender = api.LocalUser.Value, Timestamp = DateTimeOffset.Now, - TargetType = TargetType.Channel, //TODO: read this from currentChannel - TargetId = currentChannel.Id, + TargetType = TargetType.Channel, //TODO: read this from channel + TargetId = target.Id, Content = postText }; - textbox.ReadOnly = true; var req = new PostMessageRequest(message); - req.Failure += e => - { - textbox.FlashColour(Color4.Red, 1000); - textbox.ReadOnly = false; - }; - - req.Success += m => - { - currentChannel.AddNewMessages(m); - - textbox.ReadOnly = false; - textbox.Text = string.Empty; - }; + target.AddLocalEcho(message); + req.Failure += e => target.ReplaceMessage(message, null); + req.Success += m => target.ReplaceMessage(message, m); api.Queue(req); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 07ab58bffc..655bc08248 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -101,6 +101,7 @@ + From 9ba2258f80236152ffcad17f29531cc8e7c3c93b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 17:44:39 +0900 Subject: [PATCH 106/180] Add spaces for smoogipoo --- osu.Game/Overlays/ChatOverlay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 705772aec3..6dd5425fd1 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -414,6 +414,7 @@ namespace osu.Game.Overlays if (fetchReq != null) return; fetchReq = new GetMessagesRequest(careChannels, lastMessageId); + fetchReq.Success += delegate (List messages) { foreach (var group in messages.Where(m => m.TargetType == TargetType.Channel).GroupBy(m => m.TargetId)) @@ -424,6 +425,7 @@ namespace osu.Game.Overlays Debug.Write("success!"); fetchReq = null; }; + fetchReq.Failure += delegate { Debug.Write("failure!"); From 1d0b89d592bf5e5141047fd8313175d35888228a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 18:51:14 +0900 Subject: [PATCH 107/180] Restore usage of AddRange --- osu.Game/Online/Chat/Channel.cs | 3 +-- osu.Game/Overlays/Chat/DrawableChannel.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 0c10ddde97..2878856159 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -56,8 +56,7 @@ namespace osu.Game.Online.Chat { messages = messages.Except(Messages).ToArray(); - foreach (Message message in messages) - Messages.Add(message); + Messages.AddRange(messages); purgeOldMessages(); diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 38a736993e..840edaece2 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -86,8 +86,7 @@ namespace osu.Game.Overlays.Chat // Add up to last Channel.MAX_HISTORY messages var displayMessages = newMessages.Skip(Math.Max(0, newMessages.Count() - Channel.MAX_HISTORY)); - foreach (Message m in displayMessages) - flow.Add(new ChatLine(m)); + flow.AddRange(displayMessages.Select(m => new ChatLine(m))); if (!IsLoaded) return; From 7d1c270126a60b075504ca4ae4769e03fc94cee3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 23:34:08 +0900 Subject: [PATCH 108/180] Review fixes --- osu.Game/Online/Chat/Channel.cs | 2 +- osu.Game/Online/Chat/Message.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 2878856159..81d488353a 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -79,7 +79,7 @@ namespace osu.Game.Online.Chat public void ReplaceMessage(LocalEchoMessage echo, Message final) { if (!pendingMessages.Remove(echo)) - Trace.Fail("Attempted to remove echo that wasn't present"); + throw new InvalidOperationException("Attempted to remove echo that wasn't present"); Messages.Remove(echo); diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index fc61b9f37a..509861868a 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -44,7 +44,6 @@ namespace osu.Game.Online.Chat public int CompareTo(Message other) { - if (!Id.HasValue) return other.Id.HasValue ? 1 : Timestamp.CompareTo(other.Timestamp); if (!other.Id.HasValue) From a9fe1d94f7646a95dec42f680f54199b7de3665a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 23:41:51 +0900 Subject: [PATCH 109/180] Remove unnecessary using --- osu.Game/Online/Chat/Channel.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 81d488353a..bec4aadb18 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using Newtonsoft.Json; using osu.Framework.Configuration; From 5c489eb3f059d08f808e88323877a19bc50909ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Aug 2017 23:46:37 +0900 Subject: [PATCH 110/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index bce1e26732..f1527e5456 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit bce1e26732360caf4acb716fde439de48805014e +Subproject commit f1527e5456cd228ddfb68cf6d56eb5d28dc360bf From 31bb1ebe0e3058fe1f174fc4bea3aeaa2d1f7400 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 12:42:35 +0900 Subject: [PATCH 111/180] Add comment and index on column --- osu.Game/Beatmaps/BeatmapInfo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 432da57a5c..ebf77bf9df 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -52,6 +52,10 @@ namespace osu.Game.Beatmaps [JsonProperty("file_sha2")] public string Hash { get; set; } + /// + /// MD5 is kept for legacy support (matching against replays, osu-web-10 etc.). + /// + [Indexed] [JsonProperty("file_md5")] public string MD5Hash { get; set; } From 964982e2e61885db1ab701e9b6eb242e4d2a25d5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 13:00:35 +0900 Subject: [PATCH 112/180] Remove now unneeded ApplyBeatmap. --- osu.Game/Rulesets/UI/RulesetContainer.cs | 7 ------- .../Rulesets/UI/ScrollingRulesetContainer.cs | 19 ++++++++----------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 50fcaa128c..5b19200f2d 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -173,8 +173,6 @@ namespace osu.Game.Rulesets.UI // Post-process the beatmap processor.PostProcess(Beatmap); - ApplyBeatmap(); - // Add mods, should always be the last thing applied to give full control to mods applyMods(Mods); } @@ -192,11 +190,6 @@ namespace osu.Game.Rulesets.UI mod.ApplyToRulesetContainer(this); } - /// - /// Called when the beatmap of this hit renderer has been set. Used to apply any default values from the beatmap. - /// - protected virtual void ApplyBeatmap() { } - /// /// Creates a processor to perform post-processing operations /// on HitObjects in converted Beatmaps. diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs index 64e865473d..ff156f788c 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs @@ -39,17 +39,6 @@ namespace osu.Game.Rulesets.UI [BackgroundDependencyLoader] private void load() - { - DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield)); - } - - private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) - { - playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); - playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); - } - - protected override void ApplyBeatmap() { // Calculate default multiplier control points var lastTimingPoint = new TimingControlPoint(); @@ -95,6 +84,14 @@ namespace osu.Game.Rulesets.UI // If we have no control points, add a default one if (DefaultControlPoints.Count == 0) DefaultControlPoints.Add(new MultiplierControlPoint()); + + DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield)); + } + + private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) + { + playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); + playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); } /// From 4eec59f669684fcb32758e95b3fc5a6521a58fca Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 13:01:51 +0900 Subject: [PATCH 113/180] Only set the number of availableColumns once, at ManiaRulesetContainer level. # Conflicts: # osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs # osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs # osu.Game/Rulesets/UI/RulesetContainer.cs --- .../Beatmaps/ManiaBeatmapConverter.cs | 14 ++++++++++--- .../Beatmaps/Patterns/PatternGenerator.cs | 4 +--- .../UI/ManiaRulesetContainer.cs | 20 +++++++++---------- osu.Game/Rulesets/UI/RulesetContainer.cs | 19 +++++++++++++----- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index b55b9fdb37..e5a3c7849e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -28,12 +28,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps private Pattern lastPattern = new Pattern(); private FastRandom random; private Beatmap beatmap; - private bool isForCurrentRuleset; - protected override Beatmap ConvertBeatmap(Beatmap original, bool isForCurrentRuleset) + private readonly int availableColumns; + private readonly bool isForCurrentRuleset; + + public ManiaBeatmapConverter(bool isForCurrentRuleset, int availableColumns) { this.isForCurrentRuleset = isForCurrentRuleset; + this.availableColumns = availableColumns; + } + protected override Beatmap ConvertBeatmap(Beatmap original) + { beatmap = original; BeatmapDifficulty difficulty = original.BeatmapInfo.Difficulty; @@ -89,7 +95,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The hit objects generated. private IEnumerable generateSpecific(HitObject original) { - var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern); + var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern) { AvailableColumns = availableColumns }; Pattern newPattern = generator.Generate(); lastPattern = newPattern; @@ -128,6 +134,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (conversion == null) return null; + conversion.AvailableColumns = availableColumns; + Pattern newPattern = conversion.Generate(); lastPattern = newPattern; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index dda4d07182..6b85a51402 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// The number of columns available to create the pattern. /// - protected readonly int AvailableColumns; + public int AvailableColumns; /// /// The last pattern. @@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns PreviousPattern = previousPattern; HitObject = hitObject; Beatmap = beatmap; - - AvailableColumns = (int)Math.Round(beatmap.BeatmapInfo.Difficulty.CircleSize); } /// diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 9584dc34b8..58ce05b165 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -33,9 +33,10 @@ namespace osu.Game.Rulesets.Mania.UI public class ManiaRulesetContainer : ScrollingRulesetContainer { /// - /// Preferred column count. This will only have an effect during the initialization of the play field. + /// The number of columns which the should display, and which + /// the beatmap converter will attempt to convert beatmaps to use. /// - public int PreferredColumns; + private int availableColumns; public IEnumerable BarLines; @@ -76,14 +77,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected override void ApplyBeatmap() - { - base.ApplyBeatmap(); - - PreferredColumns = (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize)); - } - - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(PreferredColumns) + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(availableColumns) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -95,7 +89,11 @@ namespace osu.Game.Rulesets.Mania.UI public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo); - protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() + { + availableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize)); + return new ManiaBeatmapConverter(IsForCurrentRuleset, availableColumns); + } protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 5b19200f2d..c7240448b9 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -139,16 +139,25 @@ namespace osu.Game.Rulesets.UI protected IEnumerable Mods; /// + /// The this was created with. + /// + protected readonly WorkingBeatmap WorkingBeatmap; + + /// + /// Whether to assume the beatmap passed into this is for the current ruleset. /// Creates a hit renderer for a beatmap. /// /// The ruleset being repesented. - /// The beatmap to create the hit renderer for. + /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. internal RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset) + internal RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset) + : base(ruleset) { - Debug.Assert(beatmap != null, "RulesetContainer initialized with a null beatmap."); + Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap."); - Mods = beatmap.Mods.Value; + WorkingBeatmap = workingBeatmap; + Mods = workingBeatmap.Mods.Value; RelativeSizeAxes = Axes.Both; @@ -156,11 +165,11 @@ namespace osu.Game.Rulesets.UI BeatmapProcessor processor = CreateBeatmapProcessor(); // Check if the beatmap can be converted - if (!converter.CanConvert(beatmap.Beatmap)) + if (!converter.CanConvert(workingBeatmap.Beatmap)) throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); // Convert the beatmap - Beatmap = converter.Convert(beatmap.Beatmap, isForCurrentRuleset); + Beatmap = converter.Convert(workingBeatmap.Beatmap, isForCurrentRuleset); // Apply difficulty adjustments from mods before using Difficulty. foreach (var mod in Mods.OfType()) From 88151eff3f2a49b0882b833392935656357c4131 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 13:34:58 +0900 Subject: [PATCH 114/180] Fix dofficulty calculators not working and make mania set the correct key count for non-mania specific maps. --- .../ManiaDifficultyCalculator.cs | 5 +++-- .../UI/ManiaRulesetContainer.cs | 16 +++++++++++++++- .../TaikoDifficultyCalculator.cs | 4 ++-- osu.Game/Beatmaps/DifficultyCalculator.cs | 6 +++++- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index aaba4d94f0..1f01750f44 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using System.Collections.Generic; +using System; namespace osu.Game.Rulesets.Mania { @@ -21,6 +22,6 @@ namespace osu.Game.Rulesets.Mania return 0; } - protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.Difficulty.CircleSize))); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 58ce05b165..6502b77cac 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -91,7 +91,21 @@ namespace osu.Game.Rulesets.Mania.UI protected override BeatmapConverter CreateBeatmapConverter() { - availableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize)); + if (IsForCurrentRuleset) + availableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize)); + else + { + float percentSliderOrSpinner = WorkingBeatmap.Beatmap.HitObjects.Count(h => h is IHasEndTime) / WorkingBeatmap.Beatmap.HitObjects.Count; + if (percentSliderOrSpinner < 0.2) + availableColumns = 7; + else if (percentSliderOrSpinner < 0.3 || Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize) >= 5) + availableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) > 5 ? 7 : 6; + else if (percentSliderOrSpinner > 0.6) + availableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) > 4 ? 5 : 4; + else + availableColumns = Math.Max(4, Math.Min((int)Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.OverallDifficulty) + 1, 7)); + } + return new ManiaBeatmapConverter(IsForCurrentRuleset, availableColumns); } diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index 33e9510f1c..35f849c704 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -135,6 +135,6 @@ namespace osu.Game.Rulesets.Taiko return difficulty; } - protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(true); } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index 474d38aa1b..5071e2c1b6 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -30,11 +30,15 @@ namespace osu.Game.Beatmaps public abstract class DifficultyCalculator : DifficultyCalculator where T : HitObject { + protected readonly Beatmap Beatmap; + protected List Objects; protected DifficultyCalculator(Beatmap beatmap) { - Objects = CreateBeatmapConverter().Convert(beatmap, true).HitObjects; + Beatmap = beatmap; + + Objects = CreateBeatmapConverter().Convert(beatmap).HitObjects; foreach (var h in Objects) h.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.Difficulty); diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index c7240448b9..1d5b27a7fb 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -169,7 +169,7 @@ namespace osu.Game.Rulesets.UI throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); // Convert the beatmap - Beatmap = converter.Convert(workingBeatmap.Beatmap, isForCurrentRuleset); + Beatmap = converter.Convert(workingBeatmap.Beatmap); // Apply difficulty adjustments from mods before using Difficulty. foreach (var mod in Mods.OfType()) From cd3c825bd22231ac520ac900d5fc14c05bb318b2 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 14:04:14 +0900 Subject: [PATCH 115/180] Fix mania playfield not working. --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 + osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index b836b54fa8..0c9351cad2 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -125,6 +125,7 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < columnCount; i++) { var c = new Column(); + c.Reversed.BindTo(Reversed); c.VisibleTimeRange.BindTo(VisibleTimeRange); columns.Add(c); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 6502b77cac..aea2d26791 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -74,6 +74,8 @@ namespace osu.Game.Rulesets.Mania.UI [BackgroundDependencyLoader] private void load() { + Playfield.Reversed.Value = true; + BarLines.ForEach(Playfield.Add); } @@ -81,8 +83,6 @@ namespace osu.Game.Rulesets.Mania.UI { Anchor = Anchor.Centre, Origin = Anchor.Centre, - // Invert by default for now (should be moved to config/skin later) - Scale = new Vector2(1, -1) }; public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); From 9a7c9e9af0107e3af439e422c7fcdd59f9b67819 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 14:17:57 +0900 Subject: [PATCH 116/180] Disable reversing for now - this needs to be re-implemented in a later PR. --- osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index aea2d26791..9b4d3adb86 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -74,8 +74,6 @@ namespace osu.Game.Rulesets.Mania.UI [BackgroundDependencyLoader] private void load() { - Playfield.Reversed.Value = true; - BarLines.ForEach(Playfield.Add); } From 68c7226d124bb9292dd9fd3364f502460031b5a8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 14:18:17 +0900 Subject: [PATCH 117/180] Fix cherry pick issues. --- osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 7 +++++-- osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs | 2 +- osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs | 8 +++----- osu.Game/Rulesets/UI/RulesetContainer.cs | 7 ++++++- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index e5a3c7849e..9b88a8c96c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); random = new FastRandom(seed); - return base.ConvertBeatmap(original, isForCurrentRuleset); + return base.ConvertBeatmap(original); } protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 869d54dded..40147f7c24 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -43,15 +43,18 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; - protected override Beatmap ConvertBeatmap(Beatmap original, bool isForCurrentRuleset) + public TaikoBeatmapConverter(bool isForCurrentRuleset) { this.isForCurrentRuleset = isForCurrentRuleset; + } + protected override Beatmap ConvertBeatmap(Beatmap original) + { // Rewrite the beatmap info to add the slider velocity multiplier BeatmapInfo info = original.BeatmapInfo.DeepClone(); info.Difficulty.SliderMultiplier *= legacy_velocity_multiplier; - Beatmap converted = base.ConvertBeatmap(original, isForCurrentRuleset); + Beatmap converted = base.ConvertBeatmap(original); // Post processing step to transform hit objects with the same start time into strong hits converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x => diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 1ecd699a8e..96e5df12cd 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); - protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(IsForCurrentRuleset); public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo); diff --git a/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs b/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs index aafa576d4b..e79d9eee4b 100644 --- a/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs @@ -26,21 +26,19 @@ namespace osu.Game.Rulesets.Beatmaps /// Converts a Beatmap using this Beatmap Converter. /// /// The un-converted Beatmap. - /// Whether to assume the beatmap is for the current ruleset. /// The converted Beatmap. - public Beatmap Convert(Beatmap original, bool isForCurrentRuleset) + public Beatmap Convert(Beatmap original) { // We always operate on a clone of the original beatmap, to not modify it game-wide - return ConvertBeatmap(new Beatmap(original), isForCurrentRuleset); + return ConvertBeatmap(new Beatmap(original)); } /// /// Performs the conversion of a Beatmap using this Beatmap Converter. /// /// The un-converted Beatmap. - /// Whether to assume the beatmap is for the current ruleset. /// The converted Beatmap. - protected virtual Beatmap ConvertBeatmap(Beatmap original, bool isForCurrentRuleset) + protected virtual Beatmap ConvertBeatmap(Beatmap original) { return new Beatmap { diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 1d5b27a7fb..2f1cb915f3 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -143,6 +143,11 @@ namespace osu.Game.Rulesets.UI /// protected readonly WorkingBeatmap WorkingBeatmap; + /// + /// Whether the specified beatmap is assumed to be specific to the current ruleset. + /// + protected readonly bool IsForCurrentRuleset; + /// /// Whether to assume the beatmap passed into this is for the current ruleset. /// Creates a hit renderer for a beatmap. @@ -150,13 +155,13 @@ namespace osu.Game.Rulesets.UI /// The ruleset being repesented. /// The beatmap to create the hit renderer for. /// Whether to assume the beatmap is for the current ruleset. - internal RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset) internal RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset) : base(ruleset) { Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap."); WorkingBeatmap = workingBeatmap; + IsForCurrentRuleset = isForCurrentRuleset; Mods = workingBeatmap.Mods.Value; RelativeSizeAxes = Axes.Both; From 909cae5861da45943ec55b5d70d1bd81a8ab6915 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 14:21:28 +0900 Subject: [PATCH 118/180] CI fixes. --- osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs | 1 - osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs | 2 +- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 6b85a51402..6ab9c86b9f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 9b4d3adb86..0e750a348e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Mania.UI availableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize)); else { - float percentSliderOrSpinner = WorkingBeatmap.Beatmap.HitObjects.Count(h => h is IHasEndTime) / WorkingBeatmap.Beatmap.HitObjects.Count; + float percentSliderOrSpinner = (float)WorkingBeatmap.Beatmap.HitObjects.Count(h => h is IHasEndTime) / WorkingBeatmap.Beatmap.HitObjects.Count; if (percentSliderOrSpinner < 0.2) availableColumns = 7; else if (percentSliderOrSpinner < 0.3 || Math.Round(WorkingBeatmap.BeatmapInfo.Difficulty.CircleSize) >= 5) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 40147f7c24..2bf058fc2b 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps /// private const float taiko_base_distance = 100; - private bool isForCurrentRuleset; + private readonly bool isForCurrentRuleset; protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; From ff8ad30127b78091a63dab2cfc1c2597e6af9394 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 14:42:49 +0900 Subject: [PATCH 119/180] Add support for binding mousewheel actions --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index a3361743a1..eb7d528897 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -172,6 +172,21 @@ namespace osu.Game.Overlays.KeyBinding return base.OnMouseUp(state, args); } + protected override bool OnWheel(InputState state) + { + if (HasFocus) + { + if (bindTarget.IsHovered) + { + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + finalise(); + return true; + } + } + + return base.OnWheel(state); + } + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (!HasFocus) From 18645fcf297325daa0391619775a4becbb538f4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 14:44:13 +0900 Subject: [PATCH 120/180] Update volume control logic to use key bindings Fixes them not working at all, too. --- .../UserInterface/Volume/VolumeControl.cs | 22 ++++++++---- .../Volume/VolumeControlReceptor.cs | 28 ++++----------- .../UserInterface/Volume/VolumeMeter.cs | 34 ++++++++++++++++--- .../Bindings/GlobalKeyBindingInputManager.cs | 9 ++++- osu.Game/OsuGame.cs | 3 +- 5 files changed, 60 insertions(+), 36 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index cd77fb9f5b..4c108e793a 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -3,11 +3,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; using osu.Framework.Threading; using OpenTK; using osu.Framework.Audio; using osu.Framework.Allocation; +using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface.Volume { @@ -64,15 +64,25 @@ namespace osu.Game.Graphics.UserInterface.Volume volumeMeterMusic.Bindable.ValueChanged -= volumeChanged; } - public void Adjust(InputState state) + public bool Adjust(GlobalAction action) { - if (State == Visibility.Hidden) + switch (action) { - Show(); - return; + case GlobalAction.DecreaseVolume: + if (State == Visibility.Hidden) + Show(); + else + volumeMeterMaster.Decrease(); + return true; + case GlobalAction.IncreaseVolume: + if (State == Visibility.Hidden) + Show(); + else + volumeMeterMaster.Increase(); + return true; } - volumeMeterMaster.TriggerOnWheel(state); + return false; } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs index c155871f33..c222fecb5d 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs @@ -3,32 +3,16 @@ using System; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; -using OpenTK.Input; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface.Volume { - internal class VolumeControlReceptor : Container + internal class VolumeControlReceptor : Container, IKeyBindingHandler { - public Action ActionRequested; + public Func ActionRequested; - protected override bool OnWheel(InputState state) - { - ActionRequested?.Invoke(state); - return true; - } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - switch (args.Key) - { - case Key.Up: - case Key.Down: - ActionRequested?.Invoke(state); - return true; - } - - return base.OnKeyDown(state, args); - } + public bool OnPressed(GlobalAction action) => ActionRequested?.Invoke(action) ?? false; + public bool OnReleased(GlobalAction action) => false; } } diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index 41fa60bec2..81c4fa9bae 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -4,15 +4,16 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Input; using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface.Volume { - internal class VolumeMeter : Container + internal class VolumeMeter : Container, IKeyBindingHandler { private readonly Box meterFill; public BindableDouble Bindable { get; } = new BindableDouble(); @@ -76,12 +77,35 @@ namespace osu.Game.Graphics.UserInterface.Volume } } - protected override bool OnWheel(InputState state) + public void Increase() { - Volume += 0.05f * state.Mouse.WheelDelta; - return true; + Volume += 0.05f; + } + + public void Decrease() + { + Volume -= 0.05f; } private void updateFill() => meterFill.ScaleTo(new Vector2(1, (float)Volume), 300, Easing.OutQuint); + + public bool OnPressed(GlobalAction action) + { + if (!IsHovered) return false; + + switch (action) + { + case GlobalAction.DecreaseVolume: + Decrease(); + return true; + case GlobalAction.IncreaseVolume: + Increase(); + return true; + } + + return false; + } + + public bool OnReleased(GlobalAction action) => false; } } \ No newline at end of file diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs index 5ea66fa600..759396e195 100644 --- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs @@ -26,7 +26,10 @@ namespace osu.Game.Input.Bindings new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), - new KeyBinding(new[] { InputKey.Control, InputKey.D }, GlobalAction.ToggleDirect), + new KeyBinding(new[] { InputKey.Up }, GlobalAction.IncreaseVolume), + new KeyBinding(new[] { InputKey.MouseWheelUp }, GlobalAction.IncreaseVolume), + new KeyBinding(new[] { InputKey.Down }, GlobalAction.DecreaseVolume), + new KeyBinding(new[] { InputKey.MouseWheelDown }, GlobalAction.DecreaseVolume), }; protected override IEnumerable KeyBindingInputQueue => @@ -47,5 +50,9 @@ namespace osu.Game.Input.Bindings ToggleSettings, [Description("Toggle osu!direct")] ToggleDirect, + [Description("Increase Volume")] + IncreaseVolume, + [Description("Decrease Volume")] + DecreaseVolume, } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e3525e423c..6e340a7f1d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -8,7 +8,6 @@ using osu.Game.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays; -using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Graphics.UserInterface.Volume; using osu.Framework.Allocation; @@ -160,7 +159,7 @@ namespace osu.Game new VolumeControlReceptor { RelativeSizeAxes = Axes.Both, - ActionRequested = delegate(InputState state) { volume.Adjust(state); } + ActionRequested = action => volume.Adjust(action) }, mainContent = new Container { From 09dd0cabd64b6084aa0d40e64e119993c6844289 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 15:58:47 +0900 Subject: [PATCH 121/180] Move beatmap/ruleset change restrictions to OsuGame Allows test cases to more freely exist --- osu.Game/OsuGame.cs | 7 +++++++ osu.Game/Screens/OsuScreen.cs | 13 ------------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index e3525e423c..68b5aa1cc9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -359,6 +359,13 @@ namespace osu.Game { base.UpdateAfterChildren(); + // we only want to apply these restrictions when we are inside a screen stack. + // the use case for not applying is in visual/unit tests. + bool applyRestrictions = currentScreen?.AllowBeatmapRulesetChange ?? false; + + Ruleset.Disabled = applyRestrictions; + Beatmap.Disabled = applyRestrictions; + mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; Cursor.State = currentScreen?.HasLocalCursorDisplayed == false ? Visibility.Visible : Visibility.Hidden; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 6e79d2b427..ae10d8828b 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -69,19 +69,6 @@ namespace osu.Game.Screens sampleExit = audio.Sample.Get(@"UI/melodic-1"); } - protected override void Update() - { - if (!IsCurrentScreen) return; - - if (ParentScreen != null) - { - // we only want to apply these restrictions when we are inside a screen stack. - // the use case for not applying is in visual/unit tests. - Ruleset.Disabled = !AllowBeatmapRulesetChange; - Beatmap.Disabled = !AllowBeatmapRulesetChange; - } - } - protected override void OnResuming(Screen last) { base.OnResuming(last); From 5fcd94880d19f36fba5566f03d3bd0aed6359a36 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 15:58:21 +0900 Subject: [PATCH 122/180] Fix incorrect inequality with multiple speed adjustments at the same start time. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 0a8469c928..9745e5d098 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -181,7 +181,7 @@ namespace osu.Game.Rulesets.UI speedAdjustments.Add(speedAdjustment); // We now need to re-sort the hit objects in the last speed adjustment prior to this one, to see if they need a new parent - var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s.ControlPoint.StartTime < speedAdjustment.ControlPoint.StartTime); + var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s.ControlPoint.StartTime <= speedAdjustment.ControlPoint.StartTime); if (previousSpeedAdjustment == null) return; From b7b8d8b76461b29c9cab011c94460fdbb1e5c29e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 15:59:38 +0900 Subject: [PATCH 123/180] Let's not construct scrolling containers in load() for now This isn't utilized at the moment, and we should be avoiding this here in the first place. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 5d6c03b9de..0ca6fc84c2 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -51,11 +51,7 @@ namespace osu.Game.Rulesets.Timing { ControlPoint = controlPoint; RelativeSizeAxes = Axes.Both; - } - [BackgroundDependencyLoader] - private void load() - { scrollingContainer = CreateScrollingContainer(); scrollingContainer.ScrollingAxes = ScrollingAxes; From 6f662d721cb47e33dafcd3c9a8b44e9914b9da1f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:00:26 +0900 Subject: [PATCH 124/180] Fix possible CollectionModifiedException while adding new SpeedAdjustmentContainers --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 9745e5d098..2678df7d44 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -185,14 +185,18 @@ namespace osu.Game.Rulesets.UI if (previousSpeedAdjustment == null) return; - foreach (DrawableHitObject h in previousSpeedAdjustment.Children) + for (int i = 0; i < previousSpeedAdjustment.Children.Count; i++) { - var newSpeedAdjustment = adjustmentContainerFor(h); + DrawableHitObject hitObject = previousSpeedAdjustment[i]; + + var newSpeedAdjustment = adjustmentContainerFor(hitObject); if (newSpeedAdjustment == previousSpeedAdjustment) continue; - previousSpeedAdjustment.Remove(h); - newSpeedAdjustment.Add(h); + previousSpeedAdjustment.Remove(hitObject); + newSpeedAdjustment.Add(hitObject); + + i--; } } From 4fc77be62498ae4ae2d998cf38cc8b991a4d11b0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:00:59 +0900 Subject: [PATCH 125/180] Fix incorrect sorting of hit objects into SpeedAdjustmentContainers --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 2678df7d44..09a8e50809 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -228,7 +228,7 @@ namespace osu.Game.Rulesets.UI /// /// The hit object to find the active for. /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.FirstOrDefault(c => c.CanContain(hitObject)) ?? speedAdjustments.LastOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.LastOrDefault(c => c.CanContain(hitObject)) ?? speedAdjustments.FirstOrDefault(); /// /// Finds the which provides the speed adjustment active at a time. @@ -236,7 +236,7 @@ namespace osu.Game.Rulesets.UI /// /// The time to find the active at. /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? speedAdjustments.LastOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.LastOrDefault(c => c.CanContain(time)) ?? speedAdjustments.FirstOrDefault(); } } } From c3cfad4eb5a009d650a3603093a3afc0b3799ff6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:01:19 +0900 Subject: [PATCH 126/180] Add RemoveSpeedAdjustment --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 09a8e50809..aea224ab9e 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -200,6 +200,25 @@ namespace osu.Game.Rulesets.UI } } + /// + /// Removes a from this container, re-sorting all hit objects + /// which it contained into new s. + /// + /// The to remove. + public void RemoveSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) + { + if (!speedAdjustments.Remove(speedAdjustment)) + return; + + while (speedAdjustment.Count > 0) + { + DrawableHitObject hitObject = speedAdjustment[0]; + + speedAdjustment.Remove(hitObject); + Add(hitObject); + } + } + public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); /// From d20ea97e7f8222296b99a21528d66316132cf191 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:05:12 +0900 Subject: [PATCH 127/180] Add NUnit test for ScrollingHitObjectContainer Tests ordering of SpeedAdjustmentContainers and DrawableHitObjects added to the ScrollingHitObjectContainer. --- .../Visual/TestCaseScrollingPlayfield.cs | 67 ++++++++++++++++++- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 5 +- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index e9c29d36c2..2d49b2d0f9 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -3,19 +3,23 @@ using System; using System.Collections.Generic; +using NUnit.Framework; using OpenTK; using osu.Desktop.Tests.Beatmaps; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; namespace osu.Desktop.Tests.Visual @@ -23,6 +27,7 @@ namespace osu.Desktop.Tests.Visual /// /// The most minimal implementation of a playfield with scrolling hit objects. /// + [TestFixture] public class TestCaseScrollingPlayfield : OsuTestCase { public TestCaseScrollingPlayfield() @@ -64,6 +69,66 @@ namespace osu.Desktop.Tests.Visual }); } + [Test] + public void TestSpeedAdjustmentOrdering() + { + var hitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.X); + + var speedAdjustments = new[] + { + new SpeedAdjustmentContainer(new MultiplierControlPoint()), + new SpeedAdjustmentContainer(new MultiplierControlPoint(1000) + { + TimingPoint = new TimingControlPoint { BeatLength = 500 } + }), + new SpeedAdjustmentContainer(new MultiplierControlPoint(2000) + { + TimingPoint = new TimingControlPoint { BeatLength = 1000 }, + DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 2} + }), + new SpeedAdjustmentContainer(new MultiplierControlPoint(3000) + { + TimingPoint = new TimingControlPoint { BeatLength = 1000 }, + DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 1} + }), + }; + + var hitObjects = new[] + { + new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = -1000 }), + new DrawableTestHitObject(Axes.X, new TestHitObject()), + new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 1000 }), + new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 2000 }), + new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 3000 }), + new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 4000 }), + }; + + hitObjects.ForEach(h => hitObjectContainer.Add(h)); + speedAdjustments.ForEach(hitObjectContainer.AddSpeedAdjustment); + + // The 0th index in hitObjectContainer.SpeedAdjustments is the "default" control point + // Check multiplier of the default speed adjustment + Assert.AreEqual(1, hitObjectContainer.SpeedAdjustments[0].ControlPoint.Multiplier); + Assert.AreEqual(1, speedAdjustments[0].ControlPoint.Multiplier); + Assert.AreEqual(2, speedAdjustments[1].ControlPoint.Multiplier); + Assert.AreEqual(2, speedAdjustments[2].ControlPoint.Multiplier); + Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier); + + // Check insertion of hit objects + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[0])); + Assert.IsTrue(speedAdjustments[0].Contains(hitObjects[1])); + Assert.IsTrue(speedAdjustments[1].Contains(hitObjects[2])); + Assert.IsTrue(speedAdjustments[2].Contains(hitObjects[3])); + Assert.IsTrue(speedAdjustments[3].Contains(hitObjects[4])); + Assert.IsTrue(speedAdjustments[3].Contains(hitObjects[5])); + + hitObjectContainer.RemoveSpeedAdjustment(speedAdjustments[1]); + + // The hit object contained in this speed adjustment should be resorted into the previous one + + Assert.IsTrue(speedAdjustments[0].Contains(hitObjects[2])); + } + private class TestRulesetContainer : ScrollingRulesetContainer { private readonly Axes scrollingAxes; @@ -158,4 +223,4 @@ namespace osu.Desktop.Tests.Visual public override string MaxResultString { get { throw new NotImplementedException(); } } } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index aea224ab9e..bfaacdd08e 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.UI /// /// The container that contains the s and s. /// - internal new readonly ScrollingHitObjectContainer HitObjects; + public new readonly ScrollingHitObjectContainer HitObjects; /// /// Creates a new . @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.UI /// /// A container that provides the foundation for sorting s into s. /// - internal class ScrollingHitObjectContainer : HitObjectContainer + public class ScrollingHitObjectContainer : HitObjectContainer { /// /// Gets or sets the range of time that is visible by the length of the scrolling axes. @@ -152,6 +152,7 @@ namespace osu.Game.Rulesets.UI public readonly BindableBool Reversed = new BindableBool(); private readonly Container speedAdjustments; + public IReadOnlyList SpeedAdjustments => speedAdjustments; private readonly Axes scrollingAxes; From a737f5fe0da77583cdbd35f41dac09b7a133faf7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:05:19 +0900 Subject: [PATCH 128/180] CI fixes. --- osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 0ca6fc84c2..3b13fdf00a 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -27,7 +26,7 @@ namespace osu.Game.Rulesets.Timing public readonly BindableBool Reversed = new BindableBool(); protected override Container Content => content; - private Container content; + private readonly Container content; /// /// The axes which the content of this container will scroll through. @@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Timing /// public readonly MultiplierControlPoint ControlPoint; - private ScrollingContainer scrollingContainer; + private readonly ScrollingContainer scrollingContainer; /// /// Creates a new . From 5a3c0de7ada1a3a9726e695e02f88a4015442e44 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:10:58 +0900 Subject: [PATCH 129/180] Fix further incorrect comparison. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index bfaacdd08e..e9f6b4f2ed 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -182,7 +182,7 @@ namespace osu.Game.Rulesets.UI speedAdjustments.Add(speedAdjustment); // We now need to re-sort the hit objects in the last speed adjustment prior to this one, to see if they need a new parent - var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s.ControlPoint.StartTime <= speedAdjustment.ControlPoint.StartTime); + var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s != speedAdjustment && s.ControlPoint.StartTime <= speedAdjustment.ControlPoint.StartTime); if (previousSpeedAdjustment == null) return; From 0189f014028b9bdcad1d1b43a3a4650294bfed96 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:15:40 +0900 Subject: [PATCH 130/180] Explicitly store defaultSpeedAdjustment, and make it un-removable --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index e9f6b4f2ed..524665487d 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -154,6 +154,8 @@ namespace osu.Game.Rulesets.UI private readonly Container speedAdjustments; public IReadOnlyList SpeedAdjustments => speedAdjustments; + private readonly SpeedAdjustmentContainer defaultSpeedAdjustment; + private readonly Axes scrollingAxes; /// @@ -167,7 +169,7 @@ namespace osu.Game.Rulesets.UI AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); // Default speed adjustment - AddSpeedAdjustment(new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); + AddSpeedAdjustment(defaultSpeedAdjustment = new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); } /// @@ -208,6 +210,9 @@ namespace osu.Game.Rulesets.UI /// The to remove. public void RemoveSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) { + if (speedAdjustment == defaultSpeedAdjustment) + throw new InvalidOperationException($"The default {nameof(SpeedAdjustmentContainer)} must not be removed."); + if (!speedAdjustments.Remove(speedAdjustment)) return; @@ -232,11 +237,7 @@ namespace osu.Game.Rulesets.UI if (!(hitObject is IScrollingHitObject)) throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - var target = adjustmentContainerFor(hitObject); - if (target == null) - throw new InvalidOperationException($"A {nameof(SpeedAdjustmentContainer)} to container {hitObject} could not be found."); - - target.Add(hitObject); + adjustmentContainerFor(hitObject).Add(hitObject); } public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); @@ -248,7 +249,7 @@ namespace osu.Game.Rulesets.UI /// /// The hit object to find the active for. /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.LastOrDefault(c => c.CanContain(hitObject)) ?? speedAdjustments.FirstOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.LastOrDefault(c => c.CanContain(hitObject)) ?? defaultSpeedAdjustment; /// /// Finds the which provides the speed adjustment active at a time. @@ -256,7 +257,7 @@ namespace osu.Game.Rulesets.UI /// /// The time to find the active at. /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.LastOrDefault(c => c.CanContain(time)) ?? speedAdjustments.FirstOrDefault(); + private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.LastOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; } } } From e337fbcf4fe9dedc008a1ff33be26919ca2a6de9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:22:40 +0900 Subject: [PATCH 131/180] Make availableColumns into a ctor argument. --- .../Beatmaps/ManiaBeatmapConverter.cs | 14 ++++++-------- .../Legacy/DistanceObjectPatternGenerator.cs | 4 ++-- .../Legacy/EndTimeObjectPatternGenerator.cs | 4 ++-- .../Patterns/Legacy/HitObjectPatternGenerator.cs | 4 ++-- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 4 ++-- .../Beatmaps/Patterns/PatternGenerator.cs | 7 ++++--- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 9b88a8c96c..262f1c67ed 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The hit objects generated. private IEnumerable generateSpecific(HitObject original) { - var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern) { AvailableColumns = availableColumns }; + var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, availableColumns, lastPattern); Pattern newPattern = generator.Generate(); lastPattern = newPattern; @@ -119,14 +119,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps Patterns.PatternGenerator conversion = null; if (distanceData != null) - conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern); + conversion = new DistanceObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern); else if (endTimeData != null) - conversion = new EndTimeObjectPatternGenerator(random, original, beatmap); + conversion = new EndTimeObjectPatternGenerator(random, original, beatmap, availableColumns); else if (positionData != null) { computeDensity(original.StartTime); - conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair); + conversion = new HitObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern, lastTime, lastPosition, density, lastStair); recordNote(original.StartTime, positionData.Position); } @@ -134,8 +134,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (conversion == null) return null; - conversion.AvailableColumns = availableColumns; - Pattern newPattern = conversion.Generate(); lastPattern = newPattern; @@ -150,8 +148,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator { - public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern) - : base(random, hitObject, beatmap, previousPattern) + public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) + : base(random, hitObject, beatmap, availableColumns, previousPattern) { } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index c03a8438ae..20966a75f7 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -29,8 +29,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private PatternType convertType; - public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern) - : base(random, hitObject, beatmap, previousPattern) + public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) + : base(random, hitObject, beatmap, availableColumns, previousPattern) { convertType = PatternType.None; if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 6ad7489e0f..c353496410 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { private readonly double endTime; - public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap) - : base(random, hitObject, beatmap, new Pattern()) + public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns) + : base(random, hitObject, beatmap, availableColumns, new Pattern()) { var endtimeData = HitObject as IHasEndTime; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 99f55cb98b..0716671da3 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -20,8 +20,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly PatternType convertType; - public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) - : base(random, hitObject, beatmap, previousPattern) + public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) + : base(random, hitObject, beatmap, availableColumns, previousPattern) { StairType = lastStair; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index b72618c36c..d1b962bdd4 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -25,8 +25,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// protected readonly FastRandom Random; - protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, Pattern previousPattern) - : base(hitObject, beatmap, previousPattern) + protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) + : base(hitObject, beatmap, availableColumns, previousPattern) { Random = random; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 6ab9c86b9f..4fe100df23 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// The number of columns available to create the pattern. /// - public int AvailableColumns; + protected readonly int AvailableColumns; /// /// The last pattern. @@ -31,11 +31,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// protected readonly Beatmap Beatmap; - protected PatternGenerator(HitObject hitObject, Beatmap beatmap, Pattern previousPattern) + protected PatternGenerator(HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) { - PreviousPattern = previousPattern; HitObject = hitObject; Beatmap = beatmap; + AvailableColumns = availableColumns; + PreviousPattern = previousPattern; } /// From 2f2abf122b38a4d53c0c1b02449781010f0f0dcd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 16:46:12 +0900 Subject: [PATCH 132/180] Add exceptions galore. --- .../Beatmaps/ManiaBeatmapConverter.cs | 2 ++ .../Patterns/Legacy/HitObjectPatternGenerator.cs | 3 +++ .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 12 +++++++++++- .../Beatmaps/Patterns/PatternGenerator.cs | 6 ++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 262f1c67ed..be670936fd 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps public ManiaBeatmapConverter(bool isForCurrentRuleset, int availableColumns) { + if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); + this.isForCurrentRuleset = isForCurrentRuleset; this.availableColumns = availableColumns; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 0716671da3..077b926635 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -23,6 +23,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) : base(random, hitObject, beatmap, availableColumns, previousPattern) { + if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); + if (density < 0) throw new ArgumentOutOfRangeException(nameof(density)); + StairType = lastStair; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index d1b962bdd4..a3173f9784 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -28,8 +28,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) : base(hitObject, beatmap, availableColumns, previousPattern) { - Random = random; + if (random == null) throw new ArgumentNullException(nameof(random)); + if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); + if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); + if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); + Random = random; RandomStart = AvailableColumns == 8 ? 1 : 0; } @@ -62,6 +66,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The amount of notes to be generated. protected int GetRandomNoteCount(double p2, double p3, double p4 = 0, double p5 = 0, double p6 = 0) { + if (p2 < 0 || p2 > 1) throw new ArgumentOutOfRangeException(nameof(p2)); + if (p3 < 0 || p3 > 1) throw new ArgumentOutOfRangeException(nameof(p3)); + if (p4 < 0 || p4 > 1) throw new ArgumentOutOfRangeException(nameof(p4)); + if (p5 < 0 || p5 > 1) throw new ArgumentOutOfRangeException(nameof(p5)); + if (p6 < 0 || p6 > 1) throw new ArgumentOutOfRangeException(nameof(p6)); + double val = Random.NextDouble(); if (val >= 1 - p6) return 6; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 4fe100df23..ef321232c8 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; @@ -33,6 +34,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns protected PatternGenerator(HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) { + if (hitObject == null) throw new ArgumentNullException(nameof(hitObject)); + if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); + if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); + if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); + HitObject = hitObject; Beatmap = beatmap; AvailableColumns = availableColumns; From 803cbddfe224e756a52696e965a2168736943ccc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 16:58:47 +0900 Subject: [PATCH 133/180] Ensure score's user is set directly from API Previously would fail in visualtests due to `OsuGame` case. --- osu.Game/Screens/Play/Player.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3f399d69e6..992c5c5f6f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -23,6 +23,7 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Ranking; using osu.Framework.Audio.Sample; using osu.Game.Beatmaps; +using osu.Game.Online.API; namespace osu.Game.Screens.Play { @@ -50,6 +51,8 @@ namespace osu.Game.Screens.Play private RulesetInfo ruleset; + private APIAccess api; + private ScoreProcessor scoreProcessor; protected RulesetContainer RulesetContainer; @@ -69,9 +72,12 @@ namespace osu.Game.Screens.Play private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true; [BackgroundDependencyLoader(permitNulls: true)] - private void load(AudioManager audio, OsuConfigManager config, OsuGame osu) + private void load(AudioManager audio, OsuConfigManager config, OsuGame osu, APIAccess api) { + this.api = api; + dimLevel = config.GetBindable(OsuSetting.DimLevel); + mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); sampleRestart = audio.Sample.Get(@"Gameplay/restart"); @@ -235,7 +241,7 @@ namespace osu.Game.Screens.Play Ruleset = ruleset }; scoreProcessor.PopulateScore(score); - score.User = RulesetContainer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value; + score.User = RulesetContainer.Replay?.User ?? api.LocalUser.Value; Push(new Results(score)); }); } From 8f32fd28c927b3a90a35e6dbf9d5f33dfbbee0e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 17:21:19 +0900 Subject: [PATCH 134/180] Fix backwards conditional --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 68b5aa1cc9..8cb45c39a5 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -361,7 +361,7 @@ namespace osu.Game // we only want to apply these restrictions when we are inside a screen stack. // the use case for not applying is in visual/unit tests. - bool applyRestrictions = currentScreen?.AllowBeatmapRulesetChange ?? false; + bool applyRestrictions = !currentScreen?.AllowBeatmapRulesetChange ?? false; Ruleset.Disabled = applyRestrictions; Beatmap.Disabled = applyRestrictions; From a26885c1ab46c72b6df4647fcd1db7bfdfb0d144 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 17:25:45 +0900 Subject: [PATCH 135/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index f1527e5456..ba70b8eaa9 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit f1527e5456cd228ddfb68cf6d56eb5d28dc360bf +Subproject commit ba70b8eaa9b79d4248873d4399f3b9e918fc3c8f From d8de6e289c18f495239c8db4539cb7622733e022 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 17:38:51 +0900 Subject: [PATCH 136/180] Don't start rotating the cursor until it has travelled a minimum disatnce Some people, myself included, were annoyed by the rotation starting too soon (especially when dragging up and left one pixel). --- osu.Game/Graphics/Cursor/MenuCursor.cs | 29 +++++++++++++++++++------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 9658cfdb09..ea02feef0e 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Configuration; using System; +using System.Diagnostics; using osu.Framework.Graphics.Textures; namespace osu.Game.Graphics.Cursor @@ -21,20 +22,31 @@ namespace osu.Game.Graphics.Cursor private bool dragging; + private bool startRotation; + protected override bool OnMouseMove(InputState state) { if (dragging) { - Vector2 offset = state.Mouse.Position - state.Mouse.PositionMouseDown ?? state.Mouse.Delta; - float degrees = (float)MathHelper.RadiansToDegrees(Math.Atan2(-offset.X, offset.Y)) + 24.3f; + Debug.Assert(state.Mouse.PositionMouseDown != null); - // Always rotate in the direction of least distance - float diff = (degrees - ActiveCursor.Rotation) % 360; - if (diff < -180) diff += 360; - if (diff > 180) diff -= 360; - degrees = ActiveCursor.Rotation + diff; + // don't start rotating until we're moved a minimum distance away from the mouse down location, + // else it can have an annoying effect. + startRotation |= Vector2.Distance(state.Mouse.Position, state.Mouse.PositionMouseDown.Value) > 30; - ActiveCursor.RotateTo(degrees, 600, Easing.OutQuint); + if (startRotation) + { + Vector2 offset = state.Mouse.Position - state.Mouse.PositionMouseDown.Value; + float degrees = (float)MathHelper.RadiansToDegrees(Math.Atan2(-offset.X, offset.Y)) + 24.3f; + + // Always rotate in the direction of least distance + float diff = (degrees - ActiveCursor.Rotation) % 360; + if (diff < -180) diff += 360; + if (diff > 180) diff -= 360; + degrees = ActiveCursor.Rotation + diff; + + ActiveCursor.RotateTo(degrees, 600, Easing.OutQuint); + } } return base.OnMouseMove(state); @@ -61,6 +73,7 @@ namespace osu.Game.Graphics.Cursor if (!state.Mouse.HasMainButtonPressed) { dragging = false; + startRotation = false; ((Cursor)ActiveCursor).AdditiveLayer.FadeOut(500, Easing.OutQuint); ActiveCursor.RotateTo(0, 600 * (1 + Math.Abs(ActiveCursor.Rotation / 720)), Easing.OutElasticHalf); From 97acff535d97d6fbe760b86dff2dd57221ba8255 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 18:21:00 +0900 Subject: [PATCH 137/180] Tidy up conditionals --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index eb7d528897..6c697c8660 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -136,40 +136,34 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - if (HasFocus) - { - if (bindTarget.IsHovered) - { - if (!AllowMainMouseButtons) - { - switch (args.Button) - { - case MouseButton.Left: - case MouseButton.Right: - return true; - } - } + if (!HasFocus || !bindTarget.IsHovered) + return base.OnMouseDown(state, args); - bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); - return true; + if (!AllowMainMouseButtons) + { + switch (args.Button) + { + case MouseButton.Left: + case MouseButton.Right: + return true; } } - return base.OnMouseDown(state, args); + bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state)); + return true; } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - if (HasFocus && !state.Mouse.Buttons.Any()) - { - if (bindTarget.IsHovered) - finalise(); - else - updateBindTarget(); - return true; - } + // don't do anything until the last button is released. + if (!HasFocus || state.Mouse.Buttons.Any()) + return base.OnMouseUp(state, args); - return base.OnMouseUp(state, args); + if (bindTarget.IsHovered) + finalise(); + else + updateBindTarget(); + return true; } protected override bool OnWheel(InputState state) @@ -211,13 +205,10 @@ namespace osu.Game.Overlays.KeyBinding protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) { - if (HasFocus) - { - finalise(); - return true; - } + if (!HasFocus) return base.OnKeyUp(state, args); - return base.OnKeyUp(state, args); + finalise(); + return true; } private void finalise() From c5a20e337274356283092a6f67b7184019dfb824 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 18:02:38 +0900 Subject: [PATCH 138/180] Remove permitNulls --- osu.Game/Screens/Play/Player.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 992c5c5f6f..615e04d6c2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -71,8 +71,8 @@ namespace osu.Game.Screens.Play private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true; - [BackgroundDependencyLoader(permitNulls: true)] - private void load(AudioManager audio, OsuConfigManager config, OsuGame osu, APIAccess api) + [BackgroundDependencyLoader] + private void load(AudioManager audio, OsuConfigManager config, APIAccess api) { this.api = api; @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play if (beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); - ruleset = osu?.Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; + ruleset = Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset; var rulesetInstance = ruleset.CreateInstance(); try From b46a51fd8b7ccdbdd6019cff246a82c2efa72444 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:36:32 +0900 Subject: [PATCH 139/180] Make the speed adjustment containers ordered decreasingly by their control point start time. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 524665487d..6f0b7ac4ac 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -151,7 +151,7 @@ namespace osu.Game.Rulesets.UI /// public readonly BindableBool Reversed = new BindableBool(); - private readonly Container speedAdjustments; + private readonly SortedContainer speedAdjustments; public IReadOnlyList SpeedAdjustments => speedAdjustments; private readonly SpeedAdjustmentContainer defaultSpeedAdjustment; @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.UI { this.scrollingAxes = scrollingAxes; - AddInternal(speedAdjustments = new Container { RelativeSizeAxes = Axes.Both }); + AddInternal(speedAdjustments = new SortedContainer { RelativeSizeAxes = Axes.Both }); // Default speed adjustment AddSpeedAdjustment(defaultSpeedAdjustment = new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); @@ -257,7 +257,21 @@ namespace osu.Game.Rulesets.UI /// /// The time to find the active at. /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.LastOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; + private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.First(c => c.CanContain(time)) ?? defaultSpeedAdjustment; + + private class SortedContainer : Container + { + protected override int Compare(Drawable x, Drawable y) + { + var sX = (SpeedAdjustmentContainer)x; + var sY = (SpeedAdjustmentContainer)y; + + int result = sY.ControlPoint.StartTime.CompareTo(sX.ControlPoint.StartTime); + if (result != 0) + return result; + return base.Compare(x, y); + } + } } } } From 137964b79297e27b9eb36a61e176f2b929068094 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:36:56 +0900 Subject: [PATCH 140/180] Fix hit objects not getting added to the correct speed adjustment container. --- .../Timing/SpeedAdjustmentContainer.cs | 5 --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 38 +++++++------------ 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index 3b13fdf00a..df0abd28df 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -98,11 +98,6 @@ namespace osu.Game.Rulesets.Timing base.Add(drawable); } - /// - /// Whether a falls within this s affecting timespan. - /// - public bool CanContain(DrawableHitObject hitObject) => CanContain(hitObject.HitObject.StartTime); - /// /// Whether a point in time falls within this s affecting timespan. /// diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 6f0b7ac4ac..550740c5ec 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -181,26 +181,25 @@ namespace osu.Game.Rulesets.UI speedAdjustment.ScrollingAxes = scrollingAxes; speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); speedAdjustment.Reversed.BindTo(Reversed); - speedAdjustments.Add(speedAdjustment); - // We now need to re-sort the hit objects in the last speed adjustment prior to this one, to see if they need a new parent - var previousSpeedAdjustment = speedAdjustments.LastOrDefault(s => s != speedAdjustment && s.ControlPoint.StartTime <= speedAdjustment.ControlPoint.StartTime); - if (previousSpeedAdjustment == null) - return; - - for (int i = 0; i < previousSpeedAdjustment.Children.Count; i++) + if (speedAdjustments.Count > 0) { - DrawableHitObject hitObject = previousSpeedAdjustment[i]; + var existingAdjustment = adjustmentContainerAt(speedAdjustment.ControlPoint.StartTime); + for (int i = 0; i < existingAdjustment.Count; i++) + { + DrawableHitObject hitObject = existingAdjustment[i]; - var newSpeedAdjustment = adjustmentContainerFor(hitObject); - if (newSpeedAdjustment == previousSpeedAdjustment) - continue; + if (!speedAdjustment.CanContain(hitObject.HitObject.StartTime)) + continue; - previousSpeedAdjustment.Remove(hitObject); - newSpeedAdjustment.Add(hitObject); + existingAdjustment.Remove(hitObject); + speedAdjustment.Add(hitObject); - i--; + i--; + } } + + speedAdjustments.Add(speedAdjustment); } /// @@ -237,20 +236,11 @@ namespace osu.Game.Rulesets.UI if (!(hitObject is IScrollingHitObject)) throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - adjustmentContainerFor(hitObject).Add(hitObject); + adjustmentContainerAt(hitObject.HitObject.StartTime).Add(hitObject); } public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); - /// - /// Finds the which provides the speed adjustment active at the start time - /// of a hit object. If there is no active at the start time of the hit object, - /// then the first (time-wise) speed adjustment is returned. - /// - /// The hit object to find the active for. - /// The active at 's start time. Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerFor(DrawableHitObject hitObject) => speedAdjustments.LastOrDefault(c => c.CanContain(hitObject)) ?? defaultSpeedAdjustment; - /// /// Finds the which provides the speed adjustment active at a time. /// If there is no active at the time, then the first (time-wise) speed adjustment is returned. From e5d985838f55d95742003d829b6759904786a18d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:37:49 +0900 Subject: [PATCH 141/180] Set ScrollingAxes and RelativeChildOffset a bit more safely. --- .../Rulesets/Timing/LinearScrollingContainer.cs | 8 +++----- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 2 ++ .../Rulesets/Timing/SpeedAdjustmentContainer.cs | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs index db497b7664..f8e87bc022 100644 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs @@ -10,12 +10,10 @@ namespace osu.Game.Rulesets.Timing /// internal class LinearScrollingContainer : ScrollingContainer { - private readonly Axes scrollingAxes; private readonly MultiplierControlPoint controlPoint; - public LinearScrollingContainer(Axes scrollingAxes, MultiplierControlPoint controlPoint) + public LinearScrollingContainer(MultiplierControlPoint controlPoint) { - this.scrollingAxes = scrollingAxes; this.controlPoint = controlPoint; } @@ -23,8 +21,8 @@ namespace osu.Game.Rulesets.Timing { base.Update(); - if ((scrollingAxes & Axes.X) > 0) X = (float)(controlPoint.StartTime - Time.Current); - if ((scrollingAxes & Axes.Y) > 0) Y = (float)(controlPoint.StartTime - Time.Current); + if ((ScrollingAxes & Axes.X) > 0) X = (float)(controlPoint.StartTime - Time.Current); + if ((ScrollingAxes & Axes.Y) > 0) Y = (float)(controlPoint.StartTime - Time.Current); } } } diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index 9bb32ead77..ad5fc7c2f0 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -96,6 +96,8 @@ namespace osu.Game.Rulesets.Timing { base.Update(); + RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); + // We want our size and position-space along the scrolling axes to span our duration to completely enclose all the hit objects Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)Duration : Size.X, (ScrollingAxes & Axes.Y) > 0 ? (float)Duration : Size.Y); // And we need to make sure the hit object's position-space doesn't change due to our resizing diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index df0abd28df..d3bd7685da 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -31,7 +31,11 @@ namespace osu.Game.Rulesets.Timing /// /// The axes which the content of this container will scroll through. /// - public Axes ScrollingAxes { get; internal set; } + public Axes ScrollingAxes + { + get { return scrollingContainer.ScrollingAxes; } + set { scrollingContainer.ScrollingAxes = value; } + } public override bool RemoveWhenNotAlive => false; @@ -52,11 +56,8 @@ namespace osu.Game.Rulesets.Timing RelativeSizeAxes = Axes.Both; scrollingContainer = CreateScrollingContainer(); - - scrollingContainer.ScrollingAxes = ScrollingAxes; scrollingContainer.ControlPoint = ControlPoint; scrollingContainer.VisibleTimeRange.BindTo(VisibleTimeRange); - scrollingContainer.RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); AddInternal(content = scrollingContainer); } @@ -107,6 +108,6 @@ namespace osu.Game.Rulesets.Timing /// Creates the which contains the scrolling s of this container. /// /// The . - protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ScrollingAxes, ControlPoint); + protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ControlPoint); } -} \ No newline at end of file +} From 1964bc72e5c933c051b84b483bf62d0c223e0277 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:39:09 +0900 Subject: [PATCH 142/180] Should be FirstOrDefault for hit objects occuriung before the first control point. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 550740c5ec..007f2af803 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -247,7 +247,7 @@ namespace osu.Game.Rulesets.UI /// /// The time to find the active at. /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.First(c => c.CanContain(time)) ?? defaultSpeedAdjustment; + private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; private class SortedContainer : Container { From ad63cbf45505c8fe2ba027cf3d9fe78e551e5a56 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:54:41 +0900 Subject: [PATCH 143/180] Fix default comparator being inverted. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 007f2af803..7143401824 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -259,7 +259,7 @@ namespace osu.Game.Rulesets.UI int result = sY.ControlPoint.StartTime.CompareTo(sX.ControlPoint.StartTime); if (result != 0) return result; - return base.Compare(x, y); + return base.Compare(y, x); } } } From d64071f3de78291766b494d1078099f051badd3e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 18:55:27 +0900 Subject: [PATCH 144/180] Fix up + make test case more sane. --- .../Visual/TestCaseScrollingPlayfield.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index 2d49b2d0f9..c8c95da618 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -115,18 +115,18 @@ namespace osu.Desktop.Tests.Visual Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier); // Check insertion of hit objects - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[0])); - Assert.IsTrue(speedAdjustments[0].Contains(hitObjects[1])); - Assert.IsTrue(speedAdjustments[1].Contains(hitObjects[2])); - Assert.IsTrue(speedAdjustments[2].Contains(hitObjects[3])); - Assert.IsTrue(speedAdjustments[3].Contains(hitObjects[4])); - Assert.IsTrue(speedAdjustments[3].Contains(hitObjects[5])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[4].Contains(hitObjects[0])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[2].Contains(hitObjects[2])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[1].Contains(hitObjects[3])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[4])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[5])); - hitObjectContainer.RemoveSpeedAdjustment(speedAdjustments[1]); + hitObjectContainer.RemoveSpeedAdjustment(hitObjectContainer.SpeedAdjustments[3]); - // The hit object contained in this speed adjustment should be resorted into the previous one + // The hit object contained in this speed adjustment should be resorted into the one occuring before it - Assert.IsTrue(speedAdjustments[0].Contains(hitObjects[2])); + Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); } private class TestRulesetContainer : ScrollingRulesetContainer From 322dfe0250eef71d0321e53bd70d4238d1ad48a4 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 19:17:12 +0900 Subject: [PATCH 145/180] Fix ScrollingContainer possibly not getting the correct size to cover hit objects. --- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index ad5fc7c2f0..e4b098d2bd 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -74,8 +74,7 @@ namespace osu.Game.Rulesets.Timing // absolutely-sized element along the scrolling axes and adding a corresponding duration value. This introduces a bit of error, but will never under-estimate.ion. // Find the largest element that is absolutely-sized along ScrollingAxes - float maxAbsoluteSize = Children.Where(c => (c.RelativeSizeAxes & ScrollingAxes) == 0) - .Select(c => (ScrollingAxes & Axes.X) > 0 ? c.Width : c.Height) + float maxAbsoluteSize = Children.Select(c => (ScrollingAxes & Axes.X) > 0 ? c.DrawWidth : c.DrawHeight) .DefaultIfEmpty().Max(); float ourAbsoluteSize = (ScrollingAxes & Axes.X) > 0 ? DrawWidth : DrawHeight; From ab0e3ccc5502074cb493cfbb44cf160443467745 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 19:33:18 +0900 Subject: [PATCH 146/180] Make SimpleNotifications support word wrap --- osu.Game/Overlays/Notifications/SimpleNotification.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index e10cc26546..daf1ac838d 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -4,17 +4,16 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using OpenTK; namespace osu.Game.Overlays.Notifications { public class SimpleNotification : Notification { - private string text; + private string text = string.Empty; public string Text { get { return text; } @@ -36,7 +35,7 @@ namespace osu.Game.Overlays.Notifications } } - private readonly SpriteText textDrawable; + private readonly TextFlowContainer textDrawable; private readonly SpriteIcon iconDrawable; protected Box IconBackgound; @@ -59,9 +58,8 @@ namespace osu.Game.Overlays.Notifications } }); - Content.Add(textDrawable = new OsuSpriteText + Content.Add(textDrawable = new TextFlowContainer(t => t.TextSize = 16) { - TextSize = 16, Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, From 0ea6c65be6525c295902f3cd884c97d82bedb1d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 19:34:06 +0900 Subject: [PATCH 147/180] Fix potentially racey behaviour of versionManager initialisation Changing the state while the container wasn't necessarily completed loading caused inconsistent behaviour. --- osu.Desktop/OsuGameDesktop.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index 88c8a206c8..a623347540 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -20,16 +20,11 @@ namespace osu.Desktop { internal class OsuGameDesktop : OsuGame { - private readonly VersionManager versionManager; + private VersionManager versionManager; public OsuGameDesktop(string[] args = null) : base(args) { - versionManager = new VersionManager - { - Depth = int.MinValue, - State = Visibility.Hidden - }; } public override Storage GetStorageForStableInstall() @@ -88,11 +83,15 @@ namespace osu.Desktop { base.LoadComplete(); - LoadComponentAsync(versionManager, Add); + LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }); + ScreenChanged += s => { - if (!versionManager.IsPresent && s is Intro) + if (s is Intro && s.ChildScreen == null) + { + Add(versionManager); versionManager.State = Visibility.Visible; + } }; } From 9f69aa908225ea55dbdc9ee172c1688183d721bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 19:41:39 +0900 Subject: [PATCH 148/180] Show a notification after a successful update Allows access to the github changelog --- osu.Desktop/Overlays/VersionManager.cs | 48 +++++++++++++++++++++- osu.Game/Configuration/OsuConfigManager.cs | 5 ++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index b445340f50..dab2d160c5 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -19,6 +20,7 @@ using OpenTK.Graphics; using System.Net.Http; using osu.Framework.Logging; using osu.Game; +using osu.Game.Configuration; namespace osu.Desktop.Overlays { @@ -26,18 +28,24 @@ namespace osu.Desktop.Overlays { private UpdateManager updateManager; private NotificationOverlay notificationOverlay; + private OsuConfigManager config; + private OsuGameBase game; public override bool HandleInput => false; [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game) + private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) { notificationOverlay = notification; + this.config = config; + this.game = game; AutoSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; Origin = Anchor.BottomCentre; + Alpha = 0; + State = Visibility.Hidden; Children = new Drawable[] { @@ -91,6 +99,44 @@ namespace osu.Desktop.Overlays checkForUpdateAsync(); } + protected override void LoadComplete() + { + base.LoadComplete(); + + State = Visibility.Visible; + + var version = game.Version; + var lastVersion = config.Get(OsuSetting.Version); + if (char.IsNumber(version[0]) && version != lastVersion) + { + config.Set(OsuSetting.Version, version); + + // only show a notification if we've previously saved a version to the config file (ie. not the first run). + if (!string.IsNullOrEmpty(lastVersion)) + Scheduler.AddDelayed(() => notificationOverlay.Post(new UpdateCompleteNotification(version)), 5000); + } + } + + private class UpdateCompleteNotification : SimpleNotification + { + public UpdateCompleteNotification(string version) + { + Text = $"You are now running osu!lazer {version}.\nClick to see what's new!"; + Icon = FontAwesome.fa_check_square; + Activated = delegate + { + Process.Start($"https://github.com/ppy/osu/releases/tag/v{version}"); + return true; + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IconBackgound.Colour = colours.BlueDark; + } + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 6b07d5c967..44a6af841c 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -70,6 +70,8 @@ namespace osu.Game.Configuration // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); + + Set(OsuSetting.Version, string.Empty); } public OsuConfigManager(Storage storage) : base(storage) @@ -106,6 +108,7 @@ namespace osu.Game.Configuration SnakingInSliders, SnakingOutSliders, ShowFpsDisplay, - ChatDisplayHeight + ChatDisplayHeight, + Version } } From 480d839d678e4eb1a537a559984c8718f3a09c49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 19:51:42 +0900 Subject: [PATCH 149/180] Allow the notification overlay to close when all notifications are dismissed --- osu.Game/Overlays/NotificationOverlay.cs | 11 ++++++++++- osu.Game/Overlays/Notifications/Notification.cs | 4 ++-- .../Overlays/Notifications/NotificationSection.cs | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 7eabb592c6..5b9c3d20a0 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays private ScrollContainer scrollContainer; private FlowContainer sections; - [BackgroundDependencyLoader(permitNulls: true)] + [BackgroundDependencyLoader] private void load() { Width = width; @@ -72,6 +72,13 @@ namespace osu.Game.Overlays private int runningDepth; + private void notificationClosed() + { + // hide ourselves if all notifications have been dismissed. + if (sections.Select(c => c.DisplayedCount).Sum() > 0) + State = Visibility.Hidden; + } + public void Post(Notification notification) { Schedule(() => @@ -81,6 +88,8 @@ namespace osu.Game.Overlays ++runningDepth; notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; + notification.Closed += notificationClosed; + var hasCompletionTarget = notification as IHasCompletionTarget; if (hasCompletionTarget != null) hasCompletionTarget.CompletionTarget = Post; diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index 14446a468c..b63efd3226 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -19,9 +19,9 @@ namespace osu.Game.Overlays.Notifications public abstract class Notification : Container { /// - /// Use requested close. + /// User requested close. /// - public Action Closed; + public event Action Closed; /// /// Run on user activating the notification. Return true to close. diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index efd3b39ee2..705800d4aa 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -24,6 +24,8 @@ namespace osu.Game.Overlays.Notifications private FlowContainer notifications; + public int DisplayedCount => notifications.Count; + public void Add(Notification notification) { notifications.Add(notification); From db275517096197d86e721172d274d6b2d2356157 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 20:51:20 +0900 Subject: [PATCH 150/180] Make hit objects put in ScrollingContainers strictly ordered by start time This won't change anything as is since all hit objects are given a depth at the moment. --- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index e4b098d2bd..d2a6939dd3 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -45,18 +45,15 @@ namespace osu.Game.Rulesets.Timing RelativePositionAxes = Axes.Both; } - public override void InvalidateFromChild(Invalidation invalidation) + protected override int Compare(Drawable x, Drawable y) { - // We only want to re-compute our size when a child's size or position has changed - if ((invalidation & Invalidation.RequiredParentSizeToFit) == 0) - { - base.InvalidateFromChild(invalidation); - return; - } + var hX = (DrawableHitObject)x; + var hY = (DrawableHitObject)y; - durationBacking.Invalidate(); - - base.InvalidateFromChild(invalidation); + int result = hY.HitObject.StartTime.CompareTo(hX.HitObject.StartTime); + if (result != 0) + return result; + return base.Compare(y, x); } private double computeDuration() From d080a7e970252059cef1df35f5f3080d77cbecfc Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 20:51:53 +0900 Subject: [PATCH 151/180] Determine size of ScrollingContainer a bit better to avoid taiko weirdness --- .../Objects/Drawables/DrawableHit.cs | 15 ++++--- .../Objects/Drawables/DrawableSwell.cs | 2 + .../Drawables/DrawableTaikoHitObject.cs | 4 +- .../Rulesets/Timing/ScrollingContainer.cs | 41 +++++++------------ 4 files changed, 27 insertions(+), 35 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 5fcae7d0f4..6b041dfe25 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -28,14 +28,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables FillMode = FillMode.Fit; } - protected override void LoadComplete() - { - base.LoadComplete(); - - // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize - Width *= Parent.RelativeChildSize.X; - } - protected override void CheckJudgement(bool userTriggered) { if (!userTriggered) @@ -71,6 +63,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return UpdateJudgement(true); } + protected override void Update() + { + base.Update(); + + Size = BaseSize * Parent.RelativeChildSize; + } + protected override void UpdateState(ArmedState state) { var circlePiece = MainPiece as CirclePiece; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index fc3bc82520..4eb5c46838 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -199,6 +199,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { base.Update(); + Size = BaseSize * Parent.RelativeChildSize; + // Make the swell stop at the hit target X = (float)Math.Max(Time.Current, HitObject.StartTime); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 765002fb34..46cdfcc365 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); + protected readonly Vector2 BaseSize; + protected readonly TaikoPiece MainPiece; public new TaikoHitType HitObject; @@ -29,7 +31,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Origin = Anchor.Custom; RelativeSizeAxes = Axes.Both; - Size = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); + Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index d2a6939dd3..c8da8d7ac9 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Caching; using osu.Framework.Configuration; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Timing /// internal MultiplierControlPoint ControlPoint; - private Cached durationBacking; + private Cached durationBacking = new Cached(); /// /// Creates a new . @@ -56,35 +57,23 @@ namespace osu.Game.Rulesets.Timing return base.Compare(y, x); } - private double computeDuration() + public override void Add(DrawableHitObject drawable) { - if (!Children.Any()) - return 0; - - double baseDuration = Children.Max(c => (c.HitObject as IHasEndTime)?.EndTime ?? c.HitObject.StartTime) - ControlPoint.StartTime; - - // If we have a singular hit object at the timing section's start time, let's set a sane default duration - if (baseDuration == 0) - baseDuration = 1; - - // This container needs to resize such that it completely encloses the hit objects to avoid masking optimisations. This is done by converting the largest - // absolutely-sized element along the scrolling axes and adding a corresponding duration value. This introduces a bit of error, but will never under-estimate.ion. - - // Find the largest element that is absolutely-sized along ScrollingAxes - float maxAbsoluteSize = Children.Select(c => (ScrollingAxes & Axes.X) > 0 ? c.DrawWidth : c.DrawHeight) - .DefaultIfEmpty().Max(); - - float ourAbsoluteSize = (ScrollingAxes & Axes.X) > 0 ? DrawWidth : DrawHeight; - - // Add the extra duration to account for the absolute size - baseDuration *= 1 + maxAbsoluteSize / ourAbsoluteSize; - - return baseDuration; + durationBacking.Invalidate(); + base.Add(drawable); } + public override bool Remove(DrawableHitObject drawable) + { + durationBacking.Invalidate(); + return base.Remove(drawable); + } + + // Todo: This may underestimate the size of the hit object in some cases, but won't be too much of a problem for now + private double computeDuration() => Math.Max(0, Children.Select(c => (c.HitObject as IHasEndTime)?.EndTime ?? c.HitObject.StartTime).DefaultIfEmpty().Max() - ControlPoint.StartTime) + 1000; + /// - /// The maximum duration of any one hit object inside this . This is calculated as the maximum - /// duration of all hit objects relative to this 's . + /// An approximate total duration of this scrolling container. /// public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); From f8576d44b12feb101f6983a18784828b9f16364f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 22 Aug 2017 21:08:27 +0900 Subject: [PATCH 152/180] Add some more xmldoc. --- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 7143401824..92845c3f3a 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -173,7 +173,8 @@ namespace osu.Game.Rulesets.UI } /// - /// Adds a to this container. + /// Adds a to this container, re-sorting all hit objects + /// in the last that occurred (time-wise) before it. /// /// The . public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) @@ -184,6 +185,8 @@ namespace osu.Game.Rulesets.UI if (speedAdjustments.Count > 0) { + // We need to re-sort all hit objects in the speed adjustment container prior to figure out if they + // should now lie within this one var existingAdjustment = adjustmentContainerAt(speedAdjustment.ControlPoint.StartTime); for (int i = 0; i < existingAdjustment.Count; i++) { From 71af30d2225e4c74bd2210ef37694e7ec8a15bd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 22:48:50 +0900 Subject: [PATCH 153/180] Remove redundant visibility changes --- osu.Desktop/Overlays/VersionManager.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index dab2d160c5..1c0c1475b1 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -45,7 +45,6 @@ namespace osu.Desktop.Overlays Origin = Anchor.BottomCentre; Alpha = 0; - State = Visibility.Hidden; Children = new Drawable[] { @@ -103,11 +102,9 @@ namespace osu.Desktop.Overlays { base.LoadComplete(); - State = Visibility.Visible; - var version = game.Version; var lastVersion = config.Get(OsuSetting.Version); - if (char.IsNumber(version[0]) && version != lastVersion) + if (game.IsDeployedBuild && version != lastVersion) { config.Set(OsuSetting.Version, version); From ef2d9ffede813a5c2ddff6d01af1f269ea3a9496 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 23:43:10 +0900 Subject: [PATCH 154/180] Fix redundant initialiser --- osu.Game/Rulesets/Timing/ScrollingContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index c8da8d7ac9..6e77c49e3d 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Timing /// internal MultiplierControlPoint ControlPoint; - private Cached durationBacking = new Cached(); + private Cached durationBacking; /// /// Creates a new . From dbde27ceefdeae85ad2927ba59baae21b5f62c81 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Aug 2017 23:43:40 +0900 Subject: [PATCH 155/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index ba70b8eaa9..74f644bad0 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit ba70b8eaa9b79d4248873d4399f3b9e918fc3c8f +Subproject commit 74f644bad039606e242d8782014d8c249a38b6a3 From fd3239ad15fa0833a3b6f2c4b7010840e60f6300 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:36:53 +0900 Subject: [PATCH 156/180] Fix KeyBindingStore not getting correct defaults for variants. --- osu.Game/Input/KeyBindingStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 56302acafe..c5ba1683dd 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -22,7 +22,7 @@ namespace osu.Game.Input { var ruleset = info.CreateInstance(); foreach (var variant in ruleset.AvailableVariants) - insertDefaults(ruleset.GetDefaultKeyBindings(), info.ID, variant); + insertDefaults(ruleset.GetDefaultKeyBindings(variant), info.ID, variant); } } From a6266850d60c6366666a4e0223f6e01d0183fa8a Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:46:28 +0900 Subject: [PATCH 157/180] Make KeyBindingRow take a non-action enum. --- osu-framework | 2 +- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index 74f644bad0..1fd9259e86 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 74f644bad039606e242d8782014d8c249a38b6a3 +Subproject commit 1fd9259e86379838dbbc43c12a2238df83800fc0 diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 6c697c8660..c182382d70 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -22,7 +21,7 @@ namespace osu.Game.Overlays.KeyBinding { internal class KeyBindingRow : Container, IFilterable { - private readonly Enum action; + private readonly object action; private readonly IEnumerable bindings; private const float transition_time = 150; @@ -50,7 +49,7 @@ namespace osu.Game.Overlays.KeyBinding public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); - public KeyBindingRow(Enum action, IEnumerable bindings) + public KeyBindingRow(object action, IEnumerable bindings) { this.action = action; this.bindings = bindings; From b2db550cb457abf41bcf12658731d6f9768655d2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 12:47:20 +0900 Subject: [PATCH 158/180] Fix notification count including fading (already closed) notifications --- osu.Game/Overlays/NotificationOverlay.cs | 2 +- osu.Game/Overlays/Notifications/Notification.cs | 6 +++--- osu.Game/Overlays/Notifications/NotificationSection.cs | 7 ++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 5b9c3d20a0..260214a14f 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -75,7 +75,7 @@ namespace osu.Game.Overlays private void notificationClosed() { // hide ourselves if all notifications have been dismissed. - if (sections.Select(c => c.DisplayedCount).Sum() > 0) + if (sections.Select(c => c.DisplayedCount).Sum() == 0) State = Visibility.Hidden; } diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index b63efd3226..422051364e 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -142,12 +142,12 @@ namespace osu.Game.Overlays.Notifications NotificationContent.MoveToX(0, 500, Easing.OutQuint); } - private bool wasClosed; + public bool WasClosed; public virtual void Close() { - if (wasClosed) return; - wasClosed = true; + if (WasClosed) return; + WasClosed = true; Closed?.Invoke(); this.FadeOut(100); diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 705800d4aa..09768ba0ea 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -24,12 +24,9 @@ namespace osu.Game.Overlays.Notifications private FlowContainer notifications; - public int DisplayedCount => notifications.Count; + public int DisplayedCount => notifications.Count(n => !n.WasClosed); - public void Add(Notification notification) - { - notifications.Add(notification); - } + public void Add(Notification notification) => notifications.Add(notification); public IEnumerable AcceptTypes; From be96fb32b30aeb4c2b461c0974a34c8c03545967 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:47:47 +0900 Subject: [PATCH 159/180] Make RulesetContainer load KeyBindingInputManager in load() --- osu.Game/Rulesets/UI/RulesetContainer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 2f1cb915f3..ebf570fecc 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI /// /// The key conversion input manager for this RulesetContainer. /// - public readonly PassThroughInputManager KeyBindingInputManager; + public PassThroughInputManager KeyBindingInputManager; /// /// Whether we are currently providing the local user a gameplay cursor. @@ -76,6 +76,11 @@ namespace osu.Game.Rulesets.UI internal RulesetContainer(Ruleset ruleset) { Ruleset = ruleset; + } + + [BackgroundDependencyLoader] + private void load() + { KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; } From 38a4c841636144d2d46405166d0cf7ee0e62a44f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:48:53 +0900 Subject: [PATCH 160/180] Load SettingsSubsection in load() Fixes header not being displayed with variant bindings. This follows what SettingsSection does. --- .../Overlays/Settings/SettingsSubsection.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index ac6d2fa239..0fbb5b92f7 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -7,14 +7,15 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using System.Collections.Generic; using System.Linq; +using osu.Framework.Allocation; namespace osu.Game.Overlays.Settings { public abstract class SettingsSubsection : FillFlowContainer, IHasFilterableChildren { - protected override Container Content => content; + protected override Container Content => FlowContent; - private readonly Container content; + protected readonly FillFlowContainer FlowContent; protected abstract string Header { get; } @@ -33,6 +34,19 @@ namespace osu.Game.Overlays.Settings RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Direction = FillDirection.Vertical; + + FlowContent = new FillFlowContainer + { + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + } + + [BackgroundDependencyLoader] + private void load() + { AddRangeInternal(new Drawable[] { new OsuSpriteText @@ -41,13 +55,7 @@ namespace osu.Game.Overlays.Settings Margin = new MarginPadding { Bottom = 10 }, Font = @"Exo2.0-Black", }, - content = new FillFlowContainer - { - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 5), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, + FlowContent }); } } From c1860f2ce21450801151fea1bc408890d2fcf566 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:49:30 +0900 Subject: [PATCH 161/180] Make KeyBindingOverlay support variants as settings sub sections. --- .../KeyBinding/GlobalKeyBindingsSection.cs | 24 ++++++++++++------ ...ngsSection.cs => KeyBindingsSubsection.cs} | 25 ++++++++----------- .../KeyBinding/RulesetBindingsSection.cs | 16 ++++++++---- .../KeyBinding/VariantBindingsSubsection.cs | 23 +++++++++++++++++ osu.Game/Overlays/KeyBindingOverlay.cs | 2 +- osu.Game/osu.Game.csproj | 3 ++- 6 files changed, 63 insertions(+), 30 deletions(-) rename osu.Game/Overlays/KeyBinding/{KeyBindingsSection.cs => KeyBindingsSubsection.cs} (57%) create mode 100644 osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 7dd9919e5d..77de9fc865 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -3,21 +3,29 @@ using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Overlays.Settings; namespace osu.Game.Overlays.KeyBinding { - public class GlobalKeyBindingsSection : KeyBindingsSection + public class GlobalKeyBindingsSection : SettingsSection { - private readonly string name; + public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override string Header => "Global"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => name; - - public GlobalKeyBindingsSection(KeyBindingInputManager manager, string name) + public GlobalKeyBindingsSection(KeyBindingInputManager manager) { - this.name = name; + Add(new DefaultBindingsSubsection(manager)); + } - Defaults = manager.DefaultKeyBindings; + private class DefaultBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => string.Empty; + + public DefaultBindingsSubsection(KeyBindingInputManager manager) + : base(0) + { + Defaults = manager.DefaultKeyBindings; + } } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs similarity index 57% rename from osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs rename to osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 44c28ee9c8..9bbbf539c5 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -12,38 +11,34 @@ using OpenTK; namespace osu.Game.Overlays.KeyBinding { - public abstract class KeyBindingsSection : SettingsSection + public abstract class KeyBindingsSubsection : SettingsSubsection { protected IEnumerable Defaults; protected RulesetInfo Ruleset; - protected KeyBindingsSection() + private readonly int variant; + + protected KeyBindingsSubsection(int variant) { + this.variant = variant; + FlowContent.Spacing = new Vector2(0, 1); } [BackgroundDependencyLoader] private void load(KeyBindingStore store) { - var enumType = Defaults?.FirstOrDefault()?.Action?.GetType(); - - if (enumType == null) return; - - // for now let's just assume a variant of zero. - // this will need to be implemented in a better way in the future. - int? variant = null; - if (Ruleset != null) - variant = 0; - var bindings = store.Query(Ruleset?.ID, variant); - foreach (Enum v in Enum.GetValues(enumType)) + foreach (var defaultBinding in Defaults) + { // one row per valid action. - Add(new KeyBindingRow(v, bindings.Where(b => b.Action.Equals((int)(object)v))) + Add(new KeyBindingRow(defaultBinding.Action, bindings.Where(b => b.Action.Equals((int)defaultBinding.Action))) { AllowMainMouseButtons = Ruleset != null }); + } } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs index 20941115e3..885e149cb2 100644 --- a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs @@ -2,20 +2,26 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; +using osu.Game.Overlays.Settings; using osu.Game.Rulesets; namespace osu.Game.Overlays.KeyBinding { - public class RulesetBindingsSection : KeyBindingsSection + public class RulesetBindingsSection : SettingsSection { - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Header => Ruleset.Name; + public override FontAwesome Icon => FontAwesome.fa_osu_hot; + public override string Header => ruleset.Name; + + private readonly RulesetInfo ruleset; public RulesetBindingsSection(RulesetInfo ruleset) { - Ruleset = ruleset; + this.ruleset = ruleset; - Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(); + var r = ruleset.CreateInstance(); + + foreach (var variant in r.AvailableVariants) + Add(new VariantBindingsSubsection(ruleset, variant)); } } } \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs new file mode 100644 index 0000000000..f58cb632de --- /dev/null +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets; + +namespace osu.Game.Overlays.KeyBinding +{ + public class VariantBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => variant > 0 ? $"Variant: {variant}" : string.Empty; + + private readonly int variant; + + public VariantBindingsSubsection(RulesetInfo ruleset, int variant) + : base(variant) + { + this.variant = variant; + + Ruleset = ruleset; + Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(variant); + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 827d361099..72c653030c 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader(permitNulls: true)] private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global) { - AddSection(new GlobalKeyBindingsSection(global, "Global")); + AddSection(new GlobalKeyBindingsSection(global)); foreach (var ruleset in rulesets.AllRulesets) AddSection(new RulesetBindingsSection(ruleset)); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 11b99c1796..32a8df6357 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -105,9 +105,10 @@ - + + From 0e41fc8842d3c870c47acd046868d3bd948417c0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 12:49:50 +0900 Subject: [PATCH 162/180] Add mania bindings. --- osu.Game.Rulesets.Mania/ManiaInputManager.cs | 26 +++++++++++-- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 37 +++++++++++++++++++ .../UI/ManiaRulesetContainer.cs | 2 +- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index b608e4d8d6..0fac1bef10 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.UI; @@ -8,14 +9,33 @@ namespace osu.Game.Rulesets.Mania { public class ManiaInputManager : RulesetInputManager { - public ManiaInputManager(RulesetInfo ruleset) - : base(ruleset, 0, SimultaneousBindingMode.Unique) + public ManiaInputManager(RulesetInfo ruleset, int variant) + : base(ruleset, variant, SimultaneousBindingMode.Unique) { } } public enum ManiaAction { - // placeholder + [Description("Key 1")] + Key1, + [Description("Key 2")] + Key2, + [Description("Key 3")] + Key3, + [Description("Key 4")] + Key4, + [Description("Key 5")] + Key5, + [Description("Key 6")] + Key6, + [Description("Key 7")] + Key7, + [Description("Key 8")] + Key8, + [Description("Key 9")] + Key9, + [Description("Special")] + Special } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index c7809f83ed..f073d5a04c 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; +using osu.Framework.Input.Bindings; using osu.Game.Graphics; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Scoring; @@ -120,5 +121,41 @@ namespace osu.Game.Rulesets.Mania : base(rulesetInfo) { } + + public override IEnumerable AvailableVariants => new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + public override IEnumerable GetDefaultKeyBindings(int variant = 0) + { + var leftKeys = new[] + { + InputKey.A, + InputKey.S, + InputKey.D, + InputKey.F + }; + + var rightKeys = new[] + { + InputKey.J, + InputKey.K, + InputKey.L, + InputKey.Semicolon + }; + + ManiaAction currentKey = ManiaAction.Key1; + + var bindings = new List(); + + for (int i = 0; i < variant / 2; i++) + bindings.Add(new KeyBinding(leftKeys[leftKeys.Length - 1 - i], currentKey++)); + + for (int i = 0; i < variant / 2; i++) + bindings.Add(new KeyBinding(rightKeys[i], currentKey++)); + + if (variant % 2 == 1) + bindings.Add(new KeyBinding(InputKey.Space, ManiaAction.Special)); + + return bindings; + } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 0e750a348e..782fa5f69e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); - public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo); + public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, availableColumns); protected override BeatmapConverter CreateBeatmapConverter() { From 84dd1283dec2e73b1c96d6deabd9ed1906156532 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 13:39:51 +0900 Subject: [PATCH 163/180] Fix nullref. --- osu.Game/Rulesets/UI/RulesetContainer.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index ebf570fecc..7fed5c2225 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -249,7 +249,7 @@ namespace osu.Game.Rulesets.UI public Playfield Playfield { get; private set; } protected override Container Content => content; - private readonly Container content; + private Container content; private readonly List> drawableObjects = new List>(); @@ -261,6 +261,11 @@ namespace osu.Game.Rulesets.UI /// Whether to assume the beatmap is for the current ruleset. protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) + { + } + + [BackgroundDependencyLoader] + private void load() { InputManager.Add(content = new Container { @@ -269,11 +274,6 @@ namespace osu.Game.Rulesets.UI }); AddInternal(InputManager); - } - - [BackgroundDependencyLoader] - private void load() - { KeyBindingInputManager.Add(Playfield = CreatePlayfield()); loadObjects(); From d8dfcc614a4a182da84be71f6ca579cc79804abc Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 13:42:11 +0900 Subject: [PATCH 164/180] Make mania work with key bindings --- .../Visual/TestCaseManiaHitObjects.cs | 7 +- .../Visual/TestCaseManiaPlayfield.cs | 178 +++++++++--------- .../Objects/Drawables/DrawableHoldNote.cs | 51 +++-- .../Drawables/DrawableManiaHitObject.cs | 10 +- .../Objects/Drawables/DrawableNote.cs | 22 +-- osu.Game.Rulesets.Mania/UI/Column.cs | 34 ++-- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 25 +-- .../UI/ManiaRulesetContainer.cs | 8 +- 8 files changed, 146 insertions(+), 189 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs b/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs index 7dcc48c778..76235bbf19 100644 --- a/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs +++ b/osu.Desktop.Tests/Visual/TestCaseManiaHitObjects.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using OpenTK; @@ -40,8 +41,8 @@ namespace osu.Desktop.Tests.Visual RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableNote(new Note { StartTime = 5000 }) { AccentColour = Color4.Red }, - new DrawableNote(new Note { StartTime = 6000 }) { AccentColour = Color4.Red } + new DrawableNote(new Note { StartTime = 5000 }, ManiaAction.Key1) { AccentColour = Color4.Red }, + new DrawableNote(new Note { StartTime = 6000 }, ManiaAction.Key1) { AccentColour = Color4.Red } } } } @@ -66,7 +67,7 @@ namespace osu.Desktop.Tests.Visual { StartTime = 5000, Duration = 1000 - }) { AccentColour = Color4.Red } + }, ManiaAction.Key1) { AccentColour = Color4.Red } } } } diff --git a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs index ed0e5d81e9..c52594930e 100644 --- a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs @@ -3,109 +3,34 @@ using System; using System.Linq; -using osu.Framework.Configuration; +using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; -using osu.Framework.Input; using osu.Framework.Timing; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Timing; using OpenTK; -using OpenTK.Input; +using osu.Game.Rulesets; namespace osu.Desktop.Tests.Visual { internal class TestCaseManiaPlayfield : OsuTestCase { + private const double start_time = 500; + private const double duration = 500; + public override string Description => @"Mania playfield"; protected override double TimePerAction => 200; + private RulesetInfo maniaRuleset; + public TestCaseManiaPlayfield() { - Action createPlayfield = (cols, pos) => - { - Clear(); - Add(new ManiaPlayfield(cols) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - SpecialColumnPosition = pos, - Scale = new Vector2(1, -1) - }); - }; - - const double start_time = 500; - const double duration = 500; - - Func createTimingChange = (time, gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) - { - TimingPoint = { BeatLength = 1000 } - }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); - - Action createPlayfieldWithNotes = gravity => - { - Clear(); - - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; - - ManiaPlayfield playField; - Add(playField = new ManiaPlayfield(4) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Scale = new Vector2(1, -1), - Clock = new FramedClock(rateAdjustClock) - }); - - if (!gravity) - playField.Columns.ForEach(c => c.Add(createTimingChange(0, false))); - - for (double t = start_time; t <= start_time + duration; t += 100) - { - if (gravity) - playField.Columns.ElementAt(0).Add(createTimingChange(t, true)); - - playField.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 0 - }, new Bindable(Key.D))); - - if (gravity) - playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); - - playField.Add(new DrawableNote(new Note - { - StartTime = t, - Column = 3 - }, new Bindable(Key.K))); - } - - if (gravity) - playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - - playField.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 1 - }, new Bindable(Key.F))); - - if (gravity) - playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - - playField.Add(new DrawableHoldNote(new HoldNote - { - StartTime = start_time, - Duration = duration, - Column = 2 - }, new Bindable(Key.J))); - }; - AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal)); AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal)); AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left)); @@ -122,21 +47,94 @@ namespace osu.Desktop.Tests.Visual AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction)); } - private void triggerKeyDown(Column column) + [BackgroundDependencyLoader] + private void load(RulesetStore rulesets) { - column.TriggerOnKeyDown(new InputState(), new KeyDownEventArgs + maniaRuleset = rulesets.GetRuleset(3); + } + + private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) + { + TimingPoint = { BeatLength = 1000 } + }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); + + private void createPlayfield(int cols, SpecialColumnPosition specialPos) + { + Clear(); + + var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both }; + Add(inputManager); + + inputManager.Add(new ManiaPlayfield(cols) { - Key = column.Key, - Repeat = false + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + SpecialColumnPosition = specialPos, + Scale = new Vector2(1, -1) }); } - private void triggerKeyUp(Column column) + private void createPlayfieldWithNotes(bool gravity) { - column.TriggerOnKeyUp(new InputState(), new KeyUpEventArgs + Clear(); + + var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; + + var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both }; + Add(inputManager); + + ManiaPlayfield playField; + inputManager.Add(playField = new ManiaPlayfield(4) { - Key = column.Key + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scale = new Vector2(1, -1), + Clock = new FramedClock(rateAdjustClock) }); + + if (!gravity) + playField.Columns.ForEach(c => c.Add(createTimingChange(0, false))); + + for (double t = start_time; t <= start_time + duration; t += 100) + { + if (gravity) + playField.Columns.ElementAt(0).Add(createTimingChange(t, true)); + + playField.Add(new DrawableNote(new Note + { + StartTime = t, + Column = 0 + }, ManiaAction.Key1)); + + if (gravity) + playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); + + playField.Add(new DrawableNote(new Note + { + StartTime = t, + Column = 3 + }, ManiaAction.Key4)); + } + + if (gravity) + playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); + + playField.Add(new DrawableHoldNote(new HoldNote + { + StartTime = start_time, + Duration = duration, + Column = 1 + }, ManiaAction.Key2)); + + if (gravity) + playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); + + playField.Add(new DrawableHoldNote(new HoldNote + { + StartTime = start_time, + Duration = duration, + Column = 2 + }, ManiaAction.Key3)); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 17b0b0a607..e06f71cb64 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -5,20 +5,18 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using osu.Framework.Configuration; -using OpenTK.Input; -using osu.Framework.Input; using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Mania.Objects.Drawables { /// /// Visualises a hit object. /// - public class DrawableHoldNote : DrawableManiaHitObject + public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { private readonly DrawableNote head; private readonly DrawableNote tail; @@ -36,8 +34,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// private bool hasBroken; - public DrawableHoldNote(HoldNote hitObject, Bindable key = null) - : base(hitObject, key) + public DrawableHoldNote(HoldNote hitObject, ManiaAction action) + : base(hitObject, action) { RelativeSizeAxes = Axes.Both; Height = (float)HitObject.Duration; @@ -58,12 +56,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), RelativeChildSize = new Vector2(1, (float)HitObject.Duration) }, - head = new DrawableHeadNote(this, key) + head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, - tail = new DrawableTailNote(this, key) + tail = new DrawableTailNote(this, action) { Anchor = Anchor.BottomCentre, Origin = Anchor.TopCentre @@ -106,16 +104,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(ManiaAction action) { - // Make sure the keypress happened within the body of the hold note + // Make sure the action happened within the body of the hold note if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime) return false; - if (args.Key != Key) - return false; - - if (args.Repeat) + if (action != Action) return false; // The user has pressed during the body of the hold note, after the head note and its hit windows have passed @@ -126,13 +121,13 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public bool OnReleased(ManiaAction action) { // Make sure that the user started holding the key during the hold note if (!holdStartTime.HasValue) return false; - if (args.Key != Key) + if (action != Action) return false; holdStartTime = null; @@ -151,8 +146,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { private readonly DrawableHoldNote holdNote; - public DrawableHeadNote(DrawableHoldNote holdNote, Bindable key = null) - : base(holdNote.HitObject.Head, key) + public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action) + : base(holdNote.HitObject.Head, action) { this.holdNote = holdNote; @@ -160,9 +155,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Y = 0; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public override bool OnPressed(ManiaAction action) { - if (!base.OnKeyDown(state, args)) + if (!base.OnPressed(action)) return false; // We only want to trigger a holding state from the head if the head has received a judgement @@ -188,8 +183,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { private readonly DrawableHoldNote holdNote; - public DrawableTailNote(DrawableHoldNote holdNote, Bindable key = null) - : base(holdNote.HitObject.Tail, key) + public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action) + : base(holdNote.HitObject.Tail, action) { this.holdNote = holdNote; @@ -210,7 +205,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables tailJudgement.HasBroken = holdNote.hasBroken; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down + + public override bool OnReleased(ManiaAction action) { // Make sure that the user started holding the key during the hold note if (!holdNote.holdStartTime.HasValue) @@ -219,7 +216,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (Judgement.Result != HitResult.None) return false; - if (args.Key != Key) + if (action != Action) return false; UpdateJudgement(true); @@ -227,12 +224,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // Handled by the hold note, which will set holding = false return false; } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - // Tail doesn't handle key down - return false; - } } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 10dc607ec3..bfef05ea07 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; -using OpenTK.Input; -using osu.Framework.Configuration; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Drawables; @@ -15,17 +13,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// The key that will trigger input for this hit object. /// - protected Bindable Key { get; private set; } = new Bindable(); + protected ManiaAction Action { get; } public new TObject HitObject; - protected DrawableManiaHitObject(TObject hitObject, Bindable key = null) + protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { HitObject = hitObject; - if (key != null) - Key.BindTo(key); + if (action != null) + Action = action.Value; } public override Color4 AccentColour diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 9322fed3eb..c201ab7bd0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -3,10 +3,8 @@ using System; using OpenTK.Graphics; -using OpenTK.Input; -using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Framework.Input; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Objects.Drawables; @@ -16,12 +14,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// /// Visualises a hit object. /// - public class DrawableNote : DrawableManiaHitObject + public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { private readonly NotePiece headPiece; - public DrawableNote(Note hitObject, Bindable key = null) - : base(hitObject, key) + public DrawableNote(Note hitObject, ManiaAction action) + : base(hitObject, action) { RelativeSizeAxes = Axes.X; Height = 100; @@ -81,18 +79,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public virtual bool OnPressed(ManiaAction action) { - if (Judgement.Result != HitResult.None) - return false; - - if (args.Key != Key) - return false; - - if (args.Repeat) + if (action != Action) return false; return UpdateJudgement(true); } + + public virtual bool OnReleased(ManiaAction action) => false; } } diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 9fbc9ba5e7..a8f5b4919d 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -3,17 +3,15 @@ using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Colour; -using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; -using osu.Framework.Configuration; +using osu.Framework.Input.Bindings; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Judgements; @@ -32,10 +30,7 @@ namespace osu.Game.Rulesets.Mania.UI private const float column_width = 45; private const float special_column_width = 70; - /// - /// The key that will trigger input actions for this column and hit objects contained inside it. - /// - public Bindable Key = new Bindable(); + public ManiaAction Action; private readonly Box background; private readonly Container hitTargetBar; @@ -101,8 +96,8 @@ namespace osu.Game.Rulesets.Mania.UI // For column lighting, we need to capture input events before the notes new InputTarget { - KeyDown = onKeyDown, - KeyUp = onKeyUp + Pressed = onPressed, + Released = onReleased } } }, @@ -199,12 +194,9 @@ namespace osu.Game.Rulesets.Mania.UI HitObjects.Add(hitObject); } - private bool onKeyDown(InputState state, KeyDownEventArgs args) + private bool onPressed(ManiaAction action) { - if (args.Repeat) - return false; - - if (args.Key == Key) + if (action == Action) { background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint); keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint); @@ -213,9 +205,9 @@ namespace osu.Game.Rulesets.Mania.UI return false; } - private bool onKeyUp(InputState state, KeyUpEventArgs args) + private bool onReleased(ManiaAction action) { - if (args.Key == Key) + if (action == Action) { background.FadeTo(0.2f, 800, Easing.OutQuart); keyIcon.ScaleTo(1f, 400, Easing.OutQuart); @@ -227,10 +219,10 @@ namespace osu.Game.Rulesets.Mania.UI /// /// This is a simple container which delegates various input events that have to be captured before the notes. /// - private class InputTarget : Container + private class InputTarget : Container, IKeyBindingHandler { - public Func KeyDown; - public Func KeyUp; + public Func Pressed; + public Func Released; public InputTarget() { @@ -239,8 +231,8 @@ namespace osu.Game.Rulesets.Mania.UI Alpha = 0; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => KeyDown?.Invoke(state, args) ?? false; - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => KeyUp?.Invoke(state, args) ?? false; + public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false; + public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false; } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 0c9351cad2..be14585354 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -122,12 +122,16 @@ namespace osu.Game.Rulesets.Mania.UI } }; + var currentAction = ManiaAction.Key1; for (int i = 0; i < columnCount; i++) { var c = new Column(); c.Reversed.BindTo(Reversed); c.VisibleTimeRange.BindTo(VisibleTimeRange); + c.IsSpecial = isSpecialColumn(i); + c.Action = c.IsSpecial ? ManiaAction.Special : currentAction++; + columns.Add(c); AddNested(c); } @@ -145,15 +149,11 @@ namespace osu.Game.Rulesets.Mania.UI specialColumnColour = colours.BlueDark; // Set the special column + colour + key - for (int i = 0; i < columnCount; i++) + foreach (var column in Columns) { - Column column = Columns.ElementAt(i); - column.IsSpecial = isSpecialColumn(i); - if (!column.IsSpecial) continue; - column.Key.Value = Key.Space; column.AccentColour = specialColumnColour; } @@ -167,21 +167,6 @@ namespace osu.Game.Rulesets.Mania.UI nonSpecialColumns[i].AccentColour = colour; nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour; } - - // We'll set the keys for non-special columns in another separate loop because it's not mirrored like the above colours - // Todo: This needs to go when we get to bindings and use Button1, ..., ButtonN instead - for (int i = 0; i < nonSpecialColumns.Count; i++) - { - Column column = nonSpecialColumns[i]; - - int keyOffset = default_keys.Length / 2 - nonSpecialColumns.Count / 2 + i; - if (keyOffset >= 0 && keyOffset < default_keys.Length) - column.Key.Value = default_keys[keyOffset]; - else - // There is no default key defined for this column. Let's set this to Unknown for now - // however note that this will be gone after bindings are in place - column.Key.Value = Key.Unknown; - } } /// diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 782fa5f69e..5a3da6d074 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -5,9 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenTK; -using OpenTK.Input; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -109,15 +107,15 @@ namespace osu.Game.Rulesets.Mania.UI protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { - Bindable key = Playfield.Columns.ElementAt(h.Column).Key; + ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action; var holdNote = h as HoldNote; if (holdNote != null) - return new DrawableHoldNote(holdNote, key); + return new DrawableHoldNote(holdNote, action); var note = h as Note; if (note != null) - return new DrawableNote(note, key); + return new DrawableNote(note, action); return null; } From 68e7cf854f8798568379d1d78a434588cafa4dd5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 14:19:14 +0900 Subject: [PATCH 165/180] Add variant names. --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 2 ++ .../KeyBinding/VariantBindingsSubsection.cs | 13 +++++++------ osu.Game/Rulesets/Ruleset.cs | 7 +++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index f073d5a04c..6c356195b2 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -157,5 +157,7 @@ namespace osu.Game.Rulesets.Mania return bindings; } + + public override string GetVariantName(int variant) => $"{variant}K"; } } diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs index f58cb632de..dca5f53b4a 100644 --- a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -7,17 +7,18 @@ namespace osu.Game.Overlays.KeyBinding { public class VariantBindingsSubsection : KeyBindingsSubsection { - protected override string Header => variant > 0 ? $"Variant: {variant}" : string.Empty; - - private readonly int variant; + protected override string Header => variantName; + private readonly string variantName; public VariantBindingsSubsection(RulesetInfo ruleset, int variant) : base(variant) { - this.variant = variant; - Ruleset = ruleset; - Defaults = ruleset.CreateInstance().GetDefaultKeyBindings(variant); + + var rulesetInstance = ruleset.CreateInstance(); + + variantName = rulesetInstance.GetVariantName(variant); + Defaults = rulesetInstance.GetDefaultKeyBindings(variant); } } } \ No newline at end of file diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 32d958b462..c54aeb7852 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -63,5 +63,12 @@ namespace osu.Game.Rulesets /// A variant. /// A list of valid s. public virtual IEnumerable GetDefaultKeyBindings(int variant = 0) => new KeyBinding[] { }; + + /// + /// Gets the name for a key binding variant. This is used for display in the settings overlay. + /// + /// The variant. + /// A descriptive name of the variant. + public virtual string GetVariantName(int variant) => string.Empty; } } From e777ccc3398a155b33423bf3f056d8d075142368 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 14:38:26 +0900 Subject: [PATCH 166/180] Avoid threading conflicts when resetting the database in unit tests --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index ecaf0db096..eb456d7a63 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -13,7 +13,6 @@ using osu.Framework.Platform; using osu.Game.IPC; using osu.Framework.Allocation; using osu.Game.Beatmaps; -using osu.Game.Rulesets; namespace osu.Game.Tests.Beatmaps.IO { @@ -98,16 +97,14 @@ namespace osu.Game.Tests.Beatmaps.IO private OsuGameBase loadOsu(GameHost host) { + host.Storage.DeleteDatabase(@"client"); + var osu = new OsuGameBase(); Task.Run(() => host.Run(osu)); while (!osu.IsLoaded) Thread.Sleep(1); - //reset beatmap database (sqlite and storage backing) - osu.Dependencies.Get().Reset(); - osu.Dependencies.Get().Reset(); - return osu; } From 751bd3432e3dc4dee25bbb097a7dc019619d53dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 14:48:58 +0900 Subject: [PATCH 167/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 74f644bad0..e2d41820b3 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 74f644bad039606e242d8782014d8c249a38b6a3 +Subproject commit e2d41820b3795d97f8510a18fad5e42caeb23f0a From 0c60563fda957d7efc27fd0b62a6b8a592d9ef62 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 15:24:08 +0900 Subject: [PATCH 168/180] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 1fd9259e86..e2d41820b3 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1fd9259e86379838dbbc43c12a2238df83800fc0 +Subproject commit e2d41820b3795d97f8510a18fad5e42caeb23f0a From 7639e096d865cb044186df0fc4ca4d085b4e9d5c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 15:30:17 +0900 Subject: [PATCH 169/180] No longer flip legacy replay mouse positions. --- osu.Game/Rulesets/Scoring/ScoreStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index c6421522b4..c06d31e38f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -137,7 +137,7 @@ namespace osu.Game.Rulesets.Scoring frames.Add(new ReplayFrame( lastTime, float.Parse(split[1]), - 384 - float.Parse(split[2]), + float.Parse(split[2]), (ReplayButtonState)int.Parse(split[3]) )); } From 4395ea3850baaf67047cc910c4e60a028e76af5c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 15:37:22 +0900 Subject: [PATCH 170/180] Add applied suggestions. --- osu.Game.Rulesets.Mania/ManiaInputManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index 0fac1bef10..a574bc75ec 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -17,8 +17,10 @@ namespace osu.Game.Rulesets.Mania public enum ManiaAction { + [Description("Special")] + Special, [Description("Key 1")] - Key1, + Key1 = 10, [Description("Key 2")] Key2, [Description("Key 3")] @@ -34,8 +36,6 @@ namespace osu.Game.Rulesets.Mania [Description("Key 8")] Key8, [Description("Key 9")] - Key9, - [Description("Special")] - Special + Key9 } } From bdd0a51c6e178ca0ccac027087f8f576037513f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 16:10:10 +0900 Subject: [PATCH 171/180] Fix left keys setting defaults in incorrect order --- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 6c356195b2..ed46da4f85 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -146,8 +146,8 @@ namespace osu.Game.Rulesets.Mania var bindings = new List(); - for (int i = 0; i < variant / 2; i++) - bindings.Add(new KeyBinding(leftKeys[leftKeys.Length - 1 - i], currentKey++)); + for (int i = leftKeys.Length - variant / 2; i < leftKeys.Length; i++) + bindings.Add(new KeyBinding(leftKeys[i], currentKey++)); for (int i = 0; i < variant / 2; i++) bindings.Add(new KeyBinding(rightKeys[i], currentKey++)); From efdd5eb152d532adeed652e8d63f8b930b5331f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 16:10:31 +0900 Subject: [PATCH 172/180] Fix global key bindings being fetched with a non-null variant --- osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs | 2 +- osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 77de9fc865..8ebd4ac545 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.KeyBinding protected override string Header => string.Empty; public DefaultBindingsSubsection(KeyBindingInputManager manager) - : base(0) + : base(null) { Defaults = manager.DefaultKeyBindings; } diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 9bbbf539c5..38a5b1a171 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -17,9 +17,9 @@ namespace osu.Game.Overlays.KeyBinding protected RulesetInfo Ruleset; - private readonly int variant; + private readonly int? variant; - protected KeyBindingsSubsection(int variant) + protected KeyBindingsSubsection(int? variant) { this.variant = variant; From 42e6865493f3e87f9b1be8659d8f074b42e92b0c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 15:35:31 +0900 Subject: [PATCH 173/180] Flip hit objects. --- osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index 3b0cfc1ef1..6bc9f868ac 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -7,8 +7,12 @@ using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using System; +using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; +using OpenTK; namespace osu.Game.Rulesets.Osu.Mods { @@ -28,10 +32,23 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1.06; } - public class OsuModHardRock : ModHardRock + public class OsuModHardRock : ModHardRock, IApplicableMod { public override double ScoreMultiplier => 1.06; public override bool Ranked => true; + + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + { + rulesetContainer.Objects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, 384 - h.Y)); + rulesetContainer.Objects.OfType().ForEach(s => + { + var newControlPoints = new List(); + s.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, 384 - c.Y))); + + s.ControlPoints = newControlPoints; + s.Curve?.Calculate(); // Recalculate the slider curve + }); + } } public class OsuModSuddenDeath : ModSuddenDeath From 8ddc13e394fdaa355152f9067c0790d3f09fba8a Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 16:48:13 +0900 Subject: [PATCH 174/180] Fix replays not loading. --- osu.Game/Rulesets/UI/RulesetContainer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 2f1cb915f3..8a12286bc6 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI /// Sets a replay to be used, overriding local input. /// /// The replay, null for local input. - public void SetReplay(Replay replay) + public virtual void SetReplay(Replay replay) { Replay = replay; InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; @@ -272,6 +272,11 @@ namespace osu.Game.Rulesets.UI KeyBindingInputManager.Add(Playfield = CreatePlayfield()); loadObjects(); + } + + public override void SetReplay(Replay replay) + { + base.SetReplay(replay); if (InputManager?.ReplayInputHandler != null) InputManager.ReplayInputHandler.ToScreenSpace = Playfield.ScaledContent.ToScreenSpace; From 1972b78cb13d8bea10d7392bd4a63be6efef1a92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 15:28:33 +0900 Subject: [PATCH 175/180] Make OsuTestCases use new non-realtime option --- osu.Desktop.Tests/Visual/OsuTestCase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop.Tests/Visual/OsuTestCase.cs b/osu.Desktop.Tests/Visual/OsuTestCase.cs index e54f7dbeb5..e366aecb21 100644 --- a/osu.Desktop.Tests/Visual/OsuTestCase.cs +++ b/osu.Desktop.Tests/Visual/OsuTestCase.cs @@ -14,7 +14,7 @@ namespace osu.Desktop.Tests.Visual [Test] public override void RunTest() { - using (var host = new HeadlessGameHost()) + using (var host = new HeadlessGameHost(realtime: false)) host.Run(new OsuTestCaseTestRunner(this)); } From 022063f15766d147690f32180254cae5e806d33b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 16:51:09 +0900 Subject: [PATCH 176/180] Update framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index e2d41820b3..1ba1e8ef1e 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit e2d41820b3795d97f8510a18fad5e42caeb23f0a +Subproject commit 1ba1e8ef1e5ec0466632be02492023a081cb85ab From 56292bd7f0b1ee64a5fe7d24af2f36f47d1c98c1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 16:54:06 +0900 Subject: [PATCH 177/180] Use constant definition. --- osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index 6bc9f868ac..432c6d391c 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using OpenTK; @@ -39,11 +40,11 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) { - rulesetContainer.Objects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, 384 - h.Y)); + rulesetContainer.Objects.OfType().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Y)); rulesetContainer.Objects.OfType().ForEach(s => { var newControlPoints = new List(); - s.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, 384 - c.Y))); + s.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y))); s.ControlPoints = newControlPoints; s.Curve?.Calculate(); // Recalculate the slider curve From e9dde822a1c29b5cb160965116b895c4ac3baa93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 19:25:40 +0900 Subject: [PATCH 178/180] Expose triangles in OsuButton for further customisation --- osu.Game/Graphics/UserInterface/OsuButton.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 5650fc6f48..abc1b036bc 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -24,6 +24,8 @@ namespace osu.Game.Graphics.UserInterface private SampleChannel sampleClick; private SampleChannel sampleHover; + protected Triangles Triangles; + public OsuButton() { Height = 40; @@ -52,7 +54,7 @@ namespace osu.Game.Graphics.UserInterface AddRange(new Drawable[] { - new Triangles + Triangles = new Triangles { RelativeSizeAxes = Axes.Both, ColourDark = colours.BlueDarker, @@ -120,4 +122,4 @@ namespace osu.Game.Graphics.UserInterface } } } -} \ No newline at end of file +} From c99ed6fd440fa88906c13757fa9b08f381041083 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Aug 2017 19:26:49 +0900 Subject: [PATCH 179/180] Add reset button Also fixes a regression causing multiple rows to be displayed for a single action --- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 13 +++++++ .../KeyBinding/KeyBindingsSubsection.cs | 36 ++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index c182382d70..ee997a2185 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -109,6 +109,17 @@ namespace osu.Game.Overlays.KeyBinding buttons.Add(new KeyButton(b)); } + public void RestoreDefaults() + { + int i = 0; + foreach (var d in Defaults) + { + var button = buttons[i++]; + button.UpdateKeyCombination(d); + store.Update(button.KeyBinding); + } + } + protected override bool OnHover(InputState state) { this.FadeEdgeEffectTo(1, transition_time, Easing.OutQuint); @@ -129,6 +140,8 @@ namespace osu.Game.Overlays.KeyBinding public bool AllowMainMouseButtons; + public IEnumerable Defaults; + private bool isModifier(Key k) => k < Key.F1; protected override bool OnClick(InputState state) => true; diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index 38a5b1a171..bd69403831 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -4,10 +4,14 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Overlays.Settings; using osu.Game.Rulesets; using OpenTK; +using osu.Game.Graphics; namespace osu.Game.Overlays.KeyBinding { @@ -31,14 +35,38 @@ namespace osu.Game.Overlays.KeyBinding { var bindings = store.Query(Ruleset?.ID, variant); - foreach (var defaultBinding in Defaults) + foreach (var defaultGroup in Defaults.GroupBy(d => d.Action)) { // one row per valid action. - Add(new KeyBindingRow(defaultBinding.Action, bindings.Where(b => b.Action.Equals((int)defaultBinding.Action))) + Add(new KeyBindingRow(defaultGroup.Key, bindings.Where(b => b.Action.Equals((int)defaultGroup.Key))) { - AllowMainMouseButtons = Ruleset != null + AllowMainMouseButtons = Ruleset != null, + Defaults = defaultGroup.Select(d => d.KeyCombination) }); } + + Add(new ResetButton + { + Action = () => Children.OfType().ForEach(k => k.RestoreDefaults()) + }); } } -} \ No newline at end of file + + internal class ResetButton : OsuButton + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Text = "Reset"; + RelativeSizeAxes = Axes.X; + Margin = new MarginPadding { Top = 5 }; + Height = 20; + + Content.CornerRadius = 5; + + BackgroundColour = colours.PinkDark; + Triangles.ColourDark = colours.PinkDarker; + Triangles.ColourLight = colours.Pink; + } + } +} From 115e5c95aff64557c8c900a76feaa0dac8061e09 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 23 Aug 2017 20:50:03 +0900 Subject: [PATCH 180/180] Make ScrollingPlayfield.Reversed protected; make ManiaPlayfield 'invertible'. --- .../Visual/TestCaseManiaPlayfield.cs | 45 ++++++++++--------- .../Visual/TestCaseScrollingPlayfield.cs | 6 ++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 17 ++++++- osu.Game/Rulesets/UI/ScrollingPlayfield.cs | 4 +- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs index c52594930e..fb14bdb3bf 100644 --- a/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseManiaPlayfield.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; @@ -13,7 +12,6 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Timing; -using OpenTK; using osu.Game.Rulesets; namespace osu.Desktop.Tests.Visual @@ -39,12 +37,12 @@ namespace osu.Desktop.Tests.Visual AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal)); AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left)); AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right)); + AddStep("Reversed", () => createPlayfield(4, SpecialColumnPosition.Normal, true)); AddStep("Notes with input", () => createPlayfieldWithNotes(false)); - AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction)); - + AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(false, true)); AddStep("Notes with gravity", () => createPlayfieldWithNotes(true)); - AddWaitStep((int)Math.Ceiling((start_time + duration) / TimePerAction)); + AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true, true)); } [BackgroundDependencyLoader] @@ -58,23 +56,25 @@ namespace osu.Desktop.Tests.Visual TimingPoint = { BeatLength = 1000 } }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); - private void createPlayfield(int cols, SpecialColumnPosition specialPos) + private void createPlayfield(int cols, SpecialColumnPosition specialPos, bool inverted = false) { Clear(); var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both }; Add(inputManager); - inputManager.Add(new ManiaPlayfield(cols) + ManiaPlayfield playfield; + inputManager.Add(playfield = new ManiaPlayfield(cols) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - SpecialColumnPosition = specialPos, - Scale = new Vector2(1, -1) + SpecialColumnPosition = specialPos }); + + playfield.Inverted.Value = inverted; } - private void createPlayfieldWithNotes(bool gravity) + private void createPlayfieldWithNotes(bool gravity, bool inverted = false) { Clear(); @@ -83,33 +83,34 @@ namespace osu.Desktop.Tests.Visual var inputManager = new ManiaInputManager(maniaRuleset, 4) { RelativeSizeAxes = Axes.Both }; Add(inputManager); - ManiaPlayfield playField; - inputManager.Add(playField = new ManiaPlayfield(4) + ManiaPlayfield playfield; + inputManager.Add(playfield = new ManiaPlayfield(4) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Scale = new Vector2(1, -1), Clock = new FramedClock(rateAdjustClock) }); + playfield.Inverted.Value = inverted; + if (!gravity) - playField.Columns.ForEach(c => c.Add(createTimingChange(0, false))); + playfield.Columns.ForEach(c => c.Add(createTimingChange(0, false))); for (double t = start_time; t <= start_time + duration; t += 100) { if (gravity) - playField.Columns.ElementAt(0).Add(createTimingChange(t, true)); + playfield.Columns.ElementAt(0).Add(createTimingChange(t, true)); - playField.Add(new DrawableNote(new Note + playfield.Add(new DrawableNote(new Note { StartTime = t, Column = 0 }, ManiaAction.Key1)); if (gravity) - playField.Columns.ElementAt(3).Add(createTimingChange(t, true)); + playfield.Columns.ElementAt(3).Add(createTimingChange(t, true)); - playField.Add(new DrawableNote(new Note + playfield.Add(new DrawableNote(new Note { StartTime = t, Column = 3 @@ -117,9 +118,9 @@ namespace osu.Desktop.Tests.Visual } if (gravity) - playField.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); + playfield.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - playField.Add(new DrawableHoldNote(new HoldNote + playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, Duration = duration, @@ -127,9 +128,9 @@ namespace osu.Desktop.Tests.Visual }, ManiaAction.Key2)); if (gravity) - playField.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); + playfield.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - playField.Add(new DrawableHoldNote(new HoldNote + playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, Duration = duration, diff --git a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs index c8c95da618..444adf6c24 100644 --- a/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs +++ b/osu.Desktop.Tests/Visual/TestCaseScrollingPlayfield.cs @@ -64,8 +64,8 @@ namespace osu.Desktop.Tests.Visual AddStep("Reverse direction", () => { - horizontalRulesetContainer.Playfield.Reversed.Toggle(); - verticalRulesetContainer.Playfield.Reversed.Toggle(); + horizontalRulesetContainer.Playfield.Reverse(); + verticalRulesetContainer.Playfield.Reverse(); }); } @@ -210,6 +210,8 @@ namespace osu.Desktop.Tests.Visual content = new Container { RelativeSizeAxes = Axes.Both } }; } + + public void Reverse() => Reversed.Toggle(); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index be14585354..d3dc920fc6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -14,6 +14,7 @@ using osu.Framework.Allocation; using OpenTK.Input; using System.Linq; using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Framework.Graphics.Shapes; @@ -45,6 +46,11 @@ namespace osu.Game.Rulesets.Mania.UI } } + /// + /// Whether this playfield should be inverted. This flips everything inside the playfield. + /// + public readonly Bindable Inverted = new Bindable(true); + private readonly FlowContainer columns; public IEnumerable Columns => columns.Children; @@ -64,6 +70,8 @@ namespace osu.Game.Rulesets.Mania.UI if (columnCount <= 0) throw new ArgumentException("Can't have zero or fewer columns."); + Inverted.Value = true; + InternalChildren = new Drawable[] { new Container @@ -126,7 +134,6 @@ namespace osu.Game.Rulesets.Mania.UI for (int i = 0; i < columnCount; i++) { var c = new Column(); - c.Reversed.BindTo(Reversed); c.VisibleTimeRange.BindTo(VisibleTimeRange); c.IsSpecial = isSpecialColumn(i); @@ -135,6 +142,14 @@ namespace osu.Game.Rulesets.Mania.UI columns.Add(c); AddNested(c); } + + Inverted.ValueChanged += invertedChanged; + Inverted.TriggerChange(); + } + + private void invertedChanged(bool newValue) + { + Scale = new Vector2(1, newValue ? -1 : 1); } [BackgroundDependencyLoader] diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs index 92845c3f3a..1d13e2abb1 100644 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs @@ -55,9 +55,9 @@ namespace osu.Game.Rulesets.UI }; /// - /// Whether to reverse the scrolling direction is reversed. + /// Whether to reverse the scrolling direction is reversed. Note that this does _not_ invert the hit objects. /// - public readonly BindableBool Reversed = new BindableBool(); + protected readonly BindableBool Reversed = new BindableBool(); /// /// The container that contains the s and s.