mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Create SnapResult class to hold various snapping results
This commit is contained in:
parent
3354d48a38
commit
c46bfc2532
@ -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 System;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
@ -45,12 +44,7 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
|
|
||||||
public int TotalColumns => Playfield.TotalColumns;
|
public int TotalColumns => Playfield.TotalColumns;
|
||||||
|
|
||||||
public override (Vector2 position, double time) SnapPositionToValidTime(Vector2 position)
|
public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
|
||||||
{
|
{
|
||||||
var hoc = Playfield.GetColumn(0).HitObjectContainer;
|
var hoc = Playfield.GetColumn(0).HitObjectContainer;
|
||||||
|
|
||||||
@ -69,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
drawableRuleset.ScrollingInfo.TimeRange.Value,
|
drawableRuleset.ScrollingInfo.TimeRange.Value,
|
||||||
hoc.DrawHeight);
|
hoc.DrawHeight);
|
||||||
|
|
||||||
return (targetPosition, targetTime);
|
return new SnapResult(targetPosition, targetTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||||
|
@ -174,9 +174,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private class SnapProvider : IPositionSnapProvider
|
private class SnapProvider : IPositionSnapProvider
|
||||||
{
|
{
|
||||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) => (position, 0);
|
public SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => new SnapResult(screenSpacePosition, 0);
|
||||||
|
|
||||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => (screenSpacePosition, 0);
|
|
||||||
|
|
||||||
public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length;
|
public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length;
|
||||||
|
|
||||||
|
@ -162,11 +162,11 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
|||||||
if (ControlPoint == slider.Path.ControlPoints[0])
|
if (ControlPoint == slider.Path.ControlPoints[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
|
// 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
|
||||||
(Vector2 snappedPosition, double snappedTime) = snapProvider?.SnapScreenSpacePositionToValidTime(e.MousePosition) ?? (e.MousePosition, slider.StartTime);
|
var result = snapProvider?.SnapScreenSpacePositionToValidTime(e.MousePosition);
|
||||||
Vector2 movementDelta = snappedPosition - slider.Position;
|
Vector2 movementDelta = (result?.ScreenSpacePosition ?? e.MousePosition) - slider.Position;
|
||||||
|
|
||||||
slider.Position += movementDelta;
|
slider.Position += movementDelta;
|
||||||
slider.StartTime = snappedTime;
|
slider.StartTime = result?.Time ?? slider.StartTime;
|
||||||
|
|
||||||
// Since control points are relative to the position of the slider, they all need to be offset backwards by the delta
|
// 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 < slider.Path.ControlPoints.Count; i++)
|
for (int i = 1; i < slider.Path.ControlPoints.Count; i++)
|
||||||
|
@ -153,9 +153,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
|
|
||||||
private class SnapProvider : IPositionSnapProvider
|
private class SnapProvider : IPositionSnapProvider
|
||||||
{
|
{
|
||||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) => (position, 0);
|
public SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => new SnapResult(screenSpacePosition, 0);
|
||||||
|
|
||||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => (screenSpacePosition, 0);
|
|
||||||
|
|
||||||
public float GetBeatSnapDistanceAt(double referenceTime) => 10;
|
public float GetBeatSnapDistanceAt(double referenceTime) => 10;
|
||||||
|
|
||||||
|
@ -245,7 +245,8 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
{
|
{
|
||||||
EditorBeatmap.PlacementObject.Value = hitObject;
|
EditorBeatmap.PlacementObject.Value = hitObject;
|
||||||
|
|
||||||
hitObject.StartTime = SnapScreenSpacePositionToValidTime(inputManager.CurrentState.Mouse.Position).time;
|
if (SnapScreenSpacePositionToValidTime(inputManager.CurrentState.Mouse.Position).Time is double time)
|
||||||
|
hitObject.StartTime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndPlacement(HitObject hitObject, bool commit)
|
public void EndPlacement(HitObject hitObject, bool commit)
|
||||||
@ -264,11 +265,13 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
|
|
||||||
public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject);
|
public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject);
|
||||||
|
|
||||||
public override (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) =>
|
public override SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
||||||
distanceSnapGrid?.GetSnappedPosition(position) ?? (position, 0);
|
{
|
||||||
|
if (distanceSnapGrid == null) return new SnapResult(screenSpacePosition, null);
|
||||||
|
|
||||||
public override (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
(Vector2 pos, double time) = distanceSnapGrid.GetSnappedPosition(distanceSnapGrid.ToLocalSpace(screenSpacePosition));
|
||||||
=> SnapPositionToValidTime(drawableRulesetWrapper.Playfield.ToLocalSpace(screenSpacePosition));
|
return new SnapResult(distanceSnapGrid.ToScreenSpace(pos), time);
|
||||||
|
}
|
||||||
|
|
||||||
public override float GetBeatSnapDistanceAt(double referenceTime)
|
public override float GetBeatSnapDistanceAt(double referenceTime)
|
||||||
{
|
{
|
||||||
@ -326,9 +329,7 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null;
|
protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null;
|
||||||
|
|
||||||
public abstract (Vector2 position, double time) SnapPositionToValidTime(Vector2 position);
|
public abstract SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
||||||
|
|
||||||
public abstract (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
|
||||||
|
|
||||||
public abstract float GetBeatSnapDistanceAt(double referenceTime);
|
public abstract float GetBeatSnapDistanceAt(double referenceTime);
|
||||||
|
|
||||||
|
@ -8,13 +8,11 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
public interface IPositionSnapProvider
|
public interface IPositionSnapProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Given a position (local to the provider), find a valid time snap
|
/// Given a position, find a valid time snap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="position">The local position to be snapped.</param>
|
/// <param name="screenSpacePosition">The screen-space position to be snapped.</param>
|
||||||
/// <returns>The time and position post-snapping.</returns>
|
/// <returns>The time and position post-snapping.</returns>
|
||||||
(Vector2 position, double time) SnapPositionToValidTime(Vector2 position);
|
SnapResult SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
||||||
|
|
||||||
(Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the distance between two points within a timing point that are one beat length apart.
|
/// Retrieves the distance between two points within a timing point that are one beat length apart.
|
||||||
@ -55,4 +53,23 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
/// <returns>A value that represents <paramref name="distance"/> snapped to the closest beat of the timing point.</returns>
|
/// <returns>A value that represents <paramref name="distance"/> snapped to the closest beat of the timing point.</returns>
|
||||||
float GetSnappedDistanceFromDistance(double referenceTime, float distance);
|
float GetSnappedDistanceFromDistance(double referenceTime, float distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SnapResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The screen space position, potentially altered for snapping.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 ScreenSpacePosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The resultant time for snapping, if a value could be attained.
|
||||||
|
/// </summary>
|
||||||
|
public double? Time;
|
||||||
|
|
||||||
|
public SnapResult(Vector2 screenSpacePosition, double? time)
|
||||||
|
{
|
||||||
|
ScreenSpacePosition = screenSpacePosition;
|
||||||
|
Time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,16 +405,19 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
Vector2 movePosition = movementBlueprintOriginalPosition.Value + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition;
|
Vector2 movePosition = movementBlueprintOriginalPosition.Value + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition;
|
||||||
|
|
||||||
// Retrieve a snapped position.
|
// Retrieve a snapped position.
|
||||||
(Vector2 snappedPosition, double snappedTime) = snapProvider.SnapScreenSpacePositionToValidTime(movePosition);
|
var result = snapProvider.SnapScreenSpacePositionToValidTime(movePosition);
|
||||||
|
|
||||||
// Move the hitobjects.
|
// Move the hitobjects.
|
||||||
if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, ToScreenSpace(snappedPosition))))
|
if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, result.ScreenSpacePosition)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (result.Time.HasValue)
|
||||||
|
{
|
||||||
// Apply the start time at the newly snapped-to position
|
// Apply the start time at the newly snapped-to position
|
||||||
double offset = snappedTime - draggedObject.StartTime;
|
double offset = result.Time.Value - draggedObject.StartTime;
|
||||||
foreach (HitObject obj in selectionHandler.SelectedHitObjects)
|
foreach (HitObject obj in selectionHandler.SelectedHitObjects)
|
||||||
obj.StartTime += offset;
|
obj.StartTime += offset;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
private void updatePlacementPosition(Vector2 screenSpacePosition)
|
private void updatePlacementPosition(Vector2 screenSpacePosition)
|
||||||
{
|
{
|
||||||
Vector2 snappedPlayfieldPosition = composer.SnapScreenSpacePositionToValidTime(screenSpacePosition).position;
|
Vector2 snappedPlayfieldPosition = composer.SnapScreenSpacePositionToValidTime(screenSpacePosition).ScreenSpacePosition;
|
||||||
|
|
||||||
currentPlacement.UpdatePosition(ToScreenSpace(snappedPlayfieldPosition));
|
currentPlacement.UpdatePosition(ToScreenSpace(snappedPlayfieldPosition));
|
||||||
}
|
}
|
||||||
|
@ -181,11 +181,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private IBeatSnapProvider beatSnapProvider { get; set; }
|
private IBeatSnapProvider beatSnapProvider { get; set; }
|
||||||
|
|
||||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) =>
|
public SnapResult SnapScreenSpacePositionToValidTime(Vector2 position) =>
|
||||||
(position, beatSnapProvider.SnapTime(getTimeFromPosition(position)));
|
new SnapResult(position, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(position))));
|
||||||
|
|
||||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 position) =>
|
|
||||||
(position, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(position))));
|
|
||||||
|
|
||||||
private double getTimeFromPosition(Vector2 localPosition) =>
|
private double getTimeFromPosition(Vector2 localPosition) =>
|
||||||
(localPosition.X / Content.DrawWidth) * track.Length;
|
(localPosition.X / Content.DrawWidth) * track.Length;
|
||||||
|
@ -275,8 +275,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
OnDragHandled?.Invoke(e);
|
OnDragHandled?.Invoke(e);
|
||||||
|
|
||||||
var time = timeline.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition).time;
|
if (timeline.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition).Time is double time)
|
||||||
|
{
|
||||||
switch (hitObject)
|
switch (hitObject)
|
||||||
{
|
{
|
||||||
case IHasRepeats repeatHitObject:
|
case IHasRepeats repeatHitObject:
|
||||||
@ -302,6 +302,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
|||||||
|
|
||||||
beatmap.UpdateHitObject(hitObject);
|
beatmap.UpdateHitObject(hitObject);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnDragEnd(DragEndEvent e)
|
protected override void OnDragEnd(DragEndEvent e)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user