mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Refactor distance snap grid to not require hitobjects
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Edit.Compose.Components;
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
|
|
||||||
@ -8,8 +9,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
public class OsuDistanceSnapGrid : CircularDistanceSnapGrid
|
public class OsuDistanceSnapGrid : CircularDistanceSnapGrid
|
||||||
{
|
{
|
||||||
public OsuDistanceSnapGrid(OsuHitObject hitObject, OsuHitObject nextHitObject)
|
public OsuDistanceSnapGrid(OsuHitObject hitObject, [CanBeNull] OsuHitObject nextHitObject = null)
|
||||||
: base(hitObject, nextHitObject, hitObject.StackedEndPosition)
|
: base(hitObject.StackedPosition, hitObject.StartTime, nextHitObject?.StartTime)
|
||||||
{
|
{
|
||||||
Masking = true;
|
Masking = true;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -44,7 +43,7 @@ namespace osu.Game.Tests.Visual.Editor
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.SlateGray
|
Colour = Color4.SlateGray
|
||||||
},
|
},
|
||||||
new TestDistanceSnapGrid(new HitObject(), grid_position)
|
new TestDistanceSnapGrid()
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ namespace osu.Game.Tests.Visual.Editor
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.SlateGray
|
Colour = Color4.SlateGray
|
||||||
},
|
},
|
||||||
new TestDistanceSnapGrid(new HitObject(), grid_position, new HitObject { StartTime = 100 })
|
new TestDistanceSnapGrid(100)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -82,68 +81,68 @@ namespace osu.Game.Tests.Visual.Editor
|
|||||||
{
|
{
|
||||||
public new float DistanceSpacing => base.DistanceSpacing;
|
public new float DistanceSpacing => base.DistanceSpacing;
|
||||||
|
|
||||||
public TestDistanceSnapGrid(HitObject hitObject, Vector2 centrePosition, HitObject nextHitObject = null)
|
public TestDistanceSnapGrid(double? endTime = null)
|
||||||
: base(hitObject, nextHitObject, centrePosition)
|
: base(grid_position, 0, endTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CreateContent(Vector2 centrePosition)
|
protected override void CreateContent(Vector2 startPosition)
|
||||||
{
|
{
|
||||||
AddInternal(new Circle
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(5),
|
Size = new Vector2(5),
|
||||||
Position = centrePosition
|
Position = startPosition
|
||||||
});
|
});
|
||||||
|
|
||||||
int beatIndex = 0;
|
int beatIndex = 0;
|
||||||
|
|
||||||
for (float s = centrePosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
for (float s = startPosition.X + DistanceSpacing; s <= DrawWidth && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
||||||
{
|
{
|
||||||
AddInternal(new Circle
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(5, 10),
|
Size = new Vector2(5, 10),
|
||||||
Position = new Vector2(s, centrePosition.Y),
|
Position = new Vector2(s, startPosition.Y),
|
||||||
Colour = GetColourForBeatIndex(beatIndex)
|
Colour = GetColourForBeatIndex(beatIndex)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
beatIndex = 0;
|
beatIndex = 0;
|
||||||
|
|
||||||
for (float s = centrePosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
for (float s = startPosition.X - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
||||||
{
|
{
|
||||||
AddInternal(new Circle
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(5, 10),
|
Size = new Vector2(5, 10),
|
||||||
Position = new Vector2(s, centrePosition.Y),
|
Position = new Vector2(s, startPosition.Y),
|
||||||
Colour = GetColourForBeatIndex(beatIndex)
|
Colour = GetColourForBeatIndex(beatIndex)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
beatIndex = 0;
|
beatIndex = 0;
|
||||||
|
|
||||||
for (float s = centrePosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
for (float s = startPosition.Y + DistanceSpacing; s <= DrawHeight && beatIndex < MaxIntervals; s += DistanceSpacing, beatIndex++)
|
||||||
{
|
{
|
||||||
AddInternal(new Circle
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(10, 5),
|
Size = new Vector2(10, 5),
|
||||||
Position = new Vector2(centrePosition.X, s),
|
Position = new Vector2(startPosition.X, s),
|
||||||
Colour = GetColourForBeatIndex(beatIndex)
|
Colour = GetColourForBeatIndex(beatIndex)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
beatIndex = 0;
|
beatIndex = 0;
|
||||||
|
|
||||||
for (float s = centrePosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
for (float s = startPosition.Y - DistanceSpacing; s >= 0 && beatIndex < MaxIntervals; s -= DistanceSpacing, beatIndex++)
|
||||||
{
|
{
|
||||||
AddInternal(new Circle
|
AddInternal(new Circle
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(10, 5),
|
Size = new Vector2(10, 5),
|
||||||
Position = new Vector2(centrePosition.X, s),
|
Position = new Vector2(startPosition.X, s),
|
||||||
Colour = GetColourForBeatIndex(beatIndex)
|
Colour = GetColourForBeatIndex(beatIndex)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -5,19 +5,18 @@ using System;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Compose.Components
|
namespace osu.Game.Screens.Edit.Compose.Components
|
||||||
{
|
{
|
||||||
public abstract class CircularDistanceSnapGrid : DistanceSnapGrid
|
public abstract class CircularDistanceSnapGrid : DistanceSnapGrid
|
||||||
{
|
{
|
||||||
protected CircularDistanceSnapGrid(HitObject hitObject, HitObject nextHitObject, Vector2 centrePosition)
|
protected CircularDistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null)
|
||||||
: base(hitObject, nextHitObject, centrePosition)
|
: base(startPosition, startTime, endTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CreateContent(Vector2 centrePosition)
|
protected override void CreateContent(Vector2 startPosition)
|
||||||
{
|
{
|
||||||
const float crosshair_thickness = 1;
|
const float crosshair_thickness = 1;
|
||||||
const float crosshair_max_size = 10;
|
const float crosshair_max_size = 10;
|
||||||
@ -27,7 +26,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Position = centrePosition,
|
Position = startPosition,
|
||||||
Width = crosshair_thickness,
|
Width = crosshair_thickness,
|
||||||
EdgeSmoothness = new Vector2(1),
|
EdgeSmoothness = new Vector2(1),
|
||||||
Height = Math.Min(crosshair_max_size, DistanceSpacing * 2),
|
Height = Math.Min(crosshair_max_size, DistanceSpacing * 2),
|
||||||
@ -35,15 +34,15 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Position = centrePosition,
|
Position = startPosition,
|
||||||
EdgeSmoothness = new Vector2(1),
|
EdgeSmoothness = new Vector2(1),
|
||||||
Width = Math.Min(crosshair_max_size, DistanceSpacing * 2),
|
Width = Math.Min(crosshair_max_size, DistanceSpacing * 2),
|
||||||
Height = crosshair_thickness,
|
Height = crosshair_thickness,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
float dx = Math.Max(centrePosition.X, DrawWidth - centrePosition.X);
|
float dx = Math.Max(startPosition.X, DrawWidth - startPosition.X);
|
||||||
float dy = Math.Max(centrePosition.Y, DrawHeight - centrePosition.Y);
|
float dy = Math.Max(startPosition.Y, DrawHeight - startPosition.Y);
|
||||||
float maxDistance = new Vector2(dx, dy).Length;
|
float maxDistance = new Vector2(dx, dy).Length;
|
||||||
int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceSpacing));
|
int requiredCircles = Math.Min(MaxIntervals, (int)(maxDistance / DistanceSpacing));
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
AddInternal(new CircularProgress
|
AddInternal(new CircularProgress
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Position = centrePosition,
|
Position = startPosition,
|
||||||
Current = { Value = 1 },
|
Current = { Value = 1 },
|
||||||
Size = new Vector2(radius),
|
Size = new Vector2(radius),
|
||||||
InnerRadius = 4 * 1f / radius,
|
InnerRadius = 4 * 1f / radius,
|
||||||
@ -66,9 +65,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
public override (Vector2 position, double time) GetSnappedPosition(Vector2 position)
|
public override (Vector2 position, double time) GetSnappedPosition(Vector2 position)
|
||||||
{
|
{
|
||||||
if (MaxIntervals == 0)
|
if (MaxIntervals == 0)
|
||||||
return (CentrePosition, StartTime);
|
return (StartPosition, StartTime);
|
||||||
|
|
||||||
Vector2 direction = position - CentrePosition;
|
Vector2 direction = position - StartPosition;
|
||||||
if (direction == Vector2.Zero)
|
if (direction == Vector2.Zero)
|
||||||
direction = new Vector2(0.001f, 0.001f);
|
direction = new Vector2(0.001f, 0.001f);
|
||||||
|
|
||||||
@ -78,9 +77,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
int radialCount = Math.Clamp((int)MathF.Round(distance / radius), 1, MaxIntervals);
|
int radialCount = Math.Clamp((int)MathF.Round(distance / radius), 1, MaxIntervals);
|
||||||
|
|
||||||
Vector2 normalisedDirection = direction * new Vector2(1f / distance);
|
Vector2 normalisedDirection = direction * new Vector2(1f / distance);
|
||||||
Vector2 snappedPosition = CentrePosition + normalisedDirection * radialCount * radius;
|
Vector2 snappedPosition = StartPosition + normalisedDirection * radialCount * radius;
|
||||||
|
|
||||||
return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - CentrePosition).Length));
|
return (snappedPosition, StartTime + SnapProvider.GetSnappedDurationFromDistance(StartTime, (snappedPosition - StartPosition).Length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Caching;
|
using osu.Framework.Caching;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -9,7 +8,6 @@ using osu.Framework.Graphics.Colour;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Compose.Components
|
namespace osu.Game.Screens.Edit.Compose.Components
|
||||||
@ -24,21 +22,21 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected float DistanceSpacing { get; private set; }
|
protected float DistanceSpacing { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The snapping time at <see cref="CentrePosition"/>.
|
|
||||||
/// </summary>
|
|
||||||
protected double StartTime { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The maximum number of distance snapping intervals allowed.
|
/// The maximum number of distance snapping intervals allowed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected int MaxIntervals { get; private set; }
|
protected int MaxIntervals { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The position which the grid is centred on.
|
/// The position which the grid should start.
|
||||||
/// The first beat snapping tick is located at <see cref="CentrePosition"/> + <see cref="DistanceSpacing"/> in the desired direction.
|
/// The first beat snapping tick is located at <see cref="StartPosition"/> + <see cref="DistanceSpacing"/> away from this point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly Vector2 CentrePosition;
|
protected readonly Vector2 StartPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The snapping time at <see cref="StartPosition"/>.
|
||||||
|
/// </summary>
|
||||||
|
protected readonly double StartTime;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
protected OsuColour Colours { get; private set; }
|
protected OsuColour Colours { get; private set; }
|
||||||
@ -53,25 +51,23 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
private BindableBeatDivisor beatDivisor { get; set; }
|
private BindableBeatDivisor beatDivisor { get; set; }
|
||||||
|
|
||||||
private readonly Cached gridCache = new Cached();
|
private readonly Cached gridCache = new Cached();
|
||||||
private readonly HitObject hitObject;
|
private readonly double? endTime;
|
||||||
private readonly HitObject nextHitObject;
|
|
||||||
|
|
||||||
protected DistanceSnapGrid(HitObject hitObject, [CanBeNull] HitObject nextHitObject, Vector2 centrePosition)
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="DistanceSnapGrid"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startPosition">The position at which the grid should start. The first tick is located one distance spacing length away from this point.</param>
|
||||||
|
/// <param name="startTime">The snapping time at <see cref="StartPosition"/>.</param>
|
||||||
|
/// <param name="endTime">The time at which the snapping grid should end. If null, the grid will continue until the bounds of the screen are exceeded.</param>
|
||||||
|
protected DistanceSnapGrid(Vector2 startPosition, double startTime, double? endTime = null)
|
||||||
{
|
{
|
||||||
this.hitObject = hitObject;
|
this.endTime = endTime;
|
||||||
this.nextHitObject = nextHitObject;
|
StartPosition = startPosition;
|
||||||
|
StartTime = startTime;
|
||||||
CentrePosition = centrePosition;
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
StartTime = hitObject.GetEndTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
@ -83,12 +79,12 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
{
|
{
|
||||||
DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime);
|
DistanceSpacing = SnapProvider.GetBeatSnapDistanceAt(StartTime);
|
||||||
|
|
||||||
if (nextHitObject == null)
|
if (endTime == null)
|
||||||
MaxIntervals = int.MaxValue;
|
MaxIntervals = int.MaxValue;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors
|
// +1 is added since a snapped hitobject may have its start time slightly less than the snapped time due to floating point errors
|
||||||
double maxDuration = nextHitObject.StartTime - StartTime + 1;
|
double maxDuration = endTime.Value - StartTime + 1;
|
||||||
MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing));
|
MaxIntervals = (int)(maxDuration / SnapProvider.DistanceToDuration(StartTime, DistanceSpacing));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +106,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
if (!gridCache.IsValid)
|
if (!gridCache.IsValid)
|
||||||
{
|
{
|
||||||
ClearInternal();
|
ClearInternal();
|
||||||
CreateContent(CentrePosition);
|
CreateContent(StartPosition);
|
||||||
gridCache.Validate();
|
gridCache.Validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,7 +114,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the content which visualises the grid ticks.
|
/// Creates the content which visualises the grid ticks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected abstract void CreateContent(Vector2 centrePosition);
|
protected abstract void CreateContent(Vector2 startPosition);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Snaps a position to this grid.
|
/// Snaps a position to this grid.
|
||||||
|
Reference in New Issue
Block a user