1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 13:23:05 +08:00

Fix movement not working correctly in down-scroll

This commit is contained in:
smoogipoo 2020-04-27 19:47:25 +09:00
parent acf95fca9c
commit b88dd44252
2 changed files with 27 additions and 12 deletions

View File

@ -74,5 +74,25 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
DrawableObject.AlwaysAlive = false; DrawableObject.AlwaysAlive = false;
base.Hide(); base.Hide();
} }
public override Vector2 GetInstantDelta(Vector2 screenSpacePosition)
{
var baseDelta = base.GetInstantDelta(screenSpacePosition);
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
{
// The parent of DrawableObject is the scrolling hitobject container (SHOC).
// In the coordinate-space of the SHOC, the screen-space position at the hit target is equal to the height of the SHOC,
// but this is not what we want as it means a slight movement downwards results in a delta greater than the height of the SHOC.
// To get around this issue, the height of the SHOC is subtracted from the delta.
//
// Ideally this should be a _negative_ value in the case described above, however this code gives a _positive_ delta.
// This is intentional as the delta is added to the hitobject's position (see: ManiaSelectionHandler) and a negative delta would move them towards the top of the screen instead,
// which would cause the delta to get increasingly larger as additional movements are performed.
return new Vector2(baseDelta.X, baseDelta.Y - DrawableObject.Parent.DrawHeight);
}
return baseDelta;
}
} }
} }

View File

@ -45,11 +45,6 @@ namespace osu.Game.Rulesets.Mania.Edit
{ {
float delta = moveEvent.InstantDelta.Y; float delta = moveEvent.InstantDelta.Y;
// When scrolling downwards the anchor position is at the bottom of the screen, however the movement event assumes the anchor is at the top of the screen.
// This causes the delta to assume a positive hitobject position, and which can be corrected for by subtracting the parent height.
if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
delta -= moveEvent.Blueprint.Parent.DrawHeight; // todo: definitely wrong
foreach (var selectionBlueprint in SelectedBlueprints) foreach (var selectionBlueprint in SelectedBlueprints)
{ {
var b = (OverlaySelectionBlueprint)selectionBlueprint; var b = (OverlaySelectionBlueprint)selectionBlueprint;
@ -57,24 +52,24 @@ namespace osu.Game.Rulesets.Mania.Edit
var hitObject = b.DrawableObject; var hitObject = b.DrawableObject;
var objectParent = (HitObjectContainer)hitObject.Parent; var objectParent = (HitObjectContainer)hitObject.Parent;
// StartTime could be used to adjust the position if only one movement event was received per frame. // We receive multiple movement events per frame such that we can't rely on updating the start time
// However this is not the case and ScrollingHitObjectContainer performs movement in UpdateAfterChildren() so the position must also be updated to be valid for further movement events // since the scrolling hitobject container requires at least one update frame to update the position.
// However the position needs to be valid for future movement events to calculate the correct deltas.
hitObject.Y += delta; hitObject.Y += delta;
float targetPosition = hitObject.Position.Y; float targetPosition = hitObject.Position.Y;
// The scrolling algorithm always assumes an anchor at the top of the screen, so the position must be flipped when scrolling downwards to reflect a top anchor
if (scrollingInfo.Direction.Value == ScrollingDirection.Down) if (scrollingInfo.Direction.Value == ScrollingDirection.Down)
{
// When scrolling downwards, the position is _negative_ when the object's start time is after the current time (e.g. in the middle of the stage).
// However all scrolling algorithms upwards scrolling, meaning that a positive (inverse) position is expected in the same scenario.
targetPosition = -targetPosition; targetPosition = -targetPosition;
}
objectParent.Remove(hitObject);
hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition, hitObject.HitObject.StartTime = scrollingInfo.Algorithm.TimeAt(targetPosition,
editorClock.CurrentTime, editorClock.CurrentTime,
scrollingInfo.TimeRange.Value, scrollingInfo.TimeRange.Value,
objectParent.DrawHeight); objectParent.DrawHeight);
objectParent.Add(hitObject);
} }
} }