// 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 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 { /// /// A HitObject describes an object in a Beatmap. /// /// HitObjects may contain more properties for which you should be checking through the IHas* types. /// /// public class HitObject { /// /// The time at which the HitObject starts. /// public virtual double StartTime { get; set; } private List samples; /// /// The samples to be played when this hit object is hit. /// /// In the case of types, this is the sample of the curve body /// and can be treated as the default samples for the hit object. /// /// public List Samples { get => samples ?? (samples = new List()); set => samples = value; } [JsonIgnore] public SampleControlPoint SampleControlPoint; /// /// Whether this is in Kiai time. /// [JsonIgnore] public bool Kiai { get; private set; } private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY; /// /// The hit windows for this . /// public HitWindows HitWindows { get; set; } private readonly Lazy> nestedHitObjects = new Lazy>(() => new SortedList((h1, h2) => h1.StartTime.CompareTo(h2.StartTime))); [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects.Value; private readonly List judgements = new List(); public IReadOnlyList Judgements => judgements; /// /// Applies default values to this HitObject. /// /// The control points. /// The difficulty settings to use. public void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { ApplyDefaultsToSelf(controlPointInfo, difficulty); judgements.Clear(); judgements.AddRange(CreateJudgements()); if (nestedHitObjects.IsValueCreated) nestedHitObjects.Value.Clear(); CreateNestedHitObjects(); if (nestedHitObjects.IsValueCreated) { nestedHitObjects.Value.ForEach(h => { h.HitWindows = HitWindows; h.ApplyDefaults(controlPointInfo, difficulty); }); } } protected virtual void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { SampleControlPoint samplePoint = controlPointInfo.SamplePointAt(StartTime); EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime); Kiai = effectPoint.KiaiMode; SampleControlPoint = samplePoint; if (HitWindows == null) HitWindows = CreateHitWindows(); HitWindows?.SetDifficulty(difficulty.OverallDifficulty); } protected virtual void CreateNestedHitObjects() { } protected virtual IEnumerable CreateJudgements() => Enumerable.Empty(); protected void AddNested(HitObject hitObject) => nestedHitObjects.Value.Add(hitObject); /// /// Creates the for this . /// This can be null to indicate that the has no . /// /// This will only be invoked if hasn't been set externally (e.g. from a . /// /// protected virtual HitWindows CreateHitWindows() => new HitWindows(); } }