diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index ba1b3b4f37..c1861b0874 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -13,6 +13,7 @@ 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.Objects; using OpenTK.Graphics; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs b/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs index 0d06ce29a7..dd61fdd453 100644 --- a/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs @@ -12,8 +12,8 @@ namespace osu.Game.Modes.Catch.UI { protected override HitObjectConverter Converter => new CatchConverter(); - protected override Playfield CreatePlayfield() => new CatchPlayfield(); + protected override Playfield CreatePlayfield() => new CatchPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null;// new DrawableFruit(h); + protected override DrawableHitObject GetVisualRepresentation(CatchBaseHit h) => null;// new DrawableFruit(h); } } diff --git a/osu.Game.Modes.Catch/UI/CatchPlayfield.cs b/osu.Game.Modes.Catch/UI/CatchPlayfield.cs index cf69ab4fe2..ff57d72cb2 100644 --- a/osu.Game.Modes.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Modes.Catch/UI/CatchPlayfield.cs @@ -3,12 +3,14 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Modes.Catch.Objects; +using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.UI; using OpenTK; namespace osu.Game.Modes.Catch.UI { - public class CatchPlayfield : Playfield + public class CatchPlayfield : Playfield { public CatchPlayfield() { diff --git a/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs index 59c79f0d03..31bc4fffe4 100644 --- a/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs @@ -19,9 +19,9 @@ namespace osu.Game.Modes.Mania.UI protected override HitObjectConverter Converter => new ManiaConverter(columns); - protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns); + protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns); - protected override DrawableHitObject GetVisualRepresentation(ManiaBaseHit h) + protected override DrawableHitObject GetVisualRepresentation(ManiaBaseHit h) { return null; //return new DrawableNote(h) diff --git a/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs b/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs index 2772b09e16..3a3abdaefd 100644 --- a/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs @@ -3,13 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Game.Modes.Mania.Objects; +using osu.Game.Modes.Objects.Drawables; using osu.Game.Modes.UI; using OpenTK; using OpenTK.Graphics; namespace osu.Game.Modes.Mania.UI { - public class ManiaPlayfield : Playfield + public class ManiaPlayfield : Playfield { private readonly int columns; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs index 15614511f1..f88634f506 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -85,13 +85,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables if (hitOffset < OsuHitObject.HIT_WINDOW_50) { Judgement.Result = HitResult.Hit; - - if (hitOffset < OsuHitObject.HIT_WINDOW_300) - osuJudgement.Score = OsuScoreResult.Hit300; - else if (hitOffset < OsuHitObject.HIT_WINDOW_100) - osuJudgement.Score = OsuScoreResult.Hit100; - else if (hitOffset < OsuHitObject.HIT_WINDOW_50) - osuJudgement.Score = OsuScoreResult.Hit50; + osuJudgement.Score = HitObject.ScoreResultForOffset(hitOffset); } 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 c7cc7cfdd7..4aa7b80278 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -7,7 +7,7 @@ using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes.Osu.Objects.Drawables { - public class DrawableOsuHitObject : DrawableHitObject + public class DrawableOsuHitObject : DrawableHitObject { public const float TIME_PREEMPT = 600; public const float TIME_FADEIN = 400; diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs b/osu.Game.Modes.Osu/Objects/OsuHitObject.cs index aa12a83b4b..926182f0a4 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Modes.Osu/Objects/OsuHitObject.cs @@ -48,6 +48,17 @@ namespace osu.Game.Modes.Osu.Objects } } + public OsuScoreResult ScoreResultForOffset(double offset) + { + if (offset < HitWindowFor(OsuScoreResult.Hit300)) + return OsuScoreResult.Hit300; + if (offset < HitWindowFor(OsuScoreResult.Hit100)) + return OsuScoreResult.Hit100; + if (offset < HitWindowFor(OsuScoreResult.Hit50)) + return OsuScoreResult.Hit50; + return OsuScoreResult.Miss; + } + public override void SetDefaultsFromBeatmap(Beatmap beatmap) { base.SetDefaultsFromBeatmap(beatmap); diff --git a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs b/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs index fa222aafd7..0f232cee9b 100644 --- a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs @@ -13,9 +13,9 @@ namespace osu.Game.Modes.Osu.UI { protected override HitObjectConverter Converter => new OsuHitObjectConverter(); - protected override Playfield CreatePlayfield() => new OsuPlayfield(); + protected override Playfield CreatePlayfield() => new OsuPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) + protected override DrawableHitObject GetVisualRepresentation(OsuHitObject h) { if (h is HitCircle) return new DrawableHitCircle(h as HitCircle); diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs index 7d439a96ef..2479b15dce 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Modes.Osu/UI/OsuPlayfield.cs @@ -11,10 +11,11 @@ using osu.Game.Modes.Osu.Objects.Drawables.Connections; using osu.Game.Modes.UI; using System.Linq; using osu.Game.Graphics.Cursor; +using osu.Game.Modes.Objects; namespace osu.Game.Modes.Osu.UI { - public class OsuPlayfield : Playfield + public class OsuPlayfield : Playfield { private Container approachCircles; private Container judgementLayer; @@ -59,7 +60,7 @@ namespace osu.Game.Modes.Osu.UI }); } - public override void Add(DrawableHitObject h) + public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; IDrawableHitObjectWithProxiedApproach c = h as IDrawableHitObjectWithProxiedApproach; @@ -80,9 +81,9 @@ namespace osu.Game.Modes.Osu.UI .OrderBy(h => h.StartTime); } - private void judgement(DrawableHitObject h, JudgementInfo j) + private void judgement(DrawableHitObject h, JudgementInfo j) { - HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, (OsuHitObject)h.HitObject); + HitExplosion explosion = new HitExplosion((OsuJudgementInfo)j, h.HitObject); judgementLayer.Add(explosion); } diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs index 0e2b6cdc83..1b9bb682f1 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs @@ -12,8 +12,8 @@ namespace osu.Game.Modes.Taiko.UI { protected override HitObjectConverter Converter => new TaikoConverter(); - protected override Playfield CreatePlayfield() => new TaikoPlayfield(); + protected override Playfield CreatePlayfield() => new TaikoPlayfield(); - protected override DrawableHitObject GetVisualRepresentation(TaikoBaseHit h) => null;// new DrawableTaikoHit(h); + protected override DrawableHitObject GetVisualRepresentation(TaikoBaseHit h) => null;// new DrawableTaikoHit(h); } } diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs index e8aa28e5b3..9c57ae8ad5 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs @@ -5,13 +5,15 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Game.Modes.Objects.Drawables; +using osu.Game.Modes.Taiko.Objects; using osu.Game.Modes.UI; using OpenTK; using OpenTK.Graphics; namespace osu.Game.Modes.Taiko.UI { - public class TaikoPlayfield : Playfield + public class TaikoPlayfield : Playfield { public TaikoPlayfield() { diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs index ca1967904a..2d78f8a04a 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs @@ -16,8 +16,6 @@ namespace osu.Game.Modes.Objects.Drawables { public abstract class DrawableHitObject : Container, IStateful { - public event Action OnJudgement; - public override bool HandleInput => Interactive; public bool Interactive = true; @@ -26,12 +24,7 @@ namespace osu.Game.Modes.Objects.Drawables public abstract JudgementInfo CreateJudgementInfo(); - public HitObject HitObject; - - public DrawableHitObject(HitObject hitObject) - { - HitObject = hitObject; - } + protected abstract void UpdateState(ArmedState state); private ArmedState state; public ArmedState State @@ -52,20 +45,11 @@ namespace osu.Game.Modes.Objects.Drawables } } - SampleChannel sample; - - [BackgroundDependencyLoader] - private void load(AudioManager audio) - { - string hitType = ((HitObject.Sample?.Type ?? SampleType.None) == SampleType.None ? SampleType.Normal : HitObject.Sample.Type).ToString().ToLower(); - string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower(); - - sample = audio.Sample.Get($@"Gameplay/{sampleSet}-hit{hitType}"); - } + protected SampleChannel Sample; protected virtual void PlaySample() { - sample?.Play(); + Sample?.Play(); } protected override void LoadComplete() @@ -81,18 +65,18 @@ namespace osu.Game.Modes.Objects.Drawables Expire(true); } + } - private List nestedHitObjects; + public abstract class DrawableHitObject : DrawableHitObject + where HitObjectType : HitObject + { + public event Action, JudgementInfo> OnJudgement; - protected IEnumerable NestedHitObjects => nestedHitObjects; + public HitObjectType HitObject; - protected void AddNested(DrawableHitObject h) + public DrawableHitObject(HitObjectType hitObject) { - if (nestedHitObjects == null) - nestedHitObjects = new List(); - - h.OnJudgement += (d, j) => { OnJudgement?.Invoke(d, j); } ; - nestedHitObjects.Add(h); + HitObject = hitObject; } /// @@ -143,7 +127,27 @@ namespace osu.Game.Modes.Objects.Drawables UpdateJudgement(false); } - protected abstract void UpdateState(ArmedState state); + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + string hitType = ((HitObject.Sample?.Type ?? SampleType.None) == SampleType.None ? SampleType.Normal : HitObject.Sample.Type).ToString().ToLower(); + string sampleSet = (HitObject.Sample?.Set ?? SampleSet.Normal).ToString().ToLower(); + + Sample = audio.Sample.Get($@"Gameplay/{sampleSet}-hit{hitType}"); + } + + 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); + } } public enum ArmedState diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Modes/UI/HitRenderer.cs index 356c9b9276..eac53b811b 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Modes/UI/HitRenderer.cs @@ -20,7 +20,7 @@ namespace osu.Game.Modes.UI public event Action OnAllJudged; - public InputManager InputManager; + public abstract bool AllObjectsJudged { get; } protected void TriggerOnJudgement(JudgementInfo j) { @@ -28,18 +28,20 @@ namespace osu.Game.Modes.UI if (AllObjectsJudged) OnAllJudged?.Invoke(); } - - protected Playfield Playfield; - - public bool AllObjectsJudged => Playfield.HitObjects.Children.First()?.Judgement.Result != null; //reverse depth sort means First() instead of Last(). - - public IEnumerable DrawableObjects => Playfield.HitObjects.Children; } - public abstract class HitRenderer : HitRenderer - where T : HitObject + public abstract class HitRenderer : HitRenderer + where TObject : HitObject { - private List objects; + private List objects; + + public InputManager InputManager; + + protected Playfield Playfield; + + public override bool AllObjectsJudged => Playfield.HitObjects.Children.First()?.Judgement.Result != null; //reverse depth sort means First() instead of Last(). + + public IEnumerable DrawableObjects => Playfield.HitObjects.Children; public Beatmap Beatmap { @@ -51,11 +53,11 @@ namespace osu.Game.Modes.UI } } - protected abstract Playfield CreatePlayfield(); + protected abstract Playfield CreatePlayfield(); - protected abstract HitObjectConverter Converter { get; } + protected abstract HitObjectConverter Converter { get; } - protected virtual List Convert(Beatmap beatmap) => Converter.Convert(beatmap); + protected virtual List Convert(Beatmap beatmap) => Converter.Convert(beatmap); public HitRenderer() { @@ -76,9 +78,9 @@ namespace osu.Game.Modes.UI private void loadObjects() { if (objects == null) return; - foreach (T h in objects) + foreach (TObject h in objects) { - var drawableObject = GetVisualRepresentation(h); + DrawableHitObject drawableObject = GetVisualRepresentation(h); if (drawableObject == null) continue; @@ -89,8 +91,8 @@ namespace osu.Game.Modes.UI Playfield.PostProcess(); } - private void onJudgement(DrawableHitObject o, JudgementInfo j) => TriggerOnJudgement(j); + private void onJudgement(DrawableHitObject o, JudgementInfo j) => TriggerOnJudgement(j); - protected abstract DrawableHitObject GetVisualRepresentation(T h); + protected abstract DrawableHitObject GetVisualRepresentation(TObject h); } } diff --git a/osu.Game/Modes/UI/Playfield.cs b/osu.Game/Modes/UI/Playfield.cs index 6a8c311261..424b4c3c68 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Modes/UI/Playfield.cs @@ -6,16 +6,25 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Game.Modes.Objects; using osu.Game.Modes.Objects.Drawables; namespace osu.Game.Modes.UI { - public abstract class Playfield : Container + public abstract class Playfield : Container + where T : HitObject { - public HitObjectContainer HitObjects; - private Container scaledContent; + public HitObjectContainer> HitObjects; - public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + + public class HitObjectContainer : Container + where U : Drawable + { + public override bool Contains(Vector2 screenSpacePos) => true; + } + + private Container scaledContent; public override bool Contains(Vector2 screenSpacePos) => true; @@ -37,7 +46,7 @@ namespace osu.Game.Modes.UI } }); - Add(HitObjects = new HitObjectContainer + Add(HitObjects = new HitObjectContainer> { RelativeSizeAxes = Axes.Both, }); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 4cd919874e..644ed531a9 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -4,12 +4,10 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Track; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Timing; using osu.Game.Database; using osu.Game.Modes; -using osu.Game.Modes.Objects.Drawables; using osu.Game.Screens.Backgrounds; using OpenTK; using osu.Framework.Screens; @@ -18,24 +16,18 @@ using osu.Game.Screens.Ranking; using osu.Game.Configuration; using osu.Framework.Configuration; using System; -using System.Collections.Generic; using System.Linq; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Framework.Logging; -using osu.Framework.Input; -using osu.Framework.Input.Handlers; -using osu.Game.Graphics.Cursor; using osu.Game.Input.Handlers; namespace osu.Game.Screens.Play { public class Player : OsuScreen { - public bool Autoplay; - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); internal override bool ShowOverlays => false; @@ -148,9 +140,6 @@ namespace osu.Game.Screens.Play //bind ScoreProcessor to ourselves (for a fail situation) scoreProcessor.Failed += onFail; - if (Autoplay) - hitRenderer.Schedule(() => hitRenderer.DrawableObjects.ForEach(h => h.State = ArmedState.Hit)); - Children = new Drawable[] { new Container