From 12de3f6657a277550ff07a36d4b5f9bfb907c881 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 13:56:14 +0900 Subject: [PATCH 001/250] Implement DrumRoll + DrumRollTick. --- osu.Game.Modes.Taiko/Objects/DrumRoll.cs | 121 ++++++++++++++++++ osu.Game.Modes.Taiko/Objects/DrumRollTick.cs | 21 +++ .../osu.Game.Modes.Taiko.csproj | 2 + 3 files changed, 144 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/DrumRoll.cs create mode 100644 osu.Game.Modes.Taiko/Objects/DrumRollTick.cs diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs new file mode 100644 index 0000000000..9ce2758d84 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs @@ -0,0 +1,121 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Samples; +using osu.Game.Modes.Objects.Types; +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps.Timing; +using osu.Game.Database; + +namespace osu.Game.Modes.Taiko.Objects +{ + public class DrumRoll : TaikoHitObject, IHasDistance + { + public double EndTime => StartTime + Distance / Velocity; + + public double Duration => EndTime - StartTime; + + /// + /// Raw length of the drum roll in positional length units. + /// + public double Distance { get; set; } + + /// + /// Velocity of the drum roll in positional length units per millisecond. + /// + public double Velocity; + + /// + /// The distance between ticks of this drumroll. + /// Half of this value is the hit window of the ticks. + /// + public double TickTimeDistance; + + /// + /// Number of drum roll ticks required for a "Good" hit. + /// + public double RequiredGoodHits; + + /// + /// Number of drum roll ticks required for a "Great" hit. + /// + public double RequiredGreatHits; + + /// + /// Total number of drum roll ticks. + /// + public int TotalTicks; + + /// + /// Initializes the drum roll ticks if not initialized and returns them. + /// + public IEnumerable Ticks + { + get + { + if (ticks == null) + createTicks(); + return ticks; + } + } + + private List ticks; + + public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) + { + base.ApplyDefaults(timing, difficulty); + + Velocity = (timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier) / 1000; + TickTimeDistance = timing.BeatLengthAt(StartTime); + + if (difficulty.SliderTickRate == 3) + TickTimeDistance /= 3; + else + TickTimeDistance /= 4; + + TotalTicks = Ticks.Count(); + RequiredGoodHits = TotalTicks * Math.Min(0.15, 0.05 + 0.10 / 6 * difficulty.OverallDifficulty); + RequiredGreatHits = TotalTicks * Math.Min(0.30, 0.10 + 0.20 / 6 * difficulty.OverallDifficulty); + } + + private void createTicks() + { + ticks = new List(); + + if (TickTimeDistance == 0) + return; + + bool first = true; + for (double t = StartTime; t < EndTime + (int)TickTimeDistance; t += TickTimeDistance) + { + ticks.Add(new DrumRollTick + { + FirstTick = first, + PreEmpt = PreEmpt, + TickTimeDistance = TickTimeDistance, + StartTime = t, + Sample = new HitSampleInfo + { + Type = SampleType.None, + Set = SampleSet.Soft + } + }); + + first = false; + } + } + + public override TaikoHitType Type + { + get + { + SampleType st = Sample?.Type ?? SampleType.None; + + return TaikoHitType.DrumRoll | ((st & SampleType.Finish) > 0 ? TaikoHitType.Finisher : TaikoHitType.None); + } + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs new file mode 100644 index 0000000000..c2487f7422 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/DrumRollTick.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 + +namespace osu.Game.Modes.Taiko.Objects +{ + public class DrumRollTick : TaikoHitObject + { + /// + /// Whether this is the first (initial) tick of the slider. + /// + public bool FirstTick; + + /// + /// The distance between this tick and the next in milliseconds. + /// Half of this value is the hit window of the tick. + /// + public double TickTimeDistance; + + public override TaikoHitType Type => TaikoHitType.DrumRollTick; + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 0e9e6a56b4..5fbdc7d525 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,6 +50,8 @@ + + From d2194e3d2a51e7e6851977af222657d9462ab5fb Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 14:01:32 +0900 Subject: [PATCH 002/250] Implement Bash. --- osu.Game.Modes.Taiko/Objects/Bash.cs | 32 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 1 + 2 files changed, 33 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/Bash.cs diff --git a/osu.Game.Modes.Taiko/Objects/Bash.cs b/osu.Game.Modes.Taiko/Objects/Bash.cs new file mode 100644 index 0000000000..c9f4d01256 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Bash.cs @@ -0,0 +1,32 @@ +// 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.Timing; +using osu.Game.Database; +using osu.Game.Modes.Objects.Types; + +namespace osu.Game.Modes.Taiko.Objects +{ + public class Bash : TaikoHitObject, IHasEndTime + { + public double EndTime => StartTime + Duration; + + public double Duration { get; set; } + + /// + /// The number of hits required to complete the bash successfully. + /// + public int RequiredHits; + + public override void ApplyDefaults(TimingInfo timing, BeatmapDifficulty difficulty) + { + base.ApplyDefaults(timing, difficulty); + + double spinnerRotationRatio = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5); + RequiredHits = (int)Math.Max(1, Duration / 1000f * spinnerRotationRatio); + } + + public override TaikoHitType Type => TaikoHitType.Bash; + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 0e9e6a56b4..699ef87e99 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,6 +50,7 @@ + From ccc2253068a669158cc8f9fcbc94f0d34ce42fd8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 14:39:38 +0900 Subject: [PATCH 003/250] Implement basic Taiko HitObject conversion. --- .../Beatmaps/TaikoBeatmapConverter.cs | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index d78c347f22..0fa7572cd4 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -2,8 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Modes.Objects; +using osu.Game.Modes.Objects.Types; using osu.Game.Modes.Taiko.Objects; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes.Taiko.Beatmaps { @@ -11,9 +15,52 @@ namespace osu.Game.Modes.Taiko.Beatmaps { public Beatmap Convert(Beatmap original) { + if (original is IIsLegacy) + original.TimingInfo.ControlPoints.ForEach(c => c.VelocityAdjustment *= 1.4); + return new Beatmap(original) { - HitObjects = new List() // Todo: Implement + HitObjects = convertHitObjects(original.HitObjects) + }; + } + + private List convertHitObjects(List hitObjects) + { + return hitObjects.Select(convertHitObject).ToList(); + } + + private TaikoHitObject convertHitObject(HitObject original) + { + IHasDistance distanceData = original as IHasDistance; + IHasRepeats repeatsData = original as IHasRepeats; + IHasEndTime endTimeData = original as IHasEndTime; + + if (distanceData != null) + { + return new DrumRoll + { + StartTime = original.StartTime, + Sample = original.Sample, + + Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1) + }; + } + + if (endTimeData != null) + { + return new Bash + { + StartTime = original.StartTime, + Sample = original.Sample, + + EndTime = endTimeData.EndTime + }; + } + + return new TaikoHitObject + { + StartTime = original.StartTime, + Sample = original.Sample, }; } } From d478a58a89545c08f544129838746316069dc943 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 14:43:00 +0900 Subject: [PATCH 004/250] Invert getters and setters for EndTime / Duration. --- osu.Game.Modes.Taiko/Objects/Bash.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Bash.cs b/osu.Game.Modes.Taiko/Objects/Bash.cs index c9f4d01256..895b25e987 100644 --- a/osu.Game.Modes.Taiko/Objects/Bash.cs +++ b/osu.Game.Modes.Taiko/Objects/Bash.cs @@ -10,9 +10,9 @@ namespace osu.Game.Modes.Taiko.Objects { public class Bash : TaikoHitObject, IHasEndTime { - public double EndTime => StartTime + Duration; + public double EndTime { get; set; } - public double Duration { get; set; } + public double Duration => EndTime - StartTime; /// /// The number of hits required to complete the bash successfully. From 4a85b899c9a9fdf9adbbcb0510adebd5134e1fd2 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 14:44:48 +0900 Subject: [PATCH 005/250] Fix up VelocityAdjustment value. --- osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 0fa7572cd4..e89ba110be 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -13,10 +13,12 @@ namespace osu.Game.Modes.Taiko.Beatmaps { internal class TaikoBeatmapConverter : IBeatmapConverter { + private const float legacy_velocity_scale = 1.4f; + public Beatmap Convert(Beatmap original) { if (original is IIsLegacy) - original.TimingInfo.ControlPoints.ForEach(c => c.VelocityAdjustment *= 1.4); + original.TimingInfo.ControlPoints.ForEach(c => c.VelocityAdjustment /= legacy_velocity_scale); return new Beatmap(original) { From 2e0d100a226823ee7279fc455325df5eb4f4d352 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 15:19:56 +0900 Subject: [PATCH 006/250] Add base DrawableTaikoHitObject, remove DrawableTaikoHit. --- .../Objects/Drawable/DrawableTaikoHit.cs | 39 ------------------- .../Drawable/DrawableTaikoHitObject.cs | 34 ++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 2 +- 3 files changed, 35 insertions(+), 40 deletions(-) delete mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs deleted file mode 100644 index 760977ef5b..0000000000 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHit.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Transforms; -using OpenTK; - -namespace osu.Game.Modes.Taiko.Objects.Drawable -{ - internal class DrawableTaikoHit : Sprite - { - private TaikoHitObject h; - - public DrawableTaikoHit(TaikoHitObject h) - { - this.h = h; - - Origin = Anchor.Centre; - Scale = new Vector2(0.2f); - RelativePositionAxes = Axes.Both; - Position = new Vector2(1.1f, 0.5f); - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(@"Menu/logo"); - - double duration = 0; - - Transforms.Add(new TransformPositionX { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f }); - Transforms.Add(new TransformAlpha { StartTime = h.StartTime + duration + 200, EndTime = h.StartTime + duration + 400, StartValue = 1, EndValue = 0 }); - Expire(true); - } - } -} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs new file mode 100644 index 0000000000..e29caf3f49 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableTaikoHitObject : DrawableHitObject + { + public DrawableTaikoHitObject(TaikoHitObject hitObject) + : base(hitObject) + { + LifetimeStart = HitObject.StartTime - HitObject.PreEmpt; + LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt; + } + + protected override TaikoJudgementInfo CreateJudgementInfo() => new TaikoJudgementInfo(); + + protected override void UpdateState(ArmedState state) + { + } + + protected void UpdateScrollPosition(double time) + { + MoveToX((float)((HitObject.StartTime - time) / HitObject.PreEmpt)); + } + + protected override void Update() + { + UpdateScrollPosition(Time.Current); + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 0e9e6a56b4..aab9a17276 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,9 +50,9 @@ + - From f48af91686bc48d8f57c30932aa34b87dabb8632 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 15:45:54 +0900 Subject: [PATCH 007/250] Appease the resharper gods. --- osu.Game.Modes.Taiko/Objects/DrumRoll.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Modes.Taiko/Objects/DrumRoll.cs index 9ce2758d84..eebbb4717e 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Modes.Taiko/Objects/DrumRoll.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.Game.Beatmaps; using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects.Types; using System; @@ -68,7 +67,7 @@ namespace osu.Game.Modes.Taiko.Objects { base.ApplyDefaults(timing, difficulty); - Velocity = (timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier) / 1000; + Velocity = timing.SliderVelocityAt(StartTime) * difficulty.SliderMultiplier / 1000; TickTimeDistance = timing.BeatLengthAt(StartTime); if (difficulty.SliderTickRate == 3) From cdfe95c15930ac6e0072699d7f7ab2c0725fccaf Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 16:05:16 +0900 Subject: [PATCH 008/250] Add AcentColour and xmldoc. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index e29caf3f49..4adbf2cb33 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.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 OpenTK.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; @@ -8,6 +9,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableTaikoHitObject : DrawableHitObject { + /// + /// The colour used for various elements of this DrawableHitObject. + /// + public virtual Color4 AccentColour { get; } + public DrawableTaikoHitObject(TaikoHitObject hitObject) : base(hitObject) { @@ -21,6 +27,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { } + /// + /// Sets the scroll position of the DrawableHitObject relative to the offset between + /// a time value and the HitObject's StartTime. + /// + /// protected void UpdateScrollPosition(double time) { MoveToX((float)((HitObject.StartTime - time) / HitObject.PreEmpt)); From 35f63cb2aa774daec62fc13fb7085cb9f05aef9f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 16:10:40 +0900 Subject: [PATCH 009/250] Set Anchor/Origin and RelativePositionAxes. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index 4adbf2cb33..321a1beea7 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; +using osu.Framework.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; @@ -17,7 +18,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable public DrawableTaikoHitObject(TaikoHitObject hitObject) : base(hitObject) { - LifetimeStart = HitObject.StartTime - HitObject.PreEmpt; + Anchor = Anchor.CentreLeft; + Origin = Anchor.Centre; + + RelativePositionAxes = Axes.X; + + LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2; LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt; } From f26cf7bf68599f2ea84c8b020df832c6a5a8c694 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 16:55:57 +0900 Subject: [PATCH 010/250] Add basic DrawableHit (no graphics yet, just input). --- .../Objects/Drawable/DrawableHit.cs | 82 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 1 + 2 files changed, 83 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs new file mode 100644 index 0000000000..caf4fee335 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -0,0 +1,82 @@ +using OpenTK.Input; +using osu.Framework.Input; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; +using System; +using System.Collections.Generic; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public abstract class DrawableHit : DrawableTaikoHitObject + { + /// + /// A list of keys which can result in hits for this HitObject. + /// + protected abstract List HitKeys { get; } + + /// + /// 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 List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K }); + + /// + /// Whether the last key pressed is a valid hit key. + /// + private bool validKeyPressed; + + protected DrawableHit(TaikoHitObject hitObject) + : base(hitObject) + { + } + + protected override void CheckJudgement(bool userTriggered) + { + if (!userTriggered) + { + if (Judgement.TimeOffset > HitObject.HitWindowGood) + Judgement.Result = HitResult.Miss; + return; + } + + double hitOffset = Math.Abs(Judgement.TimeOffset); + + if (hitOffset > HitObject.HitWindowMiss) + return; + + if (!validKeyPressed) + Judgement.Result = HitResult.Miss; + else if (hitOffset < HitObject.HitWindowGood) + { + Judgement.Result = HitResult.Hit; + Judgement.Score = hitOffset < HitObject.HitWindowGreat ? TaikoScoreResult.Great : TaikoScoreResult.Good; + } + else + Judgement.Result = HitResult.Miss; + } + + protected virtual bool HandleKeyPress(Key key) + { + if (Judgement.Result.HasValue) + return false; + + validKeyPressed = HitKeys.Contains(key); + + return UpdateJudgement(true); + } + + protected sealed override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + // Make sure we don't handle held-down keys + if (args.Repeat) + return false; + + // Check if we've pressed a valid taiko key + if (!validKeys.Contains(args.Key)) + return false; + + // Handle it! + return HandleKeyPress(args.Key); + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index aab9a17276..dbd58d4666 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,6 +50,7 @@ + From 863d4959af1f4c7153b2c4f4763446cfc7aea845 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 17:38:24 +0900 Subject: [PATCH 011/250] Make OnKeyDown non-sealed. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index caf4fee335..46cf9e5f87 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -65,7 +65,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable return UpdateJudgement(true); } - protected sealed override bool OnKeyDown(InputState state, KeyDownEventArgs args) + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { // Make sure we don't handle held-down keys if (args.Repeat) From 1892d869215b5a525e734adc220a8e69b0672bf6 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 17:38:49 +0900 Subject: [PATCH 012/250] Add basic DrawableHitFinisher (no graphics yet, just input). --- .../Objects/Drawable/DrawableHitFinisher.cs | 80 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 1 + 2 files changed, 81 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs new file mode 100644 index 0000000000..22fc83874b --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs @@ -0,0 +1,80 @@ +using OpenTK.Input; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using osu.Framework.Input; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public abstract class DrawableHitFinisher : DrawableHit + { + /// + /// The lenience for the second key press. + /// This does not adjust by map difficulty in ScoreV2 yet. + /// + private const double second_hit_window = 30; + + private double firstHitTime; + private Key firstHitKey; + + protected DrawableHitFinisher(TaikoHitObject hitObject) + : base(hitObject) + { + } + + protected override void CheckJudgement(bool userTriggered) + { + if (!Judgement.Result.HasValue) + { + base.CheckJudgement(userTriggered); + return; + } + + if (!userTriggered) + return; + + // If we get here, we're assured that the key pressed is the correct secondary key + + if (Math.Abs(firstHitTime - Time.Current) < second_hit_window) + Judgement.SecondHit = true; + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + // Check if we've handled the initial key + if (!Judgement.Result.HasValue) + { + bool result = base.OnKeyDown(state, args); + + if (result) + { + firstHitTime = Time.Current; + firstHitKey = args.Key; + } + + return result; + } + + // If we've already hit the second key, don't handle this object any further + if (Judgement.SecondHit) + return false; + + // Don't handle represses of the same key + if (firstHitKey == args.Key) + return false; + + // Don't handle invalid hit key presses + if (!HitKeys.Contains(args.Key)) + return false; + + // If we're not holding the first key down still, assume the intention + // was not to hit the finisher with both keys simultaneously + if (!state.Keyboard.Keys.Contains(firstHitKey)) + return false; + + return UpdateJudgement(true); + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 3a79d721c6..5b8a1fd2b8 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,6 +52,7 @@ + From 891bd011c6fe86e9d7380544470b64c32de2ffa7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 18:54:44 +0900 Subject: [PATCH 013/250] Add basic DrawableBash (no graphics yet, just input). --- .../Objects/Drawable/DrawableBash.cs | 79 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 1 + 2 files changed, 80 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs new file mode 100644 index 0000000000..b69546e1aa --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Input; +using System.Collections.Generic; +using osu.Framework.Input; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; +using System; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableBash : DrawableTaikoHitObject + { + /// + /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. + /// These should be moved to bindings later. + /// + private List validKeys { get; } = new List(new[] { Key.D, Key.F, Key.J, Key.K }); + + /// + /// The amount of times the user has hit this bash. + /// + private int userHits; + + public DrawableBash(TaikoHitObject hitObject) + : base(hitObject) + { + } + + protected override void CheckJudgement(bool userTriggered) + { + if (userTriggered) + { + if (Time.Current < HitObject.StartTime) + return; + + userHits++; + + if (userHits == HitObject.RequiredHits) + { + Judgement.Result = HitResult.Hit; + Judgement.Score = TaikoScoreResult.Great; + } + } + else + { + if (Judgement.TimeOffset < 0) + return; + + if (userHits > HitObject.RequiredHits / 2) + { + Judgement.Result = HitResult.Hit; + Judgement.Score = TaikoScoreResult.Good; + } + else + Judgement.Result = HitResult.Miss; + } + } + + protected override void Update() + { + UpdateScrollPosition(Math.Min(Time.Current, HitObject.StartTime)); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (Judgement.Result.HasValue) + return false; + + if (!validKeys.Contains(args.Key)) + return false; + + UpdateJudgement(true); + + return true; + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index bdc8edb62e..73963a828c 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -51,6 +51,7 @@ + From 0e4ed829f2d148558d2f9a671ea4118ea1ab3965 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 18:55:54 +0900 Subject: [PATCH 014/250] Make DrawableTaikoHitObject generic. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index 321a1beea7..5e8aeb4844 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -8,14 +8,15 @@ using osu.Game.Modes.Taiko.Judgements; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableTaikoHitObject : DrawableHitObject + public class DrawableTaikoHitObject : DrawableHitObject + where TTaikoObject : TaikoHitObject { /// /// The colour used for various elements of this DrawableHitObject. /// public virtual Color4 AccentColour { get; } - public DrawableTaikoHitObject(TaikoHitObject hitObject) + public DrawableTaikoHitObject(TTaikoObject hitObject) : base(hitObject) { Anchor = Anchor.CentreLeft; From 938da01540c5b836baadb8fd06efae3c070d7859 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 18:56:58 +0900 Subject: [PATCH 015/250] Fix post-merge errors. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index 46cf9e5f87..dc5d846ebc 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public abstract class DrawableHit : DrawableTaikoHitObject + public abstract class DrawableHit : DrawableTaikoHitObject { /// /// A list of keys which can result in hits for this HitObject. From a2d07acb4b6089d67852b00d2cb28c6c27439c16 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 18:59:21 +0900 Subject: [PATCH 016/250] Fix post-merge errors. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs index b69546e1aa..4e848c76c3 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs @@ -10,7 +10,7 @@ using System; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableBash : DrawableTaikoHitObject + public class DrawableBash : DrawableTaikoHitObject { /// /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. @@ -23,8 +23,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private int userHits; - public DrawableBash(TaikoHitObject hitObject) - : base(hitObject) + public DrawableBash(Bash bash) + : base(bash) { } From 1ede12d847468d9b5e2826df79b17dc8d906c2db Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:08:50 +0900 Subject: [PATCH 017/250] Add basic DrawableDrumRollTick (no graphics yet, just input). --- .../TaikoDrumRollTickJudgementInfo.cs | 21 +++++++ .../Objects/Drawable/DrawableDrumRollTick.cs | 60 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 2 + 3 files changed, 83 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgementInfo.cs create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgementInfo.cs b/osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgementInfo.cs new file mode 100644 index 0000000000..ff9c4c4512 --- /dev/null +++ b/osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgementInfo.cs @@ -0,0 +1,21 @@ +namespace osu.Game.Modes.Taiko.Judgements +{ + public class TaikoDrumRollTickJudgementInfo : TaikoJudgementInfo + { + protected override int ScoreToInt(TaikoScoreResult result) + { + switch (result) + { + default: + return 0; + case TaikoScoreResult.Great: + return 200; + } + } + + protected override int AccuracyScoreToInt(TaikoScoreResult result) + { + return 0; + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs new file mode 100644 index 0000000000..3bd121321b --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -0,0 +1,60 @@ +using OpenTK.Input; +using System.Collections.Generic; +using osu.Game.Modes.Taiko.Judgements; +using System; +using osu.Game.Modes.Objects.Drawables; +using osu.Framework.Input; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableDrumRollTick : DrawableTaikoHitObject + { + /// + /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. + /// These should be moved to bindings later. + /// + private List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K }); + + public DrawableDrumRollTick(DrumRollTick tick) + : base(tick) + { + } + + protected override TaikoJudgementInfo CreateJudgementInfo() => new TaikoDrumRollTickJudgementInfo(); + + protected override void CheckJudgement(bool userTriggered) + { + if (!userTriggered) + { + if (Judgement.TimeOffset > HitObject.TickTimeDistance / 2) + Judgement.Result = Modes.Objects.Drawables.HitResult.Miss; + return; + } + + if (Math.Abs(Judgement.TimeOffset) < HitObject.TickTimeDistance / 2) + { + Judgement.Result = HitResult.Hit; + Judgement.Score = TaikoScoreResult.Great; + } + } + + protected override void Update() + { + // Drum roll ticks shouldn't move + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (args.Repeat) + return false; + + if (Judgement.Result.HasValue) + return false; + + if (!validKeys.Contains(args.Key)) + return false; + + return UpdateJudgement(true); + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index d8cd0d4ebb..61c3d460c0 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -49,8 +49,10 @@ + + From 5136064cb35b706985d50a564ec079e98fd544f5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:23:18 +0900 Subject: [PATCH 018/250] Revert "Make DrawableTaikoHitObject generic." This reverts commit 0e4ed829f2d148558d2f9a671ea4118ea1ab3965. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index 5e8aeb4844..321a1beea7 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -8,15 +8,14 @@ using osu.Game.Modes.Taiko.Judgements; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableTaikoHitObject : DrawableHitObject - where TTaikoObject : TaikoHitObject + public class DrawableTaikoHitObject : DrawableHitObject { /// /// The colour used for various elements of this DrawableHitObject. /// public virtual Color4 AccentColour { get; } - public DrawableTaikoHitObject(TTaikoObject hitObject) + public DrawableTaikoHitObject(TaikoHitObject hitObject) : base(hitObject) { Anchor = Anchor.CentreLeft; From ad396c65ee6e9c6774d15e5bc4abdb52394c1375 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:24:39 +0900 Subject: [PATCH 019/250] Fix post-merge errors. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index dc5d846ebc..46cf9e5f87 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public abstract class DrawableHit : DrawableTaikoHitObject + public abstract class DrawableHit : DrawableTaikoHitObject { /// /// A list of keys which can result in hits for this HitObject. From e3afa9bf715603a6ecd5f8e5decf82ea2507eab0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:25:55 +0900 Subject: [PATCH 020/250] Fix post-merge errors. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs index 4e848c76c3..00abd3017d 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs @@ -10,7 +10,7 @@ using System; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableBash : DrawableTaikoHitObject + public class DrawableBash : DrawableTaikoHitObject { /// /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. @@ -23,9 +23,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private int userHits; + private Bash bash; + public DrawableBash(Bash bash) : base(bash) { + this.bash = bash; } protected override void CheckJudgement(bool userTriggered) @@ -37,7 +40,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable userHits++; - if (userHits == HitObject.RequiredHits) + if (userHits == bash.RequiredHits) { Judgement.Result = HitResult.Hit; Judgement.Score = TaikoScoreResult.Great; @@ -48,7 +51,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable if (Judgement.TimeOffset < 0) return; - if (userHits > HitObject.RequiredHits / 2) + if (userHits > bash.RequiredHits / 2) { Judgement.Result = HitResult.Hit; Judgement.Score = TaikoScoreResult.Good; From 7860199fbda8360182d15019d41e7efb488bde74 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:27:06 +0900 Subject: [PATCH 021/250] Fix post-merge errors. --- .../Objects/Drawable/DrawableDrumRollTick.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs index 3bd121321b..043fe32dca 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -7,7 +7,7 @@ using osu.Framework.Input; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableDrumRollTick : DrawableTaikoHitObject + public class DrawableDrumRollTick : DrawableTaikoHitObject { /// /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. @@ -15,9 +15,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K }); + private DrumRollTick tick; + public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { + this.tick = tick; } protected override TaikoJudgementInfo CreateJudgementInfo() => new TaikoDrumRollTickJudgementInfo(); @@ -26,12 +29,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { if (!userTriggered) { - if (Judgement.TimeOffset > HitObject.TickTimeDistance / 2) + if (Judgement.TimeOffset > tick.TickTimeDistance / 2) Judgement.Result = Modes.Objects.Drawables.HitResult.Miss; return; } - if (Math.Abs(Judgement.TimeOffset) < HitObject.TickTimeDistance / 2) + if (Math.Abs(Judgement.TimeOffset) < tick.TickTimeDistance / 2) { Judgement.Result = HitResult.Hit; Judgement.Score = TaikoScoreResult.Great; From ecd6958eeae12a7a5a608d49ed1165a2f3a8e5b9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:30:22 +0900 Subject: [PATCH 022/250] Add basic DrawableDrumRoll (no graphics yet, just input). --- .../Objects/Drawable/DrawableDrumRoll.cs | 50 +++++++++++++++++++ .../osu.Game.Modes.Taiko.csproj | 1 + 2 files changed, 51 insertions(+) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs new file mode 100644 index 0000000000..70790d2ded --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRoll.cs @@ -0,0 +1,50 @@ +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; +using System.Linq; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableDrumRoll : DrawableTaikoHitObject + { + private DrumRoll drumRoll; + + public DrawableDrumRoll(DrumRoll drumRoll) + : base(drumRoll) + { + this.drumRoll = drumRoll; + + int tickIndex = 0; + foreach (var tick in drumRoll.Ticks) + { + var newTick = new DrawableDrumRollTick(tick) + { + Depth = tickIndex, + X = (float)((tick.StartTime - HitObject.StartTime) / drumRoll.Duration) + }; + + AddNested(newTick); + + tickIndex++; + } + } + + protected override void CheckJudgement(bool userTriggered) + { + if (userTriggered) + return; + + if (Judgement.TimeOffset < 0) + return; + + int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit); + + if (countHit > drumRoll.RequiredGoodHits) + { + Judgement.Result = HitResult.Hit; + Judgement.Score = countHit >= drumRoll.RequiredGreatHits ? TaikoScoreResult.Great : TaikoScoreResult.Good; + } + else + Judgement.Result = HitResult.Miss; + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 61c3d460c0..b37bc61c17 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,6 +52,7 @@ + From 7f7e8047d4dcf4c6b9bdf6cb99580d2edaa8ed47 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:51:56 +0900 Subject: [PATCH 023/250] Don't convert originally taiko hitobjects. --- osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index e89ba110be..6533295ce4 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -33,6 +33,11 @@ namespace osu.Game.Modes.Taiko.Beatmaps private TaikoHitObject convertHitObject(HitObject original) { + // Check if this HitObject is already a TaikoHitObject, and return it if so + TaikoHitObject originalTaiko = original as TaikoHitObject; + if (originalTaiko != null) + return originalTaiko; + IHasDistance distanceData = original as IHasDistance; IHasRepeats repeatsData = original as IHasRepeats; IHasEndTime endTimeData = original as IHasEndTime; From 605f733cf905f299050af7f0212662eb11e06c56 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:52:24 +0900 Subject: [PATCH 024/250] Add back the bash conversion factor. --- osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 6533295ce4..00a17c017c 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -14,6 +14,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps internal class TaikoBeatmapConverter : IBeatmapConverter { private const float legacy_velocity_scale = 1.4f; + private const float bash_convert_factor = 1.65f; public Beatmap Convert(Beatmap original) { @@ -55,12 +56,13 @@ namespace osu.Game.Modes.Taiko.Beatmaps if (endTimeData != null) { + // We compute the end time manually to add in the Bash convert factor return new Bash { StartTime = original.StartTime, Sample = original.Sample, - EndTime = endTimeData.EndTime + EndTime = original.StartTime + endTimeData.Duration * bash_convert_factor }; } From 2a9e8f4ed6b98aa4ac8e3eb83751d022f5ede0cf Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 19:54:36 +0900 Subject: [PATCH 025/250] Fix license headers. --- osu.Game/Beatmaps/Legacy/IIsLegacy.cs | 5 ++++- osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Legacy/IIsLegacy.cs b/osu.Game/Beatmaps/Legacy/IIsLegacy.cs index 23ab9f4bc4..3babd3e66f 100644 --- a/osu.Game/Beatmaps/Legacy/IIsLegacy.cs +++ b/osu.Game/Beatmaps/Legacy/IIsLegacy.cs @@ -1,4 +1,7 @@ -namespace osu.Game.Beatmaps.Legacy +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Beatmaps.Legacy { /// /// A Beatmap that was loaded from a legacy .osu beatmap file (version <=15). diff --git a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs index 00aeeb2b49..d0386e7560 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs @@ -1,4 +1,7 @@ -namespace osu.Game.Beatmaps.Legacy +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Beatmaps.Legacy { /// /// A type of Beatmap loaded from a legacy .osu beatmap file (version <=15). From b629766892dda93751102a8f51defc90b5d993f3 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 17 Mar 2017 22:01:06 +0900 Subject: [PATCH 026/250] Add initial taiko note circles. --- .../Tests/TestCaseTaikoHitObjects.cs | 348 ++++++++++++++++++ .../osu.Desktop.VisualTests.csproj | 3 +- .../osu.Game.Modes.Taiko.csproj | 3 + 3 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs new file mode 100644 index 0000000000..8dc82c4416 --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -0,0 +1,348 @@ +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Screens.Testing; +using osu.Game.Graphics; +using osu.Game.Graphics.Backgrounds; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseTaikoHitObjects : TestCase + { + public override string Description => "Taiko hit objects"; + + public override void Reset() + { + base.Reset(); + + Add(new CentreHitCirclePiece + { + Position = new Vector2(100, 100), + AccentColour = Color4.Red + }); + + Add(new RimHitCirclePiece + { + Position = new Vector2(100, 250), + AccentColour = Color4.Blue + }); + + Add(new BashCirclePiece + { + Position = new Vector2(100, 400), + AccentColour = Color4.Orange + }); + + Add(new DrumRollCirclePiece + { + Width = 256, + Position = new Vector2(100, 550), + AccentColour = Color4.Yellow + }); + } + } + + class FinisherCirclePiece : Container + { + public FinisherCirclePiece() + { + Anchor = Anchor.CentreLeft; + + } + } + + /// + /// A circle piece which is used to visualise RimHit objects. + /// + class RimHitCirclePiece : CirclePiece + { + public RimHitCirclePiece() + { + Height = 128; + } + + protected override Drawable CreateIcon() + { + return new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + Size = new Vector2(61f), + + BorderThickness = 8, + BorderColour = Color4.White, + + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + + Alpha = 0, + AlwaysPresent = true + } + } + }; + } + } + + /// + /// A circle piece which is used to visualise CentreHit objects. + /// + class CentreHitCirclePiece : CirclePiece + { + public CentreHitCirclePiece() + { + Height = 128; + } + + protected override Drawable CreateIcon() + { + return new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + Size = new Vector2(45f), + + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + + Alpha = 1 + } + } + }; + } + } + + /// + /// A circle piece which is used to visualise Bash objects. + /// + class BashCirclePiece : CirclePiece + { + public BashCirclePiece() + { + Height = 128; + } + + protected override Drawable CreateIcon() + { + return new TextAwesome + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + TextSize = 45f, + Icon = FontAwesome.fa_asterisk + }; + } + } + + /// + /// A circle piece which is used to visualise DrumRoll objects. + /// + class DrumRollCirclePiece : CirclePiece + { + public DrumRollCirclePiece() + { + Height = 128; + } + } + + /// + /// A circle piece which is used uniformly through osu!taiko to visualise hitobjects. + /// This is used uniformly throughout all osu!taiko hitobjects. + /// + /// The contents of this piece will overshoot it by 64px on both sides on the X-axis, such that + /// a regular "circle" is created by setting the width of this piece to 0px (resulting in a 64px radius circle). + /// + /// + abstract class CirclePiece : Container + { + private bool kiaiMode; + /// + /// Whether Kiai mode is active for this object. + /// + public bool KiaiMode + { + get { return kiaiMode; } + set + { + kiaiMode = value; + + if (innerCircleContainer != null) + innerCircleContainer.EdgeEffect = value ? createKiaiEdgeEffect() : default(EdgeEffect); + } + } + + /// + /// The colour of the inner circle and outer glows. + /// + public Color4 AccentColour; + + private Container innerLayer; + private Container backingGlowContainer; + private Container innerCircleContainer; + + public CirclePiece() + { + Container iconContainer; + + Origin = Anchor.CentreLeft; + + Children = new Drawable[] + { + // The "inner layer" overshoots the ObjectPiece by 64px on both sides + innerLayer = new Container + { + Name = "Inner Layer", + + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Y, + + Children = new Drawable[] + { + backingGlowContainer = new CircularContainer + { + Name = "Backing Glow", + + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + + Alpha = 0, + AlwaysPresent = true + } + } + }, + innerCircleContainer = new CircularContainer + { + Name = "Inner Circle", + + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + + Children = new Drawable[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + }, + new Triangles + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + + Alpha = 0.75f + } + } + }, + new CircularContainer + { + Name = "Ring", + + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + + BorderThickness = 8, + BorderColour = Color4.White, + + Children = new[] + { + new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + + RelativeSizeAxes = Axes.Both, + + Alpha = 0, + AlwaysPresent = true + } + } + }, + iconContainer = new Container + { + Name = "Icon Container", + + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + } + }, + }; + + Drawable icon = CreateIcon(); + + if (icon != null) + iconContainer.Add(icon); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + backingGlowContainer.EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = AccentColour, + Radius = 8 + }; + + if (KiaiMode) + innerCircleContainer.EdgeEffect = createKiaiEdgeEffect(); + + innerCircleContainer.Colour = AccentColour; + } + + protected override void Update() + { + innerLayer.Width = DrawWidth + 128; + } + + private EdgeEffect createKiaiEdgeEffect() + { + return new EdgeEffect + { + Type = EdgeEffectType.Glow, + Colour = AccentColour, + Radius = 50 + }; + } + + /// + /// Creates the icon that's shown in the middle of this object piece. + /// + /// The icon. + protected virtual Drawable CreateIcon() => null; + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 68aed38b34..28ca0655cc 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -23,7 +23,7 @@ false LocalIntranet v4.5 - true + true publish\ true Disk @@ -194,6 +194,7 @@ + diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index bc38781b01..e4c56621fb 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -81,6 +81,9 @@ osu.Game + + + - \ No newline at end of file + From be4ab13f4d567190d0d614021b64fb92665a24b9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 20:30:26 +0900 Subject: [PATCH 152/250] Rename finisher -> accented. --- .../{DrawableHitFinisher.cs => DrawableAccentedHit.cs} | 6 +++--- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename osu.Game.Modes.Taiko/Objects/Drawable/{DrawableHitFinisher.cs => DrawableAccentedHit.cs} (89%) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs similarity index 89% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs rename to osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs index 3f7361b62c..e251daae7d 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHitFinisher.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs @@ -8,7 +8,7 @@ using osu.Framework.Input; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public abstract class DrawableHitFinisher : DrawableHit + public abstract class DrawableAccentedHit : DrawableHit { /// /// The lenience for the second key press. @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private double firstHitTime; private Key firstHitKey; - protected DrawableHitFinisher(Hit hit) + protected DrawableAccentedHit(Hit hit) : base(hit) { } @@ -70,7 +70,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable return false; // If we're not holding the first key down still, assume the intention - // was not to hit the finisher with both keys simultaneously + // was not to hit the accented hit with both keys simultaneously if (!state.Keyboard.Keys.Contains(firstHitKey)) return false; diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index fcabccc9ca..d6b2fb6364 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -53,7 +53,7 @@ - + From 5bd9147661c4cace5dfa61bbf1756b3ac94307cf Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 20:53:28 +0900 Subject: [PATCH 153/250] Remove CreateCircle() - hitobjects should handle the addition of this to their hierarchy themselves. CreateCircle() lends itself to a few issues: - It can't be used for drum roll ticks unless it returned a Container instead, at which point the method loses its meaning, and I would rather that constructed in the ctor. - Writing `return Accented ? new AccentedCirclePiece() : new CirclePiece()` in two places as the body of this method feels wrong - it's something I would expect to be taken care of in the base DrawableTaikoHitObject, but that leads back to #1. - Swells don't have an AccentedCirclePiece, so #2 becomes more problematic. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index e165f40442..c77c7762e3 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -17,11 +16,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Origin = Anchor.Centre; RelativePositionAxes = Axes.X; - - Children = new[] - { - CreateCircle() - }; } protected override void LoadComplete() @@ -48,7 +42,5 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { UpdateScrollPosition(Time.Current); } - - protected abstract CirclePiece CreateCircle(); } } From e7941859e4ef1b5b102d047ffafc7968c9057545 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 20:57:49 +0900 Subject: [PATCH 154/250] Rename bash -> swell. --- .../Beatmaps/TaikoBeatmapConverter.cs | 2 +- .../{DrawableBash.cs => DrawableSwell.cs} | 16 ++++++++-------- .../Objects/{Bash.cs => Swell.cs} | 4 ++-- .../Scoring/TaikoScoreProcessor.cs | 2 +- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) rename osu.Game.Modes.Taiko/Objects/Drawable/{DrawableBash.cs => DrawableSwell.cs} (82%) rename osu.Game.Modes.Taiko/Objects/{Bash.cs => Swell.cs} (84%) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index b2676bf28a..9b143e9fde 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -61,7 +61,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps if (endTimeData != null) { // We compute the end time manually to add in the Bash convert factor - return new Bash + return new Swell { StartTime = original.StartTime, Sample = original.Sample, diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs similarity index 82% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs rename to osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 1aa962be12..9d0e23553d 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableBash.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -10,7 +10,7 @@ using System; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public class DrawableBash : DrawableTaikoHitObject + public class DrawableSwell : DrawableTaikoHitObject { /// /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. @@ -19,16 +19,16 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private List validKeys { get; } = new List(new[] { Key.D, Key.F, Key.J, Key.K }); /// - /// The amount of times the user has hit this bash. + /// The amount of times the user has hit this swell. /// private int userHits; - private readonly Bash bash; + private readonly Swell swell; - public DrawableBash(Bash bash) - : base(bash) + public DrawableSwell(Swell swell) + : base(swell) { - this.bash = bash; + this.swell = swell; } protected override void CheckJudgement(bool userTriggered) @@ -40,7 +40,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable userHits++; - if (userHits == bash.RequiredHits) + if (userHits == swell.RequiredHits) { Judgement.Result = HitResult.Hit; Judgement.TaikoResult = TaikoHitResult.Great; @@ -51,7 +51,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable if (Judgement.TimeOffset < 0) return; - if (userHits > bash.RequiredHits / 2) + if (userHits > swell.RequiredHits / 2) { Judgement.Result = HitResult.Hit; Judgement.TaikoResult = TaikoHitResult.Good; diff --git a/osu.Game.Modes.Taiko/Objects/Bash.cs b/osu.Game.Modes.Taiko/Objects/Swell.cs similarity index 84% rename from osu.Game.Modes.Taiko/Objects/Bash.cs rename to osu.Game.Modes.Taiko/Objects/Swell.cs index b8b4eea6a9..20b9a6effb 100644 --- a/osu.Game.Modes.Taiko/Objects/Bash.cs +++ b/osu.Game.Modes.Taiko/Objects/Swell.cs @@ -8,14 +8,14 @@ using osu.Game.Modes.Objects.Types; namespace osu.Game.Modes.Taiko.Objects { - public class Bash : TaikoHitObject, IHasEndTime + public class Swell : TaikoHitObject, IHasEndTime { public double EndTime { get; set; } public double Duration => EndTime - StartTime; /// - /// The number of hits required to complete the bash successfully. + /// The number of hits required to complete the swell successfully. /// public int RequiredHits { get; protected set; } diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs index 3007411230..a3759d9c81 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs @@ -165,7 +165,7 @@ namespace osu.Game.Modes.Taiko.Scoring SecondHit = obj.Accented }); } - else if (obj is Bash) + else if (obj is Swell) { AddJudgement(new TaikoJudgement { diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index b1f47832c0..7780230ede 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,9 +52,9 @@ - + - + From cbb6930f76991bc23dbf551043d98fa0e40b8c46 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 20:53:28 +0900 Subject: [PATCH 155/250] Remove CreateCircle() - hitobjects should handle the addition of this to their hierarchy themselves. CreateCircle() lends itself to a few issues: - It can't be used for drum roll ticks unless it returned a Container instead, at which point the method loses its meaning, and I would rather that constructed in the ctor. - Writing `return Accented ? new AccentedCirclePiece() : new CirclePiece()` in two places as the body of this method feels wrong - it's something I would expect to be taken care of in the base DrawableTaikoHitObject, but that leads back to #1. - Swells don't have an AccentedCirclePiece, so #2 becomes more problematic. --- .../Objects/Drawable/DrawableTaikoHitObject.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index e165f40442..c77c7762e3 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -17,11 +16,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Origin = Anchor.Centre; RelativePositionAxes = Axes.X; - - Children = new[] - { - CreateCircle() - }; } protected override void LoadComplete() @@ -48,7 +42,5 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { UpdateScrollPosition(Time.Current); } - - protected abstract CirclePiece CreateCircle(); } } From 989a6ab02be514a04c270c07247652b1065e6866 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 23:43:41 +0900 Subject: [PATCH 156/250] Move validKeys to DrawableTaikoHitObject. Cleanup + reword comments. --- .../Objects/Drawable/DrawableAccentedHit.cs | 33 +++++++++++-------- .../Objects/Drawable/DrawableHit.cs | 23 +------------ .../Drawable/DrawableTaikoHitObject.cs | 25 ++++++++++++++ 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs index e251daae7d..9d9c67a7f4 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs @@ -17,6 +17,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private const double second_hit_window = 30; private double firstHitTime; + private bool firstKeyHeld; private Key firstHitKey; protected DrawableAccentedHit(Hit hit) @@ -41,40 +42,44 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Judgement.SecondHit = true; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + protected override bool HandleKeyPress(Key key) { - // Check if we've handled the initial key + // Check if we've handled the first key if (!Judgement.Result.HasValue) { - bool result = base.OnKeyDown(state, args); + // First key hasn't been handled yet, attempt to handle it + bool handled = base.HandleKeyPress(key); - if (result) + if (handled) { firstHitTime = Time.Current; - firstHitKey = args.Key; + firstHitKey = key; } - return result; + return handled; } // If we've already hit the second key, don't handle this object any further if (Judgement.SecondHit) return false; - // Don't handle represses of the same key - if (firstHitKey == args.Key) + // Don't handle represses of the first key + if (firstHitKey == key) return false; // Don't handle invalid hit key presses - if (!HitKeys.Contains(args.Key)) + if (!HitKeys.Contains(key)) return false; - // If we're not holding the first key down still, assume the intention - // was not to hit the accented hit with both keys simultaneously - if (!state.Keyboard.Keys.Contains(firstHitKey)) - return false; + // Assume the intention was to hit the accented hit with both keys only if the first key is still being held down + return firstKeyHeld && UpdateJudgement(true); + } - return 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.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index cc017ab376..a3ea9e36b9 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; -using osu.Framework.Input; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using System; @@ -17,12 +16,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// protected abstract List HitKeys { get; } - /// - /// 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 }); - private readonly Hit hit; /// @@ -61,7 +54,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Judgement.Result = HitResult.Miss; } - protected virtual bool HandleKeyPress(Key key) + protected override bool HandleKeyPress(Key key) { if (Judgement.Result.HasValue) return false; @@ -70,19 +63,5 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable return UpdateJudgement(true); } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - // Make sure we don't handle held-down keys - if (args.Repeat) - return false; - - // Check if we've pressed a valid taiko key - if (!validKeys.Contains(args.Key)) - return false; - - // Handle it! - return HandleKeyPress(args.Key); - } } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index e165f40442..bb6ca627da 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -1,15 +1,24 @@ // 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.Framework.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; +using System.Collections.Generic; +using osu.Framework.Input; namespace osu.Game.Modes.Taiko.Objects.Drawable { public abstract class DrawableTaikoHitObject : DrawableHitObject { + /// + /// 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 }); + protected DrawableTaikoHitObject(TaikoHitObject hitObject) : base(hitObject) { @@ -49,6 +58,22 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable UpdateScrollPosition(Time.Current); } + protected virtual bool HandleKeyPress(Key key) { return false; } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + // Make sure we don't handle held-down keys + if (args.Repeat) + return false; + + // Check if we've pressed a valid taiko key + if (!validKeys.Contains(args.Key)) + return false; + + // Handle it! + return HandleKeyPress(args.Key); + } + protected abstract CirclePiece CreateCircle(); } } From 9b0a15cd6ccf83b977c32def44c14e69e254969f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 23:48:00 +0900 Subject: [PATCH 157/250] Fix post-merge errors. --- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index f11b9c24d1..b32288c2d9 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -54,11 +54,9 @@ - - From d9ecb430ede96463a314fc2637e7f27f179867c1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 23:48:13 +0900 Subject: [PATCH 158/250] Remove validKeys (now in DrawableTaikoHitObject). --- .../Objects/Drawable/DrawableSwell.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 9d0e23553d..15584ac73f 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -2,8 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; -using System.Collections.Generic; -using osu.Framework.Input; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using System; @@ -12,12 +10,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableSwell : DrawableTaikoHitObject { - /// - /// A list of keys which this HitObject will accept. These are the standard Taiko keys for now. - /// These should be moved to bindings later. - /// - private List validKeys { get; } = new List(new[] { Key.D, Key.F, Key.J, Key.K }); - /// /// The amount of times the user has hit this swell. /// @@ -70,14 +62,11 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable base.UpdateScrollPosition(Math.Min(time, HitObject.StartTime)); } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + protected override bool HandleKeyPress(Key key) { if (Judgement.Result.HasValue) return false; - if (!validKeys.Contains(args.Key)) - return false; - UpdateJudgement(true); return true; From 7c9900376f952035828193e3febee6f7310b9c31 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 25 Mar 2017 23:54:50 +0900 Subject: [PATCH 159/250] Remove validKeys (now in DrawableTaikoHitObject). --- .../Objects/Drawable/DrawableDrumRollTick.cs | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs index 360cccd6ca..fe7ed855f5 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -2,22 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; -using System.Collections.Generic; using osu.Game.Modes.Taiko.Judgements; using System; using osu.Game.Modes.Objects.Drawables; -using osu.Framework.Input; namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableDrumRollTick : DrawableTaikoHitObject { - /// - /// A list of keys which this HitObject 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 }); - private readonly DrumRollTick tick; public DrawableDrumRollTick(DrumRollTick tick) @@ -53,18 +45,9 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable // Drum roll ticks shouldn't move } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + protected override bool HandleKeyPress(Key key) { - if (args.Repeat) - return false; - - if (Judgement.Result.HasValue) - return false; - - if (!validKeys.Contains(args.Key)) - return false; - - return UpdateJudgement(true); + return !Judgement.Result.HasValue && UpdateJudgement(true); } } } From bcaf2f97582d03c36904937c47ed6af31f293706 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sun, 26 Mar 2017 00:01:00 +0900 Subject: [PATCH 160/250] Use lambda expression. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index bb6ca627da..5f63a956e1 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -58,7 +58,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable UpdateScrollPosition(Time.Current); } - protected virtual bool HandleKeyPress(Key key) { return false; } + protected virtual bool HandleKeyPress(Key key) => false; protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { From d0b1fda24f4e48cabca2febe3d4ecc09d84a5851 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2017 12:33:15 +0900 Subject: [PATCH 161/250] Fix merge fail. --- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 50ec2002fb..a7b382b24c 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -56,7 +56,6 @@ - @@ -103,4 +102,4 @@ --> - \ No newline at end of file + From b8c8ca2f0e63ae08c78c6897a4237cd32c7a3950 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2017 15:49:32 +0900 Subject: [PATCH 162/250] Adjust input drum transition slightly. --- osu.Game.Modes.Taiko/UI/InputDrum.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/UI/InputDrum.cs b/osu.Game.Modes.Taiko/UI/InputDrum.cs index 1787670c7a..2e4c2232fa 100644 --- a/osu.Game.Modes.Taiko/UI/InputDrum.cs +++ b/osu.Game.Modes.Taiko/UI/InputDrum.cs @@ -139,7 +139,7 @@ namespace osu.Game.Modes.Taiko.UI { target.FadeTo(Math.Min(target.Alpha + 0.4f, 1), 40, EasingTypes.OutQuint); target.Delay(40); - target.FadeOut(600, EasingTypes.OutQuint); + target.FadeOut(1000, EasingTypes.OutQuint); } return false; From cc5154dd12bee125b5d0371dd0babbce7de0e6aa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2017 17:48:18 +0900 Subject: [PATCH 163/250] Fix regression in mouse dragging behaviour. --- osu.Game/Graphics/Cursor/MenuCursor.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 3ab6fa7093..39d0cf181c 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -20,9 +20,11 @@ namespace osu.Game.Graphics.Cursor { protected override Drawable CreateCursor() => new Cursor(); + private bool dragging; + protected override bool OnMouseMove(InputState state) { - if (state.Mouse.HasMainButtonPressed) + 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; @@ -39,6 +41,12 @@ namespace osu.Game.Graphics.Cursor return base.OnMouseMove(state); } + protected override bool OnDragStart(InputState state) + { + dragging = true; + return base.OnDragStart(state); + } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { ActiveCursor.Scale = new Vector2(1); @@ -53,6 +61,8 @@ namespace osu.Game.Graphics.Cursor { if (!state.Mouse.HasMainButtonPressed) { + dragging = false; + ((Cursor)ActiveCursor).AdditiveLayer.FadeOut(500, EasingTypes.OutQuint); ActiveCursor.RotateTo(0, 600 * (1 + Math.Abs(ActiveCursor.Rotation / 720)), EasingTypes.OutElasticHalf); ActiveCursor.ScaleTo(1, 500, EasingTypes.OutElastic); From 0ad070c2d83101d4d820c31755f21d794f598723 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 27 Mar 2017 22:22:34 +0900 Subject: [PATCH 164/250] Update grade textures. --- osu-resources | 2 +- osu.Game/Screens/Select/Leaderboards/DrawableRank.cs | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/osu-resources b/osu-resources index 2d8a6c1699..e674531595 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 2d8a6c1699ff1acd3915fc28e8906dabf1b145a3 +Subproject commit e67453159540f5008b5efadfbc12dfb3f4bee1f7 diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 6b59af0bb4..fd8a24f213 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -13,14 +13,14 @@ namespace osu.Game.Screens.Select.Leaderboards { public class DrawableRank : Container { - private readonly Sprite sprite; + private readonly Sprite rankSprite; public ScoreRank Rank { get; private set; } [BackgroundDependencyLoader] private void load(TextureStore textures) { - sprite.Texture = textures.Get($@"Badges/ScoreRanks/{Rank.GetDescription()}"); + rankSprite.Texture = textures.Get($@"Grades/{Rank.GetDescription()}"); } public DrawableRank(ScoreRank rank) @@ -29,10 +29,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new Drawable[] { - sprite = new Sprite - { - RelativeSizeAxes = Axes.Both, - }, + rankSprite = new Sprite { FillMode = FillMode.Fill }, }; } } From 55df07a8720da80706fb32d8a993db0cdcc3d8c4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 00:03:09 +0900 Subject: [PATCH 165/250] Fix username being cleared when it shouldn't be. --- osu.Game/Online/API/APIAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index f39dec47e1..087bae3071 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -118,7 +118,7 @@ namespace osu.Game.Online.API //todo: this fails even on network-related issues. we should probably handle those differently. //NotificationManager.ShowMessage("Login failed!"); log.Add(@"Login failed!"); - clearCredentials(); + Password = null; continue; } From 039f4a65dc5b83c2f437b00ecec3a14e263ebd4b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 00:04:07 +0900 Subject: [PATCH 166/250] Combine user models. --- osu.Game/Online/API/APIAccess.cs | 1 + .../Online/API/Requests/GetUserRequest.cs | 2 ++ osu.Game/Online/Chat/Drawables/ChatLine.cs | 2 +- osu.Game/Online/Chat/Message.cs | 1 + osu.Game/Online/User.cs | 19 ------------------- osu.Game/Users/User.cs | 12 +++++++++++- osu.Game/osu.Game.csproj | 3 +-- 7 files changed, 17 insertions(+), 23 deletions(-) delete mode 100644 osu.Game/Online/User.cs diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 087bae3071..c4b679fc92 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -12,6 +12,7 @@ using osu.Framework.Configuration; using osu.Framework.Logging; using osu.Framework.Threading; using osu.Game.Online.API.Requests; +using osu.Game.Users; namespace osu.Game.Online.API { diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index e396c56b53..2fd1ee5efc 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.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.Users; + namespace osu.Game.Online.API.Requests { public class GetUserRequest : APIRequest diff --git a/osu.Game/Online/Chat/Drawables/ChatLine.cs b/osu.Game/Online/Chat/Drawables/ChatLine.cs index 9f78be92d1..bfbcf3d707 100644 --- a/osu.Game/Online/Chat/Drawables/ChatLine.cs +++ b/osu.Game/Online/Chat/Drawables/ChatLine.cs @@ -91,7 +91,7 @@ namespace osu.Game.Online.Chat.Drawables new OsuSpriteText { Font = @"Exo2.0-BoldItalic", - Text = $@"{Message.User.Name}:", + Text = $@"{Message.User.Username}:", Colour = getUsernameColour(Message), TextSize = text_size, Origin = Anchor.TopRight, diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 3081653c34..b267cf63ac 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -3,6 +3,7 @@ using System; using Newtonsoft.Json; +using osu.Game.Users; namespace osu.Game.Online.Chat { diff --git a/osu.Game/Online/User.cs b/osu.Game/Online/User.cs deleted file mode 100644 index 0059f940a5..0000000000 --- a/osu.Game/Online/User.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using Newtonsoft.Json; - -namespace osu.Game.Online -{ - public class User - { - [JsonProperty(@"username")] - public string Name; - - [JsonProperty(@"id")] - public int Id; - - [JsonProperty(@"colour")] - public string Colour; - } -} diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 2763b3100f..6e1de7e3ac 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -1,13 +1,23 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using Newtonsoft.Json; + namespace osu.Game.Users { public class User { - public int Id; + [JsonProperty(@"id")] + public long Id = 1; + + [JsonProperty(@"username")] public string Username; + public Country Country; + public Team Team; + + [JsonProperty(@"colour")] + public string Colour; } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 32dd814fdc..7cb55aaa89 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -247,7 +247,6 @@ - @@ -396,4 +395,4 @@ --> - + \ No newline at end of file From 13272e699575203fdbc87c4367886d7dd7995ff9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 00:04:51 +0900 Subject: [PATCH 167/250] Make Avatar accept a user. Add UpdateableAvatar to handle the toolbar use-case. --- .../Overlays/Toolbar/ToolbarUserButton.cs | 8 +- .../Select/Leaderboards/LeaderboardScore.cs | 3 +- osu.Game/Users/Avatar.cs | 103 +++++++----------- osu.Game/Users/UpdateableAvatar.cs | 43 ++++++++ osu.Game/osu.Game.csproj | 1 + 5 files changed, 87 insertions(+), 71 deletions(-) create mode 100644 osu.Game/Users/UpdateableAvatar.cs diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 7e266a2b43..4e59f87bee 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -14,7 +14,7 @@ namespace osu.Game.Overlays.Toolbar { internal class ToolbarUserButton : ToolbarButton, IOnlineComponent { - private readonly Avatar avatar; + private readonly UpdateableAvatar avatar; public ToolbarUserButton() { @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Toolbar Add(new OpaqueBackground { Depth = 1 }); - Flow.Add(avatar = new Avatar + Flow.Add(avatar = new UpdateableAvatar { Masking = true, Size = new Vector2(32), @@ -52,11 +52,11 @@ namespace osu.Game.Overlays.Toolbar { default: Text = @"Guest"; - avatar.UserId = 1; + avatar.User = new User(); break; case APIState.Online: Text = api.Username; - avatar.UserId = api.LocalUser.Value.Id; + avatar.User = api.LocalUser; break; } } diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 1df6d2b55c..c31ebc6095 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -142,7 +142,7 @@ namespace osu.Game.Screens.Select.Leaderboards Padding = new MarginPadding(edge_margin), Children = new Drawable[] { - avatar = new Avatar + avatar = new Avatar(Score.User ?? new User { Id = Score.UserID }) { Size = new Vector2(HEIGHT - edge_margin * 2, HEIGHT - edge_margin * 2), CornerRadius = corner_radius, @@ -153,7 +153,6 @@ namespace osu.Game.Screens.Select.Leaderboards Radius = 1, Colour = Color4.Black.Opacity(0.2f), }, - UserId = Score.User?.Id ?? Score.UserID, }, new Container { diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index a6ce9f1e41..2ac17cd23f 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.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.Diagnostics; +using System; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -13,68 +13,60 @@ namespace osu.Game.Users { public class Avatar : Container { - public Drawable Sprite; + private const int time_before_load = 500; - private long userId; - private OsuGameBase game; - private Texture guestTexture; + private Drawable sprite; + private readonly User user; + private readonly bool delayedLoad; - [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuGameBase game, TextureStore textures) + /// + /// An avatar for specified user. + /// + /// The user. A null value will get a placeholder avatar. + /// Whether we should delay the load of the avatar until it has been on-screen for a specified duration. + public Avatar(User user = null, bool delayedLoad = true) { - this.game = game; - guestTexture = textures.Get(@"Online/avatar-guest"); - } - - public long UserId - { - get { return userId; } - set - { - if (userId == value) - return; - - userId = value; - invalidateSprite(); - } + this.user = user; + this.delayedLoad = delayedLoad; } + private Action performLoad; private Task loadTask; - private void invalidateSprite() + [BackgroundDependencyLoader(permitNulls: true)] + private void load(TextureStore textures) { - Sprite?.FadeOut(100); - Sprite?.Expire(); - Sprite = null; - } - - private void updateSprite() - { - if (loadTask != null || Sprite != null) return; - - var newSprite = userId > 1 ? new OnlineSprite($@"https://a.ppy.sh/{userId}", guestTexture) : new Sprite { Texture = guestTexture }; - - newSprite.FillMode = FillMode.Fill; - - loadTask = newSprite.LoadAsync(game, s => + performLoad = () => { - Sprite = s; - Add(Sprite); + Texture texture = null; + if (user?.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); + if (texture == null) texture = textures.Get(@"Online/avatar-guest"); - Sprite.FadeInFromZero(200); - loadTask = null; - }); + sprite = new Sprite + { + Texture = texture, + FillMode = FillMode.Fit, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + + Schedule(() => + { + Add(sprite); + sprite.FadeInFromZero(150); + }); + }; } private double timeVisible; - private bool shouldUpdate => Sprite != null || timeVisible > 500; + private bool shouldLoad => !delayedLoad || timeVisible > time_before_load; protected override void Update() { base.Update(); - if (!shouldUpdate) + if (!shouldLoad) { //Special optimisation to not start loading until we are within bounds of our closest ScrollContainer parent. ScrollContainer scroll = null; @@ -88,27 +80,8 @@ namespace osu.Game.Users timeVisible = 0; } - if (shouldUpdate) - updateSprite(); - } - - public class OnlineSprite : Sprite - { - private readonly string url; - private readonly Texture fallbackTexture; - - public OnlineSprite(string url, Texture fallbackTexture = null) - { - Debug.Assert(url != null); - this.url = url; - this.fallbackTexture = fallbackTexture; - } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - Texture = textures.Get(url) ?? fallbackTexture; - } + if (shouldLoad && loadTask == null) + (loadTask = Task.Factory.StartNew(performLoad, TaskCreationOptions.LongRunning)).ConfigureAwait(false); } } } diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs new file mode 100644 index 0000000000..cf6448dac7 --- /dev/null +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -0,0 +1,43 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Users +{ + /// + /// An avatar which can update to a new user when needed. + /// + public class UpdateableAvatar : Container + { + private Avatar displayedAvatar; + + private User user; + + public User User + { + get { return user; } + set + { + if (user?.Id == value?.Id) + return; + + user = value; + + if (IsLoaded) + updateAvatar(); + } + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateAvatar(); + } + + private void updateAvatar() + { + displayedAvatar?.FadeOut(300); + displayedAvatar?.Expire(); + Add(displayedAvatar = new Avatar(user, false) { RelativeSizeAxes = Axes.Both }); + } + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 7cb55aaa89..a5bdf1df69 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -266,6 +266,7 @@ + From 768b3c4b4b554a5cbd6dc8d2fc1267921d422abd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 00:05:11 +0900 Subject: [PATCH 168/250] Add better focus handling in the login form. --- osu.Game/Overlays/LoginOverlay.cs | 2 ++ .../Options/Sections/General/LoginOptions.cs | 27 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index fec1c5ec6e..4ceb8092a1 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -67,6 +67,8 @@ namespace osu.Game.Overlays optionsSection.Bounding = true; FadeIn(transition_time, EasingTypes.OutQuint); + + optionsSection.TriggerFocus(); } protected override void PopOut() diff --git a/osu.Game/Overlays/Options/Sections/General/LoginOptions.cs b/osu.Game/Overlays/Options/Sections/General/LoginOptions.cs index f95d3a026e..a5e38dd284 100644 --- a/osu.Game/Overlays/Options/Sections/General/LoginOptions.cs +++ b/osu.Game/Overlays/Options/Sections/General/LoginOptions.cs @@ -11,12 +11,14 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using OpenTK; +using osu.Framework.Input; namespace osu.Game.Overlays.Options.Sections.General { public class LoginOptions : OptionsSubsection, IOnlineComponent { private bool bounding = true; + private LoginForm form; protected override string Header => "Account"; @@ -40,12 +42,14 @@ namespace osu.Game.Overlays.Options.Sections.General public void APIStateChanged(APIAccess api, APIState state) { + form = null; + switch (state) { case APIState.Offline: Children = new Drawable[] { - new LoginForm() + form = new LoginForm() }; break; case APIState.Failing: @@ -82,6 +86,14 @@ namespace osu.Game.Overlays.Options.Sections.General }; break; } + + form?.TriggerFocus(); + } + + protected override bool OnFocus(InputState state) + { + form?.TriggerFocus(); + return base.OnFocus(state); } private class LoginForm : FillFlowContainer @@ -144,6 +156,19 @@ namespace osu.Game.Overlays.Options.Sections.General } }; } + + protected override bool OnFocus(InputState state) + { + Schedule(() => + { + if (string.IsNullOrEmpty(username.Text)) + username.TriggerFocus(); + else + password.TriggerFocus(); + }); + + return base.OnFocus(state); + } } } } From 36af868f447d72f29641b61fbac609df837e26b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 00:13:38 +0900 Subject: [PATCH 169/250] Add missing licence header. --- osu.Game/Users/UpdateableAvatar.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index cf6448dac7..265c177ced 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; namespace osu.Game.Users From 4bb60607e16498bc6b5527faeab2deb87c06d3ff Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 09:50:43 +0900 Subject: [PATCH 170/250] Add property to make the div2 internal. --- .../Objects/Drawable/DrawableDrumRollTick.cs | 4 ++-- osu.Game.Modes.Taiko/Objects/DrumRollTick.cs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs index fe7ed855f5..1e270c6751 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -24,12 +24,12 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { if (!userTriggered) { - if (Judgement.TimeOffset > tick.TickTimeDistance / 2) + if (Judgement.TimeOffset > tick.HitWindow) Judgement.Result = HitResult.Miss; return; } - if (Math.Abs(Judgement.TimeOffset) < tick.TickTimeDistance / 2) + if (Math.Abs(Judgement.TimeOffset) < tick.HitWindow) { Judgement.Result = HitResult.Hit; Judgement.TaikoResult = TaikoHitResult.Great; diff --git a/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs index 66a2d16fe1..2ca0d71fc1 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs @@ -15,5 +15,10 @@ namespace osu.Game.Modes.Taiko.Objects /// Half of this value is the hit window of the tick. /// public double TickTimeDistance; + + /// + /// The time allowed to hit this tick. + /// + public double HitWindow => TickTimeDistance / 2; } } \ No newline at end of file From 4c7e523d1870c3691cdff4c06a3f617cd5a9c294 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 10:02:41 +0900 Subject: [PATCH 171/250] Rename Accented to Strong. --- .../Tests/TestCaseTaikoHitObjects.cs | 8 ++++---- .../Beatmaps/TaikoBeatmapConverter.cs | 8 ++++---- ...DrawableAccentedHit.cs => DrawableStrongHit.cs} | 6 +++--- ...AccentedCirclePiece.cs => StrongCirclePiece.cs} | 14 +++++++------- osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs | 6 +++--- .../Scoring/TaikoScoreProcessor.cs | 8 ++++---- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) rename osu.Game.Modes.Taiko/Objects/Drawable/{DrawableAccentedHit.cs => DrawableStrongHit.cs} (88%) rename osu.Game.Modes.Taiko/Objects/Drawable/Pieces/{AccentedCirclePiece.cs => StrongCirclePiece.cs} (64%) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index edd9c74485..0204058b8a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -38,7 +38,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(100, 100) }); - Add(new CentreHitCircle(new AccentedCirclePiece() + Add(new CentreHitCircle(new StrongCirclePiece() { KiaiMode = kiai }) @@ -54,7 +54,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(100, 300) }); - Add(new RimHitCircle(new AccentedCirclePiece() + Add(new RimHitCircle(new StrongCirclePiece() { KiaiMode = kiai }) @@ -70,7 +70,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(100, 500) }); - Add(new SwellCircle(new AccentedCirclePiece() + Add(new SwellCircle(new StrongCirclePiece() { KiaiMode = kiai }) @@ -87,7 +87,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(575, 100) }); - Add(new DrumRollCircle(new AccentedCirclePiece() + Add(new DrumRollCircle(new StrongCirclePiece() { KiaiMode = kiai }) diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 9b143e9fde..1fc2db53fa 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -44,7 +44,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps IHasRepeats repeatsData = original as IHasRepeats; IHasEndTime endTimeData = original as IHasEndTime; - bool accented = ((original.Sample?.Type ?? SampleType.None) & SampleType.Finish) > 0; + bool strong = ((original.Sample?.Type ?? SampleType.None) & SampleType.Finish) > 0; if (distanceData != null) { @@ -52,7 +52,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps { StartTime = original.StartTime, Sample = original.Sample, - Accented = accented, + IsStrong = strong, Distance = distanceData.Distance * (repeatsData?.RepeatCount ?? 1) }; @@ -65,7 +65,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps { StartTime = original.StartTime, Sample = original.Sample, - Accented = accented, + IsStrong = strong, EndTime = original.StartTime + endTimeData.Duration * bash_convert_factor }; @@ -75,7 +75,7 @@ namespace osu.Game.Modes.Taiko.Beatmaps { StartTime = original.StartTime, Sample = original.Sample, - Accented = accented + IsStrong = strong }; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs similarity index 88% rename from osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs rename to osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs index 9d9c67a7f4..5e225e1dce 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableAccentedHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs @@ -8,7 +8,7 @@ using osu.Framework.Input; namespace osu.Game.Modes.Taiko.Objects.Drawable { - public abstract class DrawableAccentedHit : DrawableHit + public abstract class DrawableStrongHit : DrawableHit { /// /// The lenience for the second key press. @@ -20,7 +20,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private bool firstKeyHeld; private Key firstHitKey; - protected DrawableAccentedHit(Hit hit) + protected DrawableStrongHit(Hit hit) : base(hit) { } @@ -71,7 +71,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable if (!HitKeys.Contains(key)) return false; - // Assume the intention was to hit the accented hit with both keys only if the first key is still being held down + // 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); } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/AccentedCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs similarity index 64% rename from osu.Game.Modes.Taiko/Objects/Drawable/Pieces/AccentedCirclePiece.cs rename to osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs index c02cbc572a..319ca17cb8 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/AccentedCirclePiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/StrongCirclePiece.cs @@ -6,20 +6,20 @@ using OpenTK; namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces { /// - /// A type of circle piece which is drawn at a higher scale as an "accent". + /// A type of circle piece which is drawn at a higher scale to represent a "strong" piece. /// - public class AccentedCirclePiece : CirclePiece + public class StrongCirclePiece : CirclePiece { /// - /// The amount to scale up the base circle to show it as an "accented" piece. + /// The amount to scale up the base circle to show it as a "strong" piece. /// - private const float accent_scale = 1.5f; + private const float strong_scale = 1.5f; - public AccentedCirclePiece() + public StrongCirclePiece() { - SymbolContainer.Scale = new Vector2(accent_scale); + SymbolContainer.Scale = new Vector2(strong_scale); } - public override Vector2 Size => new Vector2(base.Size.X, base.Size.Y * accent_scale); + public override Vector2 Size => new Vector2(base.Size.X, base.Size.Y * strong_scale); } } diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs index 0ec1c2b93c..28077db1ba 100644 --- a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs @@ -20,10 +20,10 @@ namespace osu.Game.Modes.Taiko.Objects public double PreEmpt; /// - /// Whether this HitObject is accented. - /// Accented hit objects give more points for hitting the hit object with both keys. + /// Whether this HitObject is a "strong" type. + /// Strong hit objects give more points for hitting the hit object with both keys. /// - public bool Accented; + public bool IsStrong; /// /// Whether this HitObject is in Kiai time. diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs index a3759d9c81..2ab31c5efb 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs @@ -128,7 +128,7 @@ namespace osu.Game.Modes.Taiko.Scoring hpIncreaseGood = hpMultiplierNormal * hp_hit_good; hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); - var accentedHits = beatmap.HitObjects.FindAll(o => o is Hit && o.Accented); + var accentedHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong); // This is a linear function that awards: // 10 times bonus points for hitting an accented hit object with both keys with 30 accented hit objects in the map @@ -143,7 +143,7 @@ namespace osu.Game.Modes.Taiko.Scoring { Result = HitResult.Hit, TaikoResult = TaikoHitResult.Great, - SecondHit = obj.Accented + SecondHit = obj.IsStrong }); } else if (obj is DrumRoll) @@ -154,7 +154,7 @@ namespace osu.Game.Modes.Taiko.Scoring { Result = HitResult.Hit, TaikoResult = TaikoHitResult.Great, - SecondHit = obj.Accented + SecondHit = obj.IsStrong }); } @@ -162,7 +162,7 @@ namespace osu.Game.Modes.Taiko.Scoring { Result = HitResult.Hit, TaikoResult = TaikoHitResult.Great, - SecondHit = obj.Accented + SecondHit = obj.IsStrong }); } else if (obj is Swell) diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index b32288c2d9..fa09ae2c82 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -53,8 +53,8 @@ - - + + From 542cff0976fdbc5e0a8e8d9edcc2ada87599bd25 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 10:32:01 +0900 Subject: [PATCH 172/250] Move consts to CirclePiece. --- osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs index 453ab7a05d..ec98feddae 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs @@ -20,6 +20,10 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces /// public class CirclePiece : Container { + public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; + public const float SYMBOL_BORDER = 8; + public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER; + private Color4 accentColour; /// /// The colour of the inner circle and outer glows. From 2211c084416802a9b98af717a0e356de3170cb2d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 10:32:27 +0900 Subject: [PATCH 173/250] Properly set playfield scale. --- osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index b7fac507d6..d4abdb5ead 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -173,6 +173,7 @@ namespace osu.Game.Modes.Taiko.UI public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; + h.Scale = new Vector2(PLAYFIELD_SCALE); base.Add(h); } From 621bcaed59ac9257d4e85cc1a586a7db6e3ff7f5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 10:33:23 +0900 Subject: [PATCH 174/250] Add drawable Hits/StrongHits. --- .../Tests/TestCaseTaikoHitObjects.cs | 43 +++------------- .../Tests/TestCaseTaikoPlayfield.cs | 10 ++++ .../Objects/Drawable/CentreHitCirclePiece.cs | 49 +++++++++++++++++++ .../Objects/Drawable/DrawableCentreHit.cs | 17 +++++++ .../Objects/Drawable/DrawableHit.cs | 34 +++++++++++++ .../Drawable/DrawableStrongCentreHit.cs | 17 +++++++ .../osu.Game.Modes.Taiko.csproj | 3 ++ 7 files changed, 136 insertions(+), 37 deletions(-) create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs create mode 100644 osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 0204058b8a..48d7017f78 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Screens.Testing; using osu.Game.Graphics; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Taiko.Objects.Drawable; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; namespace osu.Desktop.VisualTests.Tests @@ -30,7 +31,7 @@ namespace osu.Desktop.VisualTests.Tests Reset(); }); - Add(new CentreHitCircle(new CirclePiece() + Add(new CentreHitCirclePiece(new CirclePiece() { KiaiMode = kiai }) @@ -38,7 +39,7 @@ namespace osu.Desktop.VisualTests.Tests Position = new Vector2(100, 100) }); - Add(new CentreHitCircle(new StrongCirclePiece() + Add(new CentreHitCirclePiece(new StrongCirclePiece() { KiaiMode = kiai }) @@ -106,7 +107,7 @@ namespace osu.Desktop.VisualTests.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - TextSize = SYMBOL_INNER_SIZE, + TextSize = CirclePiece.SYMBOL_INNER_SIZE, Icon = FontAwesome.fa_asterisk, Shadow = false }); @@ -133,34 +134,6 @@ namespace osu.Desktop.VisualTests.Tests } } - private class CentreHitCircle : BaseCircle - { - public CentreHitCircle(CirclePiece piece) - : base(piece) - { - Piece.Add(new CircularContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(SYMBOL_INNER_SIZE), - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both - } - } - }); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - Piece.AccentColour = colours.PinkDarker; - } - } - private class RimHitCircle : BaseCircle { public RimHitCircle(CirclePiece piece) @@ -170,8 +143,8 @@ namespace osu.Desktop.VisualTests.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Size = new Vector2(SYMBOL_SIZE), - BorderThickness = SYMBOL_BORDER, + Size = new Vector2(CirclePiece.SYMBOL_SIZE), + BorderThickness = CirclePiece.SYMBOL_BORDER, BorderColour = Color4.White, Masking = true, Children = new[] @@ -195,10 +168,6 @@ namespace osu.Desktop.VisualTests.Tests private abstract class BaseCircle : Container { - protected const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; - protected const float SYMBOL_BORDER = 8; - protected const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER; - protected readonly CirclePiece Piece; protected BaseCircle(CirclePiece piece) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 395a0cab13..483c156ea5 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -6,6 +6,7 @@ using osu.Framework.Screens.Testing; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Taiko.Objects.Drawable; using osu.Game.Modes.Taiko.UI; namespace osu.Desktop.VisualTests.Tests @@ -22,6 +23,15 @@ namespace osu.Desktop.VisualTests.Tests AddButton("Hit!", addHitJudgement); AddButton("Miss :(", addMissJudgement); + AddButton("Centre", () => + { + playfield.Add(new DrawableCentreHit(new Hit + { + StartTime = Time.Current + 1000, + PreEmpt = 1000, + IsStrong = false + })); + }); Add(playfield = new TaikoPlayfield { diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs new file mode 100644 index 0000000000..e476430aab --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs @@ -0,0 +1,49 @@ +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + /// + /// A circle piece used for centre hits. + /// + public class CentreHitCirclePiece : Container + { + private CirclePiece circle; + + public CentreHitCirclePiece(CirclePiece piece) + { + Add(circle = piece); + + circle.Add(new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE), + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both + } + } + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + circle.AccentColour = colours.PinkDarker; + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs new file mode 100644 index 0000000000..363ffdd451 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using OpenTK.Input; +using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableCentreHit : DrawableHit + { + protected override List HitKeys { get; } = new List(new Key[] { Key.F, Key.J }); + + public DrawableCentreHit(Hit hit) + : base(hit) + { + Add(new CentreHitCirclePiece(new CirclePiece())); + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index a3ea9e36b9..f455fc8d5b 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -2,6 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Transforms; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using System; @@ -16,6 +19,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// protected abstract List HitKeys { get; } + protected override Container Content => bodyContainer; + private readonly Hit hit; /// @@ -23,10 +28,18 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private bool validKeyPressed; + private Container bodyContainer; + protected DrawableHit(Hit hit) : base(hit) { this.hit = hit; + + AddInternal(bodyContainer = new Container + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }); } protected override void CheckJudgement(bool userTriggered) @@ -63,5 +76,26 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable return UpdateJudgement(true); } + + protected override void UpdateState(ArmedState state) + { + switch (State) + { + case ArmedState.Idle: + break; + case ArmedState.Miss: + bodyContainer.FadeOut(100); + break; + case ArmedState.Hit: + bodyContainer.ScaleTo(0.8f, 400, EasingTypes.OutQuad); + bodyContainer.FadeOut(600, EasingTypes.OutQuint); + bodyContainer.MoveToY(-200, 250, EasingTypes.Out); + + bodyContainer.Delay(250); + + bodyContainer.MoveToY(0, 500, EasingTypes.In); + break; + } + } } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs new file mode 100644 index 0000000000..19a1eec618 --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using OpenTK.Input; +using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; + +namespace osu.Game.Modes.Taiko.Objects.Drawable +{ + public class DrawableStrongCentreHit : DrawableStrongHit + { + protected override List HitKeys { get; } = new List(new Key[] { Key.F, Key.J }); + + public DrawableStrongCentreHit(Hit hit) + : base(hit) + { + Add(new CentreHitCirclePiece(new StrongCirclePiece())); + } + } +} diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index fa09ae2c82..1272c7b079 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,7 +52,10 @@ + + + From 3f1e8ddcd16324558cd7e553861eae3015a1afca Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 28 Mar 2017 10:51:22 +0900 Subject: [PATCH 175/250] License headers + general fixes. --- .../Tests/TestCaseTaikoHitObjects.cs | 1 - .../Objects/Drawable/CentreHitCirclePiece.cs | 12 +++++------- .../Objects/Drawable/DrawableCentreHit.cs | 7 +++++-- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 2 +- .../Objects/Drawable/DrawableStrongCentreHit.cs | 7 +++++-- osu.Game.Modes.Taiko/packages.config | 1 - 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 48d7017f78..96d5ece693 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Screens.Testing; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Objects; using osu.Game.Modes.Taiko.Objects.Drawable; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs index e476430aab..580541546f 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/CentreHitCirclePiece.cs @@ -1,15 +1,13 @@ -using OpenTK; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -18,7 +16,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// public class CentreHitCirclePiece : Container { - private CirclePiece circle; + private readonly CirclePiece circle; public CentreHitCirclePiece(CirclePiece piece) { diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs index 363ffdd451..b3f9974c15 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// 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 OpenTK.Input; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; @@ -6,7 +9,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableCentreHit : DrawableHit { - protected override List HitKeys { get; } = new List(new Key[] { Key.F, Key.J }); + protected override List HitKeys { get; } = new List(new[] { Key.F, Key.J }); public DrawableCentreHit(Hit hit) : base(hit) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index f455fc8d5b..f48993fd45 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -28,7 +28,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// private bool validKeyPressed; - private Container bodyContainer; + private readonly Container bodyContainer; protected DrawableHit(Hit hit) : base(hit) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs index 19a1eec618..2ad4537bce 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// 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 OpenTK.Input; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; @@ -6,7 +9,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableStrongCentreHit : DrawableStrongHit { - protected override List HitKeys { get; } = new List(new Key[] { Key.F, Key.J }); + protected override List HitKeys { get; } = new List(new[] { Key.F, Key.J }); public DrawableStrongCentreHit(Hit hit) : base(hit) diff --git a/osu.Game.Modes.Taiko/packages.config b/osu.Game.Modes.Taiko/packages.config index 08fca09c35..4031dd62a8 100644 --- a/osu.Game.Modes.Taiko/packages.config +++ b/osu.Game.Modes.Taiko/packages.config @@ -1,5 +1,4 @@  - - + \ No newline at end of file From e518508f2d0e86a28dd466e01fcf08b0e49b811b Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 09:11:07 +0900 Subject: [PATCH 193/250] Better life time ends. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 9 +++++---- .../Objects/Drawable/DrawableTaikoHitObject.cs | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index 56e2f329bf..504e3c7c19 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -83,16 +83,17 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable case ArmedState.Idle: break; case ArmedState.Miss: - bodyContainer.FadeOut(100); + FadeOut(100); + Expire(); break; case ArmedState.Hit: bodyContainer.ScaleTo(0.8f, 400, EasingTypes.OutQuad); - bodyContainer.FadeOut(600, EasingTypes.OutQuint); bodyContainer.MoveToY(-200, 250, EasingTypes.Out); - bodyContainer.Delay(250); - bodyContainer.MoveToY(0, 500, EasingTypes.In); + + FadeOut(600); + Expire(); break; } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index c14dc6d7b0..5d6d669dc1 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -30,7 +30,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void LoadComplete() { LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2; - LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt; base.LoadComplete(); } From d74454141bc903aeb37de8404a076542cac8c16c Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 09:12:21 +0900 Subject: [PATCH 194/250] Remove explicit life time end. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs | 2 -- osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs | 1 - 2 files changed, 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 862b81c5dc..b5246321da 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -124,8 +124,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { base.LoadComplete(); - LifetimeEnd = double.MaxValue; - targetRing.Delay(HitObject.StartTime - Time.Current).ScaleTo(target_ring_scale, 600, EasingTypes.OutQuint); } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs index c14dc6d7b0..5d6d669dc1 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableTaikoHitObject.cs @@ -30,7 +30,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void LoadComplete() { LifetimeStart = HitObject.StartTime - HitObject.PreEmpt * 2; - LifetimeEnd = HitObject.StartTime + HitObject.PreEmpt; base.LoadComplete(); } From ab97967237ae3fbe10fca376fa59a42892b070da Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Mar 2017 21:03:34 +0900 Subject: [PATCH 195/250] Update references and framework. --- osu.Desktop.VisualTests/Benchmark.cs | 2 +- .../Tests/TestCaseBeatmapDetailArea.cs | 2 +- .../Tests/TestCaseBeatmapOptionsOverlay.cs | 2 +- .../Tests/TestCaseChatDisplay.cs | 2 +- .../Tests/TestCaseDialogOverlay.cs | 2 +- .../Tests/TestCaseDrawings.cs | 2 +- .../Tests/TestCaseGamefield.cs | 2 +- .../Tests/TestCaseHitObjects.cs | 2 +- .../Tests/TestCaseKeyCounter.cs | 2 +- .../Tests/TestCaseLeaderboard.cs | 2 +- .../Tests/TestCaseMenuButtonSystem.cs | 2 +- .../Tests/TestCaseModSelectOverlay.cs | 2 +- .../Tests/TestCaseMusicController.cs | 2 +- .../Tests/TestCaseNotificationManager.cs | 2 +- .../Tests/TestCaseOptions.cs | 2 +- .../Tests/TestCasePauseOverlay.cs | 2 +- .../Tests/TestCasePlaySongSelect.cs | 2 +- .../Tests/TestCasePlayer.cs | 2 +- .../Tests/TestCaseScoreCounter.cs | 2 +- .../Tests/TestCaseTabControl.cs | 2 +- .../Tests/TestCaseTaikoHitObjects.cs | 2 +- .../Tests/TestCaseTaikoPlayfield.cs | 2 +- .../Tests/TestCaseTextAwesome.cs | 2 +- .../Tests/TestCaseTwoLayerButton.cs | 2 +- osu.Desktop.VisualTests/VisualTestGame.cs | 2 +- .../osu.Desktop.VisualTests.csproj | 8 +++++--- osu.Game/Screens/Menu/MainMenu.cs | 2 -- osu.sln | 19 ++++++++++++++----- 28 files changed, 44 insertions(+), 35 deletions(-) diff --git a/osu.Desktop.VisualTests/Benchmark.cs b/osu.Desktop.VisualTests/Benchmark.cs index 0a15b38fc2..884dff9f7a 100644 --- a/osu.Desktop.VisualTests/Benchmark.cs +++ b/osu.Desktop.VisualTests/Benchmark.cs @@ -3,7 +3,7 @@ using System; using osu.Framework.Allocation; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game; namespace osu.Desktop.VisualTests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs index bb7df19202..e755924a15 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetailArea.cs @@ -3,7 +3,7 @@ using OpenTK; using osu.Framework.Graphics; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Screens.Select; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs index a13f6005bf..3fc6ce10e7 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs @@ -3,7 +3,7 @@ using OpenTK.Graphics; using OpenTK.Input; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Screens.Select.Options; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs index 08765a9b0f..2cb63ba7a0 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseChatDisplay.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; using osu.Game.Overlays; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs index c9edcb8a54..3ae5929ecc 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs index 00e41de254..a0463516de 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawings.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Screens.Tournament; using osu.Game.Screens.Tournament.Teams; using osu.Game.Users; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs index e876c21a12..3129cade63 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs @@ -5,7 +5,7 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Database; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 2a20cad2db..8818240b2d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs index 83ad49fcd2..051db489e9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Graphics; using OpenTK.Input; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs index 329d5c5687..c985375873 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs @@ -3,7 +3,7 @@ using OpenTK; using osu.Framework.Graphics; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Modes.Mods; using osu.Game.Modes.Osu.Mods; using osu.Game.Modes.Scoring; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs index 36dc3945e2..ddb62598cf 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Sprites; using osu.Game.Screens.Menu; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index eaaa531691..73f8ed6242 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics; using osu.Game.Overlays.Mods; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Modes; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs index f44f662321..305aa24252 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Overlays; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs index 13f89153e9..990052012f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Overlays; using System.Linq; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseOptions.cs b/osu.Desktop.VisualTests/Tests/TestCaseOptions.cs index 1b4ecd726a..ff6bdc8a5a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseOptions.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseOptions.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Overlays; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs index ad8039bc66..09e2dc38aa 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Logging; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Screens.Play; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index c97ea929f3..16f7881dcd 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using osu.Desktop.VisualTests.Platform; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Database; using osu.Game.Modes; diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index a08cb3e97e..f36889b02a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Beatmaps; using OpenTK; using osu.Framework.Graphics.Sprites; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs index be313efed3..cca87cd12b 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Modes.UI; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs index da807d5e53..23e7f8a74d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTabControl.cs @@ -3,7 +3,7 @@ using OpenTK; using osu.Framework.Graphics.Primitives; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index edd9c74485..e406fe3a60 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -7,7 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Modes.Taiko.Objects; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 395a0cab13..5a988c54e1 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.MathUtils; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs b/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs index 3ba657d60a..7182ee7c06 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTextAwesome.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs b/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs index 4694a6c6ea..2427b6d12c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTwoLayerButton.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 osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; diff --git a/osu.Desktop.VisualTests/VisualTestGame.cs b/osu.Desktop.VisualTests/VisualTestGame.cs index c41bdeef66..bdce72b3f5 100644 --- a/osu.Desktop.VisualTests/VisualTestGame.cs +++ b/osu.Desktop.VisualTests/VisualTestGame.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Platform; -using osu.Framework.Screens.Testing; +using osu.Framework.Testing; using osu.Game; using osu.Game.Screens.Backgrounds; diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index f1b4a99510..9f3cd6b3c4 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -150,6 +150,10 @@ {65dc628f-a640-4111-ab35-3a5652bc1e17} osu.Framework.Desktop + + {007b2356-ab6f-4bd9-96d5-116fc2dce69a} + osu.Framework.Testing + {c76bf5b3-985e-4d39-95fe-97c9c879b83a} osu.Framework @@ -212,9 +216,7 @@ - - - + - + \ No newline at end of file From 982fcbbf5334583f4b94b8110af4ac5892f7d269 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 15:20:20 +0900 Subject: [PATCH 208/250] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 4d131fd0d9..54830759f8 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 4d131fd0d997bee313de3fa33a45900637570ff0 +Subproject commit 54830759f8a9a248585684de6faf3d9f1976b335 From 7ba7bc18f8468aeba9c6875f15eded270954f363 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 15:35:22 +0900 Subject: [PATCH 209/250] Don't use a List for HitKeys. --- osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs | 1 - osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs | 3 +-- osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs | 4 ++-- osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs | 3 +-- .../Objects/Drawable/DrawableStrongCentreHit.cs | 3 +-- osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs | 3 +-- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 94f09e12a6..5d6ab9bd1a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -6,7 +6,6 @@ using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs index a3fcf26f6d..683d48df10 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableCentreHit.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.Collections.Generic; using OpenTK.Input; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using osu.Game.Graphics; @@ -11,7 +10,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableCentreHit : DrawableHit { - protected override List HitKeys { get; } = new List(new[] { Key.F, Key.J }); + protected override Key[] HitKeys { get; } = { Key.F, Key.J }; private readonly CirclePiece circlePiece; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index 94c5f63deb..ae328fe9ca 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using System; -using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -16,7 +16,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// /// A list of keys which can result in hits for this HitObject. /// - protected abstract List HitKeys { get; } + protected abstract Key[] HitKeys { get; } protected override Container Content => bodyContainer; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs index 029cdfb7e7..cab6819300 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableRimHit.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.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Graphics; using OpenTK.Input; @@ -11,7 +10,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableRimHit : DrawableHit { - protected override List HitKeys { get; } = new List(new[] { Key.D, Key.K }); + protected override Key[] HitKeys { get; } = { Key.D, Key.K }; private readonly CirclePiece circlePiece; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs index 7b21924868..b4ec0b108a 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongCentreHit.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.Collections.Generic; using OpenTK.Input; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using osu.Framework.Allocation; @@ -11,7 +10,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableStrongCentreHit : DrawableStrongHit { - protected override List HitKeys { get; } = new List(new[] { Key.F, Key.J }); + protected override Key[] HitKeys { get; } = { Key.F, Key.J }; private readonly CirclePiece circlePiece; diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs index 74d8cdfd49..1f77ad0409 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongRimHit.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.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Graphics; using OpenTK.Input; @@ -11,7 +10,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { public class DrawableStrongRimHit : DrawableStrongHit { - protected override List HitKeys { get; } = new List(new[] { Key.D, Key.K }); + protected override Key[] HitKeys { get; } = { Key.D, Key.K }; private readonly CirclePiece circlePiece; From 3d2c8f19ae0a13c9f85c4994bf8095d52115ea3d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 15:59:12 +0900 Subject: [PATCH 210/250] Make Swells require alternating key hits. --- .../Objects/Drawable/DrawableSwell.cs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 291e1df837..d1a9760691 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -14,6 +14,7 @@ using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects.Drawable.Pieces; using System; +using System.Linq; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -30,11 +31,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private const float target_ring_scale = 5f; private const float inner_ring_alpha = 0.35f; - /// - /// The amount of times the user has hit this swell. - /// - private int userHits; - private readonly Swell swell; private readonly Container bodyContainer; @@ -43,6 +39,15 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private readonly CirclePiece circlePiece; + private readonly Key[] rimKeys = { Key.D, Key.K }; + private readonly Key[] centreKeys = { Key.F, Key.J }; + private Key[] lastKeySet; + + /// + /// The amount of times the user has hit this swell. + /// + private int userHits; + private bool hasStarted; public DrawableSwell(Swell swell) @@ -206,6 +211,14 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable if (Judgement.Result.HasValue) return false; + // Find the keyset which this key corresponds to + var keySet = rimKeys.Contains(key) ? rimKeys : centreKeys; + + // Ensure alternating keysets + if (keySet == lastKeySet) + return false; + lastKeySet = keySet; + UpdateJudgement(true); return true; From 1b3e908565161f814ba884d3c66bf0ac19848592 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 16:02:12 +0900 Subject: [PATCH 211/250] Fix notelocking by pressing a key before the swell's start time. --- osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index d1a9760691..0462880f3e 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -138,9 +138,6 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { if (userTriggered) { - if (Time.Current < HitObject.StartTime) - return; - userHits++; innerRing.FadeTo(1); @@ -211,6 +208,10 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable if (Judgement.Result.HasValue) return false; + // Don't handle keys before the swell starts + if (Time.Current < HitObject.StartTime) + return false; + // Find the keyset which this key corresponds to var keySet = rimKeys.Contains(key) ? rimKeys : centreKeys; From c5f9c4cac95ed4e70d7f844651fcffaef3f1deeb Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 16:20:54 +0900 Subject: [PATCH 212/250] Fix possible nullref. --- osu.Game.Modes.Taiko/TaikoAutoReplay.cs | 31 ++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs index ba121e0968..04f634be05 100644 --- a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs +++ b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs @@ -4,6 +4,7 @@ using osu.Game.Modes.Taiko.Objects; using osu.Game.Modes.Objects.Types; using osu.Game.Beatmaps; +using System; namespace osu.Game.Modes.Taiko { @@ -34,13 +35,16 @@ namespace osu.Game.Modes.Taiko IHasEndTime endTimeData = h as IHasEndTime; double endTime = endTimeData?.EndTime ?? h.StartTime; - Swell sp = h as Swell; - if (sp != null) + Swell swell = h as Swell; + DrumRoll drumRoll = h as DrumRoll; + Hit hit = h as Hit; + + if (swell != null) { int d = 0; int count = 0; - int req = sp.RequiredHits; - double hitRate = sp.Duration / req; + int req = swell.RequiredHits; + double hitRate = swell.Duration / req; for (double j = h.StartTime; j < endTime; j += hitRate) { switch (d) @@ -65,25 +69,21 @@ namespace osu.Game.Modes.Taiko break; } } - else if (h is DrumRoll) + else if (drumRoll != null) { - DrumRoll d = h as DrumRoll; + double delay = drumRoll.TickTimeDistance; - double delay = d.TickTimeDistance; + double time = drumRoll.StartTime; - double time = d.StartTime; - - for (int j = 0; j < d.TotalTicks; j++) + for (int j = 0; j < drumRoll.TotalTicks; j++) { Frames.Add(new LegacyReplayFrame((int)time, 0, 0, hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2)); time += delay; hitButton = !hitButton; } } - else + else if (hit != null) { - Hit hit = h as Hit; - if (hit.Type == HitType.Centre) { if (h.IsStrong) @@ -101,6 +101,8 @@ namespace osu.Game.Modes.Taiko Frames.Add(new LegacyReplayFrame(h.StartTime, 0, 0, button)); } + else + throw new Exception("Unknown hit object type."); Frames.Add(new LegacyReplayFrame(endTime + 1, 0, 0, LegacyButtonState.None)); @@ -113,9 +115,6 @@ namespace osu.Game.Modes.Taiko hitButton = !hitButton; } - - //Player.currentScore.Replay = InputManager.ReplayScore.Replay; - //Player.currentScore.PlayerName = "mekkadosu!"; } } } \ No newline at end of file From 2967000839b83f5e045c143ba307a0fda8978184 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 16:22:08 +0900 Subject: [PATCH 213/250] Taiko autoplay username :D. --- osu.Game.Modes.Taiko/Mods/TaikoMod.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs index 007187d81b..79370f58ee 100644 --- a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs +++ b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Modes.Mods; using osu.Game.Modes.Scoring; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Users; namespace osu.Game.Modes.Taiko.Mods { @@ -69,6 +70,7 @@ namespace osu.Game.Modes.Taiko.Mods { protected override Score CreateReplayScore(Beatmap beatmap) => new Score { + User = new User { Username = "mekkadosu!" }, Replay = new TaikoAutoReplay(beatmap) }; } From bae0ac490124fe2d6c96a71d9796e07a03f4f25d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 18:21:45 +0900 Subject: [PATCH 214/250] Fix missing base call that may result in invalid ScoreProcessor state. --- osu.Game/Modes/Scoring/ScoreProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Modes/Scoring/ScoreProcessor.cs index f14b306e18..393d651dbf 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Modes/Scoring/ScoreProcessor.cs @@ -152,6 +152,8 @@ namespace osu.Game.Modes.Scoring protected override void Reset() { + base.Reset(); + Judgements.Clear(); } From 305003997279cc9a17797487943afb702c61e995 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 17:57:36 +0900 Subject: [PATCH 215/250] Implement partial judgements + make Result non-nullable. --- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawable/DrawableDrumRollTick.cs | 2 +- .../Objects/Drawable/DrawableHit.cs | 2 +- .../Objects/Drawable/DrawableStrongHit.cs | 5 ++-- .../Objects/Drawable/DrawableSwell.cs | 2 +- .../Modes/Judgements/IPartialJudgement.cs | 26 +++++++++++++++++++ osu.Game/Modes/Judgements/Judgement.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 19 +++++++++++--- osu.Game/Modes/Objects/Drawables/HitResult.cs | 11 ++++++++ osu.Game/Modes/UI/HitRenderer.cs | 2 +- osu.Game/osu.Game.csproj | 1 + 11 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 osu.Game/Modes/Judgements/IPartialJudgement.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index dcc25a997a..68c5ec0a45 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -38,7 +38,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Colour = AccentColour, Hit = () => { - if (Judgement.Result.HasValue) return false; + if (Judgement.Result != HitResult.None) return false; Judgement.PositionOffset = Vector2.Zero; //todo: set to correct value UpdateJudgement(true); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs index 1e270c6751..5217fd9085 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableDrumRollTick.cs @@ -47,7 +47,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - return !Judgement.Result.HasValue && UpdateJudgement(true); + return Judgement.Result == HitResult.None && UpdateJudgement(true); } } } diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs index ae328fe9ca..c8a7355e3c 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs @@ -68,7 +68,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - if (Judgement.Result.HasValue) + if (Judgement.Result != HitResult.None) return false; validKeyPressed = HitKeys.Contains(key); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs index 5e225e1dce..a77fd1d6be 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs @@ -5,6 +5,7 @@ using OpenTK.Input; using System; using System.Linq; using osu.Framework.Input; +using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -27,7 +28,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void CheckJudgement(bool userTriggered) { - if (!Judgement.Result.HasValue) + if (Judgement.Result == HitResult.None) { base.CheckJudgement(userTriggered); return; @@ -45,7 +46,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { // Check if we've handled the first key - if (!Judgement.Result.HasValue) + if (Judgement.Result == HitResult.None) { // First key hasn't been handled yet, attempt to handle it bool handled = base.HandleKeyPress(key); diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 15584ac73f..22fa4dea6f 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -64,7 +64,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override bool HandleKeyPress(Key key) { - if (Judgement.Result.HasValue) + if (Judgement.Result != HitResult.None) return false; UpdateJudgement(true); diff --git a/osu.Game/Modes/Judgements/IPartialJudgement.cs b/osu.Game/Modes/Judgements/IPartialJudgement.cs new file mode 100644 index 0000000000..2ca1ffce4d --- /dev/null +++ b/osu.Game/Modes/Judgements/IPartialJudgement.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Scoring; + +namespace osu.Game.Modes.Judgements +{ + /// + /// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change. + /// + /// This judgement will be continually processed by + /// unless the result is a miss and will trigger a full re-process of the when changed. + /// + /// + public interface IPartialJudgement + { + /// + /// Indicates that this partial judgement has changed and requires a full re-process of the . + /// + /// This is set to false once the judgement has been re-processed. + /// + /// + bool Changed { get; set; } + } +} diff --git a/osu.Game/Modes/Judgements/Judgement.cs b/osu.Game/Modes/Judgements/Judgement.cs index d916fc15de..5b1e4ddac6 100644 --- a/osu.Game/Modes/Judgements/Judgement.cs +++ b/osu.Game/Modes/Judgements/Judgement.cs @@ -10,7 +10,7 @@ namespace osu.Game.Modes.Judgements /// /// Whether this judgement is the result of a hit or a miss. /// - public HitResult? Result; + public HitResult Result; /// /// The offset at which this judgement occurred. diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 3998a3e385..2939980ac6 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -93,16 +93,26 @@ namespace osu.Game.Modes.Objects.Drawables /// Whether a hit was processed. protected bool UpdateJudgement(bool userTriggered) { - if (Judgement.Result != null) + IPartialJudgement partial = Judgement as IPartialJudgement; + + // Never re-process non-partial hits, or partial judgements that were previously judged as misses + if (Judgement.Result != HitResult.None && (partial == null || Judgement.Result == HitResult.Miss)) return false; + // Update the judgement state double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - Judgement.TimeOffset = Time.Current - endTime; + // Update the judgement state + bool hadResult = Judgement.Result != HitResult.None; CheckJudgement(userTriggered); - if (Judgement.Result == null) + // Don't process judgements with no result + if (Judgement.Result == HitResult.None) + return false; + + // Don't process judgements that previously had results but the results were unchanged + if (hadResult && partial?.Changed != true) return false; switch (Judgement.Result) @@ -117,6 +127,9 @@ namespace osu.Game.Modes.Objects.Drawables OnJudgement?.Invoke(this); + if (partial != null) + partial.Changed = false; + return true; } diff --git a/osu.Game/Modes/Objects/Drawables/HitResult.cs b/osu.Game/Modes/Objects/Drawables/HitResult.cs index 1bbf9269bb..e036610ae2 100644 --- a/osu.Game/Modes/Objects/Drawables/HitResult.cs +++ b/osu.Game/Modes/Objects/Drawables/HitResult.cs @@ -7,8 +7,19 @@ namespace osu.Game.Modes.Objects.Drawables { public enum HitResult { + /// + /// Indicates that the object has not been judged yet. + /// + [Description("")] + None, + /// + /// Indicates that the object has been judged as a miss. + /// [Description(@"Miss")] Miss, + /// + /// Indicates that the object has been judged as a hit. + /// [Description(@"Hit")] Hit, } diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 3d108b895d..1681da2ba9 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -149,7 +149,7 @@ namespace osu.Game.Modes.UI public event Action OnJudgement; protected override Container Content => content; - protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result.HasValue); + protected override bool AllObjectsJudged => Playfield.HitObjects.Children.All(h => h.Judgement.Result != HitResult.None); /// /// The playfield. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a5bdf1df69..fcb45f91fd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -97,6 +97,7 @@ + From c0dae89844d603fb6bd486f76d3a2235bafefbe1 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 29 Mar 2017 18:16:26 +0900 Subject: [PATCH 216/250] Implement partial strong hit judgements. --- .../Judgements/TaikoJudgement.cs | 6 ++--- .../Judgements/TaikoStrongHitJudgement.cs | 25 +++++++++++++++++++ .../Objects/Drawable/DrawableStrongHit.cs | 3 +++ .../osu.Game.Modes.Taiko.csproj | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs index e50a685e24..f4745730db 100644 --- a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs @@ -22,7 +22,7 @@ namespace osu.Game.Modes.Taiko.Judgements /// The result value for the combo portion of the score. /// public int ResultValueForScore => NumericResultForScore(TaikoResult); - + /// /// The result value for the accuracy portion of the score. /// @@ -32,7 +32,7 @@ namespace osu.Game.Modes.Taiko.Judgements /// The maximum result value for the combo portion of the score. /// public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT); - + /// /// The maximum result value for the accuracy portion of the score. /// @@ -45,7 +45,7 @@ namespace osu.Game.Modes.Taiko.Judgements /// /// Whether this Judgement has a secondary hit in the case of finishers. /// - public bool SecondHit; + public virtual bool SecondHit { get; set; } /// /// Computes the numeric result value for the combo portion of the score. diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs new file mode 100644 index 0000000000..ee978d0026 --- /dev/null +++ b/osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Judgements; + +namespace osu.Game.Modes.Taiko.Judgements +{ + public class TaikoStrongHitJudgement : TaikoJudgement, IPartialJudgement + { + public bool Changed { get; set; } + + public override bool SecondHit + { + get { return base.SecondHit; } + set + { + if (base.SecondHit == value) + return; + base.SecondHit = value; + + Changed = true; + } + } + } +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs index a77fd1d6be..a6cb6ae7fa 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableStrongHit.cs @@ -6,6 +6,7 @@ using System; using System.Linq; using osu.Framework.Input; using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Judgements; namespace osu.Game.Modes.Taiko.Objects.Drawable { @@ -26,6 +27,8 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { } + protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement(); + protected override void CheckJudgement(bool userTriggered) { if (Judgement.Result == HitResult.None) diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 07f9a5d4e6..60fe8cb51f 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -50,6 +50,7 @@ + From fa7fd6efe30a738675bfd438da53a989a6284caa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2017 19:47:53 +0900 Subject: [PATCH 217/250] Fix mode selector not invoking a re-filter. --- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 5 ++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 3 ++- osu.Game/Screens/Select/FilterControl.cs | 1 + osu.Game/Screens/Select/SongSelect.cs | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index fdcc250d0f..66196670b8 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -199,7 +199,7 @@ namespace osu.Game { Depth = -3, OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); }, - OnPlayModeChange = delegate (PlayMode m) { PlayMode.Value = m; }, + OnPlayModeChange = m => PlayMode.Value = m, }).LoadAsync(this, t => { PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); }; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index be28857de6..d20564bd03 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -65,14 +65,13 @@ namespace osu.Game.Overlays.Toolbar foreach (PlayMode m in Ruleset.PlayModes) { - var localMode = m; modeButtons.Add(new ToolbarModeButton { Mode = m, Action = delegate { - SetGameMode(localMode); - OnPlayModeChange?.Invoke(localMode); + SetGameMode(m); + OnPlayModeChange?.Invoke(m); } }); } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index e947d12f22..24251439ce 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -181,7 +181,8 @@ namespace osu.Game.Screens.Select { if (!IsLoaded) return; - criteria = newCriteria ?? criteria ?? new FilterCriteria(); + if (newCriteria != null) + criteria = newCriteria; Action perform = delegate { diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index d6537ca0d6..5445847da5 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -175,6 +175,7 @@ namespace osu.Game.Screens.Select if (osu != null) playMode.BindTo(osu.PlayMode); + playMode.ValueChanged += (s, e) => FilterChanged?.Invoke(CreateCriteria()); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 6eb26d22cb..656adf0d62 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -276,7 +276,7 @@ namespace osu.Game.Screens.Select initialAddSetsTask.Cancel(); } - private void playMode_ValueChanged(object sender, EventArgs e) => carousel.Filter(); + private void playMode_ValueChanged(object sender, EventArgs e) => Beatmap.PreferredPlayMode = playMode; private void changeBackground(WorkingBeatmap beatmap) { From a6c8be363782605543f9bcdfbbeed3ef33316e23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2017 19:52:16 +0900 Subject: [PATCH 218/250] Increase load delay on panel backgrounds; add back missing fade. --- osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index f8986b2ecd..e26dcac16b 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -36,7 +36,8 @@ namespace osu.Game.Beatmaps.Drawables new DelayedLoadContainer { RelativeSizeAxes = Axes.Both, - TimeBeforeLoad = 100, + TimeBeforeLoad = 300, + FinishedLoading = d => d.FadeInFromZero(400, EasingTypes.Out), Children = new[] { new PanelBackground(beatmap) From 6afa6f30cc19ac5bce67428eaa548346e2425675 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Mar 2017 20:01:46 +0900 Subject: [PATCH 219/250] Keep selected beatmap in centre of screen post-filter. --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 24251439ce..7443603c8b 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -203,6 +203,8 @@ namespace osu.Game.Screens.Select if (selectedGroup == null || selectedGroup.State == BeatmapGroupState.Hidden) SelectNext(); + else + selectGroup(selectedGroup); }; filterTask?.Cancel(); From c2d6faa7c25a1e22640fb50b3f10e9fe5e595537 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 30 Mar 2017 10:34:37 +0900 Subject: [PATCH 220/250] Change Judgements into HashSet to prevent duplicates. --- osu.Game/Modes/Scoring/ScoreProcessor.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Modes/Scoring/ScoreProcessor.cs index f14b306e18..b24ab090b3 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Modes/Scoring/ScoreProcessor.cs @@ -110,7 +110,7 @@ namespace osu.Game.Modes.Scoring /// /// All judgements held by this ScoreProcessor. /// - protected readonly List Judgements = new List(); + protected readonly HashSet Judgements = new HashSet(); public override bool HasFailed => Health.Value == Health.MinValue; @@ -120,8 +120,6 @@ namespace osu.Game.Modes.Scoring protected ScoreProcessor(HitRenderer hitRenderer) { - Judgements.Capacity = hitRenderer.Beatmap.HitObjects.Count; - hitRenderer.OnJudgement += AddJudgement; ComputeTargets(hitRenderer.Beatmap); From 6287ba321da555faf353d801a855179ac58fc8ce Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 30 Mar 2017 10:51:14 +0900 Subject: [PATCH 221/250] Rewrite ScoreProcessor to have a new method for when existing judgements are changed. - OnNewJudgement: Keeps its previous functionality. It is now only invoked when a _new_ judgement has been added to the Judgements hashset. - OnJudgementChanged: Has a similar funcitonality to OnNewJudgement, but is only invoked whenever a judgement that was _previously_ in the Judgements hashset is changed. --- .../Tests/TestCaseTaikoPlayfield.cs | 4 +- .../Scoring/CatchScoreProcessor.cs | 2 +- .../Scoring/ManiaScoreProcessor.cs | 2 +- .../Scoring/OsuScoreProcessor.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 79 ++++++++++++------- osu.Game/Modes/Judgements/Judgement.cs | 2 +- osu.Game/Modes/Scoring/ScoreProcessor.cs | 28 +++++-- 7 files changed, 75 insertions(+), 44 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index a6491bd07b..ca4fee1b4d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -55,7 +55,6 @@ namespace osu.Desktop.VisualTests.Tests Result = HitResult.Hit, TaikoResult = hitResult, TimeOffset = 0, - ComboAtHit = 1, SecondHit = RNG.Next(10) == 0 } }); @@ -68,8 +67,7 @@ namespace osu.Desktop.VisualTests.Tests Judgement = new TaikoJudgement { Result = HitResult.Miss, - TimeOffset = 0, - ComboAtHit = 0 + TimeOffset = 0 } }); } diff --git a/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs index 766a492bf4..1b9bedf7fb 100644 --- a/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Catch.Scoring { } - protected override void OnNewJugement(CatchJudgement judgement) + protected override void OnNewJudgement(CatchJudgement judgement) { } } diff --git a/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs index c6b223af6d..0f87030e25 100644 --- a/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Mania.Scoring { } - protected override void OnNewJugement(ManiaJudgement judgement) + protected override void OnNewJudgement(ManiaJudgement judgement) { } } diff --git a/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs index b71e7dbadd..0bd587e8ea 100644 --- a/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs @@ -28,7 +28,7 @@ namespace osu.Game.Modes.Osu.Scoring Accuracy.Value = 1; } - protected override void OnNewJugement(OsuJudgement judgement) + protected override void OnNewJudgement(OsuJudgement judgement) { if (judgement != null) { diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs index 2ab31c5efb..fa7e18cadb 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs @@ -96,9 +96,9 @@ namespace osu.Game.Modes.Taiko.Scoring /// /// The multiple of the original score added to the combo portion of the score - /// for correctly hitting an accented hit object with both keys. + /// for correctly hitting a strong hit object with both keys. /// - private double accentedHitScale; + private double strongHitScale; private double hpIncreaseTick; private double hpIncreaseGreat; @@ -128,12 +128,12 @@ namespace osu.Game.Modes.Taiko.Scoring hpIncreaseGood = hpMultiplierNormal * hp_hit_good; hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); - var accentedHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong); + var strongHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong); // This is a linear function that awards: - // 10 times bonus points for hitting an accented hit object with both keys with 30 accented hit objects in the map - // 3 times bonus points for hitting an accented hit object with both keys with 120 accented hit objects in the map - accentedHitScale = -7d / 90d * MathHelper.Clamp(accentedHits.Count, 30, 120) + 111d / 9d; + // 10 times bonus points for hitting a strong hit object with both keys with 30 strong hit objects in the map + // 3 times bonus points for hitting a strong hit object with both keys with 120 strong hit objects in the map + strongHitScale = -7d / 90d * MathHelper.Clamp(strongHits.Count, 30, 120) + 111d / 9d; foreach (var obj in beatmap.HitObjects) { @@ -179,7 +179,7 @@ namespace osu.Game.Modes.Taiko.Scoring maxComboPortion = comboPortion; } - protected override void OnNewJugement(TaikoJudgement judgement) + protected override void OnNewJudgement(TaikoJudgement judgement) { bool isTick = judgement is TaikoDrumRollTickJudgement; @@ -187,29 +187,12 @@ namespace osu.Game.Modes.Taiko.Scoring if (!isTick) totalHits++; + // Apply combo changes, must be done before the hit score is added + if (!isTick && judgement.Result == HitResult.Hit) + Combo.Value++; + // Apply score changes - if (judgement.Result == HitResult.Hit) - { - double baseValue = judgement.ResultValueForScore; - - // Add bonus points for hitting an accented hit object with the second key - if (judgement.SecondHit) - baseValue += baseValue * accentedHitScale; - - // Add score to portions - if (isTick) - bonusScore += baseValue; - else - { - Combo.Value++; - - // A relevance factor that needs to be applied to make higher combos more relevant - // Value is capped at 400 combo - double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base))); - - comboPortion += baseValue * comboRelevance; - } - } + addHitScore(judgement); // Apply HP changes switch (judgement.Result) @@ -235,7 +218,43 @@ namespace osu.Game.Modes.Taiko.Scoring break; } - // Compute the new score + accuracy + calculateScore(); + } + + protected override void OnJudgementChanged(TaikoJudgement judgement) + { + // Apply score changes + addHitScore(judgement); + + calculateScore(); + } + + private void addHitScore(TaikoJudgement judgement) + { + if (judgement.Result != HitResult.Hit) + return; + + double baseValue = judgement.ResultValueForScore; + + // Add increased score for hitting a strong hit object with the second key + if (judgement.SecondHit) + baseValue *= strongHitScale; + + // Add score to portions + if (judgement is TaikoDrumRollTickJudgement) + bonusScore += baseValue; + else + { + // A relevance factor that needs to be applied to make higher combos more relevant + // Value is capped at 400 combo + double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base))); + + comboPortion += baseValue * comboRelevance; + } + } + + private void calculateScore() + { int scoreForAccuracy = 0; int maxScoreForAccuracy = 0; diff --git a/osu.Game/Modes/Judgements/Judgement.cs b/osu.Game/Modes/Judgements/Judgement.cs index 5b1e4ddac6..677ec8bca9 100644 --- a/osu.Game/Modes/Judgements/Judgement.cs +++ b/osu.Game/Modes/Judgements/Judgement.cs @@ -20,7 +20,7 @@ namespace osu.Game.Modes.Judgements /// /// The combo after this judgement was processed. /// - public ulong? ComboAtHit; + public int ComboAtHit; /// /// The string representation for the result achieved. diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Modes/Scoring/ScoreProcessor.cs index b24ab090b3..4e902596ce 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Modes/Scoring/ScoreProcessor.cs @@ -139,11 +139,13 @@ namespace osu.Game.Modes.Scoring /// The judgement to add. protected void AddJudgement(TJudgement judgement) { - Judgements.Add(judgement); - - OnNewJugement(judgement); - - judgement.ComboAtHit = (ulong)Combo.Value; + if (Judgements.Add(judgement)) + { + OnNewJudgement(judgement); + judgement.ComboAtHit = Combo.Value; + } + else + OnJudgementChanged(judgement); UpdateFailed(); } @@ -154,9 +156,21 @@ namespace osu.Game.Modes.Scoring } /// - /// Update any values that potentially need post-processing on a judgement change. + /// Updates any values that need post-processing. Invoked when a new judgement has occurred. + /// + /// This is not triggered when existing judgements are changed - for that see . + /// /// /// The judgement that triggered this calculation. - protected abstract void OnNewJugement(TJudgement judgement); + protected abstract void OnNewJudgement(TJudgement judgement); + + /// + /// Updates any values that need post-processing. Invoked when an existing judgement has changed. + /// + /// This is not triggered when a new judgement has occurred - for that see . + /// + /// + /// The judgement that triggered this calculation. + protected virtual void OnJudgementChanged(TJudgement judgement) { } } } \ No newline at end of file From cf4d11c51c3d71abcdcd48798a3b19ad6437aada Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 30 Mar 2017 15:51:16 +0900 Subject: [PATCH 222/250] Add explicit CentreHit/RimHit classes. --- .../Beatmaps/TaikoBeatmapConverter.cs | 15 ++++++++++++--- .../Objects/{HitType.cs => CentreHit.cs} | 7 +------ osu.Game.Modes.Taiko/Objects/Hit.cs | 5 ----- osu.Game.Modes.Taiko/Objects/RimHit.cs | 9 +++++++++ osu.Game.Modes.Taiko/TaikoAutoReplay.cs | 2 +- osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj | 3 ++- 6 files changed, 25 insertions(+), 16 deletions(-) rename osu.Game.Modes.Taiko/Objects/{HitType.cs => CentreHit.cs} (55%) create mode 100644 osu.Game.Modes.Taiko/Objects/RimHit.cs diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs index aa095a1dda..cc361628a3 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -74,14 +74,23 @@ namespace osu.Game.Modes.Taiko.Beatmaps }; } - HitType type = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0 ? HitType.Centre : HitType.Rim; + bool isCentre = (sample & ~(SampleType.Finish | SampleType.Normal)) == 0; - return new Hit + if (isCentre) + { + return new CentreHit + { + StartTime = original.StartTime, + Sample = original.Sample, + IsStrong = strong + }; + } + + return new RimHit { StartTime = original.StartTime, Sample = original.Sample, IsStrong = strong, - Type = type }; } } diff --git a/osu.Game.Modes.Taiko/Objects/HitType.cs b/osu.Game.Modes.Taiko/Objects/CentreHit.cs similarity index 55% rename from osu.Game.Modes.Taiko/Objects/HitType.cs rename to osu.Game.Modes.Taiko/Objects/CentreHit.cs index 6e8e147d75..258112f045 100644 --- a/osu.Game.Modes.Taiko/Objects/HitType.cs +++ b/osu.Game.Modes.Taiko/Objects/CentreHit.cs @@ -3,12 +3,7 @@ namespace osu.Game.Modes.Taiko.Objects { - /// - /// Describes whether a hit is a centre-hit or a rim-hit. - /// - public enum HitType + public class CentreHit : Hit { - Centre, - Rim } } diff --git a/osu.Game.Modes.Taiko/Objects/Hit.cs b/osu.Game.Modes.Taiko/Objects/Hit.cs index 0ba07028fd..ad8d07d901 100644 --- a/osu.Game.Modes.Taiko/Objects/Hit.cs +++ b/osu.Game.Modes.Taiko/Objects/Hit.cs @@ -8,11 +8,6 @@ namespace osu.Game.Modes.Taiko.Objects { public class Hit : TaikoHitObject { - /// - /// Whether this hit is a centre-hit or a rim-hit. - /// - public HitType Type; - /// /// The hit window that results in a "GREAT" hit. /// diff --git a/osu.Game.Modes.Taiko/Objects/RimHit.cs b/osu.Game.Modes.Taiko/Objects/RimHit.cs new file mode 100644 index 0000000000..aae93ec10d --- /dev/null +++ b/osu.Game.Modes.Taiko/Objects/RimHit.cs @@ -0,0 +1,9 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Modes.Taiko.Objects +{ + public class RimHit : Hit + { + } +} diff --git a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs index 04f634be05..b30f26a9d3 100644 --- a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs +++ b/osu.Game.Modes.Taiko/TaikoAutoReplay.cs @@ -84,7 +84,7 @@ namespace osu.Game.Modes.Taiko } else if (hit != null) { - if (hit.Type == HitType.Centre) + if (hit is CentreHit) { if (h.IsStrong) button = LegacyButtonState.Right1 | LegacyButtonState.Right2; diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index 9ff16989af..a892cedf22 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -53,6 +53,7 @@ + @@ -70,7 +71,7 @@ - + From f3599b080ccbf60454ec73435fab938eb8e5014d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 30 Mar 2017 16:12:21 +0900 Subject: [PATCH 223/250] Fix using. --- osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index 5bf12ce586..e8e32ebf3d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -4,7 +4,6 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; using osu.Game.Graphics; From 76d0beb64f12dc2a3adbb3436ff4a634a56656b9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Thu, 30 Mar 2017 19:03:16 +0900 Subject: [PATCH 224/250] Fix custom transform. --- osu-framework | 2 +- osu.Game/Screens/Tournament/ScrollingTeamContainer.cs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/osu-framework b/osu-framework index 4d131fd0d9..269a1fd192 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 4d131fd0d997bee313de3fa33a45900637570ff0 +Subproject commit 269a1fd192c573d558a5ab0ff990a8b462947287 diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index 4d965bf3a5..b80f76d281 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -298,9 +298,7 @@ namespace osu.Game.Screens.Tournament private void speedTo(float value, double duration = 0, EasingTypes easing = EasingTypes.None) { DelayReset(); - - UpdateTransformsOfType(typeof(TransformScrollSpeed)); - TransformFloatTo(speed, value, duration, easing, new TransformScrollSpeed()); + TransformTo(speed, value, duration, easing, new TransformScrollSpeed()); } private enum ScrollState From e57de373a8c372bc211ab0b2eff2bc3693789a41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 09:02:55 +0900 Subject: [PATCH 225/250] Add opentk to osu.Desktop's packages. --- osu.Desktop/OpenTK.dll.config | 29 +++++++++++++++++++++++++++++ osu.Desktop/osu.Desktop.csproj | 3 ++- osu.Desktop/packages.config | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 osu.Desktop/OpenTK.dll.config diff --git a/osu.Desktop/OpenTK.dll.config b/osu.Desktop/OpenTK.dll.config new file mode 100644 index 0000000000..627e9f6009 --- /dev/null +++ b/osu.Desktop/OpenTK.dll.config @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index b02032cbb1..fbc342d695 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -153,6 +153,7 @@ osu.licenseheader + @@ -248,4 +249,4 @@ - + \ No newline at end of file diff --git a/osu.Desktop/packages.config b/osu.Desktop/packages.config index bdeaf1de89..be9b65f0c6 100644 --- a/osu.Desktop/packages.config +++ b/osu.Desktop/packages.config @@ -7,6 +7,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste + \ No newline at end of file From d944b8c1922bbc88098223159a2291048c8cd753 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 11:01:42 +0900 Subject: [PATCH 226/250] Implement IAccented interface + transform. --- osu-framework | 2 +- osu.Game/Graphics/IAccented.cs | 36 ++++++++++++++++++ .../Graphics/Transforms/TransformAccent.cs | 37 +++++++++++++++++++ .../UserInterface/PercentageCounter.cs | 2 +- .../Graphics/UserInterface/ScoreCounter.cs | 2 +- osu.Game/Modes/UI/ComboCounter.cs | 2 +- osu.Game/Modes/UI/ComboResultCounter.cs | 2 +- osu.Game/osu.Game.csproj | 2 + 8 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Graphics/IAccented.cs create mode 100644 osu.Game/Graphics/Transforms/TransformAccent.cs diff --git a/osu-framework b/osu-framework index 269a1fd192..3931f8e358 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 269a1fd192c573d558a5ab0ff990a8b462947287 +Subproject commit 3931f8e358365b1853a76e1d141fcf4c929a2143 diff --git a/osu.Game/Graphics/IAccented.cs b/osu.Game/Graphics/IAccented.cs new file mode 100644 index 0000000000..6f0f107f3c --- /dev/null +++ b/osu.Game/Graphics/IAccented.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Game.Graphics.Transforms; + +namespace osu.Game.Graphics +{ + /// + /// A type of drawable that has an accent colour. + /// The accent colour is used to colorize various objects inside a drawable + /// without colorizing the drawable itself. + /// + public interface IAccented : IDrawable + { + Color4 AccentColour { get; set; } + } + + public static class AccentedExtensions + { + /// + /// Tweens the accent colour of a drawable to another colour. + /// + /// The type of drawable. + /// The drawable to apply the accent colour to. + /// The new accent colour. + /// The tween duration. + /// The tween easing. + public static void FadeAccent(this TDrawable drawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None) + where TDrawable : Drawable, IAccented + { + drawable.TransformTo(drawable.AccentColour, newColour, duration, easing, new TransformAccent()); + } + } +} diff --git a/osu.Game/Graphics/Transforms/TransformAccent.cs b/osu.Game/Graphics/Transforms/TransformAccent.cs new file mode 100644 index 0000000000..7f40a0a016 --- /dev/null +++ b/osu.Game/Graphics/Transforms/TransformAccent.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; +using osu.Framework.MathUtils; + +namespace osu.Game.Graphics.Transforms +{ + public class TransformAccent : Transform + { + /// + /// Current value of the transformed colour in linear colour space. + /// + public override Color4 CurrentValue + { + get + { + double time = Time?.Current ?? 0; + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + } + + public override void Apply(Drawable d) + { + base.Apply(d); + + var accented = d as IAccented; + if (accented != null) + accented.AccentColour = CurrentValue; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 66c9e7d461..c32b654840 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -47,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface protected class TransformAccuracy : Transform { - protected override double CurrentValue + public override double CurrentValue { get { diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index c9a1040185..c2b1b026b6 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface protected class TransformScore : Transform { - protected override double CurrentValue + public override double CurrentValue { get { diff --git a/osu.Game/Modes/UI/ComboCounter.cs b/osu.Game/Modes/UI/ComboCounter.cs index f831677e44..3629634889 100644 --- a/osu.Game/Modes/UI/ComboCounter.cs +++ b/osu.Game/Modes/UI/ComboCounter.cs @@ -213,7 +213,7 @@ namespace osu.Game.Modes.UI protected class TransformComboRoll : Transform { - protected override int CurrentValue + public override int CurrentValue { get { diff --git a/osu.Game/Modes/UI/ComboResultCounter.cs b/osu.Game/Modes/UI/ComboResultCounter.cs index 957a720c94..63009c5351 100644 --- a/osu.Game/Modes/UI/ComboResultCounter.cs +++ b/osu.Game/Modes/UI/ComboResultCounter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Modes.UI protected class TransformComboResult : Transform { - protected override ulong CurrentValue + public override ulong CurrentValue { get { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a5bdf1df69..00c189d01c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -82,7 +82,9 @@ + + From b54201cbe388603c5349eaf81dd4fd8a95779d23 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 11:09:02 +0900 Subject: [PATCH 227/250] Appease resharpoo. --- osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs index ec98feddae..20e16ae03c 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Backgrounds; using OpenTK.Graphics; using System; +using osu.Game.Graphics; namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces { @@ -18,7 +19,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces /// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0. /// /// - public class CirclePiece : Container + public class CirclePiece : Container, IAccented { public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; public const float SYMBOL_BORDER = 8; From b48def16275378e131ce2ed9157796a7c687eaab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 11:19:33 +0900 Subject: [PATCH 228/250] Align SwellSymbolPiece better for rotation. --- osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs index ba7f5b8df9..2bd86406a7 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/SwellSymbolPiece.cs @@ -15,6 +15,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces { Anchor = Anchor.Centre; Origin = Anchor.Centre; + UseFullGlyphHeight = true; TextSize = CirclePiece.SYMBOL_INNER_SIZE; Icon = FontAwesome.fa_asterisk; Shadow = false; From bcd7e41bf78956e2a3ed643cece478f0471834db Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 11:20:04 +0900 Subject: [PATCH 229/250] Visual adjustments to DrawableSwell. --- .../Objects/Drawable/DrawableSwell.cs | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs index 0462880f3e..d789d12c90 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableSwell.cs @@ -26,16 +26,16 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable /// public event Action OnStart; - private const float target_ring_thick_border = 4f; + private const float target_ring_thick_border = 1.4f; private const float target_ring_thin_border = 1f; private const float target_ring_scale = 5f; - private const float inner_ring_alpha = 0.35f; + private const float inner_ring_alpha = 0.65f; private readonly Swell swell; private readonly Container bodyContainer; private readonly CircularContainer targetRing; - private readonly CircularContainer innerRing; + private readonly CircularContainer expandingRing; private readonly CirclePiece circlePiece; @@ -49,6 +49,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private int userHits; private bool hasStarted; + private readonly SwellSymbolPiece symbol; public DrawableSwell(Swell swell) : base(swell) @@ -61,12 +62,14 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { Children = new Framework.Graphics.Drawable[] { - innerRing = new CircularContainer + expandingRing = new CircularContainer { - Name = "Inner ring", + Name = "Expanding ring", Anchor = Anchor.Centre, Origin = Anchor.Centre, + Alpha = 0, Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2), + BlendingMode = BlendingMode.Additive, Masking = true, Children = new [] { @@ -85,6 +88,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable Size = new Vector2(TaikoHitObject.CIRCLE_RADIUS * 2), Masking = true, BorderThickness = target_ring_thick_border, + BlendingMode = BlendingMode.Additive, Children = new Framework.Graphics.Drawable[] { new Box @@ -118,7 +122,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { Children = new [] { - new SwellSymbolPiece() + symbol = new SwellSymbolPiece() } } } @@ -130,7 +134,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable private void load(OsuColour colours) { circlePiece.AccentColour = colours.YellowDark; - innerRing.Colour = colours.YellowDark; + expandingRing.Colour = colours.YellowLight; targetRing.BorderColour = colours.YellowDark.Opacity(0.25f); } @@ -140,9 +144,16 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable { userHits++; - innerRing.FadeTo(1); - innerRing.FadeTo(inner_ring_alpha, 500, EasingTypes.OutQuint); - innerRing.ScaleTo(1f + (target_ring_scale - 1) * userHits / swell.RequiredHits, 1200, EasingTypes.OutElastic); + var completion = (float)userHits / swell.RequiredHits; + + expandingRing.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50); + expandingRing.Delay(50); + expandingRing.FadeTo(completion / 8, 2000, EasingTypes.OutQuint); + expandingRing.DelayReset(); + + symbol.RotateTo((float)(completion * swell.Duration / 8), 4000, EasingTypes.OutQuint); + + expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, EasingTypes.OutQuint); if (userHits == swell.RequiredHits) { @@ -168,23 +179,26 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable protected override void UpdateState(ArmedState state) { - const float preempt = 300; + const float preempt = 100; Delay(HitObject.StartTime - Time.Current - preempt, true); - targetRing.ScaleTo(target_ring_scale, preempt, EasingTypes.Out); + targetRing.ScaleTo(target_ring_scale, preempt * 4, EasingTypes.OutQuint); + Delay(preempt, true); Delay(Judgement.TimeOffset + swell.Duration, true); + const float out_transition_time = 300; + switch (state) { case ArmedState.Hit: - bodyContainer.ScaleTo(1.2f, 400, EasingTypes.OutQuad); + bodyContainer.ScaleTo(1.4f, out_transition_time); break; } - FadeOut(600); + FadeOut(out_transition_time, EasingTypes.Out); Expire(); } From 591ecc0ef4087899f69068b25a07d3e4ca578983 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 11:48:54 +0900 Subject: [PATCH 230/250] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 3931f8e358..591b799f95 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 3931f8e358365b1853a76e1d141fcf4c929a2143 +Subproject commit 591b799f95a47e5da893c82d024e01311c9c37c6 From c2dbbc608a85e430ad19ac21e63757ab52a828b9 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 11:50:31 +0900 Subject: [PATCH 231/250] General fixes. --- osu.Game.Modes.Taiko/LegacyTaikoReplay.cs | 27 ++++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs b/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs index 0b59c9ddd4..38a28270b3 100644 --- a/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs +++ b/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs @@ -29,19 +29,24 @@ namespace osu.Game.Modes.Taiko { } - public override List GetPendingStates() => new List + public override List GetPendingStates() { - new InputState + var keys = new List(); + + if (CurrentFrame?.MouseRight1 == true) + keys.Add(Key.F); + if (CurrentFrame?.MouseRight2 == true) + keys.Add(Key.J); + if (CurrentFrame?.MouseLeft1 == true) + keys.Add(Key.D); + if (CurrentFrame?.MouseLeft2 == true) + keys.Add(Key.K); + + return new List { - Keyboard = new ReplayKeyboardState(new List(new[] - { - CurrentFrame?.MouseRight1 == true ? Key.F : Key.Unknown, - CurrentFrame?.MouseRight2 == true ? Key.J : Key.Unknown, - CurrentFrame?.MouseLeft1 == true ? Key.D : Key.Unknown, - CurrentFrame?.MouseLeft2 == true ? Key.K : Key.Unknown - })) - } - }; + new InputState { Keyboard = new ReplayKeyboardState(keys) } + }; + } } } } From 49575c34476adb06e3d81789bfbac8cd2b733304 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 11:54:12 +0900 Subject: [PATCH 232/250] Special case not needed. --- osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 2939980ac6..ed8269876e 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -95,8 +95,8 @@ namespace osu.Game.Modes.Objects.Drawables { IPartialJudgement partial = Judgement as IPartialJudgement; - // Never re-process non-partial hits, or partial judgements that were previously judged as misses - if (Judgement.Result != HitResult.None && (partial == null || Judgement.Result == HitResult.Miss)) + // Never re-process non-partial hits + if (Judgement.Result != HitResult.None && partial == null) return false; // Update the judgement state From cd915a32bef6b2f8bead9b4d6007528c21011b93 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 11:58:24 +0900 Subject: [PATCH 233/250] Let's use a List for now. --- osu.Game/Modes/Scoring/ScoreProcessor.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Modes/Scoring/ScoreProcessor.cs index 314d4fa194..4c42f2a384 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Modes/Scoring/ScoreProcessor.cs @@ -110,7 +110,7 @@ namespace osu.Game.Modes.Scoring /// /// All judgements held by this ScoreProcessor. /// - protected readonly HashSet Judgements = new HashSet(); + protected readonly List Judgements = new List(); public override bool HasFailed => Health.Value == Health.MinValue; @@ -139,9 +139,13 @@ namespace osu.Game.Modes.Scoring /// The judgement to add. protected void AddJudgement(TJudgement judgement) { - if (Judgements.Add(judgement)) + bool exists = Judgements.Contains(judgement); + + if (!exists) { + Judgements.Add(judgement); OnNewJudgement(judgement); + judgement.ComboAtHit = Combo.Value; } else From e7ecc479c9bad2681f9b2c6211efd54c9f5bc2d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 12:43:42 +0900 Subject: [PATCH 234/250] Add FramedReplay and use where legacy is not needed. --- osu.Game.Modes.Osu/OsuAutoReplay.cs | 63 ++++---- .../FramedReplay.cs} | 134 ++---------------- osu.Game/Modes/Replays/LegacyFramedReplay.cs | 70 +++++++++ osu.Game/Modes/{ => Replays}/Replay.cs | 2 +- osu.Game/Modes/Replays/ReplayButtonState.cs | 18 +++ osu.Game/Modes/Replays/ReplayFrame.cs | 71 ++++++++++ osu.Game/Modes/Scoring/Score.cs | 1 + osu.Game/osu.Game.csproj | 7 +- 8 files changed, 209 insertions(+), 157 deletions(-) rename osu.Game/Modes/{LegacyReplay.cs => Replays/FramedReplay.cs} (53%) create mode 100644 osu.Game/Modes/Replays/LegacyFramedReplay.cs rename osu.Game/Modes/{ => Replays}/Replay.cs (87%) create mode 100644 osu.Game/Modes/Replays/ReplayButtonState.cs create mode 100644 osu.Game/Modes/Replays/ReplayFrame.cs diff --git a/osu.Game.Modes.Osu/OsuAutoReplay.cs b/osu.Game.Modes.Osu/OsuAutoReplay.cs index 86985c834a..2ac5f771c3 100644 --- a/osu.Game.Modes.Osu/OsuAutoReplay.cs +++ b/osu.Game.Modes.Osu/OsuAutoReplay.cs @@ -11,10 +11,11 @@ using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Graphics; using osu.Game.Modes.Objects.Types; +using osu.Game.Modes.Replays; namespace osu.Game.Modes.Osu { - public class OsuAutoReplay : LegacyReplay + public class OsuAutoReplay : FramedReplay { private static readonly Vector2 spinner_centre = new Vector2(256, 192); @@ -29,17 +30,17 @@ namespace osu.Game.Modes.Osu createAutoReplay(); } - private class LegacyReplayFrameComparer : IComparer + private class ReplayFrameComparer : IComparer { - public int Compare(LegacyReplayFrame f1, LegacyReplayFrame f2) + public int Compare(ReplayFrame f1, ReplayFrame f2) { return f1.Time.CompareTo(f2.Time); } } - private static readonly IComparer replay_frame_comparer = new LegacyReplayFrameComparer(); + private static readonly IComparer replay_frame_comparer = new ReplayFrameComparer(); - private int findInsertionIndex(LegacyReplayFrame frame) + private int findInsertionIndex(ReplayFrame frame) { int index = Frames.BinarySearch(frame, replay_frame_comparer); @@ -59,7 +60,7 @@ namespace osu.Game.Modes.Osu return index; } - private void addFrameToReplay(LegacyReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame); + private void addFrameToReplay(ReplayFrame frame) => Frames.Insert(findInsertionIndex(frame), frame); private static Vector2 circlePosition(double t, double radius) => new Vector2((float)(Math.Cos(t) * radius), (float)(Math.Sin(t) * radius)); @@ -74,9 +75,9 @@ namespace osu.Game.Modes.Osu EasingTypes preferredEasing = DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out; - addFrameToReplay(new LegacyReplayFrame(-100000, 256, 500, LegacyButtonState.None)); - addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, LegacyButtonState.None)); - addFrameToReplay(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, LegacyButtonState.None)); + addFrameToReplay(new ReplayFrame(-100000, 256, 500, ReplayButtonState.None)); + addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1500, 256, 500, ReplayButtonState.None)); + addFrameToReplay(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 256, 192, ReplayButtonState.None)); // We are using ApplyModsToRate and not ApplyModsToTime to counteract the speed up / slow down from HalfTime / DoubleTime so that we remain at a constant framerate of 60 fps. float frameDelay = (float)applyModsToRate(1000.0 / 60.0); @@ -106,18 +107,18 @@ namespace osu.Game.Modes.Osu //Make the cursor stay at a hitObject as long as possible (mainly for autopilot). if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50) { - if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None)); - if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, LegacyButtonState.None)); + if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.Position.X, h.Position.Y, ReplayButtonState.None)); } else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50) { - if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None)); - if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, LegacyButtonState.None)); + if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.Position.X, h.Position.Y, ReplayButtonState.None)); } else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50) { - if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new LegacyReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, LegacyButtonState.None)); - if (!(h is Spinner)) addFrameToReplay(new LegacyReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, LegacyButtonState.None)); + if (!(last is Spinner) && h.StartTime - endTime < 1000) addFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), last.EndPosition.X, last.EndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) addFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.Position.X, h.Position.Y, ReplayButtonState.None)); } } @@ -173,13 +174,13 @@ namespace osu.Game.Modes.Osu // Do some nice easing for cursor movements if (Frames.Count > 0) { - LegacyReplayFrame lastFrame = Frames[Frames.Count - 1]; + ReplayFrame lastFrame = Frames[Frames.Count - 1]; // Wait until Auto could "see and react" to the next note. double waitTime = h.StartTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime); if (waitTime > lastFrame.Time) { - lastFrame = new LegacyReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); + lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); addFrameToReplay(lastFrame); } @@ -196,7 +197,7 @@ namespace osu.Game.Modes.Osu for (double time = lastFrame.Time + frameDelay; time < h.StartTime; time += frameDelay) { Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPosition, lastFrame.Time, h.StartTime, easing); - addFrameToReplay(new LegacyReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); + addFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); } buttonIndex = 0; @@ -207,12 +208,12 @@ namespace osu.Game.Modes.Osu } } - LegacyButtonState button = buttonIndex % 2 == 0 ? LegacyButtonState.Left1 : LegacyButtonState.Right1; + ReplayButtonState button = buttonIndex % 2 == 0 ? ReplayButtonState.Left1 : ReplayButtonState.Right1; double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime; - LegacyReplayFrame newFrame = new LegacyReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button); - LegacyReplayFrame endFrame = new LegacyReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, LegacyButtonState.None); + ReplayFrame newFrame = new ReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button); + ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, ReplayButtonState.None); // Decrement because we want the previous frame, not the next one int index = findInsertionIndex(newFrame) - 1; @@ -220,19 +221,19 @@ namespace osu.Game.Modes.Osu // Do we have a previous frame? No need to check for < replay.Count since we decremented! if (index >= 0) { - LegacyReplayFrame previousFrame = Frames[index]; + ReplayFrame previousFrame = Frames[index]; var previousButton = previousFrame.ButtonState; // If a button is already held, then we simply alternate - if (previousButton != LegacyButtonState.None) + if (previousButton != ReplayButtonState.None) { - Debug.Assert(previousButton != (LegacyButtonState.Left1 | LegacyButtonState.Right1)); + Debug.Assert(previousButton != (ReplayButtonState.Left1 | ReplayButtonState.Right1)); // Force alternation if we have the same button. Otherwise we can just keep the naturally to us assigned button. if (previousButton == button) { - button = (LegacyButtonState.Left1 | LegacyButtonState.Right1) & ~button; - newFrame.SetButtonStates(button); + button = (ReplayButtonState.Left1 | ReplayButtonState.Right1) & ~button; + newFrame.ButtonState = button; } // We always follow the most recent slider / spinner, so remove any other frames that occur while it exists. @@ -246,7 +247,7 @@ namespace osu.Game.Modes.Osu { // Don't affect frames which stop pressing a button! if (j < Frames.Count - 1 || Frames[j].ButtonState == previousButton) - Frames[j].SetButtonStates(button); + Frames[j].ButtonState = button; } } } @@ -270,13 +271,13 @@ namespace osu.Game.Modes.Osu t = applyModsToTime(j - h.StartTime) * spinnerDirection; Vector2 pos = spinner_centre + circlePosition(t / 20 + angle, spin_radius); - addFrameToReplay(new LegacyReplayFrame((int)j, pos.X, pos.Y, button)); + addFrameToReplay(new ReplayFrame((int)j, pos.X, pos.Y, button)); } t = applyModsToTime(s.EndTime - h.StartTime) * spinnerDirection; Vector2 endPosition = spinner_centre + circlePosition(t / 20 + angle, spin_radius); - addFrameToReplay(new LegacyReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button)); + addFrameToReplay(new ReplayFrame(s.EndTime, endPosition.X, endPosition.Y, button)); endFrame.MouseX = endPosition.X; endFrame.MouseY = endPosition.Y; @@ -288,10 +289,10 @@ namespace osu.Game.Modes.Osu for (double j = frameDelay; j < s.Duration; j += frameDelay) { Vector2 pos = s.PositionAt(j / s.Duration); - addFrameToReplay(new LegacyReplayFrame(h.StartTime + j, pos.X, pos.Y, button)); + addFrameToReplay(new ReplayFrame(h.StartTime + j, pos.X, pos.Y, button)); } - addFrameToReplay(new LegacyReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button)); + addFrameToReplay(new ReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button)); } // We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed! diff --git a/osu.Game/Modes/LegacyReplay.cs b/osu.Game/Modes/Replays/FramedReplay.cs similarity index 53% rename from osu.Game/Modes/LegacyReplay.cs rename to osu.Game/Modes/Replays/FramedReplay.cs index d57d4a15d2..26144d1ed7 100644 --- a/osu.Game/Modes/LegacyReplay.cs +++ b/osu.Game/Modes/Replays/FramedReplay.cs @@ -3,67 +3,39 @@ using System; using System.Collections.Generic; -using System.IO; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Input.Handlers; -using osu.Game.IO.Legacy; using OpenTK; using OpenTK.Input; using KeyboardState = osu.Framework.Input.KeyboardState; using MouseState = osu.Framework.Input.MouseState; -namespace osu.Game.Modes +namespace osu.Game.Modes.Replays { - public class LegacyReplay : Replay + public abstract class FramedReplay : Replay { - protected List Frames = new List(); + protected List Frames = new List(); - protected LegacyReplay() - { - - } - - public LegacyReplay(StreamReader reader) - { - float lastTime = 0; - - foreach (var l in reader.ReadToEnd().Split(',')) - { - var split = l.Split('|'); - - if (split.Length < 4 || float.Parse(split[0]) < 0) continue; - - lastTime += float.Parse(split[0]); - - Frames.Add(new LegacyReplayFrame( - lastTime, - float.Parse(split[1]), - 384 - float.Parse(split[2]), - (LegacyButtonState)int.Parse(split[3]) - )); - } - } - - public override ReplayInputHandler CreateInputHandler() => new LegacyReplayInputHandler(Frames); + public override ReplayInputHandler CreateInputHandler() => new FramedReplayInputHandler(Frames); /// /// The ReplayHandler will take a replay and handle the propagation of updates to the input stack. /// It handles logic of any frames which *must* be executed. /// - protected class LegacyReplayInputHandler : ReplayInputHandler + public class FramedReplayInputHandler : ReplayInputHandler { - private readonly List replayContent; + private readonly List replayContent; - public LegacyReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex]; - public LegacyReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex]; + public ReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex]; + public ReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex]; private int currentFrameIndex; private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, replayContent.Count - 1); - public LegacyReplayInputHandler(List replayContent) + public FramedReplayInputHandler(List replayContent) { this.replayContent = replayContent; } @@ -133,7 +105,7 @@ namespace osu.Game.Modes private bool inImportantSection => FrameAccuratePlayback && //a button is in a pressed state - (currentDirection > 0 ? CurrentFrame : NextFrame)?.ButtonState > LegacyButtonState.None && + ((currentDirection > 0 ? CurrentFrame : NextFrame)?.IsImportant ?? false) && //the next frame is within an allowable time span Math.Abs(currentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2; @@ -180,89 +152,5 @@ namespace osu.Game.Modes } } } - - [Flags] - protected enum LegacyButtonState - { - None = 0, - Left1 = 1, - Right1 = 2, - Left2 = 4, - Right2 = 8, - Smoke = 16 - } - - protected class LegacyReplayFrame - { - public Vector2 Position => new Vector2(MouseX, MouseY); - - public float MouseX; - public float MouseY; - public bool MouseLeft; - public bool MouseRight; - public bool MouseLeft1; - public bool MouseRight1; - public bool MouseLeft2; - public bool MouseRight2; - public LegacyButtonState ButtonState; - public double Time; - - public LegacyReplayFrame(double time, float posX, float posY, LegacyButtonState buttonState) - { - MouseX = posX; - MouseY = posY; - ButtonState = buttonState; - SetButtonStates(buttonState); - Time = time; - } - - public void SetButtonStates(LegacyButtonState buttonState) - { - ButtonState = buttonState; - MouseLeft = (buttonState & (LegacyButtonState.Left1 | LegacyButtonState.Left2)) > 0; - MouseLeft1 = (buttonState & LegacyButtonState.Left1) > 0; - MouseLeft2 = (buttonState & LegacyButtonState.Left2) > 0; - MouseRight = (buttonState & (LegacyButtonState.Right1 | LegacyButtonState.Right2)) > 0; - MouseRight1 = (buttonState & LegacyButtonState.Right1) > 0; - MouseRight2 = (buttonState & LegacyButtonState.Right2) > 0; - } - - public LegacyReplayFrame(Stream s) : this(new SerializationReader(s)) - { - } - - public LegacyReplayFrame(SerializationReader sr) - { - ButtonState = (LegacyButtonState)sr.ReadByte(); - SetButtonStates(ButtonState); - - byte bt = sr.ReadByte(); - if (bt > 0)//Handle Pre-Taiko compatible replays. - SetButtonStates(LegacyButtonState.Right1); - - MouseX = sr.ReadSingle(); - MouseY = sr.ReadSingle(); - Time = sr.ReadInt32(); - } - - public void ReadFromStream(SerializationReader sr) - { - throw new NotImplementedException(); - } - - public void WriteToStream(SerializationWriter sw) - { - sw.Write((byte)ButtonState); - sw.Write((byte)0); - sw.Write(MouseX); - sw.Write(MouseY); - sw.Write(Time); - } - - public override string ToString() - { - return $"{Time}\t({MouseX},{MouseY})\t{MouseLeft}\t{MouseRight}\t{MouseLeft1}\t{MouseRight1}\t{MouseLeft2}\t{MouseRight2}\t{ButtonState}"; - } - } } -} +} \ No newline at end of file diff --git a/osu.Game/Modes/Replays/LegacyFramedReplay.cs b/osu.Game/Modes/Replays/LegacyFramedReplay.cs new file mode 100644 index 0000000000..3e93751e09 --- /dev/null +++ b/osu.Game/Modes/Replays/LegacyFramedReplay.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.IO; +using osu.Game.IO.Legacy; + +namespace osu.Game.Modes.Replays +{ + /// + /// Reads a replay from a legacy replay file (.osr v1) + /// + public class LegacyReplay : FramedReplay + { + public LegacyReplay(StreamReader reader) + { + float lastTime = 0; + + foreach (var l in reader.ReadToEnd().Split(',')) + { + var split = l.Split('|'); + + if (split.Length < 4 || float.Parse(split[0]) < 0) continue; + + lastTime += float.Parse(split[0]); + + Frames.Add(new ReplayFrame( + lastTime, + float.Parse(split[1]), + 384 - float.Parse(split[2]), + (ReplayButtonState)int.Parse(split[3]) + )); + } + } + + public class LegacyReplayFrame : ReplayFrame + { + public LegacyReplayFrame(Stream s) : this(new SerializationReader(s)) + { + } + + public LegacyReplayFrame(SerializationReader sr) + { + ButtonState = (ReplayButtonState)sr.ReadByte(); + + byte bt = sr.ReadByte(); + if (bt > 0)//Handle Pre-Taiko compatible replays. + ButtonState = ReplayButtonState.Right1; + + MouseX = sr.ReadSingle(); + MouseY = sr.ReadSingle(); + Time = sr.ReadInt32(); + } + + public void ReadFromStream(SerializationReader sr) + { + throw new NotImplementedException(); + } + + public void WriteToStream(SerializationWriter sw) + { + sw.Write((byte)ButtonState); + sw.Write((byte)0); + sw.Write(MouseX); + sw.Write(MouseY); + sw.Write(Time); + } + } + } +} diff --git a/osu.Game/Modes/Replay.cs b/osu.Game/Modes/Replays/Replay.cs similarity index 87% rename from osu.Game/Modes/Replay.cs rename to osu.Game/Modes/Replays/Replay.cs index 6d93afdeb9..c1ae952b77 100644 --- a/osu.Game/Modes/Replay.cs +++ b/osu.Game/Modes/Replays/Replay.cs @@ -3,7 +3,7 @@ using osu.Game.Input.Handlers; -namespace osu.Game.Modes +namespace osu.Game.Modes.Replays { public abstract class Replay { diff --git a/osu.Game/Modes/Replays/ReplayButtonState.cs b/osu.Game/Modes/Replays/ReplayButtonState.cs new file mode 100644 index 0000000000..d49139226c --- /dev/null +++ b/osu.Game/Modes/Replays/ReplayButtonState.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; + +namespace osu.Game.Modes.Replays +{ + [Flags] + public enum ReplayButtonState + { + None = 0, + Left1 = 1, + Right1 = 2, + Left2 = 4, + Right2 = 8, + Smoke = 16 + } +} \ No newline at end of file diff --git a/osu.Game/Modes/Replays/ReplayFrame.cs b/osu.Game/Modes/Replays/ReplayFrame.cs new file mode 100644 index 0000000000..4cd681beaf --- /dev/null +++ b/osu.Game/Modes/Replays/ReplayFrame.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; + +namespace osu.Game.Modes.Replays +{ + public class ReplayFrame + { + public Vector2 Position => new Vector2(MouseX, MouseY); + + public bool IsImportant => MouseLeft || MouseRight; + + public float MouseX; + public float MouseY; + + public bool MouseLeft => MouseLeft1 || MouseLeft2; + public bool MouseRight => MouseRight1 || MouseRight2; + + public bool MouseLeft1 + { + get { return (ButtonState & ReplayButtonState.Left1) > 0; } + set { setButtonState(ReplayButtonState.Left1, value); } + } + public bool MouseRight1 + { + get { return (ButtonState & ReplayButtonState.Right1) > 0; } + set { setButtonState(ReplayButtonState.Right1, value); } + } + public bool MouseLeft2 + { + get { return (ButtonState & ReplayButtonState.Left2) > 0; } + set { setButtonState(ReplayButtonState.Left2, value); } + } + public bool MouseRight2 + { + get { return (ButtonState & ReplayButtonState.Right2) > 0; } + set { setButtonState(ReplayButtonState.Right2, value); } + } + + private void setButtonState(ReplayButtonState singleButton, bool pressed) + { + if (pressed) + ButtonState |= singleButton; + else + ButtonState &= ~singleButton; + } + + public double Time; + + public ReplayButtonState ButtonState; + + protected ReplayFrame() + { + + } + + public ReplayFrame(double time, float posX, float posY, ReplayButtonState buttonState) + { + MouseX = posX; + MouseY = posY; + ButtonState = buttonState; + Time = time; + } + + public override string ToString() + { + return $"{Time}\t({MouseX},{MouseY})\t{MouseLeft}\t{MouseRight}\t{MouseLeft1}\t{MouseRight1}\t{MouseLeft2}\t{MouseRight2}\t{ButtonState}"; + } + } +} \ No newline at end of file diff --git a/osu.Game/Modes/Scoring/Score.cs b/osu.Game/Modes/Scoring/Score.cs index 75c243278d..ab376ebdd6 100644 --- a/osu.Game/Modes/Scoring/Score.cs +++ b/osu.Game/Modes/Scoring/Score.cs @@ -7,6 +7,7 @@ using osu.Game.Database; using osu.Game.Modes.Mods; using osu.Game.Users; using System.IO; +using osu.Game.Modes.Replays; namespace osu.Game.Modes.Scoring { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a5bdf1df69..0bcbe9032f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -96,8 +96,9 @@ + - + @@ -123,7 +124,9 @@ - + + + From 0bcec4e61a158f976d0af09f258dbcb08ed6991d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 12:55:43 +0900 Subject: [PATCH 235/250] Add null-checks to comparers. --- osu.Game.Modes.Osu/OsuAutoReplay.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Modes.Osu/OsuAutoReplay.cs b/osu.Game.Modes.Osu/OsuAutoReplay.cs index 2ac5f771c3..cc5859602a 100644 --- a/osu.Game.Modes.Osu/OsuAutoReplay.cs +++ b/osu.Game.Modes.Osu/OsuAutoReplay.cs @@ -34,6 +34,9 @@ namespace osu.Game.Modes.Osu { public int Compare(ReplayFrame f1, ReplayFrame f2) { + if (f1 == null) throw new NullReferenceException($@"{nameof(f1)} cannot be null"); + if (f2 == null) throw new NullReferenceException($@"{nameof(f2)} cannot be null"); + return f1.Time.CompareTo(f2.Time); } } From 79031b9e749fe5e1ca2e81eb82d1acdc805e15f9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 12:58:54 +0900 Subject: [PATCH 236/250] Update framework. --- osu-framework | 2 +- osu.Game/Graphics/UserInterface/PercentageCounter.cs | 2 +- osu.Game/Graphics/UserInterface/ScoreCounter.cs | 2 +- osu.Game/Modes/UI/ComboCounter.cs | 2 +- osu.Game/Modes/UI/ComboResultCounter.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu-framework b/osu-framework index 269a1fd192..7ae3cf1a10 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 269a1fd192c573d558a5ab0ff990a8b462947287 +Subproject commit 7ae3cf1a10fa973a49995a71cbaf768702be1cce diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 66c9e7d461..c32b654840 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -47,7 +47,7 @@ namespace osu.Game.Graphics.UserInterface protected class TransformAccuracy : Transform { - protected override double CurrentValue + public override double CurrentValue { get { diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index c9a1040185..c2b1b026b6 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -51,7 +51,7 @@ namespace osu.Game.Graphics.UserInterface protected class TransformScore : Transform { - protected override double CurrentValue + public override double CurrentValue { get { diff --git a/osu.Game/Modes/UI/ComboCounter.cs b/osu.Game/Modes/UI/ComboCounter.cs index f831677e44..3629634889 100644 --- a/osu.Game/Modes/UI/ComboCounter.cs +++ b/osu.Game/Modes/UI/ComboCounter.cs @@ -213,7 +213,7 @@ namespace osu.Game.Modes.UI protected class TransformComboRoll : Transform { - protected override int CurrentValue + public override int CurrentValue { get { diff --git a/osu.Game/Modes/UI/ComboResultCounter.cs b/osu.Game/Modes/UI/ComboResultCounter.cs index 957a720c94..63009c5351 100644 --- a/osu.Game/Modes/UI/ComboResultCounter.cs +++ b/osu.Game/Modes/UI/ComboResultCounter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Modes.UI protected class TransformComboResult : Transform { - protected override ulong CurrentValue + public override ulong CurrentValue { get { From 09b98d71a705b56802a4dc1c7f89eae064905061 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 13:33:19 +0900 Subject: [PATCH 237/250] Add back Capacity. --- osu.Game/Modes/Scoring/ScoreProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Modes/Scoring/ScoreProcessor.cs index 4c42f2a384..a64b4d4013 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Modes/Scoring/ScoreProcessor.cs @@ -120,6 +120,8 @@ namespace osu.Game.Modes.Scoring protected ScoreProcessor(HitRenderer hitRenderer) { + Judgements.Capacity = hitRenderer.Beatmap.HitObjects.Count; + hitRenderer.OnJudgement += AddJudgement; ComputeTargets(hitRenderer.Beatmap); From 43c306d65860f3d42d1482e48e903a05b1a130f5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 14:47:59 +0900 Subject: [PATCH 238/250] IAccented -> IHasAccentColour. --- osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs | 2 +- osu.Game/Graphics/{IAccented.cs => IHasAccentColour.cs} | 6 +++--- osu.Game/Graphics/Transforms/TransformAccent.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename osu.Game/Graphics/{IAccented.cs => IHasAccentColour.cs} (87%) diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs index 20e16ae03c..2321ad30ee 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs +++ b/osu.Game.Modes.Taiko/Objects/Drawable/Pieces/CirclePiece.cs @@ -19,7 +19,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawable.Pieces /// a rounded (_[-Width-]_) figure such that a regular "circle" is the result of a parent with Width = 0. /// /// - public class CirclePiece : Container, IAccented + public class CirclePiece : Container, IHasAccentColour { public const float SYMBOL_SIZE = TaikoHitObject.CIRCLE_RADIUS * 2f * 0.45f; public const float SYMBOL_BORDER = 8; diff --git a/osu.Game/Graphics/IAccented.cs b/osu.Game/Graphics/IHasAccentColour.cs similarity index 87% rename from osu.Game/Graphics/IAccented.cs rename to osu.Game/Graphics/IHasAccentColour.cs index 6f0f107f3c..19f063e29a 100644 --- a/osu.Game/Graphics/IAccented.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -12,12 +12,12 @@ namespace osu.Game.Graphics /// The accent colour is used to colorize various objects inside a drawable /// without colorizing the drawable itself. /// - public interface IAccented : IDrawable + public interface IHasAccentColour : IDrawable { Color4 AccentColour { get; set; } } - public static class AccentedExtensions + public static class AccentedColourExtensions { /// /// Tweens the accent colour of a drawable to another colour. @@ -28,7 +28,7 @@ namespace osu.Game.Graphics /// The tween duration. /// The tween easing. public static void FadeAccent(this TDrawable drawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None) - where TDrawable : Drawable, IAccented + where TDrawable : Drawable, IHasAccentColour { drawable.TransformTo(drawable.AccentColour, newColour, duration, easing, new TransformAccent()); } diff --git a/osu.Game/Graphics/Transforms/TransformAccent.cs b/osu.Game/Graphics/Transforms/TransformAccent.cs index 7f40a0a016..406d1ea9eb 100644 --- a/osu.Game/Graphics/Transforms/TransformAccent.cs +++ b/osu.Game/Graphics/Transforms/TransformAccent.cs @@ -29,7 +29,7 @@ namespace osu.Game.Graphics.Transforms { base.Apply(d); - var accented = d as IAccented; + var accented = d as IHasAccentColour; if (accented != null) accented.AccentColour = CurrentValue; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 00c189d01c..b2f76137fd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -82,7 +82,7 @@ - + From a48224bd6dcc7e150e32518d487a96895f1f484e Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 15:05:14 +0900 Subject: [PATCH 239/250] Don't need Drawable type. --- osu-framework | 2 +- osu.Game/Graphics/IHasAccentColour.cs | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu-framework b/osu-framework index 591b799f95..57821bd61c 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 591b799f95a47e5da893c82d024e01311c9c37c6 +Subproject commit 57821bd61c7676c2fd9e8ff3ea314ec81c1eef41 diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index 19f063e29a..f959bc8760 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -22,15 +22,13 @@ namespace osu.Game.Graphics /// /// Tweens the accent colour of a drawable to another colour. /// - /// The type of drawable. - /// The drawable to apply the accent colour to. + /// The drawable to apply the accent colour to. /// The new accent colour. /// The tween duration. /// The tween easing. - public static void FadeAccent(this TDrawable drawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None) - where TDrawable : Drawable, IHasAccentColour + public static void FadeAccent(this IHasAccentColour accentedDrawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None) { - drawable.TransformTo(drawable.AccentColour, newColour, duration, easing, new TransformAccent()); + accentedDrawable.TransformTo(accentedDrawable.AccentColour, newColour, duration, easing, new TransformAccent()); } } } From c531d774b7d77eda253cdbd1e459f27adec72060 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 15:21:30 +0900 Subject: [PATCH 240/250] Fix file naming. --- osu.Game/Modes/Replays/LegacyFramedReplay.cs | 4 ++-- osu.Game/Modes/Scoring/Score.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Modes/Replays/LegacyFramedReplay.cs b/osu.Game/Modes/Replays/LegacyFramedReplay.cs index 3e93751e09..3b99614f5e 100644 --- a/osu.Game/Modes/Replays/LegacyFramedReplay.cs +++ b/osu.Game/Modes/Replays/LegacyFramedReplay.cs @@ -10,9 +10,9 @@ namespace osu.Game.Modes.Replays /// /// Reads a replay from a legacy replay file (.osr v1) /// - public class LegacyReplay : FramedReplay + public class LegacyFramedReplay : FramedReplay { - public LegacyReplay(StreamReader reader) + public LegacyFramedReplay(StreamReader reader) { float lastTime = 0; diff --git a/osu.Game/Modes/Scoring/Score.cs b/osu.Game/Modes/Scoring/Score.cs index ab376ebdd6..70777a77ef 100644 --- a/osu.Game/Modes/Scoring/Score.cs +++ b/osu.Game/Modes/Scoring/Score.cs @@ -50,7 +50,7 @@ namespace osu.Game.Modes.Scoring /// /// The stream reader. /// The replay. - public virtual Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyReplay(reader); + public virtual Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyFramedReplay(reader); // [JsonProperty(@"count50")] 0, //[JsonProperty(@"count100")] 0, From 0f4b98ce7320825aefa7440a4d5c483f68aebc41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 15:32:34 +0900 Subject: [PATCH 241/250] Move FramedReplayInputHandler to own file and un-nest. --- osu.Game/Modes/Replays/FramedReplay.cs | 141 ----------------- .../Modes/Replays/FramedReplayInputHandler.cs | 146 ++++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 3 files changed, 147 insertions(+), 141 deletions(-) create mode 100644 osu.Game/Modes/Replays/FramedReplayInputHandler.cs diff --git a/osu.Game/Modes/Replays/FramedReplay.cs b/osu.Game/Modes/Replays/FramedReplay.cs index 26144d1ed7..53b258e28b 100644 --- a/osu.Game/Modes/Replays/FramedReplay.cs +++ b/osu.Game/Modes/Replays/FramedReplay.cs @@ -1,16 +1,8 @@ // 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.Extensions.IEnumerableExtensions; -using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Game.Input.Handlers; -using OpenTK; -using OpenTK.Input; -using KeyboardState = osu.Framework.Input.KeyboardState; -using MouseState = osu.Framework.Input.MouseState; namespace osu.Game.Modes.Replays { @@ -19,138 +11,5 @@ namespace osu.Game.Modes.Replays protected List Frames = new List(); public override ReplayInputHandler CreateInputHandler() => new FramedReplayInputHandler(Frames); - - /// - /// The ReplayHandler will take a replay and handle the propagation of updates to the input stack. - /// It handles logic of any frames which *must* be executed. - /// - public class FramedReplayInputHandler : ReplayInputHandler - { - private readonly List replayContent; - - public ReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex]; - public ReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex]; - - private int currentFrameIndex; - - private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, replayContent.Count - 1); - - public FramedReplayInputHandler(List replayContent) - { - this.replayContent = replayContent; - } - - private bool advanceFrame() - { - int newFrame = nextFrameIndex; - - //ensure we aren't at an extent. - if (newFrame == currentFrameIndex) return false; - - currentFrameIndex = newFrame; - return true; - } - - public void SetPosition(Vector2 pos) - { - } - - private Vector2? position - { - get - { - if (!hasFrames) - return null; - - return Interpolation.ValueAt(currentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); - } - } - - public override List GetPendingStates() - { - var buttons = new HashSet(); - if (CurrentFrame?.MouseLeft ?? false) - buttons.Add(MouseButton.Left); - if (CurrentFrame?.MouseRight ?? false) - buttons.Add(MouseButton.Right); - - return new List - { - new InputState - { - Mouse = new ReplayMouseState(ToScreenSpace(position ?? Vector2.Zero), buttons), - Keyboard = new ReplayKeyboardState(new List()) - } - }; - } - - public bool AtLastFrame => currentFrameIndex == replayContent.Count - 1; - public bool AtFirstFrame => currentFrameIndex == 0; - - public Vector2 Size => new Vector2(512, 384); - - private const double sixty_frame_time = 1000.0 / 60; - - private double currentTime; - private int currentDirection; - - /// - /// When set, we will ensure frames executed by nested drawables are frame-accurate to replay data. - /// Disabling this can make replay playback smoother (useful for autoplay, currently). - /// - public bool FrameAccuratePlayback = true; - - private bool hasFrames => replayContent.Count > 0; - - private bool inImportantSection => - FrameAccuratePlayback && - //a button is in a pressed state - ((currentDirection > 0 ? CurrentFrame : NextFrame)?.IsImportant ?? false) && - //the next frame is within an allowable time span - Math.Abs(currentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2; - - /// - /// Update the current frame based on an incoming time value. - /// There are cases where we return a "must-use" time value that is different from the input. - /// This is to ensure accurate playback of replay data. - /// - /// The time which we should use for finding the current frame. - /// The usable time value. If null, we should not advance time as we do not have enough data. - public override double? SetFrameFromTime(double time) - { - currentDirection = time.CompareTo(currentTime); - if (currentDirection == 0) currentDirection = 1; - - if (hasFrames) - { - //if we changed frames, we want to execute once *exactly* on the frame's time. - if (currentDirection == time.CompareTo(NextFrame.Time) && advanceFrame()) - return currentTime = CurrentFrame.Time; - - //if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. - if (inImportantSection) - return null; - } - - return currentTime = time; - } - - protected class ReplayMouseState : MouseState - { - public ReplayMouseState(Vector2 position, IEnumerable list) - { - Position = position; - list.ForEach(b => PressedButtons.Add(b)); - } - } - - protected class ReplayKeyboardState : KeyboardState - { - public ReplayKeyboardState(List keys) - { - Keys = keys; - } - } - } } } \ No newline at end of file diff --git a/osu.Game/Modes/Replays/FramedReplayInputHandler.cs b/osu.Game/Modes/Replays/FramedReplayInputHandler.cs new file mode 100644 index 0000000000..d72c023539 --- /dev/null +++ b/osu.Game/Modes/Replays/FramedReplayInputHandler.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Game.Input.Handlers; +using OpenTK; +using OpenTK.Input; +using KeyboardState = osu.Framework.Input.KeyboardState; +using MouseState = osu.Framework.Input.MouseState; + +namespace osu.Game.Modes.Replays +{ + /// + /// The ReplayHandler will take a replay and handle the propagation of updates to the input stack. + /// It handles logic of any frames which *must* be executed. + /// + public class FramedReplayInputHandler : ReplayInputHandler + { + private readonly List replayContent; + + public ReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex]; + public ReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex]; + + private int currentFrameIndex; + + private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, replayContent.Count - 1); + + public FramedReplayInputHandler(List replayContent) + { + this.replayContent = replayContent; + } + + private bool advanceFrame() + { + int newFrame = nextFrameIndex; + + //ensure we aren't at an extent. + if (newFrame == currentFrameIndex) return false; + + currentFrameIndex = newFrame; + return true; + } + + public void SetPosition(Vector2 pos) + { + } + + private Vector2? position + { + get + { + if (!hasFrames) + return null; + + return Interpolation.ValueAt(currentTime, CurrentFrame.Position, NextFrame.Position, CurrentFrame.Time, NextFrame.Time); + } + } + + public override List GetPendingStates() + { + var buttons = new HashSet(); + if (CurrentFrame?.MouseLeft ?? false) + buttons.Add(MouseButton.Left); + if (CurrentFrame?.MouseRight ?? false) + buttons.Add(MouseButton.Right); + + return new List + { + new InputState + { + Mouse = new ReplayMouseState(ToScreenSpace(position ?? Vector2.Zero), buttons), + Keyboard = new ReplayKeyboardState(new List()) + } + }; + } + + public bool AtLastFrame => currentFrameIndex == replayContent.Count - 1; + public bool AtFirstFrame => currentFrameIndex == 0; + + public Vector2 Size => new Vector2(512, 384); + + private const double sixty_frame_time = 1000.0 / 60; + + private double currentTime; + private int currentDirection; + + /// + /// When set, we will ensure frames executed by nested drawables are frame-accurate to replay data. + /// Disabling this can make replay playback smoother (useful for autoplay, currently). + /// + public bool FrameAccuratePlayback = true; + + private bool hasFrames => replayContent.Count > 0; + + private bool inImportantSection => + FrameAccuratePlayback && + //a button is in a pressed state + ((currentDirection > 0 ? CurrentFrame : NextFrame)?.IsImportant ?? false) && + //the next frame is within an allowable time span + Math.Abs(currentTime - NextFrame?.Time ?? 0) <= sixty_frame_time * 1.2; + + /// + /// Update the current frame based on an incoming time value. + /// There are cases where we return a "must-use" time value that is different from the input. + /// This is to ensure accurate playback of replay data. + /// + /// The time which we should use for finding the current frame. + /// The usable time value. If null, we should not advance time as we do not have enough data. + public override double? SetFrameFromTime(double time) + { + currentDirection = time.CompareTo(currentTime); + if (currentDirection == 0) currentDirection = 1; + + if (hasFrames) + { + //if we changed frames, we want to execute once *exactly* on the frame's time. + if (currentDirection == time.CompareTo(NextFrame.Time) && advanceFrame()) + return currentTime = CurrentFrame.Time; + + //if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. + if (inImportantSection) + return null; + } + + return currentTime = time; + } + + protected class ReplayMouseState : MouseState + { + public ReplayMouseState(Vector2 position, IEnumerable list) + { + Position = position; + list.ForEach(b => PressedButtons.Add(b)); + } + } + + protected class ReplayKeyboardState : KeyboardState + { + public ReplayKeyboardState(List keys) + { + Keys = keys; + } + } + } +} \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0bcbe9032f..a3ece6d5ca 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -98,6 +98,7 @@ + From fa7c72a0990c8b5f0ec19ec4c71bd1b821e790f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 15:59:53 +0900 Subject: [PATCH 242/250] Refactor ReplayInputHandler creation for more flexibility. --- osu.Game.Modes.Osu/OsuAutoReplay.cs | 2 +- osu.Game/Database/ScoreDatabase.cs | 2 +- osu.Game/Modes/Mods/Mod.cs | 2 +- osu.Game/Modes/Replays/FramedReplay.cs | 15 ---- .../Modes/Replays/FramedReplayInputHandler.cs | 23 +++--- osu.Game/Modes/Replays/LegacyFramedReplay.cs | 70 ------------------- osu.Game/Modes/Replays/Replay.cs | 6 +- osu.Game/Modes/Scoring/Score.cs | 28 +++++++- osu.Game/Modes/UI/HitRenderer.cs | 5 ++ osu.Game/OsuGame.cs | 2 +- osu.Game/Screens/Play/Player.cs | 20 ++---- osu.Game/Screens/Play/ReplayPlayer.cs | 23 ++++++ osu.Game/osu.Game.csproj | 5 +- 13 files changed, 84 insertions(+), 119 deletions(-) delete mode 100644 osu.Game/Modes/Replays/FramedReplay.cs delete mode 100644 osu.Game/Modes/Replays/LegacyFramedReplay.cs create mode 100644 osu.Game/Screens/Play/ReplayPlayer.cs diff --git a/osu.Game.Modes.Osu/OsuAutoReplay.cs b/osu.Game.Modes.Osu/OsuAutoReplay.cs index cc5859602a..ae85bd72d8 100644 --- a/osu.Game.Modes.Osu/OsuAutoReplay.cs +++ b/osu.Game.Modes.Osu/OsuAutoReplay.cs @@ -15,7 +15,7 @@ using osu.Game.Modes.Replays; namespace osu.Game.Modes.Osu { - public class OsuAutoReplay : FramedReplay + public class OsuAutoReplay : Replay { private static readonly Vector2 spinner_centre = new Vector2(256, 192); diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 096c0dcc29..5ce3ff273e 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -101,7 +101,7 @@ namespace osu.Game.Database using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) - score.Replay = score.CreateLegacyReplayFrom(reader); + score.Replay = score.CreateReplay(reader); } } diff --git a/osu.Game/Modes/Mods/Mod.cs b/osu.Game/Modes/Mods/Mod.cs index c53c6faa21..b6f09b8506 100644 --- a/osu.Game/Modes/Mods/Mod.cs +++ b/osu.Game/Modes/Mods/Mod.cs @@ -157,7 +157,7 @@ namespace osu.Game.Modes.Mods public void Apply(HitRenderer hitRenderer) { - hitRenderer.InputManager.ReplayInputHandler = CreateReplayScore(hitRenderer.Beatmap)?.Replay?.CreateInputHandler(); + hitRenderer.SetReplay(CreateReplayScore(hitRenderer.Beatmap)?.Replay); } } diff --git a/osu.Game/Modes/Replays/FramedReplay.cs b/osu.Game/Modes/Replays/FramedReplay.cs deleted file mode 100644 index 53b258e28b..0000000000 --- a/osu.Game/Modes/Replays/FramedReplay.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using osu.Game.Input.Handlers; - -namespace osu.Game.Modes.Replays -{ - public abstract class FramedReplay : Replay - { - protected List Frames = new List(); - - public override ReplayInputHandler CreateInputHandler() => new FramedReplayInputHandler(Frames); - } -} \ No newline at end of file diff --git a/osu.Game/Modes/Replays/FramedReplayInputHandler.cs b/osu.Game/Modes/Replays/FramedReplayInputHandler.cs index d72c023539..ae20ece515 100644 --- a/osu.Game/Modes/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Modes/Replays/FramedReplayInputHandler.cs @@ -1,4 +1,7 @@ -using System; +// 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.Extensions.IEnumerableExtensions; using osu.Framework.Input; @@ -17,18 +20,20 @@ namespace osu.Game.Modes.Replays /// public class FramedReplayInputHandler : ReplayInputHandler { - private readonly List replayContent; + private readonly Replay replay; - public ReplayFrame CurrentFrame => !hasFrames ? null : replayContent[currentFrameIndex]; - public ReplayFrame NextFrame => !hasFrames ? null : replayContent[nextFrameIndex]; + protected List Frames => replay.Frames; + + public ReplayFrame CurrentFrame => !hasFrames ? null : Frames[currentFrameIndex]; + public ReplayFrame NextFrame => !hasFrames ? null : Frames[nextFrameIndex]; private int currentFrameIndex; - private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, replayContent.Count - 1); + private int nextFrameIndex => MathHelper.Clamp(currentFrameIndex + (currentDirection > 0 ? 1 : -1), 0, Frames.Count - 1); - public FramedReplayInputHandler(List replayContent) + public FramedReplayInputHandler(Replay replay) { - this.replayContent = replayContent; + this.replay = replay; } private bool advanceFrame() @@ -75,7 +80,7 @@ namespace osu.Game.Modes.Replays }; } - public bool AtLastFrame => currentFrameIndex == replayContent.Count - 1; + public bool AtLastFrame => currentFrameIndex == Frames.Count - 1; public bool AtFirstFrame => currentFrameIndex == 0; public Vector2 Size => new Vector2(512, 384); @@ -91,7 +96,7 @@ namespace osu.Game.Modes.Replays /// public bool FrameAccuratePlayback = true; - private bool hasFrames => replayContent.Count > 0; + private bool hasFrames => Frames.Count > 0; private bool inImportantSection => FrameAccuratePlayback && diff --git a/osu.Game/Modes/Replays/LegacyFramedReplay.cs b/osu.Game/Modes/Replays/LegacyFramedReplay.cs deleted file mode 100644 index 3b99614f5e..0000000000 --- a/osu.Game/Modes/Replays/LegacyFramedReplay.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.IO; -using osu.Game.IO.Legacy; - -namespace osu.Game.Modes.Replays -{ - /// - /// Reads a replay from a legacy replay file (.osr v1) - /// - public class LegacyFramedReplay : FramedReplay - { - public LegacyFramedReplay(StreamReader reader) - { - float lastTime = 0; - - foreach (var l in reader.ReadToEnd().Split(',')) - { - var split = l.Split('|'); - - if (split.Length < 4 || float.Parse(split[0]) < 0) continue; - - lastTime += float.Parse(split[0]); - - Frames.Add(new ReplayFrame( - lastTime, - float.Parse(split[1]), - 384 - float.Parse(split[2]), - (ReplayButtonState)int.Parse(split[3]) - )); - } - } - - public class LegacyReplayFrame : ReplayFrame - { - public LegacyReplayFrame(Stream s) : this(new SerializationReader(s)) - { - } - - public LegacyReplayFrame(SerializationReader sr) - { - ButtonState = (ReplayButtonState)sr.ReadByte(); - - byte bt = sr.ReadByte(); - if (bt > 0)//Handle Pre-Taiko compatible replays. - ButtonState = ReplayButtonState.Right1; - - MouseX = sr.ReadSingle(); - MouseY = sr.ReadSingle(); - Time = sr.ReadInt32(); - } - - public void ReadFromStream(SerializationReader sr) - { - throw new NotImplementedException(); - } - - public void WriteToStream(SerializationWriter sw) - { - sw.Write((byte)ButtonState); - sw.Write((byte)0); - sw.Write(MouseX); - sw.Write(MouseY); - sw.Write(Time); - } - } - } -} diff --git a/osu.Game/Modes/Replays/Replay.cs b/osu.Game/Modes/Replays/Replay.cs index c1ae952b77..62f60358e0 100644 --- a/osu.Game/Modes/Replays/Replay.cs +++ b/osu.Game/Modes/Replays/Replay.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Input.Handlers; +using System.Collections.Generic; namespace osu.Game.Modes.Replays { - public abstract class Replay + public class Replay { - public virtual ReplayInputHandler CreateInputHandler() => null; + public List Frames = new List(); } } \ No newline at end of file diff --git a/osu.Game/Modes/Scoring/Score.cs b/osu.Game/Modes/Scoring/Score.cs index 70777a77ef..c998b11f77 100644 --- a/osu.Game/Modes/Scoring/Score.cs +++ b/osu.Game/Modes/Scoring/Score.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 Newtonsoft.Json; using osu.Game.Database; using osu.Game.Modes.Mods; @@ -46,11 +47,34 @@ namespace osu.Game.Modes.Scoring public DateTime Date; /// - /// Creates a legacy replay which is read from a stream. + /// Creates a replay which is read from a stream. /// /// The stream reader. /// The replay. - public virtual Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyFramedReplay(reader); + public virtual Replay CreateReplay(StreamReader reader) + { + var frames = new List(); + + float lastTime = 0; + + foreach (var l in reader.ReadToEnd().Split(',')) + { + var split = l.Split('|'); + + if (split.Length < 4 || float.Parse(split[0]) < 0) continue; + + lastTime += float.Parse(split[0]); + + frames.Add(new ReplayFrame( + lastTime, + float.Parse(split[1]), + 384 - float.Parse(split[2]), + (ReplayButtonState)int.Parse(split[3]) + )); + } + + return new Replay { Frames = frames }; + } // [JsonProperty(@"count50")] 0, //[JsonProperty(@"count100")] 0, diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 3d108b895d..8581d12244 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -14,6 +14,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Game.Modes.Replays; using osu.Game.Modes.Scoring; namespace osu.Game.Modes.UI @@ -68,6 +69,10 @@ namespace osu.Game.Modes.UI /// /// The input manager. protected virtual KeyConversionInputManager CreateKeyConversionInputManager() => new KeyConversionInputManager(); + + protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); + + public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = CreateReplayInputHandler(replay); } /// diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 66196670b8..8ac86c5c67 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -125,7 +125,7 @@ namespace osu.Game Beatmap.Value = BeatmapDatabase.GetWorkingBeatmap(s.Beatmap); - menu.Push(new PlayerLoader(new Player { ReplayInputHandler = s.Replay.CreateInputHandler() })); + menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay))); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0554c0e77b..73d397b24b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -15,7 +15,6 @@ using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.Input.Handlers; using osu.Game.Modes; using osu.Game.Modes.UI; using osu.Game.Screens.Backgrounds; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Play internal override bool HasLocalCursorDisplayed => !hasReplayLoaded && !IsPaused; - private bool hasReplayLoaded => hitRenderer.InputManager.ReplayInputHandler != null; + private bool hasReplayLoaded => HitRenderer.InputManager.ReplayInputHandler != null; public BeatmapInfo BeatmapInfo; @@ -53,7 +52,7 @@ namespace osu.Game.Screens.Play private Ruleset ruleset; private ScoreProcessor scoreProcessor; - private HitRenderer hitRenderer; + protected HitRenderer HitRenderer; private Bindable dimLevel; private SkipButton skipButton; @@ -112,9 +111,9 @@ namespace osu.Game.Screens.Play }); ruleset = Ruleset.GetRuleset(Beatmap.PlayMode); - hitRenderer = ruleset.CreateHitRendererWith(Beatmap); + HitRenderer = ruleset.CreateHitRendererWith(Beatmap); - scoreProcessor = hitRenderer.CreateScoreProcessor(); + scoreProcessor = HitRenderer.CreateScoreProcessor(); hudOverlay = new StandardHudOverlay(); hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys()); @@ -133,13 +132,10 @@ namespace osu.Game.Screens.Play }; - if (ReplayInputHandler != null) - hitRenderer.InputManager.ReplayInputHandler = ReplayInputHandler; - - hudOverlay.BindHitRenderer(hitRenderer); + hudOverlay.BindHitRenderer(HitRenderer); //bind HitRenderer to ScoreProcessor and ourselves (for a pass situation) - hitRenderer.OnAllJudged += onCompletion; + HitRenderer.OnAllJudged += onCompletion; //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; @@ -152,7 +148,7 @@ namespace osu.Game.Screens.Play Clock = interpolatedSourceClock, Children = new Drawable[] { - hitRenderer, + HitRenderer, skipButton = new SkipButton { Alpha = 0 @@ -336,8 +332,6 @@ namespace osu.Game.Screens.Play private Bindable mouseWheelDisabled; - public ReplayInputHandler ReplayInputHandler; - protected override bool OnWheel(InputState state) => mouseWheelDisabled.Value && !IsPaused; } } \ No newline at end of file diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs new file mode 100644 index 0000000000..4593656a2e --- /dev/null +++ b/osu.Game/Screens/Play/ReplayPlayer.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.Modes.Replays; + +namespace osu.Game.Screens.Play +{ + public class ReplayPlayer : Player + { + public Replay Replay; + + public ReplayPlayer(Replay replay) + { + Replay = replay; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + HitRenderer.SetReplay(Replay); + } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a3ece6d5ca..0dc2da48d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -96,10 +96,9 @@ - + - @@ -125,7 +124,6 @@ - @@ -202,6 +200,7 @@ + From cf87330f802b20d5e838fd3bfc1f3fc881ef2a00 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 16:00:40 +0900 Subject: [PATCH 243/250] Allow SetReplay to receive null. --- osu.Game/Modes/UI/HitRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 8581d12244..62e3babd77 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -72,7 +72,7 @@ namespace osu.Game.Modes.UI protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); - public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = CreateReplayInputHandler(replay); + public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; } /// From 3f080ab424d80df7c9baf9dda602c916475f6c0c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 16:01:48 +0900 Subject: [PATCH 244/250] Add some commenting. --- osu.Game/Modes/UI/HitRenderer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 62e3babd77..8c1e495c7a 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -72,6 +72,10 @@ namespace osu.Game.Modes.UI protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); + /// + /// Sets a replay to be used, overriding local input. + /// + /// The replay, null for local input. public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; } From 75bdccdc3e5bbbb45478fd4f971c7aa2376c712c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 16:03:59 +0900 Subject: [PATCH 245/250] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 57821bd61c..415884e7e1 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 57821bd61c7676c2fd9e8ff3ea314ec81c1eef41 +Subproject commit 415884e7e19f9062a4fac457a7ce19b566fa2ee7 From 8f37d1ad91a4228e134d1db8c0d5520fcc30672f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Fri, 31 Mar 2017 16:20:31 +0900 Subject: [PATCH 246/250] Update to match new replay structure. --- osu.Game.Modes.Taiko/LegacyTaikoReplay.cs | 52 ------------------- osu.Game.Modes.Taiko/Mods/TaikoMod.cs | 1 + .../{ => Replays}/TaikoAutoReplay.cs | 43 +++++++-------- .../Replays/TaikoFramedReplayInputHandler.cs | 37 +++++++++++++ .../Scoring/TaikoScoreProcessor.cs | 9 ---- osu.Game.Modes.Taiko/TaikoScore.cs | 13 ----- osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs | 4 ++ .../osu.Game.Modes.Taiko.csproj | 5 +- 8 files changed, 66 insertions(+), 98 deletions(-) delete mode 100644 osu.Game.Modes.Taiko/LegacyTaikoReplay.cs rename osu.Game.Modes.Taiko/{ => Replays}/TaikoAutoReplay.cs (65%) create mode 100644 osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs delete mode 100644 osu.Game.Modes.Taiko/TaikoScore.cs diff --git a/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs b/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs deleted file mode 100644 index 38a28270b3..0000000000 --- a/osu.Game.Modes.Taiko/LegacyTaikoReplay.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using System.IO; -using osu.Framework.Input; -using osu.Game.Input.Handlers; -using OpenTK.Input; - -namespace osu.Game.Modes.Taiko -{ - public class LegacyTaikoReplay : LegacyReplay - { - protected LegacyTaikoReplay() - { - } - - public LegacyTaikoReplay(StreamReader reader) - : base(reader) - { - } - - public override ReplayInputHandler CreateInputHandler() => new LegacyTaikoReplayInputHandler(Frames); - - private class LegacyTaikoReplayInputHandler : LegacyReplayInputHandler - { - public LegacyTaikoReplayInputHandler(List replayContent) - : base(replayContent) - { - } - - public override List GetPendingStates() - { - var keys = new List(); - - if (CurrentFrame?.MouseRight1 == true) - keys.Add(Key.F); - if (CurrentFrame?.MouseRight2 == true) - keys.Add(Key.J); - if (CurrentFrame?.MouseLeft1 == true) - keys.Add(Key.D); - if (CurrentFrame?.MouseLeft2 == true) - keys.Add(Key.K); - - return new List - { - new InputState { Keyboard = new ReplayKeyboardState(keys) } - }; - } - } - } -} diff --git a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs index 79370f58ee..422f0ec250 100644 --- a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs +++ b/osu.Game.Modes.Taiko/Mods/TaikoMod.cs @@ -5,6 +5,7 @@ using osu.Game.Beatmaps; using osu.Game.Modes.Mods; using osu.Game.Modes.Scoring; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Taiko.Replays; using osu.Game.Users; namespace osu.Game.Modes.Taiko.Mods diff --git a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs b/osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs similarity index 65% rename from osu.Game.Modes.Taiko/TaikoAutoReplay.cs rename to osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs index b30f26a9d3..c8a93c9068 100644 --- a/osu.Game.Modes.Taiko/TaikoAutoReplay.cs +++ b/osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs @@ -1,14 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Objects.Types; -using osu.Game.Beatmaps; using System; +using osu.Game.Beatmaps; +using osu.Game.Modes.Objects.Types; +using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Replays; -namespace osu.Game.Modes.Taiko +namespace osu.Game.Modes.Taiko.Replays { - public class TaikoAutoReplay : LegacyTaikoReplay + public class TaikoAutoReplay : Replay { private readonly Beatmap beatmap; @@ -23,14 +24,14 @@ namespace osu.Game.Modes.Taiko { bool hitButton = true; - Frames.Add(new LegacyReplayFrame(-100000, 320, 240, LegacyButtonState.None)); - Frames.Add(new LegacyReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, LegacyButtonState.None)); + Frames.Add(new ReplayFrame(-100000, 320, 240, ReplayButtonState.None)); + Frames.Add(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, ReplayButtonState.None)); for (int i = 0; i < beatmap.HitObjects.Count; i++) { TaikoHitObject h = beatmap.HitObjects[i]; - LegacyButtonState button; + ReplayButtonState button; IHasEndTime endTimeData = h as IHasEndTime; double endTime = endTimeData?.EndTime ?? h.StartTime; @@ -50,20 +51,20 @@ namespace osu.Game.Modes.Taiko switch (d) { default: - button = LegacyButtonState.Left1; + button = ReplayButtonState.Left1; break; case 1: - button = LegacyButtonState.Right1; + button = ReplayButtonState.Right1; break; case 2: - button = LegacyButtonState.Left2; + button = ReplayButtonState.Left2; break; case 3: - button = LegacyButtonState.Right2; + button = ReplayButtonState.Right2; break; } - Frames.Add(new LegacyReplayFrame(j, 0, 0, button)); + Frames.Add(new ReplayFrame(j, 0, 0, button)); d = (d + 1) % 4; if (++count > req) break; @@ -77,7 +78,7 @@ namespace osu.Game.Modes.Taiko for (int j = 0; j < drumRoll.TotalTicks; j++) { - Frames.Add(new LegacyReplayFrame((int)time, 0, 0, hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2)); + Frames.Add(new ReplayFrame((int)time, 0, 0, hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2)); time += delay; hitButton = !hitButton; } @@ -87,30 +88,30 @@ namespace osu.Game.Modes.Taiko if (hit is CentreHit) { if (h.IsStrong) - button = LegacyButtonState.Right1 | LegacyButtonState.Right2; + button = ReplayButtonState.Right1 | ReplayButtonState.Right2; else - button = hitButton ? LegacyButtonState.Right1 : LegacyButtonState.Right2; + button = hitButton ? ReplayButtonState.Right1 : ReplayButtonState.Right2; } else { if (h.IsStrong) - button = LegacyButtonState.Left1 | LegacyButtonState.Left2; + button = ReplayButtonState.Left1 | ReplayButtonState.Left2; else - button = hitButton ? LegacyButtonState.Left1 : LegacyButtonState.Left2; + button = hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2; } - Frames.Add(new LegacyReplayFrame(h.StartTime, 0, 0, button)); + Frames.Add(new ReplayFrame(h.StartTime, 0, 0, button)); } else throw new Exception("Unknown hit object type."); - Frames.Add(new LegacyReplayFrame(endTime + 1, 0, 0, LegacyButtonState.None)); + Frames.Add(new ReplayFrame(endTime + 1, 0, 0, ReplayButtonState.None)); if (i < beatmap.HitObjects.Count - 1) { double waitTime = beatmap.HitObjects[i + 1].StartTime - 1000; if (waitTime > endTime) - Frames.Add(new LegacyReplayFrame(waitTime, 0, 0, LegacyButtonState.None)); + Frames.Add(new ReplayFrame(waitTime, 0, 0, ReplayButtonState.None)); } hitButton = !hitButton; diff --git a/osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs new file mode 100644 index 0000000000..44fca4abe7 --- /dev/null +++ b/osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Modes.Replays; +using System.Collections.Generic; +using osu.Framework.Input; +using OpenTK.Input; + +namespace osu.Game.Modes.Taiko.Replays +{ + internal class TaikoFramedReplayInputHandler : FramedReplayInputHandler + { + public TaikoFramedReplayInputHandler(Replay replay) + : base(replay) + { + } + + public override List GetPendingStates() + { + var keys = new List(); + + if (CurrentFrame?.MouseRight1 == true) + keys.Add(Key.F); + if (CurrentFrame?.MouseRight2 == true) + keys.Add(Key.J); + if (CurrentFrame?.MouseLeft1 == true) + keys.Add(Key.D); + if (CurrentFrame?.MouseLeft2 == true) + keys.Add(Key.K); + + return new List + { + new InputState { Keyboard = new ReplayKeyboardState(keys) } + }; + } + } +} diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs index ad9392a72e..2ab31c5efb 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs @@ -119,15 +119,6 @@ namespace osu.Game.Modes.Taiko.Scoring { } - public override Score CreateScore() => new TaikoScore - { - TotalScore = TotalScore, - Combo = Combo, - MaxCombo = HighestCombo, - Accuracy = Accuracy, - Health = Health, - }; - protected override void ComputeTargets(Beatmap beatmap) { double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98)); diff --git a/osu.Game.Modes.Taiko/TaikoScore.cs b/osu.Game.Modes.Taiko/TaikoScore.cs deleted file mode 100644 index 2d5c3e750b..0000000000 --- a/osu.Game.Modes.Taiko/TaikoScore.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Modes.Scoring; -using System.IO; - -namespace osu.Game.Modes.Taiko -{ - public class TaikoScore : Score - { - public override Replay CreateLegacyReplayFrom(StreamReader reader) => new LegacyTaikoReplay(reader); - } -} diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs index 3266b5c030..e70e2d3811 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs @@ -3,10 +3,12 @@ using osu.Game.Beatmaps; using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Replays; using osu.Game.Modes.Scoring; using osu.Game.Modes.Taiko.Beatmaps; using osu.Game.Modes.Taiko.Judgements; using osu.Game.Modes.Taiko.Objects; +using osu.Game.Modes.Taiko.Replays; using osu.Game.Modes.Taiko.Scoring; using osu.Game.Modes.UI; @@ -28,5 +30,7 @@ namespace osu.Game.Modes.Taiko.UI protected override Playfield CreatePlayfield() => new TaikoPlayfield(); protected override DrawableHitObject GetVisualRepresentation(TaikoHitObject h) => null; + + protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new TaikoFramedReplayInputHandler(replay); } } diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj index f00253b53e..4e42ea5761 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj @@ -52,7 +52,6 @@ - @@ -74,12 +73,12 @@ - + + - From 24d06fa92d69ba69c69fa707a18b4153a60030a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 17:38:33 +0900 Subject: [PATCH 247/250] CheckBox -> Checkbox. --- osu.Game/Graphics/UserInterface/Nub.cs | 10 +++++----- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 12 ++++++------ osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 6 +++--- .../Graphics/UserInterface/OsuTabControlCheckBox.cs | 12 ++++++------ .../Screens/Select/BeatmapDetailAreaTabControl.cs | 6 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index 06e3be5c15..e150c7dc07 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.UserInterface; namespace osu.Game.Graphics.UserInterface { - public class Nub : CircularContainer, IStateful + public class Nub : CircularContainer, IStateful { public const float COLLAPSED_SIZE = 20; public const float EXPANDED_SIZE = 40; @@ -84,9 +84,9 @@ namespace osu.Game.Graphics.UserInterface } } - private CheckBoxState state; + private CheckboxState state; - public CheckBoxState State + public CheckboxState State { get { @@ -98,10 +98,10 @@ namespace osu.Game.Graphics.UserInterface switch (state) { - case CheckBoxState.Checked: + case CheckboxState.Checked: fill.FadeIn(200, EasingTypes.OutQuint); break; - case CheckBoxState.Unchecked: + case CheckboxState.Unchecked: fill.FadeTo(0.01f, 200, EasingTypes.OutQuint); //todo: remove once we figure why containers aren't drawing at all times break; } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 2209c96689..fc44d80ea6 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -16,7 +16,7 @@ using OpenTK.Graphics; namespace osu.Game.Graphics.UserInterface { - public class OsuCheckbox : CheckBox + public class OsuCheckbox : Checkbox { private Bindable bindable; @@ -29,9 +29,9 @@ namespace osu.Game.Graphics.UserInterface bindable = value; if (bindable != null) { - bool state = State == CheckBoxState.Checked; + bool state = State == CheckboxState.Checked; if (state != bindable.Value) - State = bindable.Value ? CheckBoxState.Checked : CheckBoxState.Unchecked; + State = bindable.Value ? CheckboxState.Checked : CheckboxState.Unchecked; bindable.ValueChanged += bindableValueChanged; } @@ -88,7 +88,7 @@ namespace osu.Game.Graphics.UserInterface private void bindableValueChanged(object sender, EventArgs e) { - State = bindable.Value ? CheckBoxState.Checked : CheckBoxState.Unchecked; + State = bindable.Value ? CheckboxState.Checked : CheckboxState.Unchecked; } protected override void Dispose(bool isDisposing) @@ -122,7 +122,7 @@ namespace osu.Game.Graphics.UserInterface protected override void OnChecked() { sampleChecked?.Play(); - nub.State = CheckBoxState.Checked; + nub.State = CheckboxState.Checked; if (bindable != null) bindable.Value = true; @@ -131,7 +131,7 @@ namespace osu.Game.Graphics.UserInterface protected override void OnUnchecked() { sampleUnchecked?.Play(); - nub.State = CheckBoxState.Unchecked; + nub.State = CheckboxState.Unchecked; if (bindable != null) bindable.Value = false; diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index b7d46cd409..078c8564d7 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -50,7 +50,7 @@ namespace osu.Game.Graphics.UserInterface nub = new Nub { Origin = Anchor.TopCentre, - State = CheckBoxState.Unchecked, + State = CheckboxState.Unchecked, Expanded = true, } }; @@ -94,13 +94,13 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - nub.State = CheckBoxState.Checked; + nub.State = CheckboxState.Checked; return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - nub.State = CheckBoxState.Unchecked; + nub.State = CheckboxState.Unchecked; return base.OnMouseUp(state, args); } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckBox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckBox.cs index f9d14f3b09..5914d0ba4c 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckBox.cs @@ -16,15 +16,15 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { /// - /// A checkbox styled to be placed in line with an + /// A Checkbox styled to be placed in line with an /// - public class OsuTabControlCheckBox : CheckBox + public class OsuTabControlCheckbox : Checkbox { private readonly Box box; private readonly SpriteText text; private readonly TextAwesome icon; - public event EventHandler Action; + public event EventHandler Action; private Color4? accentColour; public Color4 AccentColour @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.UserInterface { accentColour = value; - if (State != CheckBoxState.Checked) + if (State != CheckboxState.Checked) { text.Colour = AccentColour; icon.Colour = AccentColour; @@ -84,7 +84,7 @@ namespace osu.Game.Graphics.UserInterface protected override void OnHoverLost(InputState state) { - if (State == CheckBoxState.Unchecked) + if (State == CheckboxState.Unchecked) fadeOut(); base.OnHoverLost(state); @@ -97,7 +97,7 @@ namespace osu.Game.Graphics.UserInterface AccentColour = colours.Blue; } - public OsuTabControlCheckBox() + public OsuTabControlCheckbox() { AutoSizeAxes = Axes.Both; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index 9dc8de96d1..088346d91f 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -17,14 +17,14 @@ namespace osu.Game.Screens.Select public class BeatmapDetailAreaTabControl : Container { public static readonly float HEIGHT = 24; - private readonly OsuTabControlCheckBox modsCheckbox; + private readonly OsuTabControlCheckbox modsCheckbox; private readonly OsuTabControl tabs; public Action OnFilter; //passed the selected tab and if mods is checked private void invokeOnFilter() { - OnFilter?.Invoke(tabs.SelectedItem, modsCheckbox.State == CheckBoxState.Checked); + OnFilter?.Invoke(tabs.SelectedItem, modsCheckbox.State == CheckboxState.Checked); } [BackgroundDependencyLoader] @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.Both, }, - modsCheckbox = new OsuTabControlCheckBox + modsCheckbox = new OsuTabControlCheckbox { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, From 2b847aa2f46488e4933c869fdabd6552a93f7b88 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 17:55:07 +0900 Subject: [PATCH 248/250] Bring VisualTests up-to-date. --- osu-framework | 2 +- .../{BenchmarkTest.cs => VisualTests.cs} | 6 +-- osu.Desktop.Tests/osu.Desktop.Tests.csproj | 2 +- .../AutomatedVisualTestGame.cs | 16 +++++++ osu.Desktop.VisualTests/Benchmark.cs | 45 ------------------- osu.Desktop.VisualTests/Program.cs | 2 +- .../Tests/TestCaseBeatmapOptionsOverlay.cs | 2 +- .../Tests/TestCaseDialogOverlay.cs | 4 +- .../Tests/TestCaseHitObjects.cs | 29 +++++++----- .../Tests/TestCaseKeyCounter.cs | 26 ++++++++--- .../Tests/TestCaseLeaderboard.cs | 2 +- .../Tests/TestCaseModSelectOverlay.cs | 10 ++--- .../Tests/TestCaseMusicController.cs | 2 +- .../Tests/TestCaseNotificationManager.cs | 12 ++--- .../Tests/TestCasePauseOverlay.cs | 4 +- .../Tests/TestCasePlaySongSelect.cs | 13 ++---- .../Tests/TestCaseScoreCounter.cs | 10 ++--- .../Tests/TestCaseTaikoHitObjects.cs | 2 +- .../Tests/TestCaseTaikoPlayfield.cs | 14 +++--- .../osu.Desktop.VisualTests.csproj | 2 +- 20 files changed, 96 insertions(+), 109 deletions(-) rename osu.Desktop.Tests/{BenchmarkTest.cs => VisualTests.cs} (83%) create mode 100644 osu.Desktop.VisualTests/AutomatedVisualTestGame.cs delete mode 100644 osu.Desktop.VisualTests/Benchmark.cs diff --git a/osu-framework b/osu-framework index 415884e7e1..50b62716b1 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 415884e7e19f9062a4fac457a7ce19b566fa2ee7 +Subproject commit 50b62716b16359ce4f51110ef0d21169533ec76a diff --git a/osu.Desktop.Tests/BenchmarkTest.cs b/osu.Desktop.Tests/VisualTests.cs similarity index 83% rename from osu.Desktop.Tests/BenchmarkTest.cs rename to osu.Desktop.Tests/VisualTests.cs index 6d001655ec..6519dbe917 100644 --- a/osu.Desktop.Tests/BenchmarkTest.cs +++ b/osu.Desktop.Tests/VisualTests.cs @@ -13,10 +13,10 @@ using osu.Game.Modes.Taiko; namespace osu.Desktop.Tests { [TestFixture] - public class BenchmarkTest + public class VisualTests { [Test] - public void TestBenchmark() + public void TestVisualTests() { using (var host = new HeadlessGameHost()) { @@ -25,7 +25,7 @@ namespace osu.Desktop.Tests Ruleset.Register(new ManiaRuleset()); Ruleset.Register(new CatchRuleset()); - host.Run(new Benchmark()); + host.Run(new AutomatedVisualTestGame()); } } } diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index ad69994592..d1b20bd161 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -56,7 +56,7 @@ - + diff --git a/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs b/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs new file mode 100644 index 0000000000..0bce2ddc67 --- /dev/null +++ b/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Testing; +using osu.Game; + +namespace osu.Desktop.VisualTests +{ + public class AutomatedVisualTestGame : OsuGameBase + { + public AutomatedVisualTestGame() + { + Add(new TestRunner(new TestBrowser())); + } + } +} \ No newline at end of file diff --git a/osu.Desktop.VisualTests/Benchmark.cs b/osu.Desktop.VisualTests/Benchmark.cs deleted file mode 100644 index 884dff9f7a..0000000000 --- a/osu.Desktop.VisualTests/Benchmark.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using osu.Framework.Allocation; -using osu.Framework.Testing; -using osu.Game; - -namespace osu.Desktop.VisualTests -{ - public class Benchmark : OsuGameBase - { - private const double time_per_test = 200; - - [BackgroundDependencyLoader] - private void load() - { - Host.MaximumDrawHz = int.MaxValue; - Host.MaximumUpdateHz = int.MaxValue; - Host.MaximumInactiveHz = int.MaxValue; - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - TestBrowser f = new TestBrowser(); - Add(f); - - Console.WriteLine($@"{Time}: Running {f.TestCount} tests for {time_per_test}ms each..."); - - for (int i = 1; i < f.TestCount; i++) - { - int loadableCase = i; - Scheduler.AddDelayed(delegate - { - f.LoadTest(loadableCase); - Console.WriteLine($@"{Time}: Switching to test #{loadableCase}"); - }, loadableCase * time_per_test); - } - - Scheduler.AddDelayed(Host.Exit, f.TestCount * time_per_test); - } - } -} diff --git a/osu.Desktop.VisualTests/Program.cs b/osu.Desktop.VisualTests/Program.cs index 6760852cf0..fe1cdfd7f0 100644 --- a/osu.Desktop.VisualTests/Program.cs +++ b/osu.Desktop.VisualTests/Program.cs @@ -27,7 +27,7 @@ namespace osu.Desktop.VisualTests Ruleset.Register(new CatchRuleset()); if (benchmark) - host.Run(new Benchmark()); + host.Run(new AutomatedVisualTestGame()); else host.Run(new VisualTestGame()); } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs index 3fc6ce10e7..7c211227c6 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapOptionsOverlay.cs @@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests Add(overlay); - AddButton(@"Toggle", overlay.ToggleVisibility); + AddStep(@"Toggle", overlay.ToggleVisibility); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs index 3ae5929ecc..90e214c3c9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDialogOverlay.cs @@ -20,7 +20,7 @@ namespace osu.Desktop.VisualTests.Tests Add(overlay = new DialogOverlay()); - AddButton("dialog #1", () => overlay.Push(new PopupDialog + AddStep("dialog #1", () => overlay.Push(new PopupDialog { Icon = FontAwesome.fa_trash_o, HeaderText = @"Confirm deletion of", @@ -40,7 +40,7 @@ namespace osu.Desktop.VisualTests.Tests }, })); - AddButton("dialog #2", () => overlay.Push(new PopupDialog + AddStep("dialog #2", () => overlay.Push(new PopupDialog { Icon = FontAwesome.fa_gear, HeaderText = @"What do you want to do with", diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 8818240b2d..cb7a3e3f84 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -93,19 +93,28 @@ namespace osu.Desktop.VisualTests.Tests playbackSpeed.TriggerChange(); - AddButton(@"circles", () => load(HitObjectType.Circle)); - AddButton(@"slider", () => load(HitObjectType.Slider)); - AddButton(@"spinner", () => load(HitObjectType.Spinner)); + AddStep(@"circles", () => load(HitObjectType.Circle)); + AddStep(@"slider", () => load(HitObjectType.Slider)); + AddStep(@"spinner", () => load(HitObjectType.Spinner)); - AddToggle(@"auto", state => { auto = state; load(mode); }); + AddToggleStep(@"auto", state => { auto = state; load(mode); }); - ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" }); - ButtonsContainer.Add(new BasicSliderBar + Add(new Container { - Width = 150, - Height = 10, - SelectionColor = Color4.Orange, - Bindable = playbackSpeed + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new SpriteText { Text = "Playback Speed" }, + new BasicSliderBar + { + Width = 150, + Height = 10, + SelectionColor = Color4.Orange, + Bindable = playbackSpeed + } + } }); framedClock.ProcessFrame(); diff --git a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs index 051db489e9..3dba201f5d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using OpenTK.Input; using osu.Framework.Graphics.UserInterface; using osu.Framework.Configuration; +using osu.Framework.Graphics.Containers; using OpenTK; using OpenTK.Graphics; using osu.Framework.MathUtils; @@ -37,19 +38,30 @@ namespace osu.Desktop.VisualTests.Tests }; BindableInt bindable = new BindableInt { MinValue = 0, MaxValue = 200, Default = 50 }; bindable.ValueChanged += delegate { kc.FadeTime = bindable.Value; }; - AddButton("Add Random", () => + AddStep("Add Random", () => { Key key = (Key)((int)Key.A + RNG.Next(26)); kc.Add(new KeyCounterKeyboard(key)); }); - ButtonsContainer.Add(new SpriteText { Text = "FadeTime" }); - ButtonsContainer.Add(new TestSliderBar + + Add(new Container { - Width = 150, - Height = 10, - SelectionColor = Color4.Orange, - Bindable = bindable + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new SpriteText { Text = "FadeTime" }, + new TestSliderBar + { + Width = 150, + Height = 10, + SelectionColor = Color4.Orange, + Bindable = bindable + } + } }); + Add(kc); } private class TestSliderBar : SliderBar where T : struct diff --git a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs index c985375873..44e52c237e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs @@ -218,7 +218,7 @@ namespace osu.Desktop.VisualTests.Tests Size = new Vector2(550f, 450f), }); - AddButton(@"New Scores", newScores); + AddStep(@"New Scores", newScores); newScores(); } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index 73f8ed6242..7677682ac8 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -25,11 +25,11 @@ namespace osu.Desktop.VisualTests.Tests Anchor = Anchor.BottomCentre, }); - AddButton("Toggle", modSelect.ToggleVisibility); - AddButton("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu); - AddButton("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko); - AddButton("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch); - AddButton("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania); + AddStep("Toggle", modSelect.ToggleVisibility); + AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu); + AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko); + AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch); + AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs index 305aa24252..c0c17cd50e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMusicController.cs @@ -30,7 +30,7 @@ namespace osu.Desktop.VisualTests.Tests Anchor = Anchor.Centre }; Add(mc); - AddToggle(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden); + AddToggleStep(@"Show", state => mc.State = state ? Visibility.Visible : Visibility.Hidden); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs index 990052012f..8972040b06 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs @@ -30,13 +30,13 @@ namespace osu.Desktop.VisualTests.Tests Origin = Anchor.TopRight, }); - AddToggle(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden); + AddToggleStep(@"show", state => manager.State = state ? Visibility.Visible : Visibility.Hidden); - AddButton(@"simple #1", sendNotification1); - AddButton(@"simple #2", sendNotification2); - AddButton(@"progress #1", sendProgress1); - AddButton(@"progress #2", sendProgress2); - AddButton(@"barrage", () => sendBarrage()); + AddStep(@"simple #1", sendNotification1); + AddStep(@"simple #2", sendNotification2); + AddStep(@"progress #1", sendProgress1); + AddStep(@"progress #2", sendProgress2); + AddStep(@"barrage", () => sendBarrage()); } private void sendBarrage(int remaining = 100) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs index 09e2dc38aa..ebf6e0c350 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePauseOverlay.cs @@ -25,8 +25,8 @@ namespace osu.Desktop.VisualTests.Tests OnRetry = () => Logger.Log(@"Retry"), OnQuit = () => Logger.Log(@"Quit") }); - AddButton("Pause", pauseOverlay.Show); - AddButton("Add Retry", delegate + AddStep("Pause", pauseOverlay.Show); + AddStep("Add Retry", delegate { retryCount++; pauseOverlay.Retries = retryCount; diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 16f7881dcd..aedab7e895 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -23,12 +23,10 @@ namespace osu.Desktop.VisualTests.Tests public override void Reset() { base.Reset(); - oldDb = Dependencies.Get(); if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); db = new BeatmapDatabase(storage); - Dependencies.Cache(db, true); var sets = new List(); @@ -40,19 +38,16 @@ namespace osu.Desktop.VisualTests.Tests Add(songSelect = new PlaySongSelect()); - AddButton(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); - AddButton(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; }); - AddButton(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; }); - AddButton(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); + AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; }); + AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; }); + AddStep(@"Sort by Author", delegate { songSelect.FilterControl.Sort = SortMode.Author; }); + AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); } protected override void Dispose(bool isDisposing) { if (oldDb != null) - { - Dependencies.Cache(oldDb, true); db = null; - } base.Dispose(isDisposing); } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs index cca87cd12b..55fc969217 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs @@ -68,7 +68,7 @@ namespace osu.Desktop.VisualTests.Tests }; Add(starsLabel); - AddButton(@"Reset all", delegate + AddStep(@"Reset all", delegate { score.Current.Value = 0; comboCounter.Current.Value = 0; @@ -78,7 +78,7 @@ namespace osu.Desktop.VisualTests.Tests starsLabel.Text = stars.Count.ToString("0.00"); }); - AddButton(@"Hit! :D", delegate + AddStep(@"Hit! :D", delegate { score.Current.Value += 300 + (ulong)(300.0 * (comboCounter.Current > 0 ? comboCounter.Current - 1 : 0) / 25.0); comboCounter.Increment(); @@ -86,20 +86,20 @@ namespace osu.Desktop.VisualTests.Tests accuracyCounter.SetFraction(numerator, denominator); }); - AddButton(@"miss...", delegate + AddStep(@"miss...", delegate { comboCounter.Current.Value = 0; denominator++; accuracyCounter.SetFraction(numerator, denominator); }); - AddButton(@"Alter stars", delegate + AddStep(@"Alter stars", delegate { stars.Count = RNG.NextSingle() * (stars.StarCount + 1); starsLabel.Text = stars.Count.ToString("0.00"); }); - AddButton(@"Stop counters", delegate + AddStep(@"Stop counters", delegate { score.StopRolling(); comboCounter.StopRolling(); diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index e8e32ebf3d..4005c94b5a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -21,7 +21,7 @@ namespace osu.Desktop.VisualTests.Tests { base.Reset(); - AddToggle("Kiai", b => + AddToggleStep("Kiai", b => { kiai = !kiai; Reset(); diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 223f9ce5f8..c0aa3af176 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -24,13 +24,13 @@ namespace osu.Desktop.VisualTests.Tests { base.Reset(); - AddButton("Hit!", addHitJudgement); - AddButton("Miss :(", addMissJudgement); - AddButton("Swell", addSwell); - AddButton("Centre", () => addCentreHit(false)); - AddButton("Strong Centre", () => addCentreHit(true)); - AddButton("Rim", () => addRimHit(false)); - AddButton("Strong Rim", () => addRimHit(true)); + AddStep("Hit!", addHitJudgement); + AddStep("Miss :(", addMissJudgement); + AddStep("Swell", addSwell); + AddStep("Centre", () => addCentreHit(false)); + AddStep("Strong Centre", () => addCentreHit(true)); + AddStep("Rim", () => addRimHit(false)); + AddStep("Strong Rim", () => addRimHit(true)); Add(new Container { diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 9f3cd6b3c4..1baf322750 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -184,7 +184,7 @@ - + From 01538ed7d7c9bac1ec370132702c683e24069cab Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 18:05:24 +0900 Subject: [PATCH 249/250] Fix nullref. --- osu.Desktop.VisualTests/AutomatedVisualTestGame.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs b/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs index 0bce2ddc67..b08588b29c 100644 --- a/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs +++ b/osu.Desktop.VisualTests/AutomatedVisualTestGame.cs @@ -8,8 +8,12 @@ namespace osu.Desktop.VisualTests { public class AutomatedVisualTestGame : OsuGameBase { - public AutomatedVisualTestGame() + protected override void LoadComplete() { + base.LoadComplete(); + + // Have to construct this here, rather than in the constructor, because + // we depend on some dependencies to be loaded within OsuGameBase.load(). Add(new TestRunner(new TestBrowser())); } } From 904efb291638160e22f349b04edfed1cc8e187f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Mar 2017 18:13:24 +0900 Subject: [PATCH 250/250] Update framework again. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 50b62716b1..bf6a3dc401 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 50b62716b16359ce4f51110ef0d21169533ec76a +Subproject commit bf6a3dc40176ee4f921012808070e014fc4a5779