// 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; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.UI { public abstract class Playfield : ScalableContainer { /// /// The contained in this Playfield. /// public HitObjectContainer HitObjectContainer { get; private set; } /// /// All the s contained in this and all . /// public IEnumerable AllHitObjects => HitObjectContainer?.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>(); /// /// Whether judgements should be displayed by this and and all nested s. /// public readonly BindableBool DisplayJudgements = new BindableBool(true); /// /// A container for keeping track of DrawableHitObjects. /// /// The width to scale the internal coordinate space to. /// May be null if scaling based on is desired. If is also null, no scaling will occur. /// /// The height to scale the internal coordinate space to. /// May be null if scaling based on is desired. If is also null, no scaling will occur. /// protected Playfield(float? customWidth = null, float? customHeight = null) : base(customWidth, customHeight) { RelativeSizeAxes = Axes.Both; } private WorkingBeatmap beatmap; [BackgroundDependencyLoader] private void load(IBindableBeatmap beatmap) { this.beatmap = beatmap.Value; HitObjectContainer = CreateHitObjectContainer(); HitObjectContainer.RelativeSizeAxes = Axes.Both; Add(HitObjectContainer); } /// /// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield. /// public virtual void PostProcess() => NestedPlayfields.ForEach(p => p.PostProcess()); /// /// Adds a DrawableHitObject to this Playfield. /// /// The DrawableHitObject to add. 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) => HitObjectContainer.Remove(h); /// /// Registers a as a nested . /// This does not add the to the draw hierarchy. /// /// The to add. protected void AddNested(Playfield otherPlayfield) { otherPlayfield.DisplayJudgements.BindTo(DisplayJudgements); nestedPlayfields.Value.Add(otherPlayfield); } /// /// 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 mod in beatmap.Mods.Value) if (mod is IUpdatableByPlayfield updatable) updatable.Update(this); } } }