mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 14:12:55 +08:00
Initial game-wide update with the new SliderPath
This commit is contained in:
parent
c9a66c0d07
commit
3ebbf62b2a
@ -196,7 +196,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
AddStep($"move mouse to control point {index}", () =>
|
||||
{
|
||||
Vector2 position = slider.Position + slider.Path.ControlPoints[index];
|
||||
Vector2 position = slider.Position + slider.Path.ControlPoints[index].Position.Value;
|
||||
InputManager.MoveMouseTo(drawableObject.Parent.ToScreenSpace(position));
|
||||
});
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Position = slider.StackedPosition + slider.Path.ControlPoints[Index];
|
||||
Position = slider.StackedPosition + slider.Path.ControlPoints[Index].Position.Value;
|
||||
|
||||
updateMarkerDisplay();
|
||||
updateConnectingPath();
|
||||
@ -116,10 +116,10 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
{
|
||||
path.ClearVertices();
|
||||
|
||||
if (Index != slider.Path.ControlPoints.Length - 1)
|
||||
if (Index != slider.Path.ControlPoints.Count - 1)
|
||||
{
|
||||
path.AddVertex(Vector2.Zero);
|
||||
path.AddVertex(slider.Path.ControlPoints[Index + 1] - slider.Path.ControlPoints[Index]);
|
||||
path.AddVertex(slider.Path.ControlPoints[Index + 1].Position.Value - slider.Path.ControlPoints[Index].Position.Value);
|
||||
}
|
||||
|
||||
path.OriginPosition = path.PositionInBoundingBox(Vector2.Zero);
|
||||
@ -156,8 +156,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
|
||||
protected override bool OnDrag(DragEvent e)
|
||||
{
|
||||
var newControlPoints = slider.Path.ControlPoints.ToArray();
|
||||
|
||||
if (Index == 0)
|
||||
{
|
||||
// Special handling for the head control point - the position of the slider changes which means the snapped position and time have to be taken into account
|
||||
@ -168,29 +166,17 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
slider.StartTime = snappedTime;
|
||||
|
||||
// Since control points are relative to the position of the slider, they all need to be offset backwards by the delta
|
||||
for (int i = 1; i < newControlPoints.Length; i++)
|
||||
newControlPoints[i] -= movementDelta;
|
||||
for (int i = 1; i < slider.Path.ControlPoints.Count; i++)
|
||||
slider.Path.ControlPoints[i].Position.Value -= movementDelta;
|
||||
}
|
||||
else
|
||||
newControlPoints[Index] += e.Delta;
|
||||
|
||||
if (isSegmentSeparatorWithNext)
|
||||
newControlPoints[Index + 1] = newControlPoints[Index];
|
||||
|
||||
if (isSegmentSeparatorWithPrevious)
|
||||
newControlPoints[Index - 1] = newControlPoints[Index];
|
||||
|
||||
ControlPointsChanged?.Invoke(newControlPoints);
|
||||
slider.Path.ControlPoints[Index].Position.Value += e.Delta;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnDragEnd(DragEndEvent e) => true;
|
||||
|
||||
private bool isSegmentSeparator => isSegmentSeparatorWithNext || isSegmentSeparatorWithPrevious;
|
||||
|
||||
private bool isSegmentSeparatorWithNext => Index < slider.Path.ControlPoints.Length - 1 && slider.Path.ControlPoints[Index + 1] == slider.Path.ControlPoints[Index];
|
||||
|
||||
private bool isSegmentSeparatorWithPrevious => Index > 0 && slider.Path.ControlPoints[Index - 1] == slider.Path.ControlPoints[Index];
|
||||
private bool isSegmentSeparator => slider.Path.ControlPoints[Index].Type.Value.HasValue;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
{
|
||||
base.Update();
|
||||
|
||||
while (slider.Path.ControlPoints.Length > Pieces.Count)
|
||||
while (slider.Path.ControlPoints.Count > Pieces.Count)
|
||||
{
|
||||
var piece = new PathControlPointPiece(slider, Pieces.Count)
|
||||
{
|
||||
@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
Pieces.Add(piece);
|
||||
}
|
||||
|
||||
while (slider.Path.ControlPoints.Length < Pieces.Count)
|
||||
while (slider.Path.ControlPoints.Count < Pieces.Count)
|
||||
Pieces.Remove(Pieces[Pieces.Count - 1]);
|
||||
}
|
||||
|
||||
@ -105,29 +105,32 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
|
||||
private bool deleteSelected()
|
||||
{
|
||||
var newControlPoints = new List<Vector2>();
|
||||
int countDeleted = 0;
|
||||
|
||||
foreach (var piece in Pieces)
|
||||
{
|
||||
if (!piece.IsSelected.Value)
|
||||
newControlPoints.Add(slider.Path.ControlPoints[piece.Index]);
|
||||
if (piece.IsSelected.Value)
|
||||
{
|
||||
slider.Path.ControlPoints.RemoveAt(piece.Index);
|
||||
countDeleted++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there are any points to be deleted
|
||||
if (newControlPoints.Count == slider.Path.ControlPoints.Length)
|
||||
if (countDeleted == 0)
|
||||
return false;
|
||||
|
||||
// If there are 0 remaining control points, treat the slider as being deleted
|
||||
if (newControlPoints.Count == 0)
|
||||
if (slider.Path.ControlPoints.Count == 0)
|
||||
{
|
||||
placementHandler?.Delete(slider);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make control points relative
|
||||
Vector2 first = newControlPoints[0];
|
||||
for (int i = 0; i < newControlPoints.Count; i++)
|
||||
newControlPoints[i] = newControlPoints[i] - first;
|
||||
Vector2 first = slider.Path.ControlPoints[0].Position.Value;
|
||||
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
||||
slider.Path.ControlPoints[i].Position.Value = slider.Path.ControlPoints[i].Position.Value - first;
|
||||
|
||||
// The slider's position defines the position of the first control point, and all further control points are relative to that point
|
||||
slider.Position += first;
|
||||
@ -136,7 +139,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
foreach (var piece in Pieces)
|
||||
piece.IsSelected.Value = false;
|
||||
|
||||
ControlPointsChanged?.Invoke(newControlPoints.ToArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
private HitCirclePiece headCirclePiece;
|
||||
private HitCirclePiece tailCirclePiece;
|
||||
|
||||
private readonly List<Segment> segments = new List<Segment>();
|
||||
private Vector2 cursor;
|
||||
private InputManager inputManager;
|
||||
|
||||
private PlacementState state;
|
||||
@ -40,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
: base(new Objects.Slider())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
segments.Add(new Segment(Vector2.Zero));
|
||||
HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = Vector2.Zero } });
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -74,7 +72,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
case PlacementState.Body:
|
||||
// The given screen-space position may have been externally snapped, but the unsnapped position from the input manager
|
||||
// is used instead since snapping control points doesn't make much sense
|
||||
cursor = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position;
|
||||
HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value = ToLocalSpace(inputManager.CurrentState.Mouse.Position) - HitObject.Position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -91,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
switch (e.Button)
|
||||
{
|
||||
case MouseButton.Left:
|
||||
segments.Last().ControlPoints.Add(cursor);
|
||||
HitObject.Path.ControlPoints.Add(new PathControlPoint { Position = { Value = HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 1].Position.Value } });
|
||||
break;
|
||||
}
|
||||
|
||||
@ -110,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
protected override bool OnDoubleClick(DoubleClickEvent e)
|
||||
{
|
||||
segments.Add(new Segment(segments[segments.Count - 1].ControlPoints.Last()));
|
||||
HitObject.Path.ControlPoints[HitObject.Path.ControlPoints.Count - 2].Type.Value = PathType.Bezier;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -134,12 +132,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
private void updateSlider()
|
||||
{
|
||||
Vector2[] newControlPoints = segments.SelectMany(s => s.ControlPoints).Concat(cursor.Yield()).ToArray();
|
||||
|
||||
var unsnappedPath = new SliderPath(newControlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, newControlPoints);
|
||||
var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance;
|
||||
|
||||
HitObject.Path = new SliderPath(unsnappedPath.Type, newControlPoints, snappedDistance);
|
||||
HitObject.Path.ExpectedDistance.Value = null;
|
||||
HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance;
|
||||
|
||||
bodyPiece.UpdateFrom(HitObject);
|
||||
headCirclePiece.UpdateFrom(HitObject.HeadCircle);
|
||||
|
@ -77,12 +77,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
{
|
||||
Debug.Assert(placementControlPointIndex != null);
|
||||
|
||||
Vector2 position = e.MousePosition - HitObject.Position;
|
||||
|
||||
var controlPoints = HitObject.Path.ControlPoints.ToArray();
|
||||
controlPoints[placementControlPointIndex.Value] = position;
|
||||
|
||||
onNewControlPoints(controlPoints);
|
||||
HitObject.Path.ControlPoints[placementControlPointIndex.Value].Position.Value = e.MousePosition - HitObject.Position;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -97,15 +92,12 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
{
|
||||
position -= HitObject.Position;
|
||||
|
||||
var controlPoints = new Vector2[HitObject.Path.ControlPoints.Length + 1];
|
||||
HitObject.Path.ControlPoints.CopyTo(controlPoints);
|
||||
|
||||
int insertionIndex = 0;
|
||||
float minDistance = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < controlPoints.Length - 2; i++)
|
||||
for (int i = 0; i < HitObject.Path.ControlPoints.Count - 2; i++)
|
||||
{
|
||||
float dist = new Line(controlPoints[i], controlPoints[i + 1]).DistanceToPoint(position);
|
||||
float dist = new Line(HitObject.Path.ControlPoints[i].Position.Value, HitObject.Path.ControlPoints[i + 1].Position.Value).DistanceToPoint(position);
|
||||
|
||||
if (dist < minDistance)
|
||||
{
|
||||
@ -115,20 +107,15 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
}
|
||||
|
||||
// Move the control points from the insertion index onwards to make room for the insertion
|
||||
Array.Copy(controlPoints, insertionIndex, controlPoints, insertionIndex + 1, controlPoints.Length - insertionIndex - 1);
|
||||
controlPoints[insertionIndex] = position;
|
||||
|
||||
onNewControlPoints(controlPoints);
|
||||
HitObject.Path.ControlPoints.Insert(insertionIndex, new PathControlPoint { Position = { Value = position } });
|
||||
|
||||
return insertionIndex;
|
||||
}
|
||||
|
||||
private void onNewControlPoints(Vector2[] controlPoints)
|
||||
{
|
||||
var unsnappedPath = new SliderPath(controlPoints.Length > 2 ? PathType.Bezier : PathType.Linear, controlPoints);
|
||||
var snappedDistance = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)unsnappedPath.Distance) ?? (float)unsnappedPath.Distance;
|
||||
|
||||
HitObject.Path = new SliderPath(unsnappedPath.Type, controlPoints, snappedDistance);
|
||||
HitObject.Path.ExpectedDistance.Value = null;
|
||||
HitObject.Path.ExpectedDistance.Value = composer?.GetSnappedDistanceFromDistance(HitObject.StartTime, (float)HitObject.Path.Distance) ?? (float)HitObject.Path.Distance;
|
||||
|
||||
UpdateHitObject();
|
||||
}
|
||||
|
@ -28,11 +28,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
slider.NestedHitObjects.OfType<SliderTick>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
|
||||
slider.NestedHitObjects.OfType<RepeatPoint>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Position.Y));
|
||||
|
||||
var newControlPoints = new Vector2[slider.Path.ControlPoints.Length];
|
||||
for (int i = 0; i < slider.Path.ControlPoints.Length; i++)
|
||||
newControlPoints[i] = new Vector2(slider.Path.ControlPoints[i].X, -slider.Path.ControlPoints[i].Y);
|
||||
|
||||
slider.Path = new SliderPath(slider.Path.Type, newControlPoints, slider.Path.ExpectedDistance);
|
||||
foreach (var point in slider.Path.ControlPoints)
|
||||
point.Position.Value = new Vector2(point.Position.Value.X, -point.Position.Value.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>();
|
||||
private readonly IBindable<int> stackHeightBindable = new Bindable<int>();
|
||||
private readonly IBindable<float> scaleBindable = new Bindable<float>();
|
||||
private readonly IBindable<SliderPath> pathBindable = new Bindable<SliderPath>();
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private OsuRulesetConfigManager config { get; set; }
|
||||
@ -84,9 +84,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
positionBindable.BindTo(HitObject.PositionBindable);
|
||||
stackHeightBindable.BindTo(HitObject.StackHeightBindable);
|
||||
scaleBindable.BindTo(HitObject.ScaleBindable);
|
||||
pathBindable.BindTo(slider.PathBindable);
|
||||
pathVersion.BindTo(slider.Path.Version);
|
||||
|
||||
pathBindable.BindValueChanged(_ => Body.Refresh());
|
||||
pathVersion.BindValueChanged(_ => Body.Refresh());
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public class DrawableSliderHead : DrawableHitCircle
|
||||
{
|
||||
private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>();
|
||||
private readonly IBindable<SliderPath> pathBindable = new Bindable<SliderPath>();
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
private readonly Slider slider;
|
||||
|
||||
@ -27,10 +27,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
private void load()
|
||||
{
|
||||
positionBindable.BindTo(HitObject.PositionBindable);
|
||||
pathBindable.BindTo(slider.PathBindable);
|
||||
pathVersion.BindTo(slider.Path.Version);
|
||||
|
||||
positionBindable.BindValueChanged(_ => updatePosition());
|
||||
pathBindable.BindValueChanged(_ => updatePosition(), true);
|
||||
pathVersion.BindValueChanged(_ => updatePosition(), true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
public bool Tracking { get; set; }
|
||||
|
||||
private readonly IBindable<Vector2> positionBindable = new Bindable<Vector2>();
|
||||
private readonly IBindable<SliderPath> pathBindable = new Bindable<SliderPath>();
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
public DrawableSliderTail(Slider slider, SliderTailCircle hitCircle)
|
||||
: base(hitCircle)
|
||||
@ -36,10 +36,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
AlwaysPresent = true;
|
||||
|
||||
positionBindable.BindTo(hitCircle.PositionBindable);
|
||||
pathBindable.BindTo(slider.PathBindable);
|
||||
pathVersion.BindTo(slider.Path.Version);
|
||||
|
||||
positionBindable.BindValueChanged(_ => updatePosition());
|
||||
pathBindable.BindValueChanged(_ => updatePosition(), true);
|
||||
pathVersion.BindValueChanged(_ => updatePosition(), true);
|
||||
|
||||
// TODO: This has no drawable content. Support for skins should be added.
|
||||
}
|
||||
|
@ -28,19 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
public Vector2 StackedPositionAt(double t) => StackedPosition + this.CurvePositionAt(t);
|
||||
|
||||
public readonly Bindable<SliderPath> PathBindable = new Bindable<SliderPath>();
|
||||
|
||||
public SliderPath Path
|
||||
{
|
||||
get => PathBindable.Value;
|
||||
set
|
||||
{
|
||||
PathBindable.Value = value;
|
||||
endPositionCache.Invalidate();
|
||||
|
||||
updateNestedPositions();
|
||||
}
|
||||
}
|
||||
public SliderPath Path { get; set; } = new SliderPath(new[] { new PathControlPoint { Type = { Value = PathType.Bezier } } });
|
||||
|
||||
public double Distance => Path.Distance;
|
||||
|
||||
|
@ -15,12 +15,12 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
/// </summary>
|
||||
public class SliderTailCircle : SliderCircle
|
||||
{
|
||||
private readonly IBindable<SliderPath> pathBindable = new Bindable<SliderPath>();
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
public SliderTailCircle(Slider slider)
|
||||
{
|
||||
pathBindable.BindTo(slider.PathBindable);
|
||||
pathBindable.BindValueChanged(_ => Position = slider.EndPosition);
|
||||
pathVersion.BindTo(slider.Path.Version);
|
||||
pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
|
||||
}
|
||||
|
||||
public override Judgement CreateJudgement() => new OsuSliderTailJudgement();
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
|
||||
};
|
||||
}
|
||||
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount,
|
||||
List<IList<HitSampleInfo>> nodeSamples)
|
||||
{
|
||||
newCombo |= forceNewCombo;
|
||||
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
|
||||
X = position.X,
|
||||
NewCombo = FirstObject || newCombo,
|
||||
ComboOffset = comboOffset,
|
||||
Path = new SliderPath(pathType, controlPoints, length),
|
||||
Path = new SliderPath(controlPoints, length),
|
||||
NodeSamples = nodeSamples,
|
||||
RepeatCount = repeatCount
|
||||
};
|
||||
|
@ -115,12 +115,6 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
points[pointIndex++] = new Vector2((int)Parsing.ParseDouble(temp[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseDouble(temp[1], Parsing.MAX_COORDINATE_VALUE)) - pos;
|
||||
}
|
||||
|
||||
// osu-stable special-cased colinear perfect curves to a CurveType.Linear
|
||||
static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y));
|
||||
|
||||
if (points.Length == 3 && pathType == PathType.PerfectCurve && isLinear(points))
|
||||
pathType = PathType.Linear;
|
||||
|
||||
int repeatCount = Parsing.ParseInt(split[6]);
|
||||
|
||||
if (repeatCount > 9000)
|
||||
@ -187,7 +181,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
for (int i = 0; i < nodes; i++)
|
||||
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
|
||||
|
||||
result = CreateSlider(pos, combo, comboOffset, points, length, pathType, repeatCount, nodeSamples);
|
||||
result = CreateSlider(pos, combo, comboOffset, convertControlPoints(points, pathType), length, repeatCount, nodeSamples);
|
||||
|
||||
// The samples are played when the slider ends, which is the last node
|
||||
result.Samples = nodeSamples[nodeSamples.Count - 1];
|
||||
@ -259,6 +253,45 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
bankInfo.Filename = split.Length > 4 ? split[4] : null;
|
||||
}
|
||||
|
||||
private PathControlPoint[] convertControlPoints(Vector2[] vertices, PathType type)
|
||||
{
|
||||
if (type == PathType.PerfectCurve)
|
||||
{
|
||||
if (vertices.Length == 3)
|
||||
{
|
||||
// osu-stable special-cased colinear perfect curves to a linear path
|
||||
if (isLinear(vertices))
|
||||
type = PathType.Linear;
|
||||
}
|
||||
else
|
||||
type = PathType.Bezier;
|
||||
}
|
||||
|
||||
var points = new List<PathControlPoint>(vertices.Length)
|
||||
{
|
||||
new PathControlPoint
|
||||
{
|
||||
Position = { Value = vertices[0] },
|
||||
Type = { Value = type }
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 1; i < vertices.Length; i++)
|
||||
{
|
||||
if (vertices[i] == vertices[i - 1])
|
||||
{
|
||||
points[points.Count - 1].Type.Value = type;
|
||||
continue;
|
||||
}
|
||||
|
||||
points.Add(new PathControlPoint { Position = { Value = vertices[i] } });
|
||||
}
|
||||
|
||||
return points.ToArray();
|
||||
|
||||
static bool isLinear(Vector2[] p) => Precision.AlmostEquals(0, (p[1].Y - p[0].Y) * (p[2].X - p[0].X) - (p[1].X - p[0].X) * (p[2].Y - p[0].Y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a legacy Hit-type hit object.
|
||||
/// </summary>
|
||||
@ -276,11 +309,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
||||
/// <param name="comboOffset">When starting a new combo, the offset of the new combo relative to the current one.</param>
|
||||
/// <param name="controlPoints">The slider control points.</param>
|
||||
/// <param name="length">The slider length.</param>
|
||||
/// <param name="pathType">The slider curve type.</param>
|
||||
/// <param name="repeatCount">The slider repeat count.</param>
|
||||
/// <param name="nodeSamples">The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.</param>
|
||||
/// <returns>The hit object.</returns>
|
||||
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
|
||||
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount,
|
||||
List<IList<HitSampleInfo>> nodeSamples);
|
||||
|
||||
/// <summary>
|
||||
|
@ -26,13 +26,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
|
||||
};
|
||||
}
|
||||
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount,
|
||||
List<IList<HitSampleInfo>> nodeSamples)
|
||||
{
|
||||
return new ConvertSlider
|
||||
{
|
||||
X = position.X,
|
||||
Path = new SliderPath(pathType, controlPoints, length),
|
||||
Path = new SliderPath(controlPoints, length),
|
||||
NodeSamples = nodeSamples,
|
||||
RepeatCount = repeatCount
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
|
||||
};
|
||||
}
|
||||
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount,
|
||||
List<IList<HitSampleInfo>> nodeSamples)
|
||||
{
|
||||
newCombo |= forceNewCombo;
|
||||
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
|
||||
Position = position,
|
||||
NewCombo = FirstObject || newCombo,
|
||||
ComboOffset = comboOffset,
|
||||
Path = new SliderPath(pathType, controlPoints, length),
|
||||
Path = new SliderPath(controlPoints, length),
|
||||
NodeSamples = nodeSamples,
|
||||
RepeatCount = repeatCount
|
||||
};
|
||||
|
@ -23,12 +23,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
|
||||
return new ConvertHit();
|
||||
}
|
||||
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
|
||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, PathControlPoint[] controlPoints, double? length, int repeatCount,
|
||||
List<IList<HitSampleInfo>> nodeSamples)
|
||||
{
|
||||
return new ConvertSlider
|
||||
{
|
||||
Path = new SliderPath(pathType, controlPoints, length),
|
||||
Path = new SliderPath(controlPoints, length),
|
||||
NodeSamples = nodeSamples,
|
||||
RepeatCount = repeatCount
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user