mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 07:33:55 +09:00
Merge https://github.com/ppy/osu into online-beatmap-set-overlay
This commit is contained in:
@ -87,7 +87,9 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
if (track != null) return track;
|
||||
|
||||
track = GetTrack();
|
||||
// we want to ensure that we always have a track, even if it's a fake one.
|
||||
track = GetTrack() ?? new TrackVirtual();
|
||||
|
||||
applyRateAdjustments();
|
||||
return track;
|
||||
}
|
||||
@ -107,10 +109,17 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
track?.Dispose();
|
||||
track = null;
|
||||
background?.Dispose();
|
||||
background = null;
|
||||
}
|
||||
|
||||
public void DisposeTrack()
|
||||
{
|
||||
lock (trackLock)
|
||||
{
|
||||
track?.Dispose();
|
||||
track = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ namespace osu.Game.Graphics.Cursor
|
||||
},
|
||||
AdditiveLayer = new Sprite
|
||||
{
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = colour.Pink,
|
||||
Alpha = 0,
|
||||
Texture = textures.Get(@"Cursor/menu-cursor-additive"),
|
||||
|
@ -57,6 +57,12 @@ namespace osu.Game.Graphics
|
||||
private void load(FontStore store)
|
||||
{
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateTexture();
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In);
|
||||
flash();
|
||||
|
||||
this.Delay(click_duration).Schedule(delegate {
|
||||
this.Delay(click_duration).Schedule(delegate
|
||||
{
|
||||
colourContainer.ResizeTo(new Vector2(0.8f, 1f));
|
||||
spriteText.Spacing = Vector2.Zero;
|
||||
glowContainer.FadeOut();
|
||||
@ -140,7 +141,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
colourContainer.Add(flash);
|
||||
|
||||
flash.Colour = ButtonColour;
|
||||
flash.BlendingMode = BlendingMode.Additive;
|
||||
flash.Blending = BlendingMode.Additive;
|
||||
flash.Alpha = 0.3f;
|
||||
flash.FadeOutFromOne(click_duration);
|
||||
flash.Expire();
|
||||
|
@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
hover = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
},
|
||||
|
@ -152,10 +152,19 @@ namespace osu.Game
|
||||
|
||||
Beatmap.ValueChanged += b =>
|
||||
{
|
||||
var trackLoaded = lastBeatmap?.TrackLoaded ?? false;
|
||||
|
||||
// compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)
|
||||
if (lastBeatmap?.Track != b.Track)
|
||||
if (!trackLoaded || lastBeatmap?.Track != b.Track)
|
||||
{
|
||||
lastBeatmap?.Track?.Dispose();
|
||||
if (trackLoaded)
|
||||
{
|
||||
Debug.Assert(lastBeatmap != null);
|
||||
Debug.Assert(lastBeatmap.Track != null);
|
||||
|
||||
lastBeatmap.DisposeTrack();
|
||||
}
|
||||
|
||||
Audio.Track.AddItem(b.Track);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Settings
|
||||
backgroundBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = OsuColour.Gray(60),
|
||||
Alpha = 0,
|
||||
},
|
||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(80).Opacity(180),
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0,
|
||||
},
|
||||
Flow = new FillFlowContainer
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(150).Opacity(180),
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Depth = 2,
|
||||
Alpha = 0,
|
||||
});
|
||||
|
@ -16,11 +16,9 @@ namespace osu.Game.Rulesets.Judgements
|
||||
/// <summary>
|
||||
/// A drawable object which visualises the hit result of a <see cref="Judgements.Judgement"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TJudgement">The type of judgement to visualise.</typeparam>
|
||||
public class DrawableJudgement<TJudgement> : Container
|
||||
where TJudgement : Judgement
|
||||
public class DrawableJudgement : Container
|
||||
{
|
||||
protected readonly TJudgement Judgement;
|
||||
protected readonly Judgement Judgement;
|
||||
|
||||
protected readonly SpriteText JudgementText;
|
||||
|
||||
@ -28,21 +26,19 @@ namespace osu.Game.Rulesets.Judgements
|
||||
/// Creates a drawable which visualises a <see cref="Judgements.Judgement"/>.
|
||||
/// </summary>
|
||||
/// <param name="judgement">The judgement to visualise.</param>
|
||||
public DrawableJudgement(TJudgement judgement)
|
||||
public DrawableJudgement(Judgement judgement)
|
||||
{
|
||||
Judgement = judgement;
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
string resultString = judgement.Result == HitResult.Hit ? judgement.ResultString : judgement.Result.GetDescription();
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
JudgementText = new OsuSpriteText
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Text = resultString.ToUpper(),
|
||||
Text = judgement.Result.GetDescription().ToUpper(),
|
||||
Font = @"Venera",
|
||||
TextSize = 16
|
||||
}
|
||||
@ -68,6 +64,8 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
switch (Judgement.Result)
|
||||
{
|
||||
case HitResult.None:
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
this.ScaleTo(1.6f);
|
||||
this.ScaleTo(1, 100, Easing.In);
|
||||
@ -77,7 +75,7 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
this.Delay(600).FadeOut(200);
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
default:
|
||||
this.ScaleTo(0.9f);
|
||||
this.ScaleTo(1, 500, Easing.OutElastic);
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Judgements
|
||||
{
|
||||
/// <summary>
|
||||
/// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change.
|
||||
/// </summary>
|
||||
public interface IPartialJudgement
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that this partial judgement has changed and requires reprocessing.
|
||||
/// <para>
|
||||
/// This is set to false once the judgement has been re-processed.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
bool Changed { get; set; }
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Judgements
|
||||
{
|
||||
public abstract class Judgement
|
||||
public class Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether this judgement is the result of a hit or a miss.
|
||||
@ -13,20 +13,35 @@ namespace osu.Game.Rulesets.Judgements
|
||||
public HitResult Result;
|
||||
|
||||
/// <summary>
|
||||
/// The offset at which this judgement occurred.
|
||||
/// The maximum <see cref="HitResult"/> that can be achieved.
|
||||
/// </summary>
|
||||
public double TimeOffset;
|
||||
public virtual HitResult MaxResult => HitResult.Perfect;
|
||||
|
||||
public bool IsHit => Result > HitResult.Miss;
|
||||
|
||||
/// <summary>
|
||||
/// The offset from a perfect hit at which this judgement occurred.
|
||||
/// Populated when added via <see cref="DrawableHitObject{TObject}.AddJudgement"/>.
|
||||
/// </summary>
|
||||
public double TimeOffset { get; internal set; }
|
||||
|
||||
public virtual bool AffectsCombo => true;
|
||||
|
||||
/// <summary>
|
||||
/// The string representation for the result achieved.
|
||||
/// The numeric representation for the result achieved.
|
||||
/// </summary>
|
||||
public abstract string ResultString { get; }
|
||||
public int NumericResult => NumericResultFor(Result);
|
||||
|
||||
/// <summary>
|
||||
/// The string representation for the max result achievable.
|
||||
/// The numeric representation for the maximum achievable result.
|
||||
/// </summary>
|
||||
public abstract string MaxResultString { get; }
|
||||
public int MaxNumericResult => NumericResultFor(MaxResult);
|
||||
|
||||
/// <summary>
|
||||
/// Convert a <see cref="HitResult"/> to a numeric score representation.
|
||||
/// </summary>
|
||||
/// <param name="result">The value to convert.</param>
|
||||
/// <returns>The number.</returns>
|
||||
protected virtual int NumericResultFor(HitResult result) => result > HitResult.Miss ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
protected abstract Score CreateReplayScore(Beatmap<T> beatmap);
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<T> rulesetContainer)
|
||||
public virtual void ApplyToRulesetContainer(RulesetContainer<T> rulesetContainer)
|
||||
{
|
||||
rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay);
|
||||
}
|
||||
|
@ -12,17 +12,18 @@ using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Audio;
|
||||
using System.Linq;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableHitObject : Container
|
||||
public abstract class DrawableHitObject : Container, IHasAccentColour
|
||||
{
|
||||
public readonly HitObject HitObject;
|
||||
|
||||
/// <summary>
|
||||
/// The colour used for various elements of this DrawableHitObject.
|
||||
/// </summary>
|
||||
public virtual Color4 AccentColour { get; set; }
|
||||
public virtual Color4 AccentColour { get; set; } = Color4.Gray;
|
||||
|
||||
protected DrawableHitObject(HitObject hitObject)
|
||||
{
|
||||
@ -33,32 +34,29 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
public abstract class DrawableHitObject<TObject> : DrawableHitObject
|
||||
where TObject : HitObject
|
||||
{
|
||||
public event Action<DrawableHitObject, Judgement> OnJudgement;
|
||||
|
||||
public new readonly TObject HitObject;
|
||||
|
||||
protected DrawableHitObject(TObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class DrawableHitObject<TObject, TJudgement> : DrawableHitObject<TObject>
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
{
|
||||
public event Action<DrawableHitObject<TObject, TJudgement>> OnJudgement;
|
||||
|
||||
public override bool HandleInput => Interactive;
|
||||
|
||||
public bool Interactive = true;
|
||||
|
||||
public TJudgement Judgement;
|
||||
/// <summary>
|
||||
/// Whether this <see cref="DrawableHitObject"/> can be judged.
|
||||
/// </summary>
|
||||
protected virtual bool ProvidesJudgement => true;
|
||||
|
||||
private readonly List<Judgement> judgements = new List<Judgement>();
|
||||
public IReadOnlyList<Judgement> Judgements => judgements;
|
||||
|
||||
protected List<SampleChannel> Samples = new List<SampleChannel>();
|
||||
|
||||
protected DrawableHitObject(TObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
|
||||
Depth = (float)hitObject.StartTime;
|
||||
}
|
||||
|
||||
private ArmedState state;
|
||||
@ -95,69 +93,80 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
UpdateState(State);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this hit object and all of its nested hit objects have been judged.
|
||||
/// </summary>
|
||||
public bool Judged => (Judgement?.Result ?? HitResult.None) != HitResult.None && (NestedHitObjects?.All(h => h.Judged) ?? true);
|
||||
private bool hasJudgementResult;
|
||||
private bool judgementOccurred;
|
||||
|
||||
/// <summary>
|
||||
/// Process a hit of this hitobject. Carries out judgement.
|
||||
/// Whether this <see cref="DrawableHitObject"/> and all of its nested <see cref="DrawableHitObject"/>s have been judged.
|
||||
/// </summary>
|
||||
/// <returns>Whether a hit was processed.</returns>
|
||||
protected bool UpdateJudgement(bool userTriggered)
|
||||
public virtual bool AllJudged => (!ProvidesJudgement || hasJudgementResult) && (NestedHitObjects?.All(h => h.AllJudged) ?? true);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies that a new judgement has occurred for this <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="judgement">The <see cref="Judgement"/>.</param>
|
||||
protected void AddJudgement(Judgement judgement)
|
||||
{
|
||||
if (Judgement == null)
|
||||
return false;
|
||||
hasJudgementResult = judgement.Result >= HitResult.Miss;
|
||||
judgementOccurred = true;
|
||||
|
||||
var partial = Judgement as IPartialJudgement;
|
||||
// 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;
|
||||
judgement.TimeOffset = Time.Current - endTime;
|
||||
|
||||
// Never re-process non-partial hits
|
||||
if (Judgement.Result != HitResult.None && partial == null)
|
||||
return false;
|
||||
judgements.Add(judgement);
|
||||
|
||||
// Update the judgement state
|
||||
double endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
||||
Judgement.TimeOffset = Time.Current - endTime;
|
||||
|
||||
// Update the judgement state
|
||||
bool hadResult = Judgement.Result != HitResult.None;
|
||||
CheckJudgement(userTriggered);
|
||||
|
||||
// Don't process judgements with no result
|
||||
if (Judgement.Result == HitResult.None)
|
||||
return false;
|
||||
|
||||
// Don't process judgements that previously had results but the results were unchanged
|
||||
if (hadResult && partial?.Changed != true)
|
||||
return false;
|
||||
|
||||
switch (Judgement.Result)
|
||||
switch (judgement.Result)
|
||||
{
|
||||
default:
|
||||
State = ArmedState.Hit;
|
||||
case HitResult.None:
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
State = ArmedState.Miss;
|
||||
break;
|
||||
default:
|
||||
State = ArmedState.Hit;
|
||||
break;
|
||||
}
|
||||
|
||||
OnJudgement?.Invoke(this);
|
||||
|
||||
if (partial != null)
|
||||
partial.Changed = false;
|
||||
|
||||
return true;
|
||||
OnJudgement?.Invoke(this, judgement);
|
||||
}
|
||||
|
||||
protected virtual void CheckJudgement(bool userTriggered)
|
||||
/// <summary>
|
||||
/// Processes this <see cref="DrawableHitObject"/>, checking if any judgements have occurred.
|
||||
/// </summary>
|
||||
/// <param name="userTriggered">Whether the user triggered this process.</param>
|
||||
/// <returns>Whether a judgement has occurred from this <see cref="DrawableHitObject"/> or any nested <see cref="DrawableHitObject"/>s.</returns>
|
||||
protected bool UpdateJudgement(bool userTriggered)
|
||||
{
|
||||
judgementOccurred = false;
|
||||
|
||||
if (AllJudged || State != ArmedState.Idle)
|
||||
return false;
|
||||
|
||||
if (NestedHitObjects != null)
|
||||
{
|
||||
foreach (var d in NestedHitObjects)
|
||||
d.CheckJudgement(userTriggered);
|
||||
judgementOccurred |= d.UpdateJudgement(userTriggered);
|
||||
}
|
||||
|
||||
if (!ProvidesJudgement || hasJudgementResult || judgementOccurred)
|
||||
return judgementOccurred;
|
||||
|
||||
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
|
||||
CheckForJudgements(userTriggered, Time.Current - endTime);
|
||||
|
||||
return judgementOccurred;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if any judgements have occurred for this <see cref="DrawableHitObject"/>. This method must construct
|
||||
/// all <see cref="Judgement"/>s and notify of them through <see cref="AddJudgement"/>.
|
||||
/// </summary>
|
||||
/// <param name="userTriggered">Whether the user triggered this check.</param>
|
||||
/// <param name="timeOffset">The offset from the <see cref="HitObject"/> end time at which this check occurred. A <paramref name="timeOffset"/> > 0
|
||||
/// implies that this check occurred after the end time of <see cref="HitObject"/>. </param>
|
||||
protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { }
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
@ -178,25 +187,20 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
channel.Volume.Value = sample.Volume;
|
||||
Samples.Add(channel);
|
||||
}
|
||||
|
||||
//we may be setting a custom judgement in test cases or what not.
|
||||
if (Judgement == null)
|
||||
Judgement = CreateJudgement();
|
||||
}
|
||||
|
||||
private List<DrawableHitObject<TObject, TJudgement>> nestedHitObjects;
|
||||
protected IEnumerable<DrawableHitObject<TObject, TJudgement>> NestedHitObjects => nestedHitObjects;
|
||||
private List<DrawableHitObject<TObject>> nestedHitObjects;
|
||||
protected IEnumerable<DrawableHitObject<TObject>> NestedHitObjects => nestedHitObjects;
|
||||
|
||||
protected virtual void AddNested(DrawableHitObject<TObject, TJudgement> h)
|
||||
protected virtual void AddNested(DrawableHitObject<TObject> h)
|
||||
{
|
||||
if (nestedHitObjects == null)
|
||||
nestedHitObjects = new List<DrawableHitObject<TObject, TJudgement>>();
|
||||
nestedHitObjects = new List<DrawableHitObject<TObject>>();
|
||||
|
||||
h.OnJudgement += d => OnJudgement?.Invoke(d);
|
||||
h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j);
|
||||
nestedHitObjects.Add(h);
|
||||
}
|
||||
|
||||
protected abstract TJudgement CreateJudgement();
|
||||
protected abstract void UpdateState(ArmedState state);
|
||||
}
|
||||
}
|
||||
|
@ -3,19 +3,17 @@
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// A basic class that overrides <see cref="DrawableHitObject{TObject, TJudgement}"/> and implements <see cref="IScrollingHitObject"/>.
|
||||
/// A basic class that overrides <see cref="DrawableHitObject{TObject}"/> and implements <see cref="IScrollingHitObject"/>.
|
||||
/// This object does not need to have its <see cref="Drawable.RelativePositionAxes"/> set to be able to scroll, as this will
|
||||
/// will be set by the scrolling container that contains it.
|
||||
/// </summary>
|
||||
public abstract class DrawableScrollingHitObject<TObject, TJudgement> : DrawableHitObject<TObject, TJudgement>, IScrollingHitObject
|
||||
public abstract class DrawableScrollingHitObject<TObject> : DrawableHitObject<TObject>, IScrollingHitObject
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
{
|
||||
public BindableDouble LifetimeOffset { get; } = new BindableDouble();
|
||||
|
||||
@ -57,7 +55,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
set { lifetimeEnd = value; }
|
||||
}
|
||||
|
||||
protected override void AddNested(DrawableHitObject<TObject, TJudgement> h)
|
||||
protected override void AddNested(DrawableHitObject<TObject> h)
|
||||
{
|
||||
var scrollingHitObject = h as IScrollingHitObject;
|
||||
scrollingHitObject?.LifetimeOffset.BindTo(LifetimeOffset);
|
||||
|
@ -10,17 +10,34 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
/// <summary>
|
||||
/// Indicates that the object has not been judged yet.
|
||||
/// </summary>
|
||||
[Description("")]
|
||||
[Description(@"")]
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the object has been judged as a miss.
|
||||
/// </summary>
|
||||
[Description(@"Miss")]
|
||||
Miss,
|
||||
|
||||
[Description(@"Meh")]
|
||||
Meh,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the object has been judged as a hit.
|
||||
/// Optional judgement.
|
||||
/// </summary>
|
||||
[Description(@"Hit")]
|
||||
Hit,
|
||||
[Description(@"OK")]
|
||||
Ok,
|
||||
|
||||
[Description(@"Good")]
|
||||
Good,
|
||||
|
||||
[Description(@"Great")]
|
||||
Great,
|
||||
|
||||
/// <summary>
|
||||
/// Optional judgement.
|
||||
/// </summary>
|
||||
[Description(@"Perfect")]
|
||||
Perfect,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,11 @@ namespace osu.Game.Rulesets.Objects
|
||||
/// </summary>
|
||||
public SampleInfoList Samples = new SampleInfoList();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this <see cref="HitObject"/> is in Kiai time.
|
||||
/// </summary>
|
||||
public bool Kiai { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Applies default values to this HitObject.
|
||||
/// </summary>
|
||||
@ -38,6 +43,9 @@ namespace osu.Game.Rulesets.Objects
|
||||
public virtual void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
SoundControlPoint soundPoint = controlPointInfo.SoundPointAt(StartTime);
|
||||
EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime);
|
||||
|
||||
Kiai |= effectPoint.KiaiMode;
|
||||
|
||||
// Initialize first sample
|
||||
Samples.ForEach(s => initializeSampleInfo(s, soundPoint));
|
||||
|
@ -135,14 +135,13 @@ namespace osu.Game.Rulesets.Scoring
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ScoreProcessor<TObject, TJudgement> : ScoreProcessor
|
||||
public abstract class ScoreProcessor<TObject> : ScoreProcessor
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// All judgements held by this ScoreProcessor.
|
||||
/// </summary>
|
||||
protected readonly List<TJudgement> Judgements = new List<TJudgement>();
|
||||
protected readonly List<Judgement> Judgements = new List<Judgement>();
|
||||
|
||||
public override bool HasFailed => Health.Value == Health.MinValue;
|
||||
|
||||
@ -150,7 +149,7 @@ namespace osu.Game.Rulesets.Scoring
|
||||
{
|
||||
}
|
||||
|
||||
protected ScoreProcessor(RulesetContainer<TObject, TJudgement> rulesetContainer)
|
||||
protected ScoreProcessor(RulesetContainer<TObject> rulesetContainer)
|
||||
{
|
||||
Judgements.Capacity = rulesetContainer.Beatmap.HitObjects.Count;
|
||||
|
||||
@ -171,7 +170,7 @@ namespace osu.Game.Rulesets.Scoring
|
||||
/// Adds a judgement to this ScoreProcessor.
|
||||
/// </summary>
|
||||
/// <param name="judgement">The judgement to add.</param>
|
||||
protected void AddJudgement(TJudgement judgement)
|
||||
protected void AddJudgement(Judgement judgement)
|
||||
{
|
||||
bool exists = Judgements.Contains(judgement);
|
||||
|
||||
@ -181,10 +180,12 @@ namespace osu.Game.Rulesets.Scoring
|
||||
{
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.None:
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
Combo.Value = 0;
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
default:
|
||||
Combo.Value++;
|
||||
break;
|
||||
}
|
||||
@ -195,8 +196,6 @@ namespace osu.Game.Rulesets.Scoring
|
||||
|
||||
NotifyNewJudgement(judgement);
|
||||
}
|
||||
else
|
||||
OnJudgementChanged(judgement);
|
||||
|
||||
UpdateFailed();
|
||||
}
|
||||
@ -210,20 +209,8 @@ namespace osu.Game.Rulesets.Scoring
|
||||
|
||||
/// <summary>
|
||||
/// Updates any values that need post-processing. Invoked when a new judgement has occurred.
|
||||
/// <para>
|
||||
/// This is not triggered when existing judgements are changed - for that see <see cref="OnJudgementChanged(TJudgement)"/>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
||||
protected abstract void OnNewJudgement(TJudgement judgement);
|
||||
|
||||
/// <summary>
|
||||
/// Updates any values that need post-processing. Invoked when an existing judgement has changed.
|
||||
/// <para>
|
||||
/// This is not triggered when a new judgement has occurred - for that see <see cref="OnNewJudgement(TJudgement)"/>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="judgement">The judgement that triggered this calculation.</param>
|
||||
protected virtual void OnJudgementChanged(TJudgement judgement) { }
|
||||
protected abstract void OnNewJudgement(Judgement judgement);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
@ -14,9 +13,7 @@ using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
public abstract class Playfield<TObject, TJudgement> : Container
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
public abstract class Playfield : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// The HitObjects contained in this Playfield.
|
||||
@ -70,7 +67,7 @@ namespace osu.Game.Rulesets.UI
|
||||
public override Axes RelativeSizeAxes
|
||||
{
|
||||
get { return Axes.Both; }
|
||||
set { throw new InvalidOperationException($@"{nameof(Playfield<TObject, TJudgement>)}'s {nameof(RelativeSizeAxes)} should never be changed from {Axes.Both}"); }
|
||||
set { throw new InvalidOperationException($@"{nameof(Playfield)}'s {nameof(RelativeSizeAxes)} should never be changed from {Axes.Both}"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -82,19 +79,20 @@ namespace osu.Game.Rulesets.UI
|
||||
/// Adds a DrawableHitObject to this Playfield.
|
||||
/// </summary>
|
||||
/// <param name="h">The DrawableHitObject to add.</param>
|
||||
public virtual void Add(DrawableHitObject<TObject, TJudgement> h) => HitObjects.Add(h);
|
||||
public virtual void Add(DrawableHitObject h) => HitObjects.Add(h);
|
||||
|
||||
/// <summary>
|
||||
/// Remove a DrawableHitObject from this Playfield.
|
||||
/// </summary>
|
||||
/// <param name="h">The DrawableHitObject to remove.</param>
|
||||
public virtual void Remove(DrawableHitObject<TObject, TJudgement> h) => HitObjects.Remove(h);
|
||||
public virtual void Remove(DrawableHitObject h) => HitObjects.Remove(h);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object's Judgement is updated.
|
||||
/// Triggered when a new <see cref="Judgement"/> occurs on a <see cref="DrawableHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="judgedObject">The object that Judgement has been updated for.</param>
|
||||
public virtual void OnJudgement(DrawableHitObject<TObject, TJudgement> judgedObject) { }
|
||||
/// <param name="judgedObject">The object that <paramref name="judgement"/> occured for.</param>
|
||||
/// <param name="judgement">The <see cref="Judgement"/> that occurred.</param>
|
||||
public virtual void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { }
|
||||
|
||||
public class HitObjectContainer : CompositeDrawable
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.UI
|
||||
/// <summary>
|
||||
/// Base RulesetContainer. Doesn't hold objects.
|
||||
/// <para>
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TObject,TJudgement}"/> instead.
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TObject}"/> instead.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public abstract class RulesetContainer : Container
|
||||
@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.UI
|
||||
public event Action OnAllJudged;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to apply adjustments to the child <see cref="Playfield{TObject,TJudgement}"/> based on our own size.
|
||||
/// Whether to apply adjustments to the child <see cref="Playfield"/> based on our own size.
|
||||
/// </summary>
|
||||
public bool AspectAdjust = true;
|
||||
|
||||
@ -77,13 +77,6 @@ namespace osu.Game.Rulesets.UI
|
||||
Ruleset = ruleset;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
KeyBindingInputManager = CreateInputManager();
|
||||
KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether all HitObjects have been judged, and invokes OnAllJudged.
|
||||
/// </summary>
|
||||
@ -123,13 +116,15 @@ namespace osu.Game.Rulesets.UI
|
||||
/// RulesetContainer that applies conversion to Beatmaps. Does not contain a Playfield
|
||||
/// and does not load drawable hit objects.
|
||||
/// <para>
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TObject,TJudgement}"/> instead.
|
||||
/// Should not be derived - derive <see cref="RulesetContainer{TObject}"/> instead.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of HitObject contained by this RulesetContainer.</typeparam>
|
||||
public abstract class RulesetContainer<TObject> : RulesetContainer
|
||||
where TObject : HitObject
|
||||
{
|
||||
public event Action<Judgement> OnJudgement;
|
||||
|
||||
/// <summary>
|
||||
/// The Beatmap
|
||||
/// </summary>
|
||||
@ -155,6 +150,20 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
protected readonly bool IsForCurrentRuleset;
|
||||
|
||||
public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor;
|
||||
|
||||
protected override bool AllObjectsJudged => drawableObjects.All(h => h.AllJudged);
|
||||
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
public Playfield Playfield { get; private set; }
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private Container content;
|
||||
|
||||
private readonly List<DrawableHitObject<TObject>> drawableObjects = new List<DrawableHitObject<TObject>>();
|
||||
|
||||
/// <summary>
|
||||
/// Whether to assume the beatmap passed into this <see cref="RulesetContainer{TObject}"/> is for the current ruleset.
|
||||
/// Creates a hit renderer for a beatmap.
|
||||
@ -162,7 +171,7 @@ namespace osu.Game.Rulesets.UI
|
||||
/// <param name="ruleset">The ruleset being repesented.</param>
|
||||
/// <param name="workingBeatmap">The beatmap to create the hit renderer for.</param>
|
||||
/// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param>
|
||||
internal RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset)
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset)
|
||||
{
|
||||
Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap.");
|
||||
@ -194,78 +203,13 @@ namespace osu.Game.Rulesets.UI
|
||||
// Post-process the beatmap
|
||||
processor.PostProcess(Beatmap);
|
||||
|
||||
KeyBindingInputManager = CreateInputManager();
|
||||
KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
|
||||
|
||||
// Add mods, should always be the last thing applied to give full control to mods
|
||||
applyMods(Mods);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the active mods to this RulesetContainer.
|
||||
/// </summary>
|
||||
/// <param name="mods"></param>
|
||||
private void applyMods(IEnumerable<Mod> mods)
|
||||
{
|
||||
if (mods == null)
|
||||
return;
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableMod<TObject>>())
|
||||
mod.ApplyToRulesetContainer(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a processor to perform post-processing operations
|
||||
/// on HitObjects in converted Beatmaps.
|
||||
/// </summary>
|
||||
/// <returns>The Beatmap processor.</returns>
|
||||
protected virtual BeatmapProcessor<TObject> CreateBeatmapProcessor() => new BeatmapProcessor<TObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a converter to convert Beatmap to a specific mode.
|
||||
/// </summary>
|
||||
/// <returns>The Beatmap converter.</returns>
|
||||
protected abstract BeatmapConverter<TObject> CreateBeatmapConverter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A derivable RulesetContainer that manages the Playfield and HitObjects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of HitObject contained by this RulesetContainer.</typeparam>
|
||||
/// <typeparam name="TJudgement">The type of Judgement of DrawableHitObjects contained by this RulesetContainer.</typeparam>
|
||||
public abstract class RulesetContainer<TObject, TJudgement> : RulesetContainer<TObject>
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
{
|
||||
public event Action<TJudgement> OnJudgement;
|
||||
|
||||
public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor;
|
||||
|
||||
/// <summary>
|
||||
/// All the converted hit objects contained by this hit renderer.
|
||||
/// </summary>
|
||||
public new IEnumerable<TObject> Objects => Beatmap.HitObjects;
|
||||
|
||||
protected override bool AllObjectsJudged => drawableObjects.All(h => h.Judged);
|
||||
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
public Playfield<TObject, TJudgement> Playfield { get; private set; }
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private Container content;
|
||||
|
||||
private readonly List<DrawableHitObject<TObject, TJudgement>> drawableObjects = new List<DrawableHitObject<TObject, TJudgement>>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a hit renderer for a beatmap.
|
||||
/// </summary>
|
||||
/// <param name="ruleset">The ruleset being repesented.</param>
|
||||
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
|
||||
/// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param>
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -280,6 +224,19 @@ namespace osu.Game.Rulesets.UI
|
||||
loadObjects();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the active mods to this RulesetContainer.
|
||||
/// </summary>
|
||||
/// <param name="mods"></param>
|
||||
private void applyMods(IEnumerable<Mod> mods)
|
||||
{
|
||||
if (mods == null)
|
||||
return;
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableMod<TObject>>())
|
||||
mod.ApplyToRulesetContainer(this);
|
||||
}
|
||||
|
||||
public override void SetReplay(Replay replay)
|
||||
{
|
||||
base.SetReplay(replay);
|
||||
@ -302,7 +259,12 @@ namespace osu.Game.Rulesets.UI
|
||||
if (drawableObject == null)
|
||||
continue;
|
||||
|
||||
drawableObject.OnJudgement += onJudgement;
|
||||
drawableObject.OnJudgement += (d, j) =>
|
||||
{
|
||||
Playfield.OnJudgement(d, j);
|
||||
OnJudgement?.Invoke(j);
|
||||
CheckAllJudged();
|
||||
};
|
||||
|
||||
drawableObjects.Add(drawableObject);
|
||||
Playfield.Add(drawableObject);
|
||||
@ -319,36 +281,36 @@ namespace osu.Game.Rulesets.UI
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In some cases we want to apply changes to the relative size of our contained <see cref="Playfield{TObject, TJudgement}"/> based on custom conditions.
|
||||
/// Creates a processor to perform post-processing operations
|
||||
/// on HitObjects in converted Beatmaps.
|
||||
/// </summary>
|
||||
/// <returns>The Beatmap processor.</returns>
|
||||
protected virtual BeatmapProcessor<TObject> CreateBeatmapProcessor() => new BeatmapProcessor<TObject>();
|
||||
|
||||
/// <summary>
|
||||
/// In some cases we want to apply changes to the relative size of our contained <see cref="Playfield"/> based on custom conditions.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual Vector2 GetPlayfieldAspectAdjust() => new Vector2(0.75f); //a sane default
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object's Judgement is updated.
|
||||
/// Creates a converter to convert Beatmap to a specific mode.
|
||||
/// </summary>
|
||||
/// <param name="judgedObject">The object that Judgement has been updated for.</param>
|
||||
private void onJudgement(DrawableHitObject<TObject, TJudgement> judgedObject)
|
||||
{
|
||||
Playfield.OnJudgement(judgedObject);
|
||||
|
||||
OnJudgement?.Invoke(judgedObject.Judgement);
|
||||
|
||||
CheckAllJudged();
|
||||
}
|
||||
/// <returns>The Beatmap converter.</returns>
|
||||
protected abstract BeatmapConverter<TObject> CreateBeatmapConverter();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a DrawableHitObject from a HitObject.
|
||||
/// </summary>
|
||||
/// <param name="h">The HitObject to make drawable.</param>
|
||||
/// <returns>The DrawableHitObject.</returns>
|
||||
protected abstract DrawableHitObject<TObject, TJudgement> GetVisualRepresentation(TObject h);
|
||||
protected abstract DrawableHitObject<TObject> GetVisualRepresentation(TObject h);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Playfield.
|
||||
/// </summary>
|
||||
/// <returns>The Playfield.</returns>
|
||||
protected abstract Playfield<TObject, TJudgement> CreatePlayfield();
|
||||
protected abstract Playfield CreatePlayfield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -356,11 +318,9 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
/// <typeparam name="TPlayfield">The type of Playfield contained by this RulesetContainer.</typeparam>
|
||||
/// <typeparam name="TObject">The type of HitObject contained by this RulesetContainer.</typeparam>
|
||||
/// <typeparam name="TJudgement">The type of Judgement of DrawableHitObjects contained by this RulesetContainer.</typeparam>
|
||||
public abstract class RulesetContainer<TPlayfield, TObject, TJudgement> : RulesetContainer<TObject, TJudgement>
|
||||
public abstract class RulesetContainer<TPlayfield, TObject> : RulesetContainer<TObject>
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
where TPlayfield : Playfield<TObject, TJudgement>
|
||||
where TPlayfield : Playfield
|
||||
{
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
|
@ -11,19 +11,15 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="Playfield{TObject, TJudgement}"/> specialized towards scrolling <see cref="DrawableHitObject"/>s.
|
||||
/// A type of <see cref="Playfield"/> specialized towards scrolling <see cref="DrawableHitObject"/>s.
|
||||
/// </summary>
|
||||
public class ScrollingPlayfield<TObject, TJudgement> : Playfield<TObject, TJudgement>
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
public class ScrollingPlayfield : Playfield
|
||||
{
|
||||
/// <summary>
|
||||
/// The default span of time visible by the length of the scrolling axes.
|
||||
@ -65,7 +61,7 @@ namespace osu.Game.Rulesets.UI
|
||||
public new readonly ScrollingHitObjectContainer HitObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ScrollingPlayfield{TObject, TJudgement}"/>.
|
||||
/// Creates a new <see cref="ScrollingPlayfield"/>.
|
||||
/// </summary>
|
||||
/// <param name="scrollingAxes">The axes on which <see cref="DrawableHitObject"/>s in this container should scroll.</param>
|
||||
/// <param name="customWidth">Whether we want our internal coordinate system to be scaled to a specified width</param>
|
||||
@ -77,21 +73,21 @@ namespace osu.Game.Rulesets.UI
|
||||
HitObjects.Reversed.BindTo(Reversed);
|
||||
}
|
||||
|
||||
private List<ScrollingPlayfield<TObject, TJudgement>> nestedPlayfields;
|
||||
private List<ScrollingPlayfield> nestedPlayfields;
|
||||
/// <summary>
|
||||
/// All the <see cref="ScrollingPlayfield{TObject, TJudgement}"/>s nested inside this playfield.
|
||||
/// All the <see cref="ScrollingPlayfield"/>s nested inside this playfield.
|
||||
/// </summary>
|
||||
public IEnumerable<ScrollingPlayfield<TObject, TJudgement>> NestedPlayfields => nestedPlayfields;
|
||||
public IEnumerable<ScrollingPlayfield> NestedPlayfields => nestedPlayfields;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a <see cref="ScrollingPlayfield{TObject, TJudgement}"/> to this playfield. The nested <see cref="ScrollingPlayfield{TObject, TJudgement}"/>
|
||||
/// Adds a <see cref="ScrollingPlayfield"/> to this playfield. The nested <see cref="ScrollingPlayfield"/>
|
||||
/// will be given all of the same speed adjustments as this playfield.
|
||||
/// </summary>
|
||||
/// <param name="otherPlayfield">The <see cref="ScrollingPlayfield{TObject, TJudgement}"/> to add.</param>
|
||||
protected void AddNested(ScrollingPlayfield<TObject, TJudgement> otherPlayfield)
|
||||
/// <param name="otherPlayfield">The <see cref="ScrollingPlayfield"/> to add.</param>
|
||||
protected void AddNested(ScrollingPlayfield otherPlayfield)
|
||||
{
|
||||
if (nestedPlayfields == null)
|
||||
nestedPlayfields = new List<ScrollingPlayfield<TObject, TJudgement>>();
|
||||
nestedPlayfields = new List<ScrollingPlayfield>();
|
||||
|
||||
nestedPlayfields.Add(otherPlayfield);
|
||||
}
|
||||
@ -119,7 +115,7 @@ namespace osu.Game.Rulesets.UI
|
||||
this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing));
|
||||
}
|
||||
|
||||
private class TransformVisibleTimeRange : Transform<double, ScrollingPlayfield<TObject, TJudgement>>
|
||||
private class TransformVisibleTimeRange : Transform<double, ScrollingPlayfield>
|
||||
{
|
||||
private double valueAt(double time)
|
||||
{
|
||||
@ -131,8 +127,8 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
public override string TargetMember => "VisibleTimeRange.Value";
|
||||
|
||||
protected override void Apply(ScrollingPlayfield<TObject, TJudgement> d, double time) => d.VisibleTimeRange.Value = valueAt(time);
|
||||
protected override void ReadIntoStartValue(ScrollingPlayfield<TObject, TJudgement> d) => StartValue = d.VisibleTimeRange.Value;
|
||||
protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time);
|
||||
protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Lists;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
@ -17,17 +16,16 @@ using osu.Game.Rulesets.Timing;
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="RulesetContainer{TPlayfield,TObject,TJudgement}"/> that supports a <see cref="ScrollingPlayfield{TObject, TJudgement}"/>.
|
||||
/// <see cref="HitObject"/>s inside this <see cref="RulesetContainer{TPlayfield,TObject,TJudgement}"/> will scroll within the playfield.
|
||||
/// A type of <see cref="RulesetContainer{TPlayfield,TObject}"/> that supports a <see cref="ScrollingPlayfield"/>.
|
||||
/// <see cref="HitObject"/>s inside this <see cref="RulesetContainer{TPlayfield,TObject}"/> will scroll within the playfield.
|
||||
/// </summary>
|
||||
public abstract class ScrollingRulesetContainer<TPlayfield, TObject, TJudgement> : RulesetContainer<TPlayfield, TObject, TJudgement>
|
||||
public abstract class ScrollingRulesetContainer<TPlayfield, TObject> : RulesetContainer<TPlayfield, TObject>
|
||||
where TObject : HitObject
|
||||
where TJudgement : Judgement
|
||||
where TPlayfield : ScrollingPlayfield<TObject, TJudgement>
|
||||
where TPlayfield : ScrollingPlayfield
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the default <see cref="MultiplierControlPoint"/>s that adjust the scrolling rate of <see cref="HitObject"/>s
|
||||
/// inside this <see cref="RulesetContainer{TPlayfield,TObject,TJudgement}"/>.
|
||||
/// inside this <see cref="RulesetContainer{TPlayfield,TObject}"/>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected readonly SortedList<MultiplierControlPoint> DefaultControlPoints = new SortedList<MultiplierControlPoint>(Comparer<MultiplierControlPoint>.Default);
|
||||
@ -88,7 +86,7 @@ namespace osu.Game.Rulesets.UI
|
||||
DefaultControlPoints.ForEach(c => applySpeedAdjustment(c, Playfield));
|
||||
}
|
||||
|
||||
private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield<TObject, TJudgement> playfield)
|
||||
private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield)
|
||||
{
|
||||
playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint));
|
||||
playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p));
|
||||
|
@ -83,7 +83,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
Alpha = 0,
|
||||
Triangles = false,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Interactive = false,
|
||||
Colour = Color4.DarkGray,
|
||||
Ripple = false
|
||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
texture = Texture.WhitePixel;
|
||||
AccentColour = new Color4(1, 1, 1, 0.2f);
|
||||
BlendingMode = BlendingMode.Additive;
|
||||
Blending = BlendingMode.Additive;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Screens.Menu
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
},
|
||||
rightBox = new Box
|
||||
{
|
||||
@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
@ -169,7 +169,7 @@ namespace osu.Game.Screens.Menu
|
||||
flashLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
@ -272,14 +272,22 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
const float scale_adjust_cutoff = 0.4f;
|
||||
const float velocity_adjust_cutoff = 0.98f;
|
||||
const float paused_velocity = 0.5f;
|
||||
|
||||
var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value.Track?.CurrentAmplitudes.Maximum ?? 0 : 0;
|
||||
logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, Easing.OutQuint);
|
||||
if (Beatmap.Value.Track.IsRunning)
|
||||
{
|
||||
var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value.Track.CurrentAmplitudes.Maximum : 0;
|
||||
logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, Easing.OutQuint);
|
||||
|
||||
if (maxAmplitude > velocity_adjust_cutoff)
|
||||
triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50;
|
||||
if (maxAmplitude > velocity_adjust_cutoff)
|
||||
triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50;
|
||||
else
|
||||
triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, 1, 0.995f, Time.Elapsed);
|
||||
}
|
||||
else
|
||||
triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, 1, 0.995f, Time.Elapsed);
|
||||
{
|
||||
triangles.Velocity = paused_velocity;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
|
@ -100,7 +100,7 @@ namespace osu.Game.Screens
|
||||
|
||||
Colour = getColourFor(GetType()),
|
||||
Alpha = 0.2f,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
},
|
||||
textContainer = new FillFlowContainer
|
||||
{
|
||||
|
@ -304,7 +304,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
BlurSigma = new Vector2(4),
|
||||
CacheDrawnFrameBuffer = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Size = new Vector2(3f),
|
||||
Children = new[]
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ namespace osu.Game.Screens.Select.Options
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
EdgeSmoothness = new Vector2(1.5f, 0),
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
|
@ -215,7 +215,6 @@
|
||||
<Compile Include="Rulesets\Objects\Types\IHasYPosition.cs" />
|
||||
<Compile Include="Rulesets\Replays\Replay.cs" />
|
||||
<Compile Include="Rulesets\Judgements\DrawableJudgement.cs" />
|
||||
<Compile Include="Rulesets\Judgements\IPartialJudgement.cs" />
|
||||
<Compile Include="Rulesets\Replays\FramedReplayInputHandler.cs" />
|
||||
<Compile Include="Rulesets\Mods\IApplicableMod.cs" />
|
||||
<Compile Include="Rulesets\Mods\ModType.cs" />
|
||||
|
Reference in New Issue
Block a user