mirror of
https://github.com/osukey/osukey.git
synced 2025-05-24 06:57:36 +09:00
Change snapping to be screen space coordinate based
This commit is contained in:
parent
b6c9a50f7a
commit
3354d48a38
@ -77,6 +77,6 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
|
||||
public override Quad SelectionQuad => ScreenSpaceDrawQuad;
|
||||
|
||||
public override Vector2 SelectionPoint => DrawableObject.Head.ScreenSpaceDrawQuad.Centre;
|
||||
public override Vector2 ScreenSpaceSelectionPoint => DrawableObject.Head.ScreenSpaceDrawQuad.Centre;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
@ -44,26 +45,31 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
|
||||
public int TotalColumns => Playfield.TotalColumns;
|
||||
|
||||
public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time)
|
||||
public override (Vector2 position, double time) SnapPositionToValidTime(Vector2 position)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
||||
{
|
||||
var hoc = Playfield.GetColumn(0).HitObjectContainer;
|
||||
|
||||
float targetPosition = hoc.ToLocalSpace(ToScreenSpace(position)).Y;
|
||||
Vector2 targetPosition = hoc.ToLocalSpace(screenSpacePosition);
|
||||
|
||||
if (drawableRuleset.ScrollingInfo.Direction.Value == ScrollingDirection.Down)
|
||||
{
|
||||
// We're dealing with screen coordinates in which the position decreases towards the centre of the screen resulting in an increase in start time.
|
||||
// The scrolling algorithm instead assumes a top anchor meaning an increase in time corresponds to an increase in position,
|
||||
// so when scrolling downwards the coordinates need to be flipped.
|
||||
targetPosition = hoc.DrawHeight - targetPosition;
|
||||
targetPosition.Y = hoc.DrawHeight - targetPosition.Y;
|
||||
}
|
||||
|
||||
double targetTime = drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition,
|
||||
double targetTime = drawableRuleset.ScrollingInfo.Algorithm.TimeAt(targetPosition.Y,
|
||||
EditorClock.CurrentTime,
|
||||
drawableRuleset.ScrollingInfo.TimeRange.Value,
|
||||
hoc.DrawHeight);
|
||||
|
||||
return base.GetSnappedPosition(position, targetTime);
|
||||
return (targetPosition, targetTime);
|
||||
}
|
||||
|
||||
protected override DrawableRuleset<ManiaHitObject> CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod> mods = null)
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
[Cached]
|
||||
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
|
||||
|
||||
[Cached(typeof(IDistanceSnapProvider))]
|
||||
[Cached(typeof(IPositionSnapProvider))]
|
||||
private readonly SnapProvider snapProvider = new SnapProvider();
|
||||
|
||||
private TestOsuDistanceSnapGrid grid;
|
||||
@ -172,9 +172,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
}
|
||||
}
|
||||
|
||||
private class SnapProvider : IDistanceSnapProvider
|
||||
private class SnapProvider : IPositionSnapProvider
|
||||
{
|
||||
public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => (position, time);
|
||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) => (position, 0);
|
||||
|
||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => (screenSpacePosition, 0);
|
||||
|
||||
public float GetBeatSnapDistanceAt(double referenceTime) => (float)beat_length;
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
private IEditorChangeHandler changeHandler { get; set; }
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IDistanceSnapProvider snapProvider { get; set; }
|
||||
private IPositionSnapProvider snapProvider { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; }
|
||||
@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
|
||||
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
|
||||
(Vector2 snappedPosition, double snappedTime) = snapProvider?.GetSnappedPosition(e.MousePosition, slider.StartTime) ?? (e.MousePosition, slider.StartTime);
|
||||
(Vector2 snappedPosition, double snappedTime) = snapProvider?.SnapScreenSpacePositionToValidTime(e.MousePosition) ?? (e.MousePosition, slider.StartTime);
|
||||
Vector2 movementDelta = snappedPosition - slider.Position;
|
||||
|
||||
slider.Position += movementDelta;
|
||||
|
@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
new OsuMenuItem("Add control point", MenuItemType.Standard, () => addControlPoint(rightClickPosition)),
|
||||
};
|
||||
|
||||
public override Vector2 SelectionPoint => ((DrawableSlider)DrawableObject).HeadCircle.ScreenSpaceDrawQuad.Centre;
|
||||
public override Vector2 ScreenSpaceSelectionPoint => ((DrawableSlider)DrawableObject).HeadCircle.ScreenSpaceDrawQuad.Centre;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => BodyPiece.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
[Cached(typeof(EditorBeatmap))]
|
||||
private readonly EditorBeatmap editorBeatmap;
|
||||
|
||||
[Cached(typeof(IDistanceSnapProvider))]
|
||||
[Cached(typeof(IPositionSnapProvider))]
|
||||
private readonly SnapProvider snapProvider = new SnapProvider();
|
||||
|
||||
public TestSceneDistanceSnapGrid()
|
||||
@ -151,9 +151,11 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
=> (Vector2.Zero, 0);
|
||||
}
|
||||
|
||||
private class SnapProvider : IDistanceSnapProvider
|
||||
private class SnapProvider : IPositionSnapProvider
|
||||
{
|
||||
public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => (position, time);
|
||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) => (position, 0);
|
||||
|
||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition) => (screenSpacePosition, 0);
|
||||
|
||||
public float GetBeatSnapDistanceAt(double referenceTime) => 10;
|
||||
|
||||
|
@ -245,8 +245,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
EditorBeatmap.PlacementObject.Value = hitObject;
|
||||
|
||||
if (distanceSnapGrid != null)
|
||||
hitObject.StartTime = GetSnappedPosition(distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position), hitObject.StartTime).time;
|
||||
hitObject.StartTime = SnapScreenSpacePositionToValidTime(inputManager.CurrentState.Mouse.Position).time;
|
||||
}
|
||||
|
||||
public void EndPlacement(HitObject hitObject, bool commit)
|
||||
@ -265,7 +264,11 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
public void Delete(HitObject hitObject) => EditorBeatmap.Remove(hitObject);
|
||||
|
||||
public override (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) => distanceSnapGrid?.GetSnappedPosition(position) ?? (position, time);
|
||||
public override (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) =>
|
||||
distanceSnapGrid?.GetSnappedPosition(position) ?? (position, 0);
|
||||
|
||||
public override (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition)
|
||||
=> SnapPositionToValidTime(drawableRulesetWrapper.Playfield.ToLocalSpace(screenSpacePosition));
|
||||
|
||||
public override float GetBeatSnapDistanceAt(double referenceTime)
|
||||
{
|
||||
@ -297,8 +300,8 @@ namespace osu.Game.Rulesets.Edit
|
||||
}
|
||||
|
||||
[Cached(typeof(HitObjectComposer))]
|
||||
[Cached(typeof(IDistanceSnapProvider))]
|
||||
public abstract class HitObjectComposer : CompositeDrawable, IDistanceSnapProvider
|
||||
[Cached(typeof(IPositionSnapProvider))]
|
||||
public abstract class HitObjectComposer : CompositeDrawable, IPositionSnapProvider
|
||||
{
|
||||
internal HitObjectComposer()
|
||||
{
|
||||
@ -323,7 +326,9 @@ namespace osu.Game.Rulesets.Edit
|
||||
[CanBeNull]
|
||||
protected virtual DistanceSnapGrid CreateDistanceSnapGrid([NotNull] IEnumerable<HitObject> selectedHitObjects) => null;
|
||||
|
||||
public abstract (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time);
|
||||
public abstract (Vector2 position, double time) SnapPositionToValidTime(Vector2 position);
|
||||
|
||||
public abstract (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
||||
|
||||
public abstract float GetBeatSnapDistanceAt(double referenceTime);
|
||||
|
||||
|
@ -5,9 +5,16 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit
|
||||
{
|
||||
public interface IDistanceSnapProvider
|
||||
public interface IPositionSnapProvider
|
||||
{
|
||||
(Vector2 position, double time) GetSnappedPosition(Vector2 position, double time);
|
||||
/// <summary>
|
||||
/// Given a position (local to the provider), find a valid time snap
|
||||
/// </summary>
|
||||
/// <param name="position">The local position to be snapped.</param>
|
||||
/// <returns>The time and position post-snapping.</returns>
|
||||
(Vector2 position, double time) SnapPositionToValidTime(Vector2 position);
|
||||
|
||||
(Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 screenSpacePosition);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the distance between two points within a timing point that are one beat length apart.
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => DrawableObject.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
public override Vector2 SelectionPoint => DrawableObject.ScreenSpaceDrawQuad.Centre;
|
||||
public override Vector2 ScreenSpaceSelectionPoint => DrawableObject.ScreenSpaceDrawQuad.Centre;
|
||||
|
||||
public override Quad SelectionQuad => DrawableObject.ScreenSpaceDrawQuad;
|
||||
|
||||
|
@ -66,7 +66,10 @@ namespace osu.Game.Rulesets.Edit
|
||||
protected void BeginPlacement(double? startTime = null, bool commitStart = false)
|
||||
{
|
||||
HitObject.StartTime = startTime ?? EditorClock.CurrentTime;
|
||||
|
||||
// applies snapping to above time
|
||||
placementHandler.BeginPlacement(HitObject);
|
||||
|
||||
PlacementActive |= commitStart;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
/// <summary>
|
||||
/// The screen-space point that causes this <see cref="OverlaySelectionBlueprint"/> to be selected.
|
||||
/// </summary>
|
||||
public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre;
|
||||
public virtual Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.Centre;
|
||||
|
||||
/// <summary>
|
||||
/// The screen-space quad that outlines this <see cref="OverlaySelectionBlueprint"/> for selections.
|
||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
private readonly BindableList<HitObject> selectedHitObjects = new BindableList<HitObject>();
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private IDistanceSnapProvider snapProvider { get; set; }
|
||||
private IPositionSnapProvider snapProvider { get; set; }
|
||||
|
||||
protected BlueprintContainer()
|
||||
{
|
||||
@ -326,7 +326,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
foreach (var blueprint in SelectionBlueprints)
|
||||
{
|
||||
if (blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint))
|
||||
if (blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.ScreenSpaceSelectionPoint))
|
||||
blueprint.Select();
|
||||
else
|
||||
blueprint.Deselect();
|
||||
@ -384,7 +384,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
// Movement is tracked from the blueprint of the earliest hitobject, since it only makes sense to distance snap from that hitobject
|
||||
movementBlueprint = selectionHandler.SelectedBlueprints.OrderBy(b => b.HitObject.StartTime).First();
|
||||
movementBlueprintOriginalPosition = movementBlueprint.SelectionPoint; // todo: unsure if correct
|
||||
movementBlueprintOriginalPosition = movementBlueprint.ScreenSpaceSelectionPoint; // todo: unsure if correct
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -405,7 +405,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
Vector2 movePosition = movementBlueprintOriginalPosition.Value + e.ScreenSpaceMousePosition - e.ScreenSpaceMouseDownPosition;
|
||||
|
||||
// Retrieve a snapped position.
|
||||
(Vector2 snappedPosition, double snappedTime) = snapProvider.GetSnappedPosition(ToLocalSpace(movePosition), draggedObject.StartTime);
|
||||
(Vector2 snappedPosition, double snappedTime) = snapProvider.SnapScreenSpacePositionToValidTime(movePosition);
|
||||
|
||||
// Move the hitobjects.
|
||||
if (!selectionHandler.HandleMovement(new MoveSelectionEvent(movementBlueprint, ToScreenSpace(snappedPosition))))
|
||||
|
@ -67,10 +67,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
|
||||
private void updatePlacementPosition(Vector2 screenSpacePosition)
|
||||
{
|
||||
Vector2 snappedGridPosition = composer.GetSnappedPosition(ToLocalSpace(screenSpacePosition), 0).position;
|
||||
Vector2 snappedScreenSpacePosition = ToScreenSpace(snappedGridPosition);
|
||||
Vector2 snappedPlayfieldPosition = composer.SnapScreenSpacePositionToValidTime(screenSpacePosition).position;
|
||||
|
||||
currentPlacement.UpdatePosition(snappedScreenSpacePosition);
|
||||
currentPlacement.UpdatePosition(ToScreenSpace(snappedPlayfieldPosition));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
||||
protected OsuColour Colours { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
protected IDistanceSnapProvider SnapProvider { get; private set; }
|
||||
protected IPositionSnapProvider SnapProvider { get; private set; }
|
||||
|
||||
[Resolved]
|
||||
private EditorBeatmap beatmap { get; set; }
|
||||
|
@ -17,9 +17,9 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
{
|
||||
[Cached(typeof(IDistanceSnapProvider))]
|
||||
[Cached(typeof(IPositionSnapProvider))]
|
||||
[Cached]
|
||||
public class Timeline : ZoomableScrollContainer, IDistanceSnapProvider
|
||||
public class Timeline : ZoomableScrollContainer, IPositionSnapProvider
|
||||
{
|
||||
public readonly Bindable<bool> WaveformVisible = new Bindable<bool>();
|
||||
public readonly IBindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||
@ -181,12 +181,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
[Resolved]
|
||||
private IBeatSnapProvider beatSnapProvider { get; set; }
|
||||
|
||||
public double GetTimeFromScreenSpacePosition(Vector2 position)
|
||||
=> getTimeFromPosition(Content.ToLocalSpace(position));
|
||||
|
||||
public (Vector2 position, double time) GetSnappedPosition(Vector2 position, double time) =>
|
||||
public (Vector2 position, double time) SnapPositionToValidTime(Vector2 position) =>
|
||||
(position, beatSnapProvider.SnapTime(getTimeFromPosition(position)));
|
||||
|
||||
public (Vector2 position, double time) SnapScreenSpacePositionToValidTime(Vector2 position) =>
|
||||
(position, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(position))));
|
||||
|
||||
private double getTimeFromPosition(Vector2 localPosition) =>
|
||||
(localPosition.X / Content.DrawWidth) * track.Length;
|
||||
|
||||
|
@ -186,7 +186,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector2 SelectionPoint => ScreenSpaceDrawQuad.TopLeft;
|
||||
public override Vector2 ScreenSpaceSelectionPoint => ScreenSpaceDrawQuad.TopLeft;
|
||||
|
||||
public class DragBar : Container
|
||||
{
|
||||
@ -275,7 +275,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
|
||||
OnDragHandled?.Invoke(e);
|
||||
|
||||
var time = timeline.GetTimeFromScreenSpacePosition(e.ScreenSpaceMousePosition);
|
||||
var time = timeline.SnapScreenSpacePositionToValidTime(e.ScreenSpaceMousePosition).time;
|
||||
|
||||
switch (hitObject)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user