From 3e7208c8a48db353182920e25b42ed799039121f Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 12 Feb 2017 20:38:05 +0100 Subject: [PATCH 01/40] Add slider ticks. --- .../Objects/Drawables/DrawableSlider.cs | 34 ++++++- .../Objects/Drawables/DrawableSliderTick.cs | 92 +++++++++++++++++++ .../Objects/Drawables/SliderTicksRenderer.cs | 74 +++++++++++++++ osu.Game.Modes.Osu/Objects/Slider.cs | 54 ++++++++++- osu.Game.Modes.Osu/Objects/SliderTick.cs | 9 ++ osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 3 + 6 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs create mode 100644 osu.Game.Modes.Osu/Objects/SliderTick.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index 611daad642..981da050a3 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,12 +1,13 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; +using OpenTK; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; -using OpenTK; -using osu.Framework.Input; +using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -22,6 +23,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables SliderBall ball; SliderBouncer bouncer1, bouncer2; + SliderTicksRenderer ticks; public DrawableSlider(Slider s) : base(s) { @@ -34,6 +36,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Position = s.StackedPosition, PathWidth = s.Scale * 64, }, + ticks = new SliderTicksRenderer + { + Position = s.StackedPosition, + StartTime = s.StartTime, + RepeatDuration = s.Curve.Length / s.Velocity, + Ticks = s.Ticks, + }, bouncer1 = new SliderBouncer(s, false) { Position = s.Curve.PositionAt(1), @@ -96,6 +105,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables initialCircle.Position = slider.Curve.PositionAt(progress); components.ForEach(c => c.UpdateProgress(progress, repeat)); + ticks.ShouldHit = ball.Tracking; } protected override void CheckJudgement(bool userTriggered) @@ -105,8 +115,22 @@ namespace osu.Game.Modes.Osu.Objects.Drawables if (!userTriggered && Time.Current >= HitObject.EndTime) { - j.Score = sc.Score; - j.Result = sc.Result; + var ticksCount = ticks.Children.Count() + 1; + var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit); + if (sc.Result == HitResult.Hit) + ticksHit++; + + var hitFraction = (double)ticksHit / ticksCount; + if (hitFraction == 1 && sc.Score == OsuScoreResult.Hit300) + j.Score = OsuScoreResult.Hit300; + else if (hitFraction >= 0.5 && sc.Score >= OsuScoreResult.Hit100) + j.Score = OsuScoreResult.Hit100; + else if (hitFraction > 0) + j.Score = OsuScoreResult.Hit50; + else + j.Score = OsuScoreResult.Miss; + + j.Result = j.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss; } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs new file mode 100644 index 0000000000..cd5f33a4e6 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -0,0 +1,92 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; +using osu.Game.Modes.Objects.Drawables; +using System; + +namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +{ + public class DrawableSliderTick : DrawableOsuHitObject + { + private SliderTick sliderTick; + + public double FadeInTime; + public double FadeOutTime; + + public bool ShouldHit; + + public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) + { + this.sliderTick = sliderTick; + + Size = new Vector2(16) * sliderTick.Scale; + + Masking = true; + CornerRadius = Size.X / 2; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + BorderThickness = 2; + BorderColour = Color4.White; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = sliderTick.Colour, + Alpha = 0.3f, + } + }; + } + + protected override void CheckJudgement(bool userTriggered) + { + if (Judgement.TimeOffset >= 0) + Judgement.Result = ShouldHit ? HitResult.Hit : HitResult.Miss; + } + + protected override void UpdatePreemptState() + { + var animIn = Math.Min(150, sliderTick.StartTime - FadeInTime); + + ScaleTo(0.5f); + ScaleTo(1.2f, animIn); + FadeIn(animIn); + + Delay(animIn); + ScaleTo(1, 150, EasingTypes.Out); + + Delay(-animIn); + } + + protected override void UpdateState(ArmedState state) + { + if (!IsLoaded) return; + + base.UpdateState(state); + + switch (state) + { + case ArmedState.Idle: + Delay(FadeOutTime - sliderTick.StartTime); + FadeOut(); + break; + case ArmedState.Miss: + FadeTo(0.6f); + Delay(FadeOutTime - sliderTick.StartTime); + FadeOut(); + break; + case ArmedState.Hit: + FadeOut(); + break; + } + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs new file mode 100644 index 0000000000..82fa99d00a --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Containers; +using System.Collections.Generic; + +namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +{ + public class SliderTicksRenderer : Container + { + private double startTime; + public double StartTime + { + get { return startTime; } + set + { + startTime = value; + update(); + } + } + + private double repeatDuration; + public double RepeatDuration + { + get { return repeatDuration; } + set + { + repeatDuration = value; + update(); + } + } + + private IEnumerable ticks; + public IEnumerable Ticks + { + get { return ticks; } + set + { + ticks = value; + update(); + } + } + + public bool ShouldHit + { + set + { + foreach (var tick in Children) + tick.ShouldHit = value; + } + } + + private void update() + { + Clear(); + if (ticks == null || repeatDuration == 0) + return; + + foreach (var tick in ticks) + { + var repeatStartTime = startTime + tick.RepeatIndex * repeatDuration; + var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? DrawableOsuHitObject.TIME_FADEIN : DrawableOsuHitObject.TIME_FADEIN / 2); + var fadeOutTime = repeatStartTime + repeatDuration; + + Add(new DrawableSliderTick(tick) + { + FadeInTime = fadeInTime, + FadeOutTime = fadeOutTime, + Position = tick.Position, + }); + } + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index 85ee83a7f8..6f97ccf654 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -3,6 +3,9 @@ using osu.Game.Beatmaps; using OpenTK; +using System.Collections.Generic; +using System; +using osu.Game.Beatmaps.Samples; namespace osu.Game.Modes.Osu.Objects { @@ -25,17 +28,66 @@ namespace osu.Game.Modes.Osu.Objects } public double Velocity; + public double TickDistance; public override void SetDefaultsFromBeatmap(Beatmap beatmap) { base.SetDefaultsFromBeatmap(beatmap); - Velocity = 100 / beatmap.BeatLengthAt(StartTime, true) * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; + var baseDifficulty = beatmap.BeatmapInfo.BaseDifficulty; + + var startBeatLength = beatmap.BeatLengthAt(StartTime); + var multipliedStartBeatLength = beatmap.BeatLengthAt(StartTime, true); + + Velocity = 100 / multipliedStartBeatLength * baseDifficulty.SliderMultiplier; + TickDistance = (100 * baseDifficulty.SliderMultiplier) / baseDifficulty.SliderTickRate / (multipliedStartBeatLength / startBeatLength); } public int RepeatCount; public SliderCurve Curve; + + public IEnumerable Ticks + { + get + { + var length = Curve.Length; + var tickDistance = Math.Min(TickDistance, length); + var repeatDuration = length / Velocity; + + var minDistanceFromEnd = Velocity * 0.01; + + for (var repeat = 0; repeat < RepeatCount; repeat++) + { + var repeatStartTime = StartTime + repeat * repeatDuration; + var reversed = repeat % 2 == 1; + + for (var d = tickDistance; d <= length; d += tickDistance) + { + if (d > length - minDistanceFromEnd) + break; + + var distanceProgress = d / length; + var timeProgress = reversed ? 1 - distanceProgress : distanceProgress; + + yield return new SliderTick + { + RepeatIndex = repeat, + StartTime = repeatStartTime + timeProgress * repeatDuration, + Position = Curve.PositionAt(distanceProgress) - StackedPosition, + StackHeight = StackHeight, + Scale = Scale, + Colour = Colour, + Sample = new HitSampleInfo + { + Type = SampleType.None, + Set = SampleSet.Soft, + }, + }; + } + } + } + } } public enum CurveTypes diff --git a/osu.Game.Modes.Osu/Objects/SliderTick.cs b/osu.Game.Modes.Osu/Objects/SliderTick.cs new file mode 100644 index 0000000000..de8f3f4b6f --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/SliderTick.cs @@ -0,0 +1,9 @@ +using OpenTK; + +namespace osu.Game.Modes.Osu.Objects +{ + public class SliderTick : OsuHitObject + { + public int RepeatIndex { get; set; } + } +} diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index e0b9f5c904..19f0df55b8 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -47,6 +47,7 @@ + @@ -57,6 +58,7 @@ + @@ -64,6 +66,7 @@ + From 9f890139d4331f5c51560344f85c2d77521c72f1 Mon Sep 17 00:00:00 2001 From: Damnae Date: Tue, 14 Feb 2017 15:16:18 +0100 Subject: [PATCH 02/40] Cache drawable ticks. --- .../Objects/Drawables/SliderTicksRenderer.cs | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs index 82fa99d00a..03ab28e495 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.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.Framework.Allocation; +using osu.Framework.Caching; using osu.Framework.Graphics.Containers; using System.Collections.Generic; @@ -8,6 +10,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { public class SliderTicksRenderer : Container { + private Cached drawableTicks = new Cached(); + private double startTime; public double StartTime { @@ -15,7 +19,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces set { startTime = value; - update(); + drawableTicks.Invalidate(); } } @@ -26,7 +30,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces set { repeatDuration = value; - update(); + drawableTicks.Invalidate(); } } @@ -37,7 +41,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces set { ticks = value; - update(); + drawableTicks.Invalidate(); } } @@ -50,25 +54,43 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces } } - private void update() + protected override void Update() { - Clear(); - if (ticks == null || repeatDuration == 0) + base.Update(); + updateDrawableTicks(); + } + + [BackgroundDependencyLoader] + private void load() + { + updateDrawableTicks(); + } + + private void updateDrawableTicks() + { + if (drawableTicks.EnsureValid()) return; - foreach (var tick in ticks) + drawableTicks.Refresh(delegate { - var repeatStartTime = startTime + tick.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? DrawableOsuHitObject.TIME_FADEIN : DrawableOsuHitObject.TIME_FADEIN / 2); - var fadeOutTime = repeatStartTime + repeatDuration; + Clear(); + if (ticks == null || repeatDuration == 0) + return; - Add(new DrawableSliderTick(tick) + foreach (var tick in ticks) { - FadeInTime = fadeInTime, - FadeOutTime = fadeOutTime, - Position = tick.Position, - }); - } + var repeatStartTime = startTime + tick.RepeatIndex * repeatDuration; + var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? DrawableOsuHitObject.TIME_FADEIN : DrawableOsuHitObject.TIME_FADEIN / 2); + var fadeOutTime = repeatStartTime + repeatDuration; + + Add(new DrawableSliderTick(tick) + { + FadeInTime = fadeInTime, + FadeOutTime = fadeOutTime, + Position = tick.Position, + }); + } + }); } } } \ No newline at end of file From ace7a1d0096f22dd680e3569c1209a87be909146 Mon Sep 17 00:00:00 2001 From: Damnae Date: Tue, 14 Feb 2017 16:12:35 +0100 Subject: [PATCH 03/40] Fix slider ticks expiring before scoring happens. --- osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index cd5f33a4e6..cb32410303 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -20,6 +20,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces public bool ShouldHit; + public override bool RemoveWhenNotAlive => false; + public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { this.sliderTick = sliderTick; From 9a5ac64332c94a9f7278e196f92d5c3f856207de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 09:40:26 +0900 Subject: [PATCH 04/40] Make HitObjectType more accessible. # Conflicts: # osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs --- osu.Game.Modes.Osu/Objects/OsuHitObject.cs | 26 +++++++++---------- .../Objects/OsuHitObjectParser.cs | 14 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs b/osu.Game.Modes.Osu/Objects/OsuHitObject.cs index 5c3121e76c..c23c9a0b64 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObject.cs @@ -31,19 +31,19 @@ namespace osu.Game.Modes.Osu.Objects Scale = (1.0f - 0.7f * (beatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5) / 5) / 2; } + } - [Flags] - internal enum HitObjectType - { - Circle = 1, - Slider = 2, - NewCombo = 4, - CircleNewCombo = 5, - SliderNewCombo = 6, - Spinner = 8, - ColourHax = 122, - Hold = 128, - ManiaLong = 128, - } + [Flags] + public enum HitObjectType + { + Circle = 1, + Slider = 2, + NewCombo = 4, + CircleNewCombo = 5, + SliderNewCombo = 6, + Spinner = 8, + ColourHax = 122, + Hold = 128, + ManiaLong = 128, } } diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs index 0f65ae598a..ce480e1eac 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs @@ -18,17 +18,17 @@ namespace osu.Game.Modes.Osu.Objects public override HitObject Parse(string text) { string[] split = text.Split(','); - var type = (OsuHitObject.HitObjectType)int.Parse(split[3]); - bool combo = type.HasFlag(OsuHitObject.HitObjectType.NewCombo); - type &= (OsuHitObject.HitObjectType)0xF; - type &= ~OsuHitObject.HitObjectType.NewCombo; + var type = (HitObjectType)int.Parse(split[3]); + bool combo = type.HasFlag(HitObjectType.NewCombo); + type &= (HitObjectType)0xF; + type &= ~HitObjectType.NewCombo; OsuHitObject result; switch (type) { - case OsuHitObject.HitObjectType.Circle: + case HitObjectType.Circle: result = new HitCircle(); break; - case OsuHitObject.HitObjectType.Slider: + case HitObjectType.Slider: Slider s = new Slider(); CurveTypes curveType = CurveTypes.Catmull; @@ -92,7 +92,7 @@ namespace osu.Game.Modes.Osu.Objects result = s; break; - case OsuHitObject.HitObjectType.Spinner: + case HitObjectType.Spinner: result = new Spinner(); break; default: From fc192906eacb8ff4f54134b520b8451244302bb1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 10:22:28 +0900 Subject: [PATCH 05/40] Handle proxied approach layer better and add slider's approach circle (previously missing). --- .../Objects/Drawables/DrawableHitCircle.cs | 4 +++- .../Objects/Drawables/DrawableSlider.cs | 5 +++-- osu.Game.Modes.Osu/UI/OsuPlayfield.cs | 4 ++-- .../IDrawableHitObjectWithProxiedApproach.cs | 17 +++++++++++++++++ osu.Game/osu.Game.csproj | 1 + 5 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 8f59f05001..091366b88c 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -11,7 +11,7 @@ using OpenTK; namespace osu.Game.Modes.Osu.Objects.Drawables { - public class DrawableHitCircle : DrawableOsuHitObject + public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { private HitCircle osuObject; @@ -156,5 +156,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables break; } } + + public Drawable ProxiedLayer => ApproachCircle; } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index 611daad642..18999496b6 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -6,11 +6,10 @@ using osu.Framework.Graphics; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using OpenTK; -using osu.Framework.Input; namespace osu.Game.Modes.Osu.Objects.Drawables { - class DrawableSlider : DrawableOsuHitObject + public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { private Slider slider; @@ -133,6 +132,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables FadeOut(800); } + + public Drawable ProxiedLayer => initialCircle.ApproachCircle; } internal interface ISliderProgress diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index b6daffbb8b..20164060fe 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -60,10 +60,10 @@ namespace osu.Game.Modes.Osu.UI public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; - DrawableHitCircle c = h as DrawableHitCircle; + IDrawableHitObjectWithProxiedApproach c = h as IDrawableHitObjectWithProxiedApproach; if (c != null) { - approachCircles.Add(c.ApproachCircle.CreateProxy()); + approachCircles.Add(c.ProxiedLayer.CreateProxy()); } h.OnJudgement += judgement; diff --git a/osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs b/osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs new file mode 100644 index 0000000000..9abd2f8592 --- /dev/null +++ b/osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using osu.Framework.Graphics; + +namespace osu.Game.Modes.Objects.Drawables +{ + public interface IDrawableHitObjectWithProxiedApproach + { + Drawable ProxiedLayer { get; } + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 4cbc229596..858da59ed5 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -75,6 +75,7 @@ + From e88d02d3c43840317a49720fd8962a9305b71b53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 18:40:37 +0900 Subject: [PATCH 06/40] Ensure SliderCurve is assigned Calculated before used. --- .../Objects/OsuHitObjectParser.cs | 16 ++++--------- osu.Game.Modes.Osu/Objects/Slider.cs | 24 ++++++++++++++++--- osu.Game.Modes.Osu/Objects/SliderCurve.cs | 6 +++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs index ce480e1eac..801b74084b 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs @@ -29,8 +29,6 @@ namespace osu.Game.Modes.Osu.Objects result = new HitCircle(); break; case HitObjectType.Slider: - Slider s = new Slider(); - CurveTypes curveType = CurveTypes.Catmull; int repeatCount = 0; double length = 0; @@ -79,18 +77,13 @@ namespace osu.Game.Modes.Osu.Objects if (split.Length > 7) length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture); - s.RepeatCount = repeatCount; - - s.Curve = new SliderCurve + result = new Slider { ControlPoints = points, Length = length, - CurveType = curveType + CurveType = curveType, + RepeatCount = repeatCount }; - - s.Curve.Calculate(); - - result = s; break; case HitObjectType.Spinner: result = new Spinner(); @@ -101,7 +94,8 @@ namespace osu.Game.Modes.Osu.Objects } result.Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])); result.StartTime = double.Parse(split[2]); - result.Sample = new HitSampleInfo { + result.Sample = new HitSampleInfo + { Type = (SampleType)int.Parse(split[4]), Set = SampleSet.Soft, }; diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index 85ee83a7f8..a809761698 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Game.Beatmaps; using OpenTK; @@ -19,11 +20,28 @@ namespace osu.Game.Modes.Osu.Objects set { stackHeight = value; - if (Curve != null) - Curve.Offset = StackOffset; + Curve.Offset = StackOffset; } } + public List ControlPoints + { + get { return Curve.ControlPoints; } + set { Curve.ControlPoints = value; } + } + + public double Length + { + get { return Curve.Length; } + set { Curve.Length = value; } + } + + public CurveTypes CurveType + { + get { return Curve.CurveType; } + set { Curve.CurveType = value; } + } + public double Velocity; public override void SetDefaultsFromBeatmap(Beatmap beatmap) @@ -35,7 +53,7 @@ namespace osu.Game.Modes.Osu.Objects public int RepeatCount; - public SliderCurve Curve; + internal readonly SliderCurve Curve = new SliderCurve(); } public enum CurveTypes diff --git a/osu.Game.Modes.Osu/Objects/SliderCurve.cs b/osu.Game.Modes.Osu/Objects/SliderCurve.cs index 62931a7356..06312cb489 100644 --- a/osu.Game.Modes.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Modes.Osu/Objects/SliderCurve.cs @@ -172,6 +172,9 @@ namespace osu.Game.Modes.Osu.Objects /// End progress. Ranges from 0 (beginning of the slider) to 1 (end of the slider). public void GetPathToProgress(List path, double p0, double p1) { + if (calculatedPath.Count == 0 && ControlPoints.Count > 0) + Calculate(); + double d0 = progressToDistance(p0); double d1 = progressToDistance(p1); @@ -196,6 +199,9 @@ namespace osu.Game.Modes.Osu.Objects /// public Vector2 PositionAt(double progress) { + if (calculatedPath.Count == 0 && ControlPoints.Count > 0) + Calculate(); + double d = progressToDistance(progress); return interpolateVertices(indexOfDistance(d), d) + Offset; } From 396c8121d3206432bec42b44eb3b1aec13515201 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 11:15:40 +0900 Subject: [PATCH 07/40] Better slider defaults. --- osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs | 2 +- osu.Game.Modes.Osu/Objects/Slider.cs | 2 +- osu.Game.Modes.Osu/Objects/SliderCurve.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs index 801b74084b..822e9a9b7c 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs @@ -30,7 +30,7 @@ namespace osu.Game.Modes.Osu.Objects break; case HitObjectType.Slider: CurveTypes curveType = CurveTypes.Catmull; - int repeatCount = 0; + int repeatCount; double length = 0; List points = new List(); diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index a809761698..8479d69669 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -51,7 +51,7 @@ namespace osu.Game.Modes.Osu.Objects Velocity = 100 / beatmap.BeatLengthAt(StartTime, true) * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier; } - public int RepeatCount; + public int RepeatCount = 1; internal readonly SliderCurve Curve = new SliderCurve(); } diff --git a/osu.Game.Modes.Osu/Objects/SliderCurve.cs b/osu.Game.Modes.Osu/Objects/SliderCurve.cs index 06312cb489..e60e58da9a 100644 --- a/osu.Game.Modes.Osu/Objects/SliderCurve.cs +++ b/osu.Game.Modes.Osu/Objects/SliderCurve.cs @@ -15,7 +15,7 @@ namespace osu.Game.Modes.Osu.Objects public List ControlPoints; - public CurveTypes CurveType; + public CurveTypes CurveType = CurveTypes.PerfectCurve; public Vector2 Offset; From 8e9a5e9faab3715096a7eea4ed0c7de9a4d44b80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 17:52:53 +0900 Subject: [PATCH 08/40] Add the ability to make DrawableHitObjects non-interactive (for use in other contexts). --- osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index d4beabe2ba..4df49ca01f 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -19,6 +19,10 @@ namespace osu.Game.Modes.Objects.Drawables { public event Action OnJudgement; + public override bool HandleInput => Interactive; + + public bool Interactive = true; + public Container ChildObjects; public JudgementInfo Judgement; From 10dfe47638d871c67abceed4ebd30df0fe6f7360 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 14 Feb 2017 18:55:54 +0900 Subject: [PATCH 09/40] Add spinners and improve TestCaseHitObjects. --- .../Tests/TestCaseHitObjects.cs | 127 ++++++++++--- .../Objects/Drawables/DrawableHitCircle.cs | 8 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 1 + .../Objects/Drawables/DrawableSpinner.cs | 140 +++++++++++++++ .../Drawables/Pieces/SpinnerBackground.cs | 10 ++ .../Objects/Drawables/Pieces/SpinnerDisc.cs | 168 ++++++++++++++++++ .../Objects/OsuHitObjectParser.cs | 17 +- osu.Game.Modes.Osu/Objects/Spinner.cs | 5 + osu.Game.Modes.Osu/UI/OsuHitRenderer.cs | 3 +- osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 3 + 10 files changed, 451 insertions(+), 31 deletions(-) create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 7ca51f8af3..1e3d8df6c6 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -1,18 +1,23 @@ // 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; using osu.Framework.GameModes.Testing; using osu.Framework.Graphics; using osu.Framework.Timing; using OpenTK; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects; using osu.Game.Modes.Osu.Objects.Drawables; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Game.Modes; +using OpenTK.Graphics; namespace osu.Desktop.VisualTests.Tests { @@ -20,44 +25,124 @@ namespace osu.Desktop.VisualTests.Tests { public override string Name => @"Hit Objects"; + private StopwatchClock rateAdjustClock; + private FramedClock framedClock; + + bool auto = false; + public TestCaseHitObjects() { - var swClock = new StopwatchClock(true) { Rate = 0.2f }; - Clock = new FramedClock(swClock); + rateAdjustClock = new StopwatchClock(true); + framedClock = new FramedClock(rateAdjustClock); + playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; }; + } + + HitObjectType mode = HitObjectType.Spinner; + + BindableNumber playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 }; + private Container playfieldContainer; + private Container approachContainer; + + private void load(HitObjectType mode) + { + this.mode = mode; + + switch (mode) + { + case HitObjectType.Circle: + const int count = 10; + + for (int i = 0; i < count; i++) + { + var h = new HitCircle + { + StartTime = framedClock.CurrentTime + 600 + i * 80, + Position = new Vector2((i - count / 2) * 14), + }; + + add(new DrawableHitCircle(h)); + } + break; + case HitObjectType.Slider: + add(new DrawableSlider(new Slider + { + StartTime = framedClock.CurrentTime + 600, + ControlPoints = new List() + { + new Vector2(-200, 0), + new Vector2(400, 0), + }, + Length = 400, + Position = new Vector2(-200, 0), + Velocity = 1, + })); + break; + case HitObjectType.Spinner: + add(new DrawableSpinner(new Spinner + { + StartTime = framedClock.CurrentTime + 600, + Length = 1000, + Position = new Vector2(0, 0), + })); + break; + } } public override void Reset() { base.Reset(); - Clock.ProcessFrame(); + playbackSpeed.TriggerChange(); - Container approachContainer = new Container { Depth = float.MinValue, }; + AddButton(@"circles", () => load(HitObjectType.Circle)); + AddButton(@"slider", () => load(HitObjectType.Slider)); + AddButton(@"spinner", () => load(HitObjectType.Spinner)); - Add(approachContainer); + AddToggle(@"auto", () => { auto = !auto; load(mode); }); - const int count = 10; - - for (int i = 0; i < count; i++) + ButtonsContainer.Add(new SpriteText { Text = "Playback Speed" }); + ButtonsContainer.Add(new BasicSliderBar { - var h = new HitCircle + Width = 150, + Height = 10, + SelectionColor = Color4.Orange, + Bindable = playbackSpeed + }); + + framedClock.ProcessFrame(); + + var clockAdjustContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Clock = framedClock, + Children = new[] { - StartTime = Clock.CurrentTime + 600 + i * 80, - Position = new Vector2((i - count / 2) * 14), - }; + playfieldContainer = new Container { RelativeSizeAxes = Axes.Both }, + approachContainer = new Container { RelativeSizeAxes = Axes.Both } + } + }; - DrawableHitCircle d = new DrawableHitCircle(h) - { - Anchor = Anchor.Centre, - Depth = i, - State = ArmedState.Hit, - Judgement = new OsuJudgementInfo { Result = HitResult.Hit } - }; + Add(clockAdjustContainer); + load(mode); + } - approachContainer.Add(d.ApproachCircle.CreateProxy()); - Add(d); + int depth; + void add(DrawableHitObject h) + { + h.Anchor = Anchor.Centre; + h.Depth = depth++; + + if (auto) + { + h.State = ArmedState.Hit; + h.Judgement = new OsuJudgementInfo { Result = HitResult.Hit }; } + + playfieldContainer.Add(h); + var proxyable = h as IDrawableHitObjectWithProxiedApproach; + if (proxyable != null) + approachContainer.Add(proxyable.ProxiedLayer.CreateProxy()); } } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 091366b88c..5c4401455c 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.ComponentModel; using osu.Framework.Graphics; using osu.Framework.Graphics.Transformations; using osu.Game.Modes.Objects.Drawables; @@ -13,7 +12,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - private HitCircle osuObject; + private OsuHitObject osuObject; public ApproachCircle ApproachCircle; private CirclePiece circle; @@ -23,11 +22,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private NumberPiece number; private GlowPiece glow; - public DrawableHitCircle(HitCircle h) : base(h) + public DrawableHitCircle(OsuHitObject h) : base(h) { + Origin = Anchor.Centre; + osuObject = h; - Origin = Anchor.Centre; Position = osuObject.StackedPosition; Scale = new Vector2(osuObject.Scale); diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 0c7ca11672..ef153848d4 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; +using osu.Framework.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs new file mode 100644 index 0000000000..94bcade2dc --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transformations; +using osu.Framework.MathUtils; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Osu.Objects.Drawables.Pieces; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Modes.Osu.Objects.Drawables +{ + public class DrawableSpinner : DrawableOsuHitObject + { + private Spinner spinner; + + private SpinnerDisc disc; + private SpinnerBackground background; + private DrawableHitCircle circle; + private NumberPiece number; + + public DrawableSpinner(Spinner s) : base(s) + { + Origin = Anchor.Centre; + Position = s.Position; + + //take up full playfield. + Size = new Vector2(512); + + spinner = s; + + Children = new Drawable[] + { + background = new SpinnerBackground + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + DiscColour = Color4.Black + }, + disc = new SpinnerDisc + { + Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + DiscColour = s.Colour + }, + circle = new DrawableHitCircle(s) + { + Interactive = false, + Position = Vector2.Zero, + Anchor = Anchor.Centre, + } + }; + + circle.ApproachCircle.Colour = Color4.Transparent; + + background.Scale = scaleToCircle; + disc.Scale = scaleToCircle; + } + + public override bool Contains(Vector2 screenSpacePos) => true; + + protected override void CheckJudgement(bool userTriggered) + { + if (Time.Current < HitObject.StartTime) return; + + var j = Judgement as OsuJudgementInfo; + + disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100); + + if (!userTriggered && Time.Current >= HitObject.EndTime) + { + if (Progress >= 1) + { + j.Score = OsuScoreResult.Hit300; + j.Result = HitResult.Hit; + } + else if (Progress > .9) + { + j.Score = OsuScoreResult.Hit100; + j.Result = HitResult.Hit; + } + else if (Progress > .75) + { + j.Score = OsuScoreResult.Hit50; + j.Result = HitResult.Hit; + } + else + { + j.Score = OsuScoreResult.Miss; + j.Result = HitResult.Miss; + } + } + } + + private Vector2 scaleToCircle => new Vector2(circle.Scale * circle.DrawWidth / DrawWidth) * 0.95f; + + private float spinsPerMinuteNeeded = 100 + (5 * 15); //TODO: read per-map OD and place it on the 5 + + private float rotationsNeeded => (float)(spinsPerMinuteNeeded * (spinner.EndTime - spinner.StartTime) / 60000f); + + public float Progress => MathHelper.Clamp(disc.RotationAbsolute / 360 / rotationsNeeded, 0, 1); + + protected override void UpdatePreemptState() + { + base.UpdatePreemptState(); + + FadeIn(200); + + background.Delay(TIME_PREEMPT - 100); + background.FadeIn(200); + background.ScaleTo(1, 200, EasingTypes.OutQuint); + + disc.Delay(TIME_PREEMPT - 50); + disc.FadeIn(200); + } + + protected override void UpdateState(ArmedState state) + { + base.UpdateState(state); + + Delay(HitObject.Duration, true); + + FadeOut(160); + + switch (state) + { + case ArmedState.Hit: + ScaleTo(Scale * 1.2f, 320, EasingTypes.Out); + break; + case ArmedState.Miss: + ScaleTo(Scale * 0.8f, 320, EasingTypes.In); + break; + } + } + } +} diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs new file mode 100644 index 0000000000..50dab933b0 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +{ + public class SpinnerBackground : SpinnerDisc + { + public override bool HandleInput => false; + } +} diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs new file mode 100644 index 0000000000..76fd360818 --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -0,0 +1,168 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Transformations; +using osu.Framework.Input; +using osu.Framework.Logging; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +{ + public class SpinnerDisc : CircularContainer + { + public override bool Contains(Vector2 screenSpacePos) => true; + + protected Sprite Disc; + + public SRGBColour DiscColour + { + get { return Disc.Colour; } + set { Disc.Colour = value; } + } + + class SpinnerBorder : Container + { + public SpinnerBorder() + { + Origin = Anchor.Centre; + Anchor = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + + layout(); + } + + private int lastLayoutDotCount; + private void layout() + { + int count = (int)(MathHelper.Pi * ScreenSpaceDrawQuad.Width / 9); + + if (count == lastLayoutDotCount) return; + + lastLayoutDotCount = count; + + while (Children.Count() < count) + { + Add(new CircularContainer + { + Colour = Color4.White, + RelativePositionAxes = Axes.Both, + Origin = Anchor.Centre, + Size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000), + Children = new[] + { + new Box + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + } + } + }); + } + + var size = new Vector2(1 / ScreenSpaceDrawQuad.Width * 2000); + + int i = 0; + foreach (var d in Children) + { + d.Size = size; + d.Position = new Vector2( + 0.5f + (float)Math.Sin((float)i / count * 2 * MathHelper.Pi) / 2, + 0.5f + (float)Math.Cos((float)i / count * 2 * MathHelper.Pi) / 2 + ); + + i++; + } + } + + protected override void Update() + { + base.Update(); + layout(); + } + } + + public SpinnerDisc() + { + RelativeSizeAxes = Axes.Both; + + Children = new Drawable[] + { + Disc = new Box + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Alpha = 0.2f, + }, + new SpinnerBorder() + }; + } + + bool tracking; + public bool Tracking + { + get { return tracking; } + set + { + if (value == tracking) return; + + tracking = value; + + Disc.FadeTo(tracking ? 0.5f : 0.2f, 100); + } + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + Tracking = true; + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + Tracking = false; + return base.OnMouseUp(state, args); + } + + protected override bool OnMouseMove(InputState state) + { + Tracking |= state.Mouse.HasMainButtonPressed; + mousePosition = state.Mouse.Position; + return base.OnMouseMove(state); + } + + private Vector2 mousePosition; + + private float lastAngle; + private float currentRotation; + public float RotationAbsolute; + + protected override void Update() + { + base.Update(); + + var thisAngle = -(float)MathHelper.RadiansToDegrees(Math.Atan2(mousePosition.X - DrawSize.X / 2, mousePosition.Y - DrawSize.Y / 2)); + if (tracking) + { + if (thisAngle - lastAngle > 180) + lastAngle += 360; + else if (lastAngle - thisAngle > 180) + lastAngle -= 360; + + currentRotation += thisAngle - lastAngle; + RotationAbsolute += Math.Abs(thisAngle - lastAngle); + } + lastAngle = thisAngle; + + RotateTo(currentRotation, 100, EasingTypes.OutExpo); + } + } +} diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs index 822e9a9b7c..52329a2766 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs @@ -26,7 +26,10 @@ namespace osu.Game.Modes.Osu.Objects switch (type) { case HitObjectType.Circle: - result = new HitCircle(); + result = new HitCircle + { + Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])) + }; break; case HitObjectType.Slider: CurveTypes curveType = CurveTypes.Catmull; @@ -82,18 +85,22 @@ namespace osu.Game.Modes.Osu.Objects ControlPoints = points, Length = length, CurveType = curveType, - RepeatCount = repeatCount + RepeatCount = repeatCount, + Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])) }; break; case HitObjectType.Spinner: - result = new Spinner(); + result = new Spinner + { + Length = Convert.ToDouble(split[5], CultureInfo.InvariantCulture) - Convert.ToDouble(split[2], CultureInfo.InvariantCulture), + Position = new Vector2(512, 384) / 2, + }; break; default: //throw new InvalidOperationException($@"Unknown hit object type {type}"); return null; } - result.Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])); - result.StartTime = double.Parse(split[2]); + result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture); result.Sample = new HitSampleInfo { Type = (SampleType)int.Parse(split[4]), diff --git a/osu.Game.Modes.Osu/Objects/Spinner.cs b/osu.Game.Modes.Osu/Objects/Spinner.cs index ea6f1b53f2..fa1bddf760 100644 --- a/osu.Game.Modes.Osu/Objects/Spinner.cs +++ b/osu.Game.Modes.Osu/Objects/Spinner.cs @@ -1,9 +1,14 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; + namespace osu.Game.Modes.Osu.Objects { public class Spinner : OsuHitObject { + public double Length; + + public override double EndTime => StartTime + Length; } } diff --git a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs b/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs index fdaab87d55..fa222aafd7 100644 --- a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs @@ -21,7 +21,8 @@ namespace osu.Game.Modes.Osu.UI return new DrawableHitCircle(h as HitCircle); if (h is Slider) return new DrawableSlider(h as Slider); - + if (h is Spinner) + return new DrawableSpinner(h as Spinner); return null; } } diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index e0b9f5c904..4845deb167 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -49,9 +49,11 @@ + + @@ -59,6 +61,7 @@ + From 325054c7f7836812ff44f1fdc490b340aaefce12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 01:29:51 +0900 Subject: [PATCH 10/40] Update framework. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 1cd7a165ec..425857dcf4 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1cd7a165ec42cd1eeb4eee06b5a4a6cdd8c280da +Subproject commit 425857dcf4868035879fb42916fc65dd3132ca83 From f2b0fd4de017f7803eefacb28e7f7cdb72efff2b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 11:37:23 +0900 Subject: [PATCH 11/40] Throw exception on unknown hitobject. --- osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs index 52329a2766..b4dc494ad4 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectParser.cs @@ -97,8 +97,7 @@ namespace osu.Game.Modes.Osu.Objects }; break; default: - //throw new InvalidOperationException($@"Unknown hit object type {type}"); - return null; + throw new InvalidOperationException($@"Unknown hit object type {type}"); } result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture); result.Sample = new HitSampleInfo From 580584a0151746b51a1cb7118d42e33ede1109b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 12:36:47 +0900 Subject: [PATCH 12/40] Don't use osu! mode parser for other game modes for now (convert still works). --- osu.Game.Modes.Catch/CatchRuleset.cs | 2 +- osu.Game.Modes.Mania/ManiaRuleset.cs | 2 +- osu.Game.Modes.Taiko/TaikoRuleset.cs | 2 +- osu.Game/Modes/Objects/NullHitObjectParser.cs | 14 ++++++++++++++ osu.Game/osu.Game.csproj | 1 + 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Modes/Objects/NullHitObjectParser.cs diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 5b681badd7..5db11737f4 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -24,6 +24,6 @@ namespace osu.Game.Modes.Catch public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null; - public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); + public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser(); } } diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index 75f7d93228..654a4ddaa6 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -25,6 +25,6 @@ namespace osu.Game.Modes.Mania public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null; - public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); + public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser(); } } diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index c5d5ff5805..bd20608d57 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -25,6 +25,6 @@ namespace osu.Game.Modes.Taiko public override ScoreProcessor CreateScoreProcessor(int hitObjectCount) => null; - public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser(); + public override HitObjectParser CreateHitObjectParser() => new NullHitObjectParser(); } } diff --git a/osu.Game/Modes/Objects/NullHitObjectParser.cs b/osu.Game/Modes/Objects/NullHitObjectParser.cs new file mode 100644 index 0000000000..4f06d5ab26 --- /dev/null +++ b/osu.Game/Modes/Objects/NullHitObjectParser.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + + +namespace osu.Game.Modes.Objects +{ + /// + /// Returns null HitObjects but at least allows us to run. + /// + public class NullHitObjectParser : HitObjectParser + { + public override HitObject Parse(string text) => null; + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 858da59ed5..ed49590dbd 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -77,6 +77,7 @@ + From 753232533acb467ee5eeae3213e620b7e3aef544 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 12:37:57 +0900 Subject: [PATCH 13/40] Display Important/Error logging in notifications for now. --- osu.Game/OsuGame.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 9188fab355..2cce0aa0ce 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -25,6 +25,7 @@ using OpenTK; using System.Linq; using osu.Framework.Graphics.Primitives; using System.Collections.Generic; +using osu.Game.Overlays.Notifications; namespace osu.Game { @@ -130,6 +131,16 @@ namespace osu.Game Origin = Anchor.TopRight, }).Preload(this, overlayContent.Add); + Logger.NewEntry += entry => + { + if (entry.Level < LogLevel.Important) return; + + notificationManager.Post(new SimpleNotification + { + Text = $@"{entry.Level}: {entry.Message}" + }); + }; + Dependencies.Cache(options); Dependencies.Cache(musicController); Dependencies.Cache(notificationManager); From d570a6d308fe0aab0487ee13f62c540f3116da33 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 12:38:10 +0900 Subject: [PATCH 14/40] Handle cases where HitObjects were not parsed. --- osu.Game/Screens/Play/Player.cs | 17 +++++++++++++---- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7f2fa415d2..650568f60b 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -23,6 +23,7 @@ using System.Linq; using osu.Game.Beatmaps; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Logging; namespace osu.Game.Screens.Play { @@ -75,9 +76,14 @@ namespace osu.Game.Screens.Play { if (Beatmap == null) Beatmap = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); + + if ((Beatmap?.Beatmap?.HitObjects.Count ?? 0) == 0) + throw new Exception("No valid objects were found!"); } - catch + catch (Exception e) { + Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error); + //couldn't load, hard abort! Exit(); return; @@ -117,7 +123,8 @@ namespace osu.Game.Screens.Play pauseOverlay = new PauseOverlay { Depth = -1, - OnResume = delegate { + OnResume = delegate + { Delay(400); Schedule(Resume); }, @@ -277,9 +284,9 @@ namespace osu.Game.Screens.Play protected override void OnEntering(GameMode last) { base.OnEntering(last); - + (Background as BackgroundModeBeatmap)?.BlurTo(Vector2.Zero, 1000); - Background?.FadeTo((100f- dimLevel)/100, 1000); + Background?.FadeTo((100f - dimLevel) / 100, 1000); Content.Alpha = 0; dimLevel.ValueChanged += dimChanged; @@ -287,6 +294,8 @@ namespace osu.Game.Screens.Play protected override bool OnExiting(GameMode next) { + if (pauseOverlay == null) return false; + if (pauseOverlay.State != Visibility.Visible && !canPause) return true; if (!IsPaused && sourceClock.IsRunning) // For if the user presses escape quickly when entering the map diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 390d175bd4..eb93b4ac1a 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -74,7 +74,7 @@ namespace osu.Game.Screens.Select { Name = "Length", Icon = FontAwesome.fa_clock_o, - Content = TimeSpan.FromMilliseconds(beatmap.Beatmap.HitObjects.Last().EndTime - beatmap.Beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"), + Content = beatmap.Beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(beatmap.Beatmap.HitObjects.Last().EndTime - beatmap.Beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"), })); labels.Add(new InfoLabel(new BeatmapStatistic From 25e7a08cca590af9303c91f603b716cb98c0e7a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 13:40:13 +0900 Subject: [PATCH 15/40] Reset local version and explicitly show release/debug builds. --- osu.Desktop.Deploy/Program.cs | 3 +++ osu.Desktop/Overlays/VersionManager.cs | 16 +++++++++++++++- osu.Desktop/Properties/AssemblyInfo.cs | 6 +++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index 07374e7541..3cd9c80365 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -122,6 +122,9 @@ namespace osu.Desktop.Deploy uploadBuild(version); + //reset assemblyinfo. + updateAssemblyInfo("0.0.0"); + write("Done!", ConsoleColor.White); Console.ReadLine(); } diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index e3cffc1804..6c34838130 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,6 +14,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; using OpenTK; +using OpenTK.Graphics; namespace osu.Desktop.Overlays { @@ -35,7 +37,18 @@ namespace osu.Desktop.Overlays Origin = Anchor.BottomCentre; Alpha = 0; + bool isDebug = false; + Debug.Assert(isDebug = true); + var asm = Assembly.GetEntryAssembly().GetName(); + string version; + if (asm.Version.Major == 0) + { + version = @"local " + (isDebug ? @"debug" : @"release"); + } + else + version = $@"{asm.Version.Major}.{asm.Version.Minor}.{asm.Version.Build}"; + Children = new Drawable[] { new FlowContainer @@ -60,7 +73,8 @@ namespace osu.Desktop.Overlays }, new OsuSpriteText { - Text = $@"{asm.Version.Major}.{asm.Version.Minor}.{asm.Version.Build}" + Colour = isDebug ? colours.Red : Color4.White, + Text = version }, } }, diff --git a/osu.Desktop/Properties/AssemblyInfo.cs b/osu.Desktop/Properties/AssemblyInfo.cs index c078b4caf5..17329d8ac0 100644 --- a/osu.Desktop/Properties/AssemblyInfo.cs +++ b/osu.Desktop/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Reflection; @@ -25,5 +25,5 @@ using System.Runtime.InteropServices; // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("55e28cb2-7b6c-4595-8dcc-9871d8aad7e9")] -[assembly: AssemblyVersion("2017.212.0")] -[assembly: AssemblyFileVersion("2017.212.0")] +[assembly: AssemblyVersion("0.0.0")] +[assembly: AssemblyFileVersion("0.0.0")] From d42c5481b0ae05a39556f1bf0da25f1df798c307 Mon Sep 17 00:00:00 2001 From: Jorolf Date: Wed, 15 Feb 2017 05:48:49 +0100 Subject: [PATCH 16/40] Make mode selector selected line non-relative. (#352) * mode selector line has the correct length now * calculation is now a 'one-liner' * Line length is absolute now * Line length is calculated inline --- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index af543ae559..d8ad235cec 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -41,12 +41,11 @@ namespace osu.Game.Overlays.Toolbar Direction = FlowDirections.Horizontal, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Padding = new MarginPadding { Left = 10, Right = 10 }, + Padding = new MarginPadding { Left = padding, Right = padding }, }, modeButtonLine = new Container { - RelativeSizeAxes = Axes.X, - Size = new Vector2(0.3f, 3), + Size = new Vector2(padding * 2 + ToolbarButton.WIDTH, 3), Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, Masking = true, From f8e1006fcd7f29a3eca29d219c18d88950d9ff4d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 16:09:21 +0900 Subject: [PATCH 17/40] Change inspection settings. UnusedMember_002ELocal: Warning -> Hint VirtualMemberCallInConstructor: Warning -> Hint --- osu-framework | 2 +- osu.sln.DotSettings | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 425857dcf4..a766d283f4 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 425857dcf4868035879fb42916fc65dd3132ca83 +Subproject commit a766d283f4d628736db784001cc1f11d065cab9d diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index e9b225da4e..d3054a4561 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -21,8 +21,10 @@ DO_NOT_SHOW DO_NOT_SHOW HINT + HINT SUGGESTION HINT + HINT <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) True From 12e265a3e2d0cac98b49aff080f6396000df8970 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 20:39:10 +0900 Subject: [PATCH 18/40] Combine triangle system implementations. --- .../Objects/Drawables/Pieces/CirclePiece.cs | 8 ++-- .../Objects/Drawables/Pieces/ExplodePiece.cs | 5 +- .../Objects/Drawables/Pieces/Triangles.cs | 46 ------------------- .../Drawables/Pieces/TrianglesPiece.cs | 26 +++++++++++ osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 39 +++++++++++----- 6 files changed, 61 insertions(+), 65 deletions(-) delete mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Pieces/Triangles.cs create mode 100644 osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs index f7477fb6f0..23f878d491 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -14,9 +14,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { public class CirclePiece : Container { - private Sprite disc; - private Triangles triangles; + public Func Hit; @@ -36,10 +35,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces Anchor = Anchor.Centre, Origin = Anchor.Centre }, - triangles = new Triangles + new TrianglesPiece { + RelativeSizeAxes = Axes.Both, BlendingMode = BlendingMode.Additive, - RelativeSizeAxes = Axes.Both + Alpha = 0.5f, } }; } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index ae382519df..08c7423c23 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -21,10 +21,11 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces Children = new Drawable[] { - new Triangles + new TrianglesPiece { BlendingMode = BlendingMode.Additive, - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f, } }; } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/Triangles.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/Triangles.cs deleted file mode 100644 index 42b53606ef..0000000000 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/Triangles.cs +++ /dev/null @@ -1,46 +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.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; -using osu.Framework.MathUtils; -using OpenTK; - -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces -{ - public class Triangles : Container - { - public override bool HandleInput => false; - - protected override void LoadComplete() - { - base.LoadComplete(); - - const float size = 100; - for (int i = 0; i < 10; i++) - { - Add(new Triangle - { - Origin = Anchor.Centre, - RelativePositionAxes = Axes.Both, - Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()), - Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f), - // Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length) - Size = new Vector2(size, 0.866f * size), - Alpha = RNG.NextSingle() * 0.3f, - }); - } - } - - protected override void Update() - { - base.Update(); - - foreach (Drawable d in Children) - d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 2880))); - } - } -} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs new file mode 100644 index 0000000000..57e00be1cf --- /dev/null +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.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 System; +using osu.Game.Graphics.Backgrounds; + +namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +{ + public class TrianglesPiece : Triangles + { + protected override bool ExpireOffScreenTriangles => false; + protected override bool CreateNewTriangles => false; + protected override float SpawnRatio => 0.5f; + + public TrianglesPiece() + { + TriangleScale = 1.2f; + } + + protected override void Update() + { + if (IsPresent) + base.Update(); + } + } +} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index 4845deb167..82c5537597 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 2dd630efae..219af9bd38 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -2,12 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; -using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Textures; using osu.Framework.MathUtils; using OpenTK; using OpenTK.Graphics; @@ -22,6 +20,21 @@ namespace osu.Game.Graphics.Backgrounds public Color4 ColourLight = Color4.White; public Color4 ColourDark = Color4.Black; + /// + /// Whether we want to expire triangles as they exit our draw area completely. + /// + protected virtual bool ExpireOffScreenTriangles => true; + + /// + /// Whether we should create new triangles as others expire. + /// + protected virtual bool CreateNewTriangles => true; + + /// + /// The amount of triangles we want compared to the default distribution. + /// + protected virtual float SpawnRatio => 1; + private float triangleScale = 1; public float TriangleScale @@ -29,9 +42,11 @@ namespace osu.Game.Graphics.Backgrounds get { return triangleScale; } set { + float change = value / triangleScale; triangleScale = value; - Children.ForEach(t => t.ScaleTo(triangleScale)); + if (change != 1) + Children.ForEach(t => t.Scale *= change); } } @@ -42,20 +57,20 @@ namespace osu.Game.Graphics.Backgrounds addTriangle(true); } - private int aimTriangleCount => (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale)); + private int aimTriangleCount => (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio); protected override void Update() { base.Update(); - foreach (Drawable d in Children) + foreach (var t in Children) { - d.Position -= new Vector2(0, (float)(d.Scale.X * (50 / DrawHeight) * (Time.Elapsed / 950)) / triangleScale); - if (d.DrawPosition.Y + d.DrawSize.Y * d.Scale.Y < 0) - d.Expire(); + t.Position -= new Vector2(0, (float)(t.Scale.X * (50 / DrawHeight) * (Time.Elapsed / 950)) / triangleScale); + if (ExpireOffScreenTriangles && t.DrawPosition.Y + t.DrawSize.Y * t.Scale.Y < 0) + t.Expire(); } - while (Children.Count() < aimTriangleCount) + while (CreateNewTriangles && Children.Count() < aimTriangleCount) addTriangle(false); } @@ -77,8 +92,8 @@ namespace osu.Game.Graphics.Backgrounds RelativePositionAxes = Axes.Both, Scale = new Vector2(scale), EdgeSmoothness = new Vector2(1), - // Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length) Colour = GetTriangleShade(), + // Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length) Size = new Vector2(size, 0.866f * size), Depth = scale, }; @@ -89,8 +104,8 @@ namespace osu.Game.Graphics.Backgrounds private void addTriangle(bool randomY) { var sprite = CreateTriangle(); - var triangleHeight = sprite.DrawHeight / DrawHeight; - sprite.Position = new Vector2(RNG.NextSingle(), randomY ? (RNG.NextSingle() * (1 + triangleHeight) - triangleHeight) : 1); + float triangleHeight = (sprite.DrawHeight / DrawHeight); + sprite.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() * (1 + triangleHeight) - triangleHeight : 1); Add(sprite); } } From ce859196d530d6c65808bd2e46c46e9d9e02bb66 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 21:05:46 +0900 Subject: [PATCH 19/40] Avoid glow fading out early on spinners. --- osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 5c4401455c..63e4a58dfc 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -124,6 +124,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables base.UpdateState(state); ApproachCircle.FadeOut(); + + glow.Delay(osuObject.Duration); glow.FadeOut(400); switch (state) From 67105e6dfd4f9f61531be0a382bd2842d7927f6e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 21:37:43 +0900 Subject: [PATCH 20/40] Replace all usage of SpriteText with OsuSpriteText. --- osu.Game.Modes.Osu/Objects/Drawables/HitExplosion.cs | 5 +++-- .../Overlays/Notifications/ProgressNotification.cs | 3 ++- osu.Game/Overlays/Notifications/SimpleNotification.cs | 3 ++- osu.Game/Overlays/Pause/PauseButton.cs | 3 ++- osu.Game/Overlays/Pause/PauseOverlay.cs | 11 ++++++----- osu.Game/Screens/Select/FilterControl.cs | 5 +++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/HitExplosion.cs b/osu.Game.Modes.Osu/Objects/Drawables/HitExplosion.cs index 1a92436d74..4176e556d4 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/HitExplosion.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/HitExplosion.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Game.Graphics.Sprites; using osu.Game.Modes.Objects.Drawables; using OpenTK; using OpenTK.Graphics; @@ -30,7 +31,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Children = new Drawable[] { - line1 = new SpriteText + line1 = new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -38,7 +39,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Font = @"Venera", TextSize = 16, }, - line2 = new SpriteText + line2 = new OsuSpriteText { Text = judgement.Combo.GetDescription(), Font = @"Venera", diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 8b0fc27d36..28a0d8a0af 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -118,7 +119,7 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.Both, }); - Content.Add(textDrawable = new SpriteText + Content.Add(textDrawable = new OsuSpriteText { TextSize = 16, Colour = OsuColour.Gray(128), diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index cf16978c3e..24f347eee3 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -6,6 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Notifications { @@ -52,7 +53,7 @@ namespace osu.Game.Overlays.Notifications } }); - Content.Add(textDrawable = new SpriteText + Content.Add(textDrawable = new OsuSpriteText { TextSize = 16, Colour = OsuColour.Gray(128), diff --git a/osu.Game/Overlays/Pause/PauseButton.cs b/osu.Game/Overlays/Pause/PauseButton.cs index 03b4a2a09f..1a1ba4f527 100644 --- a/osu.Game/Overlays/Pause/PauseButton.cs +++ b/osu.Game/Overlays/Pause/PauseButton.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Audio.Sample; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Pause { @@ -224,7 +225,7 @@ namespace osu.Game.Overlays.Pause } } }, - spriteText = new SpriteText + spriteText = new OsuSpriteText { Text = Text, Anchor = Anchor.Centre, diff --git a/osu.Game/Overlays/Pause/PauseOverlay.cs b/osu.Game/Overlays/Pause/PauseOverlay.cs index 65eb5154a6..a915fe91dd 100644 --- a/osu.Game/Overlays/Pause/PauseOverlay.cs +++ b/osu.Game/Overlays/Pause/PauseOverlay.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transformations; using System.Threading.Tasks; +using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Pause { @@ -39,14 +40,14 @@ namespace osu.Game.Overlays.Pause retryCounterContainer.Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Text = "You've retried ", Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f), TextSize = 18 }, - new SpriteText + new OsuSpriteText { Text = String.Format("{0:n0}", value), Font = @"Exo2.0-Bold", @@ -54,7 +55,7 @@ namespace osu.Game.Overlays.Pause ShadowColour = new Color4(0, 0, 0, 0.25f), TextSize = 18 }, - new SpriteText + new OsuSpriteText { Text = $" time{((value == 1) ? "" : "s")} in this session", Shadow = true, @@ -119,7 +120,7 @@ namespace osu.Game.Overlays.Pause Anchor = Anchor.TopCentre, Children = new Drawable[] { - new SpriteText + new OsuSpriteText { Text = @"paused", Font = @"Exo2.0-Medium", @@ -131,7 +132,7 @@ namespace osu.Game.Overlays.Pause Shadow = true, ShadowColour = new Color4(0, 0, 0, 0.25f) }, - new SpriteText + new OsuSpriteText { Text = @"you're not going to do what i think you're going to do, are ya?", Origin = Anchor.TopCentre, diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 512fa22b3a..975a3f9ca3 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Select { @@ -127,7 +128,7 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both; Children = new Drawable[] { - text = new SpriteText + text = new OsuSpriteText { Margin = new MarginPadding(5), TextSize = 14, @@ -213,7 +214,7 @@ namespace osu.Game.Screens.Select Anchor = Anchor.TopRight, Children = new Drawable[] { - sortLabel = new SpriteText + sortLabel = new OsuSpriteText { Font = @"Exo2.0-Bold", Text = "Sort results by", From bab219c428f30005b51ff39c423b63c363f55326 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 21:51:16 +0900 Subject: [PATCH 21/40] Fix SliderBall weirdness (not correctly staying circular). Also adjusts tracking to only change during sldier active time. --- .../Objects/Drawables/Pieces/SliderBall.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs index d5ad94b5bd..88bf49b644 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -11,7 +11,7 @@ using OpenTK.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { - public class SliderBall : Container, ISliderProgress + public class SliderBall : CircularContainer, ISliderProgress { private readonly Slider slider; private Box follow; @@ -39,7 +39,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces Height = width, Alpha = 0, }, - new Container + new CircularContainer { Masking = true, AutoSizeAxes = Axes.Both, @@ -48,7 +48,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces BorderThickness = 10, BorderColour = Color4.White, Alpha = 1, - CornerRadius = width / 2, Children = new[] { new Box @@ -104,8 +103,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { base.Update(); - CornerRadius = DrawWidth / 2; - Tracking = canCurrentlyTrack && lastState != null && Contains(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed; + if (Time.Current < slider.EndTime) + Tracking = canCurrentlyTrack && lastState != null && Contains(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed; } public void UpdateProgress(double progress, int repeat) From 7fbc5990d134a7912c2cc17d01b66eb7af077d0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 23:23:55 +0900 Subject: [PATCH 22/40] Add combo numbers. --- .../Objects/Drawables/DrawableHitCircle.cs | 5 ++- .../Objects/Drawables/DrawableSlider.cs | 2 + .../Objects/Drawables/Pieces/NumberPiece.cs | 39 ++++++++++++++----- .../Objects/OsuHitObjectConverter.cs | 6 +++ osu.Game/Modes/Objects/HitObject.cs | 2 + 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 63e4a58dfc..208bf15328 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -49,7 +49,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables return true; }, }, - number = new NumberPiece(), + number = new NumberPiece() + { + Text = h is Spinner ? "S" : (HitObject.ComboIndex + 1).ToString(), + }, ring = new RingPiece(), flash = new FlashPiece(), explode = new ExplodePiece diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index 18999496b6..6c4e1fec78 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -49,8 +49,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables }, initialCircle = new DrawableHitCircle(new HitCircle { + //todo: avoid creating this temporary HitCircle. StartTime = s.StartTime, Position = s.StackedPosition, + ComboIndex = s.ComboIndex, Scale = s.Scale, Colour = s.Colour, Sample = s.Sample, diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 8a594ed95c..bb18e32475 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -6,33 +6,54 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { public class NumberPiece : Container { - private Sprite number; + private SpriteText number; + + public string Text + { + get { return number.Text; } + set { number.Text = value; } + } public NumberPiece() { Anchor = Anchor.Centre; Origin = Anchor.Centre; - Children = new[] + Children = new Drawable[] { - number = new Sprite + new CircularContainer { + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Glow, + Radius = 60, + Colour = Color4.White.Opacity(0.5f), + }, + Children = new[] + { + new Box() + } + }, + number = new OsuSpriteText + { + Text = @"1", + Font = @"Venera", + UseFullGlyphHeight = false, Anchor = Anchor.Centre, Origin = Anchor.Centre, + TextSize = 40, Alpha = 1 } }; } - - [BackgroundDependencyLoader] - private void load(TextureStore textures) - { - number.Texture = textures.Get(@"Play/osu/number"); - } } } \ No newline at end of file diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectConverter.cs b/osu.Game.Modes.Osu/Objects/OsuHitObjectConverter.cs index 27376df323..989a5caffb 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectConverter.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObjectConverter.cs @@ -15,8 +15,14 @@ namespace osu.Game.Modes.Osu.Objects { List output = new List(); + int combo = 0; foreach (HitObject h in beatmap.HitObjects) + { + if (h.NewCombo) combo = 0; + + h.ComboIndex = combo++; output.Add(h as OsuHitObject); + } UpdateStacking(output, beatmap.BeatmapInfo?.StackLeniency ?? 0.7f); diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Modes/Objects/HitObject.cs index 841858ac89..cdc5f1655d 100644 --- a/osu.Game/Modes/Objects/HitObject.cs +++ b/osu.Game/Modes/Objects/HitObject.cs @@ -24,6 +24,8 @@ namespace osu.Game.Modes.Objects public HitSampleInfo Sample; + public int ComboIndex; + public virtual void SetDefaultsFromBeatmap(Beatmap beatmap) { } } } From 31a617363a1d62ef93a5c4b7a0526154df635533 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Feb 2017 23:24:08 +0900 Subject: [PATCH 23/40] Improve the feel of spinners. --- .../Objects/Drawables/DrawableSpinner.cs | 31 +++++++++++---- .../Objects/Drawables/Pieces/SpinnerDisc.cs | 38 +++++++++++++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs index 94bcade2dc..cd72483d1e 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transformations; using osu.Framework.MathUtils; using osu.Game.Modes.Objects.Drawables; @@ -18,8 +19,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private SpinnerDisc disc; private SpinnerBackground background; + private Container circleContainer; private DrawableHitCircle circle; - private NumberPiece number; public DrawableSpinner(Spinner s) : base(s) { @@ -47,16 +48,23 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Origin = Anchor.Centre, DiscColour = s.Colour }, - circle = new DrawableHitCircle(s) + circleContainer = new Container { - Interactive = false, - Position = Vector2.Zero, + AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new [] + { + circle = new DrawableHitCircle(s) + { + Interactive = false, + Position = Vector2.Zero, + Anchor = Anchor.Centre, + } + } } }; - circle.ApproachCircle.Colour = Color4.Transparent; - background.Scale = scaleToCircle; disc.Scale = scaleToCircle; } @@ -71,6 +79,9 @@ namespace osu.Game.Modes.Osu.Objects.Drawables disc.ScaleTo(Interpolation.ValueAt(Math.Sqrt(Progress), scaleToCircle, Vector2.One, 0, 1), 100); + if (Progress >= 1) + disc.Complete = true; + if (!userTriggered && Time.Current >= HitObject.EndTime) { if (Progress >= 1) @@ -91,7 +102,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables else { j.Score = OsuScoreResult.Miss; - j.Result = HitResult.Miss; + if (Time.Current >= HitObject.EndTime) + j.Result = HitResult.Miss; } } } @@ -109,6 +121,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables base.UpdatePreemptState(); FadeIn(200); + circleContainer.ScaleTo(1, 400, EasingTypes.OutElastic); background.Delay(TIME_PREEMPT - 100); background.FadeIn(200); @@ -120,12 +133,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables protected override void UpdateState(ArmedState state) { + if (!IsLoaded) return; + base.UpdateState(state); Delay(HitObject.Duration, true); FadeOut(160); - + switch (state) { case ArmedState.Hit: diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 76fd360818..e982f52b44 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; @@ -10,6 +11,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using osu.Framework.Input; using osu.Framework.Logging; +using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; @@ -27,6 +29,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces set { Disc.Colour = value; } } + Color4 completeColour; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + completeColour = colours.YellowLight.Opacity(0.8f); + } + class SpinnerBorder : Container { public SpinnerBorder() @@ -120,6 +130,22 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces } } + bool complete; + public bool Complete + { + get { return complete; } + set + { + if (value == complete) return; + + complete = value; + + Disc.FadeColour(completeColour, 200); + + updateCompleteTick(); + } + } + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { Tracking = true; @@ -145,6 +171,10 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces private float currentRotation; public float RotationAbsolute; + private int completeTick; + + private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 720)); + protected override void Update() { base.Update(); @@ -162,6 +192,14 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces } lastAngle = thisAngle; + if (Complete && updateCompleteTick()) + { + Disc.Flush(flushType: typeof(TransformAlpha)); + Disc.FadeTo(0.75f, 30, EasingTypes.OutExpo); + Disc.Delay(30); + Disc.FadeTo(0.5f, 250, EasingTypes.OutQuint); + } + RotateTo(currentRotation, 100, EasingTypes.OutExpo); } } From 25f65a978b189b6a6b24365756eb8b758ae017cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 02:41:30 +0900 Subject: [PATCH 24/40] Framework bump. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index a766d283f4..659cb25892 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit a766d283f4d628736db784001cc1f11d065cab9d +Subproject commit 659cb2589252f502d2f29c1c1b3878b8f5910d86 From b7fca88b4fb5504af28946ca92b48045310ea46e Mon Sep 17 00:00:00 2001 From: Damnae Date: Wed, 15 Feb 2017 18:55:49 +0100 Subject: [PATCH 25/40] Clearer slider Velocity and TickDistance calculations. --- osu.Game.Modes.Osu/Objects/Slider.cs | 11 +++++---- osu.Game/Beatmaps/Beatmap.cs | 35 ++++++++++++++++------------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index 30ad1c0180..f64d443bcc 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -4,6 +4,7 @@ using OpenTK; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Samples; +using osu.Game.Beatmaps.Timing; using System; using System.Collections.Generic; @@ -53,11 +54,13 @@ namespace osu.Game.Modes.Osu.Objects var baseDifficulty = beatmap.BeatmapInfo.BaseDifficulty; - var startBeatLength = beatmap.BeatLengthAt(StartTime); - var multipliedStartBeatLength = beatmap.BeatLengthAt(StartTime, true); + ControlPoint overridePoint; + ControlPoint timingPoint = beatmap.TimingPointAt(StartTime, out overridePoint); + var velocityAdjustment = overridePoint?.VelocityAdjustment ?? 1; + var baseVelocity = 100 * baseDifficulty.SliderMultiplier; - Velocity = 100 / multipliedStartBeatLength * baseDifficulty.SliderMultiplier; - TickDistance = (100 * baseDifficulty.SliderMultiplier) / baseDifficulty.SliderTickRate / (multipliedStartBeatLength / startBeatLength); + Velocity = baseVelocity / (timingPoint.BeatLength * velocityAdjustment); + TickDistance = baseVelocity / (baseDifficulty.SliderTickRate * velocityAdjustment); } public int RepeatCount = 1; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 0914d1a2ad..d0ce290bad 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -26,26 +26,31 @@ namespace osu.Game.Beatmaps return 60000 / BeatLengthAt(time); } - public double BeatLengthAt(double time, bool applyMultipliers = false) + public double BeatLengthAt(double time) { - int point = 0; - int samplePoint = 0; + ControlPoint overridePoint; + ControlPoint timingPoint = TimingPointAt(time, out overridePoint); + return timingPoint.BeatLength; + } - for (int i = 0; i < ControlPoints.Count; i++) - if (ControlPoints[i].Time <= time) + public ControlPoint TimingPointAt(double time, out ControlPoint overridePoint) + { + overridePoint = null; + + ControlPoint timingPoint = null; + foreach (var controlPoint in ControlPoints) + if (controlPoint.Time <= time) { - if (ControlPoints[i].TimingChange) - point = i; - else - samplePoint = i; + if (controlPoint.TimingChange) + { + timingPoint = controlPoint; + overridePoint = null; + } + else overridePoint = controlPoint; } + else break; - double mult = 1; - - if (applyMultipliers && samplePoint > point) - mult = ControlPoints[samplePoint].VelocityAdjustment; - - return ControlPoints[point].BeatLength * mult; + return timingPoint; } } } From f1535363f41ead41e7173be7f7d57a9a349d1e15 Mon Sep 17 00:00:00 2001 From: Damnae Date: Wed, 15 Feb 2017 19:04:56 +0100 Subject: [PATCH 26/40] Rename SliderTicksRenderer to SliderTicksLayer. --- .../Drawables/{SliderTicksRenderer.cs => SliderTicksLayer.cs} | 0 osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename osu.Game.Modes.Osu/Objects/Drawables/{SliderTicksRenderer.cs => SliderTicksLayer.cs} (100%) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs similarity index 100% rename from osu.Game.Modes.Osu/Objects/Drawables/SliderTicksRenderer.cs rename to osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index d236497ff4..fd6a45c065 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -47,7 +47,7 @@ - + From 6c9fe544b24ecfc1b181a1d4fe583744e81ae970 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 13:20:30 +0900 Subject: [PATCH 27/40] Handle case where TickDistance is zero (don't draw ticks). --- osu.Game.Modes.Osu/Objects/Slider.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index f64d443bcc..72fdd70a70 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -71,6 +71,8 @@ namespace osu.Game.Modes.Osu.Objects { get { + if (TickDistance == 0) yield break; + var length = Curve.Length; var tickDistance = Math.Min(TickDistance, length); var repeatDuration = length / Velocity; From c90f5e247dbc24184ebe0372faabc52e95eb0746 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 13:20:40 +0900 Subject: [PATCH 28/40] Add a TickDistance to TestCaseHitObjects. --- osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 1e3d8df6c6..6f406307c9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -75,6 +75,7 @@ namespace osu.Desktop.VisualTests.Tests Length = 400, Position = new Vector2(-200, 0), Velocity = 1, + TickDistance = 100, })); break; case HitObjectType.Spinner: From 97b782128eba2077e43a780a88e4051b13231c45 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 13:33:59 +0900 Subject: [PATCH 29/40] Adjust tick appear/disappear animations. --- .../Objects/Drawables/DrawableSliderTick.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index cb32410303..cc6890c987 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -81,12 +81,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces FadeOut(); break; case ArmedState.Miss: - FadeTo(0.6f); - Delay(FadeOutTime - sliderTick.StartTime); - FadeOut(); + FadeOut(160); + FadeColour(Color4.Red, 80); break; case ArmedState.Hit: - FadeOut(); + FadeOut(120, EasingTypes.OutQuint); + ScaleTo(Scale * 1.5f, 120, EasingTypes.OutQuint); break; } } From 19eb58e724cfe3231b1521c96aee82d1ecb8d2e7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 13:37:08 +0900 Subject: [PATCH 30/40] Fix namespace. --- .../Objects/Drawables/DrawableSliderTick.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index cc6890c987..9139bce248 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,15 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; using osu.Game.Modes.Objects.Drawables; -using System; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Modes.Osu.Objects.Drawables { public class DrawableSliderTick : DrawableOsuHitObject { From 2640c2ac43dd4e69162f2c0a64c7bf2e002815ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 13:39:01 +0900 Subject: [PATCH 31/40] Add tick sample. --- .../Objects/Drawables/DrawableSliderTick.cs | 20 +++++++++++++++++++ .../Objects/Drawables/DrawableHitObject.cs | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index 9139bce248..b3479c0fae 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -2,9 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; +using osu.Game.Beatmaps.Samples; using osu.Game.Modes.Objects.Drawables; using OpenTK; using OpenTK.Graphics; @@ -48,6 +52,22 @@ namespace osu.Game.Modes.Osu.Objects.Drawables }; } + private AudioSample sample; + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower(); + + sample = audio.Sample.Get($@"Gameplay/{sampleSet}-slidertick"); + } + + protected override void PlaySample() + { + sample?.Play(); + } + + protected override void CheckJudgement(bool userTriggered) { if (Judgement.TimeOffset >= 0) diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 4df49ca01f..4c707c5e62 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -66,7 +66,7 @@ namespace osu.Game.Modes.Objects.Drawables sample = audio.Sample.Get($@"Gameplay/{sampleSet}-hit{hitType}"); } - protected void PlaySample() + protected virtual void PlaySample() { sample?.Play(); } From 8bf3902cbd0b2a7ffada2df90a3df4afff6cac5a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 17:02:36 +0900 Subject: [PATCH 32/40] Add the concept of nested DrawableHitObjects. - Applies to Slider Ticks and start circle. repeat/endpoints still need addressing. - Removed SliderTicksLayer abstraction for now. --- .../Tests/TestCaseHitObjects.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 + .../Objects/Drawables/DrawableSlider.cs | 36 +++++-- .../Objects/Drawables/DrawableSliderTick.cs | 10 +- .../Objects/Drawables/SliderTicksLayer.cs | 96 ------------------- osu.Game.Modes.Osu/Objects/Slider.cs | 2 +- osu.Game.Modes.Osu/OsuScoreProcessor.cs | 4 + osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj | 1 - .../Objects/Drawables/DrawableHitObject.cs | 22 ++++- 9 files changed, 60 insertions(+), 115 deletions(-) delete mode 100644 osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 6f406307c9..f82ea1c98c 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -37,7 +37,7 @@ namespace osu.Desktop.VisualTests.Tests playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; }; } - HitObjectType mode = HitObjectType.Spinner; + HitObjectType mode = HitObjectType.Slider; BindableNumber playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 }; private Container playfieldContainer; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs index ef153848d4..d6907474f3 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -73,5 +73,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Hit100, [Description(@"300")] Hit300, + [Description(@"10")] + SliderTick } } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs index 01ddd7a790..745c696fee 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs @@ -7,6 +7,7 @@ using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.Osu.Objects.Drawables.Pieces; using System.Collections.Generic; using System.Linq; +using osu.Framework.Graphics.Containers; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -18,11 +19,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables private List components = new List(); + private Container ticks; + SliderBody body; SliderBall ball; SliderBouncer bouncer1, bouncer2; - SliderTicksRenderer ticks; public DrawableSlider(Slider s) : base(s) { @@ -35,13 +37,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Position = s.StackedPosition, PathWidth = s.Scale * 64, }, - ticks = new SliderTicksRenderer - { - Position = s.StackedPosition, - StartTime = s.StartTime, - RepeatDuration = s.Curve.Length / s.Velocity, - Ticks = s.Ticks, - }, + ticks = new Container(), bouncer1 = new SliderBouncer(s, false) { Position = s.Curve.PositionAt(1), @@ -72,6 +68,26 @@ namespace osu.Game.Modes.Osu.Objects.Drawables components.Add(ball); components.Add(bouncer1); components.Add(bouncer2); + + AddNested(initialCircle); + + var repeatDuration = s.Curve.Length / s.Velocity; + foreach (var tick in s.Ticks) + { + var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration; + var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? TIME_FADEIN : TIME_FADEIN / 2); + var fadeOutTime = repeatStartTime + repeatDuration; + + var drawableTick = new DrawableSliderTick(tick) + { + FadeInTime = fadeInTime, + FadeOutTime = fadeOutTime, + Position = tick.Position, + }; + + ticks.Add(drawableTick); + AddNested(drawableTick); + } } // Since the DrawableSlider itself is just a container without a size we need to @@ -105,8 +121,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables if (initialCircle.Judgement?.Result != HitResult.Hit) initialCircle.Position = slider.Curve.PositionAt(progress); - components.ForEach(c => c.UpdateProgress(progress, repeat)); - ticks.ShouldHit = ball.Tracking; + foreach (var c in components) c.UpdateProgress(progress, repeat); + foreach (var t in ticks.Children) t.Tracking = ball.Tracking; } protected override void CheckJudgement(bool userTriggered) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index b3479c0fae..c1c17f1c53 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -22,7 +22,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables public double FadeInTime; public double FadeOutTime; - public bool ShouldHit; + public bool Tracking; public override bool RemoveWhenNotAlive => false; @@ -35,7 +35,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Masking = true; CornerRadius = Size.X / 2; - Anchor = Anchor.Centre; Origin = Anchor.Centre; BorderThickness = 2; @@ -70,8 +69,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables protected override void CheckJudgement(bool userTriggered) { + var j = Judgement as OsuJudgementInfo; + if (Judgement.TimeOffset >= 0) - Judgement.Result = ShouldHit ? HitResult.Hit : HitResult.Miss; + { + j.Result = Tracking ? HitResult.Hit : HitResult.Miss; + j.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss; + } } protected override void UpdatePreemptState() diff --git a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs b/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs deleted file mode 100644 index 03ab28e495..0000000000 --- a/osu.Game.Modes.Osu/Objects/Drawables/SliderTicksLayer.cs +++ /dev/null @@ -1,96 +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.Caching; -using osu.Framework.Graphics.Containers; -using System.Collections.Generic; - -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces -{ - public class SliderTicksRenderer : Container - { - private Cached drawableTicks = new Cached(); - - private double startTime; - public double StartTime - { - get { return startTime; } - set - { - startTime = value; - drawableTicks.Invalidate(); - } - } - - private double repeatDuration; - public double RepeatDuration - { - get { return repeatDuration; } - set - { - repeatDuration = value; - drawableTicks.Invalidate(); - } - } - - private IEnumerable ticks; - public IEnumerable Ticks - { - get { return ticks; } - set - { - ticks = value; - drawableTicks.Invalidate(); - } - } - - public bool ShouldHit - { - set - { - foreach (var tick in Children) - tick.ShouldHit = value; - } - } - - protected override void Update() - { - base.Update(); - updateDrawableTicks(); - } - - [BackgroundDependencyLoader] - private void load() - { - updateDrawableTicks(); - } - - private void updateDrawableTicks() - { - if (drawableTicks.EnsureValid()) - return; - - drawableTicks.Refresh(delegate - { - Clear(); - if (ticks == null || repeatDuration == 0) - return; - - foreach (var tick in ticks) - { - var repeatStartTime = startTime + tick.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? DrawableOsuHitObject.TIME_FADEIN : DrawableOsuHitObject.TIME_FADEIN / 2); - var fadeOutTime = repeatStartTime + repeatDuration; - - Add(new DrawableSliderTick(tick) - { - FadeInTime = fadeInTime, - FadeOutTime = fadeOutTime, - Position = tick.Position, - }); - } - }); - } - } -} \ No newline at end of file diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Modes.Osu/Objects/Slider.cs index 72fdd70a70..c3d8190240 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Modes.Osu/Objects/Slider.cs @@ -96,7 +96,7 @@ namespace osu.Game.Modes.Osu.Objects { RepeatIndex = repeat, StartTime = repeatStartTime + timeProgress * repeatDuration, - Position = Curve.PositionAt(distanceProgress) - StackedPosition, + Position = Curve.PositionAt(distanceProgress), StackHeight = StackHeight, Scale = Scale, Colour = Colour, diff --git a/osu.Game.Modes.Osu/OsuScoreProcessor.cs b/osu.Game.Modes.Osu/OsuScoreProcessor.cs index 8a9f7d6b2e..224a669746 100644 --- a/osu.Game.Modes.Osu/OsuScoreProcessor.cs +++ b/osu.Game.Modes.Osu/OsuScoreProcessor.cs @@ -53,6 +53,10 @@ namespace osu.Game.Modes.Osu score += 300; maxScore += 300; break; + case OsuScoreResult.SliderTick: + score += 10; + maxScore += 10; + break; } } diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj index f269921cac..1b1ded3d61 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj @@ -47,7 +47,6 @@ - diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index 4c707c5e62..94369d51aa 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using osu.Framework; @@ -23,8 +24,6 @@ namespace osu.Game.Modes.Objects.Drawables public bool Interactive = true; - public Container ChildObjects; - public JudgementInfo Judgement; public abstract JudgementInfo CreateJudgementInfo(); @@ -85,6 +84,19 @@ namespace osu.Game.Modes.Objects.Drawables Expire(true); } + private List nestedHitObjects; + + protected IEnumerable NestedHitObjects => nestedHitObjects; + + protected void AddNested(DrawableHitObject h) + { + if (nestedHitObjects == null) + nestedHitObjects = new List(); + + h.OnJudgement += (d, j) => { OnJudgement?.Invoke(d, j); } ; + nestedHitObjects.Add(h); + } + /// /// Process a hit of this hitobject. Carries out judgement. /// @@ -119,7 +131,11 @@ namespace osu.Game.Modes.Objects.Drawables protected virtual void CheckJudgement(bool userTriggered) { - //todo: consider making abstract. + if (NestedHitObjects != null) + { + foreach (var d in NestedHitObjects) + d.CheckJudgement(userTriggered); + } } protected override void UpdateAfterChildren() From b55d85a5c51b9ef25b996e4638c48e7b229c7e40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 17:33:13 +0900 Subject: [PATCH 33/40] Add MaxScore to correctly account for the maximum attainable score of DrawableHitObjects. --- .../Objects/Drawables/DrawableHitCircle.cs | 10 +++--- .../Objects/Drawables/DrawableOsuHitObject.cs | 33 +++++++++++++++++-- .../Objects/Drawables/DrawableSliderTick.cs | 2 ++ osu.Game.Modes.Osu/OsuScoreProcessor.cs | 24 ++------------ 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 208bf15328..0e085d63b8 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -84,18 +84,18 @@ namespace osu.Game.Modes.Osu.Objects.Drawables double hitOffset = Math.Abs(Judgement.TimeOffset); + OsuJudgementInfo osuJudgement = Judgement as OsuJudgementInfo; + if (hitOffset < hit50) { Judgement.Result = HitResult.Hit; - OsuJudgementInfo osuInfo = Judgement as OsuJudgementInfo; - if (hitOffset < hit300) - osuInfo.Score = OsuScoreResult.Hit300; + osuJudgement.Score = OsuScoreResult.Hit300; else if (hitOffset < hit100) - osuInfo.Score = OsuScoreResult.Hit100; + osuJudgement.Score = OsuScoreResult.Hit100; else if (hitOffset < hit50) - osuInfo.Score = OsuScoreResult.Hit50; + osuJudgement.Score = OsuScoreResult.Hit50; } else Judgement.Result = HitResult.Miss; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs index d6907474f3..c7cc7cfdd7 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; -using osu.Framework.Graphics; namespace osu.Game.Modes.Osu.Objects.Drawables { @@ -19,7 +18,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables { } - public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo(); + public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.Hit300 }; protected override void UpdateState(ArmedState state) { @@ -49,7 +48,37 @@ namespace osu.Game.Modes.Osu.Objects.Drawables public class OsuJudgementInfo : PositionalJudgementInfo { + /// + /// The score the user achieved. + /// public OsuScoreResult Score; + + /// + /// The score which would be achievable on a perfect hit. + /// + public OsuScoreResult MaxScore = OsuScoreResult.Hit300; + + public int ScoreValue => scoreToInt(Score); + + public int MaxScoreValue => scoreToInt(MaxScore); + + private int scoreToInt(OsuScoreResult result) + { + switch (result) + { + default: + return 0; + case OsuScoreResult.Hit50: + return 50; + case OsuScoreResult.Hit100: + return 100; + case OsuScoreResult.Hit300: + return 300; + case OsuScoreResult.SliderTick: + return 10; + } + } + public ComboResult Combo; } diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs index c1c17f1c53..7380871583 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -26,6 +26,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables public override bool RemoveWhenNotAlive => false; + public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo { MaxScore = OsuScoreResult.SliderTick }; + public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { this.sliderTick = sliderTick; diff --git a/osu.Game.Modes.Osu/OsuScoreProcessor.cs b/osu.Game.Modes.Osu/OsuScoreProcessor.cs index 224a669746..9493259558 100644 --- a/osu.Game.Modes.Osu/OsuScoreProcessor.cs +++ b/osu.Game.Modes.Osu/OsuScoreProcessor.cs @@ -36,28 +36,8 @@ namespace osu.Game.Modes.Osu foreach (OsuJudgementInfo j in Judgements) { - switch (j.Score) - { - case OsuScoreResult.Miss: - maxScore += 300; - break; - case OsuScoreResult.Hit50: - score += 50; - maxScore += 300; - break; - case OsuScoreResult.Hit100: - score += 100; - maxScore += 300; - break; - case OsuScoreResult.Hit300: - score += 300; - maxScore += 300; - break; - case OsuScoreResult.SliderTick: - score += 10; - maxScore += 10; - break; - } + score += j.ScoreValue; + maxScore += j.MaxScoreValue; } TotalScore.Value = score; From 3068fa1a620c04e0bde7d464ca225a4eb75c8d01 Mon Sep 17 00:00:00 2001 From: Nabile Rahmani Date: Thu, 16 Feb 2017 11:30:31 +0100 Subject: [PATCH 34/40] Namespace does not correspond to file location. --- osu-framework | 2 +- osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu-framework b/osu-framework index a766d283f4..7a0fb64b3d 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit a766d283f4d628736db784001cc1f11d065cab9d +Subproject commit 7a0fb64b3dc46651113c1b15bfec8e941e97a146 diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs index 173bf2c060..7f7d558294 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -8,7 +8,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.OpenGL.Textures; -using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Textures; using osu.Game.Configuration; using OpenTK; From 1cdd2a60723c140499d0634d9bf7f6e8e55d7692 Mon Sep 17 00:00:00 2001 From: Nabile Rahmani Date: Thu, 16 Feb 2017 13:09:42 +0100 Subject: [PATCH 35/40] Updated submodule. --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index 7a0fb64b3d..4a58484532 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 7a0fb64b3dc46651113c1b15bfec8e941e97a146 +Subproject commit 4a5848453240326ba08b09a33a2467af8c174b6a From 04346dbb92fe2138656f3f072c8341342febbe6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 22:23:03 +0900 Subject: [PATCH 36/40] Make osu! logo at song select correctly handle mouse focus. --- osu.Game/Screens/Menu/OsuLogo.cs | 3 ++- osu.Game/Screens/Select/Footer.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 225b15c57e..3a1a37fdcc 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -195,11 +195,12 @@ namespace osu.Game.Screens.Menu protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - logoBounceContainer.ScaleTo(1f, 500, EasingTypes.OutElastic); return true; } + protected override bool OnDragStart(InputState state) => true; + protected override bool OnClick(InputState state) { if (!Interactive) return false; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 55fb36f144..df926c0778 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.Select private const float padding = 80; + public override bool Contains(Vector2 screenSpacePos) => true; + public Action OnBack; public Action OnStart; From 9a2beb5979f6ac1a6e5b62b92e1d967a689280e2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 22:43:49 +0900 Subject: [PATCH 37/40] Update Key Counter font. --- osu.Game/Screens/Play/KeyCounter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index cadc06f561..00dd2393d1 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -89,6 +89,8 @@ namespace osu.Game.Screens.Play new OsuSpriteText { Text = Name, + Font = @"Venera", + TextSize = 12, Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, From ca6946c7a29c44caab61e4755231f3971ac5c6bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 22:44:21 +0900 Subject: [PATCH 38/40] Update Health display design. --- osu.Game/Modes/UI/HealthDisplay.cs | 45 +++++++++++++++++++++++------- osu.Game/Modes/UI/ScoreOverlay.cs | 4 +-- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/osu.Game/Modes/UI/HealthDisplay.cs b/osu.Game/Modes/UI/HealthDisplay.cs index 1771edb1d8..27734cea15 100644 --- a/osu.Game/Modes/UI/HealthDisplay.cs +++ b/osu.Game/Modes/UI/HealthDisplay.cs @@ -1,23 +1,29 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE -using OpenTK; -using OpenTK.Graphics; +using System; +using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Transformations; -using System; +using osu.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Modes.UI { public class HealthDisplay : Container { private Box background; - private Box fill; + private Container fill; - public BindableDouble Current = new BindableDouble() { MinValue = 0, MaxValue = 1 }; + public BindableDouble Current = new BindableDouble() + { + MinValue = 0, + MaxValue = 1 + }; public HealthDisplay() { @@ -26,19 +32,38 @@ namespace osu.Game.Modes.UI background = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, + Colour = Color4.Black, }, - fill = new Box + fill = new Container { RelativeSizeAxes = Axes.Both, - Colour = Color4.White, Scale = new Vector2(0, 1), - }, + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + } + } + }, }; Current.ValueChanged += current_ValueChanged; } + [BackgroundDependencyLoader] + private void laod(OsuColour colours) + { + fill.Colour = colours.BlueLighter; + fill.EdgeEffect = new EdgeEffect + { + Colour = colours.BlueDarker.Opacity(0.6f), + Radius = 8, + Type= EdgeEffectType.Glow + }; + } + private void current_ValueChanged(object sender, EventArgs e) { fill.ScaleTo(new Vector2((float)Current, 1), 200, EasingTypes.OutQuint); diff --git a/osu.Game/Modes/UI/ScoreOverlay.cs b/osu.Game/Modes/UI/ScoreOverlay.cs index 7268b5a3b5..7be6af5c6a 100644 --- a/osu.Game/Modes/UI/ScoreOverlay.cs +++ b/osu.Game/Modes/UI/ScoreOverlay.cs @@ -27,9 +27,9 @@ namespace osu.Game.Modes.UI protected abstract ScoreCounter CreateScoreCounter(); protected virtual HealthDisplay CreateHealthDisplay() => new HealthDisplay { - Size = new Vector2(0.5f, 20), + Size = new Vector2(1, 5), RelativeSizeAxes = Axes.X, - Padding = new MarginPadding(5) + Margin = new MarginPadding { Top = 20 } }; public virtual void OnHit(HitObject h) From 53e40804ab70c712f56936823ddfbcedd474ae3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 22:44:41 +0900 Subject: [PATCH 39/40] Move other score components to centre alignment (and switch font). --- osu.Game.Modes.Osu/UI/OsuScoreOverlay.cs | 14 ++++++++------ osu.Game/Graphics/UserInterface/RollingCounter.cs | 5 ++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/osu.Game.Modes.Osu/UI/OsuScoreOverlay.cs b/osu.Game.Modes.Osu/UI/OsuScoreOverlay.cs index ba996be326..eb5aaa97c9 100644 --- a/osu.Game.Modes.Osu/UI/OsuScoreOverlay.cs +++ b/osu.Game.Modes.Osu/UI/OsuScoreOverlay.cs @@ -15,17 +15,19 @@ namespace osu.Game.Modes.Osu.UI { protected override ScoreCounter CreateScoreCounter() => new ScoreCounter() { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - TextSize = 60, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 40, + Position = new Vector2(0, 30), Margin = new MarginPadding { Right = 5 }, }; protected override PercentageCounter CreateAccuracyCounter() => new PercentageCounter() { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Position = new Vector2(0, 55), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Position = new Vector2(0, 65), + TextSize = 20, Margin = new MarginPadding { Right = 5 }, }; diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index fd1022e546..e0a5d8ed2d 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -107,7 +107,10 @@ namespace osu.Game.Graphics.UserInterface { Children = new Drawable[] { - DisplayedCountSpriteText = new OsuSpriteText(), + DisplayedCountSpriteText = new OsuSpriteText() + { + Font = @"Venera" + }, }; TextSize = 40; From aaed7141609a5dbfbf448c371e7f8dc1717a7931 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Feb 2017 22:48:47 +0900 Subject: [PATCH 40/40] Adjust Explode alpha slightly. --- osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 08c7423c23..97228f610f 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -25,7 +25,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces { BlendingMode = BlendingMode.Additive, RelativeSizeAxes = Axes.Both, - Alpha = 0.1f, + Alpha = 0.2f, } }; }