mirror of
https://github.com/osukey/osukey.git
synced 2025-08-03 22:56:36 +09:00
Normalize all the line endings
This commit is contained in:
@ -1,21 +1,21 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public class BarLine : ManiaHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The control point which this bar line is part of.
|
||||
/// </summary>
|
||||
public TimingControlPoint ControlPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the beat which this bar line represents within the control point.
|
||||
/// This is a "major" bar line if <see cref="BeatIndex"/> % <see cref="TimingControlPoint.TimeSignature"/> == 0.
|
||||
/// </summary>
|
||||
public int BeatIndex;
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public class BarLine : ManiaHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The control point which this bar line is part of.
|
||||
/// </summary>
|
||||
public TimingControlPoint ControlPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the beat which this bar line represents within the control point.
|
||||
/// This is a "major" bar line if <see cref="BeatIndex"/> % <see cref="TimingControlPoint.TimeSignature"/> == 0.
|
||||
/// </summary>
|
||||
public int BeatIndex;
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,74 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject,
|
||||
/// this does not handle input/sound like a normal hit object.
|
||||
/// </summary>
|
||||
public class DrawableBarLine : DrawableManiaHitObject<BarLine>
|
||||
{
|
||||
/// <summary>
|
||||
/// Height of major bar line triangles.
|
||||
/// </summary>
|
||||
private const float triangle_height = 12;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the major bar line triangles from the sides of the bar line.
|
||||
/// </summary>
|
||||
private const float triangle_offset = 9;
|
||||
|
||||
public DrawableBarLine(BarLine barLine)
|
||||
: base(barLine)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 1;
|
||||
|
||||
AddInternal(new Box
|
||||
{
|
||||
Name = "Bar line",
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0;
|
||||
|
||||
if (isMajor)
|
||||
{
|
||||
AddInternal(new EquilateralTriangle
|
||||
{
|
||||
Name = "Left triangle",
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(triangle_height),
|
||||
X = -triangle_offset,
|
||||
Rotation = 90
|
||||
});
|
||||
|
||||
AddInternal(new EquilateralTriangle
|
||||
{
|
||||
Name = "Right triangle",
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(triangle_height),
|
||||
X = triangle_offset,
|
||||
Rotation = -90
|
||||
});
|
||||
}
|
||||
|
||||
if (!isMajor && barLine.BeatIndex % 2 == 1)
|
||||
Alpha = 0.2f;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="BarLine"/>. Although this derives DrawableManiaHitObject,
|
||||
/// this does not handle input/sound like a normal hit object.
|
||||
/// </summary>
|
||||
public class DrawableBarLine : DrawableManiaHitObject<BarLine>
|
||||
{
|
||||
/// <summary>
|
||||
/// Height of major bar line triangles.
|
||||
/// </summary>
|
||||
private const float triangle_height = 12;
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the major bar line triangles from the sides of the bar line.
|
||||
/// </summary>
|
||||
private const float triangle_offset = 9;
|
||||
|
||||
public DrawableBarLine(BarLine barLine)
|
||||
: base(barLine)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = 1;
|
||||
|
||||
AddInternal(new Box
|
||||
{
|
||||
Name = "Bar line",
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0;
|
||||
|
||||
if (isMajor)
|
||||
{
|
||||
AddInternal(new EquilateralTriangle
|
||||
{
|
||||
Name = "Left triangle",
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(triangle_height),
|
||||
X = -triangle_offset,
|
||||
Rotation = 90
|
||||
});
|
||||
|
||||
AddInternal(new EquilateralTriangle
|
||||
{
|
||||
Name = "Right triangle",
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(triangle_height),
|
||||
X = triangle_offset,
|
||||
Rotation = -90
|
||||
});
|
||||
}
|
||||
|
||||
if (!isMajor && barLine.BeatIndex % 2 == 1)
|
||||
Alpha = 0.2f;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,254 +1,254 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="HoldNote"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly DrawableNote head;
|
||||
private readonly DrawableNote tail;
|
||||
|
||||
private readonly GlowPiece glowPiece;
|
||||
private readonly BodyPiece bodyPiece;
|
||||
private readonly Container fullHeightContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||
/// </summary>
|
||||
private double? holdStartTime;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hold note has been released too early and shouldn't give full score for the release.
|
||||
/// </summary>
|
||||
private bool hasBroken;
|
||||
|
||||
public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
Container<DrawableHoldNoteTick> tickContainer;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
// The hit object itself cannot be used for various elements because the tail overshoots it
|
||||
// So a specialized container that is updated to contain the tail height is used
|
||||
fullHeightContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Child = glowPiece = new GlowPiece()
|
||||
},
|
||||
bodyPiece = new BodyPiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
tickContainer = new Container<DrawableHoldNoteTick>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ChildrenEnumerable = HitObject.NestedHitObjects.OfType<HoldNoteTick>().Select(tick => new DrawableHoldNoteTick(tick)
|
||||
{
|
||||
HoldStartTime = () => holdStartTime
|
||||
})
|
||||
},
|
||||
head = new DrawableHeadNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
tail = new DrawableTailNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var tick in tickContainer)
|
||||
AddNested(tick);
|
||||
|
||||
AddNested(head);
|
||||
AddNested(tail);
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
|
||||
glowPiece.AccentColour = value;
|
||||
bodyPiece.AccentColour = value;
|
||||
head.AccentColour = value;
|
||||
tail.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Make the body piece not lie under the head note
|
||||
bodyPiece.Y = head.Height;
|
||||
bodyPiece.Height = DrawHeight - head.Height;
|
||||
|
||||
// Make the fullHeightContainer "contain" the height of the tail note, keeping in mind
|
||||
// that the tail note overshoots the height of this hit object
|
||||
fullHeightContainer.Height = DrawHeight + tail.Height;
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
// Make sure the action happened within the body of the hold note
|
||||
if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed
|
||||
// and within the limited range of the above if-statement. This state will be managed by the head note if the
|
||||
// user has pressed during the hit windows of the head note.
|
||||
holdStartTime = Time.Current;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
holdStartTime = null;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!tail.IsHit)
|
||||
hasBroken = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The head note of a hold.
|
||||
/// </summary>
|
||||
private class DrawableHeadNote : DrawableNote
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Head, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
public override bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (!base.OnPressed(action))
|
||||
return false;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (Judgements.Any(j => j.Result == HitResult.Miss))
|
||||
holdNote.hasBroken = true;
|
||||
|
||||
// The head note also handles early hits before the body, but we want accurate early hits to count as the body being held
|
||||
// The body doesn't handle these early early hits, so we have to explicitly set the holding state here
|
||||
holdNote.holdStartTime = Time.Current;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
// The holdnote keeps scrolling through for now, so having the head disappear looks weird
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tail note of a hold.
|
||||
/// </summary>
|
||||
private class DrawableTailNote : DrawableNote
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Tail, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||
{
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitResult.Miss,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
if (result == HitResult.None)
|
||||
return;
|
||||
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = result,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
// The holdnote keeps scrolling through, so having the tail disappear looks weird
|
||||
}
|
||||
|
||||
public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down
|
||||
|
||||
public override bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdNote.holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
UpdateJudgement(true);
|
||||
|
||||
// Handled by the hold note, which will set holding = false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="HoldNote"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableHoldNote : DrawableManiaHitObject<HoldNote>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly DrawableNote head;
|
||||
private readonly DrawableNote tail;
|
||||
|
||||
private readonly GlowPiece glowPiece;
|
||||
private readonly BodyPiece bodyPiece;
|
||||
private readonly Container fullHeightContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||
/// </summary>
|
||||
private double? holdStartTime;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hold note has been released too early and shouldn't give full score for the release.
|
||||
/// </summary>
|
||||
private bool hasBroken;
|
||||
|
||||
public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
Container<DrawableHoldNoteTick> tickContainer;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
// The hit object itself cannot be used for various elements because the tail overshoots it
|
||||
// So a specialized container that is updated to contain the tail height is used
|
||||
fullHeightContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Child = glowPiece = new GlowPiece()
|
||||
},
|
||||
bodyPiece = new BodyPiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
tickContainer = new Container<DrawableHoldNoteTick>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ChildrenEnumerable = HitObject.NestedHitObjects.OfType<HoldNoteTick>().Select(tick => new DrawableHoldNoteTick(tick)
|
||||
{
|
||||
HoldStartTime = () => holdStartTime
|
||||
})
|
||||
},
|
||||
head = new DrawableHeadNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
tail = new DrawableTailNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var tick in tickContainer)
|
||||
AddNested(tick);
|
||||
|
||||
AddNested(head);
|
||||
AddNested(tail);
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
|
||||
glowPiece.AccentColour = value;
|
||||
bodyPiece.AccentColour = value;
|
||||
head.AccentColour = value;
|
||||
tail.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// Make the body piece not lie under the head note
|
||||
bodyPiece.Y = head.Height;
|
||||
bodyPiece.Height = DrawHeight - head.Height;
|
||||
|
||||
// Make the fullHeightContainer "contain" the height of the tail note, keeping in mind
|
||||
// that the tail note overshoots the height of this hit object
|
||||
fullHeightContainer.Height = DrawHeight + tail.Height;
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
// Make sure the action happened within the body of the hold note
|
||||
if (Time.Current < HitObject.StartTime || Time.Current > HitObject.EndTime)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed
|
||||
// and within the limited range of the above if-statement. This state will be managed by the head note if the
|
||||
// user has pressed during the hit windows of the head note.
|
||||
holdStartTime = Time.Current;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
holdStartTime = null;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!tail.IsHit)
|
||||
hasBroken = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The head note of a hold.
|
||||
/// </summary>
|
||||
private class DrawableHeadNote : DrawableNote
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableHeadNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Head, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
public override bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (!base.OnPressed(action))
|
||||
return false;
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (Judgements.Any(j => j.Result == HitResult.Miss))
|
||||
holdNote.hasBroken = true;
|
||||
|
||||
// The head note also handles early hits before the body, but we want accurate early hits to count as the body being held
|
||||
// The body doesn't handle these early early hits, so we have to explicitly set the holding state here
|
||||
holdNote.holdStartTime = Time.Current;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
// The holdnote keeps scrolling through for now, so having the head disappear looks weird
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tail note of a hold.
|
||||
/// </summary>
|
||||
private class DrawableTailNote : DrawableNote
|
||||
{
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableTailNote(DrawableHoldNote holdNote, ManiaAction action)
|
||||
: base(holdNote.HitObject.Tail, action)
|
||||
{
|
||||
this.holdNote = holdNote;
|
||||
|
||||
GlowPiece.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||
{
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitResult.Miss,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
if (result == HitResult.None)
|
||||
return;
|
||||
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = result,
|
||||
HasBroken = holdNote.hasBroken
|
||||
});
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
// The holdnote keeps scrolling through, so having the tail disappear looks weird
|
||||
}
|
||||
|
||||
public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down
|
||||
|
||||
public override bool OnReleased(ManiaAction action)
|
||||
{
|
||||
// Make sure that the user started holding the key during the hold note
|
||||
if (!holdNote.holdStartTime.HasValue)
|
||||
return false;
|
||||
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
UpdateJudgement(true);
|
||||
|
||||
// Handled by the hold note, which will set holding = false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,111 +1,111 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="HoldNoteTick"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableHoldNoteTick : DrawableManiaHitObject<HoldNoteTick>
|
||||
{
|
||||
/// <summary>
|
||||
/// References the time at which the user started holding the hold note.
|
||||
/// </summary>
|
||||
public Func<double?> HoldStartTime;
|
||||
|
||||
private readonly Container glowContainer;
|
||||
|
||||
public DrawableHoldNoteTick(HoldNoteTick hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Size = new Vector2(1);
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
glowContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
|
||||
glowContainer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 2f,
|
||||
Roundness = 15f,
|
||||
Colour = value.Opacity(0.3f)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
return;
|
||||
|
||||
if (Time.Current < HitObject.StartTime)
|
||||
return;
|
||||
|
||||
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
||||
return;
|
||||
|
||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (State.Value)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
AccentColour = Color4.Green;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (AllJudged)
|
||||
return;
|
||||
|
||||
if (HoldStartTime?.Invoke() == null)
|
||||
return;
|
||||
|
||||
UpdateJudgement(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="HoldNoteTick"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableHoldNoteTick : DrawableManiaHitObject<HoldNoteTick>
|
||||
{
|
||||
/// <summary>
|
||||
/// References the time at which the user started holding the hold note.
|
||||
/// </summary>
|
||||
public Func<double?> HoldStartTime;
|
||||
|
||||
private readonly Container glowContainer;
|
||||
|
||||
public DrawableHoldNoteTick(HoldNoteTick hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Size = new Vector2(1);
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
glowContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
|
||||
glowContainer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 2f,
|
||||
Roundness = 15f,
|
||||
Colour = value.Opacity(0.3f)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
return;
|
||||
|
||||
if (Time.Current < HitObject.StartTime)
|
||||
return;
|
||||
|
||||
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
||||
return;
|
||||
|
||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (State.Value)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
AccentColour = Color4.Green;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (AllJudged)
|
||||
return;
|
||||
|
||||
if (HoldStartTime?.Invoke() == null)
|
||||
return;
|
||||
|
||||
UpdateJudgement(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableManiaHitObject<TObject> : DrawableHitObject<ManiaHitObject>
|
||||
where TObject : ManiaHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that will trigger input for this hit object.
|
||||
/// </summary>
|
||||
protected ManiaAction Action { get; }
|
||||
|
||||
public new TObject HitObject;
|
||||
|
||||
protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
HitObject = hitObject;
|
||||
|
||||
if (action != null)
|
||||
Action = action.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableManiaHitObject<TObject> : DrawableHitObject<ManiaHitObject>
|
||||
where TObject : ManiaHitObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that will trigger input for this hit object.
|
||||
/// </summary>
|
||||
protected ManiaAction Action { get; }
|
||||
|
||||
public new TObject HitObject;
|
||||
|
||||
protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null)
|
||||
: base(hitObject)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
HitObject = hitObject;
|
||||
|
||||
if (action != null)
|
||||
Action = action.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +1,95 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="Note"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
protected readonly GlowPiece GlowPiece;
|
||||
|
||||
private readonly LaneGlowPiece laneGlowPiece;
|
||||
private readonly NotePiece headPiece;
|
||||
|
||||
public DrawableNote(Note hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
laneGlowPiece = new LaneGlowPiece
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
GlowPiece = new GlowPiece(),
|
||||
headPiece = new NotePiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
laneGlowPiece.AccentColour = AccentColour;
|
||||
GlowPiece.AccentColour = AccentColour;
|
||||
headPiece.AccentColour = AccentColour;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Miss });
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
if (result == HitResult.None)
|
||||
return;
|
||||
|
||||
AddJudgement(new ManiaJudgement { Result = result });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(100).Expire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
return UpdateJudgement(true);
|
||||
}
|
||||
|
||||
public virtual bool OnReleased(ManiaAction action) => false;
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualises a <see cref="Note"/> hit object.
|
||||
/// </summary>
|
||||
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
protected readonly GlowPiece GlowPiece;
|
||||
|
||||
private readonly LaneGlowPiece laneGlowPiece;
|
||||
private readonly NotePiece headPiece;
|
||||
|
||||
public DrawableNote(Note hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
laneGlowPiece = new LaneGlowPiece
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
GlowPiece = new GlowPiece(),
|
||||
headPiece = new NotePiece
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
laneGlowPiece.AccentColour = AccentColour;
|
||||
GlowPiece.AccentColour = AccentColour;
|
||||
headPiece.AccentColour = AccentColour;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (!HitObject.HitWindows.CanBeHit(timeOffset))
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Miss });
|
||||
return;
|
||||
}
|
||||
|
||||
var result = HitObject.HitWindows.ResultFor(timeOffset);
|
||||
if (result == HitResult.None)
|
||||
return;
|
||||
|
||||
AddJudgement(new ManiaJudgement { Result = result });
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case ArmedState.Hit:
|
||||
case ArmedState.Miss:
|
||||
this.FadeOut(100).Expire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action != Action)
|
||||
return false;
|
||||
|
||||
return UpdateJudgement(true);
|
||||
}
|
||||
|
||||
public virtual bool OnReleased(ManiaAction action) => false;
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +1,132 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Caching;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents length-wise portion of a hold note.
|
||||
/// </summary>
|
||||
internal class BodyPiece : Container, IHasAccentColour
|
||||
{
|
||||
private readonly Container subtractionLayer;
|
||||
|
||||
private readonly Drawable background;
|
||||
private readonly BufferedContainer foreground;
|
||||
private readonly BufferedContainer subtractionContainer;
|
||||
|
||||
public BodyPiece()
|
||||
{
|
||||
Blending = BlendingMode.Additive;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
foreground = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box { RelativeSizeAxes = Axes.Both },
|
||||
subtractionContainer = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// This is needed because we're blending with another object
|
||||
BackgroundColour = Color4.White.Opacity(0),
|
||||
CacheDrawnFrameBuffer = true,
|
||||
// The 'hole' is achieved by subtracting the result of this container with the parent
|
||||
Blending = new BlendingParameters { AlphaEquation = BlendingEquation.ReverseSubtract },
|
||||
Child = subtractionLayer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
// Height computed in Update
|
||||
Width = 1,
|
||||
Masking = true,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
}
|
||||
|
||||
private Cached subtractionCache = new Cached();
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
subtractionCache.Invalidate();
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!subtractionCache.IsValid)
|
||||
{
|
||||
subtractionLayer.Width = 5;
|
||||
subtractionLayer.Height = Math.Max(0, DrawHeight - DrawWidth);
|
||||
subtractionLayer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = DrawWidth
|
||||
};
|
||||
|
||||
foreground.ForceRedraw();
|
||||
subtractionContainer.ForceRedraw();
|
||||
|
||||
subtractionCache.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccentColour()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
foreground.Colour = AccentColour.Opacity(0.4f);
|
||||
background.Colour = AccentColour.Opacity(0.2f);
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Caching;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents length-wise portion of a hold note.
|
||||
/// </summary>
|
||||
internal class BodyPiece : Container, IHasAccentColour
|
||||
{
|
||||
private readonly Container subtractionLayer;
|
||||
|
||||
private readonly Drawable background;
|
||||
private readonly BufferedContainer foreground;
|
||||
private readonly BufferedContainer subtractionContainer;
|
||||
|
||||
public BodyPiece()
|
||||
{
|
||||
Blending = BlendingMode.Additive;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
foreground = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box { RelativeSizeAxes = Axes.Both },
|
||||
subtractionContainer = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// This is needed because we're blending with another object
|
||||
BackgroundColour = Color4.White.Opacity(0),
|
||||
CacheDrawnFrameBuffer = true,
|
||||
// The 'hole' is achieved by subtracting the result of this container with the parent
|
||||
Blending = new BlendingParameters { AlphaEquation = BlendingEquation.ReverseSubtract },
|
||||
Child = subtractionLayer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
// Height computed in Update
|
||||
Width = 1,
|
||||
Masking = true,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
}
|
||||
|
||||
private Cached subtractionCache = new Cached();
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
subtractionCache.Invalidate();
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (!subtractionCache.IsValid)
|
||||
{
|
||||
subtractionLayer.Width = 5;
|
||||
subtractionLayer.Height = Math.Max(0, DrawHeight - DrawWidth);
|
||||
subtractionLayer.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = DrawWidth
|
||||
};
|
||||
|
||||
foreground.ForceRedraw();
|
||||
subtractionContainer.ForceRedraw();
|
||||
|
||||
subtractionCache.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAccentColour()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
foreground.Colour = AccentColour.Opacity(0.4f);
|
||||
background.Colour = AccentColour.Opacity(0.2f);
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +1,65 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class GlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float glow_alpha = 0.7f;
|
||||
private const float glow_radius = 5;
|
||||
|
||||
public GlowPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
|
||||
InternalChild = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateGlow();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
updateGlow();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGlow()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = AccentColour.Opacity(glow_alpha),
|
||||
Radius = glow_radius,
|
||||
Hollow = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class GlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float glow_alpha = 0.7f;
|
||||
private const float glow_radius = 5;
|
||||
|
||||
public GlowPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
|
||||
InternalChild = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateGlow();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
updateGlow();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGlow()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = AccentColour.Opacity(glow_alpha),
|
||||
Radius = glow_radius,
|
||||
Hollow = true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +1,85 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class LaneGlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float total_height = 100;
|
||||
private const float glow_height = 50;
|
||||
private const float glow_alpha = 0.4f;
|
||||
private const float edge_alpha = 0.3f;
|
||||
|
||||
public LaneGlowPiece()
|
||||
{
|
||||
BypassAutoSizeAxes = Axes.Both;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = total_height;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Left edge",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Right edge",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Glow",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = glow_height,
|
||||
Children = createGradient(glow_alpha)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Drawable[] createGradient(float alpha) => new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Top",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha))
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Name = "Bottom",
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent)
|
||||
}
|
||||
};
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return Colour; }
|
||||
set { Colour = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
public class LaneGlowPiece : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float total_height = 100;
|
||||
private const float glow_height = 50;
|
||||
private const float glow_alpha = 0.4f;
|
||||
private const float edge_alpha = 0.3f;
|
||||
|
||||
public LaneGlowPiece()
|
||||
{
|
||||
BypassAutoSizeAxes = Axes.Both;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = total_height;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Left edge",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Right edge",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 1,
|
||||
Children = createGradient(edge_alpha)
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Glow",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = glow_height,
|
||||
Children = createGradient(glow_alpha)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Drawable[] createGradient(float alpha) => new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Top",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White.Opacity(alpha))
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Name = "Bottom",
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(alpha), Color4.Transparent)
|
||||
}
|
||||
};
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return Colour; }
|
||||
set { Colour = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the static hit markers of notes.
|
||||
/// </summary>
|
||||
internal class NotePiece : Container, IHasAccentColour
|
||||
{
|
||||
private const float head_height = 10;
|
||||
private const float head_colour_height = 6;
|
||||
|
||||
private readonly Box colouredBox;
|
||||
|
||||
public NotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = head_height;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
colouredBox = new Box
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = head_colour_height,
|
||||
Alpha = 0.2f
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
colouredBox.Colour = AccentColour.Lighten(0.9f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the static hit markers of notes.
|
||||
/// </summary>
|
||||
internal class NotePiece : Container, IHasAccentColour
|
||||
{
|
||||
private const float head_height = 10;
|
||||
private const float head_colour_height = 6;
|
||||
|
||||
private readonly Box colouredBox;
|
||||
|
||||
public NotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = head_height;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
colouredBox = new Box
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = head_colour_height,
|
||||
Alpha = 0.2f
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
colouredBox.Colour = AccentColour.Lighten(0.9f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,117 +1,117 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hit object which requires pressing, holding, and releasing a key.
|
||||
/// </summary>
|
||||
public class HoldNote : ManiaHitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime => StartTime + Duration;
|
||||
|
||||
private double duration;
|
||||
public double Duration
|
||||
{
|
||||
get { return duration; }
|
||||
set
|
||||
{
|
||||
duration = value;
|
||||
Tail.StartTime = EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override double StartTime
|
||||
{
|
||||
get { return base.StartTime; }
|
||||
set
|
||||
{
|
||||
base.StartTime = value;
|
||||
Head.StartTime = value;
|
||||
Tail.StartTime = EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Column
|
||||
{
|
||||
get { return base.Column; }
|
||||
set
|
||||
{
|
||||
base.Column = value;
|
||||
Head.Column = value;
|
||||
Tail.Column = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The head note of the hold.
|
||||
/// </summary>
|
||||
public readonly Note Head = new Note();
|
||||
|
||||
/// <summary>
|
||||
/// The tail note of the hold.
|
||||
/// </summary>
|
||||
public readonly Note Tail = new TailNote();
|
||||
|
||||
/// <summary>
|
||||
/// The time between ticks of this hold.
|
||||
/// </summary>
|
||||
private double tickSpacing = 50;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||
tickSpacing = timingPoint.BeatLength / difficulty.SliderTickRate;
|
||||
|
||||
Head.ApplyDefaults(controlPointInfo, difficulty);
|
||||
Tail.ApplyDefaults(controlPointInfo, difficulty);
|
||||
}
|
||||
|
||||
protected override void CreateNestedHitObjects()
|
||||
{
|
||||
base.CreateNestedHitObjects();
|
||||
|
||||
createTicks();
|
||||
}
|
||||
|
||||
private void createTicks()
|
||||
{
|
||||
if (tickSpacing == 0)
|
||||
return;
|
||||
|
||||
for (double t = StartTime + tickSpacing; t <= EndTime - tickSpacing; t += tickSpacing)
|
||||
{
|
||||
AddNested(new HoldNoteTick
|
||||
{
|
||||
StartTime = t,
|
||||
Column = Column
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tail of the hold note.
|
||||
/// </summary>
|
||||
private class TailNote : Note
|
||||
{
|
||||
/// <summary>
|
||||
/// Lenience of release hit windows. This is to make cases where the hold note release
|
||||
/// is timed alongside presses of other hit objects less awkward.
|
||||
/// </summary>
|
||||
private const double release_window_lenience = 1.5;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
HitWindows *= release_window_lenience;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hit object which requires pressing, holding, and releasing a key.
|
||||
/// </summary>
|
||||
public class HoldNote : ManiaHitObject, IHasEndTime
|
||||
{
|
||||
public double EndTime => StartTime + Duration;
|
||||
|
||||
private double duration;
|
||||
public double Duration
|
||||
{
|
||||
get { return duration; }
|
||||
set
|
||||
{
|
||||
duration = value;
|
||||
Tail.StartTime = EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override double StartTime
|
||||
{
|
||||
get { return base.StartTime; }
|
||||
set
|
||||
{
|
||||
base.StartTime = value;
|
||||
Head.StartTime = value;
|
||||
Tail.StartTime = EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Column
|
||||
{
|
||||
get { return base.Column; }
|
||||
set
|
||||
{
|
||||
base.Column = value;
|
||||
Head.Column = value;
|
||||
Tail.Column = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The head note of the hold.
|
||||
/// </summary>
|
||||
public readonly Note Head = new Note();
|
||||
|
||||
/// <summary>
|
||||
/// The tail note of the hold.
|
||||
/// </summary>
|
||||
public readonly Note Tail = new TailNote();
|
||||
|
||||
/// <summary>
|
||||
/// The time between ticks of this hold.
|
||||
/// </summary>
|
||||
private double tickSpacing = 50;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||
tickSpacing = timingPoint.BeatLength / difficulty.SliderTickRate;
|
||||
|
||||
Head.ApplyDefaults(controlPointInfo, difficulty);
|
||||
Tail.ApplyDefaults(controlPointInfo, difficulty);
|
||||
}
|
||||
|
||||
protected override void CreateNestedHitObjects()
|
||||
{
|
||||
base.CreateNestedHitObjects();
|
||||
|
||||
createTicks();
|
||||
}
|
||||
|
||||
private void createTicks()
|
||||
{
|
||||
if (tickSpacing == 0)
|
||||
return;
|
||||
|
||||
for (double t = StartTime + tickSpacing; t <= EndTime - tickSpacing; t += tickSpacing)
|
||||
{
|
||||
AddNested(new HoldNoteTick
|
||||
{
|
||||
StartTime = t,
|
||||
Column = Column
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tail of the hold note.
|
||||
/// </summary>
|
||||
private class TailNote : Note
|
||||
{
|
||||
/// <summary>
|
||||
/// Lenience of release hit windows. This is to make cases where the hold note release
|
||||
/// is timed alongside presses of other hit objects less awkward.
|
||||
/// </summary>
|
||||
private const double release_window_lenience = 1.5;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
HitWindows *= release_window_lenience;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// A scoring tick of a hold note.
|
||||
/// </summary>
|
||||
public class HoldNoteTick : ManiaHitObject
|
||||
{
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// A scoring tick of a hold note.
|
||||
/// </summary>
|
||||
public class HoldNoteTick : ManiaHitObject
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Objects.Types;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public abstract class ManiaHitObject : HitObject, IHasColumn
|
||||
{
|
||||
public virtual int Column { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
HitWindows.AllowsPerfect = true;
|
||||
HitWindows.AllowsOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Objects.Types;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
public abstract class ManiaHitObject : HitObject, IHasColumn
|
||||
{
|
||||
public virtual int Column { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
HitWindows.AllowsPerfect = true;
|
||||
HitWindows.AllowsOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,113 +1,113 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
internal class ManiaHitObjectDifficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// Factor by how much individual / overall strain decays per second.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These values are results of tweaking a lot and taking into account general feedback.
|
||||
/// </remarks>
|
||||
internal const double INDIVIDUAL_DECAY_BASE = 0.125;
|
||||
internal const double OVERALL_DECAY_BASE = 0.30;
|
||||
|
||||
internal ManiaHitObject BaseHitObject;
|
||||
|
||||
private readonly int beatmapColumnCount;
|
||||
|
||||
|
||||
private readonly double endTime;
|
||||
private readonly double[] heldUntil;
|
||||
|
||||
/// <summary>
|
||||
/// Measures jacks or more generally: repeated presses of the same button
|
||||
/// </summary>
|
||||
private readonly double[] individualStrains;
|
||||
|
||||
internal double IndividualStrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return individualStrains[BaseHitObject.Column];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
individualStrains[BaseHitObject.Column] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measures note density in a way
|
||||
/// </summary>
|
||||
internal double OverallStrain = 1;
|
||||
|
||||
public ManiaHitObjectDifficulty(ManiaHitObject baseHitObject, int columnCount)
|
||||
{
|
||||
BaseHitObject = baseHitObject;
|
||||
|
||||
endTime = (baseHitObject as IHasEndTime)?.EndTime ?? baseHitObject.StartTime;
|
||||
|
||||
beatmapColumnCount = columnCount;
|
||||
heldUntil = new double[beatmapColumnCount];
|
||||
individualStrains = new double[beatmapColumnCount];
|
||||
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
individualStrains[i] = 0;
|
||||
heldUntil[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void CalculateStrains(ManiaHitObjectDifficulty previousHitObject, double timeRate)
|
||||
{
|
||||
// TODO: Factor in holds
|
||||
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
||||
double individualDecay = Math.Pow(INDIVIDUAL_DECAY_BASE, timeElapsed / 1000);
|
||||
double overallDecay = Math.Pow(OVERALL_DECAY_BASE, timeElapsed / 1000);
|
||||
|
||||
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
||||
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly
|
||||
|
||||
// Fill up the heldUntil array
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
heldUntil[i] = previousHitObject.heldUntil[i];
|
||||
|
||||
// If there is at least one other overlapping end or note, then we get an addition, buuuuuut...
|
||||
if (BaseHitObject.StartTime < heldUntil[i] && endTime > heldUntil[i])
|
||||
{
|
||||
holdAddition = 1.0;
|
||||
}
|
||||
|
||||
// ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1
|
||||
if (endTime == heldUntil[i])
|
||||
{
|
||||
holdAddition = 0;
|
||||
}
|
||||
|
||||
// We give a slight bonus to everything if something is held meanwhile
|
||||
if (heldUntil[i] > endTime)
|
||||
{
|
||||
holdFactor = 1.25;
|
||||
}
|
||||
|
||||
// Decay individual strains
|
||||
individualStrains[i] = previousHitObject.individualStrains[i] * individualDecay;
|
||||
}
|
||||
|
||||
heldUntil[BaseHitObject.Column] = endTime;
|
||||
|
||||
// Increase individual strain in own column
|
||||
IndividualStrain += 2.0 * holdFactor;
|
||||
|
||||
OverallStrain = previousHitObject.OverallStrain * overallDecay + (1.0 + holdAddition) * holdFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
internal class ManiaHitObjectDifficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// Factor by how much individual / overall strain decays per second.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These values are results of tweaking a lot and taking into account general feedback.
|
||||
/// </remarks>
|
||||
internal const double INDIVIDUAL_DECAY_BASE = 0.125;
|
||||
internal const double OVERALL_DECAY_BASE = 0.30;
|
||||
|
||||
internal ManiaHitObject BaseHitObject;
|
||||
|
||||
private readonly int beatmapColumnCount;
|
||||
|
||||
|
||||
private readonly double endTime;
|
||||
private readonly double[] heldUntil;
|
||||
|
||||
/// <summary>
|
||||
/// Measures jacks or more generally: repeated presses of the same button
|
||||
/// </summary>
|
||||
private readonly double[] individualStrains;
|
||||
|
||||
internal double IndividualStrain
|
||||
{
|
||||
get
|
||||
{
|
||||
return individualStrains[BaseHitObject.Column];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
individualStrains[BaseHitObject.Column] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measures note density in a way
|
||||
/// </summary>
|
||||
internal double OverallStrain = 1;
|
||||
|
||||
public ManiaHitObjectDifficulty(ManiaHitObject baseHitObject, int columnCount)
|
||||
{
|
||||
BaseHitObject = baseHitObject;
|
||||
|
||||
endTime = (baseHitObject as IHasEndTime)?.EndTime ?? baseHitObject.StartTime;
|
||||
|
||||
beatmapColumnCount = columnCount;
|
||||
heldUntil = new double[beatmapColumnCount];
|
||||
individualStrains = new double[beatmapColumnCount];
|
||||
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
individualStrains[i] = 0;
|
||||
heldUntil[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void CalculateStrains(ManiaHitObjectDifficulty previousHitObject, double timeRate)
|
||||
{
|
||||
// TODO: Factor in holds
|
||||
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
||||
double individualDecay = Math.Pow(INDIVIDUAL_DECAY_BASE, timeElapsed / 1000);
|
||||
double overallDecay = Math.Pow(OVERALL_DECAY_BASE, timeElapsed / 1000);
|
||||
|
||||
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
||||
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly
|
||||
|
||||
// Fill up the heldUntil array
|
||||
for (int i = 0; i < beatmapColumnCount; ++i)
|
||||
{
|
||||
heldUntil[i] = previousHitObject.heldUntil[i];
|
||||
|
||||
// If there is at least one other overlapping end or note, then we get an addition, buuuuuut...
|
||||
if (BaseHitObject.StartTime < heldUntil[i] && endTime > heldUntil[i])
|
||||
{
|
||||
holdAddition = 1.0;
|
||||
}
|
||||
|
||||
// ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1
|
||||
if (endTime == heldUntil[i])
|
||||
{
|
||||
holdAddition = 0;
|
||||
}
|
||||
|
||||
// We give a slight bonus to everything if something is held meanwhile
|
||||
if (heldUntil[i] > endTime)
|
||||
{
|
||||
holdFactor = 1.25;
|
||||
}
|
||||
|
||||
// Decay individual strains
|
||||
individualStrains[i] = previousHitObject.individualStrains[i] * individualDecay;
|
||||
}
|
||||
|
||||
heldUntil[BaseHitObject.Column] = endTime;
|
||||
|
||||
// Increase individual strain in own column
|
||||
IndividualStrain += 2.0 * holdFactor;
|
||||
|
||||
OverallStrain = previousHitObject.OverallStrain * overallDecay + (1.0 + holdAddition) * holdFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hit object which has a single hit press.
|
||||
/// </summary>
|
||||
public class Note : ManiaHitObject
|
||||
{
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hit object which has a single hit press.
|
||||
/// </summary>
|
||||
public class Note : ManiaHitObject
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of hit object which lies in one of a number of predetermined columns.
|
||||
/// </summary>
|
||||
public interface IHasColumn
|
||||
{
|
||||
/// <summary>
|
||||
/// The column which the hit object lies in.
|
||||
/// </summary>
|
||||
int Column { get; }
|
||||
}
|
||||
}
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of hit object which lies in one of a number of predetermined columns.
|
||||
/// </summary>
|
||||
public interface IHasColumn
|
||||
{
|
||||
/// <summary>
|
||||
/// The column which the hit object lies in.
|
||||
/// </summary>
|
||||
int Column { get; }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user