From d504a44dfb08d78024bbd512695270198d80c3cd Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Sun, 20 May 2018 13:22:42 +0300 Subject: [PATCH 001/277] Implement mask layering (incomplete) --- .../Layers/Selection/Overlays/HoldNoteMask.cs | 50 ++++++++++++++++ .../Overlays/ManiaHitObjectColumnMaskLayer.cs | 29 ++++++++++ .../Overlays/ManiaHitObjectMaskLayer.cs | 28 +++++++++ .../Overlays/ManiaHitObjectStageMaskLayer.cs | 31 ++++++++++ .../Layers/Selection/Overlays/NoteMask.cs | 35 +++++++++++ .../Edit/ManiaHitObjectComposer.cs | 58 +++++++++++++++++++ .../Objects/Drawables/DrawableHoldNote.cs | 26 ++++----- .../Objects/ManiaHitObject.cs | 34 ++++++++++- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 35 +++++++---- .../osu.Game.Rulesets.Mania.csproj | 3 + osu.Game/Rulesets/Edit/HitObjectComposer.cs | 24 +++++--- osu.Game/Rulesets/Edit/HitObjectMask.cs | 22 ++++++- .../Edit/Tools/HitObjectCompositionTool.cs | 16 ++++- .../Rulesets/Edit/Tools/ICompositionTool.cs | 6 ++ .../Rulesets/Edit/Types/IHasEditableColumn.cs | 12 ++++ .../Rulesets/Edit/Types/IHasEditableLayer.cs | 12 ++++ .../Rulesets}/Objects/Types/IHasColumn.cs | 2 +- .../Compose/Layers/HitObjectMaskLayer.cs | 24 +++++--- .../Screens/Compose/Layers/MaskContainer.cs | 16 +++++ .../Screens/Compose/Layers/MaskSelection.cs | 10 ++++ 20 files changed, 426 insertions(+), 47 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs create mode 100644 osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs create mode 100644 osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs rename {osu.Game.Rulesets.Mania => osu.Game/Rulesets}/Objects/Types/IHasColumn.cs (90%) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs new file mode 100644 index 0000000000..3106fedb30 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 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.Primitives; +using osu.Game.Graphics; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays +{ + public class HoldNoteMask : HitObjectMask + { + private readonly BodyPiece body; + private readonly DrawableHoldNote holdNote; + + public HoldNoteMask(DrawableHoldNote hold) + : base(hold) + { + holdNote = hold; + + Position = hold.Position; + + var holdObject = hold.HitObject; + + InternalChildren = new Drawable[] + { + new NoteMask(hold.Head), + new NoteMask(hold.Tail), + body = new BodyPiece() + { + AccentColour = Color4.Transparent + }, + }; + + holdObject.ColumnChanged += _ => Position = hold.Position; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + body.BorderColour = colours.Yellow; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs new file mode 100644 index 0000000000..1f8d391c99 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Screens.Edit.Screens.Compose.Layers; + +namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays +{ + public class ManiaHitObjectColumnMaskLayer : HitObjectMaskLayer + { + public readonly Column Column; + + public ManiaHitObjectColumnMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, Column column) + : base(playfield, composer) + { + Column = column; + } + + public void CreateMasks() => AddMasks(); + + protected override void AddMasks() + { + foreach (var obj in Column.HitObjects.Objects) + AddMask(obj); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs new file mode 100644 index 0000000000..012fc495b5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Screens.Edit.Screens.Compose.Layers; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays +{ + public class ManiaHitObjectMaskLayer : HitObjectMaskLayer + { + public readonly List Stages; + + public ManiaHitObjectMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer) + : base(playfield, composer) + { + Stages = new List(); + foreach (var s in ((ManiaEditPlayfield)Playfield).Stages) + Stages.Add(new ManiaHitObjectStageMaskLayer((ManiaEditPlayfield)Playfield, Composer, s)); + } + + protected override void AddMasks() + { + foreach (var s in Stages) + s.CreateMasks(); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs new file mode 100644 index 0000000000..ae800019c5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Screens.Edit.Screens.Compose.Layers; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays +{ + public class ManiaHitObjectStageMaskLayer : HitObjectMaskLayer + { + public readonly List Columns; + + public ManiaHitObjectStageMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, ManiaStage s) + : base(playfield, composer) + { + Columns = new List(); + foreach (var c in s.Columns) + Columns.Add(new ManiaHitObjectColumnMaskLayer((ManiaEditPlayfield)Playfield, Composer, c)); + } + + public void CreateMasks() => AddMasks(); + + protected override void AddMasks() + { + foreach (var c in Columns) + c.CreateMasks(); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs new file mode 100644 index 0000000000..8228adf35f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; + +namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays +{ + public class NoteMask : HitObjectMask + { + public NoteMask(DrawableNote note) + : base(note) + { + Origin = Anchor.Centre; + + Position = note.Position; + Size = note.Size; + Scale = note.Scale; + + AddInternal(new NotePiece()); + + note.HitObject.ColumnChanged += _ => Position = note.Position; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.Yellow; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs new file mode 100644 index 0000000000..3a2c398e84 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Tools; +using osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Screens.Compose; +using osu.Game.Screens.Edit.Screens.Compose.Layers; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaHitObjectComposer : HitObjectComposer + { + public BindableBeatDivisor BeatDivisor; + public ManiaHitObjectComposer(Ruleset ruleset, BindableBeatDivisor beatDivisor) + : base(ruleset) + { + BeatDivisor = beatDivisor; + } + + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap, BeatDivisor); + + protected override IReadOnlyList CompositionTools => new ICompositionTool[] + { + new HitObjectCompositionTool("Note"), + new HitObjectCompositionTool("Hold"), + }; + + // TODO: According to another proposal, extend this to support multiple layers for mania maps + // The logic could be moving all the layers that the beatmap has simultaneously + // To avoid using too many resources, this could be changed to simply changing the Alpha to something + // between 0.25f to 0.5f for notes that are in other layers (and may be also not selected) + // Will also need a tool to navigate through layers + // Please ignore the comment above, I just wanted to write my thoughts down so that I do not forget in 2 months when I get around to it + + public override HitObjectMask CreateMaskFor(DrawableHitObject hitObject) + { + switch (hitObject) + { + case DrawableNote note: + return new NoteMask(note); + case DrawableHoldNote holdNote: + return new HoldNoteMask(holdNote); + } + + return base.CreateMaskFor(hitObject); + } + + protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer((ManiaEditPlayfield)RulesetContainer.Playfield, this); + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 8791e8ed86..2f2d1abe6b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -18,8 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { - private readonly DrawableNote head; - private readonly DrawableNote tail; + public readonly DrawableNote Head; + public readonly DrawableNote Tail; private readonly GlowPiece glowPiece; private readonly BodyPiece bodyPiece; @@ -64,12 +64,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables HoldStartTime = () => holdStartTime }) }, - head = new DrawableHeadNote(this, action) + Head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre }, - tail = new DrawableTailNote(this, action) + Tail = new DrawableTailNote(this, action) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre @@ -79,8 +79,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables foreach (var tick in tickContainer) AddNested(tick); - AddNested(head); - AddNested(tail); + AddNested(Head); + AddNested(Tail); } public override Color4 AccentColour @@ -92,8 +92,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables glowPiece.AccentColour = value; bodyPiece.AccentColour = value; - head.AccentColour = value; - tail.AccentColour = value; + Head.AccentColour = value; + Tail.AccentColour = value; } } @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (tail.AllJudged) + if (Tail.AllJudged) AddJudgement(new HoldNoteJudgement { Result = HitResult.Perfect }); } @@ -119,12 +119,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables base.Update(); // Make the body piece not lie under the head note - bodyPiece.Y = head.Height; - bodyPiece.Height = DrawHeight - head.Height; + bodyPiece.Y = Head.Height; + bodyPiece.Height = DrawHeight - Head.Height; // Make the fullHeightContainer "contain" the height of the tail note, keeping in mind // that the tail note overshoots the height of this hit object - fullHeightContainer.Height = DrawHeight + tail.Height; + fullHeightContainer.Height = DrawHeight + Tail.Height; } public bool OnPressed(ManiaAction action) @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables holdStartTime = null; // If the key has been released too early, the user should not receive full score for the release - if (!tail.IsHit) + if (!Tail.IsHit) hasBroken = true; return true; diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index e183098a51..8b7191c4c4 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,14 +1,42 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Mania.Objects.Types; +using osu.Game.Rulesets.Edit.Types; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using System; namespace osu.Game.Rulesets.Mania.Objects { - public abstract class ManiaHitObject : HitObject, IHasColumn + public abstract class ManiaHitObject : HitObject, IHasColumn, IHasLayer, IHasXPosition, IHasEditableColumn, IHasEditableLayer { - public virtual int Column { get; set; } + public event Action ColumnChanged; + + private int column { get; set; } + + public virtual int Column + { + get => column; + set + { + if (column == value) + return; + column = value; + + ColumnChanged?.Invoke(value); + } + } + + public virtual int Layer { get; set; } + + public virtual float X + { + get => Column; + } + + public virtual void OffsetColumn(int offset) => Column += offset; + + public virtual void OffsetLayer(int offset) => Layer += offset; protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 4b936fc7f9..ae931e2f66 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -1,19 +1,19 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; -using osu.Game.Rulesets.Mania.Objects; using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; using System; using System.Collections.Generic; using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Configuration; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Mania.Configuration; -using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { @@ -25,7 +25,11 @@ namespace osu.Game.Rulesets.Mania.UI public readonly Bindable Inverted = new Bindable(true); public List Columns => stages.SelectMany(x => x.Columns).ToList(); + private readonly List stages = new List(); + public IReadOnlyList Stages => stages; + + protected virtual bool DisplayJudgements => true; public ManiaPlayfield(List stageDefinitions) : base(ScrollingDirection.Up) @@ -50,7 +54,8 @@ namespace osu.Game.Rulesets.Mania.UI int firstColumnIndex = 0; for (int i = 0; i < stageDefinitions.Count; i++) { - var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + var newStage = CreateStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + newStage.DisplayJudgements = DisplayJudgements; newStage.VisibleTimeRange.BindTo(VisibleTimeRange); newStage.Inverted.BindTo(Inverted); @@ -63,7 +68,11 @@ namespace osu.Game.Rulesets.Mania.UI } } - public override void Add(DrawableHitObject h) => getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h); + public override void Add(DrawableHitObject h) + { + h.OnJudgement += OnJudgement; + getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h); + } public void Add(BarLine barline) => stages.ForEach(s => s.Add(barline)); @@ -88,7 +97,13 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { + if (!judgedObject.DisplayJudgement || !DisplayJudgements) + return; + getStageByColumn(((ManiaHitObject)judgedObject.HitObject).Column).OnJudgement(judgedObject, judgement); } + + protected virtual ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + => new ManiaStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction); } } diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index a086da0565..1d95dbf004 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -10,4 +10,7 @@ + + + \ No newline at end of file diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 5f1b9a6bad..545c152bbd 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Edit protected ICompositionTool CurrentTool { get; private set; } - private RulesetContainer rulesetContainer; + protected RulesetContainer RulesetContainer; private readonly List layerContainers = new List(); private readonly Bindable beatmap = new Bindable(); @@ -44,8 +44,8 @@ namespace osu.Game.Rulesets.Edit try { - rulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value); - rulesetContainer.Clock = framedClock; + RulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value); + RulesetContainer.Clock = framedClock; } catch (Exception e) { @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Edit }; var layerAboveRuleset = CreateLayerContainer(); - layerAboveRuleset.Child = new HitObjectMaskLayer(rulesetContainer.Playfield, this); + layerAboveRuleset.Child = CreateHitObjectMaskLayer(); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - rulesetContainer, + RulesetContainer, layerAboveRuleset } } @@ -116,13 +116,14 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = rulesetContainer.Playfield.Anchor; - l.Origin = rulesetContainer.Playfield.Origin; - l.Position = rulesetContainer.Playfield.Position; - l.Size = rulesetContainer.Playfield.Size; + l.Anchor = RulesetContainer.Playfield.Anchor; + l.Origin = RulesetContainer.Playfield.Origin; + l.Position = RulesetContainer.Playfield.Position; + l.Size = RulesetContainer.Playfield.Size; }); } + private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool; protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap); @@ -141,6 +142,11 @@ namespace osu.Game.Rulesets.Edit /// public virtual MaskSelection CreateMaskSelection() => new MaskSelection(); + /// + /// Creates a depending on the ruleset. + /// + protected virtual HitObjectMaskLayer CreateHitObjectMaskLayer() => new HitObjectMaskLayer(RulesetContainer.Playfield, this); + /// /// Creates a which provides a layer above or below the . /// diff --git a/osu.Game/Rulesets/Edit/HitObjectMask.cs b/osu.Game/Rulesets/Edit/HitObjectMask.cs index 61fb700dd3..3caa4d9fbf 100644 --- a/osu.Game/Rulesets/Edit/HitObjectMask.cs +++ b/osu.Game/Rulesets/Edit/HitObjectMask.cs @@ -33,11 +33,21 @@ namespace osu.Game.Rulesets.Edit /// public event Action SelectionRequested; + /// + /// Invoked when this has started drag. + /// + public event Action DragStarted; + /// /// Invoked when this has requested drag. /// public event Action DragRequested; + /// + /// Invoked when this has ended drag. + /// + public event Action DragEnded; + /// /// The which this applies to. /// @@ -120,7 +130,11 @@ namespace osu.Game.Rulesets.Edit return base.OnClick(state); } - protected override bool OnDragStart(InputState state) => true; + protected override bool OnDragStart(InputState state) + { + DragStarted?.Invoke(this, state); + return true; + } protected override bool OnDrag(InputState state) { @@ -128,6 +142,12 @@ namespace osu.Game.Rulesets.Edit return true; } + protected override bool OnDragEnd(InputState state) + { + DragEnded?.Invoke(this, state); + return true; + } + /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 2c3720fc8f..9c3f99127d 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using osu.Framework.Input; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Edit.Tools @@ -8,6 +10,18 @@ namespace osu.Game.Rulesets.Edit.Tools public class HitObjectCompositionTool : ICompositionTool where T : HitObject { - public string Name => typeof(T).Name; + public string Name { get; } = typeof(T).Name; + + public Action OnMouseDown { get; } + public Action OnMouseUp { get; } + + public HitObjectCompositionTool() + { + } + + public HitObjectCompositionTool(string name) + { + Name = name; + } } } diff --git a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs index ce8b139b43..456c7e6fb3 100644 --- a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs @@ -1,10 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Input; +using System; + namespace osu.Game.Rulesets.Edit.Tools { public interface ICompositionTool { string Name { get; } + + Action OnMouseDown { get; } + Action OnMouseUp { get; } } } diff --git a/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs b/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs new file mode 100644 index 0000000000..2691223476 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Edit.Types +{ + public interface IHasEditableColumn : IHasColumn + { + void OffsetColumn(int offset); + } +} diff --git a/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs b/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs new file mode 100644 index 0000000000..3c886caba8 --- /dev/null +++ b/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Edit.Types +{ + public interface IHasEditableLayer : IHasLayer + { + void OffsetLayer(int offset); + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs b/osu.Game/Rulesets/Objects/Types/IHasColumn.cs similarity index 90% rename from osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs rename to osu.Game/Rulesets/Objects/Types/IHasColumn.cs index 44a79de7db..ba9c7ac933 100644 --- a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasColumn.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Rulesets.Mania.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A type of hit object which lies in one of a number of predetermined columns. diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index b9a8e9914a..5339be7d57 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -14,17 +14,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers { public class HitObjectMaskLayer : CompositeDrawable { - private readonly Playfield playfield; - private readonly HitObjectComposer composer; + protected readonly Playfield Playfield; + protected readonly HitObjectComposer Composer; private MaskContainer maskContainer; public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer) { // we need the playfield as HitObjects may not be initialised until its BDL. - this.playfield = playfield; + this.Playfield = playfield; - this.composer = composer; + this.Composer = composer; RelativeSizeAxes = Axes.Both; } @@ -34,12 +34,14 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers { maskContainer = new MaskContainer(); - var maskSelection = composer.CreateMaskSelection(); + var maskSelection = Composer.CreateMaskSelection(); maskContainer.MaskSelected += maskSelection.HandleSelected; maskContainer.MaskDeselected += maskSelection.HandleDeselected; maskContainer.MaskSelectionRequested += maskSelection.HandleSelectionRequested; + maskContainer.MaskDragStarted += maskSelection.HandleDragStart; maskContainer.MaskDragRequested += maskSelection.HandleDrag; + maskContainer.MaskDragEnded += maskSelection.HandleDragEnd; maskSelection.DeselectAll = maskContainer.DeselectAll; @@ -53,9 +55,13 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers maskContainer, dragLayer.CreateProxy() }; + AddMasks(); + } - foreach (var obj in playfield.HitObjects.Objects) - addMask(obj); + protected virtual void AddMasks() + { + foreach (var obj in Playfield.HitObjects.Objects) + AddMask(obj); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) @@ -68,9 +74,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers /// Adds a mask for a which adds movement support. /// /// The to create a mask for. - private void addMask(DrawableHitObject hitObject) + protected void AddMask(DrawableHitObject hitObject) { - var mask = composer.CreateMaskFor(hitObject); + var mask = Composer.CreateMaskFor(hitObject); if (mask == null) return; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs index df2691c28e..bce6d876be 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs @@ -29,11 +29,21 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers /// public event Action MaskSelectionRequested; + /// + /// Invoked when any starts drag. + /// + public event Action MaskDragStarted; + /// /// Invoked when any requests drag. /// public event Action MaskDragRequested; + /// + /// Invoked when any ends drag. + /// + public event Action MaskDragEnded; + private IEnumerable aliveMasks => AliveInternalChildren.Cast(); public MaskContainer() @@ -50,7 +60,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers drawable.Selected += onMaskSelected; drawable.Deselected += onMaskDeselected; drawable.SelectionRequested += onSelectionRequested; + drawable.DragStarted += onDragStarted; drawable.DragRequested += onDragRequested; + drawable.DragEnded += onDragEnded; } public override bool Remove(HitObjectMask drawable) @@ -64,7 +76,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers drawable.Selected -= onMaskSelected; drawable.Deselected -= onMaskDeselected; drawable.SelectionRequested -= onSelectionRequested; + drawable.DragStarted -= onDragStarted; drawable.DragRequested -= onDragRequested; + drawable.DragEnded -= onDragEnded; } return result; @@ -103,7 +117,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers } private void onSelectionRequested(HitObjectMask mask, InputState state) => MaskSelectionRequested?.Invoke(mask, state); + private void onDragStarted(HitObjectMask mask, InputState state) => MaskDragStarted?.Invoke(mask, state); private void onDragRequested(HitObjectMask mask, InputState state) => MaskDragRequested?.Invoke(mask, state); + private void onDragEnded(HitObjectMask mask, InputState state) => MaskDragEnded?.Invoke(mask, state); protected override int Compare(Drawable x, Drawable y) { diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs index 54697bad77..7cd77eeb1c 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs @@ -25,6 +25,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers private readonly List selectedMasks; private Drawable outline; + private Vector2 startingPosition; public MaskSelection() { @@ -54,6 +55,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers #region User Input Handling + public void HandleDragStart(HitObjectMask m, InputState state) => startingPosition = state.Mouse.Position; public void HandleDrag(HitObjectMask m, InputState state) { // Todo: Various forms of snapping @@ -65,9 +67,17 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers case IHasEditablePosition editablePosition: editablePosition.OffsetPosition(state.Mouse.Delta); break; + case IHasEditableColumn editableColumn: + if (IsDragged) + editableColumn.OffsetColumn((int)((startingPosition.X - state.Mouse.Position.X) / m.Width)); // Perform snapping, needs fixing + break; } } } + public void HandleDragEnd(HitObjectMask m, InputState state) + { + + } #endregion From 61a18b952fef7ced177f3928680e24e374f0955b Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Mon, 21 May 2018 23:24:10 +0300 Subject: [PATCH 002/277] Remove useless things --- osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs | 2 +- osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 4 +++- osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs | 12 ------------ 4 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 8b7191c4c4..aeb998b694 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -8,7 +8,7 @@ using System; namespace osu.Game.Rulesets.Mania.Objects { - public abstract class ManiaHitObject : HitObject, IHasColumn, IHasLayer, IHasXPosition, IHasEditableColumn, IHasEditableLayer + public abstract class ManiaHitObject : HitObject, IHasColumn, IHasXPosition, IHasEditableColumn { public event Action ColumnChanged; diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 6566d44ef5..233e4420f7 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.UI { - internal class DrawableManiaJudgement : DrawableJudgement + public class DrawableManiaJudgement : DrawableJudgement { public DrawableManiaJudgement(Judgement judgement, DrawableHitObject judgedObject) : base(judgement, judgedObject) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 904be3a9e3..53631838ba 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A collection of s. /// - internal class ManiaStage : ScrollingPlayfield + public class ManiaStage : ScrollingPlayfield { public const float HIT_TARGET_POSITION = 50; @@ -34,6 +34,8 @@ namespace osu.Game.Rulesets.Mania.UI /// public readonly Bindable Inverted = new Bindable(true); + public bool DisplayJudgements = true; + public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; diff --git a/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs b/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs deleted file mode 100644 index 3c886caba8..0000000000 --- a/osu.Game/Rulesets/Edit/Types/IHasEditableLayer.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Edit.Types -{ - public interface IHasEditableLayer : IHasLayer - { - void OffsetLayer(int offset); - } -} From 44cf2aa7a3bf0667812661992a7e646e67a425a0 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:00:11 +0300 Subject: [PATCH 003/277] Sync changes on composition tools --- osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs | 7 +++++-- osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs | 6 ------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 9c3f99127d..91062a211e 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -12,8 +12,11 @@ namespace osu.Game.Rulesets.Edit.Tools { public string Name { get; } = typeof(T).Name; - public Action OnMouseDown { get; } - public Action OnMouseUp { get; } + public Func OnMouseDown; + public Func OnMouseUp; + public Func OnDragStart; + public Func OnDragRequested; + public Func OnDragEnd; public HitObjectCompositionTool() { diff --git a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs index 456c7e6fb3..ce8b139b43 100644 --- a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs @@ -1,16 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Input; -using System; - namespace osu.Game.Rulesets.Edit.Tools { public interface ICompositionTool { string Name { get; } - - Action OnMouseDown { get; } - Action OnMouseUp { get; } } } From bbe7765a95d7a8ece6dedaffc6edeff74ae1696b Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:03:47 +0300 Subject: [PATCH 004/277] Add files to not require dependencies from #2534 --- .../Edit/ManiaEditPlayfield.cs | 29 +++++ .../Edit/ManiaEditRulesetContainer.cs | 102 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs new file mode 100644 index 0000000000..15ab4be52b --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.UI; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaEditPlayfield : ManiaPlayfield + { + protected override bool DisplayJudgements => false; + + public ManiaEditPlayfield(List stages) + : base(stages) + { + } + + public void Add(EditSnapLine editSnapLine) => Stages.Cast().ForEach(s => s.Add(editSnapLine)); + public void Remove(DrawableManiaEditSnapLine editSnapLine) => Stages.Cast().ForEach(s => s.Remove(editSnapLine)); + public void ClearEditSnapLines() => Stages.Cast().ForEach(s => s.ClearEditSnapLines()); + + protected override ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + => new ManiaEditStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction); + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs new file mode 100644 index 0000000000..49c13044e9 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs @@ -0,0 +1,102 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Cursor; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Screens.Compose; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaEditRulesetContainer : ManiaRulesetContainer + { + public BindableBeatDivisor BeatDivisor; + + public List EditSnapLines; + + public ManiaEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) + : base(ruleset, beatmap) + { + BeatDivisor = beatDivisor; + } + + [BackgroundDependencyLoader] + private void load() + { + BeatDivisor.ValueChanged += OnBeatSnapDivisorChange; + OnBeatSnapDivisorChange(BeatDivisor.Value); + } + + public void OnBeatSnapDivisorChange(int newDivisor) + { + generateEditSnapLines(newDivisor); + } + + private void generateEditSnapLines(int newDivisor) + { + // Generate the edit lines + double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; + + var timingPoints = Beatmap.ControlPointInfo.TimingPoints; + EditSnapLines = new List(); + + // Create lines before the beginning of the first timing point + if (timingPoints.Any()) + { + double step = timingPoints[0].BeatLength / newDivisor; + int index = (int)(timingPoints[0].Time / step); + index += newDivisor - index % newDivisor - 1; + for (double t = timingPoints[0].Time - step; t >= 0; t -= step, index--) + { + EditSnapLines.Add(new EditSnapLine + { + StartTime = t, + ControlPoint = timingPoints[0], + BeatDivisor = BeatDivisor, + BeatIndex = index, + }); + } + } + + for (int i = 0; i < timingPoints.Count; i++) + { + TimingControlPoint point = timingPoints[i]; + + // Stop 1ms before the end of the timing point before the next one if any, otherwise stop at the last object's time + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - 1 : lastObjectTime + point.BeatLength * (int)point.TimeSignature; + + int index = 0; + double step = point.BeatLength / newDivisor; + for (double t = timingPoints[i].Time; t <= endTime; t += step, index++) + { + EditSnapLines.Add(new EditSnapLine + { + StartTime = t, + ControlPoint = point, + BeatDivisor = BeatDivisor, + BeatIndex = index, + }); + } + } + + var editPlayfield = (ManiaEditPlayfield)Playfield; + + editPlayfield.ClearEditSnapLines(); + EditSnapLines.ForEach(editPlayfield.Add); + } + + protected override Playfield CreatePlayfield() => new ManiaEditPlayfield(Beatmap.Stages); + + protected override Vector2 PlayfieldArea => Vector2.One; + + protected override CursorContainer CreateCursor() => null; + } +} From 2769f6c47bd794c5b97f963846d1bdedf9ff729e Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:09:25 +0300 Subject: [PATCH 005/277] Fix issues --- .../Edit/Layers/Selection/Overlays/HoldNoteMask.cs | 5 +---- .../Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs | 1 - osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs | 8 -------- .../Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs | 4 ++-- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index 3106fedb30..ea28d24752 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -3,13 +3,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Primitives; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays @@ -32,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { new NoteMask(hold.Head), new NoteMask(hold.Tail), - body = new BodyPiece() + body = new BodyPiece { AccentColour = Color4.Transparent }, diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs index 1f8d391c99..6886ff83f7 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.UI; using osu.Game.Screens.Edit.Screens.Compose.Layers; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 3a2c398e84..f0e0f27818 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit.Tools; @@ -33,13 +32,6 @@ namespace osu.Game.Rulesets.Mania.Edit new HitObjectCompositionTool("Hold"), }; - // TODO: According to another proposal, extend this to support multiple layers for mania maps - // The logic could be moving all the layers that the beatmap has simultaneously - // To avoid using too many resources, this could be changed to simply changing the Alpha to something - // between 0.25f to 0.5f for notes that are in other layers (and may be also not selected) - // Will also need a tool to navigate through layers - // Please ignore the comment above, I just wanted to write my thoughts down so that I do not forget in 2 months when I get around to it - public override HitObjectMask CreateMaskFor(DrawableHitObject hitObject) { switch (hitObject) diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index 5339be7d57..ffef177d00 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -22,9 +22,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer) { // we need the playfield as HitObjects may not be initialised until its BDL. - this.Playfield = playfield; + Playfield = playfield; - this.Composer = composer; + Composer = composer; RelativeSizeAxes = Axes.Both; } From 8aac1f50eea9127de3db49151fbea11dffd9274c Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:12:22 +0300 Subject: [PATCH 006/277] Remove more dependencies --- .../Edit/ManiaEditRulesetContainer.cs | 61 ------------------- .../UI/ManiaRulesetContainer.cs | 2 +- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs index 49c13044e9..442997f1f3 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs @@ -5,14 +5,9 @@ using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Screens.Edit.Screens.Compose; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.Mania.Edit { @@ -20,8 +15,6 @@ namespace osu.Game.Rulesets.Mania.Edit { public BindableBeatDivisor BeatDivisor; - public List EditSnapLines; - public ManiaEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) : base(ruleset, beatmap) { @@ -37,60 +30,6 @@ namespace osu.Game.Rulesets.Mania.Edit public void OnBeatSnapDivisorChange(int newDivisor) { - generateEditSnapLines(newDivisor); - } - - private void generateEditSnapLines(int newDivisor) - { - // Generate the edit lines - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints; - EditSnapLines = new List(); - - // Create lines before the beginning of the first timing point - if (timingPoints.Any()) - { - double step = timingPoints[0].BeatLength / newDivisor; - int index = (int)(timingPoints[0].Time / step); - index += newDivisor - index % newDivisor - 1; - for (double t = timingPoints[0].Time - step; t >= 0; t -= step, index--) - { - EditSnapLines.Add(new EditSnapLine - { - StartTime = t, - ControlPoint = timingPoints[0], - BeatDivisor = BeatDivisor, - BeatIndex = index, - }); - } - } - - for (int i = 0; i < timingPoints.Count; i++) - { - TimingControlPoint point = timingPoints[i]; - - // Stop 1ms before the end of the timing point before the next one if any, otherwise stop at the last object's time - double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - 1 : lastObjectTime + point.BeatLength * (int)point.TimeSignature; - - int index = 0; - double step = point.BeatLength / newDivisor; - for (double t = timingPoints[i].Time; t <= endTime; t += step, index++) - { - EditSnapLines.Add(new EditSnapLine - { - StartTime = t, - ControlPoint = point, - BeatDivisor = BeatDivisor, - BeatIndex = index, - }); - } - } - - var editPlayfield = (ManiaEditPlayfield)Playfield; - - editPlayfield.ClearEditSnapLines(); - EditSnapLines.ForEach(editPlayfield.Add); } protected override Playfield CreatePlayfield() => new ManiaEditPlayfield(Beatmap.Stages); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 7123aab901..6618125176 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) + protected override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From a178c44b60e578cf654d57d2a98361d94d147737 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:12:51 +0300 Subject: [PATCH 007/277] Remove snap line dependencies --- osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs index 15ab4be52b..30ff591359 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs @@ -1,12 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.UI; using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.Mania.Edit { @@ -19,10 +16,6 @@ namespace osu.Game.Rulesets.Mania.Edit { } - public void Add(EditSnapLine editSnapLine) => Stages.Cast().ForEach(s => s.Add(editSnapLine)); - public void Remove(DrawableManiaEditSnapLine editSnapLine) => Stages.Cast().ForEach(s => s.Remove(editSnapLine)); - public void ClearEditSnapLines() => Stages.Cast().ForEach(s => s.ClearEditSnapLines()); - protected override ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) => new ManiaEditStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction); } From c7dfe88ad2229aaf4bdbaaa3953846489a1d3228 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 22 May 2018 09:18:02 +0300 Subject: [PATCH 008/277] Complete PR's independence --- .../Layers/Selection/Overlays/HoldNoteMask.cs | 3 --- osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs | 16 ++++++++++++++++ .../Objects/ManiaHitObject.cs | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index ea28d24752..0b468515d3 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -14,13 +14,10 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays public class HoldNoteMask : HitObjectMask { private readonly BodyPiece body; - private readonly DrawableHoldNote holdNote; public HoldNoteMask(DrawableHoldNote hold) : base(hold) { - holdNote = hold; - Position = hold.Position; var holdObject = hold.HitObject; diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs new file mode 100644 index 0000000000..9068725023 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Edit +{ + public class ManiaEditStage : ManiaStage + { + public ManiaEditStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + : base(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index aeb998b694..4d28c39faa 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -8,7 +8,7 @@ using System; namespace osu.Game.Rulesets.Mania.Objects { - public abstract class ManiaHitObject : HitObject, IHasColumn, IHasXPosition, IHasEditableColumn + public abstract class ManiaHitObject : HitObject, IHasXPosition, IHasEditableColumn { public event Action ColumnChanged; From e98f9f1323342f3643da07d2fbb3347b0a3b1b25 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 2 Jun 2018 21:02:45 +0300 Subject: [PATCH 009/277] Add dropdown for selecting fullscreen resolution --- .../Sections/Graphics/LayoutSettings.cs | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 1f87a635de..b3a2243ca3 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Platform; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -16,20 +20,32 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; + private OsuGame game; + private SettingsDropdown resolutionDropdown; + private SettingsEnumDropdown windowModeDropdown; + private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config) + private void load(FrameworkConfigManager config, OsuGame game) { + this.game = game; + letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); Children = new Drawable[] { - new SettingsEnumDropdown + windowModeDropdown = new SettingsEnumDropdown { LabelText = "Screen mode", Bindable = config.GetBindable(FrameworkSetting.WindowMode), }, + resolutionDropdown = new SettingsDropdown + { + LabelText = "Resolution", + Items = getResolutions(), + Bindable = config.GetBindable(FrameworkSetting.FullscreenResolution) + }, new SettingsCheckbox { LabelText = "Letterboxing", @@ -62,6 +78,15 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; + windowModeDropdown.Bindable.ValueChanged += (s) => + { + if (windowModeDropdown.Bindable.Value == WindowMode.Fullscreen) + resolutionDropdown.Show(); + else + resolutionDropdown.Hide(); + }; + windowModeDropdown.Bindable.TriggerChange(); + letterboxing.ValueChanged += isVisible => { letterboxSettings.ClearTransforms(); @@ -72,5 +97,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }; letterboxing.TriggerChange(); } + + private IEnumerable> getResolutions() + { + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + + return (availableDisplayResolutions ?? throw new InvalidOperationException()).Select((t, i) => new KeyValuePair($"{t.Width}x{t.Height}@{t.RefreshRate}Hz", i)); + } } } From f715734662ee56224ac061790587b18d73aac4a7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 15:57:21 +0900 Subject: [PATCH 010/277] Remove unnecessary csproj edit --- osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 1d95dbf004..a086da0565 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -10,7 +10,4 @@ - - - \ No newline at end of file From 279a2844f045e7d699f88148c264d9fd38463709 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 16:08:37 +0900 Subject: [PATCH 011/277] Actually make ManiaHitObjectComposer constructible/testable --- .../TestCaseEditor.cs | 17 +++++++++++++++++ .../Edit/ManiaEditRulesetContainer.cs | 18 +----------------- .../Edit/ManiaHitObjectComposer.cs | 7 ++----- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ++++ 4 files changed, 24 insertions(+), 22 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs new file mode 100644 index 0000000000..799bb9efd8 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestCaseEditor : EditorTestCase + { + public TestCaseEditor() + : base(new ManiaRuleset()) + { + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs index 442997f1f3..71ec668531 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs @@ -2,33 +2,17 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Framework.Allocation; using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Edit.Screens.Compose; namespace osu.Game.Rulesets.Mania.Edit { public class ManiaEditRulesetContainer : ManiaRulesetContainer { - public BindableBeatDivisor BeatDivisor; - - public ManiaEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, BindableBeatDivisor beatDivisor) + public ManiaEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) - { - BeatDivisor = beatDivisor; - } - - [BackgroundDependencyLoader] - private void load() - { - BeatDivisor.ValueChanged += OnBeatSnapDivisorChange; - OnBeatSnapDivisorChange(BeatDivisor.Value); - } - - public void OnBeatSnapDivisorChange(int newDivisor) { } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index f0e0f27818..d04c70ae16 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Edit.Screens.Compose; using osu.Game.Screens.Edit.Screens.Compose.Layers; using System.Collections.Generic; @@ -17,14 +16,12 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaHitObjectComposer : HitObjectComposer { - public BindableBeatDivisor BeatDivisor; - public ManiaHitObjectComposer(Ruleset ruleset, BindableBeatDivisor beatDivisor) + public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) { - BeatDivisor = beatDivisor; } - protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap, BeatDivisor); + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap); protected override IReadOnlyList CompositionTools => new ICompositionTool[] { diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 02ecb3afda..9d7c37d9e9 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -16,8 +16,10 @@ using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Replays.Types; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Difficulty; +using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania @@ -28,6 +30,8 @@ namespace osu.Game.Rulesets.Mania public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); + public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); + public override IEnumerable ConvertLegacyMods(LegacyMods mods) { if (mods.HasFlag(LegacyMods.Nightcore)) From d1b469c1a3b3737e02086a85b4bcd6dfeffb9700 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 16:27:49 +0900 Subject: [PATCH 012/277] Better handling of nested playfields' hitobjects --- .../Overlays/ManiaHitObjectColumnMaskLayer.cs | 28 ----------------- .../Overlays/ManiaHitObjectMaskLayer.cs | 28 ----------------- .../Overlays/ManiaHitObjectStageMaskLayer.cs | 31 ------------------- .../Edit/ManiaHitObjectComposer.cs | 3 -- .../Compose/Layers/HitObjectMaskLayer.cs | 15 ++++++--- 5 files changed, 10 insertions(+), 95 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs delete mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs delete mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs deleted file mode 100644 index 6886ff83f7..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectColumnMaskLayer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Screens.Edit.Screens.Compose.Layers; - -namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays -{ - public class ManiaHitObjectColumnMaskLayer : HitObjectMaskLayer - { - public readonly Column Column; - - public ManiaHitObjectColumnMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, Column column) - : base(playfield, composer) - { - Column = column; - } - - public void CreateMasks() => AddMasks(); - - protected override void AddMasks() - { - foreach (var obj in Column.HitObjects.Objects) - AddMask(obj); - } - } -} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs deleted file mode 100644 index 012fc495b5..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectMaskLayer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Edit; -using osu.Game.Screens.Edit.Screens.Compose.Layers; -using System.Collections.Generic; - -namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays -{ - public class ManiaHitObjectMaskLayer : HitObjectMaskLayer - { - public readonly List Stages; - - public ManiaHitObjectMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer) - : base(playfield, composer) - { - Stages = new List(); - foreach (var s in ((ManiaEditPlayfield)Playfield).Stages) - Stages.Add(new ManiaHitObjectStageMaskLayer((ManiaEditPlayfield)Playfield, Composer, s)); - } - - protected override void AddMasks() - { - foreach (var s in Stages) - s.CreateMasks(); - } - } -} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs deleted file mode 100644 index ae800019c5..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/ManiaHitObjectStageMaskLayer.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Edit; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Screens.Edit.Screens.Compose.Layers; -using System.Collections.Generic; - -namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays -{ - public class ManiaHitObjectStageMaskLayer : HitObjectMaskLayer - { - public readonly List Columns; - - public ManiaHitObjectStageMaskLayer(ManiaEditPlayfield playfield, HitObjectComposer composer, ManiaStage s) - : base(playfield, composer) - { - Columns = new List(); - foreach (var c in s.Columns) - Columns.Add(new ManiaHitObjectColumnMaskLayer((ManiaEditPlayfield)Playfield, Composer, c)); - } - - public void CreateMasks() => AddMasks(); - - protected override void AddMasks() - { - foreach (var c in Columns) - c.CreateMasks(); - } - } -} diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index d04c70ae16..b1968d0aff 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -9,7 +9,6 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; -using osu.Game.Screens.Edit.Screens.Compose.Layers; using System.Collections.Generic; namespace osu.Game.Rulesets.Mania.Edit @@ -41,7 +40,5 @@ namespace osu.Game.Rulesets.Mania.Edit return base.CreateMaskFor(hitObject); } - - protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer((ManiaEditPlayfield)RulesetContainer.Playfield, this); } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index ffef177d00..9444e07f85 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -55,13 +55,18 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers maskContainer, dragLayer.CreateProxy() }; - AddMasks(); + + addMasks(Playfield); } - protected virtual void AddMasks() + private void addMasks(Playfield playfield) { - foreach (var obj in Playfield.HitObjects.Objects) - AddMask(obj); + foreach (var obj in playfield.HitObjects.Objects) + addMask(obj); + + if (playfield.NestedPlayfields != null) + foreach (var p in playfield.NestedPlayfields) + addMasks(p); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) @@ -74,7 +79,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers /// Adds a mask for a which adds movement support. /// /// The to create a mask for. - protected void AddMask(DrawableHitObject hitObject) + private void addMask(DrawableHitObject hitObject) { var mask = Composer.CreateMaskFor(hitObject); if (mask == null) From cd532cde2d7852d94d8969dbed881c115baec6ae Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 18:28:49 +0900 Subject: [PATCH 013/277] Fix note masks not working --- .../Edit/Layers/Selection/Overlays/NoteMask.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs index 8228adf35f..9f34bb4fa4 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; @@ -15,10 +14,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays public NoteMask(DrawableNote note) : base(note) { - Origin = Anchor.Centre; - - Position = note.Position; - Size = note.Size; Scale = note.Scale; AddInternal(new NotePiece()); @@ -31,5 +26,13 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { Colour = colours.Yellow; } + + protected override void Update() + { + base.Update(); + + Size = HitObject.DrawSize; + Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.BottomLeft); + } } } From f299ae0fbd18541f0078bc7cfac9fc45866c8988 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 18:59:52 +0900 Subject: [PATCH 014/277] Fix positioning --- .../Edit/Layers/ManiaHitObjectMaskLayer.cs | 27 +++++++++++++++++++ .../Layers/Selection/Overlays/NoteMask.cs | 3 ++- .../Edit/ManiaHitObjectComposer.cs | 11 ++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs new file mode 100644 index 0000000000..2bf9cbe6e0 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Edit.Screens.Compose.Layers; +using OpenTK; + +namespace osu.Game.Rulesets.Mania.Edit.Layers +{ + public class ManiaHitObjectMaskLayer : HitObjectMaskLayer + { + public readonly IBindable Inverted = new Bindable(); + + public ManiaHitObjectMaskLayer(Playfield playfield, HitObjectComposer composer) + : base(playfield, composer) + { + Inverted.ValueChanged += invertedChanged; + } + + private void invertedChanged(bool newValue) + { + Scale = new Vector2(1, newValue ? -1 : 1); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs index 9f34bb4fa4..d61ef114c5 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -32,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays base.Update(); Size = HitObject.DrawSize; - Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.BottomLeft); + Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.TopLeft); } } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index b1968d0aff..225f04479d 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -10,6 +10,9 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using System.Collections.Generic; +using osu.Game.Rulesets.Mania.Edit.Layers; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Screens.Edit.Screens.Compose.Layers; namespace osu.Game.Rulesets.Mania.Edit { @@ -40,5 +43,13 @@ namespace osu.Game.Rulesets.Mania.Edit return base.CreateMaskFor(hitObject); } + + protected override HitObjectMaskLayer CreateHitObjectMaskLayer() + { + var layer = new ManiaHitObjectMaskLayer(RulesetContainer.Playfield, this); + layer.Inverted.BindTo(((ManiaPlayfield)RulesetContainer.Playfield).Inverted); + + return layer; + } } } From 24b314b51f9c5c28be61b09fa6f56558c03c8100 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:00:02 +0900 Subject: [PATCH 015/277] Fix hold note masks not working --- .../Layers/Selection/Overlays/HoldNoteMask.cs | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index 0b468515d3..648ec29e64 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -18,14 +18,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays public HoldNoteMask(DrawableHoldNote hold) : base(hold) { - Position = hold.Position; - var holdObject = hold.HitObject; InternalChildren = new Drawable[] { - new NoteMask(hold.Head), - new NoteMask(hold.Tail), + new HoldNoteNoteMask(hold.Head), + new HoldNoteNoteMask(hold.Tail), body = new BodyPiece { AccentColour = Color4.Transparent @@ -40,5 +38,29 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { body.BorderColour = colours.Yellow; } + + protected override void Update() + { + base.Update(); + + Size = HitObject.DrawSize; + Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.TopLeft); + } + + private class HoldNoteNoteMask : NoteMask + { + public HoldNoteNoteMask(DrawableNote note) + : base(note) + { + Select(); + } + + protected override void Update() + { + base.Update(); + + Position = HitObject.DrawPosition; + } + } } } From ce7a5e8914af475684e95d6420d6aa2ff8ff7055 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 7 Jun 2018 19:19:32 +0900 Subject: [PATCH 016/277] Update visual style to match new notes --- .../Edit/Layers/Selection/Overlays/NoteMask.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs index d61ef114c5..8c46e20835 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; @@ -17,6 +16,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { Scale = note.Scale; + CornerRadius = 5; + Masking = true; + AddInternal(new NotePiece()); note.HitObject.ColumnChanged += _ => Position = note.Position; From de7e4328c5c316df687ab91c5901d99961fe2d69 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sun, 10 Jun 2018 16:17:57 +0300 Subject: [PATCH 017/277] Use bindable size --- .../Sections/Graphics/LayoutSettings.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index b3a2243ca3..2d970e41de 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,8 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; @@ -19,11 +19,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private FillFlowContainer letterboxSettings; private Bindable letterboxing; + private Bindable sizeFullscreen; private OsuGame game; private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; + private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -32,6 +34,17 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics this.game = game; letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); + sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); + + var resolutions = getResolutions(); + var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); + + resolutionDropdownBindable.ValueChanged += _ => + { + var newResolution = resolutions.First(r => r.Value == _); + var newResolutionparts = newResolution.Key.Split('x'); + sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); + }; Children = new Drawable[] { @@ -43,8 +56,8 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", - Items = getResolutions(), - Bindable = config.GetBindable(FrameworkSetting.FullscreenResolution) + Items = resolutions, + Bindable = resolutionDropdownBindable }, new SettingsCheckbox { @@ -98,11 +111,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing.TriggerChange(); } - private IEnumerable> getResolutions() + private List> getResolutions() { var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + if (availableDisplayResolutions == null) + return new List>(); + var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); - return (availableDisplayResolutions ?? throw new InvalidOperationException()).Select((t, i) => new KeyValuePair($"{t.Width}x{t.Height}@{t.RefreshRate}Hz", i)); + return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); } } } From 71371dc4b86090e493c73ee6ea5b325424a34e91 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 12 Jun 2018 19:27:55 +0300 Subject: [PATCH 018/277] ValueChanged parameters quickfix --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 2d970e41de..588be967e5 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -39,9 +39,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics var resolutions = getResolutions(); var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); - resolutionDropdownBindable.ValueChanged += _ => + resolutionDropdownBindable.ValueChanged += resolution => { - var newResolution = resolutions.First(r => r.Value == _); + var newResolution = resolutions.First(r => r.Value == resolution); var newResolutionparts = newResolution.Key.Split('x'); sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); }; @@ -91,9 +91,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; - windowModeDropdown.Bindable.ValueChanged += (s) => + windowModeDropdown.Bindable.ValueChanged += windowMode => { - if (windowModeDropdown.Bindable.Value == WindowMode.Fullscreen) + if (windowMode == WindowMode.Fullscreen) resolutionDropdown.Show(); else resolutionDropdown.Hide(); From 5d26d5d4ed81d97dc0ce257d85665ce9b8495d62 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 21 Jun 2018 20:42:22 +0300 Subject: [PATCH 019/277] Fix resolutionDropdown --- .../Sections/Graphics/LayoutSettings.cs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 588be967e5..36de8d4771 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -20,6 +20,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; private Bindable sizeFullscreen; + private readonly BindableInt resolutionDropdownBindable = new BindableInt(); private OsuGame game; private SettingsDropdown resolutionDropdown; @@ -36,14 +37,23 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); - var resolutions = getResolutions(); - var resolutionDropdownBindable = new BindableInt(resolutions.FirstOrDefault(r => r.Key.StartsWith($"{sizeFullscreen.Value.Width}x{sizeFullscreen.Value.Height}")).Value); + sizeFullscreen.ValueChanged += size => + { + KeyValuePair valuePair = getResolutions().FirstOrDefault(r => r.Key.StartsWith($"{size.Width}x{size.Height}")); + + resolutionDropdownBindable.Value = valuePair.Value; + }; resolutionDropdownBindable.ValueChanged += resolution => { - var newResolution = resolutions.First(r => r.Value == resolution); - var newResolutionparts = newResolution.Key.Split('x'); - sizeFullscreen.Value = new Size(int.Parse(newResolutionparts.First()), int.Parse(newResolutionparts.Last())); + var newSelection = getResolutions().First(r => r.Value == resolution); + var newSelectionParts = newSelection.Key.Split('x'); + + var newSelectionWidth = int.Parse(newSelectionParts.First()); + var newSelectionHeight = int.Parse(newSelectionParts.Last()); + + if (sizeFullscreen.Value.Width != newSelectionWidth || sizeFullscreen.Value.Height != newSelectionHeight) + sizeFullscreen.Value = new Size(newSelectionWidth, newSelectionHeight); }; Children = new Drawable[] @@ -56,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", - Items = resolutions, + Items = getResolutions(), Bindable = resolutionDropdownBindable }, new SettingsCheckbox @@ -94,7 +104,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics windowModeDropdown.Bindable.ValueChanged += windowMode => { if (windowMode == WindowMode.Fullscreen) + { resolutionDropdown.Show(); + sizeFullscreen.TriggerChange(); + } else resolutionDropdown.Hide(); }; @@ -113,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions; + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions.OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); if (availableDisplayResolutions == null) return new List>(); var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); From 5076fe4c2000747b34c826fd3d3925a1ce7d8f85 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 23 Jun 2018 12:45:13 +0300 Subject: [PATCH 020/277] LayoutSettings: inject OsuGameBase instead of OsuGame --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 36de8d4771..27ce8bad13 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable sizeFullscreen; private readonly BindableInt resolutionDropdownBindable = new BindableInt(); - private OsuGame game; + private OsuGameBase game; private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private const int transition_duration = 400; [BackgroundDependencyLoader] - private void load(FrameworkConfigManager config, OsuGame game) + private void load(FrameworkConfigManager config, OsuGameBase game) { this.game = game; From a0b67f4059ffab31581f086c882427d032ad7bb7 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Thu, 28 Jun 2018 13:39:49 +0200 Subject: [PATCH 021/277] Add Shake Transformation --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 88990d435c..4bae3e93e6 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -13,6 +13,8 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using OpenTK.Graphics; +using osu.Framework.Graphics; +using OpenTK; namespace osu.Game.Rulesets.Objects.Drawables { @@ -229,6 +231,16 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { } + + public void Shake() + { + this.MoveToOffset(new Vector2(8, 0), 20).Delay(20) + .MoveToOffset(-new Vector2(16, 0), 20).Delay(20) + .MoveToOffset(new Vector2(16, 0), 20).Delay(20) + .MoveToOffset(-new Vector2(16, 0), 20).Delay(20) + .MoveToOffset(new Vector2(16, 0), 20).Delay(20) + .MoveToOffset(-new Vector2(8, 0), 20); + } } public abstract class DrawableHitObject : DrawableHitObject From 61c416dc16d0a35ac5740993902f03cf0ab64fb6 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Thu, 28 Jun 2018 13:41:23 +0200 Subject: [PATCH 022/277] Trigger Shake if HitCircles are hit too early --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 9fe6dcd46c..a133e85842 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -88,7 +88,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var result = HitObject.HitWindows.ResultFor(timeOffset); if (result == HitResult.None) + { + Shake(); return; + } AddJudgement(new OsuJudgement { From 59e03fa5289512e795960fe0f6c13c98a36a9b98 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Thu, 28 Jun 2018 15:33:59 +0200 Subject: [PATCH 023/277] Move Shake to DrawableOsuHitObject, Clean up Shake() --- .../Objects/Drawables/DrawableOsuHitObject.cs | 12 ++++++++++++ .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 7c9503dfe2..c871520080 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -58,6 +58,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); + + public void Shake() + { + const int shake_amount = 8; + + this.MoveToX(Position.X + shake_amount, 20).Then() + .MoveToX(Position.X - shake_amount, 20).Then() + .MoveToX(Position.X + shake_amount, 20).Then() + .MoveToX(Position.X - shake_amount, 20).Then() + .MoveToX(Position.X + shake_amount, 20).Then() + .MoveToX(Position.X, 20); + } } public enum ComboResult diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4bae3e93e6..88990d435c 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -13,8 +13,6 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using OpenTK.Graphics; -using osu.Framework.Graphics; -using OpenTK; namespace osu.Game.Rulesets.Objects.Drawables { @@ -231,16 +229,6 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { } - - public void Shake() - { - this.MoveToOffset(new Vector2(8, 0), 20).Delay(20) - .MoveToOffset(-new Vector2(16, 0), 20).Delay(20) - .MoveToOffset(new Vector2(16, 0), 20).Delay(20) - .MoveToOffset(-new Vector2(16, 0), 20).Delay(20) - .MoveToOffset(new Vector2(16, 0), 20).Delay(20) - .MoveToOffset(-new Vector2(8, 0), 20); - } } public abstract class DrawableHitObject : DrawableHitObject From e3317b5145f4aa7c4a31fd649849691c649fa60f Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Fri, 29 Jun 2018 17:31:13 +0900 Subject: [PATCH 024/277] Make method protected --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index c871520080..c02d711ee8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - public void Shake() + protected void Shake() { const int shake_amount = 8; From 3d500500899c27f2dc634cb12363ff5ebdd2e2b4 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Fri, 29 Jun 2018 10:36:00 +0200 Subject: [PATCH 025/277] Move shake duration to a constant --- .../Objects/Drawables/DrawableOsuHitObject.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index c02d711ee8..f25ddc4d82 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -62,13 +62,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected void Shake() { const int shake_amount = 8; + const int shake_duration = 20; - this.MoveToX(Position.X + shake_amount, 20).Then() - .MoveToX(Position.X - shake_amount, 20).Then() - .MoveToX(Position.X + shake_amount, 20).Then() - .MoveToX(Position.X - shake_amount, 20).Then() - .MoveToX(Position.X + shake_amount, 20).Then() - .MoveToX(Position.X, 20); + this.MoveToX(Position.X + shake_amount, shake_duration).Then() + .MoveToX(Position.X - shake_amount, shake_duration).Then() + .MoveToX(Position.X + shake_amount, shake_duration).Then() + .MoveToX(Position.X - shake_amount, shake_duration).Then() + .MoveToX(Position.X + shake_amount, shake_duration).Then() + .MoveToX(Position.X, shake_duration); } } From 4af45b751817f8a95624b6d7a93e98468c56a412 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 30 Jun 2018 20:06:11 +0300 Subject: [PATCH 026/277] Do not display resolutions lower than 800x600 --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 27ce8bad13..996b6a2a24 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -126,11 +126,14 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions.OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + if (availableDisplayResolutions == null) return new List>(); - var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct().ToList(); + var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct(); return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); } } From 558b2622a74e90ef7899b4d1d8549dba62e53ae3 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Thu, 5 Jul 2018 15:48:54 +0200 Subject: [PATCH 027/277] Move the Shake logic to a new ShakeContainer --- .../Objects/Drawables/DrawableOsuHitObject.cs | 23 +++++++++++------- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/Pieces/SliderBall.cs | 6 +++-- .../Graphics/Containers/ShakeContainer.cs | 24 +++++++++++++++++++ 4 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Graphics/Containers/ShakeContainer.cs diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f25ddc4d82..6b12fc029e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -8,6 +8,7 @@ using System.Linq; using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using OpenTK.Graphics; +using osu.Game.Graphics.Containers; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -15,12 +16,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; + private readonly ShakeContainer shakeContainer; + protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { + shakeContainer = new ShakeContainer + { + RelativeSizeAxes = Axes.Both, + }; + base.AddInternal(shakeContainer); Alpha = 0; } + // Forward all internal management to shakeContainer + protected override void AddInternal(Drawable drawable) => shakeContainer.Add(drawable); + protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); + protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); + protected sealed override void UpdateState(ArmedState state) { double transformTime = HitObject.StartTime - HitObject.TimePreempt; @@ -61,15 +74,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected void Shake() { - const int shake_amount = 8; - const int shake_duration = 20; - - this.MoveToX(Position.X + shake_amount, shake_duration).Then() - .MoveToX(Position.X - shake_amount, shake_duration).Then() - .MoveToX(Position.X + shake_amount, shake_duration).Then() - .MoveToX(Position.X - shake_amount, shake_duration).Then() - .MoveToX(Position.X + shake_amount, shake_duration).Then() - .MoveToX(Position.X, shake_duration); + shakeContainer.Shake(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index c8544d9cc1..d48419ba53 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, ticks = new Container { RelativeSizeAxes = Axes.Both }, repeatPoints = new Container { RelativeSizeAxes = Axes.Both }, - Ball = new SliderBall(s) + Ball = new SliderBall(s, this) { BypassAutoSizeAxes = Axes.Both, Scale = new Vector2(s.Scale), diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 894d972e47..278bb0dcb1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -34,9 +34,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private readonly Slider slider; public readonly Box FollowCircle; private readonly Box ball; + private readonly DrawableSlider drawableSlider; - public SliderBall(Slider slider) + public SliderBall(Slider slider, DrawableSlider drawableSlider = null) { + this.drawableSlider = drawableSlider; this.slider = slider; Masking = true; AutoSizeAxes = Axes.Both; @@ -136,7 +138,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces Tracking = canCurrentlyTrack && lastState != null && base.ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) - && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); + && (drawableSlider?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); } } diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs new file mode 100644 index 0000000000..33fba390d6 --- /dev/null +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Graphics.Containers +{ + public class ShakeContainer : Container + { + public void Shake() + { + const int shake_amount = 8; + const int shake_duration = 20; + + this.MoveToX(shake_amount, shake_duration).Then() + .MoveToX(-shake_amount, shake_duration).Then() + .MoveToX(shake_amount, shake_duration).Then() + .MoveToX(-shake_amount, shake_duration).Then() + .MoveToX(shake_amount, shake_duration).Then() + .MoveToX(0, shake_duration); + } + } +} From d4534140706cb277e317a7340453caa1dfe3b4b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 11:52:58 +0900 Subject: [PATCH 028/277] Forward shakes from slider head objects to sliders --- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 5 ++++- .../Objects/Drawables/DrawableSliderHead.cs | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 6b12fc029e..bf58c0c0e3 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - protected void Shake() + protected virtual void Shake() { shakeContainer.Shake(); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index d48419ba53..2b1c37b2b6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -52,7 +52,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - HeadCircle = new DrawableSliderHead(s, s.HeadCircle), + HeadCircle = new DrawableSliderHead(s, s.HeadCircle) + { + OnShake = Shake + }, TailCircle = new DrawableSliderTail(s, s.TailCircle) }; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index e823c870f9..fbea927956 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Game.Rulesets.Objects.Types; using OpenTK; @@ -28,5 +29,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!IsHit) Position = slider.CurvePositionAt(completionProgress); } + + public Action OnShake; + + protected override void Shake() => OnShake?.Invoke(); } } From 0ecbc5945f3a93914756d42baf459bc2a9cd14c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 12:07:39 +0900 Subject: [PATCH 029/277] Adjust transform to look better --- osu.Game/Graphics/Containers/ShakeContainer.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 33fba390d6..3316fb5306 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -10,15 +10,15 @@ namespace osu.Game.Graphics.Containers { public void Shake() { - const int shake_amount = 8; - const int shake_duration = 20; + const float shake_amount = 8; + const float shake_duration = 30; - this.MoveToX(shake_amount, shake_duration).Then() - .MoveToX(-shake_amount, shake_duration).Then() - .MoveToX(shake_amount, shake_duration).Then() - .MoveToX(-shake_amount, shake_duration).Then() - .MoveToX(shake_amount, shake_duration).Then() - .MoveToX(0, shake_duration); + this.MoveToX(shake_amount, shake_duration / 2, Easing.OutSine).Then() + .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() + .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() + .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() + .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() + .MoveToX(0, shake_duration / 2, Easing.InSine); } } } From 48d90a67ae60446b29bfae1a461d7c1219b15a94 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 12:13:23 +0900 Subject: [PATCH 030/277] xmldoc and formatting --- .../Objects/Drawables/DrawableOsuHitObject.cs | 11 ++--------- osu.Game/Graphics/Containers/ShakeContainer.cs | 6 ++++++ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index bf58c0c0e3..1764d3c487 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -21,11 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { - shakeContainer = new ShakeContainer - { - RelativeSizeAxes = Axes.Both, - }; - base.AddInternal(shakeContainer); + base.AddInternal(shakeContainer = new ShakeContainer { RelativeSizeAxes = Axes.Both }); Alpha = 0; } @@ -72,10 +68,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - protected virtual void Shake() - { - shakeContainer.Shake(); - } + protected virtual void Shake() => shakeContainer.Shake(); } public enum ComboResult diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 3316fb5306..f90ae5c438 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -6,8 +6,14 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Graphics.Containers { + /// + /// A container that adds the ability to shake its contents. + /// public class ShakeContainer : Container { + /// + /// Shake the contents of this container. + /// public void Shake() { const float shake_amount = 8; From e0413526906881d5b15162eea09145b56f09f999 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 13:02:00 +0900 Subject: [PATCH 031/277] Add comment regarding add/clear/remove overrides --- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 1764d3c487..cc4a6ea547 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -25,7 +25,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Alpha = 0; } - // Forward all internal management to shakeContainer + // Forward all internal management to shakeContainer. + // This is a bit ugly but we don't have the concept of InternalContent so it'll have to do for now. (https://github.com/ppy/osu-framework/issues/1690) protected override void AddInternal(Drawable drawable) => shakeContainer.Add(drawable); protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); From 98410dbb6d3276d674bba5e5f77bdffd1e598b40 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 13:23:44 +0900 Subject: [PATCH 032/277] Reduce shake transform count by one for more aesthetic behaviour --- osu.Game/Graphics/Containers/ShakeContainer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index f90ae5c438..57544e8892 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -23,7 +23,6 @@ namespace osu.Game.Graphics.Containers .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() .MoveToX(0, shake_duration / 2, Easing.InSine); } } From 79af5cb0a03ad08af91e2b65ac14e847ad63d292 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 17:24:30 +0900 Subject: [PATCH 033/277] Limit shake duration to ensure it doesn't overlap miss window --- .../Objects/Drawables/DrawableHitCircle.cs | 2 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- .../Objects/Drawables/DrawableSliderHead.cs | 4 ++-- .../Graphics/Containers/ShakeContainer.cs | 22 ++++++++++++++----- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 79705356fa..212bc01ef9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables var result = HitObject.HitWindows.ResultFor(timeOffset); if (result == HitResult.None) { - Shake(); + Shake(Math.Abs(timeOffset) - HitObject.HitWindows.HalfWindowFor(HitResult.Miss)); return; } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index cc4a6ea547..89b81a02ac 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -69,7 +69,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - protected virtual void Shake() => shakeContainer.Shake(); + protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); } public enum ComboResult diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs index fbea927956..6d6cba4936 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderHead.cs @@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Position = slider.CurvePositionAt(completionProgress); } - public Action OnShake; + public Action OnShake; - protected override void Shake() => OnShake?.Invoke(); + protected override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength); } } diff --git a/osu.Game/Graphics/Containers/ShakeContainer.cs b/osu.Game/Graphics/Containers/ShakeContainer.cs index 57544e8892..fde4d59f46 100644 --- a/osu.Game/Graphics/Containers/ShakeContainer.cs +++ b/osu.Game/Graphics/Containers/ShakeContainer.cs @@ -14,16 +14,26 @@ namespace osu.Game.Graphics.Containers /// /// Shake the contents of this container. /// - public void Shake() + /// The maximum length the shake should last. + public void Shake(double maximumLength) { const float shake_amount = 8; const float shake_duration = 30; - this.MoveToX(shake_amount, shake_duration / 2, Easing.OutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then() - .MoveToX(0, shake_duration / 2, Easing.InSine); + // if we don't have enough time, don't bother shaking. + if (maximumLength < shake_duration * 2) + return; + + var sequence = this.MoveToX(shake_amount, shake_duration / 2, Easing.OutSine).Then() + .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + + // if we don't have enough time for the second shake, skip it. + if (maximumLength > shake_duration * 4) + sequence = sequence + .MoveToX(shake_amount, shake_duration, Easing.InOutSine).Then() + .MoveToX(-shake_amount, shake_duration, Easing.InOutSine).Then(); + + sequence.MoveToX(0, shake_duration / 2, Easing.InSine); } } } From 3005259d506342695e7760c0ff3be9b391cf6796 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Jul 2018 17:38:58 +0900 Subject: [PATCH 034/277] Add test for shaking --- .../TestCaseHitCircle.cs | 4 +++- .../TestCaseShaking.cs | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index 7af7140fd8..49c6978cdc 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.Tests } } - private class TestDrawableHitCircle : DrawableHitCircle + protected class TestDrawableHitCircle : DrawableHitCircle { private readonly bool auto; @@ -96,6 +96,8 @@ namespace osu.Game.Rulesets.Osu.Tests this.auto = auto; } + public void TriggerJudgement() => UpdateJudgement(true); + protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (auto && !userTriggered && timeOffset > 0) diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs new file mode 100644 index 0000000000..97978cff1e --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseShaking.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestCaseShaking : TestCaseHitCircle + { + public override void Add(Drawable drawable) + { + base.Add(drawable); + + if (drawable is TestDrawableHitCircle hitObject) + { + Scheduler.AddDelayed(() => hitObject.TriggerJudgement(), + hitObject.HitObject.StartTime - (hitObject.HitObject.HitWindows.HalfWindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current); + } + } + } +} From 699702f8d027eebba3e9a676539246f184deb690 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Mon, 9 Jul 2018 21:57:31 +0300 Subject: [PATCH 035/277] Use DesktopGameWindow.GetCurrentDisplay method --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 996b6a2a24..a67548d959 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.AvailableDisplayResolutions + var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.GetCurrentDisplay().AvailableResolutions .Where(r => r.Width >= 800 && r.Height >= 600) .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); From 8f9bf4bd3e4a4e4b5da5b3cc219d38036379d87a Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Tue, 10 Jul 2018 22:07:32 +0300 Subject: [PATCH 036/277] Remove redundant DesktopGameWindow cast --- .../Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index a67548d959..7fe628016c 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Platform; namespace osu.Game.Overlays.Settings.Sections.Graphics { @@ -126,9 +125,9 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private List> getResolutions() { - var availableDisplayResolutions = (game.Window as DesktopGameWindow)?.GetCurrentDisplay().AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + var availableDisplayResolutions = game.Window?.GetCurrentDisplay().AvailableResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); if (availableDisplayResolutions == null) return new List>(); From 0b66f63f7d436f518abbf0fe1c1b40546e492fdd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 15:35:32 +0900 Subject: [PATCH 037/277] Invert flow order of hitobjects between composer and mask layers --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 12 +++++++++++- .../Compose/Layers/HitObjectMaskLayer.cs | 18 ++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 0c91c9f548..1c55f0a09f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -28,6 +28,9 @@ namespace osu.Game.Rulesets.Edit private RulesetContainer rulesetContainer; private readonly List layerContainers = new List(); + public IEnumerable HitObjects => rulesetContainer.Playfield.HitObjects.Objects; + public IEnumerable AliveHitObjects => rulesetContainer.Playfield.HitObjects.AliveObjects; + private readonly IBindable beatmap = new Bindable(); protected HitObjectComposer(Ruleset ruleset) @@ -60,7 +63,7 @@ namespace osu.Game.Rulesets.Edit }; var layerAboveRuleset = CreateLayerContainer(); - layerAboveRuleset.Child = new HitObjectMaskLayer(rulesetContainer.Playfield, this); + layerAboveRuleset.Child = new HitObjectMaskLayer(); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -110,6 +113,13 @@ namespace osu.Game.Rulesets.Edit toolboxCollection.Items[0].Select(); } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(this); + return dependencies; + } + protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index b9a8e9914a..9e5b7300ab 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -8,30 +8,24 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Input; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Edit.Screens.Compose.Layers { public class HitObjectMaskLayer : CompositeDrawable { - private readonly Playfield playfield; - private readonly HitObjectComposer composer; - private MaskContainer maskContainer; + private HitObjectComposer composer; - public HitObjectMaskLayer(Playfield playfield, HitObjectComposer composer) + public HitObjectMaskLayer() { - // we need the playfield as HitObjects may not be initialised until its BDL. - this.playfield = playfield; - - this.composer = composer; - RelativeSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load() + private void load(HitObjectComposer composer) { + this.composer = composer; + maskContainer = new MaskContainer(); var maskSelection = composer.CreateMaskSelection(); @@ -54,7 +48,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers dragLayer.CreateProxy() }; - foreach (var obj in playfield.HitObjects.Objects) + foreach (var obj in composer.HitObjects) addMask(obj); } From 48190e3b5a055e7e0c17176d92171430b36349ef Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 15:48:51 +0900 Subject: [PATCH 038/277] Make NestedPlayfields non-null --- osu.Game/Rulesets/UI/Playfield.cs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index f2c9b49900..43999e3d29 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -1,10 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Rulesets.UI { @@ -15,11 +18,8 @@ namespace osu.Game.Rulesets.UI /// public HitObjectContainer HitObjects { get; private set; } - /// - /// All the s nested inside this playfield. - /// - public IReadOnlyList NestedPlayfields => nestedPlayfields; - private List nestedPlayfields; + private readonly Lazy> nestedPlayfields = new Lazy>(); + public IEnumerable NestedPlayfields => nestedPlayfields.IsValueCreated ? nestedPlayfields.Value : Enumerable.Empty(); /// /// A container for keeping track of DrawableHitObjects. @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI /// /// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield. /// - public virtual void PostProcess() => nestedPlayfields?.ForEach(p => p.PostProcess()); + public virtual void PostProcess() => NestedPlayfields.ForEach(p => p.PostProcess()); /// /// Adds a DrawableHitObject to this Playfield. @@ -67,13 +67,7 @@ namespace osu.Game.Rulesets.UI /// This does not add the to the draw hierarchy. /// /// The to add. - protected void AddNested(Playfield otherPlayfield) - { - if (nestedPlayfields == null) - nestedPlayfields = new List(); - - nestedPlayfields.Add(otherPlayfield); - } + protected void AddNested(Playfield otherPlayfield) => nestedPlayfields.Value.Add(otherPlayfield); /// /// Creates the container that will be used to contain the s. From 3905a9105c5bc1e563bd2a02704ee47015cc6914 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 15:51:10 +0900 Subject: [PATCH 039/277] Add a playfield method to retrieve all hitobjects --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 3 +-- osu.Game/Rulesets/UI/Playfield.cs | 13 +++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 1c55f0a09f..8b199c7e02 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -28,8 +28,7 @@ namespace osu.Game.Rulesets.Edit private RulesetContainer rulesetContainer; private readonly List layerContainers = new List(); - public IEnumerable HitObjects => rulesetContainer.Playfield.HitObjects.Objects; - public IEnumerable AliveHitObjects => rulesetContainer.Playfield.HitObjects.AliveObjects; + public IEnumerable HitObjects => rulesetContainer.Playfield.AllHitObjects; private readonly IBindable beatmap = new Bindable(); diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 43999e3d29..7a7360afe2 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -14,13 +14,22 @@ namespace osu.Game.Rulesets.UI public abstract class Playfield : ScalableContainer { /// - /// The HitObjects contained in this Playfield. + /// The contained in this Playfield. /// public HitObjectContainer HitObjects { get; private set; } - private readonly Lazy> nestedPlayfields = new Lazy>(); + /// + /// All the s contained in this and all . + /// + public IEnumerable AllHitObjects => HitObjects?.Objects.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects)) ?? Enumerable.Empty(); + + /// + /// All s nested inside this . + /// public IEnumerable NestedPlayfields => nestedPlayfields.IsValueCreated ? nestedPlayfields.Value : Enumerable.Empty(); + private readonly Lazy> nestedPlayfields = new Lazy>(); + /// /// A container for keeping track of DrawableHitObjects. /// From 48c1561676540486e59e03cfd6c4cb0f10445bcb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 16:01:14 +0900 Subject: [PATCH 040/277] Remove now unnecessary mask layer --- .../Edit/Layers/ManiaHitObjectMaskLayer.cs | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs b/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs deleted file mode 100644 index a2df612d79..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/Layers/ManiaHitObjectMaskLayer.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Game.Screens.Edit.Screens.Compose.Layers; -using OpenTK; - -namespace osu.Game.Rulesets.Mania.Edit.Layers -{ - public class ManiaHitObjectMaskLayer : HitObjectMaskLayer - { - public readonly IBindable Inverted = new Bindable(); - - public ManiaHitObjectMaskLayer() - { - Inverted.ValueChanged += invertedChanged; - } - - private void invertedChanged(bool newValue) - { - Scale = new Vector2(1, newValue ? -1 : 1); - } - } -} From c51fe6a119c60414a994a4848ebe58fa1d1153c3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 16:01:47 +0900 Subject: [PATCH 041/277] Remove more unused stuff --- .../Edit/ManiaHitObjectComposer.cs | 4 ---- .../Screens/Compose/Layers/HitObjectMaskLayer.cs | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index 03553480d9..b1968d0aff 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -10,8 +10,6 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using System.Collections.Generic; -using osu.Game.Rulesets.Mania.Edit.Layers; -using osu.Game.Screens.Edit.Screens.Compose.Layers; namespace osu.Game.Rulesets.Mania.Edit { @@ -42,7 +40,5 @@ namespace osu.Game.Rulesets.Mania.Edit return base.CreateMaskFor(hitObject); } - - protected override HitObjectMaskLayer CreateHitObjectMaskLayer() => new ManiaHitObjectMaskLayer(); } } diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index 6d73c03cad..db4ea05e59 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -72,18 +71,5 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers maskContainer.Add(mask); } - - /// - /// Removes the mask for a . - /// - /// The to remove the mask for. - private void removeMask(DrawableHitObject hitObject) - { - var mask = maskContainer.FirstOrDefault(h => h.HitObject == hitObject); - if (mask == null) - return; - - maskContainer.Remove(mask); - } } } From 9b7d01397b7f8aedeadc1866c55d6a261211df19 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 16:53:32 +0900 Subject: [PATCH 042/277] Add ruleset config to HitObjectComposer --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 18a84ccee0..2301620116 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Logging; using osu.Framework.Timing; using osu.Game.Beatmaps; +using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Edit.Tools; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; @@ -25,6 +26,8 @@ namespace osu.Game.Rulesets.Edit protected ICompositionTool CurrentTool { get; private set; } + protected IRulesetConfigManager Config { get; private set; } + protected RulesetContainer RulesetContainer; private readonly List layerContainers = new List(); @@ -115,7 +118,10 @@ namespace osu.Game.Rulesets.Edit protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(this); + Config = dependencies.Get().GetConfigFor(ruleset); + return dependencies; } From 54e288f09b8953514b5d28dae5e3d2b4777ff7a8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Jul 2018 16:55:50 +0900 Subject: [PATCH 043/277] Correctly give note masks a scrolling info --- .../Edit/ManiaHitObjectComposer.cs | 12 ++++++++++ .../UI/ManiaRulesetContainer.cs | 19 ++++----------- .../UI/ManiaScrollingInfo.cs | 23 +++++++++++++++++++ 3 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs index b1968d0aff..f37d8134ce 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaHitObjectComposer.cs @@ -10,16 +10,28 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; namespace osu.Game.Rulesets.Mania.Edit { public class ManiaHitObjectComposer : HitObjectComposer { + protected new ManiaConfigManager Config => (ManiaConfigManager)base.Config; + public ManiaHitObjectComposer(Ruleset ruleset) : base(ruleset) { } + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + { + var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + dependencies.CacheAs(new ManiaScrollingInfo(Config)); + return dependencies; + } + protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new ManiaEditRulesetContainer(ruleset, beatmap); protected override IReadOnlyList CompositionTools => new ICompositionTool[] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 810a6fad9b..09ebde2799 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; -using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -35,9 +34,7 @@ namespace osu.Game.Rulesets.Mania.UI public IEnumerable BarLines; - private readonly Bindable configDirection = new Bindable(); - private ManiaScrollingInfo scrollingInfo; - protected IScrollingInfo ScrollingInfo => scrollingInfo; + protected new ManiaConfigManager Config => (ManiaConfigManager)base.Config; public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) : base(ruleset, beatmap) @@ -74,9 +71,6 @@ namespace osu.Game.Rulesets.Mania.UI private void load() { BarLines.ForEach(Playfield.Add); - - ((ManiaConfigManager)Config).BindWith(ManiaSetting.ScrollDirection, configDirection); - configDirection.BindValueChanged(d => scrollingInfo.Direction.Value = (ScrollingDirection)d, true); } private DependencyContainer dependencies; @@ -84,7 +78,10 @@ namespace osu.Game.Rulesets.Mania.UI protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(scrollingInfo = new ManiaScrollingInfo()); + + if (dependencies.Get() == null) + dependencies.CacheAs(new ManiaScrollingInfo(Config)); + return dependencies; } @@ -116,11 +113,5 @@ namespace osu.Game.Rulesets.Mania.UI protected override Vector2 PlayfieldArea => new Vector2(1, 0.8f); protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay); - - private class ManiaScrollingInfo : IScrollingInfo - { - public readonly Bindable Direction = new Bindable(); - IBindable IScrollingInfo.Direction => Direction; - } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs new file mode 100644 index 0000000000..a1cc7cfbc7 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class ManiaScrollingInfo : IScrollingInfo + { + private readonly Bindable configDirection = new Bindable(); + + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; + + public ManiaScrollingInfo(ManiaConfigManager config) + { + config.BindWith(ManiaSetting.ScrollDirection, configDirection); + configDirection.BindValueChanged(v => Direction.Value = (ScrollingDirection)v); + } + } +} From b7721edc80d1620b49be12956bfcc767aaf61403 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Jul 2018 17:04:51 +0900 Subject: [PATCH 044/277] Remove more unnecessary changes --- .../Layers/Selection/Overlays/HoldNoteMask.cs | 4 --- .../Layers/Selection/Overlays/NoteMask.cs | 2 -- .../Edit/ManiaEditPlayfield.cs | 5 --- .../Edit/ManiaEditRulesetContainer.cs | 3 -- .../Edit/ManiaEditStage.cs | 16 --------- .../Objects/ManiaHitObject.cs | 34 ++----------------- .../Objects/Types/IHasColumn.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 27 ++------------- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 4 +-- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 31 +++++++---------- osu.Game/Rulesets/Edit/HitObjectMask.cs | 22 +----------- .../Edit/Tools/HitObjectCompositionTool.cs | 11 ++---- .../Rulesets/Edit/Types/IHasEditableColumn.cs | 12 ------- .../Compose/Layers/HitObjectMaskLayer.cs | 2 -- .../Screens/Compose/Layers/MaskContainer.cs | 16 --------- .../Screens/Compose/Layers/MaskSelection.cs | 10 ------ 16 files changed, 22 insertions(+), 179 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs rename {osu.Game/Rulesets => osu.Game.Rulesets.Mania}/Objects/Types/IHasColumn.cs (90%) delete mode 100644 osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index 648ec29e64..d0faea564c 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays public HoldNoteMask(DrawableHoldNote hold) : base(hold) { - var holdObject = hold.HitObject; - InternalChildren = new Drawable[] { new HoldNoteNoteMask(hold.Head), @@ -29,8 +27,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays AccentColour = Color4.Transparent }, }; - - holdObject.ColumnChanged += _ => Position = hold.Position; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs index 8c46e20835..78f876cb14 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/NoteMask.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays Masking = true; AddInternal(new NotePiece()); - - note.HitObject.ColumnChanged += _ => Position = note.Position; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs index 30ff591359..e7bc526471 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditPlayfield.cs @@ -9,14 +9,9 @@ namespace osu.Game.Rulesets.Mania.Edit { public class ManiaEditPlayfield : ManiaPlayfield { - protected override bool DisplayJudgements => false; - public ManiaEditPlayfield(List stages) : base(stages) { } - - protected override ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - => new ManiaEditStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction); } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs index fa33f41de3..a01947a60b 100644 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/Edit/ManiaEditRulesetContainer.cs @@ -3,7 +3,6 @@ using osu.Framework.Graphics; using OpenTK; -using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.UI; @@ -24,7 +23,5 @@ namespace osu.Game.Rulesets.Mania.Edit }; protected override Vector2 PlayfieldArea => Vector2.One; - - protected override CursorContainer CreateCursor() => null; } } diff --git a/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs b/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs deleted file mode 100644 index 9068725023..0000000000 --- a/osu.Game.Rulesets.Mania/Edit/ManiaEditStage.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Mania.Beatmaps; -using osu.Game.Rulesets.Mania.UI; - -namespace osu.Game.Rulesets.Mania.Edit -{ - public class ManiaEditStage : ManiaStage - { - public ManiaEditStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - : base(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction) - { - } - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 4d28c39faa..e183098a51 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,42 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Edit.Types; +using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Types; -using System; namespace osu.Game.Rulesets.Mania.Objects { - public abstract class ManiaHitObject : HitObject, IHasXPosition, IHasEditableColumn + public abstract class ManiaHitObject : HitObject, IHasColumn { - public event Action ColumnChanged; - - private int column { get; set; } - - public virtual int Column - { - get => column; - set - { - if (column == value) - return; - column = value; - - ColumnChanged?.Invoke(value); - } - } - - public virtual int Layer { get; set; } - - public virtual float X - { - get => Column; - } - - public virtual void OffsetColumn(int offset) => Column += offset; - - public virtual void OffsetLayer(int offset) => Layer += offset; + public virtual int Column { get; set; } protected override HitWindows CreateHitWindows() => new ManiaHitWindows(); } diff --git a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs similarity index 90% rename from osu.Game/Rulesets/Objects/Types/IHasColumn.cs rename to osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs index ba9c7ac933..44a79de7db 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasColumn.cs +++ b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Rulesets.Objects.Types +namespace osu.Game.Rulesets.Mania.Objects.Types { /// /// A type of hit object which lies in one of a number of predetermined columns. diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index b3d11307a7..57a00f3820 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -4,25 +4,18 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; using System; using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : ManiaScrollingPlayfield { - public List Columns => stages.SelectMany(x => x.Columns).ToList(); - private readonly List stages = new List(); - public IReadOnlyList Stages => stages; - - protected virtual bool DisplayJudgements => true; public ManiaPlayfield(List stageDefinitions) { @@ -44,8 +37,7 @@ namespace osu.Game.Rulesets.Mania.UI int firstColumnIndex = 0; for (int i = 0; i < stageDefinitions.Count; i++) { - var newStage = CreateStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); - newStage.DisplayJudgements = DisplayJudgements; + var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); newStage.VisibleTimeRange.BindTo(VisibleTimeRange); playfieldGrid.Content[0][i] = newStage; @@ -57,11 +49,7 @@ namespace osu.Game.Rulesets.Mania.UI } } - public override void Add(DrawableHitObject h) - { - h.OnJudgement += OnJudgement; - getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h); - } + public override void Add(DrawableHitObject h) => getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h); public void Add(BarLine barline) => stages.ForEach(s => s.Add(barline)); @@ -83,16 +71,5 @@ namespace osu.Game.Rulesets.Mania.UI { maniaConfig.BindWith(ManiaSetting.ScrollTime, VisibleTimeRange); } - - internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) - { - if (!judgedObject.DisplayJudgement || !DisplayJudgements) - return; - - getStageByColumn(((ManiaHitObject)judgedObject.HitObject).Column).OnJudgement(judgedObject, judgement); - } - - protected virtual ManiaStage CreateStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) - => new ManiaStage(firstColumnIndex, definition, ref normalColumnStartAction, ref specialColumnStartAction); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 867eb1214b..b22217b73a 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -23,12 +23,10 @@ namespace osu.Game.Rulesets.Mania.UI /// /// A collection of s. /// - public class ManiaStage : ScrollingPlayfield + public class ManiaStage : ManiaScrollingPlayfield { public const float HIT_TARGET_POSITION = 50; - - public bool DisplayJudgements = true; public IReadOnlyList Columns => columnFlow.Children; private readonly FillFlowContainer columnFlow; diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 2301620116..a36f703fe6 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -24,17 +24,16 @@ namespace osu.Game.Rulesets.Edit { private readonly Ruleset ruleset; - protected ICompositionTool CurrentTool { get; private set; } + public IEnumerable HitObjects => rulesetContainer.Playfield.AllHitObjects; + protected ICompositionTool CurrentTool { get; private set; } protected IRulesetConfigManager Config { get; private set; } - protected RulesetContainer RulesetContainer; private readonly List layerContainers = new List(); - - public IEnumerable HitObjects => RulesetContainer.Playfield.AllHitObjects; - private readonly IBindable beatmap = new Bindable(); + private RulesetContainer rulesetContainer; + protected HitObjectComposer(Ruleset ruleset) { this.ruleset = ruleset; @@ -49,8 +48,8 @@ namespace osu.Game.Rulesets.Edit try { - RulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value); - RulesetContainer.Clock = framedClock; + rulesetContainer = CreateRulesetContainer(ruleset, beatmap.Value); + rulesetContainer.Clock = framedClock; } catch (Exception e) { @@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Edit }; var layerAboveRuleset = CreateLayerContainer(); - layerAboveRuleset.Child = CreateHitObjectMaskLayer(); + layerAboveRuleset.Child = new HitObjectMaskLayer(); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -95,7 +94,7 @@ namespace osu.Game.Rulesets.Edit Children = new Drawable[] { layerBelowRuleset, - RulesetContainer, + rulesetContainer, layerAboveRuleset } } @@ -131,14 +130,13 @@ namespace osu.Game.Rulesets.Edit layerContainers.ForEach(l => { - l.Anchor = RulesetContainer.Playfield.Anchor; - l.Origin = RulesetContainer.Playfield.Origin; - l.Position = RulesetContainer.Playfield.Position; - l.Size = RulesetContainer.Playfield.Size; + l.Anchor = rulesetContainer.Playfield.Anchor; + l.Origin = rulesetContainer.Playfield.Origin; + l.Position = rulesetContainer.Playfield.Position; + l.Size = rulesetContainer.Playfield.Size; }); } - private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool; protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap); @@ -157,11 +155,6 @@ namespace osu.Game.Rulesets.Edit /// public virtual MaskSelection CreateMaskSelection() => new MaskSelection(); - /// - /// Creates a depending on the ruleset. - /// - protected virtual HitObjectMaskLayer CreateHitObjectMaskLayer() => new HitObjectMaskLayer(); - /// /// Creates a which provides a layer above or below the . /// diff --git a/osu.Game/Rulesets/Edit/HitObjectMask.cs b/osu.Game/Rulesets/Edit/HitObjectMask.cs index 3caa4d9fbf..61fb700dd3 100644 --- a/osu.Game/Rulesets/Edit/HitObjectMask.cs +++ b/osu.Game/Rulesets/Edit/HitObjectMask.cs @@ -33,21 +33,11 @@ namespace osu.Game.Rulesets.Edit /// public event Action SelectionRequested; - /// - /// Invoked when this has started drag. - /// - public event Action DragStarted; - /// /// Invoked when this has requested drag. /// public event Action DragRequested; - /// - /// Invoked when this has ended drag. - /// - public event Action DragEnded; - /// /// The which this applies to. /// @@ -130,11 +120,7 @@ namespace osu.Game.Rulesets.Edit return base.OnClick(state); } - protected override bool OnDragStart(InputState state) - { - DragStarted?.Invoke(this, state); - return true; - } + protected override bool OnDragStart(InputState state) => true; protected override bool OnDrag(InputState state) { @@ -142,12 +128,6 @@ namespace osu.Game.Rulesets.Edit return true; } - protected override bool OnDragEnd(InputState state) - { - DragEnded?.Invoke(this, state); - return true; - } - /// /// The screen-space point that causes this to be selected. /// diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index 91062a211e..78ad236e74 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; -using osu.Framework.Input; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Edit.Tools @@ -10,15 +8,10 @@ namespace osu.Game.Rulesets.Edit.Tools public class HitObjectCompositionTool : ICompositionTool where T : HitObject { - public string Name { get; } = typeof(T).Name; - - public Func OnMouseDown; - public Func OnMouseUp; - public Func OnDragStart; - public Func OnDragRequested; - public Func OnDragEnd; + public string Name { get; } public HitObjectCompositionTool() + : this(typeof(T).Name) { } diff --git a/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs b/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs deleted file mode 100644 index 2691223476..0000000000 --- a/osu.Game/Rulesets/Edit/Types/IHasEditableColumn.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Edit.Types -{ - public interface IHasEditableColumn : IHasColumn - { - void OffsetColumn(int offset); - } -} diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs index db4ea05e59..41987a6bf9 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/HitObjectMaskLayer.cs @@ -32,9 +32,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers maskContainer.MaskSelected += maskSelection.HandleSelected; maskContainer.MaskDeselected += maskSelection.HandleDeselected; maskContainer.MaskSelectionRequested += maskSelection.HandleSelectionRequested; - maskContainer.MaskDragStarted += maskSelection.HandleDragStart; maskContainer.MaskDragRequested += maskSelection.HandleDrag; - maskContainer.MaskDragEnded += maskSelection.HandleDragEnd; maskSelection.DeselectAll = maskContainer.DeselectAll; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs index bce6d876be..df2691c28e 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskContainer.cs @@ -29,21 +29,11 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers /// public event Action MaskSelectionRequested; - /// - /// Invoked when any starts drag. - /// - public event Action MaskDragStarted; - /// /// Invoked when any requests drag. /// public event Action MaskDragRequested; - /// - /// Invoked when any ends drag. - /// - public event Action MaskDragEnded; - private IEnumerable aliveMasks => AliveInternalChildren.Cast(); public MaskContainer() @@ -60,9 +50,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers drawable.Selected += onMaskSelected; drawable.Deselected += onMaskDeselected; drawable.SelectionRequested += onSelectionRequested; - drawable.DragStarted += onDragStarted; drawable.DragRequested += onDragRequested; - drawable.DragEnded += onDragEnded; } public override bool Remove(HitObjectMask drawable) @@ -76,9 +64,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers drawable.Selected -= onMaskSelected; drawable.Deselected -= onMaskDeselected; drawable.SelectionRequested -= onSelectionRequested; - drawable.DragStarted -= onDragStarted; drawable.DragRequested -= onDragRequested; - drawable.DragEnded -= onDragEnded; } return result; @@ -117,9 +103,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers } private void onSelectionRequested(HitObjectMask mask, InputState state) => MaskSelectionRequested?.Invoke(mask, state); - private void onDragStarted(HitObjectMask mask, InputState state) => MaskDragStarted?.Invoke(mask, state); private void onDragRequested(HitObjectMask mask, InputState state) => MaskDragRequested?.Invoke(mask, state); - private void onDragEnded(HitObjectMask mask, InputState state) => MaskDragEnded?.Invoke(mask, state); protected override int Compare(Drawable x, Drawable y) { diff --git a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs index 7cd77eeb1c..54697bad77 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Layers/MaskSelection.cs @@ -25,7 +25,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers private readonly List selectedMasks; private Drawable outline; - private Vector2 startingPosition; public MaskSelection() { @@ -55,7 +54,6 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers #region User Input Handling - public void HandleDragStart(HitObjectMask m, InputState state) => startingPosition = state.Mouse.Position; public void HandleDrag(HitObjectMask m, InputState state) { // Todo: Various forms of snapping @@ -67,17 +65,9 @@ namespace osu.Game.Screens.Edit.Screens.Compose.Layers case IHasEditablePosition editablePosition: editablePosition.OffsetPosition(state.Mouse.Delta); break; - case IHasEditableColumn editableColumn: - if (IsDragged) - editableColumn.OffsetColumn((int)((startingPosition.X - state.Mouse.Position.X) / m.Width)); // Perform snapping, needs fixing - break; } } } - public void HandleDragEnd(HitObjectMask m, InputState state) - { - - } #endregion From be297ddf76b51cfa108f2d30e7d9563575dc105a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Jul 2018 19:30:20 +0900 Subject: [PATCH 045/277] Fix direction reversal not quite working correctly --- .../TestCaseEditor.cs | 15 ++++++++++++ .../Layers/Selection/Overlays/HoldNoteMask.cs | 23 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs index 799bb9efd8..6c0f931cda 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseEditor.cs @@ -2,6 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.Mania.UI; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -9,9 +13,20 @@ namespace osu.Game.Rulesets.Mania.Tests [TestFixture] public class TestCaseEditor : EditorTestCase { + private readonly Bindable direction = new Bindable(); + public TestCaseEditor() : base(new ManiaRuleset()) { + AddStep("upwards scroll", () => direction.Value = ManiaScrollingDirection.Up); + AddStep("downwards scroll", () => direction.Value = ManiaScrollingDirection.Down); + } + + [BackgroundDependencyLoader] + private void load(RulesetConfigCache configCache) + { + var config = (ManiaConfigManager)configCache.GetConfigFor(Ruleset.Value.CreateInstance()); + config.BindWith(ManiaSetting.ScrollDirection, direction); } } } diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index d0faea564c..745ce25a3e 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -2,17 +2,25 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { public class HoldNoteMask : HitObjectMask { + public new DrawableHoldNote HitObject => (DrawableHoldNote)base.HitObject; + + private readonly IBindable direction = new Bindable(); + private readonly BodyPiece body; public HoldNoteMask(DrawableHoldNote hold) @@ -30,17 +38,25 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, IScrollingInfo scrollingInfo) { body.BorderColour = colours.Yellow; + + direction.BindTo(scrollingInfo.Direction); } protected override void Update() { base.Update(); - Size = HitObject.DrawSize; + Size = HitObject.DrawSize + new Vector2(0, HitObject.Tail.DrawHeight); Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.TopLeft); + + // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do + // When scrolling upwards our origin is at the top of the head note (which is where the origin already is), + // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) + if (direction.Value == ScrollingDirection.Down) + Y -= HitObject.Tail.DrawHeight; } private class HoldNoteNoteMask : NoteMask @@ -55,6 +71,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays { base.Update(); + Anchor = HitObject.Anchor; + Origin = HitObject.Origin; + Position = HitObject.DrawPosition; } } From c3c270621bf93b0916f871a18376df62af8e0932 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Jul 2018 19:32:47 +0900 Subject: [PATCH 046/277] Fix hold note note masks blocking mouse input --- .../Edit/Layers/Selection/Overlays/HoldNoteMask.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index 745ce25a3e..4b13bce39d 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -76,6 +76,9 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays Position = HitObject.DrawPosition; } + + // Todo: This is temporary, since the note masks don't do anything special yet. In the future they will handle input. + public override bool HandleMouseInput => false; } } } From 824c217a0d837a75e6b01987bbe0578f93bd4918 Mon Sep 17 00:00:00 2001 From: Dan Balasescu <1329837+smoogipoo@users.noreply.github.com> Date: Thu, 19 Jul 2018 19:44:06 +0900 Subject: [PATCH 047/277] Adjust comment --- .../Edit/Layers/Selection/Overlays/HoldNoteMask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs index 4b13bce39d..bfa6bc0a17 100644 --- a/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs +++ b/osu.Game.Rulesets.Mania/Edit/Layers/Selection/Overlays/HoldNoteMask.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Layers.Selection.Overlays Position = Parent.ToLocalSpace(HitObject.ScreenSpaceDrawQuad.TopLeft); // This is a side-effect of not matching the hitobject's anchors/origins, which is kinda hard to do - // When scrolling upwards our origin is at the top of the head note (which is where the origin already is), + // When scrolling upwards our origin is already at the top of the head note (which is the intended location), // but when scrolling downwards our origin is at the _bottom_ of the tail note (where we need to be at the _top_ of the tail note) if (direction.Value == ScrollingDirection.Down) Y -= HitObject.Tail.DrawHeight; From 7b4616c6c1799c339585fd84afcabf7c62a1c37d Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 20 Jul 2018 14:02:02 +0300 Subject: [PATCH 048/277] Add circular button file --- .../Components/OsuSetupCircularButton.cs | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs new file mode 100644 index 0000000000..ae22f38a08 --- /dev/null +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs @@ -0,0 +1,133 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using System; + +namespace osu.Game.Screens.Edit.Screens.Setup.Components +{ + public class OsuSetupCircularButton : Container, IHasAccentColour + { + private readonly Box fill; + private readonly OsuSpriteText label; + + public const float DEFAULT_LABEL_TEXT_SIZE = 14; + public const float SIZE_X = 125; + public const float SIZE_Y = 30; + + public event Action ButtonClicked; + + private bool disabled; + public bool Disabled + { + get => disabled; + set + { + disabled = value; + fadeColour(); + } + } + + private Color4 defaultColour; + public Color4 DefaultColour + { + get => defaultColour; + set + { + defaultColour = value; + fadeColour(); + } + } + + private Color4 accentColour; + public Color4 AccentColour + { + get => accentColour; + set + { + accentColour = value; + fill.Colour = value; + } + } + + private string labelText; + public string LabelText + { + get => labelText; + set + { + labelText = value; + label.Text = value; + } + } + + public OsuSetupCircularButton() + { + Size = new Vector2(SIZE_X, SIZE_Y); + CornerRadius = 15; + Masking = true; + + Children = new Drawable[] + { + fill = new Box + { + RelativeSizeAxes = Axes.Both, + AlwaysPresent = true, + }, + label = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Colour = Color4.White, + TextSize = DEFAULT_LABEL_TEXT_SIZE, + Text = LabelText, + Font = @"Exo2.0-Bold", + } + }; + } + + protected override void LoadComplete() + { + FadeEdgeEffectTo(0); + } + + protected override bool OnClick(InputState state) + { + // Effect to indicate the button has been clicked + if (!disabled) + ButtonClicked?.Invoke(); + return base.OnClick(state); + } + + protected override bool OnHover(InputState state) + { + fadeColour(); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + fadeColour(); + base.OnHoverLost(state); + } + + private void fadeColour() + { + if (!disabled) + { + this.FadeAccent(defaultColour.Lighten(IsHovered ? 0.3f : 0), 500, Easing.OutQuint); + this.FadeTo(1, 500, Easing.OutQuint); + } + else + this.FadeTo(0.3f, 500, Easing.OutQuint); + } + } +} From 4d0d4523ca83c47346758532f28bcfade7c044ae Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 24 Jul 2018 11:23:38 +0300 Subject: [PATCH 049/277] Add test case, rename component --- .../TestCaseEditorSetupCircularButton.cs | 38 +++++++++++++++++++ ...rcularButton.cs => SetupCircularButton.cs} | 4 +- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs rename osu.Game/Screens/Edit/Screens/Setup/Components/{OsuSetupCircularButton.cs => SetupCircularButton.cs} (96%) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs new file mode 100644 index 0000000000..77cc6dbb9d --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Screens.Edit.Screens.Setup.Components; +using System; +using System.Collections.Generic; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseEditorSetupCircularButton : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SetupCircularButton) + }; + + private readonly SetupCircularButton circularButton; + + public TestCaseEditorSetupCircularButton() + { + Child = circularButton = new SetupCircularButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + LabelText = "Button", + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour osuColour) + { + circularButton.DefaultColour = osuColour.Blue; + } + } +} diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs similarity index 96% rename from osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs rename to osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index ae22f38a08..877c398be8 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/OsuSetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -14,7 +14,7 @@ using System; namespace osu.Game.Screens.Edit.Screens.Setup.Components { - public class OsuSetupCircularButton : Container, IHasAccentColour + public class SetupCircularButton : Container, IHasAccentColour { private readonly Box fill; private readonly OsuSpriteText label; @@ -69,7 +69,7 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components } } - public OsuSetupCircularButton() + public SetupCircularButton() { Size = new Vector2(SIZE_X, SIZE_Y); CornerRadius = 15; From ebf14c9c936a205e5ad4ac4193868250cc95b2ca Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Tue, 24 Jul 2018 11:32:24 +0300 Subject: [PATCH 050/277] Update framework from current master --- .../Edit/Screens/Setup/Components/SetupCircularButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 877c398be8..da238398fa 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -7,7 +7,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; +using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using System; From 2a819a53c093c3d28e1e7c4e79a089a36ec4a2f7 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 27 Jul 2018 12:26:37 +0300 Subject: [PATCH 051/277] Prefer inheriting TriangleButton instead of Container --- .../TestCaseEditorSetupCircularButton.cs | 5 +- .../Setup/Components/SetupCircularButton.cs | 74 ++++--------------- 2 files changed, 17 insertions(+), 62 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs index 77cc6dbb9d..14649e9d79 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs @@ -27,12 +27,15 @@ namespace osu.Game.Tests.Visual Origin = Anchor.Centre, LabelText = "Button", }; + + AddStep("Enable button", () => circularButton.Enabled.Value = true); + AddStep("Disable button", () => circularButton.Enabled.Value = false); } [BackgroundDependencyLoader] private void load(OsuColour osuColour) { - circularButton.DefaultColour = osuColour.Blue; + circularButton.AccentColour = osuColour.Blue; } } } diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index da238398fa..186d1cc223 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -3,6 +3,7 @@ using OpenTK; using OpenTK.Graphics; +using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,11 +11,12 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using System; namespace osu.Game.Screens.Edit.Screens.Setup.Components { - public class SetupCircularButton : Container, IHasAccentColour + public class SetupCircularButton : TriangleButton, IHasAccentColour { private readonly Box fill; private readonly OsuSpriteText label; @@ -25,28 +27,6 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components public event Action ButtonClicked; - private bool disabled; - public bool Disabled - { - get => disabled; - set - { - disabled = value; - fadeColour(); - } - } - - private Color4 defaultColour; - public Color4 DefaultColour - { - get => defaultColour; - set - { - defaultColour = value; - fadeColour(); - } - } - private Color4 accentColour; public Color4 AccentColour { @@ -57,23 +37,16 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components fill.Colour = value; } } - - private string labelText; + public string LabelText { - get => labelText; - set - { - labelText = value; - label.Text = value; - } + get => label.Text; + set => label.Text = value; } public SetupCircularButton() { Size = new Vector2(SIZE_X, SIZE_Y); - CornerRadius = 15; - Masking = true; Children = new Drawable[] { @@ -88,46 +61,25 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components Origin = Anchor.Centre, Colour = Color4.White, TextSize = DEFAULT_LABEL_TEXT_SIZE, - Text = LabelText, Font = @"Exo2.0-Bold", } }; + + Enabled.Value = true; } - protected override void LoadComplete() + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - FadeEdgeEffectTo(0); + Triangles.Alpha = 0; + Content.CornerRadius = 15; } protected override bool OnClick(InputState state) { - // Effect to indicate the button has been clicked - if (!disabled) + if (Enabled.Value) ButtonClicked?.Invoke(); return base.OnClick(state); } - - protected override bool OnHover(InputState state) - { - fadeColour(); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - fadeColour(); - base.OnHoverLost(state); - } - - private void fadeColour() - { - if (!disabled) - { - this.FadeAccent(defaultColour.Lighten(IsHovered ? 0.3f : 0), 500, Easing.OutQuint); - this.FadeTo(1, 500, Easing.OutQuint); - } - else - this.FadeTo(0.3f, 500, Easing.OutQuint); - } } } From 3ee1353976c7647e24104f86e657ea1a9af1a664 Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 27 Jul 2018 12:28:47 +0300 Subject: [PATCH 052/277] Remove whitespace --- .../Edit/Screens/Setup/Components/SetupCircularButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 186d1cc223..51f67b2f27 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components fill.Colour = value; } } - + public string LabelText { get => label.Text; From 78cde951323e20a7543b41737e4ee5dc7e9eca0f Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 27 Jul 2018 12:34:11 +0300 Subject: [PATCH 053/277] Privatise constants --- .../Screens/Setup/Components/SetupCircularButton.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 51f67b2f27..cb4f5b6864 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -21,9 +21,9 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components private readonly Box fill; private readonly OsuSpriteText label; - public const float DEFAULT_LABEL_TEXT_SIZE = 14; - public const float SIZE_X = 125; - public const float SIZE_Y = 30; + private const float default_label_text_size = 14; + private const float size_x = 125; + private const float size_y = 30; public event Action ButtonClicked; @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components public SetupCircularButton() { - Size = new Vector2(SIZE_X, SIZE_Y); + Size = new Vector2(size_x, size_y); Children = new Drawable[] { @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components Anchor = Anchor.Centre, Origin = Anchor.Centre, Colour = Color4.White, - TextSize = DEFAULT_LABEL_TEXT_SIZE, + TextSize = default_label_text_size, Font = @"Exo2.0-Bold", } }; From 1962797e206563a113755ca9e905e84bd7221bcf Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 27 Jul 2018 12:40:38 +0300 Subject: [PATCH 054/277] Remove unnecessary using directive --- .../Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index cb4f5b6864..cd748df005 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -4,7 +4,6 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; From 93cf063c97b1da6bc22732594d76fe796f16a4fd Mon Sep 17 00:00:00 2001 From: AlFasGD Date: Fri, 27 Jul 2018 12:52:33 +0300 Subject: [PATCH 055/277] Remove useless things --- .../Edit/Screens/Setup/Components/SetupCircularButton.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index cd748df005..873a176d3d 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -5,7 +5,6 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.States; using osu.Game.Graphics; @@ -68,7 +67,7 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Triangles.Alpha = 0; Content.CornerRadius = 15; From c5a772bbc8c7035fd3c7bb45f1b8390af1b4d107 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 31 Jul 2018 15:49:04 +0900 Subject: [PATCH 056/277] Completely reuse TriangleButton --- .../TestCaseEditorSetupCircularButton.cs | 15 ++--- .../Setup/Components/SetupCircularButton.cs | 58 +------------------ 2 files changed, 5 insertions(+), 68 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs index 14649e9d79..ce3ae349b9 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs @@ -1,9 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Graphics; using osu.Game.Screens.Edit.Screens.Setup.Components; using System; using System.Collections.Generic; @@ -17,25 +15,20 @@ namespace osu.Game.Tests.Visual typeof(SetupCircularButton) }; - private readonly SetupCircularButton circularButton; - public TestCaseEditorSetupCircularButton() { + SetupCircularButton circularButton; + Child = circularButton = new SetupCircularButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, - LabelText = "Button", + Text = "Button", + Action = () => { } }; AddStep("Enable button", () => circularButton.Enabled.Value = true); AddStep("Disable button", () => circularButton.Enabled.Value = false); } - - [BackgroundDependencyLoader] - private void load(OsuColour osuColour) - { - circularButton.AccentColour = osuColour.Blue; - } } } diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 873a176d3d..0697e62224 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -2,68 +2,19 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.States; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using System; namespace osu.Game.Screens.Edit.Screens.Setup.Components { - public class SetupCircularButton : TriangleButton, IHasAccentColour + public class SetupCircularButton : TriangleButton { - private readonly Box fill; - private readonly OsuSpriteText label; - - private const float default_label_text_size = 14; private const float size_x = 125; private const float size_y = 30; - public event Action ButtonClicked; - - private Color4 accentColour; - public Color4 AccentColour - { - get => accentColour; - set - { - accentColour = value; - fill.Colour = value; - } - } - - public string LabelText - { - get => label.Text; - set => label.Text = value; - } - public SetupCircularButton() { Size = new Vector2(size_x, size_y); - - Children = new Drawable[] - { - fill = new Box - { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, - }, - label = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Colour = Color4.White, - TextSize = default_label_text_size, - Font = @"Exo2.0-Bold", - } - }; - - Enabled.Value = true; } [BackgroundDependencyLoader] @@ -72,12 +23,5 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components Triangles.Alpha = 0; Content.CornerRadius = 15; } - - protected override bool OnClick(InputState state) - { - if (Enabled.Value) - ButtonClicked?.Invoke(); - return base.OnClick(state); - } } } From c9d43328465d3c31b5d01071d3e868399b650284 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 31 Jul 2018 16:44:20 +0900 Subject: [PATCH 057/277] size_x, size_y -> width, height --- .../Edit/Screens/Setup/Components/SetupCircularButton.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 0697e62224..37cc742ad2 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -9,12 +9,12 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components { public class SetupCircularButton : TriangleButton { - private const float size_x = 125; - private const float size_y = 30; + private const float width = 125; + private const float height = 30; public SetupCircularButton() { - Size = new Vector2(size_x, size_y); + Size = new Vector2(width, height); } [BackgroundDependencyLoader] From 7c60c74d46bdfb195edd3e738b47eb5284ce582b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 16:07:58 +0900 Subject: [PATCH 058/277] Remove testcase --- .../TestCaseEditorSetupCircularButton.cs | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs deleted file mode 100644 index ce3ae349b9..0000000000 --- a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Game.Screens.Edit.Screens.Setup.Components; -using System; -using System.Collections.Generic; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseEditorSetupCircularButton : OsuTestCase - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(SetupCircularButton) - }; - - public TestCaseEditorSetupCircularButton() - { - SetupCircularButton circularButton; - - Child = circularButton = new SetupCircularButton - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "Button", - Action = () => { } - }; - - AddStep("Enable button", () => circularButton.Enabled.Value = true); - AddStep("Disable button", () => circularButton.Enabled.Value = false); - } - } -} From b9814b64ed4836d1f2e61700095ac418d6a419fb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 16:45:48 +0900 Subject: [PATCH 059/277] Move default button implementation from TriangleButton to OsuButton --- osu.Game/Graphics/UserInterface/OsuButton.cs | 75 +++++++++++++++++- .../Graphics/UserInterface/TriangleButton.cs | 79 ++----------------- osu.Game/Overlays/Settings/SidebarButton.cs | 6 +- 3 files changed, 84 insertions(+), 76 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index bf3805a44d..bb6a032a12 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,7 +1,16 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.EventArgs; +using osu.Framework.Input.States; +using osu.Game.Graphics.Sprites; +using OpenTK.Graphics; namespace osu.Game.Graphics.UserInterface { @@ -10,9 +19,73 @@ namespace osu.Game.Graphics.UserInterface /// public class OsuButton : Button { + private Box hover; + public OsuButton() { - Add(new HoverClickSounds(HoverSampleSet.Loud)); + Height = 40; + + Content.Masking = true; + Content.CornerRadius = 5; } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BackgroundColour = colours.BlueDark; + + AddRange(new Drawable[] + { + hover = new Box + { + RelativeSizeAxes = Axes.Both, + Blending = BlendingMode.Additive, + Colour = Color4.White.Opacity(0.1f), + Alpha = 0, + Depth = -1 + }, + new HoverClickSounds(HoverSampleSet.Loud), + }); + + Enabled.ValueChanged += enabled_ValueChanged; + Enabled.TriggerChange(); + } + + private void enabled_ValueChanged(bool enabled) + { + this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); + } + + protected override bool OnHover(InputState state) + { + hover.FadeIn(200); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + hover.FadeOut(200); + base.OnHoverLost(state); + } + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + Content.ScaleTo(0.9f, 4000, Easing.OutQuint); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + Content.ScaleTo(1, 1000, Easing.OutElastic); + return base.OnMouseUp(state, args); + } + + protected override SpriteText CreateText() => new OsuSpriteText + { + Depth = -1, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Font = @"Exo2.0-Bold", + }; } } diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index bfdc0c3bef..e85ef9dac1 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -2,17 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using OpenTK.Graphics; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.EventArgs; -using osu.Framework.Input.States; using osu.Game.Graphics.Backgrounds; -using osu.Game.Graphics.Sprites; namespace osu.Game.Graphics.UserInterface { @@ -21,80 +14,19 @@ namespace osu.Game.Graphics.UserInterface /// public class TriangleButton : OsuButton, IFilterable { - private Box hover; - - protected Triangles Triangles; - - public TriangleButton() - { - Height = 40; - } - - protected override SpriteText CreateText() => new OsuSpriteText - { - Depth = -1, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Font = @"Exo2.0-Bold", - }; + protected Triangles Triangles { get; private set; } [BackgroundDependencyLoader] private void load(OsuColour colours) { - BackgroundColour = colours.BlueDark; - - Content.Masking = true; - Content.CornerRadius = 5; - - AddRange(new Drawable[] + Add(Triangles = new Triangles { - Triangles = new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourDark = colours.BlueDarker, - ColourLight = colours.Blue, - }, - hover = new Box - { - RelativeSizeAxes = Axes.Both, - Blending = BlendingMode.Additive, - Colour = Color4.White.Opacity(0.1f), - Alpha = 0, - }, + RelativeSizeAxes = Axes.Both, + ColourDark = colours.BlueDarker, + ColourLight = colours.Blue, }); - - Enabled.ValueChanged += enabled_ValueChanged; - Enabled.TriggerChange(); } - private void enabled_ValueChanged(bool enabled) - { - this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); - } - - protected override bool OnHover(InputState state) - { - hover.FadeIn(200); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - hover.FadeOut(200); - base.OnHoverLost(state); - } - - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) - { - Content.ScaleTo(0.9f, 4000, Easing.OutQuint); - return base.OnMouseDown(state, args); - } - - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) - { - Content.ScaleTo(1, 1000, Easing.OutElastic); - return base.OnMouseUp(state, args); - } public IEnumerable FilterTerms => new[] { Text }; @@ -105,5 +37,6 @@ namespace osu.Game.Graphics.UserInterface this.FadeTo(value ? 1 : 0); } } + } } diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index ac2c840c94..28e2b773ec 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.States; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -16,7 +17,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { - public class SidebarButton : OsuButton + public class SidebarButton : Button { private readonly SpriteIcon drawableIcon; private readonly SpriteText headerText; @@ -97,7 +98,8 @@ namespace osu.Game.Overlays.Settings Width = 5, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - } + }, + new HoverClickSounds(HoverSampleSet.Loud), }); } From 9eb47ae69141e0c18d94a4a6b1ed2126653c2d3a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 17:02:52 +0900 Subject: [PATCH 060/277] Make SetupCircularButton inherit OsuButton --- .../Edit/Screens/Setup/Components/SetupCircularButton.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 37cc742ad2..093598be7a 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -7,7 +7,7 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Screens.Setup.Components { - public class SetupCircularButton : TriangleButton + public class SetupCircularButton : OsuButton { private const float width = 125; private const float height = 30; @@ -20,7 +20,6 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components [BackgroundDependencyLoader] private void load() { - Triangles.Alpha = 0; Content.CornerRadius = 15; } } From 10b8708d4e11314fd45c56d8307dfa648ca9f198 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 17:47:32 +0900 Subject: [PATCH 061/277] Make SetupCircularButton adjust corner radius by height --- .../TestCaseEditorSetupCircularButton.cs | 45 +++++++++++++++++++ .../Setup/Components/SetupCircularButton.cs | 7 ++- 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs new file mode 100644 index 0000000000..c6037b706b --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Containers; +using osu.Game.Screens.Edit.Screens.Setup.Components; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseEditorSetupCircularButton : OsuTestCase + { + [BackgroundDependencyLoader] + private void load() + { + Child = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new[] + { + new SetupCircularButton { Text = "Default" }, + new SetupCircularButton + { + Width = 200, + Text = "Wide", + }, + new SetupCircularButton + { + Height = 100, + Text = "High" + }, + new SetupCircularButton + { + Size = new Vector2(200, 100), + Text = "Wide 'n' High" + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs index 093598be7a..d46fb2f269 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Screens.Setup.Components @@ -17,10 +16,10 @@ namespace osu.Game.Screens.Edit.Screens.Setup.Components Size = new Vector2(width, height); } - [BackgroundDependencyLoader] - private void load() + protected override void Update() { - Content.CornerRadius = 15; + base.Update(); + Content.CornerRadius = DrawHeight / 2f; } } } From 41512667a8d8b5088a65f702874ad709b04d432a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 19:51:24 +0900 Subject: [PATCH 062/277] Require all judgements to be present for map completion --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 9e8ea0f7c2..fa8c11df7f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -247,6 +247,8 @@ namespace osu.Game.Rulesets.Scoring judgement.ComboAtJudgement = Combo; judgement.HighestComboAtJudgement = HighestCombo; + JudgedHits++; + if (judgement.AffectsCombo) { switch (judgement.Result) @@ -260,8 +262,6 @@ namespace osu.Game.Rulesets.Scoring Combo.Value++; break; } - - JudgedHits++; } if (judgement.IsBonus) @@ -285,8 +285,7 @@ namespace osu.Game.Rulesets.Scoring Combo.Value = judgement.ComboAtJudgement; HighestCombo.Value = judgement.HighestComboAtJudgement; - if (judgement.AffectsCombo) - JudgedHits--; + JudgedHits--; if (judgement.IsBonus) { From d51d0e85471722fa95b0e5d458cabfe09ada996f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 21:04:03 +0900 Subject: [PATCH 063/277] Initial structure for new hitobject judgement system --- osu.Game/Rulesets/Judgements/Judgement.cs | 12 ++--- .../Objects/Drawables/DrawableHitObject.cs | 50 +++++++++++-------- osu.Game/Rulesets/Objects/HitObject.cs | 10 ++++ 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 129dd07c3e..63378e57cc 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -28,19 +28,19 @@ namespace osu.Game.Rulesets.Judgements /// public int HighestComboAtJudgement; + /// + /// Whether this has a result. + /// + public bool HasResult => Result > HitResult.None; + /// /// Whether a successful hit occurred. /// public bool IsHit => Result > HitResult.Miss; - /// - /// Whether this judgement is the final judgement for the hit object. - /// - public bool Final = true; - /// /// The offset from a perfect hit at which this judgement occurred. - /// Populated when added via . + /// Populated when added via . /// public double TimeOffset { get; set; } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a22aaa784f..b767834e5d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -38,9 +38,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public event Action OnJudgement; public event Action OnJudgementRemoved; - public IReadOnlyList Judgements => judgements; - private readonly List judgements = new List(); - /// /// Whether a visible judgement should be displayed when this representation is hit. /// @@ -49,20 +46,20 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been hit. /// - public bool IsHit => Judgements.Any(j => j.Final && j.IsHit) && NestedHitObjects.All(n => n.IsHit); + public bool IsHit => HitObject.Judgements.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit); /// /// Whether this and all of its nested s have been judged. /// - public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && NestedHitObjects.All(h => h.AllJudged); + public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged); /// - /// Whether this can be judged. + /// Whether this has been judged. + /// Note: This does NOT include nested hitobjects. /// - protected virtual bool ProvidesJudgement => true; + public bool Judged => HitObject.Judgements.All(h => h.HasResult); private bool judgementOccurred; - private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; public bool Interactive = true; public override bool HandleKeyboardInput => Interactive; @@ -128,23 +125,31 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public void PlaySamples() => Samples?.Play(); + private double lastUpdateTime; + protected override void Update() { base.Update(); - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - - while (judgements.Count > 0) + if (lastUpdateTime > Time.Current) { - var lastJudgement = judgements[judgements.Count - 1]; - if (lastJudgement.TimeOffset + endTime <= Time.Current) - break; + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - judgements.RemoveAt(judgements.Count - 1); - State.Value = ArmedState.Idle; + for (int i = HitObject.Judgements.Count - 1; i >= 0; i--) + { + var judgement = HitObject.Judgements[i]; - OnJudgementRemoved?.Invoke(this, lastJudgement); + if (judgement.TimeOffset + endTime <= Time.Current) + break; + + judgement.Result = HitResult.None; + State.Value = ArmedState.Idle; + + OnJudgementRemoved?.Invoke(this, judgement); + } } + + lastUpdateTime = Time.Current; } protected override void UpdateAfterChildren() @@ -167,16 +172,17 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Notifies that a new judgement has occurred for this . /// /// The . - protected void AddJudgement(Judgement judgement) + protected void ApplyJudgement(T judgement, Action application) + where T : Judgement { judgementOccurred = true; + application?.Invoke(judgement); + // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; judgement.TimeOffset = Time.Current - endTime; - judgements.Add(judgement); - switch (judgement.Result) { case HitResult.None: @@ -207,7 +213,7 @@ namespace osu.Game.Rulesets.Objects.Drawables foreach (var d in NestedHitObjects) judgementOccurred |= d.UpdateJudgement(userTriggered); - if (!ProvidesJudgement || judgementFinalized || judgementOccurred) + if (judgementOccurred || Judged) return judgementOccurred; var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; @@ -218,7 +224,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Checks if any judgements have occurred for this . This method must construct - /// all s and notify of them through . + /// all s and notify of them through . /// /// Whether the user triggered this check. /// The offset from the end time at which this check occurred. A > 0 diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 15c24e2975..0e029a8657 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; +using System.Linq; using Newtonsoft.Json; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Lists; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects @@ -62,6 +64,9 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; + private readonly List judgements = new List(); + public IReadOnlyList Judgements => judgements; + /// /// Applies default values to this HitObject. /// @@ -71,6 +76,9 @@ namespace osu.Game.Rulesets.Objects { ApplyDefaultsToSelf(controlPointInfo, difficulty); + judgements.Clear(); + judgements.AddRange(CreateJudgements()); + if (nestedHitObjects.IsValueCreated) nestedHitObjects.Value.Clear(); @@ -103,6 +111,8 @@ namespace osu.Game.Rulesets.Objects { } + protected virtual IEnumerable CreateJudgements() => Enumerable.Empty(); + protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); /// From 462f1033c0e10cabd675d047522f804212f7f356 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 1 Aug 2018 21:46:22 +0900 Subject: [PATCH 064/277] Migrate Rulesets.Osu to the new judgement system --- .../TestCaseHitCircle.cs | 8 +------ .../Objects/Drawables/DrawableHitCircle.cs | 9 +++----- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 3 +-- .../Objects/Drawables/DrawableSlider.cs | 21 +++++++++++-------- .../Objects/Drawables/DrawableSliderTail.cs | 5 ++--- .../Objects/Drawables/DrawableSliderTick.cs | 3 +-- .../Objects/Drawables/DrawableSpinner.cs | 16 +++++++------- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 9 ++++++++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 4 ++-- .../Objects/SliderTailCircle.cs | 17 +++++++++++++++ 11 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index 7af7140fd8..eea5aa9a52 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -5,12 +5,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Tests.Visual; using OpenTK; -using osu.Game.Rulesets.Osu.Judgements; using System.Collections.Generic; using System; using osu.Game.Rulesets.Mods; @@ -101,11 +99,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && timeOffset > 0) { // force success - AddJudgement(new OsuJudgement - { - Result = HitResult.Great - }); - State.Value = ArmedState.Hit; + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); } else base.CheckForJudgements(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index c525b4bd97..7fd4d11455 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using OpenTK; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; using OpenTK.Graphics; @@ -82,7 +81,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - AddJudgement(new OsuJudgement { Result = HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + return; } @@ -90,10 +90,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None) return; - AddJudgement(new OsuJudgement - { - Result = result, - }); + ApplyJudgement(HitObject.Judgement, j => j.Result = result); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 5dc141bed0..6e24f1bc83 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Judgements.FirstOrDefault()?.TimeOffset ?? 0); + var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), HitObject.Judgements.FirstOrDefault()?.TimeOffset ?? 0); using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true)) UpdateCurrentState(state); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 6bff1380d6..809b27e065 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -8,7 +8,6 @@ using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using osu.Game.Graphics; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; @@ -45,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) - AddJudgement(new OsuJudgement { Result = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index f1907a92a8..6739c3a822 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -9,7 +9,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; using OpenTK.Graphics; @@ -134,21 +133,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!userTriggered && Time.Current >= slider.EndTime) + if (userTriggered || Time.Current < slider.EndTime) + return; + + ApplyJudgement(HitObject.Judgement, j => { var judgementsCount = NestedHitObjects.Count(); var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; - if (hitFraction == 1 && HeadCircle.Judgements.Any(j => j.Result == HitResult.Great)) - AddJudgement(new OsuJudgement { Result = HitResult.Great }); - else if (hitFraction >= 0.5 && HeadCircle.Judgements.Any(j => j.Result >= HitResult.Good)) - AddJudgement(new OsuJudgement { Result = HitResult.Good }); + + if (hitFraction == 1 && HeadCircle.HitObject.Judgement.Result == HitResult.Great) + j.Result = HitResult.Great; + else if (hitFraction >= 0.5 && HeadCircle.HitObject.Judgement.Result >= HitResult.Good) + j.Result = HitResult.Good; else if (hitFraction > 0) - AddJudgement(new OsuJudgement { Result = HitResult.Meh }); + j.Result = HitResult.Meh; else - AddJudgement(new OsuJudgement { Result = HitResult.Miss }); - } + j.Result = HitResult.Miss; + }); } protected override void UpdateCurrentState(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index fee663963e..64c4a8ef18 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -16,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool Tracking { get; set; } - public DrawableSliderTail(Slider slider, HitCircle hitCircle) + public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle) : base(hitCircle) { Origin = Anchor.Centre; @@ -32,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered && timeOffset >= 0) - AddJudgement(new OsuSliderTailJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = Tracking ? HitResult.Great : HitResult.Miss); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index a5ecb63d12..f7b403a5cc 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -6,7 +6,6 @@ using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using osu.Framework.Graphics.Containers; @@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 1d3df69fb8..4a0303f00f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -11,7 +11,6 @@ using OpenTK.Graphics; using osu.Game.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Screens.Ranking; using osu.Game.Rulesets.Scoring; @@ -136,17 +135,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables glow.FadeColour(completeColour, duration); } - if (!userTriggered && Time.Current >= Spinner.EndTime) + if (userTriggered || Time.Current < Spinner.EndTime) + return; + + ApplyJudgement(HitObject.Judgement, j => { if (Progress >= 1) - AddJudgement(new OsuJudgement { Result = HitResult.Great }); + j.Result = HitResult.Great; else if (Progress > .9) - AddJudgement(new OsuJudgement { Result = HitResult.Good }); + j.Result = HitResult.Good; else if (Progress > .75) - AddJudgement(new OsuJudgement { Result = HitResult.Meh }); + j.Result = HitResult.Meh; else if (Time.Current >= Spinner.EndTime) - AddJudgement(new OsuJudgement { Result = HitResult.Miss }); - } + j.Result = HitResult.Miss; + }); } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 48a6365c00..3927ed02d5 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -2,12 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using OpenTK; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit.Types; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -73,5 +76,11 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual void OffsetPosition(Vector2 offset) => Position += offset; protected override HitWindows CreateHitWindows() => new OsuHitWindows(); + + public OsuJudgement Judgement { get; private set; } + + protected override IEnumerable CreateJudgements() => new[] { Judgement = CreateJudgement() }; + + protected virtual OsuJudgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 698f9de787..972dd42fd6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Objects public double TickDistance; public HitCircle HeadCircle; - public HitCircle TailCircle; + public SliderTailCircle TailCircle; protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { @@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Objects ComboIndex = ComboIndex, }; - TailCircle = new SliderCircle(this) + TailCircle = new SliderTailCircle(this) { StartTime = EndTime, Position = EndPosition, diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs new file mode 100644 index 0000000000..3fae9e9f8a --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Osu.Judgements; + +namespace osu.Game.Rulesets.Osu.Objects +{ + public class SliderTailCircle : SliderCircle + { + public SliderTailCircle(Slider slider) + : base(slider) + { + } + + protected override OsuJudgement CreateJudgement() => new OsuSliderTailJudgement(); + } +} From e825edb6d7241b64d19e6a2babd4726831caec33 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 15:28:48 +0900 Subject: [PATCH 065/277] Migrate Rulesets.Catch to the new judgement system --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 4 ++++ osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 8 ++++++++ .../Objects/Drawable/DrawableBanana.cs | 4 ---- .../Objects/Drawable/DrawableBananaShower.cs | 2 -- .../Objects/Drawable/DrawableCatchHitObject.cs | 9 ++------- .../Objects/Drawable/DrawableDroplet.cs | 3 --- .../Objects/Drawable/DrawableJuiceStream.cs | 2 -- .../Objects/Drawable/DrawableTinyDroplet.cs | 5 +---- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 5 ++++- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 5 ++++- .../Objects/ICatchObjectWithJudgement.cs | 12 ++++++++++++ osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs | 3 +++ 12 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index f7c60a7a47..d0f4f6c5db 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Catch.Judgements; + namespace osu.Game.Rulesets.Catch.Objects { public class Banana : Fruit { public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + + public override CatchJudgement Judgement { get; } = new CatchBananaJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index d55cdac115..7f2cff561e 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2018 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 osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -54,6 +56,12 @@ namespace osu.Game.Rulesets.Catch.Objects } protected override HitWindows CreateHitWindows() => null; + + protected override IEnumerable CreateJudgements() + { + if (this is ICatchObjectWithJudgement judgeable) + yield return judgeable.Judgement; + } } public enum FruitVisualRepresentation diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs index dd027abbe0..8756a5178f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs @@ -1,8 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Catch.Judgements; - namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableBanana : DrawableFruit @@ -11,7 +9,5 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable : base(h) { } - - protected override CatchJudgement CreateJudgement() => new CatchBananaJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs index f039504600..697fab85c9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -26,8 +26,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddNested(getVisualRepresentation?.Invoke(b)); } - protected override bool ProvidesJudgement => false; - protected override void AddNested(DrawableHitObject h) { ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 6ce2e6a2ae..126977ecb2 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -5,7 +5,6 @@ using System; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; -using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; @@ -57,16 +56,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { if (CheckPosition == null) return; - if (timeOffset >= 0) + if (timeOffset >= 0 && HitObject is ICatchObjectWithJudgement judgeable) { - var judgement = CreateJudgement(); - judgement.Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss; - AddJudgement(judgement); + ApplyJudgement(judgeable.Judgement, j => j.Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } } - protected virtual CatchJudgement CreateJudgement() => new CatchJudgement(); - protected override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 11d5ed1f92..5c8a7c4a7c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using OpenTK; using OpenTK.Graphics; -using osu.Game.Rulesets.Catch.Judgements; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -24,8 +23,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Masking = false; } - protected override CatchJudgement CreateJudgement() => new CatchDropletJudgement(); - [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index 854b63edeb..e66852c5c2 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -26,8 +26,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AddNested(getVisualRepresentation?.Invoke(o)); } - protected override bool ProvidesJudgement => false; - protected override void AddNested(DrawableHitObject h) { var catchObject = (DrawableCatchHitObject)h; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs index 2232bb81a7..e0f02454c4 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs @@ -2,18 +2,15 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Rulesets.Catch.Judgements; namespace osu.Game.Rulesets.Catch.Objects.Drawable { public class DrawableTinyDroplet : DrawableDroplet { - public DrawableTinyDroplet(Droplet h) + public DrawableTinyDroplet(TinyDroplet h) : base(h) { Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 8; } - - protected override CatchJudgement CreateJudgement() => new CatchTinyDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index f91a70c506..e92b06d0d1 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,9 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Catch.Judgements; + namespace osu.Game.Rulesets.Catch.Objects { - public class Droplet : CatchHitObject + public class Droplet : CatchHitObject, ICatchObjectWithJudgement { + public virtual CatchJudgement Judgement { get; } = new CatchDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index fcbb339ffd..4bcb1a400f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,9 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Catch.Judgements; + namespace osu.Game.Rulesets.Catch.Objects { - public class Fruit : CatchHitObject + public class Fruit : CatchHitObject, ICatchObjectWithJudgement { + public virtual CatchJudgement Judgement { get; } = new CatchJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs b/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs new file mode 100644 index 0000000000..2aa5a5c83a --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Catch.Judgements; + +namespace osu.Game.Rulesets.Catch.Objects +{ + public interface ICatchObjectWithJudgement + { + CatchJudgement Judgement { get; } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 76cc8d9808..d7cc002dfc 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,9 +1,12 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Catch.Judgements; + namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { + public override CatchJudgement Judgement { get; } = new CatchTinyDropletJudgement(); } } From 1b7b6f341cdbcc4b1791fc1532470af021bf03e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 16:09:04 +0900 Subject: [PATCH 066/277] Migrate Rulesets.Taiko to the new judgement system --- .../TaikoIntermediateSwellJudgement.cs | 5 --- .../Judgements/TaikoStrongHitJudgement.cs | 5 --- .../Objects/Drawables/DrawableDrumRoll.cs | 11 ++++--- .../Objects/Drawables/DrawableDrumRollTick.cs | 20 +++++++---- .../Objects/Drawables/DrawableHit.cs | 21 ++---------- .../Objects/Drawables/DrawableHitStrong.cs | 17 ++++++---- .../Objects/Drawables/DrawableSwell.cs | 33 ++++++++++++++----- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 14 ++++++++ .../Objects/DrumRollTick.cs | 15 +++++++++ osu.Game.Rulesets.Taiko/Objects/Hit.cs | 14 ++++++++ osu.Game.Rulesets.Taiko/Objects/Swell.cs | 21 ++++++++++++ 11 files changed, 122 insertions(+), 54 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs index 608f1f9be2..adcf4572c5 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs @@ -11,11 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements public override bool AffectsCombo => false; - public TaikoIntermediateSwellJudgement() - { - Final = false; - } - /// /// Computes the numeric result value for the combo portion of the score. /// diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs index 288ad236aa..b69bbd4fd8 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -6,10 +6,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoStrongHitJudgement : TaikoJudgement { public override bool AffectsCombo => false; - - public TaikoStrongHitJudgement() - { - Final = true; - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 00eac4adca..57c0f55a59 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Taiko.Judgements; using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; @@ -85,12 +84,16 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables int countHit = NestedHitObjects.Count(o => o.IsHit); if (countHit >= HitObject.RequiredGoodHits) { - AddJudgement(new TaikoJudgement { Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good }); + ApplyJudgement(HitObject.Judgement, j => j.Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good); if (HitObject.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); } else - AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); + { + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + if (HitObject.IsStrong) + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + } } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 7a57cf77b4..86853afc35 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -28,14 +27,23 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered) + { + if (timeOffset > HitObject.HitWindow) + { + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + if (HitObject.IsStrong) + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + } + + return; + } + + if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - if (!(Math.Abs(timeOffset) < HitObject.HitWindow)) - return; - - AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); if (HitObject.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index bb9cd02b14..f7a170d838 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -5,7 +5,6 @@ using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -17,11 +16,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// protected abstract TaikoAction[] HitActions { get; } - /// - /// Whether a second hit is allowed to be processed. This occurs once this hit object has been hit successfully. - /// - protected bool SecondHitAllowed { get; private set; } - /// /// Whether the last key pressed is a valid hit key. /// @@ -38,7 +32,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); return; } @@ -47,17 +41,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; if (!validKeyPressed || result == HitResult.Miss) - AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); else - { - AddJudgement(new TaikoJudgement - { - Result = result, - Final = !HitObject.IsStrong - }); - - SecondHitAllowed = true; - } + ApplyJudgement(HitObject.Judgement, j => j.Result = result); } public override bool OnPressed(TaikoAction action) @@ -86,7 +72,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (State.Value) { case ArmedState.Idle: - SecondHitAllowed = false; validKeyPressed = false; UnproxyContent(); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index b431d35e16..ede13aadce 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -28,23 +27,27 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!SecondHitAllowed) + if (!HitObject.Judgement.HasResult) { base.CheckForJudgements(userTriggered, timeOffset); return; } + if (!HitObject.Judgement.IsHit) + { + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + return; + } + if (!userTriggered) { if (timeOffset > second_hit_window) - AddJudgement(new TaikoStrongHitJudgement { Result = HitResult.None }); + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); return; } - // If we get here, we're assured that the key pressed is the correct secondary key - if (Math.Abs(firstHitTime - Time.Current) < second_hit_window) - AddJudgement(new TaikoStrongHitJudgement { Result = HitResult.Great }); + ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); } protected override void UpdateState(ArmedState state) @@ -73,7 +76,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; // Check if we've handled the first key - if (!SecondHitAllowed) + if (!HitObject.Judgement.HasResult) { // First key hasn't been handled yet, attempt to handle it bool handled = base.OnPressed(action); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 408b37e377..f44e70d11d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -12,7 +13,6 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -128,9 +128,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (userTriggered) { - AddJudgement(new TaikoIntermediateSwellJudgement()); + var nextIntermediate = HitObject.IntermediateJudgements.FirstOrDefault(j => !j.HasResult); - var completion = (float)Judgements.Count / HitObject.RequiredHits; + if (nextIntermediate != null) + ApplyJudgement(nextIntermediate, j => j.Result = HitResult.Great); + + var numHits = HitObject.IntermediateJudgements.Count(j => j.HasResult); + + var completion = (float)numHits / HitObject.RequiredHits; expandingRing .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) @@ -141,18 +146,28 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); - if (Judgements.Count == HitObject.RequiredHits) - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); + if (numHits == HitObject.RequiredHits) + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); } else { if (timeOffset < 0) return; - //TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP - AddJudgement(Judgements.Count > HitObject.RequiredHits / 2 - ? new TaikoJudgement { Result = HitResult.Good } - : new TaikoJudgement { Result = HitResult.Miss }); + int numHits = 0; + + foreach (var intermediate in HitObject.IntermediateJudgements) + { + if (intermediate.HasResult) + { + numHits++; + continue; + } + + ApplyJudgement(intermediate, j => j.Result = HitResult.Miss); + } + + ApplyJudgement(HitObject.Judgement, j => j.Result = numHits > HitObject.RequiredHits / 2 ? HitResult.Good : HitResult.Miss); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 4c9ec5473b..b6b1efee16 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -3,8 +3,11 @@ using osu.Game.Rulesets.Objects.Types; using System; +using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { @@ -81,5 +84,16 @@ namespace osu.Game.Rulesets.Taiko.Objects first = false; } } + + public TaikoJudgement Judgement { get; private set; } + public TaikoStrongHitJudgement StrongJudgement { get; private set; } + + protected override IEnumerable CreateJudgements() + { + yield return Judgement = new TaikoJudgement(); + + if (IsStrong) + yield return StrongJudgement = new TaikoStrongHitJudgement(); + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index e546d6427f..58f6a2840a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,6 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; + namespace osu.Game.Rulesets.Taiko.Objects { public class DrumRollTick : TaikoHitObject @@ -20,5 +24,16 @@ namespace osu.Game.Rulesets.Taiko.Objects /// The time allowed to hit this tick. /// public double HitWindow => TickSpacing / 2; + + public TaikoDrumRollTickJudgement Judgement { get; private set; } + public TaikoStrongHitJudgement StrongJudgement { get; private set; } + + protected override IEnumerable CreateJudgements() + { + yield return Judgement = new TaikoDrumRollTickJudgement(); + + if (IsStrong) + yield return StrongJudgement = new TaikoStrongHitJudgement(); + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 0b47aa490b..94fc1ab20f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,9 +1,23 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; + namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoHitObject { + public TaikoJudgement Judgement { get; private set; } + public TaikoStrongHitJudgement StrongJudgement { get; private set; } + + protected override IEnumerable CreateJudgements() + { + yield return Judgement = new TaikoJudgement(); + + if (IsStrong) + yield return StrongJudgement = new TaikoStrongHitJudgement(); + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index eb6f931af4..0985853dd6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,7 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { @@ -15,5 +18,23 @@ namespace osu.Game.Rulesets.Taiko.Objects /// The number of hits required to complete the swell successfully. /// public int RequiredHits = 10; + + public TaikoJudgement Judgement { get; private set; } + + private readonly List intermediateJudgements = new List(); + public IReadOnlyList IntermediateJudgements => intermediateJudgements; + + protected override IEnumerable CreateJudgements() + { + yield return Judgement = new TaikoJudgement(); + + for (int i = 0; i < RequiredHits; i++) + { + var intermediate = new TaikoIntermediateSwellJudgement(); + intermediateJudgements.Add(intermediate); + + yield return intermediate; + } + } } } From cd70e5e30b24301b071f481d51e3d9510fe5fe44 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 16:44:01 +0900 Subject: [PATCH 067/277] Migrate Rulesets.Mania to the new judgement system --- .../Objects/Drawables/DrawableHoldNote.cs | 16 ++++++------- .../Objects/Drawables/DrawableHoldNoteTick.cs | 23 ++++--------------- .../Objects/Drawables/DrawableNote.cs | 5 ++-- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 9 +++++++- .../Objects/HoldNoteTick.cs | 7 ++++++ osu.Game.Rulesets.Mania/Objects/Note.cs | 7 ++++++ osu.Game.Rulesets.Mania/Objects/TailNote.cs | 12 ++++++++++ 7 files changed, 49 insertions(+), 30 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Objects/TailNote.cs diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 597450f223..2e64c1796a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -100,7 +100,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (tail.AllJudged) - AddJudgement(new HoldNoteJudgement { Result = HitResult.Perfect }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Perfect); } protected override void Update() @@ -166,7 +166,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return false; // If the key has been released too early, the user should not receive full score for the release - if (Judgements.Any(j => j.Result == HitResult.Miss)) + if (HitObject.Judgement.Result == HitResult.Miss) holdNote.hasBroken = true; // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held @@ -206,10 +206,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (!HitObject.HitWindows.CanBeHit(timeOffset)) { - AddJudgement(new HoldNoteTailJudgement + ApplyJudgement(holdNote.HitObject.Tail.Judgement, j => { - Result = HitResult.Miss, - HasBroken = holdNote.hasBroken + j.Result = HitResult.Miss; + ((HoldNoteTailJudgement)j).HasBroken = holdNote.hasBroken; }); } @@ -220,10 +220,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - AddJudgement(new HoldNoteTailJudgement + ApplyJudgement(holdNote.HitObject.Tail.Judgement, j => { - Result = result, - HasBroken = holdNote.hasBroken + j.Result = result; + ((HoldNoteTailJudgement)j).HasBroken = holdNote.hasBroken; }); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 5df6079efa..c281045591 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -7,7 +7,6 @@ using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Scoring; @@ -74,27 +73,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!userTriggered) - return; - if (Time.Current < HitObject.StartTime) return; - if (HoldStartTime?.Invoke() > HitObject.StartTime) - return; + var startTime = HoldStartTime?.Invoke(); - AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect }); - } - - protected override void Update() - { - if (AllJudged) - return; - - if (HoldStartTime?.Invoke() == null) - return; - - UpdateJudgement(true); + if (startTime == null || startTime > HitObject.StartTime) + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + else + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Perfect); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 18084c4c08..bc1033bead 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -6,7 +6,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -61,7 +60,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - AddJudgement(new ManiaJudgement { Result = HitResult.Miss }); + ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); return; } @@ -69,7 +68,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - AddJudgement(new ManiaJudgement { Result = result }); + ApplyJudgement(HitObject.Judgement, j => j.Result = result); } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 22fa93a308..033434a989 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,8 +1,11 @@ // Copyright (c) 2007-2018 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 osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Mania.Objects @@ -55,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.Objects /// /// The tail note of the hold. /// - public readonly Note Tail = new Note(); + public readonly TailNote Tail = new TailNote(); /// /// The time between ticks of this hold. @@ -94,5 +97,9 @@ namespace osu.Game.Rulesets.Mania.Objects }); } } + + public HoldNoteJudgement Judgement { get; private set; } + + protected override IEnumerable CreateJudgements() => new[] { Judgement = new HoldNoteJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index d078c15c92..73ad3d94ec 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,6 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Judgements; + namespace osu.Game.Rulesets.Mania.Objects { /// @@ -8,5 +12,8 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteTick : ManiaHitObject { + public HoldNoteTickJudgement Judgement { get; private set; } + + protected override IEnumerable CreateJudgements() => new[] { Judgement = new HoldNoteTickJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 975188e550..ebda40de85 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,6 +1,10 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Judgements; + namespace osu.Game.Rulesets.Mania.Objects { /// @@ -8,5 +12,8 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { + public virtual ManiaJudgement Judgement { get; } = new ManiaJudgement(); + + protected override IEnumerable CreateJudgements() => new[] { Judgement }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs new file mode 100644 index 0000000000..530f3c6ff1 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mania.Judgements; + +namespace osu.Game.Rulesets.Mania.Objects +{ + public class TailNote : Note + { + public override ManiaJudgement Judgement { get; } = new HoldNoteTailJudgement(); + } +} From b1afcf0e5d6bc14e57a8ed7e15f12a9417022bff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 2 Aug 2018 19:47:50 +0900 Subject: [PATCH 068/277] Add loading animation to player loader to make it more obvious when loading is complete --- osu.Game.Tests/Visual/TestCasePlayerLoader.cs | 40 ++++++++++++++++++- osu.Game/Screens/Play/PlayerLoader.cs | 36 +++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs index 52a9db080d..de839a21af 100644 --- a/osu.Game.Tests/Visual/TestCasePlayerLoader.cs +++ b/osu.Game.Tests/Visual/TestCasePlayerLoader.cs @@ -1,25 +1,61 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { - public class TestCasePlayerLoader : OsuTestCase + public class TestCasePlayerLoader : ManualInputManagerTestCase { + private PlayerLoader loader; + [BackgroundDependencyLoader] private void load(OsuGameBase game) { Beatmap.Value = new DummyWorkingBeatmap(game); - AddStep("load dummy beatmap", () => Add(new PlayerLoader(new Player + AddStep("load dummy beatmap", () => Add(loader = new PlayerLoader(new Player { AllowPause = false, AllowLeadIn = false, AllowResults = false, }))); + + AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre)); + + AddUntilStep(() => !loader.IsCurrentScreen, "wait for no longer current"); + + AddStep("load slow dummy beatmap", () => + { + SlowLoadPlayer slow; + + Add(loader = new PlayerLoader(slow = new SlowLoadPlayer + { + AllowPause = false, + AllowLeadIn = false, + AllowResults = false, + })); + + Scheduler.AddDelayed(() => slow.Ready = true, 5000); + }); + + AddUntilStep(() => !loader.IsCurrentScreen, "wait for no longer current"); + } + + protected class SlowLoadPlayer : Player + { + public bool Ready; + + [BackgroundDependencyLoader] + private void load() + { + while (!Ready) + Thread.Sleep(1); + } } } + } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 97a728ffb7..cc2ba3b06a 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -12,9 +12,11 @@ using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Menu; using osu.Game.Screens.Play.PlayerSettings; using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Screens.Play { @@ -65,21 +67,25 @@ namespace osu.Game.Screens.Play } }); - loadTask = LoadComponentAsync(player); + loadTask = LoadComponentAsync(player, playerLoaded); } + private void playerLoaded(Player player) => info.Loading = false; + protected override void OnResuming(Screen last) { base.OnResuming(last); contentIn(); + info.Loading = true; + //we will only be resumed if the player has requested a re-run (see ValidForResume setting above) loadTask = LoadComponentAsync(player = new Player { RestartCount = player.RestartCount + 1, RestartRequested = player.RestartRequested, - }); + }, playerLoaded); this.Delay(400).Schedule(pushWhenLoaded); } @@ -230,6 +236,25 @@ namespace osu.Game.Screens.Play } private readonly WorkingBeatmap beatmap; + private LoadingAnimation loading; + private Sprite backgroundSprite; + + public bool Loading + { + set + { + if (value) + { + loading.Show(); + backgroundSprite.FadeColour(OsuColour.Gray(0.5f), 400, Easing.OutQuint); + } + else + { + loading.Hide(); + backgroundSprite.FadeColour(Color4.White, 400, Easing.OutQuint); + } + } + } public BeatmapMetadataDisplay(WorkingBeatmap beatmap) { @@ -276,9 +301,9 @@ namespace osu.Game.Screens.Play Anchor = Anchor.TopCentre, CornerRadius = 10, Masking = true, - Children = new[] + Children = new Drawable[] { - new Sprite + backgroundSprite = new Sprite { RelativeSizeAxes = Axes.Both, Texture = beatmap?.Background, @@ -286,6 +311,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, FillMode = FillMode.Fill, }, + loading = new LoadingAnimation { Scale = new Vector2(1.3f) } } }, new OsuSpriteText @@ -313,6 +339,8 @@ namespace osu.Game.Screens.Play }, } }; + + Loading = true; } } } From 3619290c34f404f822b49b74852ecb76ea876fd7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 20:35:54 +0900 Subject: [PATCH 069/277] Split out judgement definition from judgement result --- .../Rulesets/Judgements/DrawableJudgement.cs | 16 ++-- osu.Game/Rulesets/Judgements/Judgement.cs | 56 +++--------- .../Rulesets/Judgements/JudgementResult.cs | 51 +++++++++++ .../Objects/Drawables/DrawableHitObject.cs | 49 +++++++---- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 88 +++++++++++-------- osu.Game/Rulesets/UI/RulesetContainer.cs | 8 +- .../Screens/Play/HUD/StandardHealthDisplay.cs | 4 +- 7 files changed, 161 insertions(+), 111 deletions(-) create mode 100644 osu.Game/Rulesets/Judgements/JudgementResult.cs diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 5de14ae579..65b2ef75c4 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Judgements private OsuColour colours; - protected readonly Judgement Judgement; + protected readonly JudgementResult Result; public readonly DrawableHitObject JudgedObject; @@ -34,11 +34,11 @@ namespace osu.Game.Rulesets.Judgements /// /// Creates a drawable which visualises a . /// - /// The judgement to visualise. + /// The judgement to visualise. /// The object which was judged. - public DrawableJudgement(Judgement judgement, DrawableHitObject judgedObject) + public DrawableJudgement(JudgementResult result, DrawableHitObject judgedObject) { - Judgement = judgement; + Result = result; JudgedObject = judgedObject; Size = new Vector2(judgement_size); @@ -49,11 +49,11 @@ namespace osu.Game.Rulesets.Judgements { this.colours = colours; - Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText + Child = new SkinnableDrawable($"Play/{Result.Type}", _ => JudgementText = new OsuSpriteText { - Text = Judgement.Result.GetDescription().ToUpperInvariant(), + Text = Result.Type.GetDescription().ToUpperInvariant(), Font = @"Venera", - Colour = judgementColour(Judgement.Result), + Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), TextSize = 12 }, restrictSize: false); @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Judgements this.FadeInFromZero(100, Easing.OutQuint); - switch (Judgement.Result) + switch (Result.Type) { case HitResult.None: break; diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 63378e57cc..5fddbe0b0a 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,74 +1,44 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements { public class Judgement { - /// - /// Whether this judgement is the result of a hit or a miss. - /// - public HitResult Result; - /// /// The maximum that can be achieved. /// public virtual HitResult MaxResult => HitResult.Perfect; /// - /// The combo prior to this judgement occurring. - /// - public int ComboAtJudgement; - - /// - /// The highest combo achieved prior to this judgement occurring. - /// - public int HighestComboAtJudgement; - - /// - /// Whether this has a result. - /// - public bool HasResult => Result > HitResult.None; - - /// - /// Whether a successful hit occurred. - /// - public bool IsHit => Result > HitResult.Miss; - - /// - /// The offset from a perfect hit at which this judgement occurred. - /// Populated when added via . - /// - public double TimeOffset { get; set; } - - /// - /// Whether the should affect the current combo. + /// Whether this should affect the current combo. /// public virtual bool AffectsCombo => true; /// - /// Whether the should be counted as base (combo) or bonus score. + /// Whether this should be counted as base (combo) or bonus score. /// public virtual bool IsBonus => !AffectsCombo; /// - /// The numeric representation for the result achieved. - /// - public int NumericResult => NumericResultFor(Result); - - /// - /// The numeric representation for the maximum achievable result. + /// The numeric score representation for the maximum achievable result. /// public int MaxNumericResult => NumericResultFor(MaxResult); /// - /// Convert a to a numeric score representation. + /// Retrieves the numeric score representation of a . /// - /// The value to convert. - /// The number. + /// The to find the numeric score representation for. + /// The numeric score representation of . protected virtual int NumericResultFor(HitResult result) => result > HitResult.Miss ? 1 : 0; + + /// + /// Retrieves the numeric score representation of a . + /// + /// The to find the numeric score representation for. + /// The numeric score representation of . + public int NumericResultFor(JudgementResult result) => NumericResultFor(result.Type); } } diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs new file mode 100644 index 0000000000..6971fcf593 --- /dev/null +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Judgements +{ + public class JudgementResult + { + /// + /// Whether this is the result of a hit or a miss. + /// + public HitResult Type; + + /// + /// The which this applies for. + /// + public readonly Judgement Judgement; + + /// + /// The offset from a perfect hit at which this occurred. + /// Populated when added via . + /// + public double TimeOffset { get; internal set; } + + /// + /// The combo prior to this judgement occurring. + /// + public int ComboAtJudgement { get; internal set; } + + /// + /// The highest combo achieved prior to this judgement occurring. + /// + public int HighestComboAtJudgement { get; internal set; } + + /// + /// Whether this has a result. + /// + public bool HasResult => Type > HitResult.None; + + /// + /// Whether a successful hit occurred. + /// + public bool IsHit => Type > HitResult.Miss; + + public JudgementResult(Judgement judgement) + { + Judgement = judgement; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index b767834e5d..27de18177f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Objects.Drawables private readonly Lazy> nestedHitObjects = new Lazy>(); public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty(); - public event Action OnJudgement; - public event Action OnJudgementRemoved; + public event Action OnJudgement; + public event Action OnJudgementRemoved; /// /// Whether a visible judgement should be displayed when this representation is hit. @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been hit. /// - public bool IsHit => HitObject.Judgements.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit); + public bool IsHit => Results.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit); /// /// Whether this and all of its nested s have been judged. @@ -57,7 +57,10 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether this has been judged. /// Note: This does NOT include nested hitobjects. /// - public bool Judged => HitObject.Judgements.All(h => h.HasResult); + public bool Judged => Results.All(h => h.HasResult); + + private readonly List results = new List(); + public IReadOnlyList Results => results; private bool judgementOccurred; @@ -74,6 +77,9 @@ namespace osu.Game.Rulesets.Objects.Drawables protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; + + foreach (var j in hitObject.Judgements) + results.Add(CreateJudgementResult(j)); } [BackgroundDependencyLoader] @@ -135,17 +141,17 @@ namespace osu.Game.Rulesets.Objects.Drawables { var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - for (int i = HitObject.Judgements.Count - 1; i >= 0; i--) + for (int i = Results.Count - 1; i >= 0; i--) { - var judgement = HitObject.Judgements[i]; + var judgement = Results[i]; if (judgement.TimeOffset + endTime <= Time.Current) break; - judgement.Result = HitResult.None; - State.Value = ArmedState.Idle; - OnJudgementRemoved?.Invoke(this, judgement); + + judgement.Type = HitResult.None; + State.Value = ArmedState.Idle; } } @@ -161,8 +167,8 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void AddNested(DrawableHitObject h) { - h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); - h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); + h.OnJudgement += (d, r) => OnJudgement?.Invoke(d, r); + h.OnJudgementRemoved += (d, r) => OnJudgementRemoved?.Invoke(d, r); h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); nestedHitObjects.Value.Add(h); @@ -172,18 +178,21 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Notifies that a new judgement has occurred for this . /// /// The . - protected void ApplyJudgement(T judgement, Action application) - where T : Judgement + protected void ApplyResult(JudgementResult result, Action application) { - judgementOccurred = true; + // Todo: Unsure if we want to keep this + if (!Results.Contains(result)) + throw new ArgumentException($"The applied judgement result must be a part of {Results}."); - application?.Invoke(judgement); + application?.Invoke(result); + + judgementOccurred = true; // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - judgement.TimeOffset = Time.Current - endTime; + result.TimeOffset = Time.Current - endTime; - switch (judgement.Result) + switch (result.Type) { case HitResult.None: break; @@ -195,7 +204,7 @@ namespace osu.Game.Rulesets.Objects.Drawables break; } - OnJudgement?.Invoke(this, judgement); + OnJudgement?.Invoke(this, result); } /// @@ -224,7 +233,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Checks if any judgements have occurred for this . This method must construct - /// all s and notify of them through . + /// all s and notify of them through . /// /// Whether the user triggered this check. /// The offset from the end time at which this check occurred. A > 0 @@ -232,6 +241,8 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { } + + protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index fa8c11df7f..ccd3fb6e69 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the . /// - public event Action NewJudgement; + public event Action NewJudgement; /// /// Additional conditions on top of that cause a failing state. @@ -144,9 +144,10 @@ namespace osu.Game.Rulesets.Scoring /// Notifies subscribers of that a new judgement has occurred. /// /// The judgement to notify subscribers of. - protected void NotifyNewJudgement(Judgement judgement) + /// The judgement scoring result to notify subscribers of. + protected void NotifyNewJudgement(JudgementResult result) { - NewJudgement?.Invoke(judgement); + NewJudgement?.Invoke(result); if (HasCompleted) AllJudged?.Invoke(); @@ -209,32 +210,47 @@ namespace osu.Game.Rulesets.Scoring Mode.ValueChanged += _ => updateScore(); } - /// - /// Simulates an autoplay of s that will be judged by this - /// by adding s for each in the . - /// - /// This is required for to work, otherwise will be used. - /// - /// - /// The containing the s that will be judged by this . - protected virtual void SimulateAutoplay(Beatmap beatmap) { } + protected virtual void ApplyBeatmap(Beatmap beatmap) + { + } + + protected virtual void SimulateAutoplay(Beatmap beatmap) + { + foreach (var obj in beatmap.HitObjects) + simulate(obj); + + void simulate(HitObject obj) + { + foreach (var nested in obj.NestedHitObjects) + simulate(nested); + + foreach (var judgement in obj.Judgements) + AddJudgement(new JudgementResult(judgement) { Type = judgement.MaxResult }); + } + } /// /// Adds a judgement to this ScoreProcessor. /// /// The judgement to add. - protected void AddJudgement(Judgement judgement) + /// The judgement scoring result. + protected void AddJudgement(JudgementResult result) { - OnNewJudgement(judgement); + OnNewJudgement(result); updateScore(); UpdateFailed(); - NotifyNewJudgement(judgement); + NotifyNewJudgement(result); } - protected void RemoveJudgement(Judgement judgement) + /// + /// Removes a judgement from this ScoreProcessor. + /// + /// The judgement to remove. + /// The judgement scoring result. + protected void RemoveJudgement(JudgementResult result) { - OnJudgementRemoved(judgement); + OnJudgementRemoved(result); updateScore(); } @@ -242,16 +258,17 @@ namespace osu.Game.Rulesets.Scoring /// Applies a judgement. /// /// The judgement to apply/ - protected virtual void OnNewJudgement(Judgement judgement) + /// The judgement scoring result. + protected virtual void OnNewJudgement(JudgementResult result) { - judgement.ComboAtJudgement = Combo; - judgement.HighestComboAtJudgement = HighestCombo; + result.ComboAtJudgement = Combo; + result.HighestComboAtJudgement = HighestCombo; JudgedHits++; - if (judgement.AffectsCombo) + if (result.Judgement.AffectsCombo) { - switch (judgement.Result) + switch (result.Type) { case HitResult.None: break; @@ -264,15 +281,15 @@ namespace osu.Game.Rulesets.Scoring } } - if (judgement.IsBonus) + if (result.Judgement.IsBonus) { - if (judgement.IsHit) - bonusScore += judgement.NumericResult; + if (result.IsHit) + bonusScore += result.Judgement.NumericResultFor(result); } else { - baseScore += judgement.NumericResult; - rollingMaxBaseScore += judgement.MaxNumericResult; + baseScore += result.Judgement.NumericResultFor(result); + rollingMaxBaseScore += result.Judgement.MaxNumericResult; } } @@ -280,22 +297,23 @@ namespace osu.Game.Rulesets.Scoring /// Removes a judgement. This should reverse everything in . /// /// The judgement to remove. - protected virtual void OnJudgementRemoved(Judgement judgement) + /// The judgement scoring result. + protected virtual void OnJudgementRemoved(JudgementResult result) { - Combo.Value = judgement.ComboAtJudgement; - HighestCombo.Value = judgement.HighestComboAtJudgement; + Combo.Value = result.ComboAtJudgement; + HighestCombo.Value = result.HighestComboAtJudgement; JudgedHits--; - if (judgement.IsBonus) + if (result.Judgement.IsBonus) { - if (judgement.IsHit) - bonusScore -= judgement.NumericResult; + if (result.IsHit) + bonusScore -= result.Judgement.NumericResultFor(result); } else { - baseScore -= judgement.NumericResult; - rollingMaxBaseScore -= judgement.MaxNumericResult; + baseScore -= result.Judgement.NumericResultFor(result); + rollingMaxBaseScore -= result.Judgement.MaxNumericResult; } } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index ee34e2df04..e890cccc3c 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -182,8 +182,8 @@ namespace osu.Game.Rulesets.UI public abstract class RulesetContainer : RulesetContainer where TObject : HitObject { - public event Action OnJudgement; - public event Action OnJudgementRemoved; + public event Action OnJudgement; + public event Action OnJudgementRemoved; /// /// The Beatmap @@ -290,8 +290,8 @@ namespace osu.Game.Rulesets.UI if (drawableObject == null) continue; - drawableObject.OnJudgement += (d, j) => OnJudgement?.Invoke(j); - drawableObject.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(j); + drawableObject.OnJudgement += (_, r) => OnJudgement?.Invoke(r); + drawableObject.OnJudgementRemoved += (_, r) => OnJudgementRemoved?.Invoke(r); Playfield.Add(drawableObject); } diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs index ab446550a6..b551b1f7a6 100644 --- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs @@ -92,9 +92,9 @@ namespace osu.Game.Screens.Play.HUD }; } - public void Flash(Judgement judgement) + public void Flash(JudgementResult result) { - if (judgement.Result == HitResult.Miss) + if (result.Type == HitResult.Miss) return; fill.FadeEdgeEffectTo(Math.Min(1, fill.EdgeEffect.Colour.Linear.A + (1f - base_glow_opacity) / glow_max_hits), 50, Easing.OutQuint) From 9c2122c0ca30650d364f384b3b95200cea4d5d74 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 20:36:08 +0900 Subject: [PATCH 070/277] Make Rulesets.Taiko use the new judgement result structure --- .../TestCaseTaikoPlayfield.cs | 9 ++-- .../TaikoIntermediateSwellJudgement.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 19 +++++--- .../Objects/Drawables/DrawableDrumRollTick.cs | 17 +++++-- .../Objects/Drawables/DrawableHit.cs | 14 ++++-- .../Objects/Drawables/DrawableHitStrong.cs | 17 ++++--- .../Objects/Drawables/DrawableSwell.cs | 25 +++++++--- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 7 +-- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 7 +-- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 14 +----- .../Scoring/TaikoScoreProcessor.cs | 47 +++---------------- .../UI/DrawableTaikoJudgement.cs | 10 ++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 14 +++--- 13 files changed, 96 insertions(+), 106 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 1bf24a46bc..ccae3cf3ce 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -11,6 +11,7 @@ using osu.Framework.MathUtils; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Taiko.Judgements; @@ -143,18 +144,18 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoJudgement { Result = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); if (RNG.Next(10) == 0) { - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoJudgement { Result = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoStrongHitJudgement()); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoStrongHitJudgement()) { Type = HitResult.Great }); } } private void addMissJudgement() { - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(new DrawableTestHit(new Hit()), new TaikoJudgement { Result = HitResult.Miss }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs index adcf4572c5..81a1bd1344 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoIntermediateSwellJudgement.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoIntermediateSwellJudgement : TaikoJudgement { - public override HitResult MaxResult => HitResult.Perfect; + public override HitResult MaxResult => HitResult.Great; public override bool AffectsCombo => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 57c0f55a59..93eaeb4a1f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -23,6 +24,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const int rolling_hits_for_engaged_colour = 5; + private readonly JudgementResult result; + private readonly JudgementResult strongResult; + /// /// Rolling number of tick hits. This increases for hits and decreases for misses. /// @@ -44,6 +48,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddNested(newTick); tickContainer.Add(newTick); } + + result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); + strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); } protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); @@ -60,9 +67,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables colourEngaged = colours.YellowDarker; } - private void onTickJudgement(DrawableHitObject obj, Judgement judgement) + private void onTickJudgement(DrawableHitObject obj, JudgementResult result) { - if (judgement.Result > HitResult.Miss) + if (result.Type > HitResult.Miss) rollingHits++; else rollingHits--; @@ -84,15 +91,15 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables int countHit = NestedHitObjects.Count(o => o.IsHit); if (countHit >= HitObject.RequiredGoodHits) { - ApplyJudgement(HitObject.Judgement, j => j.Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good); + ApplyResult(result, r => r.Type = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good); if (HitObject.IsStrong) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); + ApplyResult(strongResult, r => r.Type = HitResult.Great); } else { - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(result, r => r.Type = HitResult.Miss); if (HitObject.IsStrong) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + ApplyResult(strongResult, r => r.Type = HitResult.Miss); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 86853afc35..eeca1b1da3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -2,19 +2,28 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using osu.Framework.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableDrumRollTick : DrawableTaikoHitObject { + private readonly JudgementResult result; + private readonly JudgementResult strongResult; + public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { FillMode = FillMode.Fit; + + result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); + strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); } public override bool DisplayJudgement => false; @@ -30,9 +39,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (timeOffset > HitObject.HitWindow) { - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(result, r => r.Type = HitResult.Miss); if (HitObject.IsStrong) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + ApplyResult(strongResult, r => r.Type = HitResult.Miss); } return; @@ -41,9 +50,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); + ApplyResult(result, r => r.Type = HitResult.Great); if (HitObject.IsStrong) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); + ApplyResult(strongResult, r => r.Type = HitResult.Great); } protected override void UpdateState(ArmedState state) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index f7a170d838..18177ad089 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -3,8 +3,10 @@ using System.Linq; using osu.Framework.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -16,6 +18,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// protected abstract TaikoAction[] HitActions { get; } + protected readonly JudgementResult Result; + /// /// Whether the last key pressed is a valid hit key. /// @@ -25,6 +29,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables : base(hit) { FillMode = FillMode.Fit; + + Result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); } protected override void CheckForJudgements(bool userTriggered, double timeOffset) @@ -32,7 +38,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(Result, r => r.Type = HitResult.Miss); return; } @@ -40,10 +46,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (result == HitResult.None) return; - if (!validKeyPressed || result == HitResult.Miss) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + if (!validKeyPressed) + ApplyResult(Result, r => r.Type = HitResult.Miss); else - ApplyJudgement(HitObject.Judgement, j => j.Result = result); + ApplyResult(Result, r => r.Type = result); } public override bool OnPressed(TaikoAction action) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index ede13aadce..7ec0c08f0f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -3,8 +3,10 @@ using System; using System.Linq; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -16,6 +18,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const double second_hit_window = 30; + private readonly JudgementResult strongResult; + private double firstHitTime; private bool firstKeyHeld; private TaikoAction firstHitAction; @@ -23,31 +27,32 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected DrawableHitStrong(Hit hit) : base(hit) { + strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!HitObject.Judgement.HasResult) + if (!Result.HasResult) { base.CheckForJudgements(userTriggered, timeOffset); return; } - if (!HitObject.Judgement.IsHit) + if (!Result.IsHit) { - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + ApplyResult(strongResult, r => r.Type = HitResult.Miss); return; } if (!userTriggered) { if (timeOffset > second_hit_window) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Miss); + ApplyResult(strongResult, r => r.Type = HitResult.Miss); return; } if (Math.Abs(firstHitTime - Time.Current) < second_hit_window) - ApplyJudgement(HitObject.StrongJudgement, j => j.Result = HitResult.Great); + ApplyResult(strongResult, r => r.Type = HitResult.Great); } protected override void UpdateState(ArmedState state) @@ -76,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; // Check if we've handled the first key - if (!HitObject.Judgement.HasResult) + if (!Result.HasResult) { // First key hasn't been handled yet, attempt to handle it bool handled = base.OnPressed(action); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index f44e70d11d..50b010e543 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; @@ -13,7 +14,9 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -29,6 +32,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private const float target_ring_scale = 5f; private const float inner_ring_alpha = 0.65f; + private readonly JudgementResult result; + private readonly List intermediateResults; + private readonly Container bodyContainer; private readonly CircularContainer targetRing; private readonly CircularContainer expandingRing; @@ -106,6 +112,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables }); MainPiece.Add(symbol = new SwellSymbolPiece()); + + result = Results.Single(r => !(r.Judgement is TaikoIntermediateSwellJudgement)); + intermediateResults = Results.Where(r => r.Judgement is TaikoIntermediateSwellJudgement).ToList(); } [BackgroundDependencyLoader] @@ -128,12 +137,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (userTriggered) { - var nextIntermediate = HitObject.IntermediateJudgements.FirstOrDefault(j => !j.HasResult); + var nextIntermediate = intermediateResults.FirstOrDefault(j => !j.HasResult); if (nextIntermediate != null) - ApplyJudgement(nextIntermediate, j => j.Result = HitResult.Great); + ApplyResult(nextIntermediate, r => r.Type = HitResult.Great); - var numHits = HitObject.IntermediateJudgements.Count(j => j.HasResult); + var numHits = intermediateResults.Count(r => r.HasResult); var completion = (float)numHits / HitObject.RequiredHits; @@ -147,7 +156,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (numHits == HitObject.RequiredHits) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); + ApplyResult(result, r => r.Type = HitResult.Great); } else { @@ -156,7 +165,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables int numHits = 0; - foreach (var intermediate in HitObject.IntermediateJudgements) + foreach (var intermediate in intermediateResults) { if (intermediate.HasResult) { @@ -164,10 +173,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables continue; } - ApplyJudgement(intermediate, j => j.Result = HitResult.Miss); + ApplyResult(intermediate, r => r.Type = HitResult.Miss); } - ApplyJudgement(HitObject.Judgement, j => j.Result = numHits > HitObject.RequiredHits / 2 ? HitResult.Good : HitResult.Miss); + var hitResult = numHits > HitObject.RequiredHits / 2 ? HitResult.Good : HitResult.Miss; + + ApplyResult(result, r => r.Type = hitResult); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index b6b1efee16..2ed59d3c43 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -85,15 +85,12 @@ namespace osu.Game.Rulesets.Taiko.Objects } } - public TaikoJudgement Judgement { get; private set; } - public TaikoStrongHitJudgement StrongJudgement { get; private set; } - protected override IEnumerable CreateJudgements() { - yield return Judgement = new TaikoJudgement(); + yield return new TaikoJudgement(); if (IsStrong) - yield return StrongJudgement = new TaikoStrongHitJudgement(); + yield return new TaikoStrongHitJudgement(); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 94fc1ab20f..6795aef730 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -9,15 +9,12 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoHitObject { - public TaikoJudgement Judgement { get; private set; } - public TaikoStrongHitJudgement StrongJudgement { get; private set; } - protected override IEnumerable CreateJudgements() { - yield return Judgement = new TaikoJudgement(); + yield return new TaikoJudgement(); if (IsStrong) - yield return StrongJudgement = new TaikoStrongHitJudgement(); + yield return new TaikoStrongHitJudgement(); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 0985853dd6..2dec6019eb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -19,22 +19,12 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public int RequiredHits = 10; - public TaikoJudgement Judgement { get; private set; } - - private readonly List intermediateJudgements = new List(); - public IReadOnlyList IntermediateJudgements => intermediateJudgements; - protected override IEnumerable CreateJudgements() { - yield return Judgement = new TaikoJudgement(); + yield return new TaikoJudgement(); for (int i = 0; i < RequiredHits; i++) - { - var intermediate = new TaikoIntermediateSwellJudgement(); - intermediateJudgements.Add(intermediate); - - yield return intermediate; - } + yield return new TaikoIntermediateSwellJudgement(); } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 7dd50ab8b8..f5c5fcbe9c 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; @@ -60,63 +59,31 @@ namespace osu.Game.Rulesets.Taiko.Scoring private double hpIncreaseGood; private double hpIncreaseMiss; - public TaikoScoreProcessor() - { - } - public TaikoScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) { } - protected override void SimulateAutoplay(Beatmap beatmap) + protected override void ApplyBeatmap(Beatmap beatmap) { + base.ApplyBeatmap(beatmap); + double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98)); hpIncreaseTick = hp_hit_tick; hpIncreaseGreat = hpMultiplierNormal * hp_hit_great; hpIncreaseGood = hpMultiplierNormal * hp_hit_good; hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); - - foreach (var obj in beatmap.HitObjects) - { - switch (obj) - { - case Hit _: - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); - if (obj.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); - break; - case DrumRoll drumRoll: - var count = drumRoll.NestedHitObjects.OfType().Count(); - for (int i = 0; i < count; i++) - { - AddJudgement(new TaikoDrumRollTickJudgement { Result = HitResult.Great }); - - if (obj.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); - } - - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); - - if (obj.IsStrong) - AddJudgement(new TaikoStrongHitJudgement()); - break; - case Swell _: - AddJudgement(new TaikoJudgement { Result = HitResult.Great }); - break; - } - } } - protected override void OnNewJudgement(Judgement judgement) + protected override void OnNewJudgement(JudgementResult result) { - base.OnNewJudgement(judgement); + base.OnNewJudgement(result); - bool isTick = judgement is TaikoDrumRollTickJudgement; + bool isTick = result.Judgement is TaikoDrumRollTickJudgement; // Apply HP changes - switch (judgement.Result) + switch (result.Type) { case HitResult.Miss: // Missing ticks shouldn't drop HP diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index b07a3ce8df..4d660918b8 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -19,16 +19,16 @@ namespace osu.Game.Rulesets.Taiko.UI /// Creates a new judgement text. /// /// The object which is being judged. - /// The judgement to visualise. - public DrawableTaikoJudgement(Judgement judgement, DrawableHitObject judgedObject) - : base(judgement, judgedObject) + /// The judgement to visualise. + public DrawableTaikoJudgement(JudgementResult result, DrawableHitObject judgedObject) + : base(result, judgedObject) { } [BackgroundDependencyLoader] private void load(OsuColour colours) { - switch (Judgement.Result) + switch (Result.Type) { case HitResult.Good: Colour = colours.GreenLight; @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.UI protected override void LoadComplete() { - if (Judgement.IsHit) + if (Result.IsHit) this.MoveToY(-100, 500); base.LoadComplete(); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 4cb8dd48a7..40198a701a 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -224,28 +224,28 @@ namespace osu.Game.Rulesets.Taiko.UI } } - internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) { if (!DisplayJudgements) return; if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null) { - judgementContainer.Add(new DrawableTaikoJudgement(judgement, judgedObject) + judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) { - Anchor = judgement.IsHit ? Anchor.TopLeft : Anchor.CentreLeft, - Origin = judgement.IsHit ? Anchor.BottomCentre : Anchor.Centre, + Anchor = result.IsHit ? Anchor.TopLeft : Anchor.CentreLeft, + Origin = result.IsHit ? Anchor.BottomCentre : Anchor.Centre, RelativePositionAxes = Axes.X, - X = judgement.IsHit ? judgedObject.Position.X : 0, + X = result.IsHit ? judgedObject.Position.X : 0, }); } - if (!judgement.IsHit) + if (!result.IsHit) return; bool isRim = judgedObject.HitObject is RimHit; - if (judgement is TaikoStrongHitJudgement) + if (result.Judgement is TaikoStrongHitJudgement) hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == judgedObject)?.VisualiseSecondHit(); else { From 4548d2c87f72dfe0542d45d0f64f112f9ee86f1f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 20:36:38 +0900 Subject: [PATCH 071/277] Make Rulesets.Osu use the new judgement result structure --- .../TestCaseHitCircle.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs | 6 +-- .../Judgements/ComboResult.cs | 17 ++++++++ .../Judgements/OsuJudgement.cs | 3 -- .../Judgements/OsuJudgementResult.cs | 17 ++++++++ .../Objects/Drawables/DrawableHitCircle.cs | 5 ++- .../Objects/Drawables/DrawableOsuHitObject.cs | 24 ++++++------ .../Objects/Drawables/DrawableOsuJudgement.cs | 6 +-- .../Objects/Drawables/DrawableRepeatPoint.cs | 3 +- .../Objects/Drawables/DrawableSlider.cs | 14 +++---- .../Objects/Drawables/DrawableSliderTail.cs | 3 +- .../Objects/Drawables/DrawableSliderTick.cs | 3 +- .../Objects/Drawables/DrawableSpinner.cs | 10 ++--- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 5 +++ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 9 ----- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 5 +++ osu.Game.Rulesets.Osu/Objects/Slider.cs | 4 ++ .../Objects/SliderTailCircle.cs | 4 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 5 +++ osu.Game.Rulesets.Osu/Objects/Spinner.cs | 5 +++ .../Scoring/OsuScoreProcessor.cs | 39 +++++-------------- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 4 +- 22 files changed, 112 insertions(+), 81 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Judgements/ComboResult.cs create mode 100644 osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index eea5aa9a52..e44016e48b 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && timeOffset > 0) { // force success - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Great); + ApplyResult(Results.Single(), r => r.Type = HitResult.Great); } else base.CheckForJudgements(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index cb1ea5cc5f..2da4d8265d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -310,7 +310,7 @@ namespace osu.Game.Rulesets.Osu.Tests } private float judgementOffsetDirection = 1; - private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) + private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) { var osuObject = judgedObject as DrawableOsuHitObject; if (osuObject == null) @@ -321,8 +321,8 @@ namespace osu.Game.Rulesets.Osu.Tests { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = judgement.IsHit ? "Hit!" : "Miss!", - Colour = judgement.IsHit ? Color4.Green : Color4.Red, + Text = result.IsHit ? "Hit!" : "Miss!", + Colour = result.IsHit ? Color4.Green : Color4.Red, TextSize = 30, Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) }); diff --git a/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs new file mode 100644 index 0000000000..3000031c78 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Judgements/ComboResult.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; + +namespace osu.Game.Rulesets.Osu.Judgements +{ + public enum ComboResult + { + [Description(@"")] + None, + [Description(@"Good")] + Good, + [Description(@"Amazing")] + Perfect + } +} diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 26becfdec9..b1c9760866 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Judgements @@ -25,7 +24,5 @@ namespace osu.Game.Rulesets.Osu.Judgements return 300; } } - - public ComboResult Combo; } } diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs new file mode 100644 index 0000000000..17b8b4399f --- /dev/null +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgementResult.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Judgements; + +namespace osu.Game.Rulesets.Osu.Judgements +{ + public class OsuJudgementResult : JudgementResult + { + public ComboResult ComboType; + + public OsuJudgementResult(Judgement judgement) + : base(judgement) + { + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 7fd4d11455..a09748e450 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -81,7 +82,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); return; } @@ -90,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None) return; - ApplyJudgement(HitObject.Judgement, j => j.Result = result); + ApplyResult(Results.Single(), r => r.Type = result); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 6e24f1bc83..187cbc29a2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -2,11 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.ComponentModel; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using System.Linq; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using OpenTK.Graphics; @@ -34,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), HitObject.Judgements.FirstOrDefault()?.TimeOffset ?? 0); + var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Results.FirstOrDefault()?.TimeOffset ?? 0); using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true)) UpdateCurrentState(state); @@ -57,20 +58,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables // Todo: At some point we need to move these to DrawableHitObject after ensuring that all other Rulesets apply // transforms in the same way and don't rely on them not being cleared - public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { } - public override void ApplyTransformsAt(double time, bool propagateChildren = false) { } + public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) + { + } + + public override void ApplyTransformsAt(double time, bool propagateChildren = false) + { + } private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - } - public enum ComboResult - { - [Description(@"")] - None, - [Description(@"Good")] - Good, - [Description(@"Amazing")] - Perfect + protected override JudgementResult CreateJudgementResult(Judgement judgement) => new OsuJudgementResult(judgement); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index e8743281da..04ec3f13c7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -11,14 +11,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuJudgement : DrawableJudgement { - public DrawableOsuJudgement(Judgement judgement, DrawableHitObject judgedObject) - : base(judgement, judgedObject) + public DrawableOsuJudgement(JudgementResult result, DrawableHitObject judgedObject) + : base(result, judgedObject) { } protected override void LoadComplete() { - if (Judgement.Result != HitResult.Miss) + if (Result.Type != HitResult.Miss) JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); base.LoadComplete(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 809b27e065..7ef56f07e2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; @@ -44,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) - ApplyJudgement(HitObject.Judgement, j => j.Result = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 6739c3a822..fc6510471b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -136,21 +136,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (userTriggered || Time.Current < slider.EndTime) return; - ApplyJudgement(HitObject.Judgement, j => + ApplyResult(Results.Single(), r => { var judgementsCount = NestedHitObjects.Count(); var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; - if (hitFraction == 1 && HeadCircle.HitObject.Judgement.Result == HitResult.Great) - j.Result = HitResult.Great; - else if (hitFraction >= 0.5 && HeadCircle.HitObject.Judgement.Result >= HitResult.Good) - j.Result = HitResult.Good; + if (hitFraction == 1 && HeadCircle.Results.Single().Type == HitResult.Great) + r.Type = HitResult.Great; + else if (hitFraction >= 0.5 && HeadCircle.Results.Single().Type >= HitResult.Good) + r.Type = HitResult.Good; else if (hitFraction > 0) - j.Result = HitResult.Meh; + r.Type = HitResult.Meh; else - j.Result = HitResult.Miss; + r.Type = HitResult.Miss; }); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 64c4a8ef18..7cbb7db6d4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; @@ -31,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered && timeOffset >= 0) - ApplyJudgement(HitObject.Judgement, j => j.Result = Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index f7b403a5cc..c4c853cb58 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -50,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - ApplyJudgement(HitObject.Judgement, j => j.Result = Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 4a0303f00f..4db928c578 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -138,16 +138,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (userTriggered || Time.Current < Spinner.EndTime) return; - ApplyJudgement(HitObject.Judgement, j => + ApplyResult(Results.Single(), r => { if (Progress >= 1) - j.Result = HitResult.Great; + r.Type = HitResult.Great; else if (Progress > .9) - j.Result = HitResult.Good; + r.Type = HitResult.Good; else if (Progress > .75) - j.Result = HitResult.Meh; + r.Type = HitResult.Meh; else if (Time.Current >= Spinner.EndTime) - j.Result = HitResult.Miss; + r.Type = HitResult.Miss; }); } diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index 9e309a376d..2514988e9f 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,9 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; + namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { + protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 3927ed02d5..48a6365c00 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -2,15 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; using OpenTK; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit.Types; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -76,11 +73,5 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual void OffsetPosition(Vector2 offset) => Position += offset; protected override HitWindows CreateHitWindows() => new OsuHitWindows(); - - public OsuJudgement Judgement { get; private set; } - - protected override IEnumerable CreateJudgements() => new[] { Judgement = CreateJudgement() }; - - protected virtual OsuJudgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index 3495bc1b4b..ef794eafdb 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -2,8 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -24,5 +27,7 @@ namespace osu.Game.Rulesets.Osu.Objects if (RepeatIndex > 0) TimePreempt = Math.Min(SpanDuration * 2, TimePreempt); } + + protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 972dd42fd6..54899fb9f5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -10,6 +10,8 @@ using System.Linq; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -211,5 +213,7 @@ namespace osu.Game.Rulesets.Osu.Objects }); } } + + protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 3fae9e9f8a..93c8d94920 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,6 +1,8 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects @@ -12,6 +14,6 @@ namespace osu.Game.Rulesets.Osu.Objects { } - protected override OsuJudgement CreateJudgement() => new OsuSliderTailJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new OsuSliderTailJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 54337a12be..24ab812649 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,8 +1,11 @@ // Copyright (c) 2007-2018 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 osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -26,5 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = (StartTime - SpanStartTime) / 2 + offset; } + + protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 503ad85674..f7bb806503 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -2,9 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Judgements; namespace osu.Game.Rulesets.Osu.Objects { @@ -29,5 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects // spinning doesn't match 1:1 with stable, so let's fudge them easier for the time being. SpinsRequired = (int)Math.Max(1, SpinsRequired * 0.6); } + + protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 01b92255ae..a8f656bc6b 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -2,13 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -26,28 +24,11 @@ namespace osu.Game.Rulesets.Osu.Scoring private readonly Dictionary scoreResultCounts = new Dictionary(); private readonly Dictionary comboResultCounts = new Dictionary(); - protected override void SimulateAutoplay(Beatmap beatmap) + protected override void ApplyBeatmap(Beatmap beatmap) { + base.ApplyBeatmap(beatmap); + hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; - - foreach (var obj in beatmap.HitObjects) - { - if (obj is Slider slider) - { - // Head - AddJudgement(new OsuJudgement { Result = HitResult.Great }); - - // Ticks - foreach (var unused in slider.NestedHitObjects.OfType()) - AddJudgement(new OsuJudgement { Result = HitResult.Great }); - - //Repeats - foreach (var unused in slider.NestedHitObjects.OfType()) - AddJudgement(new OsuJudgement { Result = HitResult.Great }); - } - - AddJudgement(new OsuJudgement { Result = HitResult.Great }); - } } protected override void Reset(bool storeResults) @@ -70,19 +51,19 @@ namespace osu.Game.Rulesets.Osu.Scoring private const double harshness = 0.01; - protected override void OnNewJudgement(Judgement judgement) + protected override void OnNewJudgement(JudgementResult result) { - base.OnNewJudgement(judgement); + base.OnNewJudgement(result); - var osuJudgement = (OsuJudgement)judgement; + var osuResult = (OsuJudgementResult)result; - if (judgement.Result != HitResult.None) + if (result.Type != HitResult.None) { - scoreResultCounts[judgement.Result] = scoreResultCounts.GetOrDefault(judgement.Result) + 1; - comboResultCounts[osuJudgement.Combo] = comboResultCounts.GetOrDefault(osuJudgement.Combo) + 1; + scoreResultCounts[result.Type] = scoreResultCounts.GetOrDefault(result.Type) + 1; + comboResultCounts[osuResult.ComboType] = comboResultCounts.GetOrDefault(osuResult.ComboType) + 1; } - switch (judgement.Result) + switch (result.Type) { case HitResult.Great: Health.Value += (10.2 - hpDrainRate) * harshness; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index b0ba9afee6..8a898fb5e2 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -64,12 +64,12 @@ namespace osu.Game.Rulesets.Osu.UI connectionLayer.HitObjects = HitObjects.Objects.Select(d => d.HitObject).OfType(); } - private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) + private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) { if (!judgedObject.DisplayJudgement || !DisplayJudgements) return; - DrawableOsuJudgement explosion = new DrawableOsuJudgement(judgement, judgedObject) + DrawableOsuJudgement explosion = new DrawableOsuJudgement(result, judgedObject) { Origin = Anchor.Centre, Position = ((OsuHitObject)judgedObject.HitObject).StackedEndPosition From 807794d512bdbd35d5e45d7fc0a20390ad79cf46 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 20:36:54 +0900 Subject: [PATCH 072/277] Make Rulesets.Mania use the new judgement result structure --- .../Judgements/HoldNoteTailJudgement.cs | 27 -------------- .../Objects/Drawables/DrawableHoldNote.cs | 21 +++++------ .../Objects/Drawables/DrawableHoldNoteTick.cs | 5 +-- .../Objects/Drawables/DrawableNote.cs | 5 +-- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 4 +-- .../Objects/HoldNoteTick.cs | 4 +-- osu.Game.Rulesets.Mania/Objects/Note.cs | 4 +-- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 4 ++- .../Scoring/ManiaScoreProcessor.cs | 36 +++++++------------ osu.Game.Rulesets.Mania/UI/Column.cs | 4 +-- .../UI/DrawableManiaJudgement.cs | 6 ++-- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 4 +-- 12 files changed, 39 insertions(+), 85 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs deleted file mode 100644 index 3a4beda77d..0000000000 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Mania.Judgements -{ - public class HoldNoteTailJudgement : ManiaJudgement - { - /// - /// Whether the hold note has been released too early and shouldn't give full score for the release. - /// - public bool HasBroken; - - protected override int NumericResultFor(HitResult result) - { - switch (result) - { - default: - return base.NumericResultFor(result); - case HitResult.Great: - case HitResult.Perfect: - return base.NumericResultFor(HasBroken ? HitResult.Good : result); - } - } - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 2e64c1796a..a3a81245a2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; @@ -100,7 +99,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (tail.AllJudged) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Perfect); + ApplyResult(Results.Single(), r => r.Type = HitResult.Perfect); } protected override void Update() @@ -166,7 +165,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return false; // If the key has been released too early, the user should not receive full score for the release - if (HitObject.Judgement.Result == HitResult.Miss) + if (Results.Single().Type == HitResult.Miss) holdNote.hasBroken = true; // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held @@ -205,13 +204,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - { - ApplyJudgement(holdNote.HitObject.Tail.Judgement, j => - { - j.Result = HitResult.Miss; - ((HoldNoteTailJudgement)j).HasBroken = holdNote.hasBroken; - }); - } + ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); return; } @@ -220,10 +213,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - ApplyJudgement(holdNote.HitObject.Tail.Judgement, j => + ApplyResult(Results.Single(), r => { - j.Result = result; - ((HoldNoteTailJudgement)j).HasBroken = holdNote.hasBroken; + if (holdNote.hasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) + result = HitResult.Good; + + r.Type = result; }); } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index c281045591..6f718ef5ab 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; @@ -79,9 +80,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables var startTime = HoldStartTime?.Invoke(); if (startTime == null || startTime > HitObject.StartTime) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); else - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Perfect); + ApplyResult(Results.Single(), r => r.Type = HitResult.Perfect); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index bc1033bead..ad4969207d 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -60,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyJudgement(HitObject.Judgement, j => j.Result = HitResult.Miss); + ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); return; } @@ -68,7 +69,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - ApplyJudgement(HitObject.Judgement, j => j.Result = result); + ApplyResult(Results.Single(), r => r.Type = result); } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 033434a989..8a22ff1bf6 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -98,8 +98,6 @@ namespace osu.Game.Rulesets.Mania.Objects } } - public HoldNoteJudgement Judgement { get; private set; } - - protected override IEnumerable CreateJudgements() => new[] { Judgement = new HoldNoteJudgement() }; + protected override IEnumerable CreateJudgements() => new[] { new HoldNoteJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 73ad3d94ec..9056310cf2 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -12,8 +12,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteTick : ManiaHitObject { - public HoldNoteTickJudgement Judgement { get; private set; } - - protected override IEnumerable CreateJudgements() => new[] { Judgement = new HoldNoteTickJudgement() }; + protected override IEnumerable CreateJudgements() => new[] { new HoldNoteTickJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index ebda40de85..911bd2b0a2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -12,8 +12,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - public virtual ManiaJudgement Judgement { get; } = new ManiaJudgement(); - - protected override IEnumerable CreateJudgements() => new[] { Judgement }; + protected override IEnumerable CreateJudgements() => new[] { new ManiaJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index 530f3c6ff1..0f00ee3938 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; namespace osu.Game.Rulesets.Mania.Objects { public class TailNote : Note { - public override ManiaJudgement Judgement { get; } = new HoldNoteTailJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new ManiaJudgement() }; } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 4c955a680e..289bcc3d34 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -97,31 +96,20 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - protected override void SimulateAutoplay(Beatmap beatmap) + protected override void ApplyBeatmap(Beatmap beatmap) { + base.ApplyBeatmap(beatmap); + BeatmapDifficulty difficulty = beatmap.BeatmapInfo.BaseDifficulty; hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max); hpMissMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_miss_min, hp_multiplier_miss_mid, hp_multiplier_miss_max); + } + protected override void SimulateAutoplay(Beatmap beatmap) + { while (true) { - foreach (var obj in beatmap.HitObjects) - { - var holdNote = obj as HoldNote; - - if (holdNote != null) - { - // Head - AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); - - // Ticks - int tickCount = holdNote.NestedHitObjects.OfType().Count(); - for (int i = 0; i < tickCount; i++) - AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect }); - } - - AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); - } + base.SimulateAutoplay(beatmap); if (!HasFailed) break; @@ -133,20 +121,20 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override void OnNewJudgement(Judgement judgement) + protected override void OnNewJudgement(JudgementResult result) { - base.OnNewJudgement(judgement); + base.OnNewJudgement(result); - bool isTick = judgement is HoldNoteTickJudgement; + bool isTick = result.Judgement is HoldNoteTickJudgement; if (isTick) { - if (judgement.IsHit) + if (result.IsHit) Health.Value += hpMultiplier * hp_increase_tick; } else { - switch (judgement.Result) + switch (result.Type) { case HitResult.Miss: Health.Value += hpMissMultiplier * hp_increase_miss; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 877189dd61..ca7173ec50 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -136,9 +136,9 @@ namespace osu.Game.Rulesets.Mania.UI HitObjects.Add(hitObject); } - internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgement.IsHit || !judgedObject.DisplayJudgement || !DisplayJudgements) + if (!result.IsHit || !judgedObject.DisplayJudgement || !DisplayJudgements) return; explosionContainer.Add(new HitExplosion(judgedObject) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 6566d44ef5..dccd6f09fd 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -10,8 +10,8 @@ namespace osu.Game.Rulesets.Mania.UI { internal class DrawableManiaJudgement : DrawableJudgement { - public DrawableManiaJudgement(Judgement judgement, DrawableHitObject judgedObject) - : base(judgement, judgedObject) + public DrawableManiaJudgement(JudgementResult result, DrawableHitObject judgedObject) + : base(result, judgedObject) { } @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.UI this.FadeInFromZero(50, Easing.OutQuint); - if (Judgement.IsHit) + if (Result.IsHit) { this.ScaleTo(0.8f); this.ScaleTo(1, 250, Easing.OutElastic); diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index f386cf15a2..9072e044bd 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -161,13 +161,13 @@ namespace osu.Game.Rulesets.Mania.UI public void Add(BarLine barline) => base.Add(new DrawableBarLine(barline)); - internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) { if (!judgedObject.DisplayJudgement || !DisplayJudgements) return; judgements.Clear(); - judgements.Add(new DrawableManiaJudgement(judgement, judgedObject) + judgements.Add(new DrawableManiaJudgement(result, judgedObject) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 9dff5cea07089425821a19cb1a385186a150eb02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 20:37:07 +0900 Subject: [PATCH 073/277] Make Rulesets.Catch use the new judgement result structure --- .../Judgements/CatchBananaJudgement.cs | 5 +- .../Judgements/CatchJudgement.cs | 30 ++++++------ osu.Game.Rulesets.Catch/Objects/Banana.cs | 4 +- .../Objects/CatchHitObject.cs | 8 ---- .../Drawable/DrawableCatchHitObject.cs | 7 ++- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 6 ++- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 6 ++- .../Objects/ICatchObjectWithJudgement.cs | 12 ----- .../Objects/TinyDroplet.cs | 4 +- .../Scoring/CatchScoreProcessor.cs | 46 ++++--------------- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 6 +-- 12 files changed, 50 insertions(+), 87 deletions(-) delete mode 100644 osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs index c39e663d75..f38009263f 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchBananaJudgement.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Judgements @@ -9,8 +10,6 @@ namespace osu.Game.Rulesets.Catch.Judgements { public override bool AffectsCombo => false; - public override bool ShouldExplode => true; - protected override int NumericResultFor(HitResult result) { switch (result) @@ -32,5 +31,7 @@ namespace osu.Game.Rulesets.Catch.Judgements return 8; } } + + public override bool ShouldExplodeFor(JudgementResult result) => true; } } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index 51d7d3b5cd..8a51867899 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -23,21 +23,10 @@ namespace osu.Game.Rulesets.Catch.Judgements } /// - /// The base health increase for the result achieved. + /// Retrieves the numeric health increase of a . /// - public float HealthIncrease => HealthIncreaseFor(Result); - - /// - /// Whether fruit on the platter should explode or drop. - /// Note that this is only checked if the owning object is also - /// - public virtual bool ShouldExplode => IsHit; - - /// - /// Convert a to a base health increase. - /// - /// The value to convert. - /// The base health increase. + /// The to find the numeric health increase for. + /// The numeric health increase of . protected virtual float HealthIncreaseFor(HitResult result) { switch (result) @@ -48,5 +37,18 @@ namespace osu.Game.Rulesets.Catch.Judgements return 10.2f; } } + + /// + /// Retrieves the numeric health increase of a . + /// + /// The to find the numeric health increase for. + /// The numeric health increase of . + public float HealthIncreaseFor(JudgementResult result) => HealthIncreaseFor(result.Type); + + /// + /// Whether fruit on the platter should explode or drop. + /// Note that this is only checked if the owning object is also + /// + public virtual bool ShouldExplodeFor(JudgementResult result) => result.IsHit; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index d0f4f6c5db..1b84869172 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Catch.Objects { @@ -9,6 +11,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; - public override CatchJudgement Judgement { get; } = new CatchBananaJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new CatchBananaJudgement() }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 7f2cff561e..d55cdac115 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,10 +1,8 @@ // Copyright (c) 2007-2018 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 osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -56,12 +54,6 @@ namespace osu.Game.Rulesets.Catch.Objects } protected override HitWindows CreateHitWindows() => null; - - protected override IEnumerable CreateJudgements() - { - if (this is ICatchObjectWithJudgement judgeable) - yield return judgeable.Judgement; - } } public enum FruitVisualRepresentation diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 126977ecb2..019a4779ac 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -56,10 +57,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { if (CheckPosition == null) return; - if (timeOffset >= 0 && HitObject is ICatchObjectWithJudgement judgeable) - { - ApplyJudgement(judgeable.Judgement, j => j.Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); - } + if (timeOffset >= 0 && Results.Count > 0) + ApplyResult(Results.Single(), r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } protected override void SkinChanged(ISkinSource skin, bool allowFallback) diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index e92b06d0d1..a6e7d29305 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Catch.Objects { - public class Droplet : CatchHitObject, ICatchObjectWithJudgement + public class Droplet : CatchHitObject { - public virtual CatchJudgement Judgement { get; } = new CatchDropletJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new CatchDropletJudgement() }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 4bcb1a400f..fd9cd13beb 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Catch.Objects { - public class Fruit : CatchHitObject, ICatchObjectWithJudgement + public class Fruit : CatchHitObject { - public virtual CatchJudgement Judgement { get; } = new CatchJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new CatchJudgement() }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs b/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs deleted file mode 100644 index 2aa5a5c83a..0000000000 --- a/osu.Game.Rulesets.Catch/Objects/ICatchObjectWithJudgement.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Catch.Judgements; - -namespace osu.Game.Rulesets.Catch.Objects -{ - public interface ICatchObjectWithJudgement - { - CatchJudgement Judgement { get; } - } -} diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index d7cc002dfc..069d3be5c0 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,12 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Judgements; namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { - public override CatchJudgement Judgement { get; } = new CatchTinyDropletJudgement(); + protected override IEnumerable CreateJudgements() => new[] { new CatchTinyDropletJudgement() }; } } diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 5b69d836a3..183c6f0f12 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Objects; @@ -21,55 +20,28 @@ namespace osu.Game.Rulesets.Catch.Scoring private float hpDrainRate; - protected override void SimulateAutoplay(Beatmap beatmap) + protected override void ApplyBeatmap(Beatmap beatmap) { - hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; + base.ApplyBeatmap(beatmap); - foreach (var obj in beatmap.HitObjects) - { - switch (obj) - { - case JuiceStream stream: - foreach (var nestedObject in stream.NestedHitObjects) - switch (nestedObject) - { - case TinyDroplet _: - AddJudgement(new CatchTinyDropletJudgement { Result = HitResult.Perfect }); - break; - case Droplet _: - AddJudgement(new CatchDropletJudgement { Result = HitResult.Perfect }); - break; - case Fruit _: - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - break; - } - break; - case BananaShower shower: - foreach (var _ in shower.NestedHitObjects.Cast()) - AddJudgement(new CatchBananaJudgement { Result = HitResult.Perfect }); - break; - case Fruit _: - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - break; - } - } + hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate; } private const double harshness = 0.01; - protected override void OnNewJudgement(Judgement judgement) + protected override void OnNewJudgement(JudgementResult result) { - base.OnNewJudgement(judgement); + base.OnNewJudgement(result); - if (judgement.Result == HitResult.Miss) + if (result.Type == HitResult.Miss) { - if (!judgement.IsBonus) + if (!result.Judgement.IsBonus) Health.Value -= hpDrainRate * (harshness * 2); return; } - if (judgement is CatchJudgement catchJudgement) - Health.Value += Math.Max(catchJudgement.HealthIncrease - hpDrainRate, 0) * harshness; + if (result.Judgement is CatchJudgement catchJudgement) + Health.Value += Math.Max(catchJudgement.HealthIncreaseFor(result) - hpDrainRate, 0) * harshness; } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index ea3b6fb0e0..7b52066d15 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -67,6 +67,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.CheckPosition = CheckIfWeCanCatch; } - private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, judgement); + private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) + => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, result); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 7b06426b07..ca9fa6f595 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Catch.UI private DrawableCatchHitObject lastPlateableFruit; - public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement) + public void OnJudgement(DrawableCatchHitObject fruit, JudgementResult result) { void runAfterLoaded(Action action) { @@ -63,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.UI lastPlateableFruit.OnLoadComplete = _ => action(); } - if (judgement.IsHit && fruit.CanBePlated) + if (result.IsHit && fruit.CanBePlated) { var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.UI if (fruit.HitObject.LastInCombo) { - if (((CatchJudgement)judgement).ShouldExplode) + if (((CatchJudgement)result.Judgement).ShouldExplodeFor(result)) runAfterLoaded(() => MovableCatcher.Explode()); else MovableCatcher.Drop(); From 8d81e66f886f0e10f2d7232087c562a96c578f6a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 21:07:11 +0900 Subject: [PATCH 074/277] Fix osu score processor crashing --- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 2 ++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index a8f656bc6b..2986b4b5dc 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -86,5 +86,7 @@ namespace osu.Game.Rulesets.Osu.Scoring break; } } + + protected override JudgementResult CreateJudgementResult(Judgement judgement) => new OsuJudgementResult(judgement); } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ccd3fb6e69..64dcf150cf 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -225,7 +225,12 @@ namespace osu.Game.Rulesets.Scoring simulate(nested); foreach (var judgement in obj.Judgements) - AddJudgement(new JudgementResult(judgement) { Type = judgement.MaxResult }); + { + var result = CreateJudgementResult(judgement); + result.Type = judgement.MaxResult; + + AddJudgement(result); + } } } @@ -350,6 +355,8 @@ namespace osu.Game.Rulesets.Scoring rollingMaxBaseScore = 0; bonusScore = 0; } + + protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); } public enum ScoringMode From 35b4ab545646b80501a7d12a60957f67459b14e7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 21:07:31 +0900 Subject: [PATCH 075/277] Introduce the concept of a "MainResult" --- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 4 +-- .../Objects/Drawables/DrawableHitObject.cs | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index 2dec6019eb..fef7f4b889 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -21,10 +21,10 @@ namespace osu.Game.Rulesets.Taiko.Objects protected override IEnumerable CreateJudgements() { - yield return new TaikoJudgement(); - for (int i = 0; i < RequiredHits; i++) yield return new TaikoIntermediateSwellJudgement(); + + yield return new TaikoJudgement(); } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 27de18177f..06f2d689d8 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -62,6 +62,13 @@ namespace osu.Game.Rulesets.Objects.Drawables private readonly List results = new List(); public IReadOnlyList Results => results; + /// + /// The that affects whether this has been hit or missed. + /// By default, this is the last in , and should be overridden if the order + /// of s in doesn't list the main as its last element. + /// + protected virtual JudgementResult MainResult => Results.LastOrDefault(); + private bool judgementOccurred; public bool Interactive = true; @@ -192,16 +199,19 @@ namespace osu.Game.Rulesets.Objects.Drawables var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; result.TimeOffset = Time.Current - endTime; - switch (result.Type) + if (result == MainResult) { - case HitResult.None: - break; - case HitResult.Miss: - State.Value = ArmedState.Miss; - break; - default: - State.Value = ArmedState.Hit; - break; + switch (result.Type) + { + case HitResult.None: + break; + case HitResult.Miss: + State.Value = ArmedState.Miss; + break; + default: + State.Value = ArmedState.Hit; + break; + } } OnJudgement?.Invoke(this, result); From a0887a600f671453b8221141e004c41e87f5097e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 21:08:06 +0900 Subject: [PATCH 076/277] Fix swells showing hit circles on intermediate judgements --- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 40198a701a..7147972c58 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -229,7 +229,10 @@ namespace osu.Game.Rulesets.Taiko.UI if (!DisplayJudgements) return; - if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null) + if (!judgedObject.DisplayJudgement) + return; + + if (judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null) { judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) { From 0da6c8c1a7931980a4e35f4d0b5519776548b344 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 2 Aug 2018 22:20:07 +0900 Subject: [PATCH 077/277] Remove unnecessary local variables --- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 58f6a2840a..7e36a896c1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -25,15 +25,12 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double HitWindow => TickSpacing / 2; - public TaikoDrumRollTickJudgement Judgement { get; private set; } - public TaikoStrongHitJudgement StrongJudgement { get; private set; } - protected override IEnumerable CreateJudgements() { - yield return Judgement = new TaikoDrumRollTickJudgement(); + yield return new TaikoDrumRollTickJudgement(); if (IsStrong) - yield return StrongJudgement = new TaikoStrongHitJudgement(); + yield return new TaikoStrongHitJudgement(); } } } From 123f304cf1b0e9ad1322eed614b798531db03dea Mon Sep 17 00:00:00 2001 From: jorolf Date: Thu, 2 Aug 2018 19:24:17 +0200 Subject: [PATCH 078/277] update storage usages --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 67f02c8ac4..0ff6c3d98c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -329,7 +329,7 @@ namespace osu.Game.Beatmaps return; } - await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs")), TaskCreationOptions.LongRunning); + await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(stable.GetUsablePathFor).ToArray()), TaskCreationOptions.LongRunning); } /// From 2a4994e5cedc64ae7bf5d7d49b7e9573557af6c5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 15:38:48 +0900 Subject: [PATCH 079/277] Make hitobjects only have one judgement + result --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 3 +- .../Drawable/DrawableCatchHitObject.cs | 5 +- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 3 +- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 3 +- .../Objects/TinyDroplet.cs | 3 +- .../Objects/Drawables/DrawableHoldNote.cs | 8 +-- .../Objects/Drawables/DrawableHoldNoteTick.cs | 5 +- .../Objects/Drawables/DrawableNote.cs | 5 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 3 +- .../Objects/HoldNoteTick.cs | 3 +- osu.Game.Rulesets.Mania/Objects/Note.cs | 3 +- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 3 +- .../TestCaseHitCircle.cs | 2 +- .../Objects/Drawables/DrawableHitCircle.cs | 5 +- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 +- .../Objects/Drawables/DrawableRepeatPoint.cs | 3 +- .../Objects/Drawables/DrawableSlider.cs | 6 +- .../Objects/Drawables/DrawableSliderTail.cs | 3 +- .../Objects/Drawables/DrawableSliderTick.cs | 3 +- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 3 +- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 3 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- .../Objects/SliderTailCircle.cs | 3 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 3 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 3 +- .../Objects/Drawables/DrawableHitObject.cs | 64 +++++++------------ osu.Game/Rulesets/Objects/HitObject.cs | 9 +-- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 12 ++-- 29 files changed, 66 insertions(+), 110 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index 1b84869172..e021bafdb6 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; @@ -11,6 +10,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; - protected override IEnumerable CreateJudgements() => new[] { new CatchBananaJudgement() }; + protected override Judgement CreateJudgement() => new CatchBananaJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 019a4779ac..982fa193c6 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -57,8 +56,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { if (CheckPosition == null) return; - if (timeOffset >= 0 && Results.Count > 0) - ApplyResult(Results.Single(), r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); + if (timeOffset >= 0 && Result != null) + ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss); } protected override void SkinChanged(ISkinSource skin, bool allowFallback) diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index a6e7d29305..79aefdb6d3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; @@ -9,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Droplet : CatchHitObject { - protected override IEnumerable CreateJudgements() => new[] { new CatchDropletJudgement() }; + protected override Judgement CreateJudgement() => new CatchDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index fd9cd13beb..53a484ed56 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; @@ -9,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Fruit : CatchHitObject { - protected override IEnumerable CreateJudgements() => new[] { new CatchJudgement() }; + protected override Judgement CreateJudgement() => new CatchJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 069d3be5c0..ddb88c2c1c 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Judgements; @@ -9,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { - protected override IEnumerable CreateJudgements() => new[] { new CatchTinyDropletJudgement() }; + protected override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index a3a81245a2..da4bf1c575 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (tail.AllJudged) - ApplyResult(Results.Single(), r => r.Type = HitResult.Perfect); + ApplyResult(r => r.Type = HitResult.Perfect); } protected override void Update() @@ -165,7 +165,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return false; // If the key has been released too early, the user should not receive full score for the release - if (Results.Single().Type == HitResult.Miss) + if (Result.Type == HitResult.Miss) holdNote.hasBroken = true; // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held @@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); + ApplyResult(r => r.Type = HitResult.Miss); return; } @@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - ApplyResult(Results.Single(), r => + ApplyResult(r => { if (holdNote.hasBroken && (result == HitResult.Perfect || result == HitResult.Perfect)) result = HitResult.Good; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 6f718ef5ab..05a4ea60d6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Extensions.Color4Extensions; @@ -80,9 +79,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables var startTime = HoldStartTime?.Invoke(); if (startTime == null || startTime > HitObject.StartTime) - ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); + ApplyResult(r => r.Type = HitResult.Miss); else - ApplyResult(Results.Single(), r => r.Type = HitResult.Perfect); + ApplyResult(r => r.Type = HitResult.Perfect); } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index ad4969207d..42b4128019 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Extensions.Color4Extensions; using OpenTK.Graphics; using osu.Framework.Graphics; @@ -61,7 +60,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); + ApplyResult(r => r.Type = HitResult.Miss); return; } @@ -69,7 +68,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (result == HitResult.None) return; - ApplyResult(Results.Single(), r => r.Type = result); + ApplyResult(r => r.Type = result); } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 8a22ff1bf6..26116c2691 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; @@ -98,6 +97,6 @@ namespace osu.Game.Rulesets.Mania.Objects } } - protected override IEnumerable CreateJudgements() => new[] { new HoldNoteJudgement() }; + protected override Judgement CreateJudgement() => new HoldNoteJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 9056310cf2..b428c6158d 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -12,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteTick : ManiaHitObject { - protected override IEnumerable CreateJudgements() => new[] { new HoldNoteTickJudgement() }; + protected override Judgement CreateJudgement() => new HoldNoteTickJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 911bd2b0a2..ffc3ed0bd7 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -12,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - protected override IEnumerable CreateJudgements() => new[] { new ManiaJudgement() }; + protected override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index 0f00ee3938..522f78336f 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Judgements; @@ -9,6 +8,6 @@ namespace osu.Game.Rulesets.Mania.Objects { public class TailNote : Note { - protected override IEnumerable CreateJudgements() => new[] { new ManiaJudgement() }; + protected override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index e44016e48b..79866b8a4a 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Tests if (auto && !userTriggered && timeOffset > 0) { // force success - ApplyResult(Results.Single(), r => r.Type = HitResult.Great); + ApplyResult(r => r.Type = HitResult.Great); } else base.CheckForJudgements(userTriggered, timeOffset); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index a09748e450..15521113ed 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.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.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(Results.Single(), r => r.Type = HitResult.Miss); + ApplyResult(r => r.Type = HitResult.Miss); return; } @@ -91,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (result == HitResult.None) return; - ApplyResult(Results.Single(), r => r.Type = result); + ApplyResult(r => r.Type = result); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 187cbc29a2..2529ac20c4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -4,7 +4,6 @@ using System; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; -using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Judgements; @@ -35,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Results.FirstOrDefault()?.TimeOffset ?? 0); + var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Result?.TimeOffset ?? 0); using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true)) UpdateCurrentState(state); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 7ef56f07e2..ea1ee9fb1e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Game.Rulesets.Objects.Drawables; @@ -45,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) - ApplyResult(Results.Single(), r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index fc6510471b..71be07f166 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -136,16 +136,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (userTriggered || Time.Current < slider.EndTime) return; - ApplyResult(Results.Single(), r => + ApplyResult(r => { var judgementsCount = NestedHitObjects.Count(); var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; - if (hitFraction == 1 && HeadCircle.Results.Single().Type == HitResult.Great) + if (hitFraction == 1 && HeadCircle.Result.Type == HitResult.Great) r.Type = HitResult.Great; - else if (hitFraction >= 0.5 && HeadCircle.Results.Single().Type >= HitResult.Good) + else if (hitFraction >= 0.5 && HeadCircle.Result.Type >= HitResult.Good) r.Type = HitResult.Good; else if (hitFraction > 0) r.Type = HitResult.Meh; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 7cbb7db6d4..9261741a12 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Scoring; @@ -32,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered && timeOffset >= 0) - ApplyResult(Results.Single(), r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index c4c853cb58..8819fa962b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -51,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - ApplyResult(Results.Single(), r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); } protected override void UpdatePreemptState() diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 4db928c578..3feb612c8b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (userTriggered || Time.Current < Spinner.EndTime) return; - ApplyResult(Results.Single(), r => + ApplyResult(r => { if (Progress >= 1) r.Type = HitResult.Great; diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index 2514988e9f..b5e64e9e40 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; @@ -9,6 +8,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { - protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index ef794eafdb..83f7f79f39 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; @@ -28,6 +27,6 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = Math.Min(SpanDuration * 2, TimePreempt); } - protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 54899fb9f5..eead98ac28 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -214,6 +214,6 @@ namespace osu.Game.Rulesets.Osu.Objects } } - protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index 93c8d94920..faa325d416 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; @@ -14,6 +13,6 @@ namespace osu.Game.Rulesets.Osu.Objects { } - protected override IEnumerable CreateJudgements() => new[] { new OsuSliderTailJudgement() }; + protected override Judgement CreateJudgement() => new OsuSliderTailJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 24ab812649..000781dec6 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; @@ -30,6 +29,6 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = (StartTime - SpanStartTime) / 2 + offset; } - protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index f7bb806503..d100e33f17 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.ControlPoints; @@ -33,6 +32,6 @@ namespace osu.Game.Rulesets.Osu.Objects SpinsRequired = (int)Math.Max(1, SpinsRequired * 0.6); } - protected override IEnumerable CreateJudgements() => new[] { new OsuJudgement() }; + protected override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 06f2d689d8..2b2daec8c6 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether this and all of its nested s have been hit. /// - public bool IsHit => Results.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit); + public bool IsHit => (Result?.IsHit ?? true) && NestedHitObjects.All(n => n.IsHit); /// /// Whether this and all of its nested s have been judged. @@ -57,17 +57,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether this has been judged. /// Note: This does NOT include nested hitobjects. /// - public bool Judged => Results.All(h => h.HasResult); + public bool Judged => Result?.HasResult ?? true; - private readonly List results = new List(); - public IReadOnlyList Results => results; - - /// - /// The that affects whether this has been hit or missed. - /// By default, this is the last in , and should be overridden if the order - /// of s in doesn't list the main as its last element. - /// - protected virtual JudgementResult MainResult => Results.LastOrDefault(); + public readonly JudgementResult Result; private bool judgementOccurred; @@ -85,8 +77,8 @@ namespace osu.Game.Rulesets.Objects.Drawables { HitObject = hitObject; - foreach (var j in hitObject.Judgements) - results.Add(CreateJudgementResult(j)); + if (hitObject.Judgement != null) + Result = CreateJudgementResult(hitObject.Judgement); } [BackgroundDependencyLoader] @@ -144,20 +136,15 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.Update(); - if (lastUpdateTime > Time.Current) + if (Result != null && lastUpdateTime > Time.Current) { var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - for (int i = Results.Count - 1; i >= 0; i--) + if (Result.TimeOffset + endTime < Time.Current) { - var judgement = Results[i]; + OnJudgementRemoved?.Invoke(this, Result); - if (judgement.TimeOffset + endTime <= Time.Current) - break; - - OnJudgementRemoved?.Invoke(this, judgement); - - judgement.Type = HitResult.None; + Result.Type = HitResult.None; State.Value = ArmedState.Idle; } } @@ -185,36 +172,29 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Notifies that a new judgement has occurred for this . /// /// The . - protected void ApplyResult(JudgementResult result, Action application) + protected void ApplyResult(Action application) { - // Todo: Unsure if we want to keep this - if (!Results.Contains(result)) - throw new ArgumentException($"The applied judgement result must be a part of {Results}."); - - application?.Invoke(result); + application?.Invoke(Result); judgementOccurred = true; // Ensure that the judgement is given a valid time offset, because this may not get set by the caller var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - result.TimeOffset = Time.Current - endTime; + Result.TimeOffset = Time.Current - endTime; - if (result == MainResult) + switch (Result.Type) { - switch (result.Type) - { - case HitResult.None: - break; - case HitResult.Miss: - State.Value = ArmedState.Miss; - break; - default: - State.Value = ArmedState.Hit; - break; - } + case HitResult.None: + break; + case HitResult.Miss: + State.Value = ArmedState.Miss; + break; + default: + State.Value = ArmedState.Hit; + break; } - OnJudgement?.Invoke(this, result); + OnJudgement?.Invoke(this, Result); } /// diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 0e029a8657..531a8bed38 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using Newtonsoft.Json; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Lists; @@ -64,8 +63,7 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; - private readonly List judgements = new List(); - public IReadOnlyList Judgements => judgements; + public Judgement Judgement { get; private set; } /// /// Applies default values to this HitObject. @@ -76,8 +74,7 @@ namespace osu.Game.Rulesets.Objects { ApplyDefaultsToSelf(controlPointInfo, difficulty); - judgements.Clear(); - judgements.AddRange(CreateJudgements()); + Judgement = CreateJudgement(); if (nestedHitObjects.IsValueCreated) nestedHitObjects.Value.Clear(); @@ -111,7 +108,7 @@ namespace osu.Game.Rulesets.Objects { } - protected virtual IEnumerable CreateJudgements() => Enumerable.Empty(); + protected virtual Judgement CreateJudgement() => null; protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 64dcf150cf..985cfce6aa 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -224,13 +224,13 @@ namespace osu.Game.Rulesets.Scoring foreach (var nested in obj.NestedHitObjects) simulate(nested); - foreach (var judgement in obj.Judgements) - { - var result = CreateJudgementResult(judgement); - result.Type = judgement.MaxResult; + if (obj.Judgement == null) + return; - AddJudgement(result); - } + var result = CreateJudgementResult(obj.Judgement); + result.Type = obj.Judgement.MaxResult; + + AddJudgement(result); } } From 482526135fb1396de1ceed319e9f7ebafccf9589 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:07:20 +0900 Subject: [PATCH 080/277] Make IsHit not consider nested hitobjects --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 2b2daec8c6..a22a7a616b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -43,16 +43,17 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual bool DisplayJudgement => true; - /// - /// Whether this and all of its nested s have been hit. - /// - public bool IsHit => (Result?.IsHit ?? true) && NestedHitObjects.All(n => n.IsHit); - /// /// Whether this and all of its nested s have been judged. /// public bool AllJudged => Judged && NestedHitObjects.All(h => h.AllJudged); + /// + /// Whether this has been hit. This occurs if is . + /// Note: This does NOT include nested hitobjects. + /// + public bool IsHit => Result?.IsHit ?? false; + /// /// Whether this has been judged. /// Note: This does NOT include nested hitobjects. From fa3c919e2e986ee8ca74e21df052d136dfa25c40 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:11:38 +0900 Subject: [PATCH 081/277] Fix up taiko judgement creation --- osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 11 ----------- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 9 +-------- osu.Game.Rulesets.Taiko/Objects/Hit.cs | 11 ----------- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 11 ----------- osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 4 ++++ 5 files changed, 5 insertions(+), 41 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 2ed59d3c43..4c9ec5473b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -3,11 +3,8 @@ using osu.Game.Rulesets.Objects.Types; using System; -using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { @@ -84,13 +81,5 @@ namespace osu.Game.Rulesets.Taiko.Objects first = false; } } - - protected override IEnumerable CreateJudgements() - { - yield return new TaikoJudgement(); - - if (IsStrong) - yield return new TaikoStrongHitJudgement(); - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 7e36a896c1..f6a3a5efef 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Judgements; @@ -25,12 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double HitWindow => TickSpacing / 2; - protected override IEnumerable CreateJudgements() - { - yield return new TaikoDrumRollTickJudgement(); - - if (IsStrong) - yield return new TaikoStrongHitJudgement(); - } + protected override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 6795aef730..0b47aa490b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,20 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Taiko.Judgements; - namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoHitObject { - protected override IEnumerable CreateJudgements() - { - yield return new TaikoJudgement(); - - if (IsStrong) - yield return new TaikoStrongHitJudgement(); - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index fef7f4b889..eb6f931af4 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,10 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Collections.Generic; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { @@ -18,13 +15,5 @@ namespace osu.Game.Rulesets.Taiko.Objects /// The number of hits required to complete the swell successfully. /// public int RequiredHits = 10; - - protected override IEnumerable CreateJudgements() - { - for (int i = 0; i < RequiredHits; i++) - yield return new TaikoIntermediateSwellJudgement(); - - yield return new TaikoJudgement(); - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index ffbbe28f2e..f3dfb333b3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -1,7 +1,9 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { @@ -28,6 +30,8 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public bool IsStrong; + protected override Judgement CreateJudgement() => new TaikoJudgement(); + protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } } From 2dff04392e96cc8ddee313d3b616f1b91dc7c51e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:11:57 +0900 Subject: [PATCH 082/277] Re-implement strong judgements via hitobject --- .../Drawables/DrawableStrongHitObject.cs | 19 +++++++++++++++++++ .../Drawables/DrawableTaikoHitObject.cs | 13 +++++++++++++ osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs | 4 ++-- .../Objects/StrongHitObject.cs | 13 +++++++++++++ .../Objects/TaikoHitObject.cs | 8 ++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs create mode 100644 osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs new file mode 100644 index 0000000000..e9d12e9c35 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Taiko.Objects.Drawables +{ + public abstract class DrawableStrongHitObject : DrawableTaikoHitObject + { + protected DrawableStrongHitObject(StrongHitObject strong) + : base(strong) + { + } + + protected override void UpdateState(ArmedState state) + { + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index a6d61f1a5a..b0216768c1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -101,6 +101,17 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Content.Add(MainPiece = CreateMainPiece()); MainPiece.KiaiMode = HitObject.Kiai; + + var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); + if (strongObject != null) + { + var vis = CreateStrongObject(strongObject); + if (vis != null) + { + AddNested(vis); + AddInternal(vis); + } + } } // Normal and clap samples are handled by the drum @@ -109,5 +120,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override string SampleNamespace => "Taiko"; protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); + + protected virtual DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 4c9ec5473b..405ea85f0d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -54,12 +54,12 @@ namespace osu.Game.Rulesets.Taiko.Objects protected override void CreateNestedHitObjects() { - base.CreateNestedHitObjects(); - createTicks(); RequiredGoodHits = NestedHitObjects.Count * Math.Min(0.15, 0.05 + 0.10 / 6 * overallDifficulty); RequiredGreatHits = NestedHitObjects.Count * Math.Min(0.30, 0.10 + 0.20 / 6 * overallDifficulty); + + base.CreateNestedHitObjects(); } private void createTicks() diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs new file mode 100644 index 0000000000..104d662ed8 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Taiko.Judgements; + +namespace osu.Game.Rulesets.Taiko.Objects +{ + public class StrongHitObject : TaikoHitObject + { + protected override Judgement CreateJudgement() => new TaikoStrongHitJudgement(); + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index f3dfb333b3..e0b229d96d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -30,6 +30,14 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public bool IsStrong; + protected override void CreateNestedHitObjects() + { + base.CreateNestedHitObjects(); + + if (IsStrong) + AddNested(new StrongHitObject()); + } + protected override Judgement CreateJudgement() => new TaikoJudgement(); protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); From fdf889359f702a60870d6d4532a0e1b180e39447 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:12:38 +0900 Subject: [PATCH 083/277] Migrate DrawableHit to use a nested hitobject for strong hits --- .../Objects/Drawables/DrawableCentreHit.cs | 2 +- .../Drawables/DrawableCentreHitStrong.cs | 26 ---- .../Objects/Drawables/DrawableHit.cs | 45 ++++--- .../Objects/Drawables/DrawableHitStrong.cs | 111 ------------------ .../Objects/Drawables/DrawableRimHit.cs | 2 +- .../Objects/Drawables/DrawableRimHitStrong.cs | 26 ---- .../Objects/Drawables/DrawableStrongHit.cs | 68 +++++++++++ .../Objects/TaikoHitObject.cs | 3 +- 8 files changed, 101 insertions(+), 182 deletions(-) delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs create mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs index dda96c2caf..a6e9972dd3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableCentreHit : DrawableHit { - protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; + public override TaikoAction[] HitActions { get; } = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; public DrawableCentreHit(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs deleted file mode 100644 index a2dabf2b18..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Game.Graphics; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public class DrawableCentreHitStrong : DrawableHitStrong - { - protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftCentre, TaikoAction.RightCentre }; - - public DrawableCentreHitStrong(Hit hit) - : base(hit) - { - MainPiece.Add(new CentreHitSymbolPiece()); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - MainPiece.AccentColour = colours.PinkDarker; - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 18177ad089..35fa5eb344 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -3,10 +3,8 @@ using System.Linq; using osu.Framework.Graphics; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables @@ -16,21 +14,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A list of keys which can result in hits for this HitObject. /// - protected abstract TaikoAction[] HitActions { get; } - - protected readonly JudgementResult Result; + public abstract TaikoAction[] HitActions { get; } /// - /// Whether the last key pressed is a valid hit key. + /// The action that caused this to be hit. /// - private bool validKeyPressed; + public TaikoAction? HitAction { get; private set; } + + private bool validActionPressed; protected DrawableHit(Hit hit) : base(hit) { FillMode = FillMode.Fit; - - Result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); } protected override void CheckForJudgements(bool userTriggered, double timeOffset) @@ -38,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (!HitObject.HitWindows.CanBeHit(timeOffset)) - ApplyResult(Result, r => r.Type = HitResult.Miss); + ApplyResult(r => r.Type = HitResult.Miss); return; } @@ -46,18 +42,33 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (result == HitResult.None) return; - if (!validKeyPressed) - ApplyResult(Result, r => r.Type = HitResult.Miss); + if (!validActionPressed) + ApplyResult(r => r.Type = HitResult.Miss); else - ApplyResult(Result, r => r.Type = result); + ApplyResult(r => r.Type = result); } public override bool OnPressed(TaikoAction action) { - validKeyPressed = HitActions.Contains(action); + if (Judged) + return false; + + validActionPressed = HitActions.Contains(action); // Only count this as handled if the new judgement is a hit - return UpdateJudgement(true); + var result = UpdateJudgement(true); + + if (IsHit) + HitAction = action; + + return result; + } + + public override bool OnReleased(TaikoAction action) + { + if (action == HitAction) + HitAction = null; + return base.OnReleased(action); } protected override void Update() @@ -78,7 +89,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (State.Value) { case ArmedState.Idle: - validKeyPressed = false; + validActionPressed = false; UnproxyContent(); this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); @@ -114,5 +125,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } } + + protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongHit(hitObject, this); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs deleted file mode 100644 index 7ec0c08f0f..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public abstract class DrawableHitStrong : DrawableHit - { - /// - /// The lenience for the second key press. - /// This does not adjust by map difficulty in ScoreV2 yet. - /// - private const double second_hit_window = 30; - - private readonly JudgementResult strongResult; - - private double firstHitTime; - private bool firstKeyHeld; - private TaikoAction firstHitAction; - - protected DrawableHitStrong(Hit hit) - : base(hit) - { - strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); - } - - protected override void CheckForJudgements(bool userTriggered, double timeOffset) - { - if (!Result.HasResult) - { - base.CheckForJudgements(userTriggered, timeOffset); - return; - } - - if (!Result.IsHit) - { - ApplyResult(strongResult, r => r.Type = HitResult.Miss); - return; - } - - if (!userTriggered) - { - if (timeOffset > second_hit_window) - ApplyResult(strongResult, r => r.Type = HitResult.Miss); - return; - } - - if (Math.Abs(firstHitTime - Time.Current) < second_hit_window) - ApplyResult(strongResult, r => r.Type = HitResult.Great); - } - - protected override void UpdateState(ArmedState state) - { - base.UpdateState(state); - - switch (state) - { - case ArmedState.Idle: - firstHitTime = 0; - firstKeyHeld = false; - break; - } - } - - public override bool OnReleased(TaikoAction action) - { - if (action == firstHitAction) - firstKeyHeld = false; - return base.OnReleased(action); - } - - public override bool OnPressed(TaikoAction action) - { - if (AllJudged) - return false; - - // Check if we've handled the first key - if (!Result.HasResult) - { - // First key hasn't been handled yet, attempt to handle it - bool handled = base.OnPressed(action); - - if (handled) - { - firstHitTime = Time.Current; - firstHitAction = action; - firstKeyHeld = true; - } - - return handled; - } - - // Don't handle represses of the first key - if (firstHitAction == action) - return false; - - // Don't handle invalid hit action presses - if (!HitActions.Contains(action)) - return false; - - // Assume the intention was to hit the strong hit with both keys only if the first key is still being held down - return firstKeyHeld && UpdateJudgement(true); - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs index f2194c6d56..188cafe1db 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableRimHit : DrawableHit { - protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftRim, TaikoAction.RightRim }; + public override TaikoAction[] HitActions { get; } = { TaikoAction.LeftRim, TaikoAction.RightRim }; public DrawableRimHit(Hit hit) : base(hit) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs deleted file mode 100644 index 728fe416f7..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Allocation; -using osu.Game.Graphics; -using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public class DrawableRimHitStrong : DrawableHitStrong - { - protected override TaikoAction[] HitActions { get; } = { TaikoAction.LeftRim, TaikoAction.RightRim }; - - public DrawableRimHitStrong(Hit hit) - : base(hit) - { - MainPiece.Add(new RimHitSymbolPiece()); - } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - MainPiece.AccentColour = colours.BlueDarker; - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs new file mode 100644 index 0000000000..c9767c9aec --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Objects.Drawables +{ + public class DrawableStrongHit : DrawableStrongHitObject + { + /// + /// The lenience for the second key press. + /// This does not adjust by map difficulty in ScoreV2 yet. + /// + private const double second_hit_window = 30; + + private readonly DrawableHit hit; + + public DrawableStrongHit(StrongHitObject strong, DrawableHit hit) + : base(strong) + { + this.hit = hit; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!hit.Result.HasResult) + { + base.CheckForJudgements(userTriggered, timeOffset); + return; + } + + if (!hit.Result.IsHit) + { + ApplyResult(r => r.Type = HitResult.Miss); + return; + } + + if (!userTriggered) + { + if (timeOffset > second_hit_window) + ApplyResult(r => r.Type = HitResult.Miss); + return; + } + + if (Math.Abs(hit.Result.TimeOffset - timeOffset) < second_hit_window) + ApplyResult(r => r.Type = HitResult.Great); + } + + public override bool OnPressed(TaikoAction action) + { + // Don't process actions until the main hitobject is hit + if (!hit.IsHit) + return false; + + // Don't process actions if the pressed button was released + if (hit.HitAction == null) + return false; + + // Don't handle invalid hit action presses + if (!hit.HitActions.Contains(action)) + return false; + + return UpdateJudgement(true); + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index e0b229d96d..702b6d73b6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -3,6 +3,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects @@ -35,7 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Objects base.CreateNestedHitObjects(); if (IsStrong) - AddNested(new StrongHitObject()); + AddNested(new StrongHitObject { StartTime = (this as IHasEndTime)?.EndTime ?? StartTime }); } protected override Judgement CreateJudgement() => new TaikoJudgement(); From 449485344659d7fc12f52c046a34ce2e07da876f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:20:08 +0900 Subject: [PATCH 084/277] Migrate DrawableDrumRoll to use a nested hitobject for strong hits --- .../Objects/Drawables/DrawableDrumRoll.cs | 21 +++----------- .../Drawables/DrawableStrongDrumRoll.cs | 28 +++++++++++++++++++ .../Drawables/DrawableStrongHitObject.cs | 1 + 3 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 93eaeb4a1f..da57f4ec4b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -24,9 +23,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const int rolling_hits_for_engaged_colour = 5; - private readonly JudgementResult result; - private readonly JudgementResult strongResult; - /// /// Rolling number of tick hits. This increases for hits and decreases for misses. /// @@ -48,9 +44,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables AddNested(newTick); tickContainer.Add(newTick); } - - result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); - strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); } protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(); @@ -90,17 +83,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables int countHit = NestedHitObjects.Count(o => o.IsHit); if (countHit >= HitObject.RequiredGoodHits) - { - ApplyResult(result, r => r.Type = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good); - if (HitObject.IsStrong) - ApplyResult(strongResult, r => r.Type = HitResult.Great); - } + ApplyResult(r => r.Type = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good); else - { - ApplyResult(result, r => r.Type = HitResult.Miss); - if (HitObject.IsStrong) - ApplyResult(strongResult, r => r.Type = HitResult.Miss); - } + ApplyResult(r => r.Type = HitResult.Miss); } protected override void UpdateState(ArmedState state) @@ -113,5 +98,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables break; } } + + protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongDrumRoll(hitObject, this); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs new file mode 100644 index 0000000000..c886f52397 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Objects.Drawables +{ + public class DrawableStrongDrumRoll : DrawableStrongHitObject + { + private readonly DrawableDrumRoll drumRoll; + + public DrawableStrongDrumRoll(StrongHitObject strong, DrawableDrumRoll drumRoll) + : base(strong) + { + this.drumRoll = drumRoll; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!drumRoll.Judged) + return; + + ApplyResult(r => r.Type = drumRoll.IsHit ? HitResult.Great : HitResult.Miss); + } + + public override bool OnPressed(TaikoAction action) => false; + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs index e9d12e9c35..5ff7d2b396 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs @@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected DrawableStrongHitObject(StrongHitObject strong) : base(strong) { + AlwaysPresent = true; } protected override void UpdateState(ArmedState state) From e8a140930e56357bd8648592ea7b22d52cf7bedc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:35:12 +0900 Subject: [PATCH 085/277] Migrate drum roll to use nested hitobjects for strong hits --- .../Objects/Drawables/DrawableDrumRollTick.cs | 22 +++------------ .../Drawables/DrawableStrongDrumRollTick.cs | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index eeca1b1da3..458c4d7c80 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -2,28 +2,19 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Linq; using osu.Framework.Graphics; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableDrumRollTick : DrawableTaikoHitObject { - private readonly JudgementResult result; - private readonly JudgementResult strongResult; - public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { FillMode = FillMode.Fit; - - result = Results.Single(r => !(r.Judgement is TaikoStrongHitJudgement)); - strongResult = Results.SingleOrDefault(r => r.Judgement is TaikoStrongHitJudgement); } public override bool DisplayJudgement => false; @@ -38,21 +29,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!userTriggered) { if (timeOffset > HitObject.HitWindow) - { - ApplyResult(result, r => r.Type = HitResult.Miss); - if (HitObject.IsStrong) - ApplyResult(strongResult, r => r.Type = HitResult.Miss); - } - + ApplyResult(r => r.Type = HitResult.Miss); return; } if (Math.Abs(timeOffset) > HitObject.HitWindow) return; - ApplyResult(result, r => r.Type = HitResult.Great); - if (HitObject.IsStrong) - ApplyResult(strongResult, r => r.Type = HitResult.Great); + ApplyResult(r => r.Type = HitResult.Great); } protected override void UpdateState(ArmedState state) @@ -66,5 +50,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } public override bool OnPressed(TaikoAction action) => UpdateJudgement(true); + + protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongDrumRollTick(hitObject, this); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs new file mode 100644 index 0000000000..6b821ead84 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Objects.Drawables +{ + public class DrawableStrongDrumRollTick : DrawableStrongHitObject + { + private readonly DrawableDrumRollTick tick; + + public DrawableStrongDrumRollTick(StrongHitObject strong, DrawableDrumRollTick tick) + : base(strong) + { + this.tick = tick; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!tick.Judged) + return; + + ApplyResult(r => r.Type = tick.IsHit ? HitResult.Great : HitResult.Miss); + } + + public override bool OnPressed(TaikoAction action) => false; + } +} From 19c541dbf51d27020697ce7de8e4cde64f1a0e8f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:35:29 +0900 Subject: [PATCH 086/277] Migrate swells to use nested hitobjects for ticks --- .../Objects/Drawables/DrawableSwell.cs | 32 ++++++++++--------- .../Objects/Drawables/DrawableSwellTick.cs | 28 ++++++++++++++++ osu.Game.Rulesets.Taiko/Objects/Swell.cs | 8 +++++ osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 9 ++++++ .../UI/TaikoRulesetContainer.cs | 4 --- 5 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs create mode 100644 osu.Game.Rulesets.Taiko/Objects/SwellTick.cs diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 50b010e543..e6ef4c8a72 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -14,9 +14,7 @@ using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Shapes; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { @@ -32,8 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables private const float target_ring_scale = 5f; private const float inner_ring_alpha = 0.65f; - private readonly JudgementResult result; - private readonly List intermediateResults; + private readonly List ticks = new List(); private readonly Container bodyContainer; private readonly CircularContainer targetRing; @@ -113,8 +110,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables MainPiece.Add(symbol = new SwellSymbolPiece()); - result = Results.Single(r => !(r.Judgement is TaikoIntermediateSwellJudgement)); - intermediateResults = Results.Where(r => r.Judgement is TaikoIntermediateSwellJudgement).ToList(); + foreach (var tick in HitObject.NestedHitObjects.OfType()) + { + var vis = new DrawableSwellTick(tick); + + ticks.Add(vis); + AddInternal(vis); + AddNested(vis); + } } [BackgroundDependencyLoader] @@ -137,12 +140,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (userTriggered) { - var nextIntermediate = intermediateResults.FirstOrDefault(j => !j.HasResult); + var nextTick = ticks.FirstOrDefault(j => !j.IsHit); - if (nextIntermediate != null) - ApplyResult(nextIntermediate, r => r.Type = HitResult.Great); + nextTick?.TriggerResult(HitResult.Great); - var numHits = intermediateResults.Count(r => r.HasResult); + var numHits = ticks.Count(r => r.IsHit); var completion = (float)numHits / HitObject.RequiredHits; @@ -156,7 +158,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (numHits == HitObject.RequiredHits) - ApplyResult(result, r => r.Type = HitResult.Great); + ApplyResult(r => r.Type = HitResult.Great); } else { @@ -165,20 +167,20 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables int numHits = 0; - foreach (var intermediate in intermediateResults) + foreach (var tick in ticks) { - if (intermediate.HasResult) + if (tick.IsHit) { numHits++; continue; } - ApplyResult(intermediate, r => r.Type = HitResult.Miss); + tick.TriggerResult(HitResult.Miss); } var hitResult = numHits > HitObject.RequiredHits / 2 ? HitResult.Good : HitResult.Miss; - ApplyResult(result, r => r.Type = hitResult); + ApplyResult(r => r.Type = hitResult); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs new file mode 100644 index 0000000000..813b6c965b --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -0,0 +1,28 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Taiko.Objects.Drawables +{ + public class DrawableSwellTick : DrawableTaikoHitObject + { + public DrawableSwellTick(TaikoHitObject hitObject) + : base(hitObject) + { + } + + public void TriggerResult(HitResult type) => ApplyResult(r => r.Type = type); + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + } + + protected override void UpdateState(ArmedState state) + { + } + + public override bool OnPressed(TaikoAction action) => false; + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index eb6f931af4..c3ea71af3f 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -15,5 +15,13 @@ namespace osu.Game.Rulesets.Taiko.Objects /// The number of hits required to complete the swell successfully. /// public int RequiredHits = 10; + + protected override void CreateNestedHitObjects() + { + base.CreateNestedHitObjects(); + + for (int i = 0; i < RequiredHits; i++) + AddNested(new SwellTick()); + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs new file mode 100644 index 0000000000..49eb6d2a15 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -0,0 +1,9 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Taiko.Objects +{ + public class SwellTick : TaikoHitObject + { + } +} diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 2fa4627bde..229ab69ceb 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -100,12 +100,8 @@ namespace osu.Game.Rulesets.Taiko.UI { switch (h) { - case CentreHit centreHit when h.IsStrong: - return new DrawableCentreHitStrong(centreHit); case CentreHit centreHit: return new DrawableCentreHit(centreHit); - case RimHit rimHit when h.IsStrong: - return new DrawableRimHitStrong(rimHit); case RimHit rimHit: return new DrawableRimHit(rimHit); case DrumRoll drumRoll: From b778a8d207ac1706bfc54a8d9acff8fccaab9ca3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:35:53 +0900 Subject: [PATCH 087/277] Fix testcase --- .../TestCaseTaikoPlayfield.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index ccae3cf3ce..18333e794e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; -using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; @@ -79,15 +78,12 @@ namespace osu.Game.Rulesets.Taiko.Tests ControlPointInfo = controlPointInfo }); - var rateAdjustClock = new StopwatchClock(true) { Rate = 1 }; - Add(playfieldContainer = new Container { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.X, Height = 768, - Clock = new FramedClock(rateAdjustClock), Children = new[] { rulesetContainer = new TaikoRulesetContainer(new TaikoRuleset(), beatmap) } }); } @@ -205,10 +201,7 @@ namespace osu.Game.Rulesets.Taiko.Tests h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - if (strong) - rulesetContainer.Playfield.Add(new DrawableCentreHitStrong(h)); - else - rulesetContainer.Playfield.Add(new DrawableCentreHit(h)); + rulesetContainer.Playfield.Add(new DrawableCentreHit(h)); } private void addRimHit(bool strong) @@ -221,10 +214,7 @@ namespace osu.Game.Rulesets.Taiko.Tests h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - if (strong) - rulesetContainer.Playfield.Add(new DrawableRimHitStrong(h)); - else - rulesetContainer.Playfield.Add(new DrawableRimHit(h)); + rulesetContainer.Playfield.Add(new DrawableRimHit(h)); } private class DrawableTestHit : DrawableHitObject From e6775c7a162fb9af7ba893b0aec85eba0e6a49e0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:46:03 +0900 Subject: [PATCH 088/277] Fix playfield display --- .../Drawables/DrawableStrongDrumRoll.cs | 9 ++--- .../Drawables/DrawableStrongDrumRollTick.cs | 9 ++--- .../Objects/Drawables/DrawableStrongHit.cs | 17 ++++---- .../Drawables/DrawableStrongHitObject.cs | 6 ++- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 40 ++++++++++--------- 5 files changed, 40 insertions(+), 41 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs index c886f52397..3e8f5103c9 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs @@ -7,20 +7,17 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableStrongDrumRoll : DrawableStrongHitObject { - private readonly DrawableDrumRoll drumRoll; - public DrawableStrongDrumRoll(StrongHitObject strong, DrawableDrumRoll drumRoll) - : base(strong) + : base(strong, drumRoll) { - this.drumRoll = drumRoll; } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!drumRoll.Judged) + if (!MainObject.Judged) return; - ApplyResult(r => r.Type = drumRoll.IsHit ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); } public override bool OnPressed(TaikoAction action) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs index 6b821ead84..1724054800 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs @@ -7,20 +7,17 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableStrongDrumRollTick : DrawableStrongHitObject { - private readonly DrawableDrumRollTick tick; - public DrawableStrongDrumRollTick(StrongHitObject strong, DrawableDrumRollTick tick) - : base(strong) + : base(strong, tick) { - this.tick = tick; } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!tick.Judged) + if (!MainObject.Judged) return; - ApplyResult(r => r.Type = tick.IsHit ? HitResult.Great : HitResult.Miss); + ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); } public override bool OnPressed(TaikoAction action) => false; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs index c9767c9aec..d0c6525cde 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs @@ -15,23 +15,22 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// private const double second_hit_window = 30; - private readonly DrawableHit hit; + public DrawableHit MainObject => (DrawableHit)base.MainObject; public DrawableStrongHit(StrongHitObject strong, DrawableHit hit) - : base(strong) + : base(strong, hit) { - this.hit = hit; } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (!hit.Result.HasResult) + if (!MainObject.Result.HasResult) { base.CheckForJudgements(userTriggered, timeOffset); return; } - if (!hit.Result.IsHit) + if (!MainObject.Result.IsHit) { ApplyResult(r => r.Type = HitResult.Miss); return; @@ -44,22 +43,22 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return; } - if (Math.Abs(hit.Result.TimeOffset - timeOffset) < second_hit_window) + if (Math.Abs(MainObject.Result.TimeOffset - timeOffset) < second_hit_window) ApplyResult(r => r.Type = HitResult.Great); } public override bool OnPressed(TaikoAction action) { // Don't process actions until the main hitobject is hit - if (!hit.IsHit) + if (!MainObject.IsHit) return false; // Don't process actions if the pressed button was released - if (hit.HitAction == null) + if (MainObject.HitAction == null) return false; // Don't handle invalid hit action presses - if (!hit.HitActions.Contains(action)) + if (!MainObject.HitActions.Contains(action)) return false; return UpdateJudgement(true); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs index 5ff7d2b396..85a1afd74b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs @@ -7,9 +7,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public abstract class DrawableStrongHitObject : DrawableTaikoHitObject { - protected DrawableStrongHitObject(StrongHitObject strong) + public readonly DrawableHitObject MainObject; + + protected DrawableStrongHitObject(StrongHitObject strong, DrawableHitObject mainObject) : base(strong) { + MainObject = mainObject; + AlwaysPresent = true; } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 7147972c58..4a045ac86f 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -232,30 +232,32 @@ namespace osu.Game.Rulesets.Taiko.UI if (!judgedObject.DisplayJudgement) return; - if (judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null) + switch (result.Judgement) { - judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) - { - Anchor = result.IsHit ? Anchor.TopLeft : Anchor.CentreLeft, - Origin = result.IsHit ? Anchor.BottomCentre : Anchor.Centre, - RelativePositionAxes = Axes.X, - X = result.IsHit ? judgedObject.Position.X : 0, - }); - } + case TaikoStrongHitJudgement _: + if (result.IsHit) + hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongHitObject)judgedObject).MainObject)?.VisualiseSecondHit(); + break; + default: + judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) + { + Anchor = result.IsHit ? Anchor.TopLeft : Anchor.CentreLeft, + Origin = result.IsHit ? Anchor.BottomCentre : Anchor.Centre, + RelativePositionAxes = Axes.X, + X = result.IsHit ? judgedObject.Position.X : 0, + }); - if (!result.IsHit) - return; + if (!result.IsHit) + break; - bool isRim = judgedObject.HitObject is RimHit; + bool isRim = judgedObject.HitObject is RimHit; - if (result.Judgement is TaikoStrongHitJudgement) - hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == judgedObject)?.VisualiseSecondHit(); - else - { - hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim)); + hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim)); - if (judgedObject.HitObject.Kiai) - kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject, isRim)); + if (judgedObject.HitObject.Kiai) + kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject, isRim)); + + break; } } } From 412e4ff681fa7b9ffefaea753b0f736260091ea9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:49:24 +0900 Subject: [PATCH 089/277] Fix display of swells --- .../Objects/Drawables/DrawableStrongHitObject.cs | 2 ++ osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs | 5 ----- .../Objects/Drawables/DrawableSwellTick.cs | 2 ++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs index 85a1afd74b..3f6080d1b5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs @@ -7,6 +7,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public abstract class DrawableStrongHitObject : DrawableTaikoHitObject { + public override bool DisplayJudgement => false; + public readonly DrawableHitObject MainObject; protected DrawableStrongHitObject(StrongHitObject strong, DrawableHitObject mainObject) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index e6ef4c8a72..24b1a0e9da 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -20,11 +20,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableSwell : DrawableTaikoHitObject { - /// - /// A judgement is only displayed when the user has complete the swell (either a hit or miss). - /// - public override bool DisplayJudgement => AllJudged; - private const float target_ring_thick_border = 1.4f; private const float target_ring_thin_border = 1f; private const float target_ring_scale = 5f; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 813b6c965b..8266d329a2 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -8,6 +8,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableSwellTick : DrawableTaikoHitObject { + public override bool DisplayJudgement => false; + public DrawableSwellTick(TaikoHitObject hitObject) : base(hitObject) { From 38263714a13761011ff6f7cbc7cd75446f8587b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 3 Aug 2018 16:56:46 +0900 Subject: [PATCH 090/277] Cleanups --- .../TestCaseTaikoPlayfield.cs | 2 +- ...itJudgement.cs => TaikoStrongJudgement.cs} | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 20 +++++- .../Objects/Drawables/DrawableDrumRollTick.cs | 20 +++++- .../Objects/Drawables/DrawableHit.cs | 61 ++++++++++++++++- .../Drawables/DrawableStrongDrumRoll.cs | 25 ------- .../Drawables/DrawableStrongDrumRollTick.cs | 25 ------- ...gHitObject.cs => DrawableStrongHandler.cs} | 8 ++- .../Objects/Drawables/DrawableStrongHit.cs | 67 ------------------- .../Drawables/DrawableTaikoHitObject.cs | 10 ++- .../Objects/StrongHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 4 +- 12 files changed, 117 insertions(+), 129 deletions(-) rename osu.Game.Rulesets.Taiko/Judgements/{TaikoStrongHitJudgement.cs => TaikoStrongJudgement.cs} (82%) delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs rename osu.Game.Rulesets.Taiko/Objects/Drawables/{DrawableStrongHitObject.cs => DrawableStrongHandler.cs} (60%) delete mode 100644 osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 18333e794e..35cb94e8de 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Taiko.Tests if (RNG.Next(10) == 0) { ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoStrongHitJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); } } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs similarity index 82% rename from osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs rename to osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs index b69bbd4fd8..ccfdeb5b0e 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongJudgement.cs @@ -3,7 +3,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements { - public class TaikoStrongHitJudgement : TaikoJudgement + public class TaikoStrongJudgement : TaikoJudgement { public override bool AffectsCombo => false; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index da57f4ec4b..a984af3b51 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -99,6 +99,24 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongDrumRoll(hitObject, this); + protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + + private class StrongHandler : DrawableStrongHandler + { + public StrongHandler(StrongHitObject strong, DrawableDrumRoll drumRoll) + : base(strong, drumRoll) + { + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!MainObject.Judged) + return; + + ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); + } + + public override bool OnPressed(TaikoAction action) => false; + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 458c4d7c80..cbe6e10dcb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -51,6 +51,24 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public override bool OnPressed(TaikoAction action) => UpdateJudgement(true); - protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongDrumRollTick(hitObject, this); + protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + + private class StrongHandler : DrawableStrongHandler + { + public StrongHandler(StrongHitObject strong, DrawableDrumRollTick tick) + : base(strong, tick) + { + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!MainObject.Judged) + return; + + ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); + } + + public override bool OnPressed(TaikoAction action) => false; + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 35fa5eb344..4289a77f4c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -126,6 +127,64 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => new DrawableStrongHit(hitObject, this); + protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + + private class StrongHandler : DrawableStrongHandler + { + /// + /// The lenience for the second key press. + /// This does not adjust by map difficulty in ScoreV2 yet. + /// + private const double second_hit_window = 30; + + public new DrawableHit MainObject => (DrawableHit)base.MainObject; + + public StrongHandler(StrongHitObject strong, DrawableHit hit) + : base(strong, hit) + { + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!MainObject.Result.HasResult) + { + base.CheckForJudgements(userTriggered, timeOffset); + return; + } + + if (!MainObject.Result.IsHit) + { + ApplyResult(r => r.Type = HitResult.Miss); + return; + } + + if (!userTriggered) + { + if (timeOffset > second_hit_window) + ApplyResult(r => r.Type = HitResult.Miss); + return; + } + + if (Math.Abs(MainObject.Result.TimeOffset - timeOffset) < second_hit_window) + ApplyResult(r => r.Type = HitResult.Great); + } + + public override bool OnPressed(TaikoAction action) + { + // Don't process actions until the main hitobject is hit + if (!MainObject.IsHit) + return false; + + // Don't process actions if the pressed button was released + if (MainObject.HitAction == null) + return false; + + // Don't handle invalid hit action presses + if (!MainObject.HitActions.Contains(action)) + return false; + + return UpdateJudgement(true); + } + } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs deleted file mode 100644 index 3e8f5103c9..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRoll.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public class DrawableStrongDrumRoll : DrawableStrongHitObject - { - public DrawableStrongDrumRoll(StrongHitObject strong, DrawableDrumRoll drumRoll) - : base(strong, drumRoll) - { - } - - protected override void CheckForJudgements(bool userTriggered, double timeOffset) - { - if (!MainObject.Judged) - return; - - ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); - } - - public override bool OnPressed(TaikoAction action) => false; - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs deleted file mode 100644 index 1724054800..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongDrumRollTick.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public class DrawableStrongDrumRollTick : DrawableStrongHitObject - { - public DrawableStrongDrumRollTick(StrongHitObject strong, DrawableDrumRollTick tick) - : base(strong, tick) - { - } - - protected override void CheckForJudgements(bool userTriggered, double timeOffset) - { - if (!MainObject.Judged) - return; - - ApplyResult(r => r.Type = MainObject.IsHit ? HitResult.Great : HitResult.Miss); - } - - public override bool OnPressed(TaikoAction action) => false; - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs similarity index 60% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs index 3f6080d1b5..6f2db764a8 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs @@ -2,16 +2,20 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableStrongHitObject : DrawableTaikoHitObject + /// + /// Used as a nested hitobject to provide s for s. + /// + public abstract class DrawableStrongHandler : DrawableTaikoHitObject { public override bool DisplayJudgement => false; public readonly DrawableHitObject MainObject; - protected DrawableStrongHitObject(StrongHitObject strong, DrawableHitObject mainObject) + protected DrawableStrongHandler(StrongHitObject strong, DrawableHitObject mainObject) : base(strong) { MainObject = mainObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs deleted file mode 100644 index d0c6525cde..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHit.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Taiko.Objects.Drawables -{ - public class DrawableStrongHit : DrawableStrongHitObject - { - /// - /// The lenience for the second key press. - /// This does not adjust by map difficulty in ScoreV2 yet. - /// - private const double second_hit_window = 30; - - public DrawableHit MainObject => (DrawableHit)base.MainObject; - - public DrawableStrongHit(StrongHitObject strong, DrawableHit hit) - : base(strong, hit) - { - } - - protected override void CheckForJudgements(bool userTriggered, double timeOffset) - { - if (!MainObject.Result.HasResult) - { - base.CheckForJudgements(userTriggered, timeOffset); - return; - } - - if (!MainObject.Result.IsHit) - { - ApplyResult(r => r.Type = HitResult.Miss); - return; - } - - if (!userTriggered) - { - if (timeOffset > second_hit_window) - ApplyResult(r => r.Type = HitResult.Miss); - return; - } - - if (Math.Abs(MainObject.Result.TimeOffset - timeOffset) < second_hit_window) - ApplyResult(r => r.Type = HitResult.Great); - } - - public override bool OnPressed(TaikoAction action) - { - // Don't process actions until the main hitobject is hit - if (!MainObject.IsHit) - return false; - - // Don't process actions if the pressed button was released - if (MainObject.HitAction == null) - return false; - - // Don't handle invalid hit action presses - if (!MainObject.HitActions.Contains(action)) - return false; - - return UpdateJudgement(true); - } - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index b0216768c1..6d19c99b9c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); if (strongObject != null) { - var vis = CreateStrongObject(strongObject); + var vis = CreateStrongHandler(strongObject); if (vis != null) { AddNested(vis); @@ -121,6 +121,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); - protected virtual DrawableStrongHitObject CreateStrongObject(StrongHitObject hitObject) => null; + /// + /// Creates the handler for this 's . + /// This is only invoked if is true for . + /// + /// The strong hitobject. + /// The strong hitobject handler. + protected virtual DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => null; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index 104d662ed8..a9d452cc68 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class StrongHitObject : TaikoHitObject { - protected override Judgement CreateJudgement() => new TaikoStrongHitJudgement(); + protected override Judgement CreateJudgement() => new TaikoStrongJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 4a045ac86f..5202fe00ad 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -234,9 +234,9 @@ namespace osu.Game.Rulesets.Taiko.UI switch (result.Judgement) { - case TaikoStrongHitJudgement _: + case TaikoStrongJudgement _: if (result.IsHit) - hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongHitObject)judgedObject).MainObject)?.VisualiseSecondHit(); + hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongHandler)judgedObject).MainObject)?.VisualiseSecondHit(); break; default: judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) From 2ea90ef98abebc68d80724b9a1964d30cc4df2cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Aug 2018 19:25:55 +0900 Subject: [PATCH 091/277] Add sentry logging --- osu.Desktop/Program.cs | 22 +++++++ osu.Game/OsuGame.cs | 16 +++++ osu.Game/Screens/Select/PlaySongSelect.cs | 3 + osu.Game/Utils/RavenLogger.cs | 73 +++++++++++++++++++++++ osu.Game/osu.Game.csproj | 3 +- 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Utils/RavenLogger.cs diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index cc08e08653..4574fb6fc9 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -4,7 +4,10 @@ using System; using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using osu.Framework; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IPC; @@ -20,6 +23,8 @@ namespace osu.Desktop using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true)) { + host.ExceptionThrown += handleException; + if (!host.IsPrimaryInstance) { var importer = new ArchiveImportIPCChannel(host); @@ -45,5 +50,22 @@ namespace osu.Desktop return 0; } } + + private static int allowableExceptions = 1; + + /// + /// Allow a maximum of one unhandled exception, per second of execution. + /// + /// + /// + private static bool handleException(Exception arg) + { + bool continueExecution = Interlocked.Decrement(ref allowableExceptions) >= 0; + + Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed" : "denied")} with {allowableExceptions} more allowable exceptions."); + + Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); + return Interlocked.Decrement(ref allowableExceptions) >= 0; + } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 025d5f50e3..3e6317348c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -36,6 +36,8 @@ using osu.Game.Skinning; using OpenTK.Graphics; using osu.Game.Overlays.Volume; using osu.Game.Screens.Select; +using osu.Game.Utils; +using LogLevel = osu.Framework.Logging.LogLevel; namespace osu.Game { @@ -65,6 +67,8 @@ namespace osu.Game private ScreenshotManager screenshotManager; + protected RavenLogger RavenLogger; + public virtual Storage GetStorageForStableInstall() => null; private Intro intro @@ -106,6 +110,8 @@ namespace osu.Game this.args = args; forwardLoggedErrorsToNotifications(); + + RavenLogger = new RavenLogger(this); } public void ToggleSettings() => settings.ToggleVisibility(); @@ -150,6 +156,8 @@ namespace osu.Game dependencies.CacheAs(this); + dependencies.Cache(RavenLogger); + dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); @@ -271,6 +279,12 @@ namespace osu.Game menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay))); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + RavenLogger.Dispose(); + } + protected override void LoadComplete() { // this needs to be cached before base.LoadComplete as it is used by MenuCursorContainer. @@ -599,6 +613,7 @@ namespace osu.Game private void screenAdded(Screen newScreen) { currentScreen = (OsuScreen)newScreen; + Logger.Log($"Screen changed → {currentScreen}"); newScreen.ModePushed += screenAdded; newScreen.Exited += screenRemoved; @@ -607,6 +622,7 @@ namespace osu.Game private void screenRemoved(Screen newScreen) { currentScreen = (OsuScreen)newScreen; + Logger.Log($"Screen changed ← {currentScreen}"); if (newScreen == null) Exit(); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index a346911ca2..a73254627d 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -141,6 +142,8 @@ namespace osu.Game.Screens.Select { if (player != null) return false; + throw new Exception("this is a test!"); + // Ctrl+Enter should start map with autoplay enabled. if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true) { diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs new file mode 100644 index 0000000000..aadb70add8 --- /dev/null +++ b/osu.Game/Utils/RavenLogger.cs @@ -0,0 +1,73 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using osu.Framework.Logging; +using SharpRaven; +using SharpRaven.Data; + +namespace osu.Game.Utils +{ + /// + /// Report errors to sentry. + /// + public class RavenLogger : IDisposable + { + private readonly RavenClient raven = new RavenClient("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"); + + private readonly List tasks = new List(); + + public RavenLogger(OsuGame game) + { + raven.Release = game.Version; + + Logger.NewEntry += entry => + { + if (entry.Level < LogLevel.Verbose) return; + + if (entry.Exception != null) + queuePendingTask(raven.CaptureAsync(new SentryEvent(entry.Exception))); + else + raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); + }; + } + + private void queuePendingTask(Task task) + { + lock (tasks) tasks.Add(task); + task.ContinueWith(_ => + { + lock (tasks) + tasks.Remove(task); + }); + } + + #region Disposal + + ~RavenLogger() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private bool isDisposed; + + protected virtual void Dispose(bool isDisposing) + { + if (isDisposed) + return; + + isDisposed = true; + lock (tasks) Task.WaitAll(tasks.ToArray(), 5000); + } + + #endregion + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 89e80bd06b..9a7edb6ae2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,9 +18,10 @@ - + + \ No newline at end of file From 7310c38df98396b5c51bb27febc034f26e6e8532 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Fri, 3 Aug 2018 14:03:11 +0200 Subject: [PATCH 092/277] Add relax mod --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 69 ++++++++++++++++++- .../Rulesets/Mods/IUpdatableByHitObject.cs | 12 ++++ .../Rulesets/Mods/IUpdatableByPlayfield.cs | 12 ++++ .../Objects/Drawables/DrawableHitObject.cs | 12 +++- osu.Game/Rulesets/UI/Playfield.cs | 17 ++++- 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs create mode 100644 osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 9f9c2a09b6..2e07117734 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -2,14 +2,81 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; +using osu.Framework.Input.States; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.UI; +using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax + public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByHitObject, IUpdatableByPlayfield { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); + + public bool AllowFail => false; + + private bool hitStill; + private bool hitOnce; + + public void Update(DrawableHitObject o) + { + const float relax_leniency = 3; + + if (!(o is DrawableOsuHitObject d)) + return; + + double t = d.Clock.CurrentTime; + + if (t >= d.HitObject.StartTime - relax_leniency) + { + if (d.HitObject is IHasEndTime e && t > e.EndTime || d.IsHit) + return; + + hitStill |= d is DrawableSlider s && (s.Ball.IsHovered || d.IsHovered) || d is DrawableSpinner; + + hitOnce |= d is DrawableHitCircle && d.IsHovered; + } + } + + public void Update(Playfield r) + { + var d = r.HitObjects.Objects.First(h => h is DrawableOsuHitObject) as DrawableOsuHitObject; + if (hitOnce) + { + hit(d, false); + hit(d, true); + } + hit(d, hitStill); + + hitOnce = false; + hitStill = false; + } + + private bool wasHit; + private bool wasLeft; + + private void hit(DrawableOsuHitObject d, bool hitting) + { + if (wasHit == hitting) + return; + wasHit = hitting; + + var l = new ReplayState + { + PressedActions = new List() + }; + if (hitting) + { + l.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + wasLeft = !wasLeft; + } + d.OsuActionInputManager.HandleCustomInput(new InputState(), l); + } } } diff --git a/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs b/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs new file mode 100644 index 0000000000..657145b911 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.Mods +{ + public interface IUpdatableByHitObject : IApplicableMod + { + void Update(DrawableHitObject o); + } +} diff --git a/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs new file mode 100644 index 0000000000..39781a875d --- /dev/null +++ b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mods +{ + public interface IUpdatableByPlayfield : IApplicableMod + { + void Update(Playfield r); + } +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a22aaa784f..31dd5a4a91 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -13,6 +13,8 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using OpenTK.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Objects.Drawables { @@ -41,6 +43,8 @@ namespace osu.Game.Rulesets.Objects.Drawables public IReadOnlyList Judgements => judgements; private readonly List judgements = new List(); + private WorkingBeatmap beatmap; + /// /// Whether a visible judgement should be displayed when this representation is hit. /// @@ -80,8 +84,9 @@ namespace osu.Game.Rulesets.Objects.Drawables } [BackgroundDependencyLoader] - private void load() + private void load(IBindableBeatmap b) { + beatmap = b.Value; var samples = GetSamples().ToArray(); if (samples.Any()) @@ -132,6 +137,11 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.Update(); + if(beatmap != null) + foreach (var m in beatmap.Mods.Value) + if (m is IUpdatableByHitObject u) + u.Update(this); + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; while (judgements.Count > 0) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 2f44d99e18..7116dc53a9 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -6,6 +6,8 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.UI { @@ -42,9 +44,12 @@ namespace osu.Game.Rulesets.UI RelativeSizeAxes = Axes.Both; } + private WorkingBeatmap beatmap; + [BackgroundDependencyLoader] - private void load() + private void load(IBindableBeatmap b) { + beatmap = b.Value; HitObjects = CreateHitObjectContainer(); HitObjects.RelativeSizeAxes = Axes.Both; @@ -87,5 +92,15 @@ namespace osu.Game.Rulesets.UI /// Creates the container that will be used to contain the s. /// protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer(); + + protected override void Update() + { + base.Update(); + + if (beatmap != null) + foreach (var m in beatmap.Mods.Value) + if (m is IUpdatableByPlayfield u) + u.Update(this); + } } } From 07d6a75e239ed84169b2669eab2b1aee9c40cdc5 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Sat, 4 Aug 2018 00:18:09 +0200 Subject: [PATCH 093/277] Rename variables to be human readable --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 32 +++++++++---------- .../Rulesets/Mods/IUpdatableByHitObject.cs | 2 +- .../Rulesets/Mods/IUpdatableByPlayfield.cs | 2 +- .../Objects/Drawables/DrawableHitObject.cs | 10 +++--- osu.Game/Rulesets/UI/Playfield.cs | 10 +++--- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 2e07117734..296a9f9631 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -24,35 +24,35 @@ namespace osu.Game.Rulesets.Osu.Mods private bool hitStill; private bool hitOnce; - public void Update(DrawableHitObject o) + public void Update(DrawableHitObject drawable) { const float relax_leniency = 3; - if (!(o is DrawableOsuHitObject d)) + if (!(drawable is DrawableOsuHitObject osuHit)) return; - double t = d.Clock.CurrentTime; + double time = osuHit.Clock.CurrentTime; - if (t >= d.HitObject.StartTime - relax_leniency) + if (time >= osuHit.HitObject.StartTime - relax_leniency) { - if (d.HitObject is IHasEndTime e && t > e.EndTime || d.IsHit) + if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) return; - hitStill |= d is DrawableSlider s && (s.Ball.IsHovered || d.IsHovered) || d is DrawableSpinner; + hitStill |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; - hitOnce |= d is DrawableHitCircle && d.IsHovered; + hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered; } } - public void Update(Playfield r) + public void Update(Playfield playfield) { - var d = r.HitObjects.Objects.First(h => h is DrawableOsuHitObject) as DrawableOsuHitObject; + var osuHit = playfield.HitObjects.Objects.First(d => d is DrawableOsuHitObject) as DrawableOsuHitObject; if (hitOnce) { - hit(d, false); - hit(d, true); + hit(osuHit, false); + hit(osuHit, true); } - hit(d, hitStill); + hit(osuHit, hitStill); hitOnce = false; hitStill = false; @@ -61,22 +61,22 @@ namespace osu.Game.Rulesets.Osu.Mods private bool wasHit; private bool wasLeft; - private void hit(DrawableOsuHitObject d, bool hitting) + private void hit(DrawableOsuHitObject osuHit, bool hitting) { if (wasHit == hitting) return; wasHit = hitting; - var l = new ReplayState + var state = new ReplayState { PressedActions = new List() }; if (hitting) { - l.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); + state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); wasLeft = !wasLeft; } - d.OsuActionInputManager.HandleCustomInput(new InputState(), l); + osuHit.OsuActionInputManager.HandleCustomInput(new InputState(), state); } } } diff --git a/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs b/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs index 657145b911..6dd900e9c5 100644 --- a/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs +++ b/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs @@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mods { public interface IUpdatableByHitObject : IApplicableMod { - void Update(DrawableHitObject o); + void Update(DrawableHitObject drawable); } } diff --git a/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs index 39781a875d..be879759bd 100644 --- a/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs +++ b/osu.Game/Rulesets/Mods/IUpdatableByPlayfield.cs @@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mods { public interface IUpdatableByPlayfield : IApplicableMod { - void Update(Playfield r); + void Update(Playfield playfield); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 31dd5a4a91..f060f7382c 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -84,9 +84,9 @@ namespace osu.Game.Rulesets.Objects.Drawables } [BackgroundDependencyLoader] - private void load(IBindableBeatmap b) + private void load(IBindableBeatmap bBeatmap) { - beatmap = b.Value; + beatmap = bBeatmap.Value; var samples = GetSamples().ToArray(); if (samples.Any()) @@ -138,9 +138,9 @@ namespace osu.Game.Rulesets.Objects.Drawables base.Update(); if(beatmap != null) - foreach (var m in beatmap.Mods.Value) - if (m is IUpdatableByHitObject u) - u.Update(this); + foreach (var mod in beatmap.Mods.Value) + if (mod is IUpdatableByHitObject updatable) + updatable.Update(this); var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 7116dc53a9..f7b3736e74 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -47,9 +47,9 @@ namespace osu.Game.Rulesets.UI private WorkingBeatmap beatmap; [BackgroundDependencyLoader] - private void load(IBindableBeatmap b) + private void load(IBindableBeatmap bBeatmap) { - beatmap = b.Value; + beatmap = bBeatmap.Value; HitObjects = CreateHitObjectContainer(); HitObjects.RelativeSizeAxes = Axes.Both; @@ -98,9 +98,9 @@ namespace osu.Game.Rulesets.UI base.Update(); if (beatmap != null) - foreach (var m in beatmap.Mods.Value) - if (m is IUpdatableByPlayfield u) - u.Update(this); + foreach (var mod in beatmap.Mods.Value) + if (mod is IUpdatableByPlayfield updatable) + updatable.Update(this); } } } From 6d6fea47ab32c6dafbeb909189df9846741dce10 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 5 Aug 2018 14:36:09 +0900 Subject: [PATCH 094/277] Reduce animations of osu!direct list mode The panels' content was flying around and felt really shocking. This fixes elements in place to provide a better experience. --- osu.Game/Overlays/Direct/DirectListPanel.cs | 77 +++++++++++---------- osu.Game/Overlays/Direct/DirectPanel.cs | 5 +- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 45e1164a57..850ead37f6 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -12,7 +12,6 @@ using osu.Game.Graphics.Sprites; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Graphics.Shapes; -using osu.Framework.Input.States; using osu.Game.Beatmaps; namespace osu.Game.Overlays.Direct @@ -26,12 +25,14 @@ namespace osu.Game.Overlays.Direct private PlayButton playButton; private Box progressBar; - private Container downloadContainer; + + protected override bool FadePlayButton => false; protected override PlayButton PlayButton => playButton; protected override Box PreviewBar => progressBar; - public DirectListPanel(BeatmapSetInfo beatmap) : base(beatmap) + public DirectListPanel(BeatmapSetInfo beatmap) + : base(beatmap) { RelativeSizeAxes = Axes.X; Height = height; @@ -66,30 +67,45 @@ namespace osu.Game.Overlays.Direct Spacing = new Vector2(10, 0), Children = new Drawable[] { - playButton = new PlayButton(SetInfo) - { - Origin = Anchor.CentreLeft, - Anchor = Anchor.CentreLeft, - Size = new Vector2(height / 2), - FillMode = FillMode.Fit, - Alpha = 0, - }, new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, Children = new Drawable[] { - new OsuSpriteText + new FillFlowContainer { - Current = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title), - TextSize = 18, - Font = @"Exo2.0-BoldItalic", - }, - new OsuSpriteText - { - Current = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist), - Font = @"Exo2.0-BoldItalic", + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new Drawable[] + { + playButton = new PlayButton(SetInfo) + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Size = new Vector2(height / 2), + FillMode = FillMode.Fit, + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new OsuSpriteText + { + Current = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title), + TextSize = 18, + Font = @"Exo2.0-BoldItalic", + }, + new OsuSpriteText + { + Current = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist), + Font = @"Exo2.0-BoldItalic", + }, + } + }, + } }, new FillFlowContainer { @@ -108,16 +124,13 @@ namespace osu.Game.Overlays.Direct Origin = Anchor.TopRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, - LayoutEasing = Easing.OutQuint, - LayoutDuration = transition_duration, Children = new Drawable[] { - downloadContainer = new Container + new Container { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, AutoSizeAxes = Axes.Both, - Alpha = 0, Child = new DownloadButton(SetInfo) { Size = new Vector2(height - vertical_padding * 3), @@ -184,17 +197,5 @@ namespace osu.Game.Overlays.Direct }, }); } - - protected override bool OnHover(InputState state) - { - downloadContainer.FadeIn(transition_duration, Easing.InOutQuint); - return base.OnHover(state); - } - - protected override void OnHoverLost(InputState state) - { - downloadContainer.FadeOut(transition_duration, Easing.InOutQuint); - base.OnHoverLost(state); - } } } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 7d5c0c16cc..5a73aab23e 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -40,6 +40,8 @@ namespace osu.Game.Overlays.Direct protected abstract PlayButton PlayButton { get; } protected abstract Box PreviewBar { get; } + protected virtual bool FadePlayButton => true; + protected override Container Content => content; protected DirectPanel(BeatmapSetInfo setInfo) @@ -125,6 +127,7 @@ namespace osu.Game.Overlays.Direct { content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); content.MoveToY(-4, hover_transition_time, Easing.OutQuint); + if (FadePlayButton) PlayButton.FadeIn(120, Easing.InOutQuint); return base.OnHover(state); @@ -134,7 +137,7 @@ namespace osu.Game.Overlays.Direct { content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); content.MoveToY(0, hover_transition_time, Easing.OutQuint); - if (!PreviewPlaying) + if (FadePlayButton && !PreviewPlaying) PlayButton.FadeOut(120, Easing.InOutQuint); base.OnHoverLost(state); From b1d1a2400bfc49c47649ea497cb0437a0467abcd Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Sun, 5 Aug 2018 09:52:19 +0200 Subject: [PATCH 095/277] Remove IUpdatableByHitObject completely --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 60 +++++++++---------- .../Rulesets/Mods/IUpdatableByHitObject.cs | 12 ---- .../Objects/Drawables/DrawableHitObject.cs | 12 +--- 3 files changed, 29 insertions(+), 55 deletions(-) delete mode 100644 osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 296a9f9631..e10ddfaec1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Input.States; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.UI; @@ -14,48 +13,45 @@ using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByHitObject, IUpdatableByPlayfield + public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); public bool AllowFail => false; - private bool hitStill; - private bool hitOnce; - - public void Update(DrawableHitObject drawable) - { - const float relax_leniency = 3; - - if (!(drawable is DrawableOsuHitObject osuHit)) - return; - - double time = osuHit.Clock.CurrentTime; - - if (time >= osuHit.HitObject.StartTime - relax_leniency) - { - if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) - return; - - hitStill |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; - - hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered; - } - } - public void Update(Playfield playfield) { - var osuHit = playfield.HitObjects.Objects.First(d => d is DrawableOsuHitObject) as DrawableOsuHitObject; + bool hitStill = false; + bool hitOnce = false; + + const float relax_leniency = 3; + + foreach (var drawable in playfield.HitObjects.Objects) + { + if (!(drawable is DrawableOsuHitObject osuHit)) + continue; + + double time = osuHit.Clock.CurrentTime; + + if (osuHit.IsAlive && time >= osuHit.HitObject.StartTime - relax_leniency) + { + if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) + continue; + + hitStill |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; + + hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered; + } + } + + var osuHitSample = playfield.HitObjects.Objects.First(d => d is DrawableOsuHitObject) as DrawableOsuHitObject; if (hitOnce) { - hit(osuHit, false); - hit(osuHit, true); + hit(osuHitSample, false); + hit(osuHitSample, true); } - hit(osuHit, hitStill); - - hitOnce = false; - hitStill = false; + hit(osuHitSample, hitStill); } private bool wasHit; diff --git a/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs b/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs deleted file mode 100644 index 6dd900e9c5..0000000000 --- a/osu.Game/Rulesets/Mods/IUpdatableByHitObject.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Objects.Drawables; - -namespace osu.Game.Rulesets.Mods -{ - public interface IUpdatableByHitObject : IApplicableMod - { - void Update(DrawableHitObject drawable); - } -} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f060f7382c..a22aaa784f 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -13,8 +13,6 @@ using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Skinning; using OpenTK.Graphics; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Objects.Drawables { @@ -43,8 +41,6 @@ namespace osu.Game.Rulesets.Objects.Drawables public IReadOnlyList Judgements => judgements; private readonly List judgements = new List(); - private WorkingBeatmap beatmap; - /// /// Whether a visible judgement should be displayed when this representation is hit. /// @@ -84,9 +80,8 @@ namespace osu.Game.Rulesets.Objects.Drawables } [BackgroundDependencyLoader] - private void load(IBindableBeatmap bBeatmap) + private void load() { - beatmap = bBeatmap.Value; var samples = GetSamples().ToArray(); if (samples.Any()) @@ -137,11 +132,6 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.Update(); - if(beatmap != null) - foreach (var mod in beatmap.Mods.Value) - if (mod is IUpdatableByHitObject updatable) - updatable.Update(this); - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; while (judgements.Count > 0) From 924bf9174c97ec4deaae8f8d55cee174d0defbc1 Mon Sep 17 00:00:00 2001 From: tgi74000 Date: Sun, 5 Aug 2018 09:58:15 +0200 Subject: [PATCH 096/277] Fix overclick in certain situations --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index e10ddfaec1..f0e7891a96 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -33,6 +33,7 @@ namespace osu.Game.Rulesets.Osu.Mods continue; double time = osuHit.Clock.CurrentTime; + double relativetime = time - osuHit.HitObject.StartTime; if (osuHit.IsAlive && time >= osuHit.HitObject.StartTime - relax_leniency) { @@ -41,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Mods hitStill |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; - hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered; + hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); } } From 5fd4ed2f4e67f81b21d5fb628df609b5e71721d1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 10:54:16 +0900 Subject: [PATCH 097/277] Rename judgement-related methods/events + commenting --- .../Scoring/CatchScoreProcessor.cs | 4 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 4 +- .../Scoring/ManiaScoreProcessor.cs | 4 +- osu.Game.Rulesets.Mania/UI/Column.cs | 4 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 4 +- osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs | 4 +- .../Scoring/OsuScoreProcessor.cs | 4 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 4 +- .../TestCaseTaikoPlayfield.cs | 8 ++-- .../Objects/Drawables/DrawableDrumRoll.cs | 4 +- .../Scoring/TaikoScoreProcessor.cs | 4 +- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 4 +- .../Objects/Drawables/DrawableHitObject.cs | 19 +++++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 45 ++++++++++++------- osu.Game/Rulesets/UI/RulesetContainer.cs | 15 +++++-- 15 files changed, 78 insertions(+), 53 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 183c6f0f12..403cedde8c 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -29,9 +29,9 @@ namespace osu.Game.Rulesets.Catch.Scoring private const double harshness = 0.01; - protected override void OnNewJudgement(JudgementResult result) + protected override void ApplyResult(JudgementResult result) { - base.OnNewJudgement(result); + base.ApplyResult(result); if (result.Type == HitResult.Miss) { diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 7b52066d15..ffb93fd679 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.UI public override void Add(DrawableHitObject h) { - h.OnJudgement += onJudgement; + h.OnNewResult += onNewResult; base.Add(h); @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Catch.UI fruit.CheckPosition = CheckIfWeCanCatch; } - private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) + private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, result); } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 289bcc3d34..12b32c46ee 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -121,9 +121,9 @@ namespace osu.Game.Rulesets.Mania.Scoring } } - protected override void OnNewJudgement(JudgementResult result) + protected override void ApplyResult(JudgementResult result) { - base.OnNewJudgement(result); + base.ApplyResult(result); bool isTick = result.Judgement is HoldNoteTickJudgement; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index ca7173ec50..500f999dd6 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -131,12 +131,12 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject hitObject) { hitObject.AccentColour = AccentColour; - hitObject.OnJudgement += OnJudgement; + hitObject.OnNewResult += OnNewResult; HitObjects.Add(hitObject); } - internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) + internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!result.IsHit || !judgedObject.DisplayJudgement || !DisplayJudgements) return; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index 9072e044bd..f5993e61de 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -156,12 +156,12 @@ namespace osu.Game.Rulesets.Mania.UI var maniaObject = (ManiaHitObject)h.HitObject; int columnIndex = maniaObject.Column - firstColumnIndex; Columns.ElementAt(columnIndex).Add(h); - h.OnJudgement += OnJudgement; + h.OnNewResult += OnNewResult; } public void Add(BarLine barline) => base.Add(new DrawableBarLine(barline)); - internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) + internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!judgedObject.DisplayJudgement || !DisplayJudgements) return; diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs index 2da4d8265d..3f9464a98f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSlider.cs @@ -304,13 +304,13 @@ namespace osu.Game.Rulesets.Osu.Tests foreach (var mod in Mods.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); - drawable.OnJudgement += onJudgement; + drawable.OnNewResult += onNewResult; Add(drawable); } private float judgementOffsetDirection = 1; - private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) + private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { var osuObject = judgedObject as DrawableOsuHitObject; if (osuObject == null) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 2986b4b5dc..d935c28365 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -51,9 +51,9 @@ namespace osu.Game.Rulesets.Osu.Scoring private const double harshness = 0.01; - protected override void OnNewJudgement(JudgementResult result) + protected override void ApplyResult(JudgementResult result) { - base.OnNewJudgement(result); + base.ApplyResult(result); var osuResult = (OsuJudgementResult)result; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 8a898fb5e2..989b1ed964 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.UI public override void Add(DrawableHitObject h) { - h.OnJudgement += onJudgement; + h.OnNewResult += onNewResult; var c = h as IDrawableHitObjectWithProxiedApproach; if (c != null) @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Osu.UI connectionLayer.HitObjects = HitObjects.Objects.Select(d => d.HitObject).OfType(); } - private void onJudgement(DrawableHitObject judgedObject, JudgementResult result) + private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!judgedObject.DisplayJudgement || !DisplayJudgements) return; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 35cb94e8de..23c57e0767 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -140,18 +140,18 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); if (RNG.Next(10) == 0) { - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); } } private void addMissJudgement() { - ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index a984af3b51..18669cec2b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables foreach (var tick in drumRoll.NestedHitObjects.OfType()) { var newTick = new DrawableDrumRollTick(tick); - newTick.OnJudgement += onTickJudgement; + newTick.OnNewResult += onNewTickResult; AddNested(newTick); tickContainer.Add(newTick); @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables colourEngaged = colours.YellowDarker; } - private void onTickJudgement(DrawableHitObject obj, JudgementResult result) + private void onNewTickResult(DrawableHitObject obj, JudgementResult result) { if (result.Type > HitResult.Miss) rollingHits++; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index f5c5fcbe9c..cf33141027 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -76,9 +76,9 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); } - protected override void OnNewJudgement(JudgementResult result) + protected override void ApplyResult(JudgementResult result) { - base.OnNewJudgement(result); + base.ApplyResult(result); bool isTick = result.Judgement is TaikoDrumRollTickJudgement; diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 5202fe00ad..8078f648e8 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -209,7 +209,7 @@ namespace osu.Game.Rulesets.Taiko.UI public override void Add(DrawableHitObject h) { - h.OnJudgement += OnJudgement; + h.OnNewResult += OnNewResult; base.Add(h); @@ -224,7 +224,7 @@ namespace osu.Game.Rulesets.Taiko.UI } } - internal void OnJudgement(DrawableHitObject judgedObject, JudgementResult result) + internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { if (!DisplayJudgements) return; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index a22a7a616b..0bc7a160ce 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -35,8 +35,15 @@ namespace osu.Game.Rulesets.Objects.Drawables private readonly Lazy> nestedHitObjects = new Lazy>(); public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty(); - public event Action OnJudgement; - public event Action OnJudgementRemoved; + /// + /// Invoked when a has been applied by this or a nested . + /// + public event Action OnNewResult; + + /// + /// Invoked when a has been reset by this or a nested . + /// + public event Action OnResultReset; /// /// Whether a visible judgement should be displayed when this representation is hit. @@ -143,7 +150,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result.TimeOffset + endTime < Time.Current) { - OnJudgementRemoved?.Invoke(this, Result); + OnResultReset?.Invoke(this, Result); Result.Type = HitResult.None; State.Value = ArmedState.Idle; @@ -162,8 +169,8 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void AddNested(DrawableHitObject h) { - h.OnJudgement += (d, r) => OnJudgement?.Invoke(d, r); - h.OnJudgementRemoved += (d, r) => OnJudgementRemoved?.Invoke(d, r); + h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); + h.OnResultReset += (d, r) => OnResultReset?.Invoke(d, r); h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); nestedHitObjects.Value.Add(h); @@ -195,7 +202,7 @@ namespace osu.Game.Rulesets.Objects.Drawables break; } - OnJudgement?.Invoke(this, Result); + OnNewResult?.Invoke(this, Result); } /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 985cfce6aa..b727a0d685 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -195,8 +195,8 @@ namespace osu.Game.Rulesets.Scoring { Debug.Assert(base_portion + combo_portion == 1.0); - rulesetContainer.OnJudgement += AddJudgement; - rulesetContainer.OnJudgementRemoved += RemoveJudgement; + rulesetContainer.OnNewResult += applyResult; + rulesetContainer.OnResultReset += resetResult; SimulateAutoplay(rulesetContainer.Beatmap); Reset(true); @@ -210,10 +210,19 @@ namespace osu.Game.Rulesets.Scoring Mode.ValueChanged += _ => updateScore(); } + /// + /// Applies any properties of the which affect scoring to this . + /// + /// The to read properties from. protected virtual void ApplyBeatmap(Beatmap beatmap) { } + /// + /// Simulates an autoplay of the to determine scoring values. + /// + /// This provided temporarily. DO NOT USE. + /// The to simulate. protected virtual void SimulateAutoplay(Beatmap beatmap) { foreach (var obj in beatmap.HitObjects) @@ -230,18 +239,17 @@ namespace osu.Game.Rulesets.Scoring var result = CreateJudgementResult(obj.Judgement); result.Type = obj.Judgement.MaxResult; - AddJudgement(result); + applyResult(result); } } /// - /// Adds a judgement to this ScoreProcessor. + /// Applies the score change of a to this . /// - /// The judgement to add. - /// The judgement scoring result. - protected void AddJudgement(JudgementResult result) + /// The to apply. + private void applyResult(JudgementResult result) { - OnNewJudgement(result); + ApplyResult(result); updateScore(); UpdateFailed(); @@ -249,22 +257,21 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Removes a judgement from this ScoreProcessor. + /// Resets the score change of a that was applied to this . /// /// The judgement to remove. /// The judgement scoring result. - protected void RemoveJudgement(JudgementResult result) + private void resetResult(JudgementResult result) { - OnJudgementRemoved(result); + ResetResult(result); updateScore(); } /// - /// Applies a judgement. + /// Applies the score change of a to this . /// - /// The judgement to apply/ - /// The judgement scoring result. - protected virtual void OnNewJudgement(JudgementResult result) + /// The to apply. + protected virtual void ApplyResult(JudgementResult result) { result.ComboAtJudgement = Combo; result.HighestComboAtJudgement = HighestCombo; @@ -299,11 +306,11 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Removes a judgement. This should reverse everything in . + /// Resets the score change of a that was applied to this . /// /// The judgement to remove. /// The judgement scoring result. - protected virtual void OnJudgementRemoved(JudgementResult result) + protected virtual void ResetResult(JudgementResult result) { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; @@ -356,6 +363,10 @@ namespace osu.Game.Rulesets.Scoring bonusScore = 0; } + /// + /// Creates the that represents the scoring result for a . + /// + /// The that provides the scoring information. protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index e890cccc3c..23ec0575e3 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -182,8 +182,15 @@ namespace osu.Game.Rulesets.UI public abstract class RulesetContainer : RulesetContainer where TObject : HitObject { - public event Action OnJudgement; - public event Action OnJudgementRemoved; + /// + /// Invoked when a has been applied by any . + /// + public event Action OnNewResult; + + /// + /// Invoked when a has been reset by any . + /// + public event Action OnResultReset; /// /// The Beatmap @@ -290,8 +297,8 @@ namespace osu.Game.Rulesets.UI if (drawableObject == null) continue; - drawableObject.OnJudgement += (_, r) => OnJudgement?.Invoke(r); - drawableObject.OnJudgementRemoved += (_, r) => OnJudgementRemoved?.Invoke(r); + drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r); + drawableObject.OnResultReset += (_, r) => OnResultReset?.Invoke(r); Playfield.Add(drawableObject); } From b35817c8779cf5a761a432a8c3f14d8a688f9d7c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 10:55:38 +0900 Subject: [PATCH 098/277] More xmldocs to hitobject/drawablehitobject --- osu.Game/Rulesets/Judgements/Judgement.cs | 4 ++++ osu.Game/Rulesets/Judgements/JudgementResult.cs | 16 ++++++++++++---- .../Objects/Drawables/DrawableHitObject.cs | 12 ++++++++++-- osu.Game/Rulesets/Objects/HitObject.cs | 8 ++++++-- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 5fddbe0b0a..c679df5900 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements { + /// + /// The scoring information provided by a . + /// public class Judgement { /// diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs index 6971fcf593..5cadf7e2ee 100644 --- a/osu.Game/Rulesets/Judgements/JudgementResult.cs +++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs @@ -1,10 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Judgements { + /// + /// The scoring result of a . + /// public class JudgementResult { /// @@ -19,22 +23,22 @@ namespace osu.Game.Rulesets.Judgements /// /// The offset from a perfect hit at which this occurred. - /// Populated when added via . + /// Populated when this is applied via . /// public double TimeOffset { get; internal set; } /// - /// The combo prior to this judgement occurring. + /// The combo prior to this occurring. /// public int ComboAtJudgement { get; internal set; } /// - /// The highest combo achieved prior to this judgement occurring. + /// The highest combo achieved prior to this occurring. /// public int HighestComboAtJudgement { get; internal set; } /// - /// Whether this has a result. + /// Whether a miss or hit occurred. /// public bool HasResult => Type > HitResult.None; @@ -43,6 +47,10 @@ namespace osu.Game.Rulesets.Judgements /// public bool IsHit => Type > HitResult.Miss; + /// + /// Creates a new . + /// + /// The to refer to for scoring information. public JudgementResult(Judgement judgement) { Judgement = judgement; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 0bc7a160ce..4b3129929e 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -67,6 +67,9 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public bool Judged => Result?.HasResult ?? true; + /// + /// The scoring result of this . + /// public readonly JudgementResult Result; private bool judgementOccurred; @@ -177,9 +180,10 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// Notifies that a new judgement has occurred for this . + /// Applies the of this , notifying responders such as + /// the of the . /// - /// The . + /// The callback that applies changes to the . protected void ApplyResult(Action application) { application?.Invoke(Result); @@ -240,6 +244,10 @@ namespace osu.Game.Rulesets.Objects.Drawables { } + /// + /// Creates the that represents the scoring result for this . + /// + /// The that provides the scoring information. protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 531a8bed38..a9cf23f924 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -108,10 +108,14 @@ namespace osu.Game.Rulesets.Objects { } - protected virtual Judgement CreateJudgement() => null; - protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); + /// + /// Creates the that represents the scoring information for this . + /// May be null. + /// + protected virtual Judgement CreateJudgement() => null; + /// /// Creates the for this . /// This can be null to indicate that the has no . From 754f3c86212f81a183d192351a48ddd53728b717 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 11:07:05 +0900 Subject: [PATCH 099/277] Move result creation to load(), add exceptions --- .../Objects/Drawables/DrawableHitObject.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4b3129929e..910abfeb4a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions.TypeExtensions; using osu.Game.Audio; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; @@ -70,7 +71,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// The scoring result of this . /// - public readonly JudgementResult Result; + public JudgementResult Result { get; private set; } private bool judgementOccurred; @@ -87,14 +88,19 @@ namespace osu.Game.Rulesets.Objects.Drawables protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; - - if (hitObject.Judgement != null) - Result = CreateJudgementResult(hitObject.Judgement); } [BackgroundDependencyLoader] private void load() { + if (HitObject.Judgement != null) + { + Result = CreateJudgementResult(HitObject.Judgement); + + if (Result == null) + throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateJudgementResult)}."); + } + var samples = GetSamples().ToArray(); if (samples.Any()) @@ -188,6 +194,9 @@ namespace osu.Game.Rulesets.Objects.Drawables { application?.Invoke(Result); + if (!Result.HasResult) + throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}."); + judgementOccurred = true; // Ensure that the judgement is given a valid time offset, because this may not get set by the caller From ab642b563fe1ac4a3b1fe6ae3ec296dd3150072b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 11:07:41 +0900 Subject: [PATCH 100/277] CreateJudgementResult -> CreateResult --- .../Objects/Drawables/DrawableOsuHitObject.cs | 2 +- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 2 +- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 2529ac20c4..0501f8b7a0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -68,6 +68,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private OsuInputManager osuActionInputManager; internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager); - protected override JudgementResult CreateJudgementResult(Judgement judgement) => new OsuJudgementResult(judgement); + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index d935c28365..a9d39e88b4 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -87,6 +87,6 @@ namespace osu.Game.Rulesets.Osu.Scoring } } - protected override JudgementResult CreateJudgementResult(Judgement judgement) => new OsuJudgementResult(judgement); + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(judgement); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 910abfeb4a..f29a6fb6db 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -95,10 +95,10 @@ namespace osu.Game.Rulesets.Objects.Drawables { if (HitObject.Judgement != null) { - Result = CreateJudgementResult(HitObject.Judgement); + Result = CreateResult(HitObject.Judgement); if (Result == null) - throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateJudgementResult)}."); + throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } var samples = GetSamples().ToArray(); @@ -257,7 +257,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Creates the that represents the scoring result for this . /// /// The that provides the scoring information. - protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); + protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement); } public abstract class DrawableHitObject : DrawableHitObject diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b727a0d685..4cadae4212 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -236,7 +236,7 @@ namespace osu.Game.Rulesets.Scoring if (obj.Judgement == null) return; - var result = CreateJudgementResult(obj.Judgement); + var result = CreateResult(obj.Judgement); result.Type = obj.Judgement.MaxResult; applyResult(result); @@ -367,7 +367,7 @@ namespace osu.Game.Rulesets.Scoring /// Creates the that represents the scoring result for a . /// /// The that provides the scoring information. - protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement); + protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(judgement); } public enum ScoringMode From 741ec0021ef9286cbaa96055c5e53a3345a5acd7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 11:31:46 +0900 Subject: [PATCH 101/277] Rename more judgement-related methods to "result" --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 +- .../Objects/Drawables/DrawableHoldNote.cs | 8 ++++---- .../Objects/Drawables/DrawableHoldNoteTick.cs | 2 +- .../Objects/Drawables/DrawableNote.cs | 4 ++-- osu.Game.Rulesets.Mania/UI/Column.cs | 2 +- osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 2 +- osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs | 4 ++-- osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs | 4 ++-- .../Objects/Drawables/DrawableHitCircle.cs | 4 ++-- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 +- .../Objects/Drawables/DrawableSlider.cs | 2 +- .../Objects/Drawables/DrawableSliderTail.cs | 4 ++-- .../Objects/Drawables/DrawableSliderTick.cs | 4 ++-- .../Objects/Drawables/DrawableSpinner.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- .../Objects/Drawables/DrawableDrumRoll.cs | 4 ++-- .../Objects/Drawables/DrawableDrumRollTick.cs | 8 ++++---- .../Objects/Drawables/DrawableHit.cs | 10 +++++----- .../Objects/Drawables/DrawableStrongHandler.cs | 2 +- .../Objects/Drawables/DrawableSwell.cs | 4 ++-- .../Objects/Drawables/DrawableSwellTick.cs | 4 ++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 12 ++++++------ 23 files changed, 47 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 982fa193c6..9e840301fd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public Func CheckPosition; - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (CheckPosition == null) return; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index da4bf1c575..f9501bdb87 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableHoldNote : DrawableManiaHitObject, IKeyBindingHandler { - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; private readonly DrawableNote head; private readonly DrawableNote tail; @@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (tail.AllJudged) ApplyResult(r => r.Type = HitResult.Perfect); @@ -196,7 +196,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables this.holdNote = holdNote; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { // Factor in the release lenience timeOffset /= release_window_lenience; @@ -233,7 +233,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (action != Action.Value) return false; - UpdateJudgement(true); + UpdateResult(true); // Handled by the hold note, which will set holding = false return false; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 05a4ea60d6..01d5bc6fd4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (Time.Current < HitObject.StartTime) return; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 42b4128019..7567f40b2f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) { @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (action != Action.Value) return false; - return UpdateJudgement(true); + return UpdateResult(true); } public virtual bool OnReleased(ManiaAction action) => false; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 500f999dd6..d489d48fc3 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!result.IsHit || !judgedObject.DisplayJudgement || !DisplayJudgements) + if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements) return; explosionContainer.Add(new HitExplosion(judgedObject) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index f5993e61de..4e888b101b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Mania.UI internal void OnNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayJudgement || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements) return; judgements.Clear(); diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs index 79866b8a4a..c2d3aab2ab 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseHitCircle.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Tests this.auto = auto; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (auto && !userTriggered && timeOffset > 0) { @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Tests ApplyResult(r => r.Type = HitResult.Great); } else - base.CheckForJudgements(userTriggered, timeOffset); + base.CheckForResult(userTriggered, timeOffset); } } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs index b05a763e88..3b91ea93b8 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestCaseSpinner.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Tests this.auto = auto; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (auto && !userTriggered && Time.Current > Spinner.StartTime + Spinner.Duration / 2 && Progress < 1) { @@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Osu.Tests auto = false; } - base.CheckForJudgements(userTriggered, timeOffset); + base.CheckForResult(userTriggered, timeOffset); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 15521113ed..6344fbb770 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (AllJudged) return false; - UpdateJudgement(true); + UpdateResult(true); return true; }, }, @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index ea1ee9fb1e..dfe7937e81 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (repeatPoint.StartTime <= Time.Current) ApplyResult(r => r.Type = drawableSlider.Tracking ? HitResult.Great : HitResult.Miss); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 71be07f166..f48f03f197 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered || Time.Current < slider.EndTime) return; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs index 9261741a12..45c925b87a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables /// /// The judgement text is provided by the . /// - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; public bool Tracking { get; set; } @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Position = HitObject.Position - slider.Position; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered && timeOffset >= 0) ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 8819fa962b..964c75131a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public bool Tracking { get; set; } - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (timeOffset >= 0) ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 3feb612c8b..51b1990a21 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public float Progress => MathHelper.Clamp(Disc.RotationAbsolute / 360 / Spinner.SpinsRequired, 0, 1); - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (Time.Current < HitObject.StartTime) return; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 989b1ed964..703d8764fc 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Osu.UI private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) { - if (!judgedObject.DisplayJudgement || !DisplayJudgements) + if (!judgedObject.DisplayResult || !DisplayJudgements) return; DrawableOsuJudgement explosion = new DrawableOsuJudgement(result, judgedObject) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 18669cec2b..0fb2405f77 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables MainPiece.FadeAccent(newColour, 100); } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered) return; @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!MainObject.Judged) return; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index cbe6e10dcb..ff1cce24b6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -17,14 +17,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables FillMode = FillMode.Fit; } - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; protected override TaikoPiece CreateMainPiece() => new TickPiece { Filled = HitObject.FirstTick }; - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) { @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - public override bool OnPressed(TaikoAction action) => UpdateJudgement(true); + public override bool OnPressed(TaikoAction action) => UpdateResult(true); protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!MainObject.Judged) return; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 4289a77f4c..6181b74822 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables FillMode = FillMode.Fit; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) { @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables validActionPressed = HitActions.Contains(action); // Only count this as handled if the new judgement is a hit - var result = UpdateJudgement(true); + var result = UpdateResult(true); if (IsHit) HitAction = action; @@ -144,11 +144,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!MainObject.Result.HasResult) { - base.CheckForJudgements(userTriggered, timeOffset); + base.CheckForResult(userTriggered, timeOffset); return; } @@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (!MainObject.HitActions.Contains(action)) return false; - return UpdateJudgement(true); + return UpdateResult(true); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs index 6f2db764a8..6406582191 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public abstract class DrawableStrongHandler : DrawableTaikoHitObject { - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; public readonly DrawableHitObject MainObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 24b1a0e9da..5059734663 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Width *= Parent.RelativeChildSize.X; } - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (userTriggered) { @@ -231,7 +231,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables return false; lastWasCentre = isCentre; - UpdateJudgement(true); + UpdateResult(true); return true; } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs index 8266d329a2..36c468c6d6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableSwellTick : DrawableTaikoHitObject { - public override bool DisplayJudgement => false; + public override bool DisplayResult => false; public DrawableSwellTick(TaikoHitObject hitObject) : base(hitObject) @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public void TriggerResult(HitResult type) => ApplyResult(r => r.Type = type); - protected override void CheckForJudgements(bool userTriggered, double timeOffset) + protected override void CheckForResult(bool userTriggered, double timeOffset) { } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 8078f648e8..8973a4ef35 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -229,7 +229,7 @@ namespace osu.Game.Rulesets.Taiko.UI if (!DisplayJudgements) return; - if (!judgedObject.DisplayJudgement) + if (!judgedObject.DisplayResult) return; switch (result.Judgement) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index f29a6fb6db..4f7ec4c29e 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether a visible judgement should be displayed when this representation is hit. /// - public virtual bool DisplayJudgement => true; + public virtual bool DisplayResult => true; /// /// Whether this and all of its nested s have been judged. @@ -173,7 +173,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { base.UpdateAfterChildren(); - UpdateJudgement(false); + UpdateResult(false); } protected virtual void AddNested(DrawableHitObject h) @@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Whether the user triggered this process. /// Whether a judgement has occurred from this or any nested s. - protected bool UpdateJudgement(bool userTriggered) + protected bool UpdateResult(bool userTriggered) { judgementOccurred = false; @@ -231,13 +231,13 @@ namespace osu.Game.Rulesets.Objects.Drawables return false; foreach (var d in NestedHitObjects) - judgementOccurred |= d.UpdateJudgement(userTriggered); + judgementOccurred |= d.UpdateResult(userTriggered); if (judgementOccurred || Judged) return judgementOccurred; var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - CheckForJudgements(userTriggered, Time.Current - endTime); + CheckForResult(userTriggered, Time.Current - endTime); return judgementOccurred; } @@ -249,7 +249,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether the user triggered this check. /// The offset from the end time at which this check occurred. A > 0 /// implies that this check occurred after the end time of . - protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) + protected virtual void CheckForResult(bool userTriggered, double timeOffset) { } From 0d6a8a2bf561f863dbed4c41b5bfdfe57546700e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 11:31:54 +0900 Subject: [PATCH 102/277] More xmldocs --- .../Objects/Drawables/DrawableHitObject.cs | 16 +++++++++------- osu.Game/Rulesets/Objects/HitObject.cs | 6 ++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4f7ec4c29e..17533f4ca0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Objects.Drawables public event Action OnResultReset; /// - /// Whether a visible judgement should be displayed when this representation is hit. + /// Whether a visual indicator should be displayed when a scoring result occurs. /// public virtual bool DisplayResult => true; @@ -219,10 +219,10 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// Processes this , checking if any judgements have occurred. + /// Processes this , checking if a scoring result has occurred. /// /// Whether the user triggered this process. - /// Whether a judgement has occurred from this or any nested s. + /// Whether a scoring result has occurred from this or any nested . protected bool UpdateResult(bool userTriggered) { judgementOccurred = false; @@ -243,12 +243,14 @@ namespace osu.Game.Rulesets.Objects.Drawables } /// - /// Checks if any judgements have occurred for this . This method must construct - /// all s and notify of them through . + /// Checks if a scoring result has occurred for this . /// + /// + /// If a scoring result has occurred, this method must invoke to update the result and notify responders. + /// /// Whether the user triggered this check. - /// The offset from the end time at which this check occurred. A > 0 - /// implies that this check occurred after the end time of . + /// The offset from the end time of the at which this check occurred. + /// A > 0 implies that this check occurred after the end time of the . protected virtual void CheckForResult(bool userTriggered, double timeOffset) { } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index a9cf23f924..eee690474b 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -63,6 +63,12 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; + /// + /// The judgement information provided by this . + /// + /// + /// Only populated after is invoked. + /// public Judgement Judgement { get; private set; } /// From 3a7488767c51b54b70e5e202f647c6404b8e0e46 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 11:50:18 +0900 Subject: [PATCH 103/277] Make HitObject not store the judgement --- osu.Game.Rulesets.Catch/Objects/Banana.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Droplet.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Fruit.cs | 2 +- osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 2 +- osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs | 2 +- osu.Game.Rulesets.Mania/Objects/Note.cs | 2 +- osu.Game.Rulesets.Mania/Objects/TailNote.cs | 2 +- osu.Game.Rulesets.Osu/Objects/HitCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Slider.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs | 2 +- osu.Game.Rulesets.Osu/Objects/SliderTick.cs | 2 +- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs | 2 +- osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 2 +- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 6 +++--- osu.Game/Rulesets/Objects/HitObject.cs | 12 +----------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 ++++--- 20 files changed, 25 insertions(+), 34 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Banana.cs b/osu.Game.Rulesets.Catch/Objects/Banana.cs index e021bafdb6..e1af4c1075 100644 --- a/osu.Game.Rulesets.Catch/Objects/Banana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Banana.cs @@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; - protected override Judgement CreateJudgement() => new CatchBananaJudgement(); + public override Judgement CreateJudgement() => new CatchBananaJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index 79aefdb6d3..8b54922959 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Droplet : CatchHitObject { - protected override Judgement CreateJudgement() => new CatchDropletJudgement(); + public override Judgement CreateJudgement() => new CatchDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 53a484ed56..2c2cd013c3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class Fruit : CatchHitObject { - protected override Judgement CreateJudgement() => new CatchJudgement(); + public override Judgement CreateJudgement() => new CatchJudgement(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index ddb88c2c1c..39f1cadad5 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Catch.Objects { public class TinyDroplet : Droplet { - protected override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); + public override Judgement CreateJudgement() => new CatchTinyDropletJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 26116c2691..e493956d6e 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -97,6 +97,6 @@ namespace osu.Game.Rulesets.Mania.Objects } } - protected override Judgement CreateJudgement() => new HoldNoteJudgement(); + public override Judgement CreateJudgement() => new HoldNoteJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index b428c6158d..05959a31c0 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class HoldNoteTick : ManiaHitObject { - protected override Judgement CreateJudgement() => new HoldNoteTickJudgement(); + public override Judgement CreateJudgement() => new HoldNoteTickJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index ffc3ed0bd7..42877649d2 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - protected override Judgement CreateJudgement() => new ManiaJudgement(); + public override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/TailNote.cs b/osu.Game.Rulesets.Mania/Objects/TailNote.cs index 522f78336f..9de542bcd3 100644 --- a/osu.Game.Rulesets.Mania/Objects/TailNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/TailNote.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Mania.Objects { public class TailNote : Note { - protected override Judgement CreateJudgement() => new ManiaJudgement(); + public override Judgement CreateJudgement() => new ManiaJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index b5e64e9e40..d1656a9672 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index 83f7f79f39..c8621cdbcf 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -27,6 +27,6 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = Math.Min(SpanDuration * 2, TimePreempt); } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index eead98ac28..7a0dcc77a6 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -214,6 +214,6 @@ namespace osu.Game.Rulesets.Osu.Objects } } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index faa325d416..23616ea005 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Osu.Objects { } - protected override Judgement CreateJudgement() => new OsuSliderTailJudgement(); + public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 000781dec6..906f0a0182 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -29,6 +29,6 @@ namespace osu.Game.Rulesets.Osu.Objects TimePreempt = (StartTime - SpanStartTime) / 2 + offset; } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index d100e33f17..e1a7a7c6df 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -32,6 +32,6 @@ namespace osu.Game.Rulesets.Osu.Objects SpinsRequired = (int)Math.Max(1, SpinsRequired * 0.6); } - protected override Judgement CreateJudgement() => new OsuJudgement(); + public override Judgement CreateJudgement() => new OsuJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index f6a3a5efef..967d5acfd7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -24,6 +24,6 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double HitWindow => TickSpacing / 2; - protected override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); + public override Judgement CreateJudgement() => new TaikoDrumRollTickJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs index a9d452cc68..fac3705110 100644 --- a/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/StrongHitObject.cs @@ -8,6 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Objects { public class StrongHitObject : TaikoHitObject { - protected override Judgement CreateJudgement() => new TaikoStrongJudgement(); + public override Judgement CreateJudgement() => new TaikoStrongJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 702b6d73b6..6948c5bcde 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.Objects AddNested(new StrongHitObject { StartTime = (this as IHasEndTime)?.EndTime ?? StartTime }); } - protected override Judgement CreateJudgement() => new TaikoJudgement(); + public override Judgement CreateJudgement() => new TaikoJudgement(); protected override HitWindows CreateHitWindows() => new TaikoHitWindows(); } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 17533f4ca0..e1848412c2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -93,10 +93,10 @@ namespace osu.Game.Rulesets.Objects.Drawables [BackgroundDependencyLoader] private void load() { - if (HitObject.Judgement != null) + var judgement = HitObject.CreateJudgement(); + if (judgement != null) { - Result = CreateResult(HitObject.Judgement); - + Result = CreateResult(judgement); if (Result == null) throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index eee690474b..beb9620f78 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -63,14 +63,6 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; - /// - /// The judgement information provided by this . - /// - /// - /// Only populated after is invoked. - /// - public Judgement Judgement { get; private set; } - /// /// Applies default values to this HitObject. /// @@ -80,8 +72,6 @@ namespace osu.Game.Rulesets.Objects { ApplyDefaultsToSelf(controlPointInfo, difficulty); - Judgement = CreateJudgement(); - if (nestedHitObjects.IsValueCreated) nestedHitObjects.Value.Clear(); @@ -120,7 +110,7 @@ namespace osu.Game.Rulesets.Objects /// Creates the that represents the scoring information for this . /// May be null. /// - protected virtual Judgement CreateJudgement() => null; + public virtual Judgement CreateJudgement() => null; /// /// Creates the for this . diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4cadae4212..a185648531 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -233,11 +233,12 @@ namespace osu.Game.Rulesets.Scoring foreach (var nested in obj.NestedHitObjects) simulate(nested); - if (obj.Judgement == null) + var judgement = obj.CreateJudgement(); + if (judgement == null) return; - var result = CreateResult(obj.Judgement); - result.Type = obj.Judgement.MaxResult; + var result = CreateResult(judgement); + result.Type = judgement.MaxResult; applyResult(result); } From 35b5aeb99ad13c12c756d89a9499336ce3c1379c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 12:23:08 +0900 Subject: [PATCH 104/277] Fix missed rename --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index ffb93fd679..d49be69856 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -68,6 +68,6 @@ namespace osu.Game.Rulesets.Catch.UI } private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) - => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, result); + => catcherArea.OnResult((DrawableCatchHitObject)judgedObject, result); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index ca9fa6f595..4327abb96f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Catch.UI private DrawableCatchHitObject lastPlateableFruit; - public void OnJudgement(DrawableCatchHitObject fruit, JudgementResult result) + public void OnResult(DrawableCatchHitObject fruit, JudgementResult result) { void runAfterLoaded(Action action) { From c48a4d999352c7c2c0a135ff38bb3ce08c142701 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 12:29:12 +0900 Subject: [PATCH 105/277] Add exception --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a185648531..1f0584405a 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -238,6 +238,9 @@ namespace osu.Game.Rulesets.Scoring return; var result = CreateResult(judgement); + if (result == null) + throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); + result.Type = judgement.MaxResult; applyResult(result); From 2a54b5b78d06859816fffed21511fee2b9657bdc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 12:29:22 +0900 Subject: [PATCH 106/277] ResetResult -> RevertResult --- .../Rulesets/Objects/Drawables/DrawableHitObject.cs | 8 ++++---- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 13 +++++++------ osu.Game/Rulesets/UI/RulesetContainer.cs | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e1848412c2..2abb2eb289 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -42,9 +42,9 @@ namespace osu.Game.Rulesets.Objects.Drawables public event Action OnNewResult; /// - /// Invoked when a has been reset by this or a nested . + /// Invoked when a is being reverted by this or a nested . /// - public event Action OnResultReset; + public event Action OnRevertResult; /// /// Whether a visual indicator should be displayed when a scoring result occurs. @@ -159,7 +159,7 @@ namespace osu.Game.Rulesets.Objects.Drawables if (Result.TimeOffset + endTime < Time.Current) { - OnResultReset?.Invoke(this, Result); + OnRevertResult?.Invoke(this, Result); Result.Type = HitResult.None; State.Value = ArmedState.Idle; @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Objects.Drawables protected virtual void AddNested(DrawableHitObject h) { h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); - h.OnResultReset += (d, r) => OnResultReset?.Invoke(d, r); + h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r); h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); nestedHitObjects.Value.Add(h); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 1f0584405a..d8c72d4b2e 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using osu.Framework.Configuration; +using osu.Framework.Extensions.TypeExtensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; @@ -196,7 +197,7 @@ namespace osu.Game.Rulesets.Scoring Debug.Assert(base_portion + combo_portion == 1.0); rulesetContainer.OnNewResult += applyResult; - rulesetContainer.OnResultReset += resetResult; + rulesetContainer.OnRevertResult += revertResult; SimulateAutoplay(rulesetContainer.Beatmap); Reset(true); @@ -261,13 +262,13 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Resets the score change of a that was applied to this . + /// Reverts the score change of a that was applied to this . /// /// The judgement to remove. /// The judgement scoring result. - private void resetResult(JudgementResult result) + private void revertResult(JudgementResult result) { - ResetResult(result); + RevertResult(result); updateScore(); } @@ -310,11 +311,11 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Resets the score change of a that was applied to this . + /// Reverts the score change of a that was applied to this . /// /// The judgement to remove. /// The judgement scoring result. - protected virtual void ResetResult(JudgementResult result) + protected virtual void RevertResult(JudgementResult result) { Combo.Value = result.ComboAtJudgement; HighestCombo.Value = result.HighestComboAtJudgement; diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 23ec0575e3..64ee680d45 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -183,14 +183,14 @@ namespace osu.Game.Rulesets.UI where TObject : HitObject { /// - /// Invoked when a has been applied by any . + /// Invoked when a has been applied by a . /// public event Action OnNewResult; /// - /// Invoked when a has been reset by any . + /// Invoked when a is being reverted by a . /// - public event Action OnResultReset; + public event Action OnRevertResult; /// /// The Beatmap @@ -298,7 +298,7 @@ namespace osu.Game.Rulesets.UI continue; drawableObject.OnNewResult += (_, r) => OnNewResult?.Invoke(r); - drawableObject.OnResultReset += (_, r) => OnResultReset?.Invoke(r); + drawableObject.OnRevertResult += (_, r) => OnRevertResult?.Invoke(r); Playfield.Add(drawableObject); } From 60c94a8ea37ef63e0664ccb5acecf20447ed3fc4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 12:42:28 +0900 Subject: [PATCH 107/277] Fix ScoreProcessor.ApplyBeatmap never being called --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index d8c72d4b2e..b0cea7009e 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -199,6 +199,7 @@ namespace osu.Game.Rulesets.Scoring rulesetContainer.OnNewResult += applyResult; rulesetContainer.OnRevertResult += revertResult; + ApplyBeatmap(rulesetContainer.Beatmap); SimulateAutoplay(rulesetContainer.Beatmap); Reset(true); From 5c4c2dff09fde00e063053ded0d6c9b2480bead8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 6 Aug 2018 13:01:27 +0900 Subject: [PATCH 108/277] Fix strong hits not being visualised --- .../TestCaseTaikoPlayfield.cs | 39 ++++++++++++++----- .../Drawables/DrawableStrongHandler.cs | 2 - 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index 23c57e0767..b002c2abab 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -39,8 +39,10 @@ namespace osu.Game.Rulesets.Taiko.Tests [BackgroundDependencyLoader] private void load() { - AddStep("Hit!", () => addHitJudgement(false)); + AddStep("Hit", () => addHitJudgement(false)); + AddStep("Strong hit", () => addStrongHitJudgement(false)); AddStep("Kiai hit", () => addHitJudgement(true)); + AddStep("Strong kiai hit", () => addStrongHitJudgement(true)); AddStep("Miss :(", addMissJudgement); AddStep("DrumRoll", () => addDrumRoll(false)); AddStep("Strong DrumRoll", () => addDrumRoll(true)); @@ -130,10 +132,7 @@ namespace osu.Game.Rulesets.Taiko.Tests HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; var cpi = new ControlPointInfo(); - cpi.EffectPoints.Add(new EffectControlPoint - { - KiaiMode = kiai - }); + cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); Hit hit = new Hit(); hit.ApplyDefaults(cpi, new BeatmapDifficulty()); @@ -141,12 +140,22 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + } - if (RNG.Next(10) == 0) - { - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); - } + private void addStrongHitJudgement(bool kiai) + { + HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great; + + var cpi = new ControlPointInfo(); + cpi.EffectPoints.Add(new EffectControlPoint { KiaiMode = kiai }); + + Hit hit = new Hit(); + hit.ApplyDefaults(cpi, new BeatmapDifficulty()); + + var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; + + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new TestStrongHandler(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() @@ -217,6 +226,16 @@ namespace osu.Game.Rulesets.Taiko.Tests rulesetContainer.Playfield.Add(new DrawableRimHit(h)); } + private class TestStrongHandler : DrawableStrongHandler + { + public TestStrongHandler(DrawableHitObject mainObject) + : base(null, mainObject) + { + } + + public override bool OnPressed(TaikoAction action) => false; + } + private class DrawableTestHit : DrawableHitObject { public DrawableTestHit(TaikoHitObject hitObject) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs index 6406582191..45a853b94b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// public abstract class DrawableStrongHandler : DrawableTaikoHitObject { - public override bool DisplayResult => false; - public readonly DrawableHitObject MainObject; protected DrawableStrongHandler(StrongHitObject strong, DrawableHitObject mainObject) From 5d573ae17618e993e8f8651ae10ee352c1a54165 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Aug 2018 01:00:06 +0900 Subject: [PATCH 109/277] Update squirrel --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 6ee9c3155e..8968a82294 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -27,7 +27,7 @@ - + From 7233e863dbbacb31043ef3c1d04158f27be834dc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Aug 2018 01:07:50 +0900 Subject: [PATCH 110/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1fed7f46bc..e9fc51ee9b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 8ee38460d37ccef81fe474c1a13a9b2bd53cf3b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Aug 2018 02:01:31 +0900 Subject: [PATCH 111/277] Bump squirrel version with bugfix --- osu.Desktop/osu.Desktop.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 8968a82294..180abd7fec 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -27,7 +27,7 @@ - + From f719b9bef58da1e82dce0d702c8f498446dd5865 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 7 Aug 2018 12:20:24 +0900 Subject: [PATCH 112/277] Fix mania scroll direction not being read from database --- osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs b/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs index a1cc7cfbc7..624ea13e1b 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaScrollingInfo.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Mania.UI public ManiaScrollingInfo(ManiaConfigManager config) { config.BindWith(ManiaSetting.ScrollDirection, configDirection); - configDirection.BindValueChanged(v => Direction.Value = (ScrollingDirection)v); + configDirection.BindValueChanged(v => Direction.Value = (ScrollingDirection)v, true); } } } From 7b8bd7f21c6b1b7f2b36cde8ce57f46b0e9d9f55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Aug 2018 14:49:44 +0900 Subject: [PATCH 113/277] Fix mod selection not restoring when re-entering song select --- osu.Game.Tests/Visual/TestCaseMods.cs | 3 + osu.Game/OsuGame.cs | 5 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 70 ++++++++++++---------- osu.Game/Screens/Select/PlaySongSelect.cs | 15 +++-- 4 files changed, 54 insertions(+), 39 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index cc396a63e3..6330afe860 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using System.Linq; using System.Collections.Generic; +using osu.Framework.Configuration; using osu.Game.Rulesets.Osu; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.Sprites; @@ -237,6 +238,8 @@ namespace osu.Game.Tests.Visual private class TestModSelectOverlay : ModSelectOverlay { + public new Bindable> SelectedMods => base.SelectedMods; + public ModButton GetModButton(Mod mod) { var section = ModSectionsContainer.Children.Single(s => s.ModType == mod.Type); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 025d5f50e3..69d1236126 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -99,7 +99,7 @@ namespace osu.Game private readonly List overlays = new List(); // todo: move this to SongSelect once Screen has the ability to unsuspend. - public readonly Bindable> SelectedMods = new Bindable>(new List()); + private readonly Bindable> selectedMods = new Bindable>(new List()); public OsuGame(string[] args = null) { @@ -153,6 +153,9 @@ namespace osu.Game dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); + dependencies.CacheAs(selectedMods); + dependencies.CacheAs>>(selectedMods); + // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 4745eba68d..3f28b7ccfd 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -39,9 +39,39 @@ namespace osu.Game.Overlays.Mods protected readonly FillFlowContainer ModSectionsContainer; - public readonly Bindable> SelectedMods = new Bindable>(); + protected readonly Bindable> SelectedMods = new Bindable>(); - public readonly IBindable Ruleset = new Bindable(); + protected readonly IBindable Ruleset = new Bindable(); + + [BackgroundDependencyLoader] + private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) + { + LowMultiplierColour = colours.Red; + HighMultiplierColour = colours.Green; + UnrankedLabel.Colour = colours.Blue; + + Ruleset.BindTo(ruleset); + SelectedMods.BindTo(selectedMods); + + sampleOn = audio.Sample.Get(@"UI/check-on"); + sampleOff = audio.Sample.Get(@"UI/check-off"); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Ruleset.BindValueChanged(rulesetChanged, true); + SelectedMods.BindValueChanged(selectedModsChanged, true); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + Ruleset.UnbindAll(); + SelectedMods.UnbindAll(); + } private void rulesetChanged(RulesetInfo newRuleset) { @@ -51,33 +81,16 @@ namespace osu.Game.Overlays.Mods foreach (ModSection section in ModSectionsContainer.Children) section.Mods = instance.GetModsFor(section.ModType); + + // attempt to re-select any already selected mods. + // this may be the first time we are receiving the ruleset, in which case they will still match. + selectedModsChanged(SelectedMods.Value); + + // write the mods back to the SelectedMods bindable in the case a change was not applicable. + // this generally isn't required as the previous line will perform deselection; just here for safety. refreshSelectedMods(); } - [BackgroundDependencyLoader] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio) - { - SelectedMods.ValueChanged += selectedModsChanged; - - LowMultiplierColour = colours.Red; - HighMultiplierColour = colours.Green; - UnrankedLabel.Colour = colours.Blue; - - Ruleset.BindTo(ruleset); - Ruleset.BindValueChanged(rulesetChanged, true); - - sampleOn = audio.Sample.Get(@"UI/check-on"); - sampleOff = audio.Sample.Get(@"UI/check-off"); - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - Ruleset.UnbindAll(); - SelectedMods.UnbindAll(); - } - private void selectedModsChanged(IEnumerable obj) { foreach (ModSection section in ModSectionsContainer.Children) @@ -176,10 +189,7 @@ namespace osu.Game.Overlays.Mods refreshSelectedMods(); } - private void refreshSelectedMods() - { - SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); - } + private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); public ModSelectOverlay() { diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index a346911ca2..7a832caf41 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -50,13 +50,12 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; - public readonly Bindable> SelectedMods = new Bindable>(new List()); + private readonly Bindable> selectedMods = new Bindable>(new List()); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame osu) + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) { - if (osu != null) SelectedMods.BindTo(osu.SelectedMods); - modSelect.SelectedMods.BindTo(SelectedMods); + if (selectedMods != null) this.selectedMods.BindTo(selectedMods); sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); @@ -84,7 +83,7 @@ namespace osu.Game.Screens.Select protected override void UpdateBeatmap(WorkingBeatmap beatmap) { - beatmap.Mods.BindTo(SelectedMods); + beatmap.Mods.BindTo(selectedMods); base.UpdateBeatmap(beatmap); @@ -131,7 +130,7 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - SelectedMods.UnbindAll(); + selectedMods.UnbindAll(); Beatmap.Value.Mods.Value = new Mod[] { }; return false; @@ -147,10 +146,10 @@ namespace osu.Game.Screens.Select var auto = Ruleset.Value.CreateInstance().GetAutoplayMod(); var autoType = auto.GetType(); - var mods = modSelect.SelectedMods.Value; + var mods = selectedMods.Value; if (mods.All(m => m.GetType() != autoType)) { - modSelect.SelectedMods.Value = mods.Append(auto); + selectedMods.Value = mods.Append(auto); removeAutoModOnResume = true; } } From 4cb7063801e561a4e58494f30befec96d413f6eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Aug 2018 16:45:18 +0900 Subject: [PATCH 114/277] Add automated testing of mod preservation/removal --- osu.Game.Tests/Visual/TestCaseMods.cs | 79 +++++++++++++--------- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 6 +- osu.Game/Screens/Select/PlaySongSelect.cs | 2 +- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index 6330afe860..ab53dbd968 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.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.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Mods; @@ -13,12 +12,11 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using System.Linq; using System.Collections.Generic; +using NUnit.Framework; using osu.Framework.Configuration; -using osu.Game.Rulesets.Osu; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Mods.Sections; -using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.UI; using OpenTK.Graphics; @@ -51,11 +49,6 @@ namespace osu.Game.Tests.Visual private void load(RulesetStore rulesets) { this.rulesets = rulesets; - } - - protected override void LoadComplete() - { - base.LoadComplete(); Add(modSelect = new TestModSelectOverlay { @@ -72,34 +65,25 @@ namespace osu.Game.Tests.Visual Position = new Vector2(0, 25), }); + modDisplay.Current.UnbindBindings(); modDisplay.Current.BindTo(modSelect.SelectedMods); - AddStep("Toggle", modSelect.ToggleVisibility); - AddStep("Hide", modSelect.Hide); AddStep("Show", modSelect.Show); - - foreach (var rulesetInfo in rulesets.AvailableRulesets) - { - Ruleset ruleset = rulesetInfo.CreateInstance(); - AddStep($"switch to {ruleset.Description}", () => Ruleset.Value = rulesetInfo); - - switch (ruleset) - { - case OsuRuleset or: - testOsuMods(or); - break; - case ManiaRuleset mr: - testManiaMods(mr); - break; - } - } + AddStep("Toggle", modSelect.ToggleVisibility); + AddStep("Toggle", modSelect.ToggleVisibility); } - private void testOsuMods(OsuRuleset ruleset) + [Test] + public void TestOsuMods() { - var easierMods = ruleset.GetModsFor(ModType.DifficultyReduction); - var harderMods = ruleset.GetModsFor(ModType.DifficultyIncrease); - var assistMods = ruleset.GetModsFor(ModType.Automation); + var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); + AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + + var instance = ruleset.CreateInstance(); + + var easierMods = instance.GetModsFor(ModType.DifficultyReduction); + var harderMods = instance.GetModsFor(ModType.DifficultyIncrease); + var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); @@ -121,9 +105,40 @@ namespace osu.Game.Tests.Visual testUnimplementedMod(autoPilotMod); } - private void testManiaMods(ManiaRuleset ruleset) + [Test] + public void TestManiaMods() { - testRankedText(ruleset.GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); + var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); + AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + + testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); + } + + [Test] + public void TestRulesetChanges() + { + var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); + var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); + + AddStep("change ruleset to null", () => { Ruleset.Value = null; }); + + var instance = rulesetOsu.CreateInstance(); + var easierMods = instance.GetModsFor(ModType.DifficultyReduction); + var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); + + AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); + + AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + + AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); + + AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; }); + + AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); + + AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + + AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); } private void testSingleMod(Mod mod) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 69d1236126..4d9a12943f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -99,7 +99,7 @@ namespace osu.Game private readonly List overlays = new List(); // todo: move this to SongSelect once Screen has the ability to unsuspend. - private readonly Bindable> selectedMods = new Bindable>(new List()); + private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); public OsuGame(string[] args = null) { diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 3f28b7ccfd..45703ac56d 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -39,11 +39,11 @@ namespace osu.Game.Overlays.Mods protected readonly FillFlowContainer ModSectionsContainer; - protected readonly Bindable> SelectedMods = new Bindable>(); + protected readonly Bindable> SelectedMods = new Bindable>(new Mod[] { }); protected readonly IBindable Ruleset = new Bindable(); - [BackgroundDependencyLoader] + [BackgroundDependencyLoader(true)] private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) { LowMultiplierColour = colours.Red; @@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Mods UnrankedLabel.Colour = colours.Blue; Ruleset.BindTo(ruleset); - SelectedMods.BindTo(selectedMods); + if (selectedMods != null) SelectedMods.BindTo(selectedMods); sampleOn = audio.Sample.Get(@"UI/check-on"); sampleOff = audio.Sample.Get(@"UI/check-off"); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 7a832caf41..210c03f2d9 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; - private readonly Bindable> selectedMods = new Bindable>(new List()); + private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); [BackgroundDependencyLoader(true)] private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) From 6379c70a68ae4369483f64b3cb3275a9b85d48c4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 Aug 2018 11:28:44 +0900 Subject: [PATCH 115/277] Add some ticks --- osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index fdc8f362f7..30318464de 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction) { - var note = new HoldNote { StartTime = 999999999, Duration = 1000 }; + var note = new HoldNote { StartTime = 999999999, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) From 31146fbc014f24630438ff1d5b0d96c3ab592bb5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 Aug 2018 11:28:55 +0900 Subject: [PATCH 116/277] Add anchor/origin tests --- .../TestCaseNotes.cs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs index 30318464de..a8b2b20fda 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseNotes.cs @@ -46,15 +46,20 @@ namespace osu.Game.Rulesets.Mania.Tests Spacing = new Vector2(20), Children = new[] { - createNoteDisplay(ScrollingDirection.Down), - createNoteDisplay(ScrollingDirection.Up), - createHoldNoteDisplay(ScrollingDirection.Down), - createHoldNoteDisplay(ScrollingDirection.Up), + createNoteDisplay(ScrollingDirection.Down, 1, out var note1), + createNoteDisplay(ScrollingDirection.Up, 2, out var note2), + createHoldNoteDisplay(ScrollingDirection.Down, 1, out var holdNote1), + createHoldNoteDisplay(ScrollingDirection.Up, 2, out var holdNote2), } }; + + AddAssert("note 1 facing downwards", () => verifyAnchors(note1, Anchor.y2)); + AddAssert("note 2 facing upwards", () => verifyAnchors(note2, Anchor.y0)); + AddAssert("hold note 1 facing downwards", () => verifyAnchors(holdNote1, Anchor.y2)); + AddAssert("hold note 2 facing upwards", () => verifyAnchors(holdNote2, Anchor.y0)); } - private Drawable createNoteDisplay(ScrollingDirection direction) + private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { var note = new Note { StartTime = 999999999 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -62,14 +67,14 @@ namespace osu.Game.Rulesets.Mania.Tests return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, - Child = new NoteContainer(direction, $"note, scrolling {direction.ToString().ToLowerInvariant()}") + Child = new NoteContainer(direction, $"note {identifier}, scrolling {direction.ToString().ToLowerInvariant()}") { - Child = new DrawableNote(note) { AccentColour = Color4.OrangeRed } + Child = hitObject = new DrawableNote(note) { AccentColour = Color4.OrangeRed } } }; } - private Drawable createHoldNoteDisplay(ScrollingDirection direction) + private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { var note = new HoldNote { StartTime = 999999999, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -77,9 +82,9 @@ namespace osu.Game.Rulesets.Mania.Tests return new ScrollingTestContainer(direction) { AutoSizeAxes = Axes.Both, - Child = new NoteContainer(direction, $"hold note, scrolling {direction.ToString().ToLowerInvariant()}") + Child = new NoteContainer(direction, $"hold note {identifier}, scrolling {direction.ToString().ToLowerInvariant()}") { - Child = new DrawableHoldNote(note) + Child = hitObject = new DrawableHoldNote(note) { RelativeSizeAxes = Axes.Both, AccentColour = Color4.OrangeRed, @@ -88,6 +93,12 @@ namespace osu.Game.Rulesets.Mania.Tests }; } + private bool verifyAnchors(DrawableHitObject hitObject, Anchor expectedAnchor) + => hitObject.Anchor.HasFlag(expectedAnchor) && hitObject.Origin.HasFlag(expectedAnchor); + + private bool verifyAnchors(DrawableHoldNote holdNote, Anchor expectedAnchor) + => verifyAnchors((DrawableHitObject)holdNote, expectedAnchor) && holdNote.NestedHitObjects.All(n => verifyAnchors(n, expectedAnchor)); + private class NoteContainer : Container { private readonly Container content; From dc7804983938cf6e721f4f1823576df8f968036a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Aug 2018 12:21:44 +0900 Subject: [PATCH 117/277] Add test for propagation of direction through mania stack --- .../ScrollingTestContainer.cs | 22 ++++++++----------- .../TestCaseStage.cs | 21 ++++++++++++++++-- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs index 5a93efb0dc..29663c2093 100644 --- a/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs +++ b/osu.Game.Rulesets.Mania.Tests/ScrollingTestContainer.cs @@ -14,24 +14,20 @@ namespace osu.Game.Rulesets.Mania.Tests /// public class ScrollingTestContainer : Container { - private readonly ScrollingDirection direction; + [Cached(Type = typeof(IScrollingInfo))] + private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo(); public ScrollingTestContainer(ScrollingDirection direction) { - this.direction = direction; + scrollingInfo.Direction.Value = direction; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(new ScrollingInfo { Direction = { Value = direction }}); - return dependencies; - } + public void Flip() => scrollingInfo.Direction.Value = scrollingInfo.Direction.Value == ScrollingDirection.Up ? ScrollingDirection.Down : ScrollingDirection.Up; + } - private class ScrollingInfo : IScrollingInfo - { - public readonly Bindable Direction = new Bindable(); - IBindable IScrollingInfo.Direction => Direction; - } + public class TestScrollingInfo : IScrollingInfo + { + public readonly Bindable Direction = new Bindable(); + IBindable IScrollingInfo.Direction => Direction; } } diff --git a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs index b1bb7f5187..5c5d955168 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestCaseStage.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -24,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Tests private readonly List stages = new List(); + private FillFlowContainer fill; + public TestCaseStage() : base(columns) { @@ -32,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Tests [BackgroundDependencyLoader] private void load() { - Child = new FillFlowContainer + Child = fill = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, @@ -54,8 +57,22 @@ namespace osu.Game.Rulesets.Mania.Tests AddStep("hold note", createHoldNote); AddStep("minor bar line", () => createBarLine(false)); AddStep("major bar line", () => createBarLine(true)); + + AddAssert("check note anchors", () => notesInStageAreAnchored(stages[0], Anchor.TopCentre)); + AddAssert("check note anchors", () => notesInStageAreAnchored(stages[1], Anchor.BottomCentre)); + + AddStep("flip direction", () => + { + foreach (var c in fill.Children) + c.Flip(); + }); + + AddAssert("check note anchors", () => notesInStageAreAnchored(stages[0], Anchor.BottomCentre)); + AddAssert("check note anchors", () => notesInStageAreAnchored(stages[1], Anchor.TopCentre)); } + private bool notesInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor); + private void createNote() { foreach (var stage in stages) @@ -101,7 +118,7 @@ namespace osu.Game.Rulesets.Mania.Tests } } - private Drawable createStage(ScrollingDirection direction, ManiaAction action) + private ScrollingTestContainer createStage(ScrollingDirection direction, ManiaAction action) { var specialAction = ManiaAction.Special1; From 4453b5facafe6f41ebf1c1f041b180527ba32df4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Aug 2018 12:26:57 +0900 Subject: [PATCH 118/277] Cache mods at PlaySongSelect --- osu.Game/OsuGame.cs | 2 ++ osu.Game/Screens/Select/PlaySongSelect.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 4d9a12943f..5923037cd9 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -99,6 +99,8 @@ namespace osu.Game private readonly List overlays = new List(); // todo: move this to SongSelect once Screen has the ability to unsuspend. + [Cached] + [Cached(Type = typeof(IBindable>))] private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); public OsuGame(string[] args = null) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 210c03f2d9..e914eb365e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -50,6 +50,8 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; + [Cached] + [Cached(Type = typeof(IBindable>))] private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); [BackgroundDependencyLoader(true)] From bfbe00e6eca12dedfda65c1307788a55b5f3d6d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 Aug 2018 15:38:09 +0900 Subject: [PATCH 119/277] Remove multiple caching --- osu.Game/OsuGame.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 5923037cd9..a1e385921f 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -155,9 +155,6 @@ namespace osu.Game dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); - dependencies.CacheAs(selectedMods); - dependencies.CacheAs>>(selectedMods); - // bind config int to database RulesetInfo configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); From 2a5b9f79ffb81964af128f23a1d6ef4f7660e7e0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 8 Aug 2018 15:49:27 +0900 Subject: [PATCH 120/277] Indent --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 5a73aab23e..322db0b7d6 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -128,7 +128,7 @@ namespace osu.Game.Overlays.Direct content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); content.MoveToY(-4, hover_transition_time, Easing.OutQuint); if (FadePlayButton) - PlayButton.FadeIn(120, Easing.InOutQuint); + PlayButton.FadeIn(120, Easing.InOutQuint); return base.OnHover(state); } From b8824a41b583453e7ac6656b0f7e69028cb761fe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 11:44:53 +0900 Subject: [PATCH 121/277] Fix certain control points not being replaced --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 26f28c86ca..29be751de2 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -354,6 +354,11 @@ namespace osu.Game.Beatmaps.Formats private void handleTimingControlPoint(TimingControlPoint newPoint) { + var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); + + if (existing.Time == newPoint.Time) + beatmap.ControlPointInfo.TimingPoints.Remove(existing); + beatmap.ControlPointInfo.TimingPoints.Add(newPoint); } @@ -364,7 +369,9 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; - beatmap.ControlPointInfo.DifficultyPoints.RemoveAll(x => x.Time == newPoint.Time); + if (existing.Time == newPoint.Time) + beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); + beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); } @@ -375,6 +382,9 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; + if (existing.Time == newPoint.Time) + beatmap.ControlPointInfo.EffectPoints.Remove(existing); + beatmap.ControlPointInfo.EffectPoints.Add(newPoint); } @@ -385,6 +395,9 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; + if (existing.Time == newPoint.Time) + beatmap.ControlPointInfo.SamplePoints.Remove(existing); + beatmap.ControlPointInfo.SamplePoints.Add(newPoint); } From 970aa811bda0dd5399de555c696665e6650ea751 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 13:19:50 +0900 Subject: [PATCH 122/277] Fix mods not being reset prior to ruleset changing --- osu.Game/Screens/Select/SongSelect.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 1bcd65e30b..54143bef8a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -314,13 +314,13 @@ namespace osu.Game.Screens.Select { Logger.Log($"updating selection with beatmap:{beatmap?.ID.ToString() ?? "null"} ruleset:{ruleset?.ID.ToString() ?? "null"}"); - WorkingBeatmap working = Beatmap.Value; - bool preview = false; if (ruleset?.Equals(Ruleset.Value) == false) { Logger.Log($"ruleset changed from \"{Ruleset.Value}\" to \"{ruleset}\""); + + Beatmap.Value.Mods.Value = Enumerable.Empty(); Ruleset.Value = ruleset; // force a filter before attempting to change the beatmap. @@ -340,7 +340,7 @@ namespace osu.Game.Screens.Select Logger.Log($"beatmap changed from \"{Beatmap.Value.BeatmapInfo}\" to \"{beatmap}\""); preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID; - working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); + Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value); if (beatmap != null) { @@ -351,9 +351,6 @@ namespace osu.Game.Screens.Select } } - working.Mods.Value = Enumerable.Empty(); - Beatmap.Value = working; - ensurePlayingSelected(preview); UpdateBeatmap(Beatmap.Value); } From 15bd7e4f1f8e84af63442c24e54c586db5935787 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:18:46 +0900 Subject: [PATCH 123/277] Test that changing ruleset resets mods --- .../Visual/TestCasePlaySongSelect.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index b1ffe04b68..1a74d21f53 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -8,11 +8,15 @@ using System.Linq; using System.Text; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Taiko; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; @@ -29,6 +33,10 @@ namespace osu.Game.Tests.Visual private WorkingBeatmap defaultBeatmap; private DatabaseContextFactory factory; + [Cached] + [Cached(Type = typeof(IBindable>))] + private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); + public override IReadOnlyList RequiredTypes => new[] { typeof(SongSelect), @@ -49,6 +57,8 @@ namespace osu.Game.Tests.Visual private class TestSongSelect : PlaySongSelect { + public new Bindable Ruleset => base.Ruleset; + public WorkingBeatmap CurrentBeatmap => Beatmap.Value; public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap; public new BeatmapCarousel Carousel => base.Carousel; @@ -143,11 +153,42 @@ namespace osu.Game.Tests.Visual AddUntilStep(() => songSelect.Carousel.SelectedBeatmap == null, "no selection"); } + [Test] + public void TestRulesetChangeResetsMods() + { + changeRuleset(0); + + changeMods(new OsuModHardRock()); + + int actionIndex = 0; + int modChangeIndex = 0; + int rulesetChangeIndex = 0; + + AddStep("change ruleset", () => + { + songSelect.CurrentBeatmap.Mods.ValueChanged += onModChange; + songSelect.Ruleset.ValueChanged += onRulesetChange; + + Ruleset.Value = new TaikoRuleset().RulesetInfo; + + songSelect.CurrentBeatmap.Mods.ValueChanged -= onModChange; + songSelect.Ruleset.ValueChanged -= onRulesetChange; + }); + + AddAssert("mods changed before ruleset", () => modChangeIndex < rulesetChangeIndex); + AddAssert("empty mods", () => !selectedMods.Value.Any()); + + void onModChange(IEnumerable mods) => modChangeIndex = actionIndex++; + void onRulesetChange(RulesetInfo ruleset) => rulesetChangeIndex = actionIndex--; + } + private void importForRuleset(int id) => AddStep($"import test map for ruleset {id}", () => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray()))); private static int importId; private int getImportId() => ++importId; + private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.ShortenedName))}", () => selectedMods.Value = mods); + private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); private void addManyTestMaps() From 78258e2fe287e92efca118f122955b237e2d7cc8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:19:26 +0900 Subject: [PATCH 124/277] Prefix some methods with "Test" --- osu.Game.Tests/Visual/TestCasePlaySongSelect.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index 1a74d21f53..888bf6250f 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -131,7 +131,7 @@ namespace osu.Game.Tests.Visual [Test] [Ignore("needs fixing")] - public void ImportUnderDifferentRuleset() + public void TestImportUnderDifferentRuleset() { changeRuleset(2); importForRuleset(0); @@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual } [Test] - public void ImportUnderCurrentRuleset() + public void TestImportUnderCurrentRuleset() { changeRuleset(2); importForRuleset(2); From 7971d06df1840dec0966f29ed8e0b98029d2a9a0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:27:47 +0900 Subject: [PATCH 125/277] Remove AlwaysPresent --- .../Objects/Drawables/DrawableStrongHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs index 45a853b94b..6408b7b369 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables : base(strong) { MainObject = mainObject; - - AlwaysPresent = true; } protected override void UpdateState(ArmedState state) From 732dfde8edb6ed5b4da6931405e08b67ecc704c7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:28:05 +0900 Subject: [PATCH 126/277] DrawableStrongHandler -> DrawableNestedStrongHit --- osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs | 6 +++--- .../Objects/Drawables/DrawableDrumRoll.cs | 6 +++--- .../Objects/Drawables/DrawableDrumRollTick.cs | 6 +++--- osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs | 6 +++--- .../Objects/Drawables/DrawableStrongHandler.cs | 4 ++-- .../Objects/Drawables/DrawableTaikoHitObject.cs | 4 ++-- osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs index b002c2abab..fc103e4c72 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestCaseTaikoPlayfield.cs @@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(h, new JudgementResult(new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new TestStrongHandler(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() @@ -226,9 +226,9 @@ namespace osu.Game.Rulesets.Taiko.Tests rulesetContainer.Playfield.Add(new DrawableRimHit(h)); } - private class TestStrongHandler : DrawableStrongHandler + private class TestStrongNestedHit : DrawableStrongNestedHit { - public TestStrongHandler(DrawableHitObject mainObject) + public TestStrongNestedHit(DrawableHitObject mainObject) : base(null, mainObject) { } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 0fb2405f77..5142f125ac 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -99,11 +99,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongHit(StrongHitObject hitObject) => new StrongNestedHit(hitObject, this); - private class StrongHandler : DrawableStrongHandler + private class StrongNestedHit : DrawableStrongNestedHit { - public StrongHandler(StrongHitObject strong, DrawableDrumRoll drumRoll) + public StrongNestedHit(StrongHitObject strong, DrawableDrumRoll drumRoll) : base(strong, drumRoll) { } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index ff1cce24b6..a70d7bde0e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -51,11 +51,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public override bool OnPressed(TaikoAction action) => UpdateResult(true); - protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongHit(StrongHitObject hitObject) => new StrongNestedHit(hitObject, this); - private class StrongHandler : DrawableStrongHandler + private class StrongNestedHit : DrawableStrongNestedHit { - public StrongHandler(StrongHitObject strong, DrawableDrumRollTick tick) + public StrongNestedHit(StrongHitObject strong, DrawableDrumRollTick tick) : base(strong, tick) { } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 6181b74822..f59dc8c1ee 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -127,9 +127,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables } } - protected override DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => new StrongHandler(hitObject, this); + protected override DrawableStrongNestedHit CreateStrongHit(StrongHitObject hitObject) => new StrongNestedHit(hitObject, this); - private class StrongHandler : DrawableStrongHandler + private class StrongNestedHit : DrawableStrongNestedHit { /// /// The lenience for the second key press. @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public new DrawableHit MainObject => (DrawableHit)base.MainObject; - public StrongHandler(StrongHitObject strong, DrawableHit hit) + public StrongNestedHit(StrongHitObject strong, DrawableHit hit) : base(strong, hit) { } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs index 6408b7b369..b27de3832a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs @@ -9,11 +9,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// Used as a nested hitobject to provide s for s. /// - public abstract class DrawableStrongHandler : DrawableTaikoHitObject + public abstract class DrawableStrongNestedHit : DrawableTaikoHitObject { public readonly DrawableHitObject MainObject; - protected DrawableStrongHandler(StrongHitObject strong, DrawableHitObject mainObject) + protected DrawableStrongNestedHit(StrongHitObject strong, DrawableHitObject mainObject) : base(strong) { MainObject = mainObject; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index 6d19c99b9c..bb63bd58cf 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); if (strongObject != null) { - var vis = CreateStrongHandler(strongObject); + var vis = CreateStrongHit(strongObject); if (vis != null) { AddNested(vis); @@ -127,6 +127,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// The strong hitobject. /// The strong hitobject handler. - protected virtual DrawableStrongHandler CreateStrongHandler(StrongHitObject hitObject) => null; + protected virtual DrawableStrongNestedHit CreateStrongHit(StrongHitObject hitObject) => null; } } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 8973a4ef35..325beb38a5 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -236,7 +236,7 @@ namespace osu.Game.Rulesets.Taiko.UI { case TaikoStrongJudgement _: if (result.IsHit) - hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongHandler)judgedObject).MainObject)?.VisualiseSecondHit(); + hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit(); break; default: judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject) From 1a355063866132f4a63dc478b4c7d1e0471eff02 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:29:49 +0900 Subject: [PATCH 127/277] Cleanup strong hit construction --- .../Objects/Drawables/DrawableTaikoHitObject.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index bb63bd58cf..51e39dc648 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -105,12 +105,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var strongObject = HitObject.NestedHitObjects.OfType().FirstOrDefault(); if (strongObject != null) { - var vis = CreateStrongHit(strongObject); - if (vis != null) - { - AddNested(vis); - AddInternal(vis); - } + var strongHit = CreateStrongHit(strongObject); + + AddNested(strongHit); + AddInternal(strongHit); } } From b045f5c9b6c19816d6b9577a895586567c406215 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 14:32:06 +0900 Subject: [PATCH 128/277] Adjust filename --- .../{DrawableStrongHandler.cs => DrawableStrongNestedHit.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename osu.Game.Rulesets.Taiko/Objects/Drawables/{DrawableStrongHandler.cs => DrawableStrongNestedHit.cs} (100%) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs similarity index 100% rename from osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongHandler.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs From 2019a89a08ff12ca8c2cd822e1ba99d2be9b7f65 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 16:40:17 +0900 Subject: [PATCH 129/277] Softly-handle infinite loops in mania beatmap conversion --- .../Legacy/DistanceObjectPatternGenerator.cs | 37 +++++++++++++++---- .../Legacy/EndTimeObjectPatternGenerator.cs | 4 +- .../Legacy/HitObjectPatternGenerator.cs | 8 ++-- .../Beatmaps/Patterns/PatternGenerator.cs | 20 ++++++++++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 8d0d78120a..010cf962cc 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -176,16 +176,23 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = Random.Next(RandomStart, TotalColumns); for (int i = 0; i < Math.Min(usableColumns, noteCount); i++) { - while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn)) //find available column + // Find available column + RunWhile(() => pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); + addToPattern(pattern, nextColumn, startTime, EndTime); } // This is can't be combined with the above loop due to RNG for (int i = 0; i < noteCount - usableColumns; i++) { - while (pattern.ColumnHasObject(nextColumn)) + RunWhile(() => pattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); + addToPattern(pattern, nextColumn, startTime, EndTime); } @@ -211,16 +218,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { - while (PreviousPattern.ColumnHasObject(nextColumn)) + RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); } int lastColumn = nextColumn; for (int i = 0; i < noteCount; i++) { addToPattern(pattern, nextColumn, startTime, startTime); - while (nextColumn == lastColumn) + + RunWhile(() => nextColumn == lastColumn, () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); lastColumn = nextColumn; startTime += SegmentDuration; @@ -393,14 +405,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { - while (PreviousPattern.ColumnHasObject(nextColumn)) + RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); } for (int i = 0; i < columnRepeat; i++) { - while (pattern.ColumnHasObject(nextColumn)) + RunWhile(() => pattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); addToPattern(pattern, nextColumn, startTime, EndTime); startTime += SegmentDuration; @@ -427,8 +443,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) { - while (PreviousPattern.ColumnHasObject(holdColumn)) + RunWhile(() => PreviousPattern.ColumnHasObject(holdColumn), () => + { holdColumn = Random.Next(RandomStart, TotalColumns); + }); } // Create the hold note @@ -455,8 +473,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { for (int j = 0; j < noteCount; j++) { - while (rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn) + RunWhile(() => rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn, () => + { nextColumn = Random.Next(RandomStart, TotalColumns); + }); + addToPattern(rowPattern, nextColumn, startTime, startTime); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 06b4b8a27e..eae9a0fc3b 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -59,8 +59,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { int nextColumn = Random.Next(start, TotalColumns); - while (PreviousPattern.ColumnHasObject(nextColumn)) + RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(start, TotalColumns); + }); return nextColumn; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 84ebfdb839..930ca26660 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -234,7 +234,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); for (int i = 0; i < noteCount; i++) { - while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking) + RunWhile(() => pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking, () => { if (convertType.HasFlag(PatternType.Gathered)) { @@ -244,7 +244,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } else nextColumn = Random.Next(RandomStart, TotalColumns); - } + }); addToPattern(pattern, nextColumn); } @@ -295,8 +295,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = Random.Next(RandomStart, columnLimit); for (int i = 0; i < noteCount; i++) { - while (pattern.ColumnHasObject(nextColumn)) + RunWhile(() => pattern.ColumnHasObject(nextColumn), () => + { nextColumn = Random.Next(RandomStart, columnLimit); + }); // Add normal note addToPattern(pattern, nextColumn); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index a42d57cdd1..74164d70c1 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -3,6 +3,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.Annotations; +using osu.Framework.Logging; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns @@ -12,6 +15,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// internal abstract class PatternGenerator { + private const int max_rng_iterations = 100; + /// /// The last pattern. /// @@ -42,6 +47,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns TotalColumns = Beatmap.TotalColumns; } + protected void RunWhile([InstantHandle] Func condition, Action action) + { + int iterations = 0; + + while (condition() && iterations++ < max_rng_iterations) + action(); + + if (iterations < max_rng_iterations) + return; + + // Generate + log an error/stacktrace + + Logger.Log($"Allowable time exceeded for hitobject generation:\n{new StackTrace(0)}", level: LogLevel.Error); + } + /// /// Generates the patterns for , each filled with hit objects. /// From f69bc23ab82a231ccd44abb9ae0115fe123bb80d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 17:26:25 +0900 Subject: [PATCH 130/277] Overflow mod select to account for parallax --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 45703ac56d..9dd6cefc34 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -27,6 +27,7 @@ namespace osu.Game.Overlays.Mods { public class ModSelectOverlay : WaveOverlayContainer { + private const float overflow_padding = 50; private const float content_width = 0.8f; protected Color4 LowMultiplierColour, HighMultiplierColour; @@ -199,6 +200,11 @@ namespace osu.Game.Overlays.Mods Waves.FourthWaveColour = OsuColour.FromHex(@"003a4e"); Height = 510; + Padding = new MarginPadding + { + Left = -overflow_padding, + Right = -overflow_padding + }; Children = new Drawable[] { @@ -258,6 +264,11 @@ namespace osu.Game.Overlays.Mods AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, Width = content_width, + Padding = new MarginPadding + { + Left = overflow_padding, + Right = overflow_padding + }, Children = new Drawable[] { new OsuSpriteText @@ -295,7 +306,12 @@ namespace osu.Game.Overlays.Mods Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Vertical = 10 }, + Padding = new MarginPadding + { + Vertical = 10, + Left = overflow_padding, + Right = overflow_padding + }, Child = ModSectionsContainer = new FillFlowContainer { Origin = Anchor.TopCentre, @@ -341,7 +357,9 @@ namespace osu.Game.Overlays.Mods Direction = FillDirection.Horizontal, Padding = new MarginPadding { - Vertical = 15 + Vertical = 15, + Left = overflow_padding, + Right = overflow_padding }, Children = new Drawable[] { From e360985d732ca356017394c6f19de60424fcc2e1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 18:15:09 +0900 Subject: [PATCH 131/277] Replace variables into the entire line --- .../Formats/LegacyStoryboardDecoderTest.cs | 14 ++++++++++++++ osu.Game.Tests/Resources/variable-with-suffix.osb | 5 +++++ .../Beatmaps/Formats/LegacyStoryboardDecoder.cs | 11 +++-------- 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 osu.Game.Tests/Resources/variable-with-suffix.osb diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index 3431be91f9..82adc88c6b 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -86,5 +86,19 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(78993, animation.StartTime); } } + + [Test] + public void TestDecodeVariableWithSuffix() + { + var decoder = new LegacyStoryboardDecoder(); + using (var resStream = Resource.OpenResource("variable-with-suffix.osb")) + using (var stream = new StreamReader(resStream)) + { + var storyboard = decoder.Decode(stream); + + StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3); + Assert.AreEqual(123456, ((StoryboardSprite)background.Elements.Single()).InitialPosition.X); + } + } } } diff --git a/osu.Game.Tests/Resources/variable-with-suffix.osb b/osu.Game.Tests/Resources/variable-with-suffix.osb new file mode 100644 index 0000000000..5c9b46ca98 --- /dev/null +++ b/osu.Game.Tests/Resources/variable-with-suffix.osb @@ -0,0 +1,5 @@ +[Variables] +$var=1234 + +[Events] +Sprite,Background,TopCentre,"img.jpg",$var56,240 diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index b418cbd5ec..a8a62013b1 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -289,15 +289,10 @@ namespace osu.Game.Beatmaps.Formats while (line.IndexOf('$') >= 0) { string origLine = line; - string[] split = line.Split(','); - for (int i = 0; i < split.Length; i++) - { - var item = split[i]; - if (item.StartsWith("$") && variables.ContainsKey(item)) - split[i] = variables[item]; - } - line = string.Join(",", split); + foreach (var v in variables) + line = line.Replace(v.Key, v.Value); + if (line == origLine) break; } From e04b2f4fa9261d0cf84028fe761361641d8cbcea Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 18:31:32 +0900 Subject: [PATCH 132/277] Fix hitobject results not rewinding --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 2abb2eb289..7e3e955740 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -147,17 +147,15 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public void PlaySamples() => Samples?.Play(); - private double lastUpdateTime; - protected override void Update() { base.Update(); - if (Result != null && lastUpdateTime > Time.Current) + if (Result != null && Result.HasResult) { var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - if (Result.TimeOffset + endTime < Time.Current) + if (Result.TimeOffset + endTime > Time.Current) { OnRevertResult?.Invoke(this, Result); @@ -165,8 +163,6 @@ namespace osu.Game.Rulesets.Objects.Drawables State.Value = ArmedState.Idle; } } - - lastUpdateTime = Time.Current; } protected override void UpdateAfterChildren() From 8be5a606bf0c9a4ba5c21f0056b3e161e7efd269 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 Aug 2018 18:33:07 +0900 Subject: [PATCH 133/277] Fix swells possibly being strong hitobjects --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 41972b5d20..acd6d43284 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -168,7 +168,6 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps { StartTime = obj.StartTime, Samples = obj.Samples, - IsStrong = strong, Duration = endTimeData.Duration, RequiredHits = (int)Math.Max(1, endTimeData.Duration / 1000 * hitMultiplier) }; From 7c3556baf8312faee499f8a075dbedfd8095ed41 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 09:12:29 +0900 Subject: [PATCH 134/277] Throw exception when Swell.IsStrong is set --- osu.Game.Rulesets.Taiko/Objects/Swell.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index c3ea71af3f..702bf63bf5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Taiko.Objects @@ -16,6 +17,8 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public int RequiredHits = 10; + public override bool IsStrong { set => throw new NotSupportedException($"{nameof(Swell)} cannot be a strong hitobject."); } + protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 6948c5bcde..9c86b60688 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Objects /// Whether this HitObject is a "strong" type. /// Strong hit objects give more points for hitting the hit object with both keys. /// - public bool IsStrong; + public virtual bool IsStrong { get; set; } protected override void CreateNestedHitObjects() { From aa3f6337a22d2aff4a74d2175a13a70761c4c29c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 09:14:07 +0900 Subject: [PATCH 135/277] Add comment --- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 9dd6cefc34..e83dedaf35 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -27,7 +27,11 @@ namespace osu.Game.Overlays.Mods { public class ModSelectOverlay : WaveOverlayContainer { + /// + /// How much this container should overflow the sides of the screen to account for parallax shifting. + /// private const float overflow_padding = 50; + private const float content_width = 0.8f; protected Color4 LowMultiplierColour, HighMultiplierColour; From 26d4bb5451639c844487d4b62cc8d6d83e5d870a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 09:51:02 +0900 Subject: [PATCH 136/277] xmldoc + reword --- .../Beatmaps/Patterns/PatternGenerator.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 74164d70c1..3434c9f01e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -15,7 +15,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// internal abstract class PatternGenerator { - private const int max_rng_iterations = 100; + /// + /// An arbitrary maximum amount of iterations to perform in . + /// The specific value is not super important - enough such that no false-positives occur. + /// + private const int max_rng_iterations = 20; /// /// The last pattern. @@ -59,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns // Generate + log an error/stacktrace - Logger.Log($"Allowable time exceeded for hitobject generation:\n{new StackTrace(0)}", level: LogLevel.Error); + Logger.Log($"Allowable iterations ({max_rng_iterations}) exceeded:\n{new StackTrace(0)}", level: LogLevel.Error); } /// From ce77473910f4b24cd0d6c608295f96d2fea9f1d9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 10:24:56 +0900 Subject: [PATCH 137/277] Simplify usage of ConvertHitObjectParser --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 12 +++++----- .../Legacy/Catch/ConvertHitObjectParser.cs | 5 ++++ .../Objects/Legacy/ConvertHitObjectParser.cs | 23 ++++++++++++++----- .../Legacy/Mania/ConvertHitObjectParser.cs | 5 ++++ .../Legacy/Osu/ConvertHitObjectParser.cs | 5 ++++ .../Legacy/Taiko/ConvertHitObjectParser.cs | 5 ++++ 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 29be751de2..31a7698f50 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -126,16 +126,16 @@ namespace osu.Game.Beatmaps.Formats switch (beatmap.BeatmapInfo.RulesetID) { case 0: - parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(); + parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 1: - parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser(); + parser = new Rulesets.Objects.Legacy.Taiko.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 2: - parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser(); + parser = new Rulesets.Objects.Legacy.Catch.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; case 3: - parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser(); + parser = new Rulesets.Objects.Legacy.Mania.ConvertHitObjectParser(getOffsetTime(), FormatVersion); break; } @@ -405,9 +405,9 @@ namespace osu.Game.Beatmaps.Formats { // If the ruleset wasn't specified, assume the osu!standard ruleset. if (parser == null) - parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(); + parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); - var obj = parser.Parse(line, getOffsetTime()); + var obj = parser.Parse(line); if (obj != null) { diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index c7451dc978..46be5ff3a5 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -13,6 +13,11 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// public class ConvertHitObjectParser : Legacy.ConvertHitObjectParser { + public ConvertHitObjectParser(double offset, int formatVersion) + : base(offset, formatVersion) + { + } + protected override HitObject CreateHit(Vector2 position, bool newCombo) { return new ConvertHit diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c48060bfa9..4919aaea2b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -19,12 +19,23 @@ namespace osu.Game.Rulesets.Objects.Legacy /// public abstract class ConvertHitObjectParser : HitObjectParser { - public override HitObject Parse(string text) + /// + /// The offset to apply to all time values. + /// + public double Offset; + + /// + /// The beatmap version. + /// + public int FormatVersion = LegacyBeatmapDecoder.LATEST_VERSION; + + protected ConvertHitObjectParser(double offset, int formatVersion) { - return Parse(text, 0); + Offset = offset; + formatVersion = formatVersion; } - public HitObject Parse(string text, double offset) + public override HitObject Parse(string text) { try { @@ -152,7 +163,7 @@ namespace osu.Game.Rulesets.Objects.Legacy } else if (type.HasFlag(ConvertHitObjectType.Spinner)) { - result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + offset); + result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + Offset); if (split.Length > 6) readCustomSampleBanks(split[6], bankInfo); @@ -170,13 +181,13 @@ namespace osu.Game.Rulesets.Objects.Legacy readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); } - result = CreateHold(pos, combo, endTime + offset); + result = CreateHold(pos, combo, endTime + Offset); } if (result == null) throw new InvalidOperationException($@"Unknown hit object type {type}."); - result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + offset; + result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + Offset; result.Samples = convertSoundType(soundType, bankInfo); return result; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 99ba1304e8..e4d4fc4687 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -13,6 +13,11 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania /// public class ConvertHitObjectParser : Legacy.ConvertHitObjectParser { + public ConvertHitObjectParser(double offset, int formatVersion) + : base(offset, formatVersion) + { + } + protected override HitObject CreateHit(Vector2 position, bool newCombo) { return new ConvertHit diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 801e4ea449..ca94234afc 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -14,6 +14,11 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu /// public class ConvertHitObjectParser : Legacy.ConvertHitObjectParser { + public ConvertHitObjectParser(double offset, int formatVersion) + : base(offset, formatVersion) + { + } + protected override HitObject CreateHit(Vector2 position, bool newCombo) { return new ConvertHit diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 03b1a3187a..20a9134dea 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -13,6 +13,11 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko /// public class ConvertHitObjectParser : Legacy.ConvertHitObjectParser { + public ConvertHitObjectParser(double offset, int formatVersion) + : base(offset, formatVersion) + { + } + protected override HitObject CreateHit(Vector2 position, bool newCombo) { return new ConvertHit From d2709613bc355d1158e577e650fdc1a3dec97d24 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 10:48:42 +0900 Subject: [PATCH 138/277] Add combo offset to ConvertHitObjectParser --- .../Legacy/Catch/ConvertHitObjectParser.cs | 8 +++--- .../Objects/Legacy/ConvertHitObjectParser.cs | 26 ++++++++++++------- .../Objects/Legacy/ConvertHitObjectType.cs | 2 +- .../Legacy/Mania/ConvertHitObjectParser.cs | 8 +++--- .../Legacy/Osu/ConvertHitObjectParser.cs | 8 +++--- .../Legacy/Taiko/ConvertHitObjectParser.cs | 8 +++--- 6 files changed, 34 insertions(+), 26 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 46be5ff3a5..35392cd237 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { } - protected override HitObject CreateHit(Vector2 position, bool newCombo) + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { return new ConvertHit { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { return new ConvertSlider { @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSpinner(Vector2 position, double endTime) + protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { return new ConvertSpinner { @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateHold(Vector2 position, bool newCombo, double endTime) + protected override HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime) { return null; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 4919aaea2b..77e5bd0e98 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -43,8 +43,11 @@ namespace osu.Game.Rulesets.Objects.Legacy Vector2 pos = new Vector2((int)Convert.ToSingle(split[0], CultureInfo.InvariantCulture), (int)Convert.ToSingle(split[1], CultureInfo.InvariantCulture)); - ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ColourHax; + ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ComboOffset; + bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); + int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; + type &= ~ConvertHitObjectType.NewCombo; var soundType = (LegacySoundType)int.Parse(split[4]); @@ -54,7 +57,7 @@ namespace osu.Game.Rulesets.Objects.Legacy if (type.HasFlag(ConvertHitObjectType.Circle)) { - result = CreateHit(pos, combo); + result = CreateHit(pos, combo, comboOffset); if (split.Length > 5) readCustomSampleBanks(split[5], bankInfo); @@ -159,11 +162,11 @@ namespace osu.Game.Rulesets.Objects.Legacy for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); - result = CreateSlider(pos, combo, points, length, curveType, repeatCount, nodeSamples); + result = CreateSlider(pos, combo, comboOffset, points, length, curveType, repeatCount, nodeSamples); } else if (type.HasFlag(ConvertHitObjectType.Spinner)) { - result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + Offset); + result = CreateSpinner(new Vector2(512, 384) / 2, combo, comboOffset, Convert.ToDouble(split[5], CultureInfo.InvariantCulture) + Offset); if (split.Length > 6) readCustomSampleBanks(split[6], bankInfo); @@ -181,7 +184,7 @@ namespace osu.Game.Rulesets.Objects.Legacy readCustomSampleBanks(string.Join(":", ss.Skip(1)), bankInfo); } - result = CreateHold(pos, combo, endTime + Offset); + result = CreateHold(pos, combo, comboOffset, endTime + Offset); } if (result == null) @@ -232,37 +235,42 @@ namespace osu.Game.Rulesets.Objects.Legacy /// /// The position of the hit object. /// Whether the hit object creates a new combo. + /// When starting a new combo, the offset of the new combo relative to the current one. /// The hit object. - protected abstract HitObject CreateHit(Vector2 position, bool newCombo); + protected abstract HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset); /// /// Creats a legacy Slider-type hit object. /// /// The position of the hit object. /// Whether the hit object creates a new combo. + /// When starting a new combo, the offset of the new combo relative to the current one. /// The slider control points. /// The slider length. /// The slider curve type. /// The slider repeat count. /// The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider. /// The hit object. - protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples); + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples); /// /// Creates a legacy Spinner-type hit object. /// /// The position of the hit object. + /// Whether the hit object creates a new combo. + /// When starting a new combo, the offset of the new combo relative to the current one. /// The spinner end time. /// The hit object. - protected abstract HitObject CreateSpinner(Vector2 position, double endTime); + protected abstract HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime); /// /// Creates a legacy Hold-type hit object. /// /// The position of the hit object. /// Whether the hit object creates a new combo. + /// When starting a new combo, the offset of the new combo relative to the current one. /// The hold end time. - protected abstract HitObject CreateHold(Vector2 position, bool newCombo, double endTime); + protected abstract HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime); private List convertSoundType(LegacySoundType type, SampleBankInfo bankInfo) { diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs index c0626c3e56..fa47e56de7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Objects.Legacy Slider = 1 << 1, NewCombo = 1 << 2, Spinner = 1 << 3, - ColourHax = 112, + ComboOffset = 1 << 4 | 1 << 5 | 1 << 6, Hold = 1 << 7 } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index e4d4fc4687..ab6cfa3061 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania { } - protected override HitObject CreateHit(Vector2 position, bool newCombo) + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { return new ConvertHit { @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { return new ConvertSlider { @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSpinner(Vector2 position, double endTime) + protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { return new ConvertSpinner { @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateHold(Vector2 position, bool newCombo, double endTime) + protected override HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime) { return new ConvertHold { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index ca94234afc..7ef9865a96 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { } - protected override HitObject CreateHit(Vector2 position, bool newCombo) + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { return new ConvertHit { @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { return new ConvertSlider { @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSpinner(Vector2 position, double endTime) + protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { return new ConvertSpinner { @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateHold(Vector2 position, bool newCombo, double endTime) + protected override HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime) { return null; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 20a9134dea..483e890392 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko { } - protected override HitObject CreateHit(Vector2 position, bool newCombo) + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { return new ConvertHit { @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { return new ConvertSlider { @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko }; } - protected override HitObject CreateSpinner(Vector2 position, double endTime) + protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { return new ConvertSpinner { @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko }; } - protected override HitObject CreateHold(Vector2 position, bool newCombo, double endTime) + protected override HitObject CreateHold(Vector2 position, bool newCombo, int comboOffset, double endTime) { return null; } From 8faf12579a0b6ec9ff54b1dcb5204c6a3be2c770 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 10:53:25 +0900 Subject: [PATCH 139/277] Fix field not being set correctly --- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 77e5bd0e98..720ba5bbab 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -27,12 +27,12 @@ namespace osu.Game.Rulesets.Objects.Legacy /// /// The beatmap version. /// - public int FormatVersion = LegacyBeatmapDecoder.LATEST_VERSION; + public int FormatVersion; protected ConvertHitObjectParser(double offset, int formatVersion) { Offset = offset; - formatVersion = formatVersion; + FormatVersion = formatVersion; } public override HitObject Parse(string text) From 83f75ac8966c794329bf396474687653f1cd9a69 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 10:57:11 +0900 Subject: [PATCH 140/277] Mania convert hitobjects should not have combo --- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs | 4 +--- .../Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs | 4 +--- osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index ea4e7f6907..cbc8d2d4df 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -8,12 +8,10 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania /// /// Legacy osu!mania Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject, IHasXPosition, IHasCombo + internal sealed class ConvertHit : HitObject, IHasXPosition { public float X { get; set; } - public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index ab6cfa3061..6f59965e18 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -22,8 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania { return new ConvertHit { - X = position.X, - NewCombo = newCombo, + X = position.X }; } @@ -32,7 +31,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania return new ConvertSlider { X = position.X, - NewCombo = newCombo, ControlPoints = controlPoints, Distance = length, CurveType = curveType, diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index a8d7b23df1..e1572889a3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -8,12 +8,10 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania /// /// Legacy osu!mania Slider-type, used for parsing Beatmaps. /// - internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition, IHasCombo + internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition { public float X { get; set; } - public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => null; } } From 4f0305ffeb17abfee12c32f2a7465cefa73e34dc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 10:58:59 +0900 Subject: [PATCH 141/277] Taiko convert hitobjects should not have combo --- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs | 6 +----- .../Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 6 +----- osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs | 6 +----- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 5e9786c84a..66e504bf22 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,17 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Objects.Types; - namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// /// Legacy osu!taiko Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject, IHasCombo + internal sealed class ConvertHit : HitObject { - public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 483e890392..e5904825c2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -20,17 +20,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { - return new ConvertHit - { - NewCombo = newCombo, - }; + return new ConvertHit(); } protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { return new ConvertSlider { - NewCombo = newCombo, ControlPoints = controlPoints, Distance = length, CurveType = curveType, diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index 8a9a0db0a7..11c0a2baae 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,17 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Rulesets.Objects.Types; - namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// /// Legacy osu!taiko Slider-type, used for parsing Beatmaps. /// - internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasCombo + internal sealed class ConvertSlider : Legacy.ConvertSlider { - public bool NewCombo { get; set; } - protected override HitWindows CreateHitWindows() => null; } } From da3e2cfee2a1684559ed3c5d66986c6b35cb2b6b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 11:04:31 +0900 Subject: [PATCH 142/277] Catch/osu! spinners should have combo --- osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs | 5 ++++- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 5 +++-- osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs | 4 +++- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 68a8dfb7d3..15d4edc411 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -41,6 +41,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps RepeatCount = curveData.RepeatCount, X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH, NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset ?? 0 }; } @@ -51,7 +52,8 @@ namespace osu.Game.Rulesets.Catch.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, Duration = endTime.Duration, - NewCombo = comboData?.NewCombo ?? false + NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, }; } else @@ -61,6 +63,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps StartTime = obj.StartTime, Samples = obj.Samples, NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, X = (positionData?.X ?? 0) / CatchPlayfield.BASE_WIDTH }; } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 405493cde4..52ca7b7759 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -52,7 +52,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, EndTime = endTimeData.EndTime, - Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2 + Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2, + NewCombo = comboData?.NewCombo ?? false, }; } else @@ -62,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps StartTime = original.StartTime, Samples = original.Samples, Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false + NewCombo = comboData?.NewCombo ?? false, }; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 9dfe12f25e..9a160db799 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -8,10 +8,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime + internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasCombo { public double EndTime { get; set; } public double Duration => EndTime - StartTime; + + public bool NewCombo { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 0141785f31..f529c16306 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu /// /// Legacy osu! Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasPosition + internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasPosition, IHasCombo { public double EndTime { get; set; } @@ -22,5 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; protected override HitWindows CreateHitWindows() => null; + + public bool NewCombo { get; set; } } } From 31f324945eea7292093c876270e33810dd4748c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 11:47:31 +0900 Subject: [PATCH 143/277] Implement combo offsets --- osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 2 ++ osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs | 3 +++ osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 2 ++ osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs | 2 ++ .../Objects/Legacy/Catch/ConvertHitObjectParser.cs | 5 ++++- .../Rulesets/Objects/Legacy/Catch/ConvertSlider.cs | 2 ++ .../Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs | 2 ++ .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 11 ++++++----- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 2 ++ .../Objects/Legacy/Osu/ConvertHitObjectParser.cs | 5 ++++- osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs | 2 ++ .../Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs | 2 ++ osu.Game/Rulesets/Objects/Types/IHasCombo.cs | 5 +++++ 13 files changed, 38 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index d55cdac115..621fc100c2 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects public virtual bool NewCombo { get; set; } + public int ComboOffset { get; set; } + public int IndexInCurrentCombo { get; set; } public int ComboIndex { get; set; } diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 52ca7b7759..93f3f06dc2 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -42,6 +42,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps RepeatCount = curveData.RepeatCount, Position = positionData?.Position ?? Vector2.Zero, NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, LegacyLastTickOffset = legacyOffset?.LegacyLastTickOffset }; } @@ -54,6 +55,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps EndTime = endTimeData.EndTime, Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2, NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, }; } else @@ -64,6 +66,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps Samples = original.Samples, Position = positionData?.Position ?? Vector2.Zero, NewCombo = comboData?.NewCombo ?? false, + ComboOffset = comboData?.ComboOffset ?? 0, }; } } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index 48a6365c00..fdf5aaffa8 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -54,6 +54,8 @@ namespace osu.Game.Rulesets.Osu.Objects public virtual bool NewCombo { get; set; } + public int ComboOffset { get; set; } + public virtual int IndexInCurrentCombo { get; set; } public virtual int ComboIndex { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index 50035ea116..0573a08361 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch public float X { get; set; } public bool NewCombo { get; set; } + + public int ComboOffset { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 35392cd237..ac97037d55 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { X = position.X, NewCombo = newCombo, + ComboOffset = comboOffset }; } @@ -33,6 +34,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { X = position.X, NewCombo = newCombo, + ComboOffset = comboOffset, ControlPoints = controlPoints, Distance = length, CurveType = curveType, @@ -45,7 +47,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { return new ConvertSpinner { - EndTime = endTime + EndTime = endTime, + ComboOffset = comboOffset }; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs index 73e277a125..a187caaa26 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs @@ -13,5 +13,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch public float X { get; set; } public bool NewCombo { get; set; } + + public int ComboOffset { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 9a160db799..db79ca60f1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -15,5 +15,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch public double Duration => EndTime - StartTime; public bool NewCombo { get; set; } + + public int ComboOffset { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 720ba5bbab..f9ca0545a1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -22,12 +22,12 @@ namespace osu.Game.Rulesets.Objects.Legacy /// /// The offset to apply to all time values. /// - public double Offset; + protected readonly double Offset; /// /// The beatmap version. /// - public int FormatVersion; + protected readonly int FormatVersion; protected ConvertHitObjectParser(double offset, int formatVersion) { @@ -43,11 +43,12 @@ namespace osu.Game.Rulesets.Objects.Legacy Vector2 pos = new Vector2((int)Convert.ToSingle(split[0], CultureInfo.InvariantCulture), (int)Convert.ToSingle(split[1], CultureInfo.InvariantCulture)); - ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]) & ~ConvertHitObjectType.ComboOffset; + ConvertHitObjectType type = (ConvertHitObjectType)int.Parse(split[3]); + + int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; + type &= ~ConvertHitObjectType.ComboOffset; bool combo = type.HasFlag(ConvertHitObjectType.NewCombo); - int comboOffset = (int)(type & ConvertHitObjectType.ComboOffset) >> 4; - type &= ~ConvertHitObjectType.NewCombo; var soundType = (LegacySoundType)int.Parse(split[4]); diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index f015272b2c..0062e83a28 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } + public int ComboOffset { get; set; } + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 7ef9865a96..9b0554c395 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { Position = position, NewCombo = newCombo, + ComboOffset = comboOffset }; } @@ -34,6 +35,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { Position = position, NewCombo = newCombo, + ComboOffset = comboOffset, ControlPoints = controlPoints, Distance = Math.Max(0, length), CurveType = curveType, @@ -47,7 +49,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu return new ConvertSpinner { Position = position, - EndTime = endTime + EndTime = endTime, + ComboOffset = comboOffset }; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index ec5a002bbb..45f7bc9e67 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -19,6 +19,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } + public int ComboOffset { get; set; } + protected override HitWindows CreateHitWindows() => null; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index f529c16306..3b349d9704 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -24,5 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitWindows CreateHitWindows() => null; public bool NewCombo { get; set; } + + public int ComboOffset { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs index cb8b6f495a..95f1a1cb3d 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs @@ -12,5 +12,10 @@ namespace osu.Game.Rulesets.Objects.Types /// Whether the HitObject starts a new combo. /// bool NewCombo { get; } + + /// + /// When starting a new combo, the offset of the new combo relative to the current one. + /// + int ComboOffset { get; } } } From 4c3e551295e12ef626ba2ec4be8205f4eecbd045 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 11:47:54 +0900 Subject: [PATCH 144/277] Fix first object not receiving new combo Note: If a normal catch fruit is the first object, it does not receive a new combo... --- .../Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs | 3 ++- osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 4 ++++ .../Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index ac97037d55..fb4cde479b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch return new ConvertSlider { X = position.X, - NewCombo = newCombo, + NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, ControlPoints = controlPoints, Distance = length, @@ -48,6 +48,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch return new ConvertSpinner { EndTime = endTime, + NewCombo = FirstObject || newCombo, ComboOffset = comboOffset }; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index f9ca0545a1..8236333a3f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -29,6 +29,8 @@ namespace osu.Game.Rulesets.Objects.Legacy /// protected readonly int FormatVersion; + protected bool FirstObject { get; private set; } = true; + protected ConvertHitObjectParser(double offset, int formatVersion) { Offset = offset; @@ -194,6 +196,8 @@ namespace osu.Game.Rulesets.Objects.Legacy result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + Offset; result.Samples = convertSoundType(soundType, bankInfo); + FirstObject = false; + return result; } catch (FormatException) diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 9b0554c395..0823653830 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu return new ConvertHit { Position = position, - NewCombo = newCombo, + NewCombo = FirstObject || newCombo, ComboOffset = comboOffset }; } @@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu return new ConvertSlider { Position = position, - NewCombo = newCombo, + NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, ControlPoints = controlPoints, Distance = Math.Max(0, length), @@ -50,6 +50,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { Position = position, EndTime = endTime, + NewCombo = FormatVersion <= 8 || FirstObject || newCombo, ComboOffset = comboOffset }; } From 539dd3134f383bf5eb0bcf7588819ab5fafc883d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 11:48:50 +0900 Subject: [PATCH 145/277] Fix beatmap processor not setting combo index on first object --- osu.Game/Beatmaps/BeatmapProcessor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 0173125e8b..9d7cd673dc 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -27,11 +27,10 @@ namespace osu.Game.Beatmaps if (obj.NewCombo) { obj.IndexInCurrentCombo = 0; + obj.ComboIndex = (lastObj?.ComboIndex ?? 0) + obj.ComboOffset + 1; + if (lastObj != null) - { lastObj.LastInCombo = true; - obj.ComboIndex = lastObj.ComboIndex + 1; - } } else if (lastObj != null) { From 05b5144dac62bcb78f526dffb9504eceda95005c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 13:36:22 +0900 Subject: [PATCH 146/277] Add parsing test --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 12 ++++++++++++ osu.Game.Tests/Resources/hitobject-combo-offset.osu | 4 ++++ 2 files changed, 16 insertions(+) create mode 100644 osu.Game.Tests/Resources/hitobject-combo-offset.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 400380b407..0a5df0e093 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -186,6 +186,18 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeBeatmapComboOffsets() + { + var decoder = new LegacyBeatmapDecoder(); + using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) + using (var stream = new StreamReader(resStream)) + { + var beatmap = decoder.Decode(stream); + Assert.AreEqual(3, ((IHasCombo)beatmap.HitObjects[0]).ComboOffset); + } + } + [Test] public void TestDecodeBeatmapHitObjects() { diff --git a/osu.Game.Tests/Resources/hitobject-combo-offset.osu b/osu.Game.Tests/Resources/hitobject-combo-offset.osu new file mode 100644 index 0000000000..4a44d31e22 --- /dev/null +++ b/osu.Game.Tests/Resources/hitobject-combo-offset.osu @@ -0,0 +1,4 @@ +osu file format v14 + +[HitObjects] +255,193,2170,49,0,0:0:0:0: \ No newline at end of file From 4dfb63023fecb6ee694d4a0972acb1957c5d0809 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 15:49:48 +0900 Subject: [PATCH 147/277] Update with recent changes --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0ff6c3d98c..1c28b533d2 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -329,7 +329,7 @@ namespace osu.Game.Beatmaps return; } - await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(stable.GetUsablePathFor).ToArray()), TaskCreationOptions.LongRunning); + await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); } /// diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e9fc51ee9b..804d6587e8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 767c284793884011e511266083660bdc588146b1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 15:49:55 +0900 Subject: [PATCH 148/277] Fix import not working --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 0465c0ad73..c00df59e3e 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -412,7 +412,7 @@ namespace osu.Game.Database private ArchiveReader getReaderFrom(string path) { if (ZipUtils.IsZipArchive(path)) - return new ZipArchiveReader(Files.Storage.GetStream(path), Path.GetFileName(path)); + return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)); if (Directory.Exists(path)) return new LegacyFilesystemReader(path); throw new InvalidFormatException($"{path} is not a valid archive"); From add78508e09efc3a34224f26b68d84e75466269b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 15:54:26 +0900 Subject: [PATCH 149/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 804d6587e8..eef586fd4c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From fe99aab0f20b7a6987bcdd9a9ea3f591c5c81e3f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 16:45:33 +0900 Subject: [PATCH 150/277] Remove highly unnecessary testcase --- .../TestCaseEditorSetupCircularButton.cs | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs diff --git a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs b/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs deleted file mode 100644 index c6037b706b..0000000000 --- a/osu.Game.Tests/Visual/TestCaseEditorSetupCircularButton.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; -using osu.Framework.Allocation; -using osu.Framework.Graphics.Containers; -using osu.Game.Screens.Edit.Screens.Setup.Components; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - public class TestCaseEditorSetupCircularButton : OsuTestCase - { - [BackgroundDependencyLoader] - private void load() - { - Child = new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new[] - { - new SetupCircularButton { Text = "Default" }, - new SetupCircularButton - { - Width = 200, - Text = "Wide", - }, - new SetupCircularButton - { - Height = 100, - Text = "High" - }, - new SetupCircularButton - { - Size = new Vector2(200, 100), - Text = "Wide 'n' High" - } - } - }; - } - } -} From 85dc42d47a9e4085eb51aed85f77fe4bd69b8ae1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 15 Aug 2018 16:47:20 +0900 Subject: [PATCH 151/277] Re-namespace/rename CircularButton --- .../CircularButton.cs} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename osu.Game/Screens/Edit/{Screens/Setup/Components/SetupCircularButton.cs => Components/CircularButton.cs} (78%) diff --git a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs b/osu.Game/Screens/Edit/Components/CircularButton.cs similarity index 78% rename from osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs rename to osu.Game/Screens/Edit/Components/CircularButton.cs index d46fb2f269..a8ad242772 100644 --- a/osu.Game/Screens/Edit/Screens/Setup/Components/SetupCircularButton.cs +++ b/osu.Game/Screens/Edit/Components/CircularButton.cs @@ -1,17 +1,17 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using osu.Game.Graphics.UserInterface; +using OpenTK; -namespace osu.Game.Screens.Edit.Screens.Setup.Components +namespace osu.Game.Screens.Edit.Components { - public class SetupCircularButton : OsuButton + public class CircularButton : OsuButton { private const float width = 125; private const float height = 30; - public SetupCircularButton() + public CircularButton() { Size = new Vector2(width, height); } From ed2a642666111e05f3af952198832cc64449d315 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 09:59:03 +0900 Subject: [PATCH 152/277] Fix info wedge test case failing randomly --- .../Visual/TestCaseBeatmapInfoWedge.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index b232180eba..175db7d246 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using JetBrains.Annotations; using NUnit.Framework; using OpenTK; using osu.Framework.Allocation; @@ -116,7 +117,7 @@ namespace osu.Game.Tests.Visual private void testNullBeatmap() { - selectNullBeatmap(); + selectBeatmap(null); AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Text)); AddAssert("check default title", () => infoWedge.Info.TitleLabel.Text == Beatmap.Default.BeatmapInfo.Metadata.Title); AddAssert("check default artist", () => infoWedge.Info.ArtistLabel.Text == Beatmap.Default.BeatmapInfo.Metadata.Artist); @@ -124,28 +125,19 @@ namespace osu.Game.Tests.Visual AddAssert("check no info labels", () => !infoWedge.Info.InfoLabelContainer.Children.Any()); } - private void selectBeatmap(IBeatmap b) + private void selectBeatmap([CanBeNull] IBeatmap b) { BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null; - AddStep($"select {b.Metadata.Title} beatmap", () => + AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () => { infoBefore = infoWedge.Info; - infoWedge.Beatmap = Beatmap.Value = new TestWorkingBeatmap(b); + infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : new TestWorkingBeatmap(b); }); AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load"); } - private void selectNullBeatmap() - { - AddStep("select null beatmap", () => - { - Beatmap.Value = Beatmap.Default; - infoWedge.Beatmap = Beatmap; - }); - } - private IBeatmap createTestBeatmap(RulesetInfo ruleset) { List objects = new List(); From 74a79bfcfa816f089a5423682a180fb3310db967 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 16 Aug 2018 10:45:06 +0900 Subject: [PATCH 153/277] Fix hold note head/tails not being nested hitobjects --- osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index e493956d6e..77562bb4c2 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -70,9 +70,6 @@ namespace osu.Game.Rulesets.Mania.Objects TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime); tickSpacing = timingPoint.BeatLength / difficulty.SliderTickRate; - - Head.ApplyDefaults(controlPointInfo, difficulty); - Tail.ApplyDefaults(controlPointInfo, difficulty); } protected override void CreateNestedHitObjects() @@ -80,6 +77,9 @@ namespace osu.Game.Rulesets.Mania.Objects base.CreateNestedHitObjects(); createTicks(); + + AddNested(Head); + AddNested(Tail); } private void createTicks() From b26c8e3b9e85c09c908332c52704aa552a2170e3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 14:02:49 +0900 Subject: [PATCH 154/277] Fix notifiation stack trace output on mania conversion failure --- .../Beatmaps/Patterns/PatternGenerator.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 3434c9f01e..1f416f921e 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -55,15 +55,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns { int iterations = 0; - while (condition() && iterations++ < max_rng_iterations) + while (condition()) + { + if (iterations++ >= max_rng_iterations) + { + // log an error but don't throw. we want to continue execution. + Logger.Error(new ExceededAllowedIterationsException(new StackTrace(0)), + "Conversion encountered errors. The beatmap may not be correctly converted."); + return; + } + action(); - - if (iterations < max_rng_iterations) - return; - - // Generate + log an error/stacktrace - - Logger.Log($"Allowable iterations ({max_rng_iterations}) exceeded:\n{new StackTrace(0)}", level: LogLevel.Error); + } } /// @@ -71,5 +74,20 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// The s containing the hit objects. public abstract IEnumerable Generate(); + + /// + /// Denotes when a single conversion operation is in an infinitely looping state. + /// + public class ExceededAllowedIterationsException : Exception + { + private readonly string stackTrace; + + public ExceededAllowedIterationsException(StackTrace stackTrace) + { + this.stackTrace = stackTrace.ToString(); + } + + public override string StackTrace => stackTrace; + } } } From 562a31713e04f23f23d1596bf74b09dad658c16b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 16:44:04 +0900 Subject: [PATCH 155/277] Fix regression in handling logic --- osu.Desktop/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 4574fb6fc9..19ceade644 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -65,7 +65,7 @@ namespace osu.Desktop Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed" : "denied")} with {allowableExceptions} more allowable exceptions."); Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); - return Interlocked.Decrement(ref allowableExceptions) >= 0; + return continueExecution; } } } From 9f55afe5692a91368df55f37e279630ceb5b78b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 16:44:12 +0900 Subject: [PATCH 156/277] Let user know automatic reporting happened --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 189a51dec9..6576529326 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -463,7 +463,7 @@ namespace osu.Game Schedule(() => notifications.Post(new SimpleNotification { Icon = entry.Level == LogLevel.Important ? FontAwesome.fa_exclamation_circle : FontAwesome.fa_bomb, - Text = entry.Message, + Text = entry.Message + (entry.Exception != null ? "\n\nThis error has been automatically reported to the devs." : string.Empty), })); } else if (recentLogCount == short_term_display_limit) From 6297ad95aa49c133c860f59d7c6cbeabbc9ad1eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 16:44:18 +0900 Subject: [PATCH 157/277] Remove test exception --- osu.Game/Screens/Select/PlaySongSelect.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index e83097637d..e914eb365e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -143,8 +142,6 @@ namespace osu.Game.Screens.Select { if (player != null) return false; - throw new Exception("this is a test!"); - // Ctrl+Enter should start map with autoplay enabled. if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true) { From 870f6bea47cb9f563ffe8d7424c7cd864de6e0d6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 18:18:08 +0900 Subject: [PATCH 158/277] Only process alive objects --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index f0e7891a96..744b313f70 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Mods const float relax_leniency = 3; - foreach (var drawable in playfield.HitObjects.Objects) + foreach (var drawable in playfield.HitObjects.AliveObjects) { if (!(drawable is DrawableOsuHitObject osuHit)) continue; From bc22a28fef7c1e773ba7b681559545ace37cdb7b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 18:18:15 +0900 Subject: [PATCH 159/277] Clean up logic and variables --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 44 ++++++++++++++--------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 744b313f70..4e0c12f619 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -7,13 +7,14 @@ using System.Linq; using osu.Framework.Input.States; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.UI; using static osu.Game.Input.Handlers.ReplayInputHandler; namespace osu.Game.Rulesets.Osu.Mods { - public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield + public class OsuModRelax : ModRelax, IApplicableFailOverride, IUpdatableByPlayfield, IApplicableToRulesetContainer { public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things."; public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); @@ -22,8 +23,8 @@ namespace osu.Game.Rulesets.Osu.Mods public void Update(Playfield playfield) { - bool hitStill = false; - bool hitOnce = false; + bool requiresHold = false; + bool requiresHit = false; const float relax_leniency = 3; @@ -35,45 +36,54 @@ namespace osu.Game.Rulesets.Osu.Mods double time = osuHit.Clock.CurrentTime; double relativetime = time - osuHit.HitObject.StartTime; - if (osuHit.IsAlive && time >= osuHit.HitObject.StartTime - relax_leniency) - { - if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) - continue; + if (time < osuHit.HitObject.StartTime - relax_leniency) continue; - hitStill |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; + if (osuHit.HitObject is IHasEndTime hasEnd && time > hasEnd.EndTime || osuHit.IsHit) + continue; - hitOnce |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); - } + requiresHit |= osuHit is DrawableHitCircle && osuHit.IsHovered && osuHit.HitObject.HitWindows.CanBeHit(relativetime); + requiresHold |= osuHit is DrawableSlider slider && (slider.Ball.IsHovered || osuHit.IsHovered) || osuHit is DrawableSpinner; } - var osuHitSample = playfield.HitObjects.Objects.First(d => d is DrawableOsuHitObject) as DrawableOsuHitObject; - if (hitOnce) + if (requiresHit) { - hit(osuHitSample, false); - hit(osuHitSample, true); + addAction(false); + addAction(true); } - hit(osuHitSample, hitStill); + + addAction(requiresHold); } private bool wasHit; private bool wasLeft; - private void hit(DrawableOsuHitObject osuHit, bool hitting) + private OsuInputManager osuInputManager; + + private void addAction(bool hitting) { if (wasHit == hitting) return; + wasHit = hitting; var state = new ReplayState { PressedActions = new List() }; + if (hitting) { state.PressedActions.Add(wasLeft ? OsuAction.LeftButton : OsuAction.RightButton); wasLeft = !wasLeft; } - osuHit.OsuActionInputManager.HandleCustomInput(new InputState(), state); + + osuInputManager.HandleCustomInput(new InputState(), state); + } + + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + { + // grab the input manager for future use. + osuInputManager = (OsuInputManager)rulesetContainer.KeyBindingInputManager; } } } From dfecb3235b7d3d0bbf0d694f1528071aa87e61b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 20:41:53 +0900 Subject: [PATCH 160/277] Fix custom exception stack trace output --- osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 1f416f921e..1eb0cdae2f 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -88,6 +88,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns } public override string StackTrace => stackTrace; + public override string ToString() => $"{GetType().Name}: {Message}\r\n{StackTrace}"; } } } From 12b81df2f39855a916b6ce9d151724361e175872 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 Aug 2018 22:01:04 +0900 Subject: [PATCH 161/277] Fix unhandled exception on startup when arguments are present --- osu.Game/OsuGame.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6576529326..ecf5500ca4 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -151,9 +151,9 @@ namespace osu.Game if (args?.Length > 0) { - var paths = args.Where(a => !a.StartsWith(@"-")); - - Task.Run(() => Import(paths.ToArray())); + var paths = args.Where(a => !a.StartsWith(@"-")).ToArray(); + if (paths.Length > 0) + Task.Run(() => Import(paths)); } dependencies.CacheAs(this); From 9f5a6457f26be725988c1e29d9641a24d7c69b07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 09:08:58 +0900 Subject: [PATCH 162/277] Don't forward errors to sentry for local builds --- osu.Game/Utils/RavenLogger.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index aadb70add8..761bd51672 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -23,6 +23,8 @@ namespace osu.Game.Utils { raven.Release = game.Version; + if (!game.IsDeployedBuild) return; + Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; From eb6f1ae72cda9baa2dc4b903724932a511163743 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 09:16:28 +0900 Subject: [PATCH 163/277] Fix spinners providing one extra combo --- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 -- .../Legacy/Catch/ConvertHitObjectParser.cs | 22 ++++++++++++++++--- .../Legacy/Osu/ConvertHitObjectParser.cs | 22 ++++++++++++++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index e1a7a7c6df..1c60fd4831 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Objects /// public int SpinsRequired { get; protected set; } = 1; - public override bool NewCombo => true; - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index fb4cde479b..cb44fb1c8c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -18,8 +18,17 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { } + private bool forceNewCombo; + private int extraComboOffset; + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertHit { X = position.X, @@ -30,6 +39,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertSlider { X = position.X, @@ -45,11 +60,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + forceNewCombo |= FormatVersion <= 8 || newCombo; + extraComboOffset += comboOffset; + return new ConvertSpinner { - EndTime = endTime, - NewCombo = FirstObject || newCombo, - ComboOffset = comboOffset + EndTime = endTime }; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 0823653830..497d85f849 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -19,8 +19,17 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { } + private bool forceNewCombo; + private int extraComboOffset; + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertHit { Position = position, @@ -31,6 +40,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertSlider { Position = position, @@ -46,12 +61,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + forceNewCombo |= FormatVersion <= 8 || newCombo; + extraComboOffset += comboOffset; + return new ConvertSpinner { Position = position, - EndTime = endTime, - NewCombo = FormatVersion <= 8 || FirstObject || newCombo, - ComboOffset = comboOffset + EndTime = endTime }; } From 557a2ee39d42937b5f0501ae147a86da66e45dc3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 10:04:00 +0900 Subject: [PATCH 164/277] Add more comprehensive tests --- .../Beatmaps/OsuBeatmapConverter.cs | 2 +- .../Beatmaps/OsuBeatmapProcessor.cs | 2 +- .../Formats/LegacyBeatmapDecoderTest.cs | 38 ++++++++++++++++++- .../Resources/hitobject-combo-offset.osu | 30 ++++++++++++++- 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 93f3f06dc2..9e0e649eb2 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapConverter : BeatmapConverter + public class OsuBeatmapConverter : BeatmapConverter { public OsuBeatmapConverter(IBeatmap beatmap) : base(beatmap) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index bbe2d67baa..5fe2457645 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapProcessor : BeatmapProcessor + public class OsuBeatmapProcessor : BeatmapProcessor { public OsuBeatmapProcessor(IBeatmap beatmap) : base(beatmap) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 0a5df0e093..d3351f86f8 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -11,7 +11,9 @@ using osu.Game.Audio; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Skinning; namespace osu.Game.Tests.Beatmaps.Formats @@ -187,14 +189,46 @@ namespace osu.Game.Tests.Beatmaps.Formats } [Test] - public void TestDecodeBeatmapComboOffsets() + public void TestDecodeBeatmapComboOffsetsOsu() { var decoder = new LegacyBeatmapDecoder(); using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); - Assert.AreEqual(3, ((IHasCombo)beatmap.HitObjects[0]).ComboOffset); + + var converted = new OsuBeatmapConverter(beatmap).Convert(); + new OsuBeatmapProcessor(converted).PreProcess(); + new OsuBeatmapProcessor(converted).PostProcess(); + + Assert.AreEqual(4, ((IHasComboInformation)converted.HitObjects.ElementAt(0)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(2)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(4)).ComboIndex); + Assert.AreEqual(6, ((IHasComboInformation)converted.HitObjects.ElementAt(6)).ComboIndex); + Assert.AreEqual(11, ((IHasComboInformation)converted.HitObjects.ElementAt(8)).ComboIndex); + Assert.AreEqual(14, ((IHasComboInformation)converted.HitObjects.ElementAt(11)).ComboIndex); + } + } + + [Test] + public void TestDecodeBeatmapComboOffsetsCatch() + { + var decoder = new LegacyBeatmapDecoder(); + using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) + using (var stream = new StreamReader(resStream)) + { + var beatmap = decoder.Decode(stream); + + var converted = new CatchBeatmapConverter(beatmap).Convert(); + new CatchBeatmapProcessor(converted).PreProcess(); + new CatchBeatmapProcessor(converted).PostProcess(); + + Assert.AreEqual(4, ((IHasComboInformation)converted.HitObjects.ElementAt(0)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(2)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(4)).ComboIndex); + Assert.AreEqual(6, ((IHasComboInformation)converted.HitObjects.ElementAt(6)).ComboIndex); + Assert.AreEqual(11, ((IHasComboInformation)converted.HitObjects.ElementAt(8)).ComboIndex); + Assert.AreEqual(14, ((IHasComboInformation)converted.HitObjects.ElementAt(11)).ComboIndex); } } diff --git a/osu.Game.Tests/Resources/hitobject-combo-offset.osu b/osu.Game.Tests/Resources/hitobject-combo-offset.osu index 4a44d31e22..c1f0dab8e9 100644 --- a/osu.Game.Tests/Resources/hitobject-combo-offset.osu +++ b/osu.Game.Tests/Resources/hitobject-combo-offset.osu @@ -1,4 +1,32 @@ osu file format v14 [HitObjects] -255,193,2170,49,0,0:0:0:0: \ No newline at end of file +// Circle with combo offset (3) +255,193,1000,49,0,0:0:0:0: +// Combo index = 4 + +// Slider with new combo followed by circle with no new combo +256,192,2000,12,0,2000,0:0:0:0: +255,193,3000,1,0,0:0:0:0: +// Combo index = 5 + +// Slider without new combo followed by circle with no new combo +256,192,4000,8,0,5000,0:0:0:0: +255,193,6000,1,0,0:0:0:0: +// Combo index = 5 + +// Slider without new combo followed by circle with new combo +256,192,7000,8,0,8000,0:0:0:0: +255,193,9000,5,0,0:0:0:0: +// Combo index = 6 + +// Slider with new combo and offset (1) followed by circle with new combo and offset (3) +256,192,10000,28,0,11000,0:0:0:0: +255,193,12000,53,0,0:0:0:0: +// Combo index = 11 + +// Slider with new combo and offset (2) followed by slider with no new combo followed by circle with no new combo +256,192,13000,44,0,14000,0:0:0:0: +256,192,15000,8,0,16000,0:0:0:0: +255,193,17000,1,0,0:0:0:0: +// Combo index = 14 \ No newline at end of file From 83dc01d07c9d61523e294d1affa9763c448b96b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 12:03:31 +0900 Subject: [PATCH 165/277] Fix multiple sentry reports arriving for similar exceptions --- osu.Desktop/Program.cs | 4 +++- osu.Game/Utils/RavenLogger.cs | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 19ceade644..db77427f96 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -62,9 +62,11 @@ namespace osu.Desktop { bool continueExecution = Interlocked.Decrement(ref allowableExceptions) >= 0; - Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed" : "denied")} with {allowableExceptions} more allowable exceptions."); + Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed with {allowableExceptions} more allowable exceptions" : "denied")} ."); + // restore the stock of allowable exceptions after a short delay. Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); + return continueExecution; } } diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 761bd51672..70080fefa8 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -19,18 +19,30 @@ namespace osu.Game.Utils private readonly List tasks = new List(); + private Exception lastException; + public RavenLogger(OsuGame game) { raven.Release = game.Version; - if (!game.IsDeployedBuild) return; - Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; - if (entry.Exception != null) - queuePendingTask(raven.CaptureAsync(new SentryEvent(entry.Exception))); + var exception = entry.Exception; + + if (exception != null) + { + // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports. + if (lastException != null && + lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace)) + { + return; + } + + lastException = exception; + queuePendingTask(raven.CaptureAsync(new SentryEvent(exception))); + } else raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); }; From 0ae487b9c9a478afff2e083a07475a2da44932c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 12:27:36 +0900 Subject: [PATCH 166/277] Add back missing statement --- osu.Game/Utils/RavenLogger.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 70080fefa8..b28dd1fb73 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -25,6 +25,8 @@ namespace osu.Game.Utils { raven.Release = game.Version; + if (!game.IsDeployedBuild) return; + Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; From 99ace9805f25c54e164b07979ed0e16a4a54fcfe Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 12:54:32 +0900 Subject: [PATCH 167/277] Fix mirror note generation never completing --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 930ca26660..5860480a91 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -286,6 +286,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The containing the hit objects. private Pattern generateRandomPatternWithMirrored(double centreProbability, double p2, double p3) { + if (convertType.HasFlag(PatternType.ForceNotStack)) + return generateRandomPattern(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3); + var pattern = new Pattern(); bool addToCentre; @@ -370,9 +373,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { addToCentre = false; - if (convertType.HasFlag(PatternType.ForceNotStack)) - return getRandomNoteCount(1 / 2f + p2 / 2, p2, (p2 + p3) / 2, p3); - switch (TotalColumns) { case 2: From 7a8aabc402acc6ca16b8d7dafa2419be4354623d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 13:18:48 +0900 Subject: [PATCH 168/277] Fix notifications suggesting automatic reporting in non-deployed builds --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ecf5500ca4..d54bdee1b2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -463,7 +463,7 @@ namespace osu.Game Schedule(() => notifications.Post(new SimpleNotification { Icon = entry.Level == LogLevel.Important ? FontAwesome.fa_exclamation_circle : FontAwesome.fa_bomb, - Text = entry.Message + (entry.Exception != null ? "\n\nThis error has been automatically reported to the devs." : string.Empty), + Text = entry.Message + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty), })); } else if (recentLogCount == short_term_display_limit) From 3d6721111a8159a0a6ad9bebb9ded491cd952cb8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:26:53 +0900 Subject: [PATCH 169/277] Increase the maximum allowable iterations during mania conversion --- osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 1eb0cdae2f..e51cbcdc60 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -18,8 +18,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// An arbitrary maximum amount of iterations to perform in . /// The specific value is not super important - enough such that no false-positives occur. + /// + /// /b/933228 requires at least 23 iterations. /// - private const int max_rng_iterations = 20; + private const int max_rng_iterations = 30; /// /// The last pattern. From 583e026906c46b5861bf30a3626dadc840fb5c13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 13:28:35 +0900 Subject: [PATCH 170/277] =?UTF-8?q?Don=E2=80=99t=20suppress=20unhandled=20?= =?UTF-8?q?exceptions=20in=20debug=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- osu.Desktop/Program.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index db77427f96..71613753bc 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework; +using osu.Framework.Development; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IPC; @@ -51,7 +52,7 @@ namespace osu.Desktop } } - private static int allowableExceptions = 1; + private static int allowableExceptions = DebugUtils.IsDebugBuild ? 0 : 1; /// /// Allow a maximum of one unhandled exception, per second of execution. From 16d30f6756d78cf9f38ac3e293c870e5b8653b0f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:31:12 +0900 Subject: [PATCH 171/277] Add explanatory comments --- .../Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs | 2 ++ osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index cb44fb1c8c..802080aedb 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -60,6 +60,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + // Convert spinners don't create the new combo themselves, but force the next non-spinner hitobject to create a new combo + // Their combo offset is still added to that next hitobject's combo index forceNewCombo |= FormatVersion <= 8 || newCombo; extraComboOffset += comboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 497d85f849..acd0de8688 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -61,6 +61,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + // Convert spinners don't create the new combo themselves, but force the next non-spinner hitobject to create a new combo + // Their combo offset is still added to that next hitobject's combo index forceNewCombo |= FormatVersion <= 8 || newCombo; extraComboOffset += comboOffset; From 83bda313d1dc092332a71e4320d6285480fe5404 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:50:27 +0900 Subject: [PATCH 172/277] Output the currently importing model --- osu.Game/Database/ArchiveModelManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index c00df59e3e..ac79a8f565 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -198,6 +198,8 @@ namespace osu.Game.Database try { + Logger.Log($"Importing {item}...", LoggingTarget.Database); + using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. { try From 9a1e92800b4e799bfd5a058a921ddbc395ceec51 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 14:30:44 +0900 Subject: [PATCH 173/277] Adjust with framework-side screenchanges --- osu.Game/Graphics/ScreenshotManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 7b3337cb23..bc30794298 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Drawing.Imaging; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -19,6 +18,7 @@ using osu.Game.Configuration; using osu.Game.Input.Bindings; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; +using SixLabors.ImageSharp; namespace osu.Game.Graphics { @@ -90,7 +90,7 @@ namespace osu.Game.Graphics waitDelegate.Cancel(); } - using (var bitmap = await host.TakeScreenshotAsync()) + using (var image = await host.TakeScreenshotAsync()) { Interlocked.Decrement(ref screenShotTasks); @@ -102,10 +102,10 @@ namespace osu.Game.Graphics switch (screenshotFormat.Value) { case ScreenshotFormat.Png: - bitmap.Save(stream, ImageFormat.Png); + image.SaveAsPng(stream); break; case ScreenshotFormat.Jpg: - bitmap.Save(stream, ImageFormat.Jpeg); + image.SaveAsJpeg(stream); break; default: throw new ArgumentOutOfRangeException(nameof(screenshotFormat)); From 442f6795bc8783a158738ea2bc388f6f02f63a9f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 19:33:14 +0900 Subject: [PATCH 174/277] Block user input --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 1 + osu.Game.Rulesets.Osu/OsuInputManager.cs | 31 ++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 4e0c12f619..4047e057cb 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -84,6 +84,7 @@ namespace osu.Game.Rulesets.Osu.Mods { // grab the input manager for future use. osuInputManager = (OsuInputManager)rulesetContainer.KeyBindingInputManager; + osuInputManager.AllowUserPresses = false; } } } diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index d9ae836e0a..78ef0ec733 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.ComponentModel; using osu.Framework.Input.Bindings; +using osu.Framework.Input.EventArgs; +using osu.Framework.Input.States; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Osu @@ -12,8 +14,34 @@ namespace osu.Game.Rulesets.Osu { public IEnumerable PressedActions => KeyBindingContainer.PressedActions; - public OsuInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique) + public bool AllowUserPresses { + set => ((OsuKeyBindingContainer)KeyBindingContainer).AllowUserPresses = value; + } + + protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + => new OsuKeyBindingContainer(ruleset, variant, unique); + + public OsuInputManager(RulesetInfo ruleset) + : base(ruleset, 0, SimultaneousBindingMode.Unique) + { + } + + private class OsuKeyBindingContainer : RulesetKeyBindingContainer + { + public bool AllowUserPresses = true; + + public OsuKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) + : base(ruleset, variant, unique) + { + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => AllowUserPresses && base.OnKeyDown( state,args); + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => AllowUserPresses && base.OnKeyUp( state,args); + protected override bool OnJoystickPress(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickPress( state,args); + protected override bool OnJoystickRelease(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickRelease( state,args); + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => AllowUserPresses && base.OnMouseDown( state,args); + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => AllowUserPresses && base.OnMouseUp( state,args); } } @@ -21,6 +49,7 @@ namespace osu.Game.Rulesets.Osu { [Description("Left Button")] LeftButton, + [Description("Right Button")] RightButton } From 41f8609e0fec70f285308adfad8860bfa68bca7a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 20:13:14 +0900 Subject: [PATCH 175/277] Also handle OnScroll --- osu.Game.Rulesets.Osu/OsuInputManager.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 78ef0ec733..e7bbe755a0 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -36,12 +36,13 @@ namespace osu.Game.Rulesets.Osu { } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => AllowUserPresses && base.OnKeyDown( state,args); - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => AllowUserPresses && base.OnKeyUp( state,args); - protected override bool OnJoystickPress(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickPress( state,args); - protected override bool OnJoystickRelease(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickRelease( state,args); - protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => AllowUserPresses && base.OnMouseDown( state,args); - protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => AllowUserPresses && base.OnMouseUp( state,args); + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => AllowUserPresses && base.OnKeyDown(state, args); + protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => AllowUserPresses && base.OnKeyUp(state, args); + protected override bool OnJoystickPress(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickPress(state, args); + protected override bool OnJoystickRelease(InputState state, JoystickEventArgs args) => AllowUserPresses && base.OnJoystickRelease(state, args); + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => AllowUserPresses && base.OnMouseDown(state, args); + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => AllowUserPresses && base.OnMouseUp(state, args); + protected override bool OnScroll(InputState state) => AllowUserPresses && base.OnScroll(state); } } From 6b0ed4a68d12f8867d498ab2c833423c946105d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 13:37:59 +0900 Subject: [PATCH 176/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index da17500128..b4e9c748d9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From e628e78f24a1601e3387e19f63821f0c805cddeb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 13:39:22 +0900 Subject: [PATCH 177/277] Update uniform usage --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 0532fe0223..abcd1ddbda 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -197,7 +197,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor if (Shared.VertexBuffer == null) Shared.VertexBuffer = new QuadVertexBuffer(max_sprites, BufferUsageHint.DynamicDraw); - Shader.GetUniform("g_FadeClock").Value = Time; + Shader.GetUniform("g_FadeClock").UpdateValue(ref Time); int updateStart = -1, updateEnd = 0; for (int i = 0; i < Parts.Length; ++i) From 18aa30fcb03c96a07ae6ecfaf02942025ea55b85 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 14:27:32 +0900 Subject: [PATCH 178/277] Unbind song select's ruleset to avoid test failures --- osu.Game/Screens/Select/SongSelect.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 54143bef8a..dcc0760262 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -460,6 +460,8 @@ namespace osu.Game.Screens.Select { base.Dispose(isDisposing); + Ruleset.UnbindAll(); + if (beatmaps != null) { beatmaps.ItemAdded -= onBeatmapSetAdded; From 65dc9f44e514ab816bbb2e1698774d4ba6724f17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 14:42:37 +0900 Subject: [PATCH 179/277] Catch OperationCanceledException in single file load sequence --- osu.Game/OsuGame.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d54bdee1b2..967cf95565 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -504,7 +504,16 @@ namespace osu.Game // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. - Schedule(() => { asyncLoadStream = asyncLoadStream?.ContinueWith(t => LoadComponentAsync(d, add).Wait()) ?? LoadComponentAsync(d, add); }); + Schedule(() => { asyncLoadStream = asyncLoadStream?.ContinueWith(async t => + { + try + { + await LoadComponentAsync(d, add); + } + catch (OperationCanceledException) + { + } + }) ?? LoadComponentAsync(d, add); }); } public bool OnPressed(GlobalAction action) From 39aa98d12de07050f459a0a0eeb219a2cfb079ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 14:58:02 +0900 Subject: [PATCH 180/277] Fix logo flying off-screen when exiting game --- osu.Game/Screens/Menu/ButtonSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index ce00686c02..7f2bc1d357 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Menu if (logo != null) { - if (logoTracking && iconFacade.IsLoaded) + if (logoTracking && logo.RelativePositionAxes == Axes.None && iconFacade.IsLoaded) logo.Position = logoTrackingPosition; iconFacade.Width = logo.SizeForFlow * 0.5f; From 295ccabf64e81b84cb386b9121f3390a4b132d72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 16:06:12 +0900 Subject: [PATCH 181/277] Expand out on to multiple lines --- osu.Game/OsuGame.cs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 967cf95565..94678a9dde 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -504,16 +504,25 @@ namespace osu.Game // schedule is here to ensure that all component loads are done after LoadComplete is run (and thus all dependencies are cached). // with some better organisation of LoadComplete to do construction and dependency caching in one step, followed by calls to loadComponentSingleFile, // we could avoid the need for scheduling altogether. - Schedule(() => { asyncLoadStream = asyncLoadStream?.ContinueWith(async t => + Schedule(() => { - try + if (asyncLoadStream != null) { - await LoadComponentAsync(d, add); + //chain with existing load stream + asyncLoadStream = asyncLoadStream.ContinueWith(async t => + { + try + { + await LoadComponentAsync(d, add); + } + catch (OperationCanceledException) + { + } + }); } - catch (OperationCanceledException) - { - } - }) ?? LoadComponentAsync(d, add); }); + else + asyncLoadStream = LoadComponentAsync(d, add); + }); } public bool OnPressed(GlobalAction action) From 7add4a8cc75df572fa695860f6abd52a021adeb7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 Aug 2018 18:26:34 +0900 Subject: [PATCH 182/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b4e9c748d9..06fb1c4f82 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 4a68b14447fd082f7c973ffa9def4e1943da21b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Aug 2018 00:15:51 +0900 Subject: [PATCH 183/277] Fix crash when selecting mods after entering play mode Closes #3260. --- osu.Game/Screens/Play/HUD/ModDisplay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index 894322dd41..1a164b473d 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -63,6 +63,12 @@ namespace osu.Game.Screens.Play.HUD }; } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + mods.UnbindAll(); + } + protected override void LoadComplete() { base.LoadComplete(); From da13266ae95f28b1121ce7df7f193dd832cfa807 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 09:17:44 +0900 Subject: [PATCH 184/277] Fix missed string interpolation --- osu.Desktop/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 71613753bc..257155478f 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -63,7 +63,7 @@ namespace osu.Desktop { bool continueExecution = Interlocked.Decrement(ref allowableExceptions) >= 0; - Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed with {allowableExceptions} more allowable exceptions" : "denied")} ."); + Logger.Log($"Unhandled exception has been {(continueExecution ? $"allowed with {allowableExceptions} more allowable exceptions" : "denied")} ."); // restore the stock of allowable exceptions after a short delay. Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); From 541c4daa810ad3700e7381b9a0f3dddfbc796749 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 11:10:54 +0900 Subject: [PATCH 185/277] Use ordinal string comparison in hot paths --- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 4 ++-- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 76a3d75e36..e9f37e583b 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -31,7 +31,7 @@ namespace osu.Game.Beatmaps.Formats if (ShouldSkipLine(line)) continue; - if (line.StartsWith(@"[") && line.EndsWith(@"]")) + if (line.StartsWith(@"[", StringComparison.Ordinal) && line.EndsWith(@"]", StringComparison.Ordinal)) { if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section)) { @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps.Formats } } - protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//"); + protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//", StringComparison.Ordinal); protected virtual void ParseLine(T output, Section section, string line) { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index a8a62013b1..1063dfc923 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -60,7 +60,7 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(string line) { var depth = 0; - while (line.StartsWith(" ") || line.StartsWith("_")) + while (line.StartsWith(" ", StringComparison.Ordinal) || line.StartsWith("_", StringComparison.Ordinal)) { ++depth; line = line.Substring(1); From fcf98390f56b0e5cca645d8f7f255d9fc1c8731b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 12:10:00 +0900 Subject: [PATCH 186/277] Cleanup --- osu.Game/Rulesets/UI/Playfield.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index 7a7ada3435..da14fb54d6 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -56,9 +56,10 @@ namespace osu.Game.Rulesets.UI private WorkingBeatmap beatmap; [BackgroundDependencyLoader] - private void load(IBindableBeatmap bBeatmap) + private void load(IBindableBeatmap beatmap) { - beatmap = bBeatmap.Value; + this.beatmap = beatmap.Value; + HitObjects = CreateHitObjectContainer(); HitObjects.RelativeSizeAxes = Axes.Both; From 34b1abeca3c1eb544d563539420492ec6838f6ef Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 12:10:43 +0900 Subject: [PATCH 187/277] Remove sliderball's input override --- .../Objects/Drawables/Pieces/SliderBall.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 182cf66df8..b11e4fc971 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input.EventArgs; using osu.Framework.Input.States; using osu.Game.Rulesets.Objects.Types; -using OpenTK; using OpenTK.Graphics; using osu.Game.Skinning; @@ -121,9 +120,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces return base.OnMouseMove(state); } - // If the current time is between the start and end of the slider, we should track mouse input regardless of the cursor position. - public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => canCurrentlyTrack || base.ReceiveMouseInputAt(screenSpacePos); - public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { // Consider the case of rewinding - children's transforms are handled internally, so propagating down @@ -158,7 +154,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces // Make sure to use the base version of ReceiveMouseInputAt so that we correctly check the position. Tracking = canCurrentlyTrack && lastState != null - && base.ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) + && ReceiveMouseInputAt(lastState.Mouse.NativeState.Position) && ((Parent as DrawableSlider)?.OsuActionInputManager?.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton) ?? false); } } From d14dad64e85c0fc4d5e15577b708b675b4c37654 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 16:01:28 +0900 Subject: [PATCH 188/277] Fix hitobject stacking being applied too early --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 5fe2457645..cfb1b0f050 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -15,9 +15,9 @@ namespace osu.Game.Rulesets.Osu.Beatmaps { } - public override void PreProcess() + public override void PostProcess() { - base.PreProcess(); + base.PostProcess(); applyStacking((Beatmap)Beatmap); } From 8b795cd52a2bbb7b955d73564c2c6d904505c11c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 Aug 2018 17:22:28 +0900 Subject: [PATCH 189/277] Add very simple stacking test --- osu.Game.Rulesets.Osu.Tests/StackingTest.cs | 64 +++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/StackingTest.cs diff --git a/osu.Game.Rulesets.Osu.Tests/StackingTest.cs b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs new file mode 100644 index 0000000000..579cb77084 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/StackingTest.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Tests.Beatmaps; +using Decoder = osu.Game.Beatmaps.Formats.Decoder; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class StackingTest + { + [Test] + public void TestStacking() + { + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(beatmap_data))) + using (var reader = new StreamReader(stream)) + { + var beatmap = Decoder.GetDecoder(reader).Decode(reader); + var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo); + + var objects = converted.HitObjects.ToList(); + + // The last hitobject triggers the stacking + for (int i = 0; i < objects.Count - 1; i++) + Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight); + } + } + + private const string beatmap_data = @" +osu file format v14 + +[General] +StackLeniency: 0.2 + +[Difficulty] +ApproachRate:9.2 +SliderMultiplier:1 +SliderTickRate:0.5 + +[TimingPoints] +217871,6400,4,2,1,20,1,0 +217871,-800,4,2,1,20,0,0 +218071,-787.5,4,2,1,20,0,0 +218271,-775,4,2,1,20,0,0 +218471,-762.5,4,2,1,20,0,0 +218671,-750,4,2,1,20,0,0 +240271,-10,4,2,0,5,0,0 + +[HitObjects] +311,185,217871,6,0,L|318:158,1,25 +311,185,218071,2,0,L|335:170,1,25 +311,185,218271,2,0,L|338:192,1,25 +311,185,218471,2,0,L|325:209,1,25 +311,185,218671,2,0,L|304:212,1,25 +311,185,240271,5,0,0:0:0:0: +"; + } +} From c97548804e5acf8c71d6cb5a186f5e8823c9646a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Aug 2018 18:46:44 +0900 Subject: [PATCH 190/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 06fb1c4f82..2115453c5e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 4cd21fabf34e59956740ad78f5703285baced4b7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Aug 2018 19:16:07 +0900 Subject: [PATCH 191/277] Remove extra newlines --- osu.Game/Graphics/UserInterface/TriangleButton.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index e85ef9dac1..683b442d93 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -27,7 +27,6 @@ namespace osu.Game.Graphics.UserInterface }); } - public IEnumerable FilterTerms => new[] { Text }; public bool MatchingFilter @@ -37,6 +36,5 @@ namespace osu.Game.Graphics.UserInterface this.FadeTo(value ? 1 : 0); } } - } } From 2bc827fa0c493a5ab552d42486c917682691955d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 11:32:00 +0900 Subject: [PATCH 192/277] Fix taiko beatmap conversion attempting to make strong swells --- osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index acd6d43284..c2cde332e8 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x => { TaikoHitObject first = x.First(); - if (x.Skip(1).Any()) + if (x.Skip(1).Any() && !(first is Swell)) first.IsStrong = true; return first; }).ToList(); From ce367bcc421f8865a4ef249767100667968a8bd9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 12:02:14 +0900 Subject: [PATCH 193/277] Fix invalid GC latency mode being set --- .../Settings/Sections/Debug/GCSettings.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 9f550413f3..b14a4b8773 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -13,15 +13,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { protected override string Header => "Garbage Collector"; + private readonly Bindable latencyMode = new Bindable(); + private Bindable configLatencyMode; + [BackgroundDependencyLoader] private void load(FrameworkDebugConfigManager config) { Children = new Drawable[] { - new SettingsEnumDropdown + new SettingsEnumDropdown { LabelText = "Active mode", - Bindable = config.GetBindable(DebugSetting.ActiveGCMode) + Bindable = latencyMode }, new SettingsButton { @@ -29,6 +32,18 @@ namespace osu.Game.Overlays.Settings.Sections.Debug Action = GC.Collect }, }; + + configLatencyMode = config.GetBindable(DebugSetting.ActiveGCMode); + configLatencyMode.BindValueChanged(v => latencyMode.Value = (LatencyMode)v, true); + latencyMode.BindValueChanged(v => configLatencyMode.Value = (GCLatencyMode)v); + } + + private enum LatencyMode + { + Batch = GCLatencyMode.Batch, + Interactive = GCLatencyMode.Interactive, + LowLatency = GCLatencyMode.LowLatency, + SustainedLowLatency = GCLatencyMode.SustainedLowLatency } } } From 50b8daf9390268cf2d94a897baf47681e31d314e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 14:07:52 +0900 Subject: [PATCH 194/277] Fix threads being cross-disposed from DatabaseContextFactory --- osu.Game/Database/DatabaseContextFactory.cs | 5 +++-- osu.Game/Database/OsuDbContext.cs | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index e70d753114..2037612a09 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using System.Threading; using Microsoft.EntityFrameworkCore.Storage; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Platform; namespace osu.Game.Database @@ -118,7 +117,9 @@ namespace osu.Game.Database private void recycleThreadContexts() { - threadContexts?.Values.ForEach(c => c.Dispose()); + // Contexts for other threads are not disposed as they may be in use elsewhere. Instead, fresh contexts are exposed + // for other threads to use, and we rely on the finalizer inside OsuDbContext to handle their previous contexts + threadContexts?.Value.Dispose(); threadContexts = new ThreadLocal(CreateContext, true); } diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index bf57644caf..20e144c033 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -75,6 +75,13 @@ namespace osu.Game.Database } } + ~OsuDbContext() + { + // DbContext does not contain a finalizer (https://github.com/aspnet/EntityFrameworkCore/issues/8872) + // This is used to clean up previous contexts when fresh contexts are exposed via DatabaseContextFactory + Dispose(); + } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); From df848896463c8d9319fece673379d31b43599c27 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 14:50:03 +0900 Subject: [PATCH 195/277] Handle invalid origins as Anchor.TopLeft --- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 1063dfc923..a73a32325a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -269,9 +269,9 @@ namespace osu.Game.Beatmaps.Formats return Anchor.BottomCentre; case LegacyOrigins.BottomRight: return Anchor.BottomRight; + default: + return Anchor.TopLeft; } - - throw new InvalidDataException($@"Unknown origin: {value}"); } private void handleVariables(string line) From bdd618a99deaf091abb8626b3d094dbdf2b3f257 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 15:42:43 +0900 Subject: [PATCH 196/277] Log the archive when failing to create model --- osu.Game/Beatmaps/BeatmapManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 1c28b533d2..e31746457a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -350,7 +350,8 @@ namespace osu.Game.Beatmaps { // let's make sure there are actually .osu files to import. string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); - if (string.IsNullOrEmpty(mapName)) throw new InvalidOperationException("No beatmap files found in this beatmap archive."); + if (string.IsNullOrEmpty(mapName)) + throw new InvalidOperationException($"No beatmap files found in this beatmap archive. ({reader.Name})"); Beatmap beatmap; using (var stream = new StreamReader(reader.GetStream(mapName))) From 551581e5cdde3f42ea7496da5b873a90a3da7dcb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 15:35:29 +0900 Subject: [PATCH 197/277] Skip invalid hitobject types, log error instead --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 3 --- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 8 +++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 31a7698f50..181d17932d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -408,11 +408,8 @@ namespace osu.Game.Beatmaps.Formats parser = new Rulesets.Objects.Legacy.Osu.ConvertHitObjectParser(getOffsetTime(), FormatVersion); var obj = parser.Parse(line); - if (obj != null) - { beatmap.HitObjects.Add(obj); - } } private int getOffsetTime(int time) => time + (ApplyOffsets ? offset : 0); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index 8236333a3f..72168a4cd2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -10,6 +10,8 @@ using System.IO; using osu.Game.Beatmaps.Formats; using osu.Game.Audio; using System.Linq; +using JetBrains.Annotations; +using osu.Framework.Logging; using osu.Framework.MathUtils; namespace osu.Game.Rulesets.Objects.Legacy @@ -37,6 +39,7 @@ namespace osu.Game.Rulesets.Objects.Legacy FormatVersion = formatVersion; } + [CanBeNull] public override HitObject Parse(string text) { try @@ -191,7 +194,10 @@ namespace osu.Game.Rulesets.Objects.Legacy } if (result == null) - throw new InvalidOperationException($@"Unknown hit object type {type}."); + { + Logger.Log($"Unknown hit object type: {type}. Skipped.", level: LogLevel.Error); + return null; + } result.StartTime = Convert.ToDouble(split[2], CultureInfo.InvariantCulture) + Offset; result.Samples = convertSoundType(soundType, bankInfo); From 2fb62827e2a6ecb101300235339e3d824bcca5e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 22 Aug 2018 16:01:58 +0900 Subject: [PATCH 198/277] Soft-handle errors when beatmap contains no objects --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2e23bb16f0..5ad0130fd7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -124,7 +124,7 @@ namespace osu.Game.Screens.Play if (!RulesetContainer.Objects.Any()) { - Logger.Error(new InvalidOperationException("Beatmap contains no hit objects!"), "Beatmap contains no hit objects!"); + Logger.Log("Beatmap contains no hit objects!", level: LogLevel.Error); return; } } From f1c6dfd735e885178cc5b4dccea6c60a91167fcb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Aug 2018 16:22:29 +0900 Subject: [PATCH 199/277] Change grammar slightly --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e31746457a..fc5a967f2d 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -351,7 +351,7 @@ namespace osu.Game.Beatmaps // let's make sure there are actually .osu files to import. string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); if (string.IsNullOrEmpty(mapName)) - throw new InvalidOperationException($"No beatmap files found in this beatmap archive. ({reader.Name})"); + throw new InvalidOperationException($"No beatmap files found in this beatmap archive ({reader.Name})."); Beatmap beatmap; using (var stream = new StreamReader(reader.GetStream(mapName))) From 9cbead55d62677653a583ccbddf7dbd169262ad5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 Aug 2018 17:41:13 +0900 Subject: [PATCH 200/277] Add a second parallax layer to break overlay arrows --- osu.Game/Screens/Play/Break/BreakArrows.cs | 39 +++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Play/Break/BreakArrows.cs b/osu.Game/Screens/Play/Break/BreakArrows.cs index 4a4a7960fa..1382aa9d9d 100644 --- a/osu.Game/Screens/Play/Break/BreakArrows.cs +++ b/osu.Game/Screens/Play/Break/BreakArrows.cs @@ -31,23 +31,30 @@ namespace osu.Game.Screens.Play.Break RelativeSizeAxes = Axes.Both; InternalChildren = new Drawable[] { - leftGlowIcon = new GlowIcon + new ParallaxContainer { - Anchor = Anchor.Centre, - Origin = Anchor.CentreRight, - X = -glow_icon_offscreen_offset, - Icon = Graphics.FontAwesome.fa_chevron_right, - BlurSigma = new Vector2(glow_icon_blur_sigma), - Size = new Vector2(glow_icon_size), - }, - rightGlowIcon = new GlowIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.CentreLeft, - X = glow_icon_offscreen_offset, - Icon = Graphics.FontAwesome.fa_chevron_left, - BlurSigma = new Vector2(glow_icon_blur_sigma), - Size = new Vector2(glow_icon_size), + ParallaxAmount = -0.01f, + Children = new Drawable[] + { + leftGlowIcon = new GlowIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.CentreRight, + X = -glow_icon_offscreen_offset, + Icon = Graphics.FontAwesome.fa_chevron_right, + BlurSigma = new Vector2(glow_icon_blur_sigma), + Size = new Vector2(glow_icon_size), + }, + rightGlowIcon = new GlowIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.CentreLeft, + X = glow_icon_offscreen_offset, + Icon = Graphics.FontAwesome.fa_chevron_left, + BlurSigma = new Vector2(glow_icon_blur_sigma), + Size = new Vector2(glow_icon_size), + }, + } }, new ParallaxContainer { From 6475dfaeef6c0c51dbb28cc05d0dfa3e9bf1674e Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 Aug 2018 09:14:55 +0900 Subject: [PATCH 201/277] Allow 2B maps to be converted to mania --- .../Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 5860480a91..b2b9fe2446 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -25,9 +25,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy PatternType lastStair, IBeatmap originalBeatmap) : base(random, hitObject, beatmap, previousPattern, originalBeatmap) { - if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); - if (density < 0) throw new ArgumentOutOfRangeException(nameof(density)); - StairType = lastStair; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); From 8f261988f781f81fa11ee5c0f94a12d3834263de Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 Aug 2018 10:56:52 +0900 Subject: [PATCH 202/277] Log all files when no beatmap files in archive error occurs --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index fc5a967f2d..1a2b5eadd9 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -351,7 +351,11 @@ namespace osu.Game.Beatmaps // let's make sure there are actually .osu files to import. string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); if (string.IsNullOrEmpty(mapName)) - throw new InvalidOperationException($"No beatmap files found in this beatmap archive ({reader.Name})."); + { + // Todo: This is temporary for debugging purposes + var files = reader.Filenames.ToList(); + throw new InvalidOperationException($"No beatmap files found in this beatmap archive. Files ({files.Count}): {string.Join(", ", files)}"); + } Beatmap beatmap; using (var stream = new StreamReader(reader.GetStream(mapName))) From 9f3f07df2e1a977797dc27a0b802663e96d7733e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 Aug 2018 11:20:20 +0900 Subject: [PATCH 203/277] Fix notifications appearing too early in load process --- osu.Game/Overlays/NotificationOverlay.cs | 3 +-- osu.Game/Screens/Loader.cs | 3 +++ osu.Game/Screens/Menu/ButtonSystem.cs | 15 +++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index d891cd96e8..78f8f57343 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -96,8 +96,7 @@ namespace osu.Game.Overlays base.LoadComplete(); StateChanged += _ => updateProcessingMode(); - OverlayActivationMode.ValueChanged += _ => updateProcessingMode(); - OverlayActivationMode.TriggerChange(); + OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true); } private int totalCount => sections.Select(c => c.DisplayedCount).Sum(); diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index c3b3e747fd..3cef20e510 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Shaders; using osu.Game.Screens.Menu; using OpenTK; using osu.Framework.Screens; +using osu.Game.Overlays; namespace osu.Game.Screens { @@ -18,6 +19,8 @@ namespace osu.Game.Screens protected override bool HideOverlaysOnEnter => true; + protected override OverlayActivation InitialOverlayActivationMode => OverlayActivation.Disabled; + protected override bool AllowBackButton => false; public Loader() diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 7f2bc1d357..b9a799328e 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -174,6 +174,9 @@ namespace osu.Game.Screens.Menu ButtonSystemState lastState = state; state = value; + if (game != null) + game.OverlayActivationMode.Value = state == ButtonSystemState.Exit ? OverlayActivation.Disabled : OverlayActivation.All; + updateLogoState(lastState); Logger.Log($"{nameof(ButtonSystem)}'s state changed from {lastState} to {state}"); @@ -205,11 +208,7 @@ namespace osu.Game.Screens.Menu { logoTracking = false; - if (game != null) - { - game.OverlayActivationMode.Value = state == ButtonSystemState.Exit ? OverlayActivation.Disabled : OverlayActivation.All; - game.Toolbar.Hide(); - } + game?.Toolbar.Hide(); logo.ClearTransforms(targetMember: nameof(Position)); logo.RelativePositionAxes = Axes.Both; @@ -243,11 +242,7 @@ namespace osu.Game.Screens.Menu if (impact) logo.Impact(); - if (game != null) - { - game.OverlayActivationMode.Value = OverlayActivation.All; - game.Toolbar.State = Visibility.Visible; - } + game?.Toolbar.Show(); }, 200); break; default: From c7db40783221ab1bbbc28feb2d0898af0ceec528 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 Aug 2018 14:53:16 +0900 Subject: [PATCH 204/277] Fix operation cancelled exception when changing visual settings --- osu.Game/Skinning/LocalSkinOverrideContainer.cs | 6 ++---- osu.Game/Skinning/SkinReloadableDrawable.cs | 7 +++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs index 3adf287cf7..25d9442e6f 100644 --- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs +++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs @@ -85,12 +85,10 @@ namespace osu.Game.Skinning private void load(OsuConfigManager config) { beatmapSkins = config.GetBindable(OsuSetting.BeatmapSkins); - beatmapSkins.ValueChanged += val => onSourceChanged(); - beatmapSkins.TriggerChange(); + beatmapSkins.BindValueChanged(_ => onSourceChanged()); beatmapHitsounds = config.GetBindable(OsuSetting.BeatmapHitsounds); - beatmapHitsounds.ValueChanged += val => onSourceChanged(); - beatmapHitsounds.TriggerChange(); + beatmapHitsounds.BindValueChanged(_ => onSourceChanged(), true); } protected override void LoadComplete() diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index f1ee0db6ce..3ff28ab871 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -52,5 +52,12 @@ namespace osu.Game.Skinning protected virtual void SkinChanged(ISkinSource skin, bool allowFallback) { } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + skin.SourceChanged -= onChange; + } } } From 90ebabd2db4c94edddc20eb134f75a1426dee9b3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 Aug 2018 15:21:36 +0900 Subject: [PATCH 205/277] Fix nullref --- osu.Game/Skinning/SkinReloadableDrawable.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinReloadableDrawable.cs b/osu.Game/Skinning/SkinReloadableDrawable.cs index 3ff28ab871..0b94697405 100644 --- a/osu.Game/Skinning/SkinReloadableDrawable.cs +++ b/osu.Game/Skinning/SkinReloadableDrawable.cs @@ -57,7 +57,8 @@ namespace osu.Game.Skinning { base.Dispose(isDisposing); - skin.SourceChanged -= onChange; + if (skin != null) + skin.SourceChanged -= onChange; } } } From 407968bb7e2f86d11a5582b69bd284dcd5ce4768 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 10:03:56 +0900 Subject: [PATCH 206/277] Log the format line when a decoder isn't found --- osu.Game/Beatmaps/Formats/Decoder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 2927654f62..759d6d14d1 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -55,11 +55,11 @@ namespace osu.Game.Beatmaps.Formats } while (line != null && line.Length == 0); if (line == null) - throw new IOException(@"Unknown file format"); + throw new IOException(@"Unknown file format (null)"); var decoder = typedDecoders.Select(d => line.StartsWith(d.Key) ? d.Value : null).FirstOrDefault(); if (decoder == null) - throw new IOException(@"Unknown file format"); + throw new IOException($@"Unknown file format ({line})"); return (Decoder)decoder.Invoke(line); } From 55370165c0487e5a1cc606ab554fe7cb1e965b5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 10:12:30 +0900 Subject: [PATCH 207/277] Compare with invariant culture --- osu.Game/Beatmaps/Formats/Decoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index 759d6d14d1..6f45718390 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -57,7 +57,7 @@ namespace osu.Game.Beatmaps.Formats if (line == null) throw new IOException(@"Unknown file format (null)"); - var decoder = typedDecoders.Select(d => line.StartsWith(d.Key) ? d.Value : null).FirstOrDefault(); + var decoder = typedDecoders.Select(d => line.StartsWith(d.Key, StringComparison.InvariantCulture) ? d.Value : null).FirstOrDefault(); if (decoder == null) throw new IOException($@"Unknown file format ({line})"); From 59d6ccbaab7796c16aefc6a223e3675bf4bceee2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 24 Aug 2018 15:27:13 +0900 Subject: [PATCH 208/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2115453c5e..69d242daa9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 1a2c3715c762406e8a6cfe93237cfcdb6b25466a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 15:50:39 +0900 Subject: [PATCH 209/277] Fix testcase dodginess --- osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs index e4cb848d90..041fce6ce3 100644 --- a/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs +++ b/osu.Game.Tests/Visual/TestCasePreviewTrackManager.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - AddInternal(trackManager); + Add(trackManager); } [Test] @@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual TestTrackOwner owner = null; PreviewTrack track = null; - AddStep("get track", () => AddInternal(owner = new TestTrackOwner(track = getTrack()))); + AddStep("get track", () => Add(owner = new TestTrackOwner(track = getTrack()))); AddStep("start", () => track.Start()); AddStep("attempt stop", () => trackManager.StopAnyPlaying(this)); AddAssert("not stopped", () => track.IsRunning); @@ -89,7 +89,7 @@ namespace osu.Game.Tests.Visual { var track = getTrack(); - AddInternal(track); + Add(track); return track; } From 99574ecad81e3294ea21c963ad139df1b3b3b381 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 17:57:39 +0900 Subject: [PATCH 210/277] Softly handle errors when no beatmap file exists in archive --- osu.Game/Beatmaps/BeatmapManager.cs | 5 ++--- osu.Game/Database/ArchiveModelManager.cs | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 1a2b5eadd9..3a12f26863 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -352,9 +352,8 @@ namespace osu.Game.Beatmaps string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); if (string.IsNullOrEmpty(mapName)) { - // Todo: This is temporary for debugging purposes - var files = reader.Filenames.ToList(); - throw new InvalidOperationException($"No beatmap files found in this beatmap archive. Files ({files.Count}): {string.Join(", ", files)}"); + Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name}). Skipping."); + return null; } Beatmap beatmap; diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index ac79a8f565..42dd6684d5 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -178,7 +178,8 @@ namespace osu.Game.Database { try { - return Import(CreateModel(archive), archive); + var model = CreateModel(archive); + return model == null ? null : Import(model, archive); } catch (Exception e) { From aeb4d47c06e57485ecb23f249133e804bf82b076 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 18:07:39 +0900 Subject: [PATCH 211/277] Remove skipping part of message --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 3a12f26863..d2be36e991 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -352,7 +352,7 @@ namespace osu.Game.Beatmaps string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); if (string.IsNullOrEmpty(mapName)) { - Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name}). Skipping."); + Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name})."); return null; } From 26dfabc86c1d90c575eaf6d8523fb685708e0f67 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 24 Aug 2018 23:57:44 +0900 Subject: [PATCH 212/277] Aggressively check for valid columns before iterating endlessly --- .../Legacy/DistanceObjectPatternGenerator.cs | 58 +++----------- .../Legacy/EndTimeObjectPatternGenerator.cs | 21 +---- .../Legacy/HitObjectPatternGenerator.cs | 34 ++++---- .../Patterns/Legacy/PatternGenerator.cs | 79 +++++++++++++++++++ .../Beatmaps/Patterns/PatternGenerator.cs | 45 ----------- 5 files changed, 110 insertions(+), 127 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 010cf962cc..37a8062d75 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -173,26 +173,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int usableColumns = TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects; - int nextColumn = Random.Next(RandomStart, TotalColumns); + int nextColumn = GetRandomColumn(); for (int i = 0; i < Math.Min(usableColumns, noteCount); i++) { // Find available column - RunWhile(() => pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - + nextColumn = FindAvailableColumn(nextColumn, pattern, PreviousPattern); addToPattern(pattern, nextColumn, startTime, EndTime); } // This is can't be combined with the above loop due to RNG for (int i = 0; i < noteCount - usableColumns; i++) { - RunWhile(() => pattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - + nextColumn = FindAvailableColumn(nextColumn, pattern); addToPattern(pattern, nextColumn, startTime, EndTime); } @@ -217,23 +209,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) - { - RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - } + nextColumn = FindAvailableColumn(nextColumn, PreviousPattern); int lastColumn = nextColumn; for (int i = 0; i < noteCount; i++) { addToPattern(pattern, nextColumn, startTime, startTime); - - RunWhile(() => nextColumn == lastColumn, () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - + nextColumn = FindAvailableColumn(nextColumn, validation: c => c != lastColumn); lastColumn = nextColumn; startTime += SegmentDuration; } @@ -325,7 +307,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (TotalColumns > 2) addToPattern(pattern, nextColumn, startTime, startTime); - nextColumn = Random.Next(RandomStart, TotalColumns); + nextColumn = GetRandomColumn(); startTime += SegmentDuration; } @@ -404,20 +386,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) - { - RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - } + nextColumn = FindAvailableColumn(nextColumn, PreviousPattern); for (int i = 0; i < columnRepeat; i++) { - RunWhile(() => pattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - + nextColumn = FindAvailableColumn(nextColumn, pattern); addToPattern(pattern, nextColumn, startTime, EndTime); startTime += SegmentDuration; } @@ -442,17 +415,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); if (convertType.HasFlag(PatternType.ForceNotStack) && PreviousPattern.ColumnWithObjects < TotalColumns) - { - RunWhile(() => PreviousPattern.ColumnHasObject(holdColumn), () => - { - holdColumn = Random.Next(RandomStart, TotalColumns); - }); - } + holdColumn = FindAvailableColumn(holdColumn, PreviousPattern); // Create the hold note addToPattern(pattern, holdColumn, startTime, EndTime); - int nextColumn = Random.Next(RandomStart, TotalColumns); + int nextColumn = GetRandomColumn(); int noteCount; if (ConversionDifficulty > 6.5) noteCount = GetRandomNoteCount(0.63, 0); @@ -473,11 +441,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { for (int j = 0; j < noteCount; j++) { - RunWhile(() => rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn, () => - { - nextColumn = Random.Next(RandomStart, TotalColumns); - }); - + nextColumn = FindAvailableColumn(nextColumn, validation: c => c != holdColumn, patterns: rowPattern); addToPattern(rowPattern, nextColumn, startTime, startTime); } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index eae9a0fc3b..775a4145e6 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -39,34 +39,17 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy addToPattern(pattern, 0, generateHold); break; case 8: - addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold); + addToPattern(pattern, FindAvailableColumn(GetRandomColumn(), PreviousPattern), generateHold); break; default: if (TotalColumns > 0) - addToPattern(pattern, getNextRandomColumn(0), generateHold); + addToPattern(pattern, GetRandomColumn(), generateHold); break; } return pattern; } - /// - /// Picks a random column after a column. - /// - /// The starting column. - /// A random column after . - private int getNextRandomColumn(int start) - { - int nextColumn = Random.Next(start, TotalColumns); - - RunWhile(() => PreviousPattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(start, TotalColumns); - }); - - return nextColumn; - } - /// /// Constructs and adds a note to a pattern. /// diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index b2b9fe2446..da1dd62cf5 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -231,22 +231,27 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); for (int i = 0; i < noteCount; i++) { - RunWhile(() => pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn) && !allowStacking, () => - { - if (convertType.HasFlag(PatternType.Gathered)) - { - nextColumn++; - if (nextColumn == TotalColumns) - nextColumn = RandomStart; - } - else - nextColumn = Random.Next(RandomStart, TotalColumns); - }); + nextColumn = allowStacking + ? FindAvailableColumn(nextColumn, nextColumn: getNextColumn, patterns: pattern) + : FindAvailableColumn(nextColumn, nextColumn: getNextColumn, patterns: new[] { pattern, PreviousPattern }); addToPattern(pattern, nextColumn); } return pattern; + + int getNextColumn(int last) + { + if (convertType.HasFlag(PatternType.Gathered)) + { + last++; + if (last == TotalColumns) + last = RandomStart; + } + else + last = GetRandomColumn(); + return last; + } } /// @@ -292,13 +297,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre); int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; - int nextColumn = Random.Next(RandomStart, columnLimit); + int nextColumn = GetRandomColumn(upperBound: columnLimit); for (int i = 0; i < noteCount; i++) { - RunWhile(() => pattern.ColumnHasObject(nextColumn), () => - { - nextColumn = Random.Next(RandomStart, columnLimit); - }); + nextColumn = FindAvailableColumn(nextColumn, upperBound: columnLimit, patterns: pattern); // Add normal note addToPattern(pattern, nextColumn); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 55081e5822..7a160ed389 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; @@ -90,6 +91,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } private double? conversionDifficulty; + /// /// A difficulty factor used for various conversion methods from osu!stable. /// @@ -116,5 +118,82 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy return conversionDifficulty.Value; } } + + /// + /// Finds a new column in which a can be placed. + /// This uses to pick the next candidate column. + /// + /// The initial column to test. This may be returned if it is already a valid column. + /// A list of patterns for which the validity of a column should be checked against. + /// A column is not a valid candidate if a occupies the same column in any of the patterns. + /// A column for which there are no s in any of occupying the same column. + /// If there are no valid candidate columns. + protected int FindAvailableColumn(int initialColumn, params Pattern[] patterns) + => FindAvailableColumn(initialColumn, null, patterns: patterns); + + /// + /// Finds a new column in which a can be placed. + /// + /// The initial column to test. This may be returned if it is already a valid column. + /// A function to retrieve the next column. If null, a randomisation scheme will be used. + /// A function to perform additional validation checks to determine if a column is a valid candidate for a . + /// The minimum column index. If null, is used. + /// The maximum column index. If null, is used. + /// A list of patterns for which the validity of a column should be checked against. + /// A column is not a valid candidate if a occupies the same column in any of the patterns. + /// A column which has passed the check and for which there are no + /// s in any of occupying the same column. + /// If there are no valid candidate columns. + protected int FindAvailableColumn(int initialColumn, int? lowerBound = null, int? upperBound = null, Func nextColumn = null, [InstantHandle] Func validation = null, + params Pattern[] patterns) + { + lowerBound = lowerBound ?? RandomStart; + upperBound = upperBound ?? TotalColumns; + nextColumn = nextColumn ?? (_ => GetRandomColumn(lowerBound, upperBound)); + + // Check for the initial column + if (isValid(initialColumn)) + return initialColumn; + + // Ensure that we have at least one free column, so that an endless loop is avoided + bool hasValidColumns = false; + for (int i = lowerBound.Value; i < upperBound.Value; i++) + { + hasValidColumns = isValid(i); + if (hasValidColumns) + break; + } + + if (!hasValidColumns) + throw new NotEnoughColumnsException(); + + // Iterate until a valid column is found. This is a random iteration in the default case. + do + { + initialColumn = nextColumn(initialColumn); + } while (!isValid(initialColumn)); + + return initialColumn; + + bool isValid(int column) => validation?.Invoke(column) != false && !patterns.Any(p => p.ColumnHasObject(column)); + } + + /// + /// Returns a random column index in the range [RandomStart, TotalColumns). + /// + /// The minimum column index. If null, is used. + /// The maximum column index. If null, is used. + protected int GetRandomColumn(int? lowerBound = null, int? upperBound = null) => Random.Next(lowerBound ?? RandomStart, upperBound ?? TotalColumns); + + /// + /// Occurs when mania conversion is stuck in an infinite loop unable to find columns to place new hitobjects in. + /// + public class NotEnoughColumnsException : Exception + { + public NotEnoughColumnsException() + : base("There were not enough columns to complete conversion.") + { + } + } } } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index e51cbcdc60..a42d57cdd1 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -3,9 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; -using JetBrains.Annotations; -using osu.Framework.Logging; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns @@ -15,14 +12,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// internal abstract class PatternGenerator { - /// - /// An arbitrary maximum amount of iterations to perform in . - /// The specific value is not super important - enough such that no false-positives occur. - /// - /// /b/933228 requires at least 23 iterations. - /// - private const int max_rng_iterations = 30; - /// /// The last pattern. /// @@ -53,44 +42,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns TotalColumns = Beatmap.TotalColumns; } - protected void RunWhile([InstantHandle] Func condition, Action action) - { - int iterations = 0; - - while (condition()) - { - if (iterations++ >= max_rng_iterations) - { - // log an error but don't throw. we want to continue execution. - Logger.Error(new ExceededAllowedIterationsException(new StackTrace(0)), - "Conversion encountered errors. The beatmap may not be correctly converted."); - return; - } - - action(); - } - } - /// /// Generates the patterns for , each filled with hit objects. /// /// The s containing the hit objects. public abstract IEnumerable Generate(); - - /// - /// Denotes when a single conversion operation is in an infinitely looping state. - /// - public class ExceededAllowedIterationsException : Exception - { - private readonly string stackTrace; - - public ExceededAllowedIterationsException(StackTrace stackTrace) - { - this.stackTrace = stackTrace.ToString(); - } - - public override string StackTrace => stackTrace; - public override string ToString() => $"{GetType().Name}: {Message}\r\n{StackTrace}"; - } } } From 49913f00f09a0ee4d6e83e93b58e253a70c6b2fc Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 25 Aug 2018 00:07:48 +0900 Subject: [PATCH 213/277] Fix xmldoc --- .../Beatmaps/Patterns/Legacy/PatternGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index 7a160ed389..05ca1d4365 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy } /// - /// Returns a random column index in the range [RandomStart, TotalColumns). + /// Returns a random column index in the range [, ). /// /// The minimum column index. If null, is used. /// The maximum column index. If null, is used. From 8204d3292eb607d6c55e21244ed53e13361865a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 Aug 2018 14:50:46 +0900 Subject: [PATCH 214/277] Log to correct file --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index d2be36e991..774a80049b 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -352,7 +352,7 @@ namespace osu.Game.Beatmaps string mapName = reader.Filenames.FirstOrDefault(f => f.EndsWith(".osu")); if (string.IsNullOrEmpty(mapName)) { - Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name})."); + Logger.Log($"No beatmap files found in the beatmap archive ({reader.Name}).", LoggingTarget.Database); return null; } From 5c7ff31675aa4e50f43469f7018b4a346984dd98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 25 Aug 2018 14:51:42 +0900 Subject: [PATCH 215/277] Add note about null return --- osu.Game/Database/ArchiveModelManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 42dd6684d5..326d042c39 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -390,7 +390,7 @@ namespace osu.Game.Database /// Actual expensive population should be done in ; this should just prepare for duplicate checking. /// /// The archive to create the model for. - /// A model populated with minimal information. + /// A model populated with minimal information. Returning a null will abort importing silently. protected abstract TModel CreateModel(ArchiveReader archive); /// From 21d5322899deede2d49e8327d1b13ae0a98e4dfa Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 27 Aug 2018 17:05:58 +0900 Subject: [PATCH 216/277] Update with async changes --- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 2 +- osu.Game/IO/Archives/ArchiveReader.cs | 7 +++++-- osu.Game/Skinning/LegacySkin.cs | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index c9389bb9e2..12b816184e 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Sprites protected override Drawable CreateFallbackCharacterDrawable() { - var tex = GetTextureForCharacter('?'); + var tex = GetTextureForCharacter('?').Result; if (tex != null) { diff --git a/osu.Game/IO/Archives/ArchiveReader.cs b/osu.Game/IO/Archives/ArchiveReader.cs index 808ce159bb..24a5094586 100644 --- a/osu.Game/IO/Archives/ArchiveReader.cs +++ b/osu.Game/IO/Archives/ArchiveReader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using osu.Framework.IO.Stores; namespace osu.Game.IO.Archives @@ -28,7 +29,9 @@ namespace osu.Game.IO.Archives public abstract IEnumerable Filenames { get; } - public virtual byte[] Get(string name) + public virtual byte[] Get(string name) => GetAsync(name).Result; + + public async Task GetAsync(string name) { using (Stream input = GetStream(name)) { @@ -36,7 +39,7 @@ namespace osu.Game.IO.Archives return null; byte[] buffer = new byte[input.Length]; - input.Read(buffer, 0, buffer.Length); + await input.ReadAsync(buffer, 0, buffer.Length); return buffer; } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 45c6ec80aa..f9801c2f92 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics; @@ -108,10 +109,12 @@ namespace osu.Game.Skinning return path == null ? null : underlyingStore.GetStream(path); } - byte[] IResourceStore.Get(string name) + byte[] IResourceStore.Get(string name) => GetAsync(name).Result; + + public async Task GetAsync(string name) { string path = getPathForFile(name); - return path == null ? null : underlyingStore.Get(path); + return path == null ? null : await underlyingStore.GetAsync(path); } #region IDisposable Support From 1b279d383f4e513c8b401b75402daf6ab3e8e604 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 27 Aug 2018 17:26:44 +0900 Subject: [PATCH 217/277] Use GetAsync on all textures --- osu.Desktop/Overlays/VersionManager.cs | 5 +++-- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 5 +++-- .../Objects/Drawables/Pieces/DefaultCirclePiece.cs | 5 +++-- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 5 +++-- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 11 ++++++----- osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 5 +++-- osu.Game/Graphics/Backgrounds/Background.cs | 5 +++-- osu.Game/Graphics/Cursor/MenuCursor.cs | 7 ++++--- osu.Game/Overlays/MedalOverlay.cs | 5 +++-- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 7 ++++--- osu.Game/Overlays/MusicController.cs | 4 ++-- osu.Game/Overlays/Profile/Components/GradeBadge.cs | 5 +++-- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 5 +++-- osu.Game/Overlays/Profile/ProfileHeader.cs | 5 +++-- .../Overlays/Profile/Sections/Recent/MedalIcon.cs | 5 +++-- .../Screens/Backgrounds/BackgroundScreenBeatmap.cs | 5 +++-- osu.Game/Screens/Menu/OsuLogo.cs | 7 ++++--- osu.Game/Screens/Play/KeyCounter.cs | 7 ++++--- osu.Game/Screens/Ranking/ResultsPageScore.cs | 5 +++-- osu.Game/Screens/Select/Leaderboards/DrawableRank.cs | 9 +++++---- .../Tournament/Components/VisualiserContainer.cs | 5 +++-- osu.Game/Screens/Tournament/Drawings.cs | 4 ++-- osu.Game/Screens/Tournament/Group.cs | 5 +++-- osu.Game/Screens/Tournament/ScrollingTeamContainer.cs | 5 +++-- osu.Game/Users/Avatar.cs | 7 ++++--- osu.Game/Users/Country.cs | 9 +++++---- osu.Game/Users/UserCoverBackground.cs | 5 +++-- osu.Game/osu.Game.csproj | 2 +- 28 files changed, 92 insertions(+), 67 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 1129969694..740ad7c3be 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -31,7 +32,7 @@ namespace osu.Desktop.Overlays public override bool HandleMouseInput => false; [BackgroundDependencyLoader] - private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host) + private async Task load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host) { notificationOverlay = notification; this.config = config; @@ -86,7 +87,7 @@ namespace osu.Desktop.Overlays { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Texture = textures.Get(@"Menu/dev-build-footer"), + Texture = await textures.GetAsync(@"Menu/dev-build-footer"), }, } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 4327abb96f..99d902d3e4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -448,9 +449,9 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); + Texture = await textures.GetAsync(@"Play/Catch/fruit-catcher-idle"); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs index 86b60c3443..c7c81756eb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public class DefaultCirclePiece : Container { [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { RelativeSizeAxes = Axes.Both; Children = new Drawable[] @@ -21,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = textures.Get(@"Play/osu/disc"), + Texture = await textures.GetAsync(@"Play/osu/disc"), }, new TrianglesPiece { diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index abcd1ddbda..4b981dc406 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Buffers; @@ -79,10 +80,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; [BackgroundDependencyLoader] - private void load(ShaderManager shaders, TextureStore textures) + private async Task load(ShaderManager shaders, TextureStore textures) { shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); - texture = textures.Get(@"Cursor/cursortrail"); + texture = await textures.GetAsync(@"Cursor/cursortrail"); Scale = new Vector2(1 / texture.ScaleAdjust); } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 524535bfde..f525ce0ff3 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -130,12 +131,12 @@ namespace osu.Game.Rulesets.Taiko.UI } [BackgroundDependencyLoader] - private void load(TextureStore textures, OsuColour colours) + private async Task load(TextureStore textures, OsuColour colours) { - rim.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer"); - rimHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer-hit"); - centre.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner"); - centreHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner-hit"); + rim.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer"); + rimHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer-hit"); + centre.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner"); + centreHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner-hit"); rimHit.Colour = colours.Blue; centreHit.Colour = colours.Pink; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index 883c05f1e4..9bba589f59 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -23,7 +24,7 @@ namespace osu.Game.Beatmaps.Drawables } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { string resource = null; @@ -41,7 +42,7 @@ namespace osu.Game.Beatmaps.Drawables } if (resource != null) - Texture = textures.Get(resource); + Texture = await textures.GetAsync(resource); } } diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index d5825a8c42..dcd1db56de 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -34,10 +35,10 @@ namespace osu.Game.Graphics.Backgrounds } [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) + private async Task load(LargeTextureStore textures) { if (!string.IsNullOrEmpty(textureName)) - Sprite.Texture = textures.Get(textureName); + Sprite.Texture = await textures.GetAsync(textureName); } } } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index b55e1aa5dd..92b45ebcb9 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using System; +using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework.Graphics.Textures; using osu.Framework.Input.EventArgs; @@ -132,7 +133,7 @@ namespace osu.Game.Graphics.Cursor } [BackgroundDependencyLoader] - private void load(OsuConfigManager config, TextureStore textures, OsuColour colour) + private async Task load(OsuConfigManager config, TextureStore textures, OsuColour colour) { Children = new Drawable[] { @@ -143,14 +144,14 @@ namespace osu.Game.Graphics.Cursor { new Sprite { - Texture = textures.Get(@"Cursor/menu-cursor"), + Texture = await textures.GetAsync(@"Cursor/menu-cursor"), }, AdditiveLayer = new Sprite { Blending = BlendingMode.Additive, Colour = colour.Pink, Alpha = 0, - Texture = textures.Get(@"Cursor/menu-cursor-additive"), + Texture = await textures.GetAsync(@"Cursor/menu-cursor-additive"), }, } } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index bd67a718a7..2ff0524880 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -20,6 +20,7 @@ using OpenTK.Input; using osu.Framework.Graphics.Shapes; using System; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Input.States; using osu.Framework.MathUtils; @@ -143,10 +144,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, TextureStore textures, AudioManager audio) + private async Task load(OsuColour colours, TextureStore textures, AudioManager audio) { getSample = audio.Sample.Get(@"MedalSplash/medal-get"); - innerSpin.Texture = outerSpin.Texture = textures.Get(@"MedalSplash/disc-spin"); + innerSpin.Texture = outerSpin.Texture = await textures.GetAsync(@"MedalSplash/disc-spin"); disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters { diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a27278e002..9ced6520df 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework; using OpenTK; using osu.Framework.Allocation; @@ -118,10 +119,10 @@ namespace osu.Game.Overlays.MedalSplash } [BackgroundDependencyLoader] - private void load(OsuColour colours, TextureStore textures) + private async Task load(OsuColour colours, TextureStore textures) { - medalSprite.Texture = textures.Get(medal.ImageUrl); - medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow"); + medalSprite.Texture = await textures.GetAsync(medal.ImageUrl); + medalGlow.Texture = await textures.GetAsync(@"MedalSplash/medal-glow"); description.Colour = colours.BlueLight; } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 886b5fb95b..42f89a4863 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -454,9 +454,9 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); + sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg4"); } } diff --git a/osu.Game/Overlays/Profile/Components/GradeBadge.cs b/osu.Game/Overlays/Profile/Components/GradeBadge.cs index 14a47e8d03..3943a5f86b 100644 --- a/osu.Game/Overlays/Profile/Components/GradeBadge.cs +++ b/osu.Game/Overlays/Profile/Components/GradeBadge.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -42,9 +43,9 @@ namespace osu.Game.Overlays.Profile.Components } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - badge.Texture = textures.Get($"Grades/{grade}"); + badge.Texture = await textures.GetAsync($"Grades/{grade}"); } } } diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index bfade5e45c..f87aefb28a 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -176,13 +177,13 @@ namespace osu.Game.Overlays.Profile.Header } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { Child = new Sprite { FillMode = FillMode.Fit, RelativeSizeAxes = Axes.Both, - Texture = textures.Get(badge.ImageUrl), + Texture = await textures.GetAsync(badge.ImageUrl), }; } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 9d09836d25..48048d2935 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -311,9 +312,9 @@ namespace osu.Game.Overlays.Profile } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - levelBadge.Texture = textures.Get(@"Profile/levelbadge"); + levelBadge.Texture = await textures.GetAsync(@"Profile/levelbadge"); } private User user; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 0d354c728f..2eec75c875 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -30,9 +31,9 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - sprite.Texture = textures.Get(url); + sprite.Texture = await textures.GetAsync(url); } } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 78561cecbf..14d4cab870 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; @@ -75,9 +76,9 @@ namespace osu.Game.Screens.Backgrounds } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - Sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); + Sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg1"); } } } diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index f0f765a4c9..fde32b31fd 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -253,13 +254,13 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private void load(TextureStore textures, AudioManager audio) + private async Task load(TextureStore textures, AudioManager audio) { sampleClick = audio.Sample.Get(@"Menu/osu-logo-select"); sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat"); - logo.Texture = textures.Get(@"Menu/logo"); - ripple.Texture = textures.Get(@"Menu/logo"); + logo.Texture = await textures.GetAsync(@"Menu/logo"); + ripple.Texture = await textures.GetAsync(@"Menu/logo"); } private int lastBeatIndex; diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 2c31e61114..49500a8426 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -61,19 +62,19 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { Children = new Drawable[] { buttonSprite = new Sprite { - Texture = textures.Get(@"KeyCounter/key-up"), + Texture = await textures.GetAsync(@"KeyCounter/key-up"), Anchor = Anchor.Centre, Origin = Anchor.Centre, }, glowSprite = new Sprite { - Texture = textures.Get(@"KeyCounter/key-glow"), + Texture = await textures.GetAsync(@"KeyCounter/key-glow"), Anchor = Anchor.Centre, Origin = Anchor.Centre, Alpha = 0 diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 42d8af07b9..87e53b8182 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -368,10 +369,10 @@ namespace osu.Game.Screens.Ranking } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { if (!string.IsNullOrEmpty(user.CoverUrl)) - cover.Texture = textures.Get(user.CoverUrl); + cover.Texture = await textures.GetAsync(user.CoverUrl); } } diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 0c4b369f36..f5f9ebbdaf 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,20 +36,20 @@ namespace osu.Game.Screens.Select.Leaderboards } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { this.textures = textures; - updateTexture(); + await updateTexture(); } - private void updateTexture() => rankSprite.Texture = textures.Get($@"Grades/{Rank.GetDescription()}"); + private async Task updateTexture() => rankSprite.Texture = await textures.GetAsync($@"Grades/{Rank.GetDescription()}"); public void UpdateRank(ScoreRank newRank) { Rank = newRank; if (LoadState >= LoadState.Ready) - updateTexture(); + updateTexture().Wait(); } } } diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs index 1453d4e78f..835b0757e0 100644 --- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs +++ b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.MathUtils; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace osu.Game.Screens.Tournament.Components { @@ -75,9 +76,9 @@ namespace osu.Game.Screens.Tournament.Components private int expiredCount; [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - texture = textures.Get("Drawings/visualiser-line"); + texture = await textures.GetAsync("Drawings/visualiser-line"); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 63d29d5cd7..20180a660f 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Tournament dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private void load(TextureStore textures, Storage storage) + private async Task load(TextureStore textures, Storage storage) { this.storage = storage; @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Tournament { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, - Texture = textures.Get(@"Backgrounds/Drawings/background.png") + Texture = await textures.GetAsync(@"Backgrounds/Drawings/background.png") }, new FillFlowContainer { diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game/Screens/Tournament/Group.cs index 6845d8fc48..5128166c15 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game/Screens/Tournament/Group.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -178,9 +179,9 @@ namespace osu.Game.Screens.Tournament } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); + flagSprite.Texture = await textures.GetAsync($@"Flags/{Team.FlagName}"); } } } diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index d1c7e0fced..cc9f805c62 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -372,9 +373,9 @@ namespace osu.Game.Screens.Tournament } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { - flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); + flagSprite.Texture = await textures.GetAsync($@"Flags/{Team.FlagName}"); } } } diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 9ba9549164..9aac662a84 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -24,14 +25,14 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); Texture texture = null; - if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); - if (texture == null) texture = textures.Get(@"Online/avatar-guest"); + if (user != null && user.Id > 1) texture = await textures.GetAsync($@"https://a.ppy.sh/{user.Id}"); + if (texture == null) texture = await textures.GetAsync(@"Online/avatar-guest"); Add(new Sprite { diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 80039eadad..a37ca10f9a 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -44,7 +45,7 @@ namespace osu.Game.Users country = value; if (LoadState >= LoadState.Ready) - sprite.Texture = getFlagTexture(); + sprite.Texture = getFlagTexture().Result; } } @@ -64,15 +65,15 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private void load(TextureStore ts) + private async Task load(TextureStore ts) { if (ts == null) throw new ArgumentNullException(nameof(ts)); textures = ts; - sprite.Texture = getFlagTexture(); + sprite.Texture = await getFlagTexture(); } - private Texture getFlagTexture() => textures.Get($@"Flags/{country?.FlagName ?? @"__"}"); + private async Task getFlagTexture() => await textures.GetAsync($@"Flags/{country?.FlagName ?? @"__"}"); } } diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 58b92b2750..97d2648e07 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -18,13 +19,13 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private async Task load(TextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); if (!string.IsNullOrEmpty(user.CoverUrl)) - Texture = textures.Get(user.CoverUrl); + Texture = await textures.GetAsync(user.CoverUrl); } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 69d242daa9..fce7cb73a2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From e7a5816d27a63dcabed1a6f6cc7e6fd49ad95a86 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 27 Aug 2018 17:30:16 +0900 Subject: [PATCH 218/277] Use GetAsync for all samples --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 7 ++++--- osu.Game/Graphics/ScreenshotManager.cs | 4 ++-- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 5 +++-- osu.Game/Graphics/UserInterface/HoverSounds.cs | 5 +++-- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 7 ++++--- osu.Game/Graphics/UserInterface/OsuMenu.cs | 7 ++++--- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 5 +++-- osu.Game/Overlays/MedalOverlay.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 ++++--- osu.Game/Screens/Menu/Button.cs | 7 ++++--- osu.Game/Screens/Menu/ButtonSystem.cs | 5 +++-- osu.Game/Screens/Menu/Intro.cs | 7 ++++--- osu.Game/Screens/Menu/OsuLogo.cs | 4 ++-- osu.Game/Screens/OsuScreen.cs | 5 +++-- osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Screens/Play/SkipOverlay.cs | 5 +++-- osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs | 5 +++-- osu.Game/Screens/Select/PlaySongSelect.cs | 4 ++-- osu.Game/Screens/Select/SongSelect.cs | 7 ++++--- 19 files changed, 58 insertions(+), 44 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index d2ab8441eb..effcc696ca 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -37,15 +38,15 @@ namespace osu.Game.Graphics.Containers } [BackgroundDependencyLoader(true)] - private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) + private async Task load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) { this.previewTrackManager = previewTrackManager; if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); - samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); - samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); + samplePopIn = await audio.Sample.GetAsync(@"UI/overlay-pop-in"); + samplePopOut = await audio.Sample.GetAsync(@"UI/overlay-pop-out"); StateChanged += onStateChanged; } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index bc30794298..63b97e3c59 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -42,7 +42,7 @@ namespace osu.Game.Graphics private SampleChannel shutter; [BackgroundDependencyLoader] - private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) + private async Task load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) { this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); @@ -51,7 +51,7 @@ namespace osu.Game.Graphics screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); - shutter = audio.Sample.Get("UI/shutter"); + shutter = await audio.Sample.GetAsync("UI/shutter"); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 27a06ba0b7..17924cdbb8 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -28,9 +29,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private async Task load(AudioManager audio) { - sampleClick = audio.Sample.Get($@"UI/generic-select{SampleSet.GetDescription()}"); + sampleClick = await audio.Sample.GetAsync($@"UI/generic-select{SampleSet.GetDescription()}"); } } } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index 821305bc92..b3a83d1cc8 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -35,9 +36,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private async Task load(AudioManager audio) { - sampleHover = audio.Sample.Get($@"UI/generic-hover{SampleSet.GetDescription()}"); + sampleHover = await audio.Sample.GetAsync($@"UI/generic-hover{SampleSet.GetDescription()}"); } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 68f59bd8cd..d6b4b51851 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -110,10 +111,10 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private async Task load(AudioManager audio) { - sampleChecked = audio.Sample.Get(@"UI/check-on"); - sampleUnchecked = audio.Sample.Get(@"UI/check-off"); + sampleChecked = await audio.Sample.GetAsync(@"UI/check-on"); + sampleUnchecked = await audio.Sample.GetAsync(@"UI/check-off"); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index abb077e94f..b5ebac0c74 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -69,10 +70,10 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private async Task load(AudioManager audio) { - sampleHover = audio.Sample.Get(@"UI/generic-hover"); - sampleClick = audio.Sample.Get(@"UI/generic-select"); + sampleHover = await audio.Sample.GetAsync(@"UI/generic-hover"); + sampleClick = await audio.Sample.GetAsync(@"UI/generic-select"); BackgroundColour = Color4.Transparent; BackgroundColourHover = OsuColour.FromHex(@"172023"); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index b7b5319e06..cd0b3dcad2 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -3,6 +3,7 @@ using System; using System.Globalization; +using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -119,9 +120,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) + private async Task load(AudioManager audio, OsuColour colours) { - sample = audio.Sample.Get(@"UI/sliderbar-notch"); + sample = await audio.Sample.GetAsync(@"UI/sliderbar-notch"); AccentColour = colours.Pink; } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 2ff0524880..038fa936b0 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -146,7 +146,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private async Task load(OsuColour colours, TextureStore textures, AudioManager audio) { - getSample = audio.Sample.Get(@"MedalSplash/medal-get"); + getSample = await audio.Sample.GetAsync(@"MedalSplash/medal-get"); innerSpin.Texture = outerSpin.Texture = await textures.GetAsync(@"MedalSplash/disc-spin"); disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index e83dedaf35..783fcfa090 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Shapes; @@ -49,7 +50,7 @@ namespace osu.Game.Overlays.Mods protected readonly IBindable Ruleset = new Bindable(); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) + private async Task load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; @@ -58,8 +59,8 @@ namespace osu.Game.Overlays.Mods Ruleset.BindTo(ruleset); if (selectedMods != null) SelectedMods.BindTo(selectedMods); - sampleOn = audio.Sample.Get(@"UI/check-on"); - sampleOff = audio.Sample.Get(@"UI/check-off"); + sampleOn = await audio.Sample.GetAsync(@"UI/check-on"); + sampleOff = await audio.Sample.GetAsync(@"UI/check-off"); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index e53905a102..3593568578 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -179,11 +180,11 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private async Task load(AudioManager audio) { - sampleHover = audio.Sample.Get(@"Menu/button-hover"); + sampleHover = await audio.Sample.GetAsync(@"Menu/button-hover"); if (!string.IsNullOrEmpty(sampleName)) - sampleClick = audio.Sample.Get($@"Menu/{sampleName}"); + sampleClick = await audio.Sample.GetAsync($@"Menu/{sampleName}"); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index b9a799328e..4137028527 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -102,10 +103,10 @@ namespace osu.Game.Screens.Menu private OsuGame game; [BackgroundDependencyLoader(true)] - private void load(AudioManager audio, OsuGame game) + private async Task load(AudioManager audio, OsuGame game) { this.game = game; - sampleBack = audio.Sample.Get(@"Menu/button-back-select"); + sampleBack = await audio.Sample.GetAsync(@"Menu/button-back-select"); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index c1032011f7..5d39d70e26 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -47,7 +48,7 @@ namespace osu.Game.Screens.Menu private WorkingBeatmap introBeatmap; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) + private async Task load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) { this.beatmap.BindTo(beatmap); @@ -80,8 +81,8 @@ namespace osu.Game.Screens.Menu introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); track = introBeatmap.Track; - welcome = audio.Sample.Get(@"welcome"); - seeya = audio.Sample.Get(@"seeya"); + welcome = await audio.Sample.GetAsync(@"welcome"); + seeya = await audio.Sample.GetAsync(@"seeya"); } private const double delay_step_one = 2300; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index fde32b31fd..c6cfd9ba2d 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -256,8 +256,8 @@ namespace osu.Game.Screens.Menu [BackgroundDependencyLoader] private async Task load(TextureStore textures, AudioManager audio) { - sampleClick = audio.Sample.Get(@"Menu/osu-logo-select"); - sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat"); + sampleClick = await audio.Sample.GetAsync(@"Menu/osu-logo-select"); + sampleBeat = await audio.Sample.GetAsync(@"Menu/osu-logo-heartbeat"); logo.Texture = await textures.GetAsync(@"Menu/logo"); ripple.Texture = await textures.GetAsync(@"Menu/logo"); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 4b893f0118..3929e631cf 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -80,7 +81,7 @@ namespace osu.Game.Screens private SampleChannel sampleExit; [BackgroundDependencyLoader(true)] - private void load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable ruleset) + private async Task load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable ruleset) { Beatmap.BindTo(beatmap); Ruleset.BindTo(ruleset); @@ -98,7 +99,7 @@ namespace osu.Game.Screens }; } - sampleExit = audio.Sample.Get(@"UI/screen-back"); + sampleExit = await audio.Sample.GetAsync(@"UI/screen-back"); } public virtual bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5ad0130fd7..863d12c1c2 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Play public bool LoadedBeatmapSuccessfully => RulesetContainer?.Objects.Any() == true; [BackgroundDependencyLoader] - private void load(AudioManager audio, APIAccess api, OsuConfigManager config) + private async Task load(AudioManager audio, APIAccess api, OsuConfigManager config) { this.api = api; @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play if (working is DummyWorkingBeatmap) return; - sampleRestart = audio.Sample.Get(@"Gameplay/restart"); + sampleRestart = await audio.Sample.GetAsync(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 06837c9274..9aaaa6152c 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -224,12 +225,12 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private void load(OsuColour colours, AudioManager audio) + private async Task load(OsuColour colours, AudioManager audio) { colourNormal = colours.Yellow; colourHover = colours.YellowDark; - sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + sampleConfirm = await audio.Sample.GetAsync(@"SongSelect/confirm-selection"); Children = new Drawable[] { diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 8a0052559e..b252f116ac 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -45,7 +46,7 @@ namespace osu.Game.Screens.Select.Carousel private SampleChannel sampleHover; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) + private async Task load(AudioManager audio, OsuColour colours) { InternalChild = borderContainer = new Container { @@ -68,7 +69,7 @@ namespace osu.Game.Screens.Select.Carousel } }; - sampleHover = audio.Sample.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); + sampleHover = await audio.Sample.GetAsync($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); hoverLayer.Colour = colours.Blue.Opacity(0.1f); } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index e914eb365e..cab7bdfe73 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -55,11 +55,11 @@ namespace osu.Game.Screens.Select private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) + private async Task load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) { if (selectedMods != null) this.selectedMods.BindTo(selectedMods); - sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + sampleConfirm = await audio.Sample.GetAsync(@"SongSelect/confirm-selection"); Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index dcc0760262..ef03aff107 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using OpenTK; using OpenTK.Input; using osu.Framework.Allocation; @@ -198,7 +199,7 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) + private async Task load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) { if (Footer != null) { @@ -218,8 +219,8 @@ namespace osu.Game.Screens.Select dialogOverlay = dialog; - sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); - sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); + sampleChangeDifficulty = await audio.Sample.GetAsync(@"SongSelect/select-difficulty"); + sampleChangeBeatmap = await audio.Sample.GetAsync(@"SongSelect/select-expand"); Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable(); } From 0d4aa37a91b7ac4c7a18bd4f01c92a32e4184e1e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 28 Aug 2018 00:59:30 +0900 Subject: [PATCH 219/277] Fix order of import set conflict checks --- osu.Game/Beatmaps/BeatmapManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 774a80049b..4f03cffc0c 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -103,6 +103,11 @@ namespace osu.Game.Beatmaps b.BeatmapSet = beatmapSet; } + validateOnlineIds(beatmapSet.Beatmaps); + + foreach (BeatmapInfo b in beatmapSet.Beatmaps) + fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps); + // check if a set already exists with the same online id, delete if it does. if (beatmapSet.OnlineBeatmapSetID != null) { @@ -114,11 +119,6 @@ namespace osu.Game.Beatmaps Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database); } } - - validateOnlineIds(beatmapSet.Beatmaps); - - foreach (BeatmapInfo b in beatmapSet.Beatmaps) - fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps); } private void validateOnlineIds(List beatmaps) From da2f04c79c3c6f5bb1b4543a3200e6e8eea65351 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 28 Aug 2018 16:07:52 +0900 Subject: [PATCH 220/277] Update framework once more --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fce7cb73a2..0633d7913e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 919e78a89ac6e7cbb8d1e23e175fd489ba7ce106 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Aug 2018 01:42:25 +0900 Subject: [PATCH 221/277] Attempt to fix cross-thread database usage --- osu.Game/Screens/Select/BeatmapCarousel.cs | 50 ++++++++++++---------- osu.Game/Screens/Select/SongSelect.cs | 2 +- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 6e4454a311..7bb0b95b9a 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -64,32 +64,36 @@ namespace osu.Game.Screens.Select public IEnumerable BeatmapSets { - get { return beatmapSets.Select(g => g.BeatmapSet); } - set + get => beatmapSets.Select(g => g.BeatmapSet); + set => loadBeatmapSets(() => value); + } + + public void LoadBeatmapSetsFromManager(BeatmapManager manager) => loadBeatmapSets(manager.GetAllUsableBeatmapSetsEnumerable); + + private void loadBeatmapSets(Func> beatmapSets) + { + CarouselRoot newRoot = new CarouselRoot(this); + + Task.Run(() => { - CarouselRoot newRoot = new CarouselRoot(this); + beatmapSets().Select(createCarouselSet).Where(g => g != null).ForEach(newRoot.AddChild); + newRoot.Filter(activeCriteria); - Task.Run(() => + // preload drawables as the ctor overhead is quite high currently. + var _ = newRoot.Drawables; + }).ContinueWith(_ => Schedule(() => + { + root = newRoot; + scrollableContent.Clear(false); + itemsCache.Invalidate(); + scrollPositionCache.Invalidate(); + + Schedule(() => { - value.Select(createCarouselSet).Where(g => g != null).ForEach(newRoot.AddChild); - newRoot.Filter(activeCriteria); - - // preload drawables as the ctor overhead is quite high currently. - var _ = newRoot.Drawables; - }).ContinueWith(_ => Schedule(() => - { - root = newRoot; - scrollableContent.Clear(false); - itemsCache.Invalidate(); - scrollPositionCache.Invalidate(); - - Schedule(() => - { - BeatmapSetsChanged?.Invoke(); - initialLoadComplete = true; - }); - })); - } + BeatmapSetsChanged?.Invoke(); + initialLoadComplete = true; + }); + })); } private readonly List yPositions = new List(); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ef03aff107..ac765c46ab 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -222,7 +222,7 @@ namespace osu.Game.Screens.Select sampleChangeDifficulty = await audio.Sample.GetAsync(@"SongSelect/select-difficulty"); sampleChangeBeatmap = await audio.Sample.GetAsync(@"SongSelect/select-expand"); - Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSetsEnumerable(); + Carousel.LoadBeatmapSetsFromManager(this.beatmaps); } public void Edit(BeatmapInfo beatmap) From 73c764d9831d17b8186771cd0a1d40a2be97a5eb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Aug 2018 03:36:01 +0900 Subject: [PATCH 222/277] Update SpriteIcon --- osu.Game/Graphics/SpriteIcon.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 6acd20719e..24b3f37505 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -24,7 +25,7 @@ namespace osu.Game.Graphics private FontStore store; [BackgroundDependencyLoader] - private void load(FontStore store) + private async Task load(FontStore store) { this.store = store; @@ -55,23 +56,23 @@ namespace osu.Game.Graphics }, }; - updateTexture(); + await updateTexture(); } protected override void LoadComplete() { base.LoadComplete(); - updateTexture(); + updateTexture().Wait(); } private FontAwesome loadedIcon; - private void updateTexture() + private async Task updateTexture() { var loadableIcon = icon; if (loadableIcon == loadedIcon) return; - var texture = store?.Get(((char)loadableIcon).ToString()); + var texture = await store.GetAsync(((char)loadableIcon).ToString()); spriteMain.Texture = texture; spriteShadow.Texture = texture; @@ -129,8 +130,8 @@ namespace osu.Game.Graphics if (icon == value) return; icon = value; - if (IsLoaded) - updateTexture(); + if (LoadState == LoadState.Loaded) + updateTexture().Wait(); } } } From 4b54c65d3f5a737c3a1634ee6c88bffcb8b4f937 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Aug 2018 15:11:02 +0900 Subject: [PATCH 223/277] Fix single file component loading not actually working correctly --- osu.Game/OsuGame.cs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 94678a9dde..f4afd23c1b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -506,22 +506,24 @@ namespace osu.Game // we could avoid the need for scheduling altogether. Schedule(() => { - if (asyncLoadStream != null) + var previousLoadStream = asyncLoadStream; + + //chain with existing load stream + asyncLoadStream = Task.Run(async () => { - //chain with existing load stream - asyncLoadStream = asyncLoadStream.ContinueWith(async t => + if (previousLoadStream != null) + await previousLoadStream; + + try { - try - { - await LoadComponentAsync(d, add); - } - catch (OperationCanceledException) - { - } - }); - } - else - asyncLoadStream = LoadComponentAsync(d, add); + Logger.Log($"{d}...", LoggingTarget.Debug); + await LoadComponentAsync(d, add); + Logger.Log($"{d} ✓", LoggingTarget.Debug); + } + catch (OperationCanceledException) + { + } + }); }); } From 499c5d28ffb09d1047e57d3c16f90227429a82ee Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Aug 2018 18:04:51 -0400 Subject: [PATCH 224/277] Refactored variable names in OsuGame.cs for improved code readability. --- osu.Game/OsuGame.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 94678a9dde..102df75420 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -75,10 +75,10 @@ namespace osu.Game { get { - Screen s = screenStack; - while (s != null && !(s is Intro)) - s = s.ChildScreen; - return s as Intro; + Screen screen = screenStack; + while (screen != null && !(screen is Intro)) + screen = screen.ChildScreen; + return screen as Intro; } } @@ -126,8 +126,8 @@ namespace osu.Game /// Whether the toolbar should also be hidden. public void CloseAllOverlays(bool toolbar = true) { - foreach (var o in overlays) - o.State = Visibility.Hidden; + foreach (var overlay in overlays) + overlay.State = Visibility.Hidden; if (toolbar) Toolbar.State = Visibility.Hidden; } @@ -244,7 +244,7 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); - protected void LoadScore(Score s) + protected void LoadScore(Score score) { scoreLoad?.Cancel(); @@ -252,18 +252,18 @@ namespace osu.Game if (menu == null) { - scoreLoad = Schedule(() => LoadScore(s)); + scoreLoad = Schedule(() => LoadScore(score)); return; } if (!menu.IsCurrentScreen) { menu.MakeCurrent(); - this.Delay(500).Schedule(() => LoadScore(s), out scoreLoad); + this.Delay(500).Schedule(() => LoadScore(score), out scoreLoad); return; } - if (s.Beatmap == null) + if (score.Beatmap == null) { notifications.Post(new SimpleNotification { @@ -273,12 +273,12 @@ namespace osu.Game return; } - ruleset.Value = s.Ruleset; + ruleset.Value = score.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(s.Beatmap); - Beatmap.Value.Mods.Value = s.Mods; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.Beatmap); + Beatmap.Value.Mods.Value = score.Mods; - menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay))); + menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); } protected override void Dispose(bool isDisposing) From 20817fdf1dc63cd7a378b8805185dc7a398bd48b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Aug 2018 11:58:30 +0900 Subject: [PATCH 225/277] Avoid using symbol windows can't diplay --- osu.Game/OsuGame.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f4afd23c1b..78c6fa052b 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -516,9 +516,9 @@ namespace osu.Game try { - Logger.Log($"{d}...", LoggingTarget.Debug); + Logger.Log($"Loading {d}...", LoggingTarget.Debug); await LoadComponentAsync(d, add); - Logger.Log($"{d} ✓", LoggingTarget.Debug); + Logger.Log($"Loaded {d}!", LoggingTarget.Debug); } catch (OperationCanceledException) { From 327bc708d7ed5a12cdafbdae4aa7a662523ae097 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 29 Aug 2018 15:56:24 +0900 Subject: [PATCH 226/277] Fix DirectOverlay performing webrequests on startup --- osu.Game/Overlays/DirectOverlay.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 423211659d..f63d314053 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -240,6 +240,15 @@ namespace osu.Game.Overlays }); } + protected override void PopIn() + { + base.PopIn(); + + // Queries are allowed to be run only on the first pop-in + if (getSetsRequest == null) + Scheduler.AddOnce(updateSearch); + } + private SearchBeatmapSetsRequest getSetsRequest; private readonly Bindable currentQuery = new Bindable(); @@ -251,16 +260,22 @@ namespace osu.Game.Overlays { queryChangedDebounce?.Cancel(); - if (!IsLoaded) return; + if (!IsLoaded) + return; + + if (State == Visibility.Hidden) + return; BeatmapSets = null; ResultAmounts = null; getSetsRequest?.Cancel(); - if (api == null) return; + if (api == null) + return; - if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; + if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) + return; previewTrackManager.StopAnyPlaying(this); From b1a3dfedd1f0f809da4365a8a09041d311d55266 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 29 Aug 2018 20:57:48 +0900 Subject: [PATCH 227/277] Reduce async-await pairs --- osu.Game/Beatmaps/BeatmapManager.cs | 6 +++--- osu.Game/Beatmaps/WorkingBeatmap.cs | 12 ++++++------ osu.Game/Graphics/ScreenshotManager.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 774a80049b..1adbb4a389 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -319,17 +319,17 @@ namespace osu.Game.Beatmaps /// /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. /// - public async Task ImportFromStable() + public Task ImportFromStable() { var stable = GetStableStorage?.Invoke(); if (stable == null) { Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error); - return; + return Task.CompletedTask; } - await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); + return Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); } /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 6c906bb1e4..085c591fce 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -67,7 +67,7 @@ namespace osu.Game.Beatmaps public bool BeatmapLoaded => beatmap.IsResultAvailable; public IBeatmap Beatmap => beatmap.Value.Result; - public async Task GetBeatmapAsync() => await beatmap.Value; + public Task GetBeatmapAsync() => beatmap.Value; private readonly AsyncLazy beatmap; private IBeatmap populateBeatmap() @@ -138,14 +138,14 @@ namespace osu.Game.Beatmaps public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value.Result; - public async Task GetBackgroundAsync() => await background.Value; + public Task GetBackgroundAsync() => background.Value; private AsyncLazy background; private Texture populateBackground() => GetBackground(); public bool TrackLoaded => track.IsResultAvailable; public Track Track => track.Value.Result; - public async Task GetTrackAsync() => await track.Value; + public Task GetTrackAsync() => track.Value; private AsyncLazy track; private Track populateTrack() @@ -158,21 +158,21 @@ namespace osu.Game.Beatmaps public bool WaveformLoaded => waveform.IsResultAvailable; public Waveform Waveform => waveform.Value.Result; - public async Task GetWaveformAsync() => await waveform.Value; + public Task GetWaveformAsync() => waveform.Value; private readonly AsyncLazy waveform; private Waveform populateWaveform() => GetWaveform(); public bool StoryboardLoaded => storyboard.IsResultAvailable; public Storyboard Storyboard => storyboard.Value.Result; - public async Task GetStoryboardAsync() => await storyboard.Value; + public Task GetStoryboardAsync() => storyboard.Value; private readonly AsyncLazy storyboard; private Storyboard populateStoryboard() => GetStoryboard(); public bool SkinLoaded => skin.IsResultAvailable; public Skin Skin => skin.Value.Result; - public async Task GetSkinAsync() => await skin.Value; + public Task GetSkinAsync() => skin.Value; private readonly AsyncLazy skin; private Skin populateSkin() => GetSkin(); diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 63b97e3c59..8426dc995b 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -71,7 +71,7 @@ namespace osu.Game.Graphics private volatile int screenShotTasks; - public async Task TakeScreenshotAsync() => await Task.Run(async () => + public Task TakeScreenshotAsync() => Task.Run(async () => { Interlocked.Increment(ref screenShotTasks); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index f9801c2f92..9c881c6abb 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -111,10 +111,10 @@ namespace osu.Game.Skinning byte[] IResourceStore.Get(string name) => GetAsync(name).Result; - public async Task GetAsync(string name) + public Task GetAsync(string name) { string path = getPathForFile(name); - return path == null ? null : await underlyingStore.GetAsync(path); + return path == null ? Task.FromResult(null) : underlyingStore.GetAsync(path); } #region IDisposable Support From 68a79f895a3e4e5d4473c0b9490b638ec1e09ecc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Aug 2018 13:30:23 +0900 Subject: [PATCH 228/277] Fix mania throwing an exception on start of map --- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 4 ++-- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- osu.Game/Rulesets/UI/Playfield.cs | 14 +++++++------- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 +- .../Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 6bf63443b5..999f84ed8e 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -26,11 +26,11 @@ namespace osu.Game.Rulesets.Mania.UI throw new ArgumentException("Can't have zero or fewer stages."); GridContainer playfieldGrid; - InternalChild = playfieldGrid = new GridContainer + AddInternal(playfieldGrid = new GridContainer { RelativeSizeAxes = Axes.Both, Content = new[] { new Drawable[stageDefinitions.Count] } - }; + }); var normalColumnAction = ManiaAction.Key1; var specialColumnAction = ManiaAction.Special1; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 4047e057cb..f3b7d60cf0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Mods const float relax_leniency = 3; - foreach (var drawable in playfield.HitObjects.AliveObjects) + foreach (var drawable in playfield.HitObjectContainer.AliveObjects) { if (!(drawable is DrawableOsuHitObject osuHit)) continue; diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 703d8764fc..61937a535c 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.UI public override void PostProcess() { - connectionLayer.HitObjects = HitObjects.Objects.Select(d => d.HitObject).OfType(); + connectionLayer.HitObjects = HitObjectContainer.Objects.Select(d => d.HitObject).OfType(); } private void onNewResult(DrawableHitObject judgedObject, JudgementResult result) diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index da14fb54d6..e090a18eda 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -19,12 +19,12 @@ namespace osu.Game.Rulesets.UI /// /// The contained in this Playfield. /// - public HitObjectContainer HitObjects { get; private set; } + public HitObjectContainer HitObjectContainer { get; private set; } /// /// All the s contained in this and all . /// - public IEnumerable AllHitObjects => HitObjects?.Objects.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects)) ?? Enumerable.Empty(); + public IEnumerable AllHitObjects => HitObjectContainer?.Objects.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects)) ?? Enumerable.Empty(); /// /// All s nested inside this . @@ -60,10 +60,10 @@ namespace osu.Game.Rulesets.UI { this.beatmap = beatmap.Value; - HitObjects = CreateHitObjectContainer(); - HitObjects.RelativeSizeAxes = Axes.Both; + HitObjectContainer = CreateHitObjectContainer(); + HitObjectContainer.RelativeSizeAxes = Axes.Both; - Add(HitObjects); + Add(HitObjectContainer); } /// @@ -75,13 +75,13 @@ namespace osu.Game.Rulesets.UI /// Adds a DrawableHitObject to this Playfield. /// /// The DrawableHitObject to add. - public virtual void Add(DrawableHitObject h) => HitObjects.Add(h); + public virtual void Add(DrawableHitObject h) => HitObjectContainer.Add(h); /// /// Remove a DrawableHitObject from this Playfield. /// /// The DrawableHitObject to remove. - public virtual void Remove(DrawableHitObject h) => HitObjects.Remove(h); + public virtual void Remove(DrawableHitObject h) => HitObjectContainer.Remove(h); /// /// Registers a as a nested . diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 64ee680d45..a830803fb1 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -306,7 +306,7 @@ namespace osu.Game.Rulesets.UI Playfield.PostProcess(); foreach (var mod in Mods.OfType()) - mod.ApplyToDrawableHitObjects(Playfield.HitObjects.Objects); + mod.ApplyToDrawableHitObjects(Playfield.HitObjectContainer.Objects); } protected override void Update() diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 7146ad8064..ec73c0fb14 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.UI.Scrolling /// /// The container that contains the s. /// - public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)HitObjectContainer; /// /// The direction in which s in this should scroll. From 9fb78852de5d27772c151a495f02964eb606d6e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Aug 2018 14:45:04 +0900 Subject: [PATCH 229/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 0633d7913e..5cde8c87d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 3276f0f54d9ae0be4bdb24de5b633bd7c22cc357 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 30 Aug 2018 14:48:06 +0900 Subject: [PATCH 230/277] Update ef/sqlite version --- osu.Desktop/osu.Desktop.csproj | 4 ++-- osu.Game/osu.Game.csproj | 4 ++-- osu.TestProject.props | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 180abd7fec..e2fc4d14f6 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -28,8 +28,8 @@ - - + + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5cde8c87d1..2e7877f5ce 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/osu.TestProject.props b/osu.TestProject.props index a73a4f8ce2..58de6ec030 100644 --- a/osu.TestProject.props +++ b/osu.TestProject.props @@ -11,7 +11,7 @@ - + From 03084aa04ba7d09ebe4b9d3eda443769d6d51b3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Aug 2018 07:04:40 +0900 Subject: [PATCH 231/277] Revert async changes --- osu.Desktop/Overlays/VersionManager.cs | 5 ++--- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 5 ++--- .../Objects/Drawables/Pieces/DefaultCirclePiece.cs | 5 ++--- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 5 ++--- osu.Game.Rulesets.Taiko/UI/InputDrum.cs | 11 +++++------ osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs | 5 ++--- osu.Game/Graphics/Backgrounds/Background.cs | 5 ++--- .../Containers/OsuFocusedOverlayContainer.cs | 7 +++---- osu.Game/Graphics/Cursor/MenuCursor.cs | 7 +++---- osu.Game/Graphics/ScreenshotManager.cs | 4 ++-- osu.Game/Graphics/SpriteIcon.cs | 13 ++++++------- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 2 +- osu.Game/Graphics/UserInterface/HoverClickSounds.cs | 5 ++--- osu.Game/Graphics/UserInterface/HoverSounds.cs | 5 ++--- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 7 +++---- osu.Game/Graphics/UserInterface/OsuMenu.cs | 7 +++---- osu.Game/Graphics/UserInterface/OsuSliderBar.cs | 5 ++--- osu.Game/Overlays/MedalOverlay.cs | 7 +++---- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 7 +++---- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 7 +++---- osu.Game/Overlays/MusicController.cs | 4 ++-- osu.Game/Overlays/Profile/Components/GradeBadge.cs | 5 ++--- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 5 ++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 5 ++--- .../Overlays/Profile/Sections/Recent/MedalIcon.cs | 5 ++--- .../Screens/Backgrounds/BackgroundScreenBeatmap.cs | 5 ++--- osu.Game/Screens/Menu/Button.cs | 7 +++---- osu.Game/Screens/Menu/ButtonSystem.cs | 5 ++--- osu.Game/Screens/Menu/Intro.cs | 7 +++---- osu.Game/Screens/Menu/OsuLogo.cs | 11 +++++------ osu.Game/Screens/OsuScreen.cs | 5 ++--- osu.Game/Screens/Play/KeyCounter.cs | 7 +++---- osu.Game/Screens/Play/Player.cs | 4 ++-- osu.Game/Screens/Play/SkipOverlay.cs | 5 ++--- osu.Game/Screens/Ranking/ResultsPageScore.cs | 5 ++--- .../Screens/Select/Carousel/DrawableCarouselItem.cs | 5 ++--- .../Screens/Select/Leaderboards/DrawableRank.cs | 12 +++++++----- osu.Game/Screens/Select/PlaySongSelect.cs | 4 ++-- osu.Game/Screens/Select/SongSelect.cs | 7 +++---- .../Tournament/Components/VisualiserContainer.cs | 5 ++--- osu.Game/Screens/Tournament/Drawings.cs | 4 ++-- osu.Game/Screens/Tournament/Group.cs | 5 ++--- .../Screens/Tournament/ScrollingTeamContainer.cs | 5 ++--- osu.Game/Users/Avatar.cs | 7 +++---- osu.Game/Users/Country.cs | 9 ++++----- osu.Game/Users/UserCoverBackground.cs | 5 ++--- 46 files changed, 120 insertions(+), 157 deletions(-) diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 740ad7c3be..1129969694 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -32,7 +31,7 @@ namespace osu.Desktop.Overlays public override bool HandleMouseInput => false; [BackgroundDependencyLoader] - private async Task load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host) + private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host) { notificationOverlay = notification; this.config = config; @@ -87,7 +86,7 @@ namespace osu.Desktop.Overlays { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Texture = await textures.GetAsync(@"Menu/dev-build-footer"), + Texture = textures.Get(@"Menu/dev-build-footer"), }, } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 99d902d3e4..4327abb96f 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -449,9 +448,9 @@ namespace osu.Game.Rulesets.Catch.UI } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - Texture = await textures.GetAsync(@"Play/Catch/fruit-catcher-idle"); + Texture = textures.Get(@"Play/Catch/fruit-catcher-idle"); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs index c7c81756eb..86b60c3443 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/DefaultCirclePiece.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -13,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public class DefaultCirclePiece : Container { [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { RelativeSizeAxes = Axes.Both; Children = new Drawable[] @@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Texture = await textures.GetAsync(@"Play/osu/disc"), + Texture = textures.Get(@"Play/osu/disc"), }, new TrianglesPiece { diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 4b981dc406..abcd1ddbda 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.OpenGL.Buffers; @@ -80,10 +79,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; [BackgroundDependencyLoader] - private async Task load(ShaderManager shaders, TextureStore textures) + private void load(ShaderManager shaders, TextureStore textures) { shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); - texture = await textures.GetAsync(@"Cursor/cursortrail"); + texture = textures.Get(@"Cursor/cursortrail"); Scale = new Vector2(1 / texture.ScaleAdjust); } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index f525ce0ff3..524535bfde 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -131,12 +130,12 @@ namespace osu.Game.Rulesets.Taiko.UI } [BackgroundDependencyLoader] - private async Task load(TextureStore textures, OsuColour colours) + private void load(TextureStore textures, OsuColour colours) { - rim.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer"); - rimHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer-hit"); - centre.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner"); - centreHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner-hit"); + rim.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer"); + rimHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer-hit"); + centre.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner"); + centreHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner-hit"); rimHit.Colour = colours.Blue; centreHit.Colour = colours.Pink; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index 9bba589f59..883c05f1e4 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -24,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { string resource = null; @@ -42,7 +41,7 @@ namespace osu.Game.Beatmaps.Drawables } if (resource != null) - Texture = await textures.GetAsync(resource); + Texture = textures.Get(resource); } } diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index dcd1db56de..d5825a8c42 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -35,10 +34,10 @@ namespace osu.Game.Graphics.Backgrounds } [BackgroundDependencyLoader] - private async Task load(LargeTextureStore textures) + private void load(LargeTextureStore textures) { if (!string.IsNullOrEmpty(textureName)) - Sprite.Texture = await textures.GetAsync(textureName); + Sprite.Texture = textures.Get(textureName); } } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index effcc696ca..d2ab8441eb 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -38,15 +37,15 @@ namespace osu.Game.Graphics.Containers } [BackgroundDependencyLoader(true)] - private async Task load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) + private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager) { this.previewTrackManager = previewTrackManager; if (osuGame != null) OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); - samplePopIn = await audio.Sample.GetAsync(@"UI/overlay-pop-in"); - samplePopOut = await audio.Sample.GetAsync(@"UI/overlay-pop-out"); + samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in"); + samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out"); StateChanged += onStateChanged; } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 92b45ebcb9..b55e1aa5dd 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using System; -using System.Threading.Tasks; using JetBrains.Annotations; using osu.Framework.Graphics.Textures; using osu.Framework.Input.EventArgs; @@ -133,7 +132,7 @@ namespace osu.Game.Graphics.Cursor } [BackgroundDependencyLoader] - private async Task load(OsuConfigManager config, TextureStore textures, OsuColour colour) + private void load(OsuConfigManager config, TextureStore textures, OsuColour colour) { Children = new Drawable[] { @@ -144,14 +143,14 @@ namespace osu.Game.Graphics.Cursor { new Sprite { - Texture = await textures.GetAsync(@"Cursor/menu-cursor"), + Texture = textures.Get(@"Cursor/menu-cursor"), }, AdditiveLayer = new Sprite { Blending = BlendingMode.Additive, Colour = colour.Pink, Alpha = 0, - Texture = await textures.GetAsync(@"Cursor/menu-cursor-additive"), + Texture = textures.Get(@"Cursor/menu-cursor-additive"), }, } } diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 8426dc995b..be253f65c1 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -42,7 +42,7 @@ namespace osu.Game.Graphics private SampleChannel shutter; [BackgroundDependencyLoader] - private async Task load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) + private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio) { this.host = host; this.storage = storage.GetStorageForDirectory(@"screenshots"); @@ -51,7 +51,7 @@ namespace osu.Game.Graphics screenshotFormat = config.GetBindable(OsuSetting.ScreenshotFormat); captureMenuCursor = config.GetBindable(OsuSetting.ScreenshotCaptureMenuCursor); - shutter = await audio.Sample.GetAsync("UI/shutter"); + shutter = audio.Sample.Get("UI/shutter"); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 24b3f37505..b72ba7e02f 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -25,7 +24,7 @@ namespace osu.Game.Graphics private FontStore store; [BackgroundDependencyLoader] - private async Task load(FontStore store) + private void load(FontStore store) { this.store = store; @@ -56,23 +55,23 @@ namespace osu.Game.Graphics }, }; - await updateTexture(); + updateTexture(); } protected override void LoadComplete() { base.LoadComplete(); - updateTexture().Wait(); + updateTexture(); } private FontAwesome loadedIcon; - private async Task updateTexture() + private void updateTexture() { var loadableIcon = icon; if (loadableIcon == loadedIcon) return; - var texture = await store.GetAsync(((char)loadableIcon).ToString()); + var texture = store.Get(((char)loadableIcon).ToString()); spriteMain.Texture = texture; spriteShadow.Texture = texture; @@ -131,7 +130,7 @@ namespace osu.Game.Graphics icon = value; if (LoadState == LoadState.Loaded) - updateTexture().Wait(); + updateTexture(); } } } diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index 12b816184e..c9389bb9e2 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.Sprites protected override Drawable CreateFallbackCharacterDrawable() { - var tex = GetTextureForCharacter('?').Result; + var tex = GetTextureForCharacter('?'); if (tex != null) { diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 17924cdbb8..27a06ba0b7 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -29,9 +28,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private async Task load(AudioManager audio) + private void load(AudioManager audio) { - sampleClick = await audio.Sample.GetAsync($@"UI/generic-select{SampleSet.GetDescription()}"); + sampleClick = audio.Sample.Get($@"UI/generic-select{SampleSet.GetDescription()}"); } } } diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index b3a83d1cc8..821305bc92 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -36,9 +35,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private async Task load(AudioManager audio) + private void load(AudioManager audio) { - sampleHover = await audio.Sample.GetAsync($@"UI/generic-hover{SampleSet.GetDescription()}"); + sampleHover = audio.Sample.Get($@"UI/generic-hover{SampleSet.GetDescription()}"); } } diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index d6b4b51851..68f59bd8cd 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -111,10 +110,10 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private async Task load(AudioManager audio) + private void load(AudioManager audio) { - sampleChecked = await audio.Sample.GetAsync(@"UI/check-on"); - sampleUnchecked = await audio.Sample.GetAsync(@"UI/check-off"); + sampleChecked = audio.Sample.Get(@"UI/check-on"); + sampleUnchecked = audio.Sample.Get(@"UI/check-off"); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index b5ebac0c74..abb077e94f 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -70,10 +69,10 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private async Task load(AudioManager audio) + private void load(AudioManager audio) { - sampleHover = await audio.Sample.GetAsync(@"UI/generic-hover"); - sampleClick = await audio.Sample.GetAsync(@"UI/generic-select"); + sampleHover = audio.Sample.Get(@"UI/generic-hover"); + sampleClick = audio.Sample.Get(@"UI/generic-select"); BackgroundColour = Color4.Transparent; BackgroundColourHover = OsuColour.FromHex(@"172023"); diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index cd0b3dcad2..b7b5319e06 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -3,7 +3,6 @@ using System; using System.Globalization; -using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -120,9 +119,9 @@ namespace osu.Game.Graphics.UserInterface } [BackgroundDependencyLoader] - private async Task load(AudioManager audio, OsuColour colours) + private void load(AudioManager audio, OsuColour colours) { - sample = await audio.Sample.GetAsync(@"UI/sliderbar-notch"); + sample = audio.Sample.Get(@"UI/sliderbar-notch"); AccentColour = colours.Pink; } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 038fa936b0..bd67a718a7 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -20,7 +20,6 @@ using OpenTK.Input; using osu.Framework.Graphics.Shapes; using System; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Input.States; using osu.Framework.MathUtils; @@ -144,10 +143,10 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private async Task load(OsuColour colours, TextureStore textures, AudioManager audio) + private void load(OsuColour colours, TextureStore textures, AudioManager audio) { - getSample = await audio.Sample.GetAsync(@"MedalSplash/medal-get"); - innerSpin.Texture = outerSpin.Texture = await textures.GetAsync(@"MedalSplash/disc-spin"); + getSample = audio.Sample.Get(@"MedalSplash/medal-get"); + innerSpin.Texture = outerSpin.Texture = textures.Get(@"MedalSplash/disc-spin"); disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters { diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 9ced6520df..a27278e002 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework; using OpenTK; using osu.Framework.Allocation; @@ -119,10 +118,10 @@ namespace osu.Game.Overlays.MedalSplash } [BackgroundDependencyLoader] - private async Task load(OsuColour colours, TextureStore textures) + private void load(OsuColour colours, TextureStore textures) { - medalSprite.Texture = await textures.GetAsync(medal.ImageUrl); - medalGlow.Texture = await textures.GetAsync(@"MedalSplash/medal-glow"); + medalSprite.Texture = textures.Get(medal.ImageUrl); + medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow"); description.Colour = colours.BlueLight; } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 783fcfa090..e83dedaf35 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -15,7 +15,6 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Graphics.Shapes; @@ -50,7 +49,7 @@ namespace osu.Game.Overlays.Mods protected readonly IBindable Ruleset = new Bindable(); [BackgroundDependencyLoader(true)] - private async Task load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) + private void load(OsuColour colours, IBindable ruleset, AudioManager audio, Bindable> selectedMods) { LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; @@ -59,8 +58,8 @@ namespace osu.Game.Overlays.Mods Ruleset.BindTo(ruleset); if (selectedMods != null) SelectedMods.BindTo(selectedMods); - sampleOn = await audio.Sample.GetAsync(@"UI/check-on"); - sampleOff = await audio.Sample.GetAsync(@"UI/check-off"); + sampleOn = audio.Sample.Get(@"UI/check-on"); + sampleOff = audio.Sample.Get(@"UI/check-off"); } protected override void LoadComplete() diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 42f89a4863..886b5fb95b 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -454,9 +454,9 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg4"); + sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4"); } } diff --git a/osu.Game/Overlays/Profile/Components/GradeBadge.cs b/osu.Game/Overlays/Profile/Components/GradeBadge.cs index 3943a5f86b..14a47e8d03 100644 --- a/osu.Game/Overlays/Profile/Components/GradeBadge.cs +++ b/osu.Game/Overlays/Profile/Components/GradeBadge.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -43,9 +42,9 @@ namespace osu.Game.Overlays.Profile.Components } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - badge.Texture = await textures.GetAsync($"Grades/{grade}"); + badge.Texture = textures.Get($"Grades/{grade}"); } } } diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index f87aefb28a..bfade5e45c 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -177,13 +176,13 @@ namespace osu.Game.Overlays.Profile.Header } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { Child = new Sprite { FillMode = FillMode.Fit, RelativeSizeAxes = Axes.Both, - Texture = await textures.GetAsync(badge.ImageUrl), + Texture = textures.Get(badge.ImageUrl), }; } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 48048d2935..9d09836d25 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -312,9 +311,9 @@ namespace osu.Game.Overlays.Profile } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - levelBadge.Texture = await textures.GetAsync(@"Profile/levelbadge"); + levelBadge.Texture = textures.Get(@"Profile/levelbadge"); } private User user; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 2eec75c875..0d354c728f 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; @@ -31,9 +30,9 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - sprite.Texture = await textures.GetAsync(url); + sprite.Texture = textures.Get(url); } } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 14d4cab870..78561cecbf 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; @@ -76,9 +75,9 @@ namespace osu.Game.Screens.Backgrounds } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - Sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg1"); + Sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg1"); } } } diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 3593568578..e53905a102 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -180,11 +179,11 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private async Task load(AudioManager audio) + private void load(AudioManager audio) { - sampleHover = await audio.Sample.GetAsync(@"Menu/button-hover"); + sampleHover = audio.Sample.Get(@"Menu/button-hover"); if (!string.IsNullOrEmpty(sampleName)) - sampleClick = await audio.Sample.GetAsync($@"Menu/{sampleName}"); + sampleClick = audio.Sample.Get($@"Menu/{sampleName}"); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 4137028527..b9a799328e 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -103,10 +102,10 @@ namespace osu.Game.Screens.Menu private OsuGame game; [BackgroundDependencyLoader(true)] - private async Task load(AudioManager audio, OsuGame game) + private void load(AudioManager audio, OsuGame game) { this.game = game; - sampleBack = await audio.Sample.GetAsync(@"Menu/button-back-select"); + sampleBack = audio.Sample.Get(@"Menu/button-back-select"); } public bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 5d39d70e26..c1032011f7 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -48,7 +47,7 @@ namespace osu.Game.Screens.Menu private WorkingBeatmap introBeatmap; [BackgroundDependencyLoader] - private async Task load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) + private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap) { this.beatmap.BindTo(beatmap); @@ -81,8 +80,8 @@ namespace osu.Game.Screens.Menu introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); track = introBeatmap.Track; - welcome = await audio.Sample.GetAsync(@"welcome"); - seeya = await audio.Sample.GetAsync(@"seeya"); + welcome = audio.Sample.Get(@"welcome"); + seeya = audio.Sample.Get(@"seeya"); } private const double delay_step_one = 2300; diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index c6cfd9ba2d..f0f765a4c9 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -254,13 +253,13 @@ namespace osu.Game.Screens.Menu } [BackgroundDependencyLoader] - private async Task load(TextureStore textures, AudioManager audio) + private void load(TextureStore textures, AudioManager audio) { - sampleClick = await audio.Sample.GetAsync(@"Menu/osu-logo-select"); - sampleBeat = await audio.Sample.GetAsync(@"Menu/osu-logo-heartbeat"); + sampleClick = audio.Sample.Get(@"Menu/osu-logo-select"); + sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat"); - logo.Texture = await textures.GetAsync(@"Menu/logo"); - ripple.Texture = await textures.GetAsync(@"Menu/logo"); + logo.Texture = textures.Get(@"Menu/logo"); + ripple.Texture = textures.Get(@"Menu/logo"); } private int lastBeatIndex; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 3929e631cf..4b893f0118 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Internal; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -81,7 +80,7 @@ namespace osu.Game.Screens private SampleChannel sampleExit; [BackgroundDependencyLoader(true)] - private async Task load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable ruleset) + private void load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable ruleset) { Beatmap.BindTo(beatmap); Ruleset.BindTo(ruleset); @@ -99,7 +98,7 @@ namespace osu.Game.Screens }; } - sampleExit = await audio.Sample.GetAsync(@"UI/screen-back"); + sampleExit = audio.Sample.Get(@"UI/screen-back"); } public virtual bool OnPressed(GlobalAction action) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 49500a8426..2c31e61114 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -62,19 +61,19 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { Children = new Drawable[] { buttonSprite = new Sprite { - Texture = await textures.GetAsync(@"KeyCounter/key-up"), + Texture = textures.Get(@"KeyCounter/key-up"), Anchor = Anchor.Centre, Origin = Anchor.Centre, }, glowSprite = new Sprite { - Texture = await textures.GetAsync(@"KeyCounter/key-glow"), + Texture = textures.Get(@"KeyCounter/key-glow"), Anchor = Anchor.Centre, Origin = Anchor.Centre, Alpha = 0 diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 863d12c1c2..5ad0130fd7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Play public bool LoadedBeatmapSuccessfully => RulesetContainer?.Objects.Any() == true; [BackgroundDependencyLoader] - private async Task load(AudioManager audio, APIAccess api, OsuConfigManager config) + private void load(AudioManager audio, APIAccess api, OsuConfigManager config) { this.api = api; @@ -92,7 +92,7 @@ namespace osu.Game.Screens.Play if (working is DummyWorkingBeatmap) return; - sampleRestart = await audio.Sample.GetAsync(@"Gameplay/restart"); + sampleRestart = audio.Sample.Get(@"Gameplay/restart"); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); userAudioOffset = config.GetBindable(OsuSetting.AudioOffset); diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs index 9aaaa6152c..06837c9274 100644 --- a/osu.Game/Screens/Play/SkipOverlay.cs +++ b/osu.Game/Screens/Play/SkipOverlay.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -225,12 +224,12 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader] - private async Task load(OsuColour colours, AudioManager audio) + private void load(OsuColour colours, AudioManager audio) { colourNormal = colours.Yellow; colourHover = colours.YellowDark; - sampleConfirm = await audio.Sample.GetAsync(@"SongSelect/confirm-selection"); + sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); Children = new Drawable[] { diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 87e53b8182..42d8af07b9 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -369,10 +368,10 @@ namespace osu.Game.Screens.Ranking } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { if (!string.IsNullOrEmpty(user.CoverUrl)) - cover.Texture = await textures.GetAsync(user.CoverUrl); + cover.Texture = textures.Get(user.CoverUrl); } } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index b252f116ac..8a0052559e 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; @@ -46,7 +45,7 @@ namespace osu.Game.Screens.Select.Carousel private SampleChannel sampleHover; [BackgroundDependencyLoader] - private async Task load(AudioManager audio, OsuColour colours) + private void load(AudioManager audio, OsuColour colours) { InternalChild = borderContainer = new Container { @@ -69,7 +68,7 @@ namespace osu.Game.Screens.Select.Carousel } }; - sampleHover = await audio.Sample.GetAsync($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); + sampleHover = audio.Sample.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); hoverLayer.Colour = colours.Blue.Opacity(0.1f); } diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index f5f9ebbdaf..0cf1e60304 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -36,20 +35,23 @@ namespace osu.Game.Screens.Select.Leaderboards } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { this.textures = textures; - await updateTexture(); + updateTexture(); } - private async Task updateTexture() => rankSprite.Texture = await textures.GetAsync($@"Grades/{Rank.GetDescription()}"); + private void updateTexture() + { + rankSprite.Texture = textures.Get($@"Grades/{Rank.GetDescription()}"); + } public void UpdateRank(ScoreRank newRank) { Rank = newRank; if (LoadState >= LoadState.Ready) - updateTexture().Wait(); + updateTexture(); } } } diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index cab7bdfe73..e914eb365e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -55,11 +55,11 @@ namespace osu.Game.Screens.Select private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); [BackgroundDependencyLoader(true)] - private async Task load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) { if (selectedMods != null) this.selectedMods.BindTo(selectedMods); - sampleConfirm = await audio.Sample.GetAsync(@"SongSelect/confirm-selection"); + sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue); diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index ac765c46ab..efdf55e477 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using System.Threading.Tasks; using OpenTK; using OpenTK.Input; using osu.Framework.Allocation; @@ -199,7 +198,7 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(true)] - private async Task load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours) { if (Footer != null) { @@ -219,8 +218,8 @@ namespace osu.Game.Screens.Select dialogOverlay = dialog; - sampleChangeDifficulty = await audio.Sample.GetAsync(@"SongSelect/select-difficulty"); - sampleChangeBeatmap = await audio.Sample.GetAsync(@"SongSelect/select-expand"); + sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); + sampleChangeBeatmap = audio.Sample.Get(@"SongSelect/select-expand"); Carousel.LoadBeatmapSetsFromManager(this.beatmaps); } diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs index 835b0757e0..1453d4e78f 100644 --- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs +++ b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Textures; using osu.Framework.MathUtils; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace osu.Game.Screens.Tournament.Components { @@ -76,9 +75,9 @@ namespace osu.Game.Screens.Tournament.Components private int expiredCount; [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - texture = await textures.GetAsync("Drawings/visualiser-line"); + texture = textures.Get("Drawings/visualiser-line"); } protected override void UpdateAfterChildren() diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 20180a660f..63d29d5cd7 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Tournament dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); [BackgroundDependencyLoader] - private async Task load(TextureStore textures, Storage storage) + private void load(TextureStore textures, Storage storage) { this.storage = storage; @@ -87,7 +87,7 @@ namespace osu.Game.Screens.Tournament { RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, - Texture = await textures.GetAsync(@"Backgrounds/Drawings/background.png") + Texture = textures.Get(@"Backgrounds/Drawings/background.png") }, new FillFlowContainer { diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game/Screens/Tournament/Group.cs index 5128166c15..6845d8fc48 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game/Screens/Tournament/Group.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -179,9 +178,9 @@ namespace osu.Game.Screens.Tournament } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - flagSprite.Texture = await textures.GetAsync($@"Flags/{Team.FlagName}"); + flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); } } } diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index cc9f805c62..d1c7e0fced 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; @@ -373,9 +372,9 @@ namespace osu.Game.Screens.Tournament } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { - flagSprite.Texture = await textures.GetAsync($@"Flags/{Team.FlagName}"); + flagSprite.Texture = textures.Get($@"Flags/{Team.FlagName}"); } } } diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 9aac662a84..9ba9549164 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -25,14 +24,14 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); Texture texture = null; - if (user != null && user.Id > 1) texture = await textures.GetAsync($@"https://a.ppy.sh/{user.Id}"); - if (texture == null) texture = await textures.GetAsync(@"Online/avatar-guest"); + if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); + if (texture == null) texture = textures.Get(@"Online/avatar-guest"); Add(new Sprite { diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index a37ca10f9a..80039eadad 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -45,7 +44,7 @@ namespace osu.Game.Users country = value; if (LoadState >= LoadState.Ready) - sprite.Texture = getFlagTexture().Result; + sprite.Texture = getFlagTexture(); } } @@ -65,15 +64,15 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private async Task load(TextureStore ts) + private void load(TextureStore ts) { if (ts == null) throw new ArgumentNullException(nameof(ts)); textures = ts; - sprite.Texture = await getFlagTexture(); + sprite.Texture = getFlagTexture(); } - private async Task getFlagTexture() => await textures.GetAsync($@"Flags/{country?.FlagName ?? @"__"}"); + private Texture getFlagTexture() => textures.Get($@"Flags/{country?.FlagName ?? @"__"}"); } } diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 97d2648e07..58b92b2750 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -19,13 +18,13 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private async Task load(TextureStore textures) + private void load(TextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); if (!string.IsNullOrEmpty(user.CoverUrl)) - Texture = await textures.GetAsync(user.CoverUrl); + Texture = textures.Get(user.CoverUrl); } } } From 4c725659363feb890b75d0931245555d3dc47ec1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Aug 2018 19:20:10 +0900 Subject: [PATCH 232/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2e7877f5ce..61b7888513 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 62a8245f11577226336b76572fb3a1b915af254e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 10:59:04 +0900 Subject: [PATCH 233/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 61b7888513..669b775674 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From bf6fb1c38048f8a7f44cfc3bc525cab22b56591b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 12:55:11 +0900 Subject: [PATCH 234/277] Don't use ConcurrentQueue for API This queue type can hold several references to already dequeued requests. In our usage, this can cause old api calls to hold references to already-disposed screens (and in turn, very large memory portions). --- osu.Game/Online/API/APIAccess.cs | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 12935a5ffe..ff5247e8f6 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Net; @@ -26,7 +25,7 @@ namespace osu.Game.Online.API private const string client_id = @"5"; private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk"; - private ConcurrentQueue queue = new ConcurrentQueue(); + private readonly Queue queue = new Queue(); /// /// The username/email provided by the user when initiating a login. @@ -75,10 +74,7 @@ namespace osu.Game.Online.API public void Unregister(IOnlineComponent component) { - Scheduler.Add(delegate - { - components.Remove(component); - }); + Scheduler.Add(delegate { components.Remove(component); }); } public string AccessToken => authentication.RequestAccessToken(); @@ -103,6 +99,7 @@ namespace osu.Game.Online.API log.Add(@"Queueing a ping request"); Queue(new ListChannelsRequest { Timeout = 5000 }); } + break; case APIState.Offline: case APIState.Connecting: @@ -161,18 +158,19 @@ namespace osu.Game.Online.API continue; } - //process the request queue. - APIRequest req; - while (queue.TryPeek(out req)) + APIRequest req = null; + + lock (queue) + if (queue.Count > 0) + req = queue.Dequeue(); + + if (req != null) { - if (handleRequest(req)) - { - //we have succeeded, so let's unqueue. - queue.TryDequeue(out req); - } + // TODO: handle failures better + handleRequest(req); } - Thread.Sleep(1); + Thread.Sleep(50); } } @@ -205,7 +203,8 @@ namespace osu.Game.Online.API } catch (WebException we) { - HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); + HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode + ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout); // special cases for un-typed but useful message responses. switch (we.Message) @@ -247,6 +246,7 @@ namespace osu.Game.Online.API } private APIState state; + public APIState State { get { return state; } @@ -271,7 +271,10 @@ namespace osu.Game.Online.API public bool IsLoggedIn => LocalUser.Value.Id > 1; - public void Queue(APIRequest request) => queue.Enqueue(request); + public void Queue(APIRequest request) + { + lock (queue) queue.Enqueue(request); + } public event StateChangeDelegate OnStateChange; @@ -279,16 +282,17 @@ namespace osu.Game.Online.API private void flushQueue(bool failOldRequests = true) { - var oldQueue = queue; - - //flush the queue. - queue = new ConcurrentQueue(); - - if (failOldRequests) + lock (queue) { - APIRequest req; - while (oldQueue.TryDequeue(out req)) - req.Fail(new WebException(@"Disconnected from server")); + var oldQueueRequests = queue.ToArray(); + + queue.Clear(); + + if (failOldRequests) + { + foreach (var req in oldQueueRequests) + req.Fail(new WebException(@"Disconnected from server")); + } } } From 562a792a9957e92ba82c78f0e3fff1b25428f20b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 13:00:55 +0900 Subject: [PATCH 235/277] Use thread instead of LongRunning for API --- osu.Game/Online/API/APIAccess.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index ff5247e8f6..eb9a60115f 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Threading; -using System.Threading.Tasks; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Logging; @@ -54,7 +53,13 @@ namespace osu.Game.Online.API authentication.TokenString = config.Get(OsuSetting.Token); authentication.Token.ValueChanged += onTokenChanged; - Task.Factory.StartNew(run, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); + var thread = new Thread(run) + { + Name = "APIAccess", + IsBackground = true + }; + + thread.Start(); } private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty); From d9e9c61731d1deac746c831b94724ba52172dc7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 1 Sep 2018 17:39:54 +0900 Subject: [PATCH 236/277] Begin loading fonts earlier in startup Should result in a considerably faster font load, as they can be concurrently loaded alongside EF. --- osu.Game/OsuGameBase.cs | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..6987b6eea7 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -114,31 +114,8 @@ namespace osu.Game dependencies.CacheAs(this); dependencies.Cache(LocalConfig); - runMigrations(); - - dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); - dependencies.CacheAs(SkinManager); - - var api = new APIAccess(LocalConfig); - - dependencies.Cache(api); - dependencies.CacheAs(api); - - dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); - dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); - dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); - dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); - dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); - dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); - dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); - dependencies.Cache(new OsuColour()); - - fileImporters.Add(BeatmapManager); - fileImporters.Add(ScoreStore); - fileImporters.Add(SkinManager); - //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); + dependencies.Cache(Fonts = new FontStore()); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); @@ -164,6 +141,29 @@ namespace osu.Game Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light")); + runMigrations(); + + dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); + dependencies.CacheAs(SkinManager); + + var api = new APIAccess(LocalConfig); + + dependencies.Cache(api); + dependencies.CacheAs(api); + + dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); + dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); + dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); + dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); + dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); + dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); + dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); + dependencies.Cache(new OsuColour()); + + fileImporters.Add(BeatmapManager); + fileImporters.Add(ScoreStore); + fileImporters.Add(SkinManager); + var defaultBeatmap = new DummyWorkingBeatmap(this); beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio); BeatmapManager.DefaultBeatmap = defaultBeatmap; From 144e80dff6806271052918a6ba3d677b4a206400 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Aug 2018 18:28:53 +0900 Subject: [PATCH 237/277] Add "import all skins from stable" option (and mass delete) --- osu.Game/Beatmaps/BeatmapManager.cs | 28 +------------- osu.Game/Database/ArchiveModelManager.cs | 38 ++++++++++++++++++- osu.Game/OsuGame.cs | 6 ++- .../Sections/Maintenance/GeneralSettings.cs | 26 ++++++++++++- osu.Game/Screens/Select/PlaySongSelect.cs | 4 +- osu.Game/Skinning/SkinManager.cs | 12 +++++- 6 files changed, 78 insertions(+), 36 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 1adbb4a389..46c48bcd0f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -62,6 +62,8 @@ namespace osu.Game.Beatmaps public override string[] HandledExtensions => new[] { ".osz" }; + protected override string ImportFromStablePath => "Songs"; + private readonly RulesetStore rulesets; private readonly BeatmapStore beatmaps; @@ -72,11 +74,6 @@ namespace osu.Game.Beatmaps private readonly List currentDownloads = new List(); - /// - /// Set a storage with access to an osu-stable install for import purposes. - /// - public Func GetStableStorage { private get; set; } - public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null) : base(storage, contextFactory, new BeatmapStore(contextFactory), importHost) { @@ -311,27 +308,6 @@ namespace osu.Game.Beatmaps /// Results from the provided query. public IQueryable QueryBeatmaps(Expression> query) => beatmaps.Beatmaps.AsNoTracking().Where(query); - /// - /// Denotes whether an osu-stable installation is present to perform automated imports from. - /// - public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null; - - /// - /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. - /// - public Task ImportFromStable() - { - var stable = GetStableStorage?.Invoke(); - - if (stable == null) - { - Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error); - return Task.CompletedTask; - } - - return Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); - } - /// /// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content. /// diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 326d042c39..a3ae19f97d 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework.IO.File; @@ -283,7 +284,7 @@ namespace osu.Game.Database var notification = new ProgressNotification { Progress = 0, - CompletionText = "Deleted all beatmaps!", + CompletionText = $"Deleted all {typeof(TModel)}s!", State = ProgressNotificationState.Active, }; @@ -385,6 +386,41 @@ namespace osu.Game.Database return fileInfos; } + #region osu-stable import + + /// + /// Set a storage with access to an osu-stable install for import purposes. + /// + public Func GetStableStorage { private get; set; } + + /// + /// Denotes whether an osu-stable installation is present to perform automated imports from. + /// + public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null; + + /// + /// The relative path from osu-stable's data directory to import items from. + /// + protected virtual string ImportFromStablePath => null; + + /// + /// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future. + /// + public Task ImportFromStableAsync() + { + var stable = GetStableStorage?.Invoke(); + + if (stable == null) + { + Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error); + return Task.CompletedTask; + } + + return Task.Factory.StartNew(() => Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning); + } + + #endregion + /// /// Create a barebones model from the provided archive. /// Actual expensive population should be done in ; this should just prepare for duplicate checking. diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 7f0576608d..6fcb948298 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -299,11 +299,13 @@ namespace osu.Game // This prevents the cursor from showing until we have a screen with CursorVisible = true MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; - // hook up notifications to components. + // todo: all archive managers should be able to be looped here. SkinManager.PostNotification = n => notifications?.Post(n); - BeatmapManager.PostNotification = n => notifications?.Post(n); + SkinManager.GetStableStorage = GetStorageForStableInstall; + BeatmapManager.PostNotification = n => notifications?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; + BeatmapManager.PresentBeatmap = PresentBeatmap; AddRange(new Drawable[] diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 93d1986e3a..57e9a528d2 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Skinning; namespace osu.Game.Overlays.Settings.Sections.Maintenance { @@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance protected override string Header => "General"; [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, DialogOverlay dialogOverlay) + private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay) { Children = new Drawable[] { @@ -30,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance Action = () => { importButton.Enabled.Value = false; - beatmaps.ImportFromStable().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); + beatmaps.ImportFromStableAsync().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); } }, deleteButton = new DangerousSettingsButton @@ -45,6 +46,27 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance })); } }, + importButton = new SettingsButton + { + Text = "Import skins from stable", + Action = () => + { + importButton.Enabled.Value = false; + skins.ImportFromStableAsync().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); + } + }, + deleteButton = new DangerousSettingsButton + { + Text = "Delete ALL skins", + Action = () => + { + dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() => + { + deleteButton.Enabled.Value = false; + Task.Run(() => skins.Delete(skins.GetAllUserSkins())).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true)); + })); + } + }, restoreButton = new SettingsButton { Text = "Restore all hidden difficulties", diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index e914eb365e..0cba6e645e 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -77,8 +76,7 @@ namespace osu.Game.Screens.Select { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) - dialogOverlay.Push(new ImportFromStablePopup(() => - Task.Factory.StartNew(beatmaps.ImportFromStable, TaskCreationOptions.LongRunning))); + dialogOverlay.Push(new ImportFromStablePopup(() => beatmaps.ImportFromStableAsync())); }); } } diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 2387924cfa..05cee8261f 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -26,17 +26,25 @@ namespace osu.Game.Skinning public override string[] HandledExtensions => new[] { ".osk" }; + protected override string ImportFromStablePath => "Skins"; + /// - /// Returns a list of all usable s. + /// Returns a list of all usable s. Includes the special default skin plus all skins from . /// /// A list of available . public List GetAllUsableSkins() { - var userSkins = ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + var userSkins = GetAllUserSkins(); userSkins.Insert(0, SkinInfo.Default); return userSkins; } + /// + /// Returns a list of all usable s that have been loaded by the user. + /// + /// A list of available . + public List GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList(); + protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name From e67f63eab651dc0be85da08b66db6a9a08061c46 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Aug 2018 18:32:21 +0900 Subject: [PATCH 238/277] Improve import progress messaging --- osu.Game/Database/ArchiveModelManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index a3ae19f97d..234e1a9bd6 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -168,6 +168,7 @@ namespace osu.Game.Database } notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!"; + notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!"; notification.State = ProgressNotificationState.Completed; } @@ -284,7 +285,7 @@ namespace osu.Game.Database var notification = new ProgressNotification { Progress = 0, - CompletionText = $"Deleted all {typeof(TModel)}s!", + CompletionText = $"Deleted all {typeof(TModel).Name.Replace("Info", "").ToLower()}s!", State = ProgressNotificationState.Active, }; From fa569e5ae4edcb86a2bf44ab44d39942443ef6f8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 31 Aug 2018 18:36:35 +0900 Subject: [PATCH 239/277] Offer to import skins on first startup --- osu.Game/Screens/Select/ImportFromStablePopup.cs | 2 +- osu.Game/Screens/Select/PlaySongSelect.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs index 7c3b98cc2e..a52b5bab2a 100644 --- a/osu.Game/Screens/Select/ImportFromStablePopup.cs +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -12,7 +12,7 @@ namespace osu.Game.Screens.Select public ImportFromStablePopup(Action importFromStable) { HeaderText = @"You have no beatmaps!"; - BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps?"; + BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps (and skins)?"; Icon = FontAwesome.fa_plane; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 0cba6e645e..2c43b333aa 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -19,6 +19,7 @@ using osu.Game.Rulesets.Mods; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; +using osu.Game.Skinning; namespace osu.Game.Screens.Select { @@ -54,7 +55,7 @@ namespace osu.Game.Screens.Select private readonly Bindable> selectedMods = new Bindable>(new Mod[] { }); [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable> selectedMods) + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay, Bindable> selectedMods) { if (selectedMods != null) this.selectedMods.BindTo(selectedMods); @@ -76,7 +77,11 @@ namespace osu.Game.Screens.Select { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) - dialogOverlay.Push(new ImportFromStablePopup(() => beatmaps.ImportFromStableAsync())); + dialogOverlay.Push(new ImportFromStablePopup(() => + { + beatmaps.ImportFromStableAsync(); + skins.ImportFromStableAsync(); + })); }); } } From fb1e8fbdcf8577165253a96874d0a4982ea698b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Sep 2018 10:23:56 +0900 Subject: [PATCH 240/277] Remove migration code --- osu.Game/Skinning/SkinManager.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 05cee8261f..91c78f80b8 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -101,16 +101,6 @@ namespace osu.Game.Skinning SourceChanged?.Invoke(); }; - - // migrate older imports which didn't have access to skin.ini - using (ContextFactory.GetForWrite()) - { - foreach (var skinInfo in ModelStore.ConsumableItems.Where(s => s.Name.EndsWith(".osk"))) - { - populate(skinInfo); - Update(skinInfo); - } - } } /// From 43824c2a94d9e108c7d05282b0c54af189692f4a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Sep 2018 11:50:50 +0900 Subject: [PATCH 241/277] Switch back to default skin when the user selected skin is deleted --- osu.Game/Skinning/SkinManager.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 91c78f80b8..74222da4a2 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -93,6 +93,12 @@ namespace osu.Game.Skinning { this.audio = audio; + ItemRemoved += removedInfo => { + // check the removed skin is not the current user choice. if it is, switch back to default. + if (removedInfo.ID == CurrentSkinInfo.Value.ID) + CurrentSkinInfo.Value = SkinInfo.Default; + }; + CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = GetSkin(info); CurrentSkin.ValueChanged += skin => { From 5efa9c765248d9b82779a601ca9a630debd28c84 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 3 Sep 2018 11:51:03 +0900 Subject: [PATCH 242/277] Fix items in skin settings not always being removed corrrectly --- .../Overlays/Settings/Sections/SkinSection.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index df8ebaf4aa..15787d29f7 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -51,10 +51,10 @@ namespace osu.Game.Overlays.Settings.Sections }, }; - skins.ItemAdded += onItemsChanged; - skins.ItemRemoved += onItemsChanged; + skins.ItemAdded += itemAdded; + skins.ItemRemoved += itemRemoved; - reloadSkins(); + skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair(s.ToString(), s.ID)); var skinBindable = config.GetBindable(OsuSetting.Skin); @@ -65,9 +65,8 @@ namespace osu.Game.Overlays.Settings.Sections skinDropdown.Bindable = skinBindable; } - private void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair(s.ToString(), s.ID)); - - private void onItemsChanged(SkinInfo _) => Schedule(reloadSkins); + private void itemRemoved(SkinInfo s) => skinDropdown.Items = skinDropdown.Items.Where(i => i.Value != s.ID); + private void itemAdded(SkinInfo s) => skinDropdown.Items = skinDropdown.Items.Append(new KeyValuePair(s.ToString(), s.ID)); protected override void Dispose(bool isDisposing) { @@ -75,8 +74,8 @@ namespace osu.Game.Overlays.Settings.Sections if (skins != null) { - skins.ItemAdded -= onItemsChanged; - skins.ItemRemoved -= onItemsChanged; + skins.ItemAdded -= itemAdded; + skins.ItemRemoved -= itemRemoved; } } From 923acfbeaf5d49a643c047a90a1d0be1bf112316 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 10:23:23 +0900 Subject: [PATCH 243/277] Fix some web requests being run after disposal of their owner --- .../BeatmapSet/Scores/ScoresContainer.cs | 2 +- .../Beatmaps/PaginatedBeatmapContainer.cs | 17 +++++++++++------ .../PaginatedMostPlayedBeatmapContainer.cs | 18 +++++++++++++----- .../Profile/Sections/PaginatedContainer.cs | 1 + .../Sections/Ranks/PaginatedScoreContainer.cs | 16 +++++++++++----- .../Recent/PaginatedRecentActivityContainer.cs | 17 ++++++++++++----- osu.Game/Overlays/UserProfileOverlay.cs | 15 +++++++-------- 7 files changed, 56 insertions(+), 30 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 626de14c98..6cb85c778b 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores loading = true; getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset); - getScoresRequest.Success += r => Scores = r.Scores; + getScoresRequest.Success += r => Schedule(() => Scores = r.Scores); api.Queue(getScoresRequest); } } diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 0b06acd426..621f752b9c 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps public class PaginatedBeatmapContainer : PaginatedContainer { private const float panel_padding = 10f; - private readonly BeatmapSetType type; + private GetUserBeatmapsRequest request; public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.") : base(user, header, missing) @@ -31,9 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps { base.ShowMore(); - var req = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); - - req.Success += sets => + request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request.Success += sets => Schedule(() => { ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -52,9 +51,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets)); ItemsContainer.Add(panel); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index 42784682be..ad886c363b 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer { + private GetUserMostPlayedBeatmapsRequest request; + public PaginatedMostPlayedBeatmapContainer(Bindable user) :base(user, "Most Played Beatmaps", "No records. :(") { @@ -24,9 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { base.ShowMore(); - var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); - - req.Success += beatmaps => + request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request.Success += beatmaps => Schedule(() => { ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -43,9 +44,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical { ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount)); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 6dbb9b9ba3..db93fcbc1b 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections protected readonly Bindable User = new Bindable(); protected APIAccess Api; + protected APIRequest RetrievalRequest; protected RulesetStore Rulesets; public PaginatedContainer(Bindable user, string header, string missing) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 707de0a10f..ed82c62e5c 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { private readonly bool includeWeight; private readonly ScoreType type; + private GetUserScoresRequest request; public PaginatedScoreContainer(ScoreType type, Bindable user, string header, string missing, bool includeWeight = false) : base(user, header, missing) @@ -32,9 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { base.ShowMore(); - var req = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); - - req.Success += scores => + request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage); + request.Success += scores => Schedule(() => { foreach (var s in scores) s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID)); @@ -66,9 +66,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks ItemsContainer.Add(drawableScore); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index ee2f2f5973..fd5eda4e44 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { public class PaginatedRecentActivityContainer : PaginatedContainer { + private GetUserRecentActivitiesRequest request; + public PaginatedRecentActivityContainer(Bindable user, string header, string missing) : base(user, header, missing) { @@ -22,9 +24,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { base.ShowMore(); - var req = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); - - req.Success += activities => + request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage); + request.Success += activities => Schedule(() => { ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0); ShowMoreLoading.Hide(); @@ -41,9 +42,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent { ItemsContainer.Add(new DrawableRecentActivity(activity)); } - }; + }); - Api.Queue(req); + Api.Queue(request); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + request?.Cancel(); } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 11b68b0e09..ea077ff645 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -73,16 +73,15 @@ namespace osu.Game.Overlays FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out); } - public void ShowUser(long userId) - { - if (userId == Header.User.Id) - return; - - ShowUser(new User { Id = userId }); - } + public void ShowUser(long userId) => ShowUser(new User { Id = userId }); public void ShowUser(User user, bool fetchOnline = true) { + Show(); + + if (user.Id == Header?.User.Id) + return; + userReq?.Cancel(); Clear(); lastSection = null; @@ -97,6 +96,7 @@ namespace osu.Game.Overlays new BeatmapsSection(), new KudosuSection() }; + tabs = new ProfileTabControl { RelativeSizeAxes = Axes.X, @@ -161,7 +161,6 @@ namespace osu.Game.Overlays userLoadComplete(user); } - Show(); sectionsContainer.ScrollToTop(); } From da3eb18784fcdcd4380ebc6cde38a83b4ddca51a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 10:38:05 +0900 Subject: [PATCH 244/277] Fix the toolbar being visible during startup causing a weird offset --- osu.Game/Overlays/Toolbar/Toolbar.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 2eabf1eb74..cdc3bc2b51 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -83,14 +83,14 @@ namespace osu.Game.Overlays.Toolbar [BackgroundDependencyLoader(true)] private void load(OsuGame osuGame) { - if (osuGame != null) - overlayActivationMode.BindTo(osuGame.OverlayActivationMode); - StateChanged += visibility => { if (overlayActivationMode == OverlayActivation.Disabled) State = Visibility.Hidden; }; + + if (osuGame != null) + overlayActivationMode.BindTo(osuGame.OverlayActivationMode); } public class ToolbarBackground : Container From 581da108fc2c348dae73486e18d828f340d1fe41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 11:32:38 +0900 Subject: [PATCH 245/277] Rewrite to not suck --- .../Sections/Graphics/LayoutSettings.cs | 57 ++++++------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 14680bc7cb..4d3cdacb6a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -19,13 +19,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics private Bindable letterboxing; private Bindable sizeFullscreen; - private readonly BindableInt resolutionDropdownBindable = new BindableInt(); private OsuGameBase game; - private SettingsDropdown resolutionDropdown; + private SettingsDropdown resolutionDropdown; private SettingsEnumDropdown windowModeDropdown; - private const int transition_duration = 400; [BackgroundDependencyLoader] @@ -36,25 +34,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxing = config.GetBindable(FrameworkSetting.Letterboxing); sizeFullscreen = config.GetBindable(FrameworkSetting.SizeFullscreen); - sizeFullscreen.ValueChanged += size => - { - KeyValuePair valuePair = getResolutions().FirstOrDefault(r => r.Key.StartsWith($"{size.Width}x{size.Height}")); - - resolutionDropdownBindable.Value = valuePair.Value; - }; - - resolutionDropdownBindable.ValueChanged += resolution => - { - var newSelection = getResolutions().First(r => r.Value == resolution); - var newSelectionParts = newSelection.Key.Split('x'); - - var newSelectionWidth = int.Parse(newSelectionParts.First()); - var newSelectionHeight = int.Parse(newSelectionParts.Last()); - - if (sizeFullscreen.Value.Width != newSelectionWidth || sizeFullscreen.Value.Height != newSelectionHeight) - sizeFullscreen.Value = new Size(newSelectionWidth, newSelectionHeight); - }; - Children = new Drawable[] { windowModeDropdown = new SettingsEnumDropdown @@ -62,11 +41,12 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Screen mode", Bindable = config.GetBindable(FrameworkSetting.WindowMode), }, - resolutionDropdown = new SettingsDropdown + resolutionDropdown = new SettingsDropdown { LabelText = "Resolution", + ShowsDefaultIndicator = false, Items = getResolutions(), - Bindable = resolutionDropdownBindable + Bindable = sizeFullscreen }, new SettingsCheckbox { @@ -100,7 +80,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, }; - windowModeDropdown.Bindable.ValueChanged += windowMode => + windowModeDropdown.Bindable.BindValueChanged(windowMode => { if (windowMode == WindowMode.Fullscreen) { @@ -109,31 +89,30 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics } else resolutionDropdown.Hide(); - }; - windowModeDropdown.Bindable.TriggerChange(); + }, true); - letterboxing.ValueChanged += isVisible => + letterboxing.BindValueChanged(isVisible => { letterboxSettings.ClearTransforms(); letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None; if (!isVisible) letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); - }; - letterboxing.TriggerChange(); + }, true); } - private List> getResolutions() + private List> getResolutions() { - var availableDisplayResolutions = game.Window?.GetCurrentDisplay().AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width).ThenByDescending(r => r.Height); + if (game.Window == null) + return new List>(); - if (availableDisplayResolutions == null) - return new List>(); - - var availableDisplayResolutionsStr = availableDisplayResolutions.Select(r => $"{r.Width}x{r.Height}").Distinct(); - return availableDisplayResolutionsStr.Select((t, i) => new KeyValuePair(t, i)).ToList(); + return game.Window?.AvailableResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width) + .ThenByDescending(r => r.Height) + .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) + .Distinct() + .ToList(); } } } From 77455e44635f1358aa9012d6f2389914a3523280 Mon Sep 17 00:00:00 2001 From: Joehu Date: Tue, 4 Sep 2018 19:44:49 -0700 Subject: [PATCH 246/277] Fix direct list play button disappearing after preview/switch --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 322db0b7d6..8a22ff7587 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -187,7 +187,7 @@ namespace osu.Game.Overlays.Direct base.LoadComplete(); this.FadeInFromZero(200, Easing.Out); - PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered ? 1 : 0, 120, Easing.InOutQuint); + PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint); PreviewPlaying.ValueChanged += newValue => PreviewBar.FadeTo(newValue ? 1 : 0, 120, Easing.InOutQuint); } From d5acc96efaefcf8fca81fd67bcf49c1a67bec7e2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 5 Sep 2018 14:59:37 +0900 Subject: [PATCH 247/277] Apply changes in line with osu!framework changes --- osu.Game/Graphics/DrawableDate.cs | 2 -- osu.Game/Graphics/Sprites/OsuSpriteText.cs | 24 ------------------- osu.Game/OsuGameBase.cs | 3 +-- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- .../Drawables/DrawableStoryboard.cs | 2 +- 5 files changed, 3 insertions(+), 30 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 406fc2ffd2..be794d93a6 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,7 +4,6 @@ using System; using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.Sprites; @@ -16,7 +15,6 @@ namespace osu.Game.Graphics public DrawableDate(DateTimeOffset date) { - AutoSizeAxes = Axes.Both; Font = "Exo2.0-RegularItalic"; Date = date.ToLocalTime(); diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index c9389bb9e2..8607d51e12 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -3,9 +3,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.MathUtils; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Graphics.Transforms; namespace osu.Game.Graphics.Sprites @@ -19,27 +16,6 @@ namespace osu.Game.Graphics.Sprites Shadow = true; TextSize = FONT_SIZE; } - - protected override Drawable CreateFallbackCharacterDrawable() - { - var tex = GetTextureForCharacter('?'); - - if (tex != null) - { - float adjust = (RNG.NextSingle() - 0.5f) * 2; - return new Sprite - { - Texture = tex, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Scale = new Vector2(1 + adjust * 0.2f), - Rotation = adjust * 15, - Colour = Color4.White, - }; - } - - return base.CreateFallbackCharacterDrawable(); - } } public static class OsuSpriteTextTransformExtensions diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..29072523f3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -138,9 +138,8 @@ namespace osu.Game fileImporters.Add(SkinManager); //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); + dependencies.Cache(Fonts = new FontStore(new GlyphStore(Resources, @"Fonts/FontAwesome"))); - Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic")); diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 9555f0fbc5..58714208c0 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Children = new[] + Children = new Drawable[] { new OsuSpriteText { diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index d746bb90c4..c5a9514095 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -57,7 +57,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); + dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From c03d1d9566cdb95507358af2c89ec84ea415b4b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 5 Sep 2018 16:45:30 +0900 Subject: [PATCH 248/277] Attempt to fix CI failures on CatcherArea.Explode --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 4327abb96f..5802f64b96 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.UI // this is required to make this run after the last caught fruit runs UpdateState at least once. // TODO: find a better alternative - if (lastPlateableFruit.IsLoaded) + if (lastPlateableFruit.LoadState > LoadState.Ready) action(); else lastPlateableFruit.OnLoadComplete = _ => action(); @@ -407,9 +407,7 @@ namespace osu.Game.Rulesets.Catch.UI /// public void Explode() { - var fruit = caughtFruit.ToArray(); - - foreach (var f in fruit) + foreach (var f in caughtFruit.ToArray()) Explode(f); } @@ -422,15 +420,15 @@ namespace osu.Game.Rulesets.Catch.UI fruit.Anchor = Anchor.TopLeft; fruit.Position = caughtFruit.ToSpaceOfOtherDrawable(fruit.DrawPosition, ExplodingFruitTarget); - caughtFruit.Remove(fruit); + if (!caughtFruit.Remove(fruit)) + // we may have already been removed by a previous operation (due to the weird OnLoadComplete scheduling). + // this avoids a crash on potentially attempting to Add a fruit to ExplodingFruitTarget twice. + return; ExplodingFruitTarget.Add(fruit); } - fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine) - .Then() - .MoveToY(fruit.Y + 50, 500, Easing.InSine); - + fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); From 8d9e0ff1c34ce62d7660db1fd2ea68e4deb60ab0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 12:51:23 +0900 Subject: [PATCH 249/277] Remove async WorkingBeatmap logic --- osu.Game/Beatmaps/WorkingBeatmap.cs | 146 ++++++++++++---------------- 1 file changed, 62 insertions(+), 84 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 085c591fce..85b98413e5 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -8,10 +8,10 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Game.Storyboards; using osu.Framework.IO.File; using System.IO; +using System.Threading; using osu.Game.IO.Serialization; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; @@ -38,12 +38,26 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - beatmap = new AsyncLazy(populateBeatmap); - background = new AsyncLazy(populateBackground, b => b == null || !b.IsDisposed); - track = new AsyncLazy(populateTrack); - waveform = new AsyncLazy(populateWaveform); - storyboard = new AsyncLazy(populateStoryboard); - skin = new AsyncLazy(populateSkin); + beatmap = new RecyclableLazy(() => + { + var b = GetBeatmap() ?? new Beatmap(); + // use the database-backed info. + b.BeatmapInfo = BeatmapInfo; + return b; + }); + + track = new RecyclableLazy(() => + { + // we want to ensure that we always have a track, even if it's a fake one. + var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); + applyRateAdjustments(t); + return t; + }); + + background = new RecyclableLazy(GetBackground, BackgroundStillValid); + waveform = new RecyclableLazy(GetWaveform); + storyboard = new RecyclableLazy(GetStoryboard); + skin = new RecyclableLazy(GetSkin); } /// @@ -58,28 +72,6 @@ namespace osu.Game.Beatmaps return path; } - protected abstract IBeatmap GetBeatmap(); - protected abstract Texture GetBackground(); - protected abstract Track GetTrack(); - protected virtual Skin GetSkin() => new DefaultSkin(); - protected virtual Waveform GetWaveform() => new Waveform(); - protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; - - public bool BeatmapLoaded => beatmap.IsResultAvailable; - public IBeatmap Beatmap => beatmap.Value.Result; - public Task GetBeatmapAsync() => beatmap.Value; - private readonly AsyncLazy beatmap; - - private IBeatmap populateBeatmap() - { - var b = GetBeatmap() ?? new Beatmap(); - - // use the database-backed info. - b.BeatmapInfo = BeatmapInfo; - - return b; - } - /// /// Constructs a playable from using the applicable converters for a specific . /// @@ -136,62 +128,53 @@ namespace osu.Game.Beatmaps public override string ToString() => BeatmapInfo.ToString(); - public bool BackgroundLoaded => background.IsResultAvailable; - public Texture Background => background.Value.Result; - public Task GetBackgroundAsync() => background.Value; - private AsyncLazy background; + public bool BeatmapLoaded => beatmap.IsResultAvailable; + public IBeatmap Beatmap => beatmap.Value; + protected abstract IBeatmap GetBeatmap(); + private readonly RecyclableLazy beatmap; - private Texture populateBackground() => GetBackground(); + public bool BackgroundLoaded => background.IsResultAvailable; + public Texture Background => background.Value; + protected virtual bool BackgroundStillValid(Texture b) => b == null || !b.IsDisposed; + protected abstract Texture GetBackground(); + private readonly RecyclableLazy background; public bool TrackLoaded => track.IsResultAvailable; - public Track Track => track.Value.Result; - public Task GetTrackAsync() => track.Value; - private AsyncLazy track; - - private Track populateTrack() - { - // we want to ensure that we always have a track, even if it's a fake one. - var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap); - applyRateAdjustments(t); - return t; - } + public Track Track => track.Value; + protected abstract Track GetTrack(); + private RecyclableLazy track; public bool WaveformLoaded => waveform.IsResultAvailable; - public Waveform Waveform => waveform.Value.Result; - public Task GetWaveformAsync() => waveform.Value; - private readonly AsyncLazy waveform; - - private Waveform populateWaveform() => GetWaveform(); + public Waveform Waveform => waveform.Value; + protected virtual Waveform GetWaveform() => new Waveform(); + private readonly RecyclableLazy waveform; public bool StoryboardLoaded => storyboard.IsResultAvailable; - public Storyboard Storyboard => storyboard.Value.Result; - public Task GetStoryboardAsync() => storyboard.Value; - private readonly AsyncLazy storyboard; - - private Storyboard populateStoryboard() => GetStoryboard(); + public Storyboard Storyboard => storyboard.Value; + protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo }; + private readonly RecyclableLazy storyboard; public bool SkinLoaded => skin.IsResultAvailable; - public Skin Skin => skin.Value.Result; - public Task GetSkinAsync() => skin.Value; - private readonly AsyncLazy skin; + public Skin Skin => skin.Value; + protected virtual Skin GetSkin() => new DefaultSkin(); + private readonly RecyclableLazy skin; - private Skin populateSkin() => GetSkin(); - - public void TransferTo(WorkingBeatmap other) + /// + /// Transfer pieces of a beatmap to a new one, where possible, to save on loading. + /// + /// The new beatmap which is being switched to. + public virtual void TransferTo(WorkingBeatmap other) { if (track.IsResultAvailable && Track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo)) other.track = track; - - if (background.IsResultAvailable && Background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) - other.background = background; } public virtual void Dispose() { - if (BackgroundLoaded) Background?.Dispose(); - if (WaveformLoaded) Waveform?.Dispose(); - if (StoryboardLoaded) Storyboard?.Dispose(); - if (SkinLoaded) Skin?.Dispose(); + background.Recycle(); + waveform.Recycle(); + storyboard.Recycle(); + skin.Recycle(); } /// @@ -210,15 +193,15 @@ namespace osu.Game.Beatmaps mod.ApplyToClock(t); } - public class AsyncLazy + public class RecyclableLazy { - private Lazy> lazy; + private Lazy lazy; private readonly Func valueFactory; private readonly Func stillValidFunction; private readonly object initLock = new object(); - public AsyncLazy(Func valueFactory, Func stillValidFunction = null) + public RecyclableLazy(Func valueFactory, Func stillValidFunction = null) { this.valueFactory = valueFactory; this.stillValidFunction = stillValidFunction; @@ -230,20 +213,13 @@ namespace osu.Game.Beatmaps { if (!IsResultAvailable) return; - (lazy.Value.Result as IDisposable)?.Dispose(); + (lazy.Value as IDisposable)?.Dispose(); recreate(); } - public bool IsResultAvailable - { - get - { - recreateIfInvalid(); - return lazy.Value.IsCompleted; - } - } + public bool IsResultAvailable => stillValid; - public Task Value + public T Value { get { @@ -252,15 +228,17 @@ namespace osu.Game.Beatmaps } } + private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true); + private void recreateIfInvalid() { lock (initLock) { - if (!lazy.IsValueCreated || !lazy.Value.IsCompleted) + if (!lazy.IsValueCreated) // we have not yet been initialised or haven't run the task. return; - if (stillValidFunction?.Invoke(lazy.Value.Result) ?? true) + if (stillValid) // we are still in a valid state. return; @@ -268,7 +246,7 @@ namespace osu.Game.Beatmaps } } - private void recreate() => lazy = new Lazy>(() => Task.Run(valueFactory)); + private void recreate() => lazy = new Lazy(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication); } } } From 65018705f43bc99465572c1e983794365e784ff5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:09:57 +0900 Subject: [PATCH 250/277] Restore IsLoaded check --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 5802f64b96..9460512a8d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Catch.UI // this is required to make this run after the last caught fruit runs UpdateState at least once. // TODO: find a better alternative - if (lastPlateableFruit.LoadState > LoadState.Ready) + if (lastPlateableFruit.IsLoaded) action(); else lastPlateableFruit.OnLoadComplete = _ => action(); From 89a92ab7eb15c86130a7127aaa7e79b75c48d0dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:27:53 +0900 Subject: [PATCH 251/277] Fix potential thread-safety issue --- osu.Game/Beatmaps/WorkingBeatmap.cs | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 85b98413e5..a2b44aab52 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -199,7 +199,7 @@ namespace osu.Game.Beatmaps private readonly Func valueFactory; private readonly Func stillValidFunction; - private readonly object initLock = new object(); + private readonly object fetchLock = new object(); public RecyclableLazy(Func valueFactory, Func stillValidFunction = null) { @@ -223,29 +223,17 @@ namespace osu.Game.Beatmaps { get { - recreateIfInvalid(); - return lazy.Value; + lock (fetchLock) + { + if (!stillValid) + recreate(); + return lazy.Value; + } } } private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true); - private void recreateIfInvalid() - { - lock (initLock) - { - if (!lazy.IsValueCreated) - // we have not yet been initialised or haven't run the task. - return; - - if (stillValid) - // we are still in a valid state. - return; - - recreate(); - } - } - private void recreate() => lazy = new Lazy(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication); } } From 4ff66bf531fc32983880ae7a7f12c3efb8affbd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:14:29 +0900 Subject: [PATCH 252/277] Update in line with framework Image changes --- .../Objects/Drawables/Pieces/SliderBody.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 283d6b91f6..6f0197e711 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -7,14 +7,15 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.OpenGL.Textures; using osu.Framework.Graphics.Lines; using osu.Framework.Graphics.Textures; -using OpenTK; using OpenTK.Graphics.ES30; using OpenTK.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Rulesets.Objects.Types; +using OpenTK; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -43,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public double? SnakedEnd { get; private set; } private Color4 accentColour = Color4.White; + /// /// Used to colour the path. /// @@ -61,6 +63,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } private Color4 borderColour = Color4.White; + /// /// Used to colour the path border. /// @@ -85,6 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces private Vector2 topLeftOffset; private readonly Slider slider; + public SliderBody(Slider s) { slider = s; @@ -139,8 +143,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces var texture = new Texture(textureWidth, 1); //initialise background - var raw = new RawTexture(textureWidth, 1); - var bytes = raw.Data; + var raw = new Image(textureWidth, 1); const float aa_portion = 0.02f; const float border_portion = 0.128f; @@ -155,19 +158,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces if (progress <= border_portion) { - bytes[i * 4] = (byte)(BorderColour.R * 255); - bytes[i * 4 + 1] = (byte)(BorderColour.G * 255); - bytes[i * 4 + 2] = (byte)(BorderColour.B * 255); - bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * (BorderColour.A * 255)); + raw[i, 0] = new Rgba32(BorderColour.R, BorderColour.G, BorderColour.B, Math.Min(progress / aa_portion, 1) * BorderColour.A); } else { progress -= border_portion; - - bytes[i * 4] = (byte)(AccentColour.R * 255); - bytes[i * 4 + 1] = (byte)(AccentColour.G * 255); - bytes[i * 4 + 2] = (byte)(AccentColour.B * 255); - bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (AccentColour.A * 255)); + raw[i, 0] = new Rgba32(AccentColour.R, AccentColour.G, AccentColour.B, + (opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * AccentColour.A); } } From 29b0d62f213441c668572f56eee01bed9d663af5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:15:43 +0900 Subject: [PATCH 253/277] Changes in line with framework refcount changes --- .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 15 +++++++++++++-- osu.Game/Graphics/Backgrounds/Background.cs | 2 +- .../Graphics/Textures/LargeTextureStore.cs | 18 ------------------ osu.Game/OsuGameBase.cs | 3 +-- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- .../Drawables/DrawableStoryboard.cs | 4 +++- 7 files changed, 20 insertions(+), 26 deletions(-) delete mode 100644 osu.Game/Graphics/Textures/LargeTextureStore.cs diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 43ae30f780..77ff53b893 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Beatmaps.Formats; -using osu.Game.Graphics.Textures; using osu.Game.Skinning; using osu.Game.Storyboards; @@ -45,6 +44,10 @@ namespace osu.Game.Beatmaps private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath; + private LargeTextureStore textureStore; + + protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes. + protected override Texture GetBackground() { if (Metadata?.BackgroundFile == null) @@ -52,7 +55,7 @@ namespace osu.Game.Beatmaps try { - return new LargeTextureStore(new RawTextureLoaderStore(store)).Get(getPathForFile(Metadata.BackgroundFile)); + return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); } catch { @@ -73,6 +76,14 @@ namespace osu.Game.Beatmaps } } + public override void TransferTo(WorkingBeatmap other) + { + base.TransferTo(other); + + if (other is BeatmapManagerWorkingBeatmap owb && textureStore != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) + owb.textureStore = textureStore; + } + protected override Waveform GetWaveform() { try diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index d5825a8c42..6fc8b0e070 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -5,8 +5,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using OpenTK.Graphics; -using osu.Game.Graphics.Textures; namespace osu.Game.Graphics.Backgrounds { diff --git a/osu.Game/Graphics/Textures/LargeTextureStore.cs b/osu.Game/Graphics/Textures/LargeTextureStore.cs deleted file mode 100644 index 4dcbb1220d..0000000000 --- a/osu.Game/Graphics/Textures/LargeTextureStore.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics.Textures; -using osu.Framework.IO.Stores; - -namespace osu.Game.Graphics.Textures -{ - /// - /// A texture store that bypasses atlasing. - /// - public class LargeTextureStore : TextureStore - { - public LargeTextureStore(IResourceStore store = null) : base(store, false) - { - } - } -} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index bada2a794d..e3ce7a19f1 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -24,7 +24,6 @@ using osu.Framework.Input; using osu.Framework.Logging; using osu.Game.Audio; using osu.Game.Database; -using osu.Game.Graphics.Textures; using osu.Game.Input; using osu.Game.Input.Bindings; using osu.Game.IO; @@ -109,7 +108,7 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 63d29d5cd7..4e2109afd0 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament TextureStore flagStore = new TextureStore(); // Local flag store - flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); + flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); // Default texture store flagStore.AddStore(textures); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9c881c6abb..ce7edf8683 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); Samples = audioManager.GetSampleManager(storage); - Textures = new TextureStore(new RawTextureLoaderStore(storage)); + Textures = new TextureStore(new TextureLoaderStore(storage)); } public override Drawable GetDrawableComponent(string componentName) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index d746bb90c4..8053a7413c 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -22,6 +22,7 @@ namespace osu.Game.Storyboards.Drawables public override bool HandleMouseInput => false; private bool passing = true; + public bool Passing { get { return passing; } @@ -36,6 +37,7 @@ namespace osu.Game.Storyboards.Drawables public override bool RemoveCompletedTransforms => false; private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); @@ -57,7 +59,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); + dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From e63f60231a408162d0f41ddc733363cc0fbd0a11 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 13:27:17 +0900 Subject: [PATCH 254/277] Optimise carousel memory usage by unloading off-screen panels --- osu.Game/Screens/Select/BeatmapCarousel.cs | 11 ++++++++++- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 9 +++++++-- .../Screens/Select/Carousel/DrawableCarouselItem.cs | 13 ++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 7bb0b95b9a..4dbfe65ebf 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -424,7 +424,7 @@ namespace osu.Game.Screens.Select float drawHeight = DrawHeight; // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); + scrollableContent.RemoveAll(p => p.CanBeRemoved && (p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent)); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); @@ -486,6 +486,15 @@ namespace osu.Game.Screens.Select updateItem(p, halfHeight); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + // aggressively dispose "off-screen" items to reduce GC pressure. + foreach (var i in Items) + i.Dispose(); + } + private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet) { if (beatmapSet.Beatmaps.All(b => b.Hidden)) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index d554a22735..3fcea908a0 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,6 +30,7 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; + private DelayedLoadUnloadWrapper delayed; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) @@ -37,6 +38,10 @@ namespace osu.Game.Screens.Select.Carousel beatmapSet = set.BeatmapSet; } + public override bool CanBeRemoved => delayed?.DelayedLoadCompleted != true; + + protected override bool RequiresChildrenUpdate => true; + [BackgroundDependencyLoader(true)] private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { @@ -50,12 +55,12 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { - new DelayedLoadWrapper( + delayed = new DelayedLoadUnloadWrapper(() => new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { RelativeSizeAxes = Axes.Both, OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint), - }, 300 + }, 300, 5000 ), new FillFlowContainer { diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 8a0052559e..5bcf4e6441 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -24,6 +24,11 @@ namespace osu.Game.Screens.Select.Carousel public override bool IsPresent => base.IsPresent || Item.Visible; + /// + /// Whether this item can be removed from the scroll container (usually due to being off-screen). + /// + public virtual bool CanBeRemoved => true; + public readonly CarouselItem Item; private Container nestedContainer; @@ -86,7 +91,13 @@ namespace osu.Game.Screens.Select.Carousel base.OnHoverLost(state); } - public void SetMultiplicativeAlpha(float alpha) => borderContainer.Alpha = alpha; + protected bool VisibleInCarousel; + + public void SetMultiplicativeAlpha(float alpha) + { + borderContainer.Alpha = alpha; + VisibleInCarousel = alpha > 0; + } protected override void LoadComplete() { From 91aada8be59b227938f10a4c782bc9f719209037 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 14:20:29 +0900 Subject: [PATCH 255/277] Fix ScaleAdjust going missing --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 6987b6eea7..5e93c2547d 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -115,7 +115,7 @@ namespace osu.Game dependencies.Cache(LocalConfig); //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore()); + dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); From ccd7c1a17d10e43d5467c99197d7f6d54ef01181 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:04:33 +0900 Subject: [PATCH 256/277] Cancel request on disposal for safety --- osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 6cb85c778b..60811d8b12 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -134,5 +134,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores this.api = api; updateDisplay(); } + + protected override void Dispose(bool isDisposing) + { + getScoresRequest?.Cancel(); + } } } From c23b9b61a814e570635da4d08eb9fde16efb799b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:27:21 +0900 Subject: [PATCH 257/277] Simplify implementation in line with framework improvements --- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 +- .../Select/Carousel/DrawableCarouselBeatmapSet.cs | 7 +------ .../Screens/Select/Carousel/DrawableCarouselItem.cs | 13 +------------ 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 4dbfe65ebf..b6cbaf45e9 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -424,7 +424,7 @@ namespace osu.Game.Screens.Select float drawHeight = DrawHeight; // Remove all items that should no longer be on-screen - scrollableContent.RemoveAll(p => p.CanBeRemoved && (p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent)); + scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); // Find index range of all items that should be on-screen Trace.Assert(Items.Count == yPositions.Count); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 3fcea908a0..23f338b530 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -30,7 +30,6 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; - private DelayedLoadUnloadWrapper delayed; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) @@ -38,10 +37,6 @@ namespace osu.Game.Screens.Select.Carousel beatmapSet = set.BeatmapSet; } - public override bool CanBeRemoved => delayed?.DelayedLoadCompleted != true; - - protected override bool RequiresChildrenUpdate => true; - [BackgroundDependencyLoader(true)] private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { @@ -55,7 +50,7 @@ namespace osu.Game.Screens.Select.Carousel Children = new Drawable[] { - delayed = new DelayedLoadUnloadWrapper(() => + new DelayedLoadUnloadWrapper(() => new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 5bcf4e6441..8a0052559e 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -24,11 +24,6 @@ namespace osu.Game.Screens.Select.Carousel public override bool IsPresent => base.IsPresent || Item.Visible; - /// - /// Whether this item can be removed from the scroll container (usually due to being off-screen). - /// - public virtual bool CanBeRemoved => true; - public readonly CarouselItem Item; private Container nestedContainer; @@ -91,13 +86,7 @@ namespace osu.Game.Screens.Select.Carousel base.OnHoverLost(state); } - protected bool VisibleInCarousel; - - public void SetMultiplicativeAlpha(float alpha) - { - borderContainer.Alpha = alpha; - VisibleInCarousel = alpha > 0; - } + public void SetMultiplicativeAlpha(float alpha) => borderContainer.Alpha = alpha; protected override void LoadComplete() { From d05cd52d9aecc3e2cc3bf888291e413167bda555 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:38:15 +0900 Subject: [PATCH 258/277] Run the queue faster if multiple requests are pending --- osu.Game/Online/API/APIAccess.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index eb9a60115f..1dda257c95 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -163,14 +163,16 @@ namespace osu.Game.Online.API continue; } - APIRequest req = null; - - lock (queue) - if (queue.Count > 0) - req = queue.Dequeue(); - - if (req != null) + while (true) { + APIRequest req; + + lock (queue) + { + if (queue.Count == 0) break; + req = queue.Dequeue(); + } + // TODO: handle failures better handleRequest(req); } From 4e012042ab55d85af59f4c5cccd9a2abf3570956 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 17:57:09 +0900 Subject: [PATCH 259/277] Fix renaming variables too eagerly --- osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/Storyboards/Drawables/DrawableStoryboard.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 77ff53b893..cc70aa783f 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps try { - return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); + return (textureStore ?? (textureStore = new LargeTextureStore(new RawTextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile)); } catch { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e3ce7a19f1..a72abb8d4e 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -108,7 +108,7 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 4e2109afd0..63d29d5cd7 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament TextureStore flagStore = new TextureStore(); // Local flag store - flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); + flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); // Default texture store flagStore.AddStore(textures); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ce7edf8683..9c881c6abb 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); Samples = audioManager.GetSampleManager(storage); - Textures = new TextureStore(new TextureLoaderStore(storage)); + Textures = new TextureStore(new RawTextureLoaderStore(storage)); } public override Drawable GetDrawableComponent(string componentName) diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 8053a7413c..d0d4c678bf 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -59,7 +59,7 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(FileStore fileStore) { - dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); + dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false, scaleAdjust: 1)); foreach (var layer in Storyboard.Layers) Add(layer.CreateDrawable()); From 9f67119ba90244dbdc5fb5b2dd43c2c7d74f6db7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:01:32 +0900 Subject: [PATCH 260/277] Fix potential nullref in IsPresent override --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index e69f340184..10cd246172 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= HitObject.StartTime - HitObject.TimePreempt; private readonly ShakeContainer shakeContainer; From a1780fddc98fec5c353bf52cb23fe70606739655 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:02:04 +0900 Subject: [PATCH 261/277] DrawInfo -> DrawColourInfo --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- osu.Game/Graphics/Backgrounds/Triangles.cs | 4 ++-- osu.Game/Graphics/SpriteIcon.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index abcd1ddbda..4a6b12d41a 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor Texture.DrawQuad( new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), - DrawInfo.Colour, + DrawColourInfo.Colour, null, v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex { diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 01b09c0a40..0f382900ce 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -116,7 +116,7 @@ namespace osu.Game.Graphics.Backgrounds float adjustedAlpha = HideAlphaDiscrepancies ? // Cubically scale alpha to make it drop off more sharply. - (float)Math.Pow(DrawInfo.Colour.AverageColour.Linear.A, 3) : + (float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) : 1; float elapsedSeconds = (float)Time.Elapsed / 1000; @@ -235,7 +235,7 @@ namespace osu.Game.Graphics.Backgrounds Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix) ); - ColourInfo colourInfo = DrawInfo.Colour; + ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(particle.Colour); Texture.DrawTriangle( diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index b72ba7e02f..1b1df45c77 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -95,7 +95,7 @@ namespace osu.Game.Graphics { //adjust shadow alpha based on highest component intensity to avoid muddy display of darker text. //squared result for quadratic fall-off seems to give the best result. - var avgColour = (Color4)DrawInfo.Colour.AverageColour; + var avgColour = (Color4)DrawColourInfo.Colour.AverageColour; spriteShadow.Alpha = (float)Math.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2); diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index fb6130fa36..a3cb2f13d0 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy; - ColourInfo colourInfo = DrawInfo.Colour; + ColourInfo colourInfo = DrawColourInfo.Colour; colourInfo.ApplyChild(Colour); if (AudioData != null) From da906c0ddf43f6c896f6e27cfe93d82d9f598e9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 18:03:27 +0900 Subject: [PATCH 262/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 669b775674..b3df528043 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 1327aed16411a5030a49a9eef4cda420ffc033c9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 19:23:19 +0900 Subject: [PATCH 263/277] Update framework again --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b3df528043..cb553731c3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From 1e39b84089c8d040f92a29327a1619e773dae01b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 6 Sep 2018 23:49:54 +0900 Subject: [PATCH 264/277] Increase visibility of osu!mania long notes --- .../Objects/Drawables/DrawableHoldNote.cs | 19 +++++++++++--- .../Objects/Drawables/Pieces/BodyPiece.cs | 25 +++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index af2a889f03..6a0457efc6 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -111,6 +111,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2; } + protected void BeginHold() + { + holdStartTime = Time.Current; + bodyPiece.Hitting = true; + } + + protected void EndHold() + { + holdStartTime = null; + bodyPiece.Hitting = false; + } + public bool OnPressed(ManiaAction action) { // Make sure the action happened within the body of the hold note @@ -123,8 +135,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // The user has pressed during the body of the hold note, after the head note and its hit windows have passed // and within the limited range of the above if-statement. This state will be managed by the head note if the // user has pressed during the hit windows of the head note. - holdStartTime = Time.Current; - + BeginHold(); return true; } @@ -137,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (action != Action.Value) return false; - holdStartTime = null; + EndHold(); // If the key has been released too early, the user should not receive full score for the release if (!Tail.IsHit) @@ -170,7 +181,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables // The head note also handles early hits before the body, but we want accurate early hits to count as the body being held // The body doesn't handle these early early hits, so we have to explicitly set the holding state here - holdNote.holdStartTime = Time.Current; + holdNote.BeginHold(); return true; } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 4ab2da208a..01bc02b15a 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces background = new Box { RelativeSizeAxes = Axes.Both }, foreground = new BufferedContainer { + Blending = BlendingMode.Additive, RelativeSizeAxes = Axes.Both, CacheDrawnFrameBuffer = true, Children = new Drawable[] @@ -73,6 +74,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } private Color4 accentColour; + public Color4 AccentColour { get { return accentColour; } @@ -86,6 +88,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } } + public bool Hitting + { + get { return hitting; } + set + { + hitting = value; + updateAccentColour(); + } + } + private Cached subtractionCache = new Cached(); public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) @@ -118,13 +130,22 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces } } + private bool hitting; + private void updateAccentColour() { if (!IsLoaded) return; - foreground.Colour = AccentColour.Opacity(0.9f); - background.Colour = AccentColour.Opacity(0.6f); + foreground.Colour = AccentColour.Opacity(0.5f); + background.Colour = AccentColour.Opacity(0.7f); + + if (hitting) + foreground.FadeColour(AccentColour.Lighten(0.3f), 50).Then().FadeColour(foreground.Colour, 50).Loop(); + else + { + foreground.ClearTransforms(false, nameof(foreground.Colour)); + } subtractionCache.Invalidate(); } From a2ba68d147e99b736df230b0dfa48dc0bf4cd103 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 03:18:39 +0900 Subject: [PATCH 265/277] Mention LD_LIBRARY_PATH requirement for linux building in README Closes #3257. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a1f478e39a..dc36145337 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Clone the repository including submodules Build and run - Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included) -- From command line using `dotnet run --project osu.Desktop` +- From command line using `dotnet run --project osu.Desktop`. When building for non-development purposes, add `-c Release` to gain higher performance. + +Note: If you run from command line under linux, you will need to prefix the output folder to your `LD_LIBRARY_PATH`. See `.vscode/launch.json` for an example If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build. From f76d00e8aee43920d978e6551d3c0b52e7312ee7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 14:31:38 +0900 Subject: [PATCH 266/277] Simplify null checks --- .../Sections/Graphics/LayoutSettings.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 4d3cdacb6a..0c463ce142 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -101,18 +101,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } - private List> getResolutions() - { - if (game.Window == null) - return new List>(); - - return game.Window?.AvailableResolutions - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width) - .ThenByDescending(r => r.Height) - .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) - .Distinct() - .ToList(); - } + private IEnumerable> getResolutions() => + game.Window?.AvailableResolutions? + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width) + .ThenByDescending(r => r.Height) + .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) + .Distinct() + .ToList() ?? Enumerable.Empty>(); } } From bf0ad723f594f567124db69804e4c7b743b92733 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 14:35:38 +0900 Subject: [PATCH 267/277] Add default fallback for headless operation --- osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 0c463ce142..548d49bd36 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -6,6 +6,7 @@ using System.Drawing; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Configuration; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -108,6 +109,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics .ThenByDescending(r => r.Height) .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) .Distinct() - .ToList() ?? Enumerable.Empty>(); + .ToList() ?? new KeyValuePair("Default", new Size(9999, 9999)).Yield(); } } From 2c0ba401d529ad4de98e3f5df56f736a0280ac43 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 16:30:11 +0900 Subject: [PATCH 268/277] Add ability to click on imported complete notification to present last import --- osu.Game/Beatmaps/BeatmapManager.cs | 9 ++++++++- osu.Game/Database/ArchiveModelManager.cs | 12 +++++++++++- .../Overlays/Notifications/ProgressNotification.cs | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index f676927404..eb30525e80 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; using osu.Framework.Logging; using osu.Framework.Platform; @@ -195,7 +196,7 @@ namespace osu.Game.Beatmaps downloadNotification.CompletionClickAction = () => { - PresentBeatmap?.Invoke(importedBeatmap); + PresentCompletedImport(importedBeatmap.Yield()); return true; }; downloadNotification.State = ProgressNotificationState.Completed; @@ -231,6 +232,12 @@ namespace osu.Game.Beatmaps BeatmapDownloadBegan?.Invoke(request); } + protected override void PresentCompletedImport(IEnumerable imported) + { + base.PresentCompletedImport(imported); + PresentBeatmap?.Invoke(imported.LastOrDefault()); + } + /// /// Get an existing download request if it exists. /// diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 326d042c39..e85d6f29aa 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -166,10 +166,20 @@ namespace osu.Game.Database } } - notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!"; + notification.CompletionText = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!"; + notification.CompletionClickAction += () => + { + if (imported.Count > 0) + PresentCompletedImport(imported); + return true; + }; notification.State = ProgressNotificationState.Completed; } + protected virtual void PresentCompletedImport(IEnumerable imported) + { + } + /// /// Import an item from an . /// diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index 7a07fb970c..254258d098 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -169,7 +169,7 @@ namespace osu.Game.Overlays.Notifications public Action CompletionTarget { get; set; } /// - /// An action to complete when the completion notification is clicked. + /// An action to complete when the completion notification is clicked. Return true to close. /// public Func CompletionClickAction; From ced6e5efd09788de3133e14d043a2f337c68f85c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 16:29:29 +0900 Subject: [PATCH 269/277] Synchronise animation; reduce flashiness --- .../Objects/Drawables/Pieces/BodyPiece.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index 01bc02b15a..619fe06c73 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -140,11 +140,15 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces foreground.Colour = AccentColour.Opacity(0.5f); background.Colour = AccentColour.Opacity(0.7f); + const float animation_length = 50; + + foreground.ClearTransforms(false, nameof(foreground.Colour)); if (hitting) - foreground.FadeColour(AccentColour.Lighten(0.3f), 50).Then().FadeColour(foreground.Colour, 50).Loop(); - else { - foreground.ClearTransforms(false, nameof(foreground.Colour)); + // wait for the next sync point + double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2); + using (foreground.BeginDelayedSequence(synchronisedOffset)) + foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(foreground.Colour, animation_length).Loop(); } subtractionCache.Invalidate(); From 168dbe9329c3f390c19a9f3976b04e3595ccc165 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 18:14:23 +0900 Subject: [PATCH 270/277] Fix error notification --- osu.Game/Database/ArchiveModelManager.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 234e1a9bd6..0564f1eb76 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -130,7 +130,6 @@ namespace osu.Game.Database List imported = new List(); int current = 0; - int errors = 0; foreach (string path in paths) { if (notification.State == ProgressNotificationState.Cancelled) @@ -163,13 +162,19 @@ namespace osu.Game.Database { e = e.InnerException ?? e; Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); - errors++; } } - notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!"; - notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!"; - notification.State = ProgressNotificationState.Completed; + if (imported.Count == 0) + { + notification.Text = "Import failed!"; + notification.State = ProgressNotificationState.Cancelled; + } + else + { + notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!"; + notification.State = ProgressNotificationState.Completed; + } } /// From 75d2cb199cb858a68fa01eac2370d02e598c40d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 18:14:27 +0900 Subject: [PATCH 271/277] Fix formatting --- osu.Game/Skinning/SkinManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index 74222da4a2..bd694e443a 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -93,7 +93,8 @@ namespace osu.Game.Skinning { this.audio = audio; - ItemRemoved += removedInfo => { + ItemRemoved += removedInfo => + { // check the removed skin is not the current user choice. if it is, switch back to default. if (removedInfo.ID == CurrentSkinInfo.Value.ID) CurrentSkinInfo.Value = SkinInfo.Default; From cc533a05c57916facbd1b5a260cfa7794180b666 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 18:56:08 +0900 Subject: [PATCH 272/277] Update framework --- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- osu.Game/osu.Game.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 0037ecf335..80520a1c31 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -108,7 +108,7 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 63d29d5cd7..4e2109afd0 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament TextureStore flagStore = new TextureStore(); // Local flag store - flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); + flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore(new StorageBackedResourceStore(storage), "Drawings"))); // Default texture store flagStore.AddStore(textures); diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9c881c6abb..ce7edf8683 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -37,7 +37,7 @@ namespace osu.Game.Skinning Configuration = new SkinConfiguration(); Samples = audioManager.GetSampleManager(storage); - Textures = new TextureStore(new RawTextureLoaderStore(storage)); + Textures = new TextureStore(new TextureLoaderStore(storage)); } public override Drawable GetDrawableComponent(string componentName) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index cb553731c3..6401a0eb1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - + From c1cdff8505dd03a1f4c6465b1529a1d7abdeb7e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Sep 2018 19:29:51 +0900 Subject: [PATCH 273/277] Add default resolution to avoid crashing --- .../Sections/Graphics/LayoutSettings.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 548d49bd36..4a8164c6df 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -102,13 +102,18 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics }, true); } - private IEnumerable> getResolutions() => - game.Window?.AvailableResolutions? - .Where(r => r.Width >= 800 && r.Height >= 600) - .OrderByDescending(r => r.Width) - .ThenByDescending(r => r.Height) - .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) - .Distinct() - .ToList() ?? new KeyValuePair("Default", new Size(9999, 9999)).Yield(); + private IEnumerable> getResolutions() + { + var resolutions = new KeyValuePair("Default", new Size(9999, 9999)).Yield(); + + if (game.Window != null) + resolutions = resolutions.Concat(game.Window.AvailableResolutions + .Where(r => r.Width >= 800 && r.Height >= 600) + .OrderByDescending(r => r.Width) + .ThenByDescending(r => r.Height) + .Select(res => new KeyValuePair($"{res.Width}x{res.Height}", new Size(res.Width, res.Height))) + .Distinct()).ToList(); + return resolutions; + } } } From 6c150c9ed793799fd6672cc2107c97c2e3844a09 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Sep 2018 03:21:42 +0900 Subject: [PATCH 274/277] Remove unnecessary override --- osu.Game/Overlays/Direct/DirectPanel.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 8a22ff7587..2ee1857ca2 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -104,8 +104,6 @@ namespace osu.Game.Overlays.Direct beatmaps.ItemAdded += setAdded; } - public override bool DisposeOnDeathRemoval => true; - protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From f149a66a4dff892d23c84580a62c3bf718a8c3a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Sep 2018 02:41:47 +0900 Subject: [PATCH 275/277] Use LargeTextureStore for all online texture retrieval Until now, many online textures were retrieved via the default texture store, which causes them to never be removed from GPU memory. It also has a performance overhead due to mipmap generation (which will be avoided via ppy/osu-framework#1885. --- osu.Game/OsuGameBase.cs | 4 +++- osu.Game/Overlays/MedalSplash/DrawableMedal.cs | 4 ++-- osu.Game/Overlays/Profile/Header/BadgeContainer.cs | 2 +- osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs | 2 +- osu.Game/Screens/Ranking/ResultsPageScore.cs | 2 +- osu.Game/Users/Avatar.cs | 2 +- osu.Game/Users/UserCoverBackground.cs | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 80520a1c31..9a5dac35b9 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -108,7 +108,9 @@ namespace osu.Game dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage)); - dependencies.Cache(new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); + var largeStore = new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures"))); + largeStore.AddStore(new TextureLoaderStore(new OnlineStore())); + dependencies.Cache(largeStore); dependencies.CacheAs(this); dependencies.Cache(LocalConfig); diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index a27278e002..629b6d6fa4 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -118,9 +118,9 @@ namespace osu.Game.Overlays.MedalSplash } [BackgroundDependencyLoader] - private void load(OsuColour colours, TextureStore textures) + private void load(OsuColour colours, TextureStore textures, LargeTextureStore largeTextures) { - medalSprite.Texture = textures.Get(medal.ImageUrl); + medalSprite.Texture = largeTextures.Get(medal.ImageUrl); medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow"); description.Colour = colours.BlueLight; } diff --git a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs index bfade5e45c..33baaf1fff 100644 --- a/osu.Game/Overlays/Profile/Header/BadgeContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BadgeContainer.cs @@ -176,7 +176,7 @@ namespace osu.Game.Overlays.Profile.Header } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { Child = new Sprite { diff --git a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs index 0d354c728f..45569271df 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/MedalIcon.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { sprite.Texture = textures.Get(url); } diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 42d8af07b9..6fa41202a4 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -368,7 +368,7 @@ namespace osu.Game.Screens.Ranking } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { if (!string.IsNullOrEmpty(user.CoverUrl)) cover.Texture = textures.Get(user.CoverUrl); diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 9ba9549164..e6e1ba3c53 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -24,7 +24,7 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 58b92b2750..fddbd57f9c 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -18,7 +18,7 @@ namespace osu.Game.Users } [BackgroundDependencyLoader] - private void load(TextureStore textures) + private void load(LargeTextureStore textures) { if (textures == null) throw new ArgumentNullException(nameof(textures)); From 92386edb32e54a65774ebcf52f53505170ccaef8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 10 Sep 2018 18:13:44 +0900 Subject: [PATCH 276/277] Scale the results screen score to keep it in view --- osu.Game/Screens/Ranking/ResultsPageScore.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 6fa41202a4..040458e0eb 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -29,6 +29,7 @@ namespace osu.Game.Screens.Ranking { public class ResultsPageScore : ResultsPage { + private Container scoreContainer; private ScoreCounter scoreCounter; public ResultsPageScore(Score score, WorkingBeatmap beatmap) : base(score, beatmap) { } @@ -76,7 +77,7 @@ namespace osu.Game.Screens.Ranking Size = new Vector2(150, 60), Margin = new MarginPadding(20), }, - new Container + scoreContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, @@ -92,8 +93,8 @@ namespace osu.Game.Screens.Ranking }, scoreCounter = new SlowScoreCounter(6) { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Colour = colours.PinkDarker, Y = 10, TextSize = 56, @@ -185,6 +186,13 @@ namespace osu.Game.Screens.Ranking }); } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + scoreCounter.Scale = new Vector2(Math.Min(1f, (scoreContainer.DrawWidth - 20) / scoreCounter.DrawWidth)); + } + private class DrawableScoreStatistic : Container { private readonly KeyValuePair statistic; From 144779c698e5372409b2691cfbcb2f123850d39e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 11 Sep 2018 00:30:13 +0900 Subject: [PATCH 277/277] Update framework --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 6401a0eb1b..3e16e90d06 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,7 +18,7 @@ - +