mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 21:43:22 +08:00
Remove other grid types
This commit is contained in:
parent
39f4a1aa8e
commit
de14da95fa
@ -1,7 +1,6 @@
|
||||
// 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 System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Testing;
|
||||
@ -101,8 +100,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
return grid switch
|
||||
{
|
||||
RectangularPositionSnapGrid rectangular => rectangular.StartPosition.Value + GeometryUtils.RotateVector(rectangular.Spacing.Value, -rectangular.GridLineRotation.Value),
|
||||
TriangularPositionSnapGrid triangular => triangular.StartPosition.Value + GeometryUtils.RotateVector(new Vector2(triangular.Spacing.Value / 2, triangular.Spacing.Value / 2 * MathF.Sqrt(3)), -triangular.GridLineRotation.Value),
|
||||
CircularPositionSnapGrid circular => circular.StartPosition.Value + GeometryUtils.RotateVector(new Vector2(circular.Spacing.Value, 0), -45),
|
||||
_ => Vector2.Zero
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,9 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -16,9 +12,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Edit.Components.RadioButtons;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
@ -82,13 +76,10 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
/// </summary>
|
||||
public Bindable<Vector2> SpacingVector { get; } = new Bindable<Vector2>();
|
||||
|
||||
public Bindable<PositionSnapGridType> GridType { get; } = new Bindable<PositionSnapGridType>();
|
||||
|
||||
private ExpandableSlider<float> startPositionXSlider = null!;
|
||||
private ExpandableSlider<float> startPositionYSlider = null!;
|
||||
private ExpandableSlider<float> spacingSlider = null!;
|
||||
private ExpandableSlider<float> gridLinesRotationSlider = null!;
|
||||
private EditorRadioButtonCollection gridTypeButtons = null!;
|
||||
|
||||
public OsuGridToolboxGroup()
|
||||
: base("grid")
|
||||
@ -122,31 +113,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
Current = GridLinesRotation,
|
||||
KeyboardStep = 1,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, 10f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
gridTypeButtons = new EditorRadioButtonCollection
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Items = new[]
|
||||
{
|
||||
new RadioButton("Square",
|
||||
() => GridType.Value = PositionSnapGridType.Square,
|
||||
() => new SpriteIcon { Icon = FontAwesome.Regular.Square }),
|
||||
new RadioButton("Triangle",
|
||||
() => GridType.Value = PositionSnapGridType.Triangle,
|
||||
() => new OutlineTriangle(true, 20)),
|
||||
new RadioButton("Circle",
|
||||
() => GridType.Value = PositionSnapGridType.Circle,
|
||||
() => new SpriteIcon { Icon = FontAwesome.Regular.Circle }),
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Spacing.Value = editorBeatmap.BeatmapInfo.GridSize;
|
||||
@ -156,8 +122,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
gridTypeButtons.Items.First().Select();
|
||||
|
||||
StartPositionX.BindValueChanged(x =>
|
||||
{
|
||||
startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:N0}";
|
||||
@ -185,12 +149,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
gridLinesRotationSlider.ContractedLabelText = $"R: {rotation.NewValue:#,0.##}";
|
||||
gridLinesRotationSlider.ExpandedLabelText = $"Rotation: {rotation.NewValue:#,0.##}";
|
||||
}, true);
|
||||
|
||||
expandingContainer?.Expanded.BindValueChanged(v =>
|
||||
{
|
||||
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
||||
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void nextGridSize()
|
||||
@ -213,42 +171,5 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
}
|
||||
|
||||
public partial class OutlineTriangle : BufferedContainer
|
||||
{
|
||||
public OutlineTriangle(bool outlineOnly, float size)
|
||||
: base(cachedFrameBuffer: true)
|
||||
{
|
||||
Size = new Vector2(size);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new EquilateralTriangle { RelativeSizeAxes = Axes.Both },
|
||||
};
|
||||
|
||||
if (outlineOnly)
|
||||
{
|
||||
AddInternal(new EquilateralTriangle
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Y = 0.48f,
|
||||
Colour = Color4.Black,
|
||||
Size = new Vector2(size - 7),
|
||||
Blending = BlendingParameters.None,
|
||||
});
|
||||
}
|
||||
|
||||
Blending = BlendingParameters.Additive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum PositionSnapGridType
|
||||
{
|
||||
Square,
|
||||
Triangle,
|
||||
Circle,
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
// we may be entering the screen with a selection already active
|
||||
updateDistanceSnapGrid();
|
||||
|
||||
OsuGridToolboxGroup.GridType.BindValueChanged(updatePositionSnapGrid, true);
|
||||
updatePositionSnapGrid();
|
||||
|
||||
RightToolbox.AddRange(new EditorToolboxGroup[]
|
||||
{
|
||||
@ -110,45 +110,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
);
|
||||
}
|
||||
|
||||
private void updatePositionSnapGrid(ValueChangedEvent<PositionSnapGridType> obj)
|
||||
private void updatePositionSnapGrid()
|
||||
{
|
||||
if (positionSnapGrid != null)
|
||||
LayerBelowRuleset.Remove(positionSnapGrid, true);
|
||||
|
||||
switch (obj.NewValue)
|
||||
{
|
||||
case PositionSnapGridType.Square:
|
||||
var rectangularPositionSnapGrid = new RectangularPositionSnapGrid();
|
||||
|
||||
rectangularPositionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition);
|
||||
rectangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.SpacingVector);
|
||||
rectangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);
|
||||
|
||||
positionSnapGrid = rectangularPositionSnapGrid;
|
||||
break;
|
||||
|
||||
case PositionSnapGridType.Triangle:
|
||||
var triangularPositionSnapGrid = new TriangularPositionSnapGrid();
|
||||
|
||||
triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);
|
||||
|
||||
positionSnapGrid = triangularPositionSnapGrid;
|
||||
break;
|
||||
|
||||
case PositionSnapGridType.Circle:
|
||||
var circularPositionSnapGrid = new CircularPositionSnapGrid();
|
||||
|
||||
circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
|
||||
positionSnapGrid = circularPositionSnapGrid;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"{OsuGridToolboxGroup.GridType} has an incorrect value.");
|
||||
}
|
||||
|
||||
// Bind the start position to the toolbox sliders.
|
||||
positionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition);
|
||||
|
||||
positionSnapGrid.RelativeSizeAxes = Axes.Both;
|
||||
LayerBelowRuleset.Add(positionSnapGrid);
|
||||
|
@ -70,51 +70,6 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
}));
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(test_cases))]
|
||||
public void TestTriangularGrid(Vector2 position, Vector2 spacing, float rotation)
|
||||
{
|
||||
TriangularPositionSnapGrid grid = null;
|
||||
|
||||
AddStep("create grid", () =>
|
||||
{
|
||||
Child = grid = new TriangularPositionSnapGrid
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
grid.StartPosition.Value = position;
|
||||
grid.Spacing.Value = spacing.X;
|
||||
grid.GridLineRotation.Value = rotation;
|
||||
});
|
||||
|
||||
AddStep("add snapping cursor", () => Add(new SnappingCursorContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
GetSnapPosition = pos => grid.GetSnappedPosition(grid.ToLocalSpace(pos))
|
||||
}));
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(test_cases))]
|
||||
public void TestCircularGrid(Vector2 position, Vector2 spacing, float rotation)
|
||||
{
|
||||
CircularPositionSnapGrid grid = null;
|
||||
|
||||
AddStep("create grid", () =>
|
||||
{
|
||||
Child = grid = new CircularPositionSnapGrid
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
};
|
||||
grid.StartPosition.Value = position;
|
||||
grid.Spacing.Value = spacing.X;
|
||||
});
|
||||
|
||||
AddStep("add snapping cursor", () => Add(new SnappingCursorContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
GetSnapPosition = pos => grid.GetSnappedPosition(grid.ToLocalSpace(pos))
|
||||
}));
|
||||
}
|
||||
|
||||
private partial class SnappingCursorContainer : CompositeDrawable
|
||||
{
|
||||
public Func<Vector2, Vector2> GetSnapPosition;
|
||||
|
@ -1,101 +0,0 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Utils;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
public partial class CircularPositionSnapGrid : PositionSnapGrid
|
||||
{
|
||||
/// <summary>
|
||||
/// The spacing between grid lines of this <see cref="CircularPositionSnapGrid"/>.
|
||||
/// </summary>
|
||||
public BindableFloat Spacing { get; } = new BindableFloat(1f)
|
||||
{
|
||||
MinValue = 0f,
|
||||
};
|
||||
|
||||
public CircularPositionSnapGrid()
|
||||
{
|
||||
Spacing.BindValueChanged(_ => GridCache.Invalidate());
|
||||
}
|
||||
|
||||
protected override void CreateContent()
|
||||
{
|
||||
var drawSize = DrawSize;
|
||||
|
||||
// Calculate the maximum distance from the origin to the edge of the grid.
|
||||
float maxDist = MathF.Max(
|
||||
MathF.Max(StartPosition.Value.Length, (StartPosition.Value - drawSize).Length),
|
||||
MathF.Max((StartPosition.Value - new Vector2(drawSize.X, 0)).Length, (StartPosition.Value - new Vector2(0, drawSize.Y)).Length)
|
||||
);
|
||||
|
||||
generateCircles((int)(maxDist / Spacing.Value) + 1);
|
||||
|
||||
GenerateOutline(drawSize);
|
||||
}
|
||||
|
||||
private void generateCircles(int count)
|
||||
{
|
||||
// Make lines the same width independent of display resolution.
|
||||
float lineWidth = 2 * DrawWidth / ScreenSpaceDrawQuad.Width;
|
||||
|
||||
List<CircularContainer> generatedCircles = new List<CircularContainer>();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Add a minimum diameter so the center circle is clearly visible.
|
||||
float diameter = MathF.Max(lineWidth * 1.5f, i * Spacing.Value * 2);
|
||||
|
||||
var gridCircle = new CircularContainer
|
||||
{
|
||||
BorderColour = Colour4.White,
|
||||
BorderThickness = lineWidth,
|
||||
Alpha = 0.2f,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = diameter,
|
||||
Height = diameter,
|
||||
Position = StartPosition.Value,
|
||||
Masking = true,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0f,
|
||||
}
|
||||
};
|
||||
|
||||
generatedCircles.Add(gridCircle);
|
||||
}
|
||||
|
||||
if (generatedCircles.Count == 0)
|
||||
return;
|
||||
|
||||
generatedCircles.First().Alpha = 0.8f;
|
||||
|
||||
AddRangeInternal(generatedCircles);
|
||||
}
|
||||
|
||||
public override Vector2 GetSnappedPosition(Vector2 original)
|
||||
{
|
||||
Vector2 relativeToStart = original - StartPosition.Value;
|
||||
|
||||
if (relativeToStart.LengthSquared < Precision.FLOAT_EPSILON)
|
||||
return StartPosition.Value;
|
||||
|
||||
float length = relativeToStart.Length;
|
||||
float wantedLength = MathF.Round(length / Spacing.Value) * Spacing.Value;
|
||||
|
||||
return StartPosition.Value + Vector2.Multiply(relativeToStart, wantedLength / length);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
// 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.Framework.Bindables;
|
||||
using osu.Game.Utils;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Compose.Components
|
||||
{
|
||||
public partial class TriangularPositionSnapGrid : LinedPositionSnapGrid
|
||||
{
|
||||
/// <summary>
|
||||
/// The spacing between grid lines of this <see cref="TriangularPositionSnapGrid"/>.
|
||||
/// </summary>
|
||||
public BindableFloat Spacing { get; } = new BindableFloat(1f)
|
||||
{
|
||||
MinValue = 0f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The rotation in degrees of the grid lines of this <see cref="TriangularPositionSnapGrid"/>.
|
||||
/// </summary>
|
||||
public BindableFloat GridLineRotation { get; } = new BindableFloat();
|
||||
|
||||
public TriangularPositionSnapGrid()
|
||||
{
|
||||
Spacing.BindValueChanged(_ => GridCache.Invalidate());
|
||||
GridLineRotation.BindValueChanged(_ => GridCache.Invalidate());
|
||||
}
|
||||
|
||||
private const float sqrt3 = 1.73205080757f;
|
||||
private const float sqrt3_over2 = 0.86602540378f;
|
||||
private const float one_over_sqrt3 = 0.57735026919f;
|
||||
|
||||
protected override void CreateContent()
|
||||
{
|
||||
var drawSize = DrawSize;
|
||||
float stepSpacing = Spacing.Value * sqrt3_over2;
|
||||
var step1 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 30);
|
||||
var step2 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 90);
|
||||
var step3 = GeometryUtils.RotateVector(new Vector2(stepSpacing, 0), -GridLineRotation.Value - 150);
|
||||
|
||||
GenerateGridLines(step1, drawSize);
|
||||
GenerateGridLines(-step1, drawSize);
|
||||
|
||||
GenerateGridLines(step2, drawSize);
|
||||
GenerateGridLines(-step2, drawSize);
|
||||
|
||||
GenerateGridLines(step3, drawSize);
|
||||
GenerateGridLines(-step3, drawSize);
|
||||
|
||||
GenerateOutline(drawSize);
|
||||
}
|
||||
|
||||
public override Vector2 GetSnappedPosition(Vector2 original)
|
||||
{
|
||||
Vector2 relativeToStart = GeometryUtils.RotateVector(original - StartPosition.Value, GridLineRotation.Value);
|
||||
Vector2 hex = pixelToHex(relativeToStart);
|
||||
|
||||
return StartPosition.Value + GeometryUtils.RotateVector(hexToPixel(hex), -GridLineRotation.Value);
|
||||
}
|
||||
|
||||
private Vector2 pixelToHex(Vector2 pixel)
|
||||
{
|
||||
float x = pixel.X / Spacing.Value;
|
||||
float y = pixel.Y / Spacing.Value;
|
||||
// Algorithm from Charles Chambers
|
||||
// with modifications and comments by Chris Cox 2023
|
||||
// <https://gitlab.com/chriscox/hex-coordinates>
|
||||
float t = sqrt3 * y + 1; // scaled y, plus phase
|
||||
float temp1 = MathF.Floor(t + x); // (y+x) diagonal, this calc needs floor
|
||||
float temp2 = t - x; // (y-x) diagonal, no floor needed
|
||||
float temp3 = 2 * x + 1; // scaled horizontal, no floor needed, needs +1 to get correct phase
|
||||
float qf = (temp1 + temp3) / 3.0f; // pseudo x with fraction
|
||||
float rf = (temp1 + temp2) / 3.0f; // pseudo y with fraction
|
||||
float q = MathF.Floor(qf); // pseudo x, quantized and thus requires floor
|
||||
float r = MathF.Floor(rf); // pseudo y, quantized and thus requires floor
|
||||
return new Vector2(q, r);
|
||||
}
|
||||
|
||||
private Vector2 hexToPixel(Vector2 hex)
|
||||
{
|
||||
// Taken from <https://www.redblobgames.com/grids/hexagons/#hex-to-pixel>
|
||||
// with modifications for the different definition of size.
|
||||
return new Vector2(Spacing.Value * (hex.X - hex.Y / 2), Spacing.Value * one_over_sqrt3 * 1.5f * hex.Y);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user