Merge remote-tracking branch 'refs/remotes/upstream/master' into fallback-to-skin-combo-colours

This commit is contained in:
iiSaLMaN
2019-11-07 19:11:29 +03:00
288 changed files with 8884 additions and 2334 deletions

View File

@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.TypeExtensions;
@ -37,7 +39,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
protected virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
private readonly Lazy<List<DrawableHitObject>> nestedHitObjects = new Lazy<List<DrawableHitObject>>();
public IEnumerable<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty<DrawableHitObject>();
public IReadOnlyList<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : (IReadOnlyList<DrawableHitObject>)Array.Empty<DrawableHitObject>();
/// <summary>
/// Invoked when a <see cref="JudgementResult"/> has been applied by this <see cref="DrawableHitObject"/> or a nested <see cref="DrawableHitObject"/>.
@ -76,6 +78,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// </summary>
public JudgementResult Result { get; private set; }
private Bindable<double> startTimeBindable;
private Bindable<int> comboIndexBindable;
public override bool RemoveWhenNotAlive => false;
@ -88,9 +91,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
public IBindable<ArmedState> State => state;
protected DrawableHitObject(HitObject hitObject)
protected DrawableHitObject([NotNull] HitObject hitObject)
{
HitObject = hitObject;
HitObject = hitObject ?? throw new ArgumentNullException(nameof(hitObject));
}
[BackgroundDependencyLoader]
@ -125,13 +128,83 @@ namespace osu.Game.Rulesets.Objects.Drawables
{
base.LoadComplete();
HitObject.DefaultsApplied += onDefaultsApplied;
startTimeBindable = HitObject.StartTimeBindable.GetBoundCopy();
startTimeBindable.BindValueChanged(_ => updateState(ArmedState.Idle, true));
if (HitObject is IHasComboInformation combo)
{
comboIndexBindable = combo.ComboIndexBindable.GetBoundCopy();
comboIndexBindable.BindValueChanged(_ => updateAccentColour());
comboIndexBindable.BindValueChanged(_ => updateAccentColour(), true);
}
updateState(ArmedState.Idle, true);
onDefaultsApplied();
}
private void onDefaultsApplied() => apply(HitObject);
private void apply(HitObject hitObject)
{
#pragma warning disable 618 // can be removed 20200417
if (GetType().GetMethod(nameof(AddNested), BindingFlags.NonPublic | BindingFlags.Instance)?.DeclaringType != typeof(DrawableHitObject))
return;
#pragma warning restore 618
if (nestedHitObjects.IsValueCreated)
{
nestedHitObjects.Value.Clear();
ClearNestedHitObjects();
}
foreach (var h in hitObject.NestedHitObjects)
{
var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}.");
addNested(drawableNested);
AddNestedHitObject(drawableNested);
}
}
/// <summary>
/// Invoked by the base <see cref="DrawableHitObject"/> to add nested <see cref="DrawableHitObject"/>s to the hierarchy.
/// </summary>
/// <param name="hitObject">The <see cref="DrawableHitObject"/> to be added.</param>
protected virtual void AddNestedHitObject(DrawableHitObject hitObject)
{
}
/// <summary>
/// Adds a nested <see cref="DrawableHitObject"/>. This should not be used except for legacy nested <see cref="DrawableHitObject"/> usages.
/// </summary>
/// <param name="h"></param>
[Obsolete("Use AddNestedHitObject() / ClearNestedHitObjects() / CreateNestedHitObject() instead.")] // can be removed 20200417
protected virtual void AddNested(DrawableHitObject h) => addNested(h);
/// <summary>
/// Invoked by the base <see cref="DrawableHitObject"/> to remove all previously-added nested <see cref="DrawableHitObject"/>s.
/// </summary>
protected virtual void ClearNestedHitObjects()
{
}
/// <summary>
/// Creates the drawable representation for a nested <see cref="HitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="HitObject"/>.</param>
/// <returns>The drawable representation for <paramref name="hitObject"/>.</returns>
protected virtual DrawableHitObject CreateNestedHitObject(HitObject hitObject) => null;
private void addNested(DrawableHitObject hitObject)
{
// Todo: Exists for legacy purposes, can be removed 20200417
hitObject.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
hitObject.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r);
hitObject.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
nestedHitObjects.Value.Add(hitObject);
}
#region State / Transform Management
@ -173,7 +246,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
{
UpdateInitialTransforms();
var judgementOffset = Math.Min(HitObject.HitWindows?.WindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0);
var judgementOffset = Result?.TimeOffset ?? 0;
using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true))
{
@ -356,15 +429,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
UpdateResult(false);
}
protected virtual void AddNested(DrawableHitObject h)
{
h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
h.OnRevertResult += (d, r) => OnRevertResult?.Invoke(d, r);
h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
nestedHitObjects.Value.Add(h);
}
/// <summary>
/// Applies the <see cref="Result"/> of this <see cref="DrawableHitObject"/>, notifying responders such as
/// the <see cref="ScoreProcessor"/> of the <see cref="JudgementResult"/>.
@ -379,7 +443,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
// 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 = Math.Min(HitObject.HitWindows.WindowFor(HitResult.Miss), Time.Current - endTime);
switch (Result.Type)
{
@ -436,6 +501,12 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// </summary>
/// <param name="judgement">The <see cref="Judgement"/> that provides the scoring information.</param>
protected virtual JudgementResult CreateResult(Judgement judgement) => new JudgementResult(HitObject, judgement);
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
HitObject.DefaultsApplied -= onDefaultsApplied;
}
}
public abstract class DrawableHitObject<TObject> : DrawableHitObject

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
@ -28,6 +29,11 @@ namespace osu.Game.Rulesets.Objects
/// </summary>
private const double control_point_leniency = 1;
/// <summary>
/// Invoked after <see cref="ApplyDefaults"/> has completed on this <see cref="HitObject"/>.
/// </summary>
public event Action DefaultsApplied;
public readonly Bindable<double> StartTimeBindable = new Bindable<double>();
/// <summary>
@ -66,7 +72,6 @@ namespace osu.Game.Rulesets.Objects
/// <summary>
/// The hit windows for this <see cref="HitObject"/>.
/// </summary>
[CanBeNull]
public HitWindows HitWindows { get; set; }
private readonly List<HitObject> nestedHitObjects = new List<HitObject>();
@ -113,10 +118,9 @@ namespace osu.Game.Rulesets.Objects
nestedHitObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
foreach (var h in nestedHitObjects)
{
h.HitWindows = HitWindows;
h.ApplyDefaults(controlPointInfo, difficulty);
}
DefaultsApplied?.Invoke();
}
protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
@ -147,7 +151,7 @@ namespace osu.Game.Rulesets.Objects
/// This will only be invoked if <see cref="HitWindows"/> hasn't been set externally (e.g. from a <see cref="BeatmapConverter{T}"/>.
/// </para>
/// </summary>
[CanBeNull]
[NotNull]
protected virtual HitWindows CreateHitWindows() => new HitWindows();
}
}

View File

@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
public float X { get; set; }
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -14,6 +14,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
public double Duration => EndTime - StartTime;
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
{
public float X { get; set; }
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -17,6 +17,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
public float X { get; set; }
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public int ComboOffset { get; set; }
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public int ComboOffset { get; set; }
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public float Y => Position.Y;
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
public bool NewCombo { get; set; }

View File

@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// </summary>
internal sealed class ConvertHit : HitObject
{
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -10,6 +10,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// </summary>
internal sealed class ConvertSlider : Legacy.ConvertSlider
{
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
public double Duration => EndTime - StartTime;
protected override HitWindows CreateHitWindows() => null;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}