mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 14:37:30 +08:00
Merge pull request #29942 from minetoblend/fix/slider-scale-origin
Fix scaling sliders ignoring the scale origin
This commit is contained in:
commit
145f2b6de7
@ -105,9 +105,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
// is not looking to change the duration of the slider but expand the whole pattern.
|
||||
if (objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider)
|
||||
{
|
||||
var originalInfo = objectsInScale[slider];
|
||||
Debug.Assert(originalInfo.PathControlPointPositions != null && originalInfo.PathControlPointTypes != null);
|
||||
scaleSlider(slider, scale, originalInfo.PathControlPointPositions, originalInfo.PathControlPointTypes, axisRotation);
|
||||
scaleSlider(slider, scale, actualOrigin, objectsInScale[slider], axisRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -159,21 +157,25 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
return scale;
|
||||
}
|
||||
|
||||
private void scaleSlider(Slider slider, Vector2 scale, Vector2[] originalPathPositions, PathType?[] originalPathTypes, float axisRotation = 0)
|
||||
private void scaleSlider(Slider slider, Vector2 scale, Vector2 origin, OriginalHitObjectState originalInfo, float axisRotation = 0)
|
||||
{
|
||||
Debug.Assert(originalInfo.PathControlPointPositions != null && originalInfo.PathControlPointTypes != null);
|
||||
|
||||
scale = Vector2.ComponentMax(scale, new Vector2(Precision.FLOAT_EPSILON));
|
||||
|
||||
// Maintain the path types in case they were defaulted to bezier at some point during scaling
|
||||
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
||||
{
|
||||
slider.Path.ControlPoints[i].Position = GeometryUtils.GetScaledPosition(scale, Vector2.Zero, originalPathPositions[i], axisRotation);
|
||||
slider.Path.ControlPoints[i].Type = originalPathTypes[i];
|
||||
slider.Path.ControlPoints[i].Position = GeometryUtils.GetScaledPosition(scale, Vector2.Zero, originalInfo.PathControlPointPositions[i], axisRotation);
|
||||
slider.Path.ControlPoints[i].Type = originalInfo.PathControlPointTypes[i];
|
||||
}
|
||||
|
||||
// Snap the slider's length to the current beat divisor
|
||||
// to calculate the final resulting duration / bounding box before the final checks.
|
||||
slider.SnapTo(snapProvider);
|
||||
|
||||
slider.Position = GeometryUtils.GetScaledPosition(scale, origin, originalInfo.Position, axisRotation);
|
||||
|
||||
//if sliderhead or sliderend end up outside playfield, revert scaling.
|
||||
Quad scaledQuad = GeometryUtils.GetSurroundingQuad(new OsuHitObject[] { slider });
|
||||
(bool xInBounds, bool yInBounds) = isQuadInBounds(scaledQuad);
|
||||
@ -182,7 +184,9 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
return;
|
||||
|
||||
for (int i = 0; i < slider.Path.ControlPoints.Count; i++)
|
||||
slider.Path.ControlPoints[i].Position = originalPathPositions[i];
|
||||
slider.Path.ControlPoints[i].Position = originalInfo.PathControlPointPositions[i];
|
||||
|
||||
slider.Position = originalInfo.Position;
|
||||
|
||||
// Snap the slider's length again to undo the potentially-invalid length applied by the previous snap.
|
||||
slider.SnapTo(snapProvider);
|
||||
|
@ -10,7 +10,10 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||
using osuTK;
|
||||
|
||||
@ -35,6 +38,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
private OsuCheckbox xCheckBox = null!;
|
||||
private OsuCheckbox yCheckBox = null!;
|
||||
|
||||
private BindableList<HitObject> selectedItems { get; } = new BindableList<HitObject>();
|
||||
|
||||
public PreciseScalePopover(OsuSelectionScaleHandler scaleHandler, OsuGridToolboxGroup gridToolbox)
|
||||
{
|
||||
this.scaleHandler = scaleHandler;
|
||||
@ -44,8 +49,10 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(EditorBeatmap editorBeatmap)
|
||||
{
|
||||
selectedItems.BindTo(editorBeatmap.SelectedHitObjects);
|
||||
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
Width = 220,
|
||||
@ -191,14 +198,26 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
updateAxisCheckBoxesEnabled();
|
||||
}
|
||||
|
||||
private Vector2? getOriginPosition(PreciseScaleInfo scale) =>
|
||||
scale.Origin switch
|
||||
private Vector2? getOriginPosition(PreciseScaleInfo scale)
|
||||
{
|
||||
switch (scale.Origin)
|
||||
{
|
||||
ScaleOrigin.GridCentre => gridToolbox.StartPosition.Value,
|
||||
ScaleOrigin.PlayfieldCentre => OsuPlayfield.BASE_SIZE / 2,
|
||||
ScaleOrigin.SelectionCentre => null,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(scale))
|
||||
};
|
||||
case ScaleOrigin.GridCentre:
|
||||
return gridToolbox.StartPosition.Value;
|
||||
|
||||
case ScaleOrigin.PlayfieldCentre:
|
||||
return OsuPlayfield.BASE_SIZE / 2;
|
||||
|
||||
case ScaleOrigin.SelectionCentre:
|
||||
if (selectedItems.Count == 1 && selectedItems.First() is Slider slider)
|
||||
return slider.Position;
|
||||
|
||||
return null;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(scale));
|
||||
}
|
||||
}
|
||||
|
||||
private Axes getAdjustAxis(PreciseScaleInfo scale) => scale.XAxis ? scale.YAxis ? Axes.Both : Axes.X : Axes.Y;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user