private void load() { var judgement = HitObject.CreateJudgement(); if (judgement != null) { Result = CreateResult(judgement); if (Result == null) { throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } } var samples = GetSamples().ToArray(); if (samples.Length > 0) { if (HitObject.SampleControlPoint == null) { throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}." + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}."); } samples = samples.Select(s => HitObject.SampleControlPoint.ApplyTo(s)).ToArray(); foreach (var s in samples) { s.Namespace = SampleNamespace; } AddInternal(Samples = new SkinnableSound(samples)); } }
private IEnumerable <HitResult> getPerfectHitResults(HitObject hitObject) { foreach (HitObject nested in hitObject.NestedHitObjects) { yield return(nested.CreateJudgement().MaxResult); } yield return(hitObject.CreateJudgement().MaxResult); }
private void load(OsuConfigManager config) { userPositionalHitSounds = config.GetBindable <bool>(OsuSetting.PositionalHitSounds); var judgement = HitObject.CreateJudgement(); Result = CreateResult(judgement); if (Result == null) { throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } }
private void load() { var judgement = HitObject.CreateJudgement(); Result = CreateResult(judgement); if (Result == null) { throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); } loadSamples(); }
/// <summary> /// Applies a new <see cref="HitObject"/> to be represented by this <see cref="DrawableHitObject"/>. /// </summary> /// <param name="hitObject">The <see cref="HitObject"/> to apply.</param> public void Apply(HitObject hitObject) { free(); HitObject = hitObject ?? throw new InvalidOperationException($"Cannot apply a null {nameof(HitObject)}."); // Ensure this DHO has a result. Result ??= CreateResult(HitObject.CreateJudgement()) ?? throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); foreach (var h in HitObject.NestedHitObjects) { var drawableNested = CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); drawableNested.OnNewResult += onNewResult; drawableNested.OnRevertResult += onRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; nestedHitObjects.Value.Add(drawableNested); AddNestedHitObject(drawableNested); } startTimeBindable.BindTo(HitObject.StartTimeBindable); if (HitObject is IHasComboInformation combo) { comboIndexBindable.BindTo(combo.ComboIndexBindable); } samplesBindable.BindTo(HitObject.SamplesBindable); samplesBindable.BindCollectionChanged(onSamplesChanged, true); HitObject.DefaultsApplied += onDefaultsApplied; OnApply(hitObject); // If not loaded, the state update happens in LoadComplete(). Otherwise, the update is scheduled to allow for lifetime updates. if (IsLoaded) { Schedule(() => updateState(ArmedState.Idle, true)); } hasHitObjectApplied = true; }
/// <summary> /// Applies a new <see cref="HitObject"/> to be represented by this <see cref="DrawableHitObject"/>. /// </summary> /// <param name="hitObject">The <see cref="HitObject"/> to apply.</param> /// <param name="lifetimeEntry">The <see cref="HitObjectLifetimeEntry"/> controlling the lifetime of <paramref name="hitObject"/>.</param> public void Apply([NotNull] HitObject hitObject, [CanBeNull] HitObjectLifetimeEntry lifetimeEntry) { free(); HitObject = hitObject ?? throw new InvalidOperationException($"Cannot apply a null {nameof(HitObject)}."); this.lifetimeEntry = lifetimeEntry; if (lifetimeEntry != null) { // Transfer lifetime from the entry. LifetimeStart = lifetimeEntry.LifetimeStart; LifetimeEnd = lifetimeEntry.LifetimeEnd; // Copy any existing result from the entry (required for rewind / judgement revert). Result = lifetimeEntry.Result; } else { LifetimeStart = HitObject.StartTime - InitialLifetimeOffset; } // Ensure this DHO has a result. Result ??= CreateResult(HitObject.CreateJudgement()) ?? throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); // Copy back the result to the entry for potential future retrieval. if (lifetimeEntry != null) { lifetimeEntry.Result = Result; } foreach (var h in HitObject.NestedHitObjects) { var pooledDrawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h, this); var drawableNested = pooledDrawableNested ?? CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); // Only invoke the event for non-pooled DHOs, otherwise the event will be fired by the playfield. if (pooledDrawableNested == null) { OnNestedDrawableCreated?.Invoke(drawableNested); } drawableNested.OnNewResult += onNewResult; drawableNested.OnRevertResult += onRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; // This is only necessary for non-pooled DHOs. For pooled DHOs, this is handled inside GetPooledDrawableRepresentation(). // Must be done before the nested DHO is added to occur before the nested Apply()! drawableNested.ParentHitObject = this; nestedHitObjects.Value.Add(drawableNested); AddNestedHitObject(drawableNested); } StartTimeBindable.BindTo(HitObject.StartTimeBindable); StartTimeBindable.BindValueChanged(onStartTimeChanged); if (HitObject is IHasComboInformation combo) { comboIndexBindable.BindTo(combo.ComboIndexBindable); } samplesBindable.BindTo(HitObject.SamplesBindable); samplesBindable.BindCollectionChanged(onSamplesChanged, true); HitObject.DefaultsApplied += onDefaultsApplied; OnApply(); HitObjectApplied?.Invoke(this); // If not loaded, the state update happens in LoadComplete(). if (IsLoaded) { if (Result.IsHit) { updateState(ArmedState.Hit, true); } else if (Result.HasResult) { updateState(ArmedState.Miss, true); } else { updateState(ArmedState.Idle, true); } } hasHitObjectApplied = true; }
/// <summary> /// Applies a new <see cref="HitObject"/> to be represented by this <see cref="DrawableHitObject"/>. /// </summary> /// <param name="hitObject">The <see cref="HitObject"/> to apply.</param> /// <param name="lifetimeEntry">The <see cref="HitObjectLifetimeEntry"/> controlling the lifetime of <paramref name="hitObject"/>.</param> public void Apply([NotNull] HitObject hitObject, [CanBeNull] HitObjectLifetimeEntry lifetimeEntry) { free(); HitObject = hitObject ?? throw new InvalidOperationException($"Cannot apply a null {nameof(HitObject)}."); this.lifetimeEntry = lifetimeEntry; if (lifetimeEntry != null) { // Transfer lifetime from the entry. LifetimeStart = lifetimeEntry.LifetimeStart; LifetimeEnd = lifetimeEntry.LifetimeEnd; // Copy any existing result from the entry (required for rewind / judgement revert). Result = lifetimeEntry.Result; } else { LifetimeStart = HitObject.StartTime - InitialLifetimeOffset; } // Ensure this DHO has a result. Result ??= CreateResult(HitObject.CreateJudgement()) ?? throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); // Copy back the result to the entry for potential future retrieval. if (lifetimeEntry != null) { lifetimeEntry.Result = Result; } foreach (var h in HitObject.NestedHitObjects) { var drawableNested = pooledObjectProvider?.GetPooledDrawableRepresentation(h) ?? CreateNestedHitObject(h) ?? throw new InvalidOperationException($"{nameof(CreateNestedHitObject)} returned null for {h.GetType().ReadableName()}."); drawableNested.OnNewResult += onNewResult; drawableNested.OnRevertResult += onRevertResult; drawableNested.ApplyCustomUpdateState += onApplyCustomUpdateState; nestedHitObjects.Value.Add(drawableNested); AddNestedHitObject(drawableNested); drawableNested.OnParentReceived(this); } StartTimeBindable.BindTo(HitObject.StartTimeBindable); StartTimeBindable.BindValueChanged(onStartTimeChanged); if (HitObject is IHasComboInformation combo) { comboIndexBindable.BindTo(combo.ComboIndexBindable); } samplesBindable.BindTo(HitObject.SamplesBindable); samplesBindable.BindCollectionChanged(onSamplesChanged, true); HitObject.DefaultsApplied += onDefaultsApplied; OnApply(hitObject); HitObjectApplied?.Invoke(this); // If not loaded, the state update happens in LoadComplete(). Otherwise, the update is scheduled to allow for lifetime updates. if (IsLoaded) { Schedule(() => updateState(ArmedState.Idle, true)); } hasHitObjectApplied = true; }
private void ensureEntryHasResult() { Debug.Assert(Entry != null); Entry.Result ??= CreateResult(HitObject.CreateJudgement()) ?? throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); }