mirror of
https://github.com/osukey/osukey.git
synced 2025-08-03 14:46:38 +09:00
Merge branch 'master' into refactor-framed-replay-input-hander
This commit is contained in:
24
osu.Game/Rulesets/Edit/BeatmapVerifier.cs
Normal file
24
osu.Game/Rulesets/Edit/BeatmapVerifier.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// A ruleset-agnostic beatmap verifier that identifies issues in common metadata or mapping standards.
|
||||
/// </summary>
|
||||
public class BeatmapVerifier : IBeatmapVerifier
|
||||
{
|
||||
private readonly List<ICheck> checks = new List<ICheck>
|
||||
{
|
||||
new CheckBackground(),
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap beatmap) => checks.SelectMany(check => check.Run(beatmap));
|
||||
}
|
||||
}
|
61
osu.Game/Rulesets/Edit/Checks/CheckBackground.cs
Normal file
61
osu.Game/Rulesets/Edit/Checks/CheckBackground.cs
Normal file
@ -0,0 +1,61 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
public class CheckBackground : ICheck
|
||||
{
|
||||
public CheckMetadata Metadata { get; } = new CheckMetadata(CheckCategory.Resources, "Missing background");
|
||||
|
||||
public IEnumerable<IssueTemplate> PossibleTemplates => new IssueTemplate[]
|
||||
{
|
||||
new IssueTemplateNoneSet(this),
|
||||
new IssueTemplateDoesNotExist(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(IBeatmap beatmap)
|
||||
{
|
||||
if (beatmap.Metadata.BackgroundFile == null)
|
||||
{
|
||||
yield return new IssueTemplateNoneSet(this).Create();
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
// If the background is set, also make sure it still exists.
|
||||
|
||||
var set = beatmap.BeatmapInfo.BeatmapSet;
|
||||
var file = set.Files.FirstOrDefault(f => f.Filename == beatmap.Metadata.BackgroundFile);
|
||||
|
||||
if (file != null)
|
||||
yield break;
|
||||
|
||||
yield return new IssueTemplateDoesNotExist(this).Create(beatmap.Metadata.BackgroundFile);
|
||||
}
|
||||
|
||||
public class IssueTemplateNoneSet : IssueTemplate
|
||||
{
|
||||
public IssueTemplateNoneSet(ICheck check)
|
||||
: base(check, IssueType.Problem, "No background has been set.")
|
||||
{
|
||||
}
|
||||
|
||||
public Issue Create() => new Issue(this);
|
||||
}
|
||||
|
||||
public class IssueTemplateDoesNotExist : IssueTemplate
|
||||
{
|
||||
public IssueTemplateDoesNotExist(ICheck check)
|
||||
: base(check, IssueType.Problem, "The background file \"{0}\" does not exist.")
|
||||
{
|
||||
}
|
||||
|
||||
public Issue Create(string filename) => new Issue(this, filename);
|
||||
}
|
||||
}
|
||||
}
|
61
osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs
Normal file
61
osu.Game/Rulesets/Edit/Checks/Components/CheckCategory.cs
Normal file
@ -0,0 +1,61 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// The category of an issue.
|
||||
/// </summary>
|
||||
public enum CheckCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// Anything to do with control points.
|
||||
/// </summary>
|
||||
Timing,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with artist, title, creator, etc.
|
||||
/// </summary>
|
||||
Metadata,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with non-audio files, e.g. background, skin, sprites, and video.
|
||||
/// </summary>
|
||||
Resources,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with audio files, e.g. song and hitsounds.
|
||||
/// </summary>
|
||||
Audio,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with files that don't fit into the above, e.g. unused, osu, or osb.
|
||||
/// </summary>
|
||||
Files,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with hitobjects unrelated to spread.
|
||||
/// </summary>
|
||||
Compose,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with difficulty levels or their progression.
|
||||
/// </summary>
|
||||
Spread,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with variables like CS, OD, AR, HP, and global SV.
|
||||
/// </summary>
|
||||
Settings,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with hitobject feedback.
|
||||
/// </summary>
|
||||
HitObjects,
|
||||
|
||||
/// <summary>
|
||||
/// Anything to do with storyboarding, breaks, video offset, etc.
|
||||
/// </summary>
|
||||
Events
|
||||
}
|
||||
}
|
24
osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs
Normal file
24
osu.Game/Rulesets/Edit/Checks/Components/CheckMetadata.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
public class CheckMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// The category this check belongs to. E.g. <see cref="CheckCategory.Metadata"/>, <see cref="CheckCategory.Timing"/>, or <see cref="CheckCategory.Compose"/>.
|
||||
/// </summary>
|
||||
public readonly CheckCategory Category;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the issue(s) that this check looks for. Keep this brief, such that it fits into "No {description}". E.g. "Offscreen objects" / "Too short sliders".
|
||||
/// </summary>
|
||||
public readonly string Description;
|
||||
|
||||
public CheckMetadata(CheckCategory category, string description)
|
||||
{
|
||||
Category = category;
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
}
|
30
osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs
Normal file
30
osu.Game/Rulesets/Edit/Checks/Components/ICheck.cs
Normal file
@ -0,0 +1,30 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A specific check that can be run on a beatmap to verify or find issues.
|
||||
/// </summary>
|
||||
public interface ICheck
|
||||
{
|
||||
/// <summary>
|
||||
/// The metadata for this check.
|
||||
/// </summary>
|
||||
public CheckMetadata Metadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All possible templates for issues that this check may return.
|
||||
/// </summary>
|
||||
public IEnumerable<IssueTemplate> PossibleTemplates { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Runs this check and returns any issues detected for the provided beatmap.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to run the check on.</param>
|
||||
public IEnumerable<Issue> Run(IBeatmap beatmap);
|
||||
}
|
||||
}
|
77
osu.Game/Rulesets/Edit/Checks/Components/Issue.cs
Normal file
77
osu.Game/Rulesets/Edit/Checks/Components/Issue.cs
Normal file
@ -0,0 +1,77 @@
|
||||
// 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 osu.Game.Extensions;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
public class Issue
|
||||
{
|
||||
/// <summary>
|
||||
/// The time which this issue is associated with, if any, otherwise null.
|
||||
/// </summary>
|
||||
public double? Time;
|
||||
|
||||
/// <summary>
|
||||
/// The hitobjects which this issue is associated with. Empty by default.
|
||||
/// </summary>
|
||||
public IReadOnlyList<HitObject> HitObjects;
|
||||
|
||||
/// <summary>
|
||||
/// The template which this issue is using. This provides properties such as the <see cref="IssueType"/>, and the <see cref="IssueTemplate.UnformattedMessage"/>.
|
||||
/// </summary>
|
||||
public IssueTemplate Template;
|
||||
|
||||
/// <summary>
|
||||
/// The check that this issue originates from.
|
||||
/// </summary>
|
||||
public ICheck Check => Template.Check;
|
||||
|
||||
/// <summary>
|
||||
/// The arguments that give this issue its context, based on the <see cref="IssueTemplate"/>. These are then substituted into the <see cref="IssueTemplate.UnformattedMessage"/>.
|
||||
/// This could for instance include timestamps, which diff is being compared to, what some volume is, etc.
|
||||
/// </summary>
|
||||
public object[] Arguments;
|
||||
|
||||
public Issue(IssueTemplate template, params object[] args)
|
||||
{
|
||||
Time = null;
|
||||
HitObjects = Array.Empty<HitObject>();
|
||||
Template = template;
|
||||
Arguments = args;
|
||||
}
|
||||
|
||||
public Issue(double? time, IssueTemplate template, params object[] args)
|
||||
: this(template, args)
|
||||
{
|
||||
Time = time;
|
||||
}
|
||||
|
||||
public Issue(HitObject hitObject, IssueTemplate template, params object[] args)
|
||||
: this(template, args)
|
||||
{
|
||||
Time = hitObject.StartTime;
|
||||
HitObjects = new[] { hitObject };
|
||||
}
|
||||
|
||||
public Issue(IEnumerable<HitObject> hitObjects, IssueTemplate template, params object[] args)
|
||||
: this(template, args)
|
||||
{
|
||||
var hitObjectList = hitObjects.ToList();
|
||||
|
||||
Time = hitObjectList.FirstOrDefault()?.StartTime;
|
||||
HitObjects = hitObjectList;
|
||||
}
|
||||
|
||||
public override string ToString() => Template.GetMessage(Arguments);
|
||||
|
||||
public string GetEditorTimestamp()
|
||||
{
|
||||
return Time == null ? string.Empty : Time.Value.ToEditorFormattedString();
|
||||
}
|
||||
}
|
||||
}
|
74
osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs
Normal file
74
osu.Game/Rulesets/Edit/Checks/Components/IssueTemplate.cs
Normal file
@ -0,0 +1,74 @@
|
||||
// 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 Humanizer;
|
||||
using osu.Framework.Graphics;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
public class IssueTemplate
|
||||
{
|
||||
private static readonly Color4 problem_red = new Colour4(1.0f, 0.4f, 0.4f, 1.0f);
|
||||
private static readonly Color4 warning_yellow = new Colour4(1.0f, 0.8f, 0.2f, 1.0f);
|
||||
private static readonly Color4 negligible_green = new Colour4(0.33f, 0.8f, 0.5f, 1.0f);
|
||||
private static readonly Color4 error_gray = new Colour4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// The check that this template originates from.
|
||||
/// </summary>
|
||||
public readonly ICheck Check;
|
||||
|
||||
/// <summary>
|
||||
/// The type of the issue.
|
||||
/// </summary>
|
||||
public readonly IssueType Type;
|
||||
|
||||
/// <summary>
|
||||
/// The unformatted message given when this issue is detected.
|
||||
/// This gets populated later when an issue is constructed with this template.
|
||||
/// E.g. "Inconsistent snapping (1/{0}) with [{1}] (1/{2})."
|
||||
/// </summary>
|
||||
public readonly string UnformattedMessage;
|
||||
|
||||
public IssueTemplate(ICheck check, IssueType type, string unformattedMessage)
|
||||
{
|
||||
Check = check;
|
||||
Type = type;
|
||||
UnformattedMessage = unformattedMessage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the formatted message given the arguments used to format it.
|
||||
/// </summary>
|
||||
/// <param name="args">The arguments used to format the message.</param>
|
||||
public string GetMessage(params object[] args) => UnformattedMessage.FormatWith(args);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the colour corresponding to the type of this issue.
|
||||
/// </summary>
|
||||
public Colour4 Colour
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case IssueType.Problem:
|
||||
return problem_red;
|
||||
|
||||
case IssueType.Warning:
|
||||
return warning_yellow;
|
||||
|
||||
case IssueType.Negligible:
|
||||
return negligible_green;
|
||||
|
||||
case IssueType.Error:
|
||||
return error_gray;
|
||||
|
||||
default:
|
||||
return Color4.White;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs
Normal file
25
osu.Game/Rulesets/Edit/Checks/Components/IssueType.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// The type, or severity, of an issue.
|
||||
/// </summary>
|
||||
public enum IssueType
|
||||
{
|
||||
/// <summary> A must-fix in the vast majority of cases. </summary>
|
||||
Problem,
|
||||
|
||||
/// <summary> A possible mistake. Often requires critical thinking. </summary>
|
||||
Warning,
|
||||
|
||||
// TODO: Try/catch all checks run and return error templates if exceptions occur.
|
||||
/// <summary> An error occurred and a complete check could not be made. </summary>
|
||||
Error,
|
||||
|
||||
// TODO: Negligible issues should be hidden by default.
|
||||
/// <summary> A possible mistake so minor/unlikely that it can often be safely ignored. </summary>
|
||||
Negligible,
|
||||
}
|
||||
}
|
17
osu.Game/Rulesets/Edit/IBeatmapVerifier.cs
Normal file
17
osu.Game/Rulesets/Edit/IBeatmapVerifier.cs
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// A class which can run against a beatmap and surface issues to the user which could go against known criteria or hinder gameplay.
|
||||
/// </summary>
|
||||
public interface IBeatmapVerifier
|
||||
{
|
||||
public IEnumerable<Issue> Run(IBeatmap beatmap);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
@ -19,7 +20,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// The base class for gameplay modifiers.
|
||||
/// </summary>
|
||||
[ExcludeFromDynamicCompile]
|
||||
public abstract class Mod : IMod, IJsonSerializable
|
||||
public abstract class Mod : IMod, IEquatable<Mod>, IJsonSerializable
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of this mod.
|
||||
@ -48,7 +49,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// The user readable description of this mod.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public virtual string Description => string.Empty;
|
||||
public abstract string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The tooltip to display for this mod when used in a <see cref="ModIcon"/>.
|
||||
@ -172,7 +173,19 @@ namespace osu.Game.Rulesets.Mods
|
||||
target.Parse(source);
|
||||
}
|
||||
|
||||
public bool Equals(IMod other) => GetType() == other?.GetType();
|
||||
public bool Equals(IMod other) => other is Mod them && Equals(them);
|
||||
|
||||
public bool Equals(Mod other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return GetType() == other.GetType() &&
|
||||
this.GetSettingsSourceProperties().All(pair =>
|
||||
EqualityComparer<object>.Default.Equals(
|
||||
ModUtils.GetSettingUnderlyingValue(pair.Item2.GetValue(this)),
|
||||
ModUtils.GetSettingUnderlyingValue(pair.Item2.GetValue(other))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset all custom settings for this mod back to their defaults.
|
||||
|
@ -37,8 +37,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
|
||||
public void ApplyToPlayer(Player player)
|
||||
{
|
||||
player.ApplyToBackground(b => b.EnableUserDim.Value = false);
|
||||
|
||||
player.ApplyToBackground(b => b.IgnoreUserSettings.Value = true);
|
||||
player.DimmableStoryboard.IgnoreUserSettings.Value = true;
|
||||
|
||||
player.BreakOverlay.Hide();
|
||||
|
@ -12,6 +12,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public override string Name => "No Mod";
|
||||
public override string Acronym => "NM";
|
||||
public override string Description => "No mods applied.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Ban;
|
||||
public override ModType Type => ModType.System;
|
||||
|
@ -56,8 +56,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
|
||||
public virtual IEnumerable<HitSampleInfo> GetSamples() => HitObject.Samples;
|
||||
|
||||
private readonly Lazy<List<DrawableHitObject>> nestedHitObjects = new Lazy<List<DrawableHitObject>>();
|
||||
public IReadOnlyList<DrawableHitObject> NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : (IReadOnlyList<DrawableHitObject>)Array.Empty<DrawableHitObject>();
|
||||
private readonly List<DrawableHitObject> nestedHitObjects = new List<DrawableHitObject>();
|
||||
public IReadOnlyList<DrawableHitObject> NestedHitObjects => nestedHitObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this object should handle any user input events.
|
||||
@ -249,7 +249,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
// Must be done before the nested DHO is added to occur before the nested Apply()!
|
||||
drawableNested.ParentHitObject = this;
|
||||
|
||||
nestedHitObjects.Value.Add(drawableNested);
|
||||
nestedHitObjects.Add(drawableNested);
|
||||
AddNestedHitObject(drawableNested);
|
||||
}
|
||||
|
||||
@ -305,19 +305,16 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
if (Samples != null)
|
||||
Samples.Samples = null;
|
||||
|
||||
if (nestedHitObjects.IsValueCreated)
|
||||
foreach (var obj in nestedHitObjects)
|
||||
{
|
||||
foreach (var obj in nestedHitObjects.Value)
|
||||
{
|
||||
obj.OnNewResult -= onNewResult;
|
||||
obj.OnRevertResult -= onRevertResult;
|
||||
obj.ApplyCustomUpdateState -= onApplyCustomUpdateState;
|
||||
}
|
||||
|
||||
nestedHitObjects.Value.Clear();
|
||||
ClearNestedHitObjects();
|
||||
obj.OnNewResult -= onNewResult;
|
||||
obj.OnRevertResult -= onRevertResult;
|
||||
obj.ApplyCustomUpdateState -= onApplyCustomUpdateState;
|
||||
}
|
||||
|
||||
nestedHitObjects.Clear();
|
||||
ClearNestedHitObjects();
|
||||
|
||||
HitObject.DefaultsApplied -= onDefaultsApplied;
|
||||
|
||||
OnFree();
|
||||
|
@ -201,6 +201,8 @@ namespace osu.Game.Rulesets
|
||||
|
||||
public virtual HitObjectComposer CreateHitObjectComposer() => null;
|
||||
|
||||
public virtual IBeatmapVerifier CreateBeatmapVerifier() => null;
|
||||
|
||||
public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.Solid.QuestionCircle };
|
||||
|
||||
public virtual IResourceStore<byte[]> CreateResourceStore() => new NamespacedResourceStore<byte[]>(new DllResourceStore(GetType().Assembly), @"Resources");
|
||||
|
@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
var enumerable = HitObjectContainer.Objects;
|
||||
|
||||
if (nestedPlayfields.IsValueCreated)
|
||||
if (nestedPlayfields.Count != 0)
|
||||
enumerable = enumerable.Concat(NestedPlayfields.SelectMany(p => p.AllHitObjects));
|
||||
|
||||
return enumerable;
|
||||
@ -76,9 +76,9 @@ namespace osu.Game.Rulesets.UI
|
||||
/// <summary>
|
||||
/// All <see cref="Playfield"/>s nested inside this <see cref="Playfield"/>.
|
||||
/// </summary>
|
||||
public IEnumerable<Playfield> NestedPlayfields => nestedPlayfields.IsValueCreated ? nestedPlayfields.Value : Enumerable.Empty<Playfield>();
|
||||
public IEnumerable<Playfield> NestedPlayfields => nestedPlayfields;
|
||||
|
||||
private readonly Lazy<List<Playfield>> nestedPlayfields = new Lazy<List<Playfield>>();
|
||||
private readonly List<Playfield> nestedPlayfields = new List<Playfield>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether judgements should be displayed by this and and all nested <see cref="Playfield"/>s.
|
||||
@ -217,7 +217,7 @@ namespace osu.Game.Rulesets.UI
|
||||
otherPlayfield.HitObjectUsageBegan += h => HitObjectUsageBegan?.Invoke(h);
|
||||
otherPlayfield.HitObjectUsageFinished += h => HitObjectUsageFinished?.Invoke(h);
|
||||
|
||||
nestedPlayfields.Value.Add(otherPlayfield);
|
||||
nestedPlayfields.Add(otherPlayfield);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -279,12 +279,7 @@ namespace osu.Game.Rulesets.UI
|
||||
return true;
|
||||
}
|
||||
|
||||
bool removedFromNested = false;
|
||||
|
||||
if (nestedPlayfields.IsValueCreated)
|
||||
removedFromNested = nestedPlayfields.Value.Any(p => p.Remove(hitObject));
|
||||
|
||||
return removedFromNested;
|
||||
return nestedPlayfields.Any(p => p.Remove(hitObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -429,10 +424,7 @@ namespace osu.Game.Rulesets.UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nestedPlayfields.IsValueCreated)
|
||||
return;
|
||||
|
||||
foreach (var p in nestedPlayfields.Value)
|
||||
foreach (var p in nestedPlayfields)
|
||||
p.SetKeepAlive(hitObject, keepAlive);
|
||||
}
|
||||
|
||||
@ -444,10 +436,7 @@ namespace osu.Game.Rulesets.UI
|
||||
foreach (var (_, entry) in lifetimeEntryMap)
|
||||
entry.KeepAlive = true;
|
||||
|
||||
if (!nestedPlayfields.IsValueCreated)
|
||||
return;
|
||||
|
||||
foreach (var p in nestedPlayfields.Value)
|
||||
foreach (var p in nestedPlayfields)
|
||||
p.KeepAllAlive();
|
||||
}
|
||||
|
||||
@ -461,10 +450,7 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
HitObjectContainer.PastLifetimeExtension = value;
|
||||
|
||||
if (!nestedPlayfields.IsValueCreated)
|
||||
return;
|
||||
|
||||
foreach (var nested in nestedPlayfields.Value)
|
||||
foreach (var nested in nestedPlayfields)
|
||||
nested.PastLifetimeExtension = value;
|
||||
}
|
||||
}
|
||||
@ -479,10 +465,7 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
HitObjectContainer.FutureLifetimeExtension = value;
|
||||
|
||||
if (!nestedPlayfields.IsValueCreated)
|
||||
return;
|
||||
|
||||
foreach (var nested in nestedPlayfields.Value)
|
||||
foreach (var nested in nestedPlayfields)
|
||||
nested.FutureLifetimeExtension = value;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user